From 557f2816f5cd30705dec989c97a8a67c026d36d1 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Fri, 12 Oct 2012 10:49:29 +0000 Subject: FreeImage: folders restructurization git-svn-id: http://svn.miranda-ng.org/main/trunk@1884 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/FreeImage/Docs/freeimage-translation.txt | 2 + plugins/FreeImage/FreeImage.rc | 113 - plugins/FreeImage/FreeImage_10.vcxproj | 329 +- plugins/FreeImage/FreeImage_10.vcxproj.filters | 321 +- plugins/FreeImage/Miranda/main.cpp | 1260 - plugins/FreeImage/Miranda/version.h | 12 - plugins/FreeImage/Source/CacheFile.h | 92 - .../Source/DeprecationManager/Deprecated.cpp | 36 - .../Source/DeprecationManager/DeprecationMgr.cpp | 103 - .../Source/DeprecationManager/DeprecationMgr.h | 83 - plugins/FreeImage/Source/FreeImage.h | 1104 - .../FreeImage/Source/FreeImage/BitmapAccess.cpp | 1210 - plugins/FreeImage/Source/FreeImage/CacheFile.cpp | 271 - plugins/FreeImage/Source/FreeImage/ColorLookup.cpp | 782 - plugins/FreeImage/Source/FreeImage/Conversion.cpp | 513 - .../Source/FreeImage/Conversion16_555.cpp | 209 - .../Source/FreeImage/Conversion16_565.cpp | 204 - .../FreeImage/Source/FreeImage/Conversion24.cpp | 214 - .../FreeImage/Source/FreeImage/Conversion32.cpp | 345 - plugins/FreeImage/Source/FreeImage/Conversion4.cpp | 246 - plugins/FreeImage/Source/FreeImage/Conversion8.cpp | 327 - .../FreeImage/Source/FreeImage/ConversionFloat.cpp | 192 - .../FreeImage/Source/FreeImage/ConversionRGB16.cpp | 144 - .../FreeImage/Source/FreeImage/ConversionRGBF.cpp | 241 - .../FreeImage/Source/FreeImage/ConversionType.cpp | 689 - .../Source/FreeImage/ConversionUINT16.cpp | 134 - plugins/FreeImage/Source/FreeImage/FreeImage.cpp | 226 - plugins/FreeImage/Source/FreeImage/FreeImageC.c | 22 - plugins/FreeImage/Source/FreeImage/FreeImageIO.cpp | 168 - plugins/FreeImage/Source/FreeImage/GetType.cpp | 92 - plugins/FreeImage/Source/FreeImage/Halftoning.cpp | 474 - plugins/FreeImage/Source/FreeImage/J2KHelper.cpp | 500 - plugins/FreeImage/Source/FreeImage/MemoryIO.cpp | 237 - plugins/FreeImage/Source/FreeImage/MultiPage.cpp | 990 - plugins/FreeImage/Source/FreeImage/NNQuantizer.cpp | 507 - plugins/FreeImage/Source/FreeImage/PSDParser.cpp | 1053 - plugins/FreeImage/Source/FreeImage/PSDParser.h | 271 - plugins/FreeImage/Source/FreeImage/PixelAccess.cpp | 209 - plugins/FreeImage/Source/FreeImage/Plugin.cpp | 747 - plugins/FreeImage/Source/FreeImage/PluginBMP.cpp | 1480 -- plugins/FreeImage/Source/FreeImage/PluginCUT.cpp | 240 - plugins/FreeImage/Source/FreeImage/PluginDDS.cpp | 651 - plugins/FreeImage/Source/FreeImage/PluginEXR.cpp | 764 - plugins/FreeImage/Source/FreeImage/PluginG3.cpp | 433 - plugins/FreeImage/Source/FreeImage/PluginGIF.cpp | 1398 -- plugins/FreeImage/Source/FreeImage/PluginHDR.cpp | 719 - plugins/FreeImage/Source/FreeImage/PluginICO.cpp | 805 - plugins/FreeImage/Source/FreeImage/PluginIFF.cpp | 459 - plugins/FreeImage/Source/FreeImage/PluginJ2K.cpp | 339 - plugins/FreeImage/Source/FreeImage/PluginJP2.cpp | 339 - plugins/FreeImage/Source/FreeImage/PluginJPEG.cpp | 1801 -- plugins/FreeImage/Source/FreeImage/PluginKOALA.cpp | 243 - plugins/FreeImage/Source/FreeImage/PluginMNG.cpp | 153 - plugins/FreeImage/Source/FreeImage/PluginPCD.cpp | 251 - plugins/FreeImage/Source/FreeImage/PluginPCX.cpp | 659 - plugins/FreeImage/Source/FreeImage/PluginPFM.cpp | 402 - plugins/FreeImage/Source/FreeImage/PluginPICT.cpp | 1342 - plugins/FreeImage/Source/FreeImage/PluginPNG.cpp | 953 - plugins/FreeImage/Source/FreeImage/PluginPNM.cpp | 831 - plugins/FreeImage/Source/FreeImage/PluginPSD.cpp | 131 - plugins/FreeImage/Source/FreeImage/PluginRAS.cpp | 512 - plugins/FreeImage/Source/FreeImage/PluginRAW.cpp | 542 - plugins/FreeImage/Source/FreeImage/PluginSGI.cpp | 425 - plugins/FreeImage/Source/FreeImage/PluginTARGA.cpp | 1565 -- plugins/FreeImage/Source/FreeImage/PluginTIFF.cpp | 2629 -- plugins/FreeImage/Source/FreeImage/PluginWBMP.cpp | 372 - plugins/FreeImage/Source/FreeImage/PluginXBM.cpp | 399 - plugins/FreeImage/Source/FreeImage/PluginXPM.cpp | 487 - plugins/FreeImage/Source/FreeImage/TIFFLogLuv.cpp | 65 - plugins/FreeImage/Source/FreeImage/ToneMapping.cpp | 75 - plugins/FreeImage/Source/FreeImage/WuQuantizer.cpp | 538 - .../FreeImage/Source/FreeImage/ZLibInterface.cpp | 223 - .../FreeImage/Source/FreeImage/tmoColorConvert.cpp | 479 - plugins/FreeImage/Source/FreeImage/tmoDrago03.cpp | 295 - plugins/FreeImage/Source/FreeImage/tmoFattal02.cpp | 689 - .../FreeImage/Source/FreeImage/tmoReinhard05.cpp | 260 - plugins/FreeImage/Source/FreeImageIO.h | 48 - .../FreeImage/Source/FreeImageLib/FreeImageLib.dsp | 448 - .../Source/FreeImageLib/FreeImageLib.vcproj | 411 - .../FreeImage/Source/FreeImageLib/FreeImageLib.vpj | 116 - .../Source/FreeImageToolkit/BSplineRotate.cpp | 730 - .../FreeImage/Source/FreeImageToolkit/Channels.cpp | 488 - .../Source/FreeImageToolkit/ClassicRotate.cpp | 917 - .../FreeImage/Source/FreeImageToolkit/Colors.cpp | 967 - .../Source/FreeImageToolkit/CopyPaste.cpp | 747 - .../FreeImage/Source/FreeImageToolkit/Display.cpp | 230 - .../FreeImage/Source/FreeImageToolkit/Filters.h | 287 - plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp | 166 - .../Source/FreeImageToolkit/JPEGTransform.cpp | 410 - .../FreeImageToolkit/MultigridPoissonSolver.cpp | 505 - .../FreeImage/Source/FreeImageToolkit/Rescale.cpp | 231 - .../FreeImage/Source/FreeImageToolkit/Resize.cpp | 656 - plugins/FreeImage/Source/FreeImageToolkit/Resize.h | 145 - plugins/FreeImage/Source/LibJPEG/ansi2knr.c | 739 - plugins/FreeImage/Source/LibJPEG/cderror.h | 134 - plugins/FreeImage/Source/LibJPEG/cdjpeg.c | 181 - plugins/FreeImage/Source/LibJPEG/cdjpeg.h | 187 - plugins/FreeImage/Source/LibJPEG/change.log | 346 - plugins/FreeImage/Source/LibJPEG/cjpeg.c | 643 - plugins/FreeImage/Source/LibJPEG/ckconfig.c | 402 - plugins/FreeImage/Source/LibJPEG/djpeg.c | 617 - plugins/FreeImage/Source/LibJPEG/example.c | 433 - plugins/FreeImage/Source/LibJPEG/jaricom.c | 153 - plugins/FreeImage/Source/LibJPEG/jcapimin.c | 288 - plugins/FreeImage/Source/LibJPEG/jcapistd.c | 161 - plugins/FreeImage/Source/LibJPEG/jcarith.c | 937 - plugins/FreeImage/Source/LibJPEG/jccoefct.c | 454 - plugins/FreeImage/Source/LibJPEG/jccolor.c | 490 - plugins/FreeImage/Source/LibJPEG/jcdctmgr.c | 482 - plugins/FreeImage/Source/LibJPEG/jchuff.c | 1576 -- plugins/FreeImage/Source/LibJPEG/jcinit.c | 65 - plugins/FreeImage/Source/LibJPEG/jcmainct.c | 293 - plugins/FreeImage/Source/LibJPEG/jcmarker.c | 682 - plugins/FreeImage/Source/LibJPEG/jcmaster.c | 858 - plugins/FreeImage/Source/LibJPEG/jcomapi.c | 106 - plugins/FreeImage/Source/LibJPEG/jconfig.h | 47 - plugins/FreeImage/Source/LibJPEG/jconfig.txt | 164 - plugins/FreeImage/Source/LibJPEG/jcparam.c | 632 - plugins/FreeImage/Source/LibJPEG/jcprepct.c | 358 - plugins/FreeImage/Source/LibJPEG/jcsample.c | 545 - plugins/FreeImage/Source/LibJPEG/jctrans.c | 382 - plugins/FreeImage/Source/LibJPEG/jdapimin.c | 396 - plugins/FreeImage/Source/LibJPEG/jdapistd.c | 275 - plugins/FreeImage/Source/LibJPEG/jdarith.c | 776 - plugins/FreeImage/Source/LibJPEG/jdatadst.c | 267 - plugins/FreeImage/Source/LibJPEG/jdatasrc.c | 275 - plugins/FreeImage/Source/LibJPEG/jdcoefct.c | 741 - plugins/FreeImage/Source/LibJPEG/jdcolor.c | 512 - plugins/FreeImage/Source/LibJPEG/jdct.h | 393 - plugins/FreeImage/Source/LibJPEG/jddctmgr.c | 384 - plugins/FreeImage/Source/LibJPEG/jdhuff.c | 1541 -- plugins/FreeImage/Source/LibJPEG/jdinput.c | 661 - plugins/FreeImage/Source/LibJPEG/jdmainct.c | 512 - plugins/FreeImage/Source/LibJPEG/jdmarker.c | 1406 -- plugins/FreeImage/Source/LibJPEG/jdmaster.c | 531 - plugins/FreeImage/Source/LibJPEG/jdmerge.c | 400 - plugins/FreeImage/Source/LibJPEG/jdpostct.c | 290 - plugins/FreeImage/Source/LibJPEG/jdsample.c | 361 - plugins/FreeImage/Source/LibJPEG/jdtrans.c | 140 - plugins/FreeImage/Source/LibJPEG/jerror.c | 252 - plugins/FreeImage/Source/LibJPEG/jerror.h | 304 - plugins/FreeImage/Source/LibJPEG/jfdctflt.c | 174 - plugins/FreeImage/Source/LibJPEG/jfdctfst.c | 230 - plugins/FreeImage/Source/LibJPEG/jfdctint.c | 4348 ---- plugins/FreeImage/Source/LibJPEG/jidctflt.c | 235 - plugins/FreeImage/Source/LibJPEG/jidctfst.c | 368 - plugins/FreeImage/Source/LibJPEG/jidctint.c | 5137 ---- plugins/FreeImage/Source/LibJPEG/jinclude.h | 91 - plugins/FreeImage/Source/LibJPEG/jmemansi.c | 167 - plugins/FreeImage/Source/LibJPEG/jmemdos.c | 638 - plugins/FreeImage/Source/LibJPEG/jmemdosa.asm | 379 - plugins/FreeImage/Source/LibJPEG/jmemmac.c | 289 - plugins/FreeImage/Source/LibJPEG/jmemmgr.c | 1119 - plugins/FreeImage/Source/LibJPEG/jmemname.c | 276 - plugins/FreeImage/Source/LibJPEG/jmemnobs.c | 109 - plugins/FreeImage/Source/LibJPEG/jmemsys.h | 198 - plugins/FreeImage/Source/LibJPEG/jmorecfg.h | 369 - plugins/FreeImage/Source/LibJPEG/jpegint.h | 426 - plugins/FreeImage/Source/LibJPEG/jpeglib.h | 1160 - plugins/FreeImage/Source/LibJPEG/jpegtran.c | 560 - plugins/FreeImage/Source/LibJPEG/jquant1.c | 857 - plugins/FreeImage/Source/LibJPEG/jquant2.c | 1311 - plugins/FreeImage/Source/LibJPEG/jutils.c | 227 - plugins/FreeImage/Source/LibJPEG/jversion.h | 14 - plugins/FreeImage/Source/LibJPEG/rdbmp.c | 480 - plugins/FreeImage/Source/LibJPEG/rdcolmap.c | 253 - plugins/FreeImage/Source/LibJPEG/rdgif.c | 38 - plugins/FreeImage/Source/LibJPEG/rdjpgcom.c | 515 - plugins/FreeImage/Source/LibJPEG/rdppm.c | 459 - plugins/FreeImage/Source/LibJPEG/rdrle.c | 387 - plugins/FreeImage/Source/LibJPEG/rdswitch.c | 365 - plugins/FreeImage/Source/LibJPEG/rdtarga.c | 500 - plugins/FreeImage/Source/LibJPEG/transupp.c | 1597 -- plugins/FreeImage/Source/LibJPEG/transupp.h | 213 - plugins/FreeImage/Source/LibJPEG/wrbmp.c | 442 - plugins/FreeImage/Source/LibJPEG/wrgif.c | 399 - plugins/FreeImage/Source/LibJPEG/wrjpgcom.c | 583 - plugins/FreeImage/Source/LibJPEG/wrppm.c | 269 - plugins/FreeImage/Source/LibJPEG/wrrle.c | 305 - plugins/FreeImage/Source/LibJPEG/wrtarga.c | 253 - plugins/FreeImage/Source/LibMNG/Changes | 1447 -- plugins/FreeImage/Source/LibMNG/LICENSE | 57 - plugins/FreeImage/Source/LibMNG/README | 36 - plugins/FreeImage/Source/LibMNG/README.autoconf | 213 - plugins/FreeImage/Source/LibMNG/README.config | 104 - plugins/FreeImage/Source/LibMNG/README.contrib | 95 - plugins/FreeImage/Source/LibMNG/README.examples | 48 - plugins/FreeImage/Source/LibMNG/README.footprint | 46 - plugins/FreeImage/Source/LibMNG/README.packaging | 24 - plugins/FreeImage/Source/LibMNG/libmng.h | 2932 --- .../FreeImage/Source/LibMNG/libmng_callback_xs.c | 1239 - .../FreeImage/Source/LibMNG/libmng_chunk_descr.c | 6090 ----- .../FreeImage/Source/LibMNG/libmng_chunk_descr.h | 146 - plugins/FreeImage/Source/LibMNG/libmng_chunk_io.c | 10740 -------- plugins/FreeImage/Source/LibMNG/libmng_chunk_io.h | 415 - plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.c | 4452 ---- plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.h | 381 - plugins/FreeImage/Source/LibMNG/libmng_chunk_xs.c | 7016 ------ plugins/FreeImage/Source/LibMNG/libmng_chunks.h | 1026 - plugins/FreeImage/Source/LibMNG/libmng_cms.c | 758 - plugins/FreeImage/Source/LibMNG/libmng_cms.h | 92 - plugins/FreeImage/Source/LibMNG/libmng_conf.h | 306 - plugins/FreeImage/Source/LibMNG/libmng_data.h | 1029 - plugins/FreeImage/Source/LibMNG/libmng_display.c | 7135 ------ plugins/FreeImage/Source/LibMNG/libmng_display.h | 343 - plugins/FreeImage/Source/LibMNG/libmng_dither.c | 58 - plugins/FreeImage/Source/LibMNG/libmng_dither.h | 45 - plugins/FreeImage/Source/LibMNG/libmng_error.c | 326 - plugins/FreeImage/Source/LibMNG/libmng_error.h | 119 - plugins/FreeImage/Source/LibMNG/libmng_filter.c | 978 - plugins/FreeImage/Source/LibMNG/libmng_filter.h | 69 - plugins/FreeImage/Source/LibMNG/libmng_hlapi.c | 2995 --- plugins/FreeImage/Source/LibMNG/libmng_jpeg.c | 1088 - plugins/FreeImage/Source/LibMNG/libmng_jpeg.h | 57 - plugins/FreeImage/Source/LibMNG/libmng_memory.h | 64 - .../FreeImage/Source/LibMNG/libmng_object_prc.c | 6998 ------ .../FreeImage/Source/LibMNG/libmng_object_prc.h | 690 - plugins/FreeImage/Source/LibMNG/libmng_objects.h | 635 - plugins/FreeImage/Source/LibMNG/libmng_pixels.c | 24610 ------------------- plugins/FreeImage/Source/LibMNG/libmng_pixels.h | 1147 - plugins/FreeImage/Source/LibMNG/libmng_prop_xs.c | 2799 --- plugins/FreeImage/Source/LibMNG/libmng_read.c | 1369 -- plugins/FreeImage/Source/LibMNG/libmng_read.h | 53 - plugins/FreeImage/Source/LibMNG/libmng_trace.c | 1683 -- plugins/FreeImage/Source/LibMNG/libmng_trace.h | 1474 -- plugins/FreeImage/Source/LibMNG/libmng_types.h | 574 - plugins/FreeImage/Source/LibMNG/libmng_write.c | 198 - plugins/FreeImage/Source/LibMNG/libmng_write.h | 49 - plugins/FreeImage/Source/LibMNG/libmng_zlib.c | 607 - plugins/FreeImage/Source/LibMNG/libmng_zlib.h | 60 - plugins/FreeImage/Source/LibPNG/ANNOUNCE | 42 - plugins/FreeImage/Source/LibPNG/CHANGES | 3820 --- plugins/FreeImage/Source/LibPNG/INSTALL | 135 - plugins/FreeImage/Source/LibPNG/KNOWNBUG | 29 - plugins/FreeImage/Source/LibPNG/LICENSE | 111 - plugins/FreeImage/Source/LibPNG/README | 202 - plugins/FreeImage/Source/LibPNG/TODO | 27 - plugins/FreeImage/Source/LibPNG/Y2KINFO | 55 - plugins/FreeImage/Source/LibPNG/configure | 19 - plugins/FreeImage/Source/LibPNG/libpng.3 | 5952 ----- plugins/FreeImage/Source/LibPNG/libpng.txt | 3352 --- plugins/FreeImage/Source/LibPNG/libpngpf.3 | 28 - plugins/FreeImage/Source/LibPNG/png.5 | 74 - plugins/FreeImage/Source/LibPNG/png.c | 2870 --- plugins/FreeImage/Source/LibPNG/png.h | 2658 -- plugins/FreeImage/Source/LibPNG/pngconf.h | 596 - plugins/FreeImage/Source/LibPNG/pngdebug.h | 157 - plugins/FreeImage/Source/LibPNG/pngerror.c | 685 - plugins/FreeImage/Source/LibPNG/pngget.c | 1124 - plugins/FreeImage/Source/LibPNG/pnginfo.h | 269 - plugins/FreeImage/Source/LibPNG/pnglibconf.h | 187 - plugins/FreeImage/Source/LibPNG/pngmem.c | 667 - plugins/FreeImage/Source/LibPNG/pngpread.c | 1843 -- plugins/FreeImage/Source/LibPNG/pngpriv.h | 1629 -- plugins/FreeImage/Source/LibPNG/pngread.c | 1308 - plugins/FreeImage/Source/LibPNG/pngrio.c | 176 - plugins/FreeImage/Source/LibPNG/pngrtran.c | 5023 ---- plugins/FreeImage/Source/LibPNG/pngrutil.c | 4158 ---- plugins/FreeImage/Source/LibPNG/pngset.c | 1284 - plugins/FreeImage/Source/LibPNG/pngstruct.h | 358 - plugins/FreeImage/Source/LibPNG/pngtest.c | 1820 -- plugins/FreeImage/Source/LibPNG/pngtrans.c | 678 - plugins/FreeImage/Source/LibPNG/pngwio.c | 254 - plugins/FreeImage/Source/LibPNG/pngwrite.c | 1655 -- plugins/FreeImage/Source/LibPNG/pngwtran.c | 633 - plugins/FreeImage/Source/LibPNG/pngwutil.c | 3180 --- plugins/FreeImage/Source/LibTIFF/ChangeLog | 4849 ---- plugins/FreeImage/Source/LibTIFF/LibTIFF.dsp | 293 - plugins/FreeImage/Source/LibTIFF/SConstruct | 73 - plugins/FreeImage/Source/LibTIFF/mkg3states.c | 451 - plugins/FreeImage/Source/LibTIFF/t4.h | 292 - plugins/FreeImage/Source/LibTIFF/tif_acorn.c | 526 - plugins/FreeImage/Source/LibTIFF/tif_apple.c | 281 - plugins/FreeImage/Source/LibTIFF/tif_atari.c | 250 - plugins/FreeImage/Source/LibTIFF/tif_aux.c | 290 - plugins/FreeImage/Source/LibTIFF/tif_close.c | 126 - plugins/FreeImage/Source/LibTIFF/tif_codec.c | 160 - plugins/FreeImage/Source/LibTIFF/tif_color.c | 287 - plugins/FreeImage/Source/LibTIFF/tif_compress.c | 295 - plugins/FreeImage/Source/LibTIFF/tif_config.h | 266 - plugins/FreeImage/Source/LibTIFF/tif_config.h-vms | 46 - plugins/FreeImage/Source/LibTIFF/tif_config.h.in | 309 - plugins/FreeImage/Source/LibTIFF/tif_config.vc.h | 63 - plugins/FreeImage/Source/LibTIFF/tif_dir.c | 1391 -- plugins/FreeImage/Source/LibTIFF/tif_dir.h | 211 - plugins/FreeImage/Source/LibTIFF/tif_dirinfo.c | 884 - plugins/FreeImage/Source/LibTIFF/tif_dirread.c | 2117 -- plugins/FreeImage/Source/LibTIFF/tif_dirwrite.c | 1436 -- plugins/FreeImage/Source/LibTIFF/tif_dumpmode.c | 126 - plugins/FreeImage/Source/LibTIFF/tif_error.c | 80 - plugins/FreeImage/Source/LibTIFF/tif_extension.c | 118 - plugins/FreeImage/Source/LibTIFF/tif_fax3.c | 1626 -- plugins/FreeImage/Source/LibTIFF/tif_fax3.h | 538 - plugins/FreeImage/Source/LibTIFF/tif_fax3sm.c | 1260 - plugins/FreeImage/Source/LibTIFF/tif_flush.c | 74 - plugins/FreeImage/Source/LibTIFF/tif_getimage.c | 2678 -- plugins/FreeImage/Source/LibTIFF/tif_jbig.c | 385 - plugins/FreeImage/Source/LibTIFF/tif_jpeg.c | 2078 -- plugins/FreeImage/Source/LibTIFF/tif_luv.c | 1629 -- plugins/FreeImage/Source/LibTIFF/tif_lzw.c | 1129 - plugins/FreeImage/Source/LibTIFF/tif_msdos.c | 193 - plugins/FreeImage/Source/LibTIFF/tif_next.c | 154 - plugins/FreeImage/Source/LibTIFF/tif_ojpeg.c | 2448 -- plugins/FreeImage/Source/LibTIFF/tif_open.c | 695 - plugins/FreeImage/Source/LibTIFF/tif_packbits.c | 300 - plugins/FreeImage/Source/LibTIFF/tif_pixarlog.c | 1371 -- plugins/FreeImage/Source/LibTIFF/tif_predict.c | 736 - plugins/FreeImage/Source/LibTIFF/tif_predict.h | 77 - plugins/FreeImage/Source/LibTIFF/tif_print.c | 642 - plugins/FreeImage/Source/LibTIFF/tif_read.c | 750 - plugins/FreeImage/Source/LibTIFF/tif_stream.cxx | 295 - plugins/FreeImage/Source/LibTIFF/tif_strip.c | 366 - plugins/FreeImage/Source/LibTIFF/tif_swab.c | 242 - plugins/FreeImage/Source/LibTIFF/tif_thunder.c | 189 - plugins/FreeImage/Source/LibTIFF/tif_tile.c | 280 - plugins/FreeImage/Source/LibTIFF/tif_unix.c | 300 - plugins/FreeImage/Source/LibTIFF/tif_version.c | 40 - plugins/FreeImage/Source/LibTIFF/tif_vms.c | 595 - plugins/FreeImage/Source/LibTIFF/tif_warning.c | 81 - plugins/FreeImage/Source/LibTIFF/tif_win3.c | 232 - plugins/FreeImage/Source/LibTIFF/tif_win32.c | 408 - plugins/FreeImage/Source/LibTIFF/tif_write.c | 718 - plugins/FreeImage/Source/LibTIFF/tif_zip.c | 419 - plugins/FreeImage/Source/LibTIFF/tiff.h | 654 - plugins/FreeImage/Source/LibTIFF/tiffconf.h-vms | 99 - plugins/FreeImage/Source/LibTIFF/tiffconf.vc.h | 116 - plugins/FreeImage/Source/LibTIFF/tiffio.h | 526 - plugins/FreeImage/Source/LibTIFF/tiffio.hxx | 49 - plugins/FreeImage/Source/LibTIFF/tiffiop.h | 353 - plugins/FreeImage/Source/LibTIFF/tiffvers.h | 9 - plugins/FreeImage/Source/LibTIFF/uvcode.h | 180 - plugins/FreeImage/Source/Metadata/Exif.cpp | 859 - plugins/FreeImage/Source/Metadata/FIRational.cpp | 176 - plugins/FreeImage/Source/Metadata/FIRational.h | 108 - plugins/FreeImage/Source/Metadata/FreeImageTag.cpp | 318 - plugins/FreeImage/Source/Metadata/FreeImageTag.h | 474 - plugins/FreeImage/Source/Metadata/IPTC.cpp | 325 - .../FreeImage/Source/Metadata/TagConversion.cpp | 1094 - plugins/FreeImage/Source/Metadata/TagLib.cpp | 1617 -- plugins/FreeImage/Source/Metadata/XTIFF.cpp | 661 - plugins/FreeImage/Source/Plugin.h | 142 - plugins/FreeImage/Source/Quantizers.h | 225 - plugins/FreeImage/Source/ToneMapping.h | 44 - plugins/FreeImage/Source/Utilities.h | 484 - plugins/FreeImage/Source/Zlib/zconf.h | 468 - plugins/FreeImage/Source/Zlib/zlib.h | 1732 -- plugins/FreeImage/Source/Zlib/zutil.h | 248 - plugins/FreeImage/freeimage-translation.txt | 2 - plugins/FreeImage/res/FreeImage.rc | 103 + plugins/FreeImage/res/Version.rc | 42 + plugins/FreeImage/src/CacheFile.h | 92 + .../src/DeprecationManager/Deprecated.cpp | 36 + .../src/DeprecationManager/DeprecationMgr.cpp | 103 + .../src/DeprecationManager/DeprecationMgr.h | 83 + plugins/FreeImage/src/FreeImage.h | 1104 + plugins/FreeImage/src/FreeImage/BitmapAccess.cpp | 1210 + plugins/FreeImage/src/FreeImage/CacheFile.cpp | 271 + plugins/FreeImage/src/FreeImage/ColorLookup.cpp | 782 + plugins/FreeImage/src/FreeImage/Conversion.cpp | 513 + .../FreeImage/src/FreeImage/Conversion16_555.cpp | 209 + .../FreeImage/src/FreeImage/Conversion16_565.cpp | 204 + plugins/FreeImage/src/FreeImage/Conversion24.cpp | 214 + plugins/FreeImage/src/FreeImage/Conversion32.cpp | 345 + plugins/FreeImage/src/FreeImage/Conversion4.cpp | 246 + plugins/FreeImage/src/FreeImage/Conversion8.cpp | 327 + .../FreeImage/src/FreeImage/ConversionFloat.cpp | 192 + .../FreeImage/src/FreeImage/ConversionRGB16.cpp | 144 + plugins/FreeImage/src/FreeImage/ConversionRGBF.cpp | 241 + plugins/FreeImage/src/FreeImage/ConversionType.cpp | 689 + .../FreeImage/src/FreeImage/ConversionUINT16.cpp | 134 + plugins/FreeImage/src/FreeImage/FreeImage.cpp | 226 + plugins/FreeImage/src/FreeImage/FreeImageC.c | 22 + plugins/FreeImage/src/FreeImage/FreeImageIO.cpp | 168 + plugins/FreeImage/src/FreeImage/GetType.cpp | 92 + plugins/FreeImage/src/FreeImage/Halftoning.cpp | 474 + plugins/FreeImage/src/FreeImage/J2KHelper.cpp | 500 + plugins/FreeImage/src/FreeImage/MemoryIO.cpp | 237 + plugins/FreeImage/src/FreeImage/MultiPage.cpp | 990 + plugins/FreeImage/src/FreeImage/NNQuantizer.cpp | 507 + plugins/FreeImage/src/FreeImage/PSDParser.cpp | 1053 + plugins/FreeImage/src/FreeImage/PSDParser.h | 271 + plugins/FreeImage/src/FreeImage/PixelAccess.cpp | 209 + plugins/FreeImage/src/FreeImage/Plugin.cpp | 747 + plugins/FreeImage/src/FreeImage/PluginBMP.cpp | 1480 ++ plugins/FreeImage/src/FreeImage/PluginCUT.cpp | 240 + plugins/FreeImage/src/FreeImage/PluginDDS.cpp | 651 + plugins/FreeImage/src/FreeImage/PluginEXR.cpp | 764 + plugins/FreeImage/src/FreeImage/PluginG3.cpp | 433 + plugins/FreeImage/src/FreeImage/PluginGIF.cpp | 1398 ++ plugins/FreeImage/src/FreeImage/PluginHDR.cpp | 719 + plugins/FreeImage/src/FreeImage/PluginICO.cpp | 805 + plugins/FreeImage/src/FreeImage/PluginIFF.cpp | 459 + plugins/FreeImage/src/FreeImage/PluginJ2K.cpp | 339 + plugins/FreeImage/src/FreeImage/PluginJP2.cpp | 339 + plugins/FreeImage/src/FreeImage/PluginJPEG.cpp | 1801 ++ plugins/FreeImage/src/FreeImage/PluginKOALA.cpp | 243 + plugins/FreeImage/src/FreeImage/PluginMNG.cpp | 153 + plugins/FreeImage/src/FreeImage/PluginPCD.cpp | 251 + plugins/FreeImage/src/FreeImage/PluginPCX.cpp | 659 + plugins/FreeImage/src/FreeImage/PluginPFM.cpp | 402 + plugins/FreeImage/src/FreeImage/PluginPICT.cpp | 1342 + plugins/FreeImage/src/FreeImage/PluginPNG.cpp | 953 + plugins/FreeImage/src/FreeImage/PluginPNM.cpp | 831 + plugins/FreeImage/src/FreeImage/PluginPSD.cpp | 131 + plugins/FreeImage/src/FreeImage/PluginRAS.cpp | 512 + plugins/FreeImage/src/FreeImage/PluginRAW.cpp | 542 + plugins/FreeImage/src/FreeImage/PluginSGI.cpp | 425 + plugins/FreeImage/src/FreeImage/PluginTARGA.cpp | 1565 ++ plugins/FreeImage/src/FreeImage/PluginTIFF.cpp | 2629 ++ plugins/FreeImage/src/FreeImage/PluginWBMP.cpp | 372 + plugins/FreeImage/src/FreeImage/PluginXBM.cpp | 399 + plugins/FreeImage/src/FreeImage/PluginXPM.cpp | 487 + plugins/FreeImage/src/FreeImage/TIFFLogLuv.cpp | 65 + plugins/FreeImage/src/FreeImage/ToneMapping.cpp | 75 + plugins/FreeImage/src/FreeImage/WuQuantizer.cpp | 538 + plugins/FreeImage/src/FreeImage/ZLibInterface.cpp | 223 + .../FreeImage/src/FreeImage/tmoColorConvert.cpp | 479 + plugins/FreeImage/src/FreeImage/tmoDrago03.cpp | 295 + plugins/FreeImage/src/FreeImage/tmoFattal02.cpp | 689 + plugins/FreeImage/src/FreeImage/tmoReinhard05.cpp | 260 + plugins/FreeImage/src/FreeImageIO.h | 48 + .../src/FreeImageToolkit/BSplineRotate.cpp | 730 + .../FreeImage/src/FreeImageToolkit/Channels.cpp | 488 + .../src/FreeImageToolkit/ClassicRotate.cpp | 917 + plugins/FreeImage/src/FreeImageToolkit/Colors.cpp | 967 + .../FreeImage/src/FreeImageToolkit/CopyPaste.cpp | 747 + plugins/FreeImage/src/FreeImageToolkit/Display.cpp | 230 + plugins/FreeImage/src/FreeImageToolkit/Filters.h | 287 + plugins/FreeImage/src/FreeImageToolkit/Flip.cpp | 166 + .../src/FreeImageToolkit/JPEGTransform.cpp | 410 + .../FreeImageToolkit/MultigridPoissonSolver.cpp | 505 + plugins/FreeImage/src/FreeImageToolkit/Rescale.cpp | 231 + plugins/FreeImage/src/FreeImageToolkit/Resize.cpp | 656 + plugins/FreeImage/src/FreeImageToolkit/Resize.h | 145 + plugins/FreeImage/src/LibJPEG/ansi2knr.c | 739 + plugins/FreeImage/src/LibJPEG/cderror.h | 134 + plugins/FreeImage/src/LibJPEG/cdjpeg.c | 181 + plugins/FreeImage/src/LibJPEG/cdjpeg.h | 187 + plugins/FreeImage/src/LibJPEG/change.log | 346 + plugins/FreeImage/src/LibJPEG/cjpeg.c | 643 + plugins/FreeImage/src/LibJPEG/ckconfig.c | 402 + plugins/FreeImage/src/LibJPEG/djpeg.c | 617 + plugins/FreeImage/src/LibJPEG/example.c | 433 + plugins/FreeImage/src/LibJPEG/jaricom.c | 153 + plugins/FreeImage/src/LibJPEG/jcapimin.c | 288 + plugins/FreeImage/src/LibJPEG/jcapistd.c | 161 + plugins/FreeImage/src/LibJPEG/jcarith.c | 937 + plugins/FreeImage/src/LibJPEG/jccoefct.c | 454 + plugins/FreeImage/src/LibJPEG/jccolor.c | 490 + plugins/FreeImage/src/LibJPEG/jcdctmgr.c | 482 + plugins/FreeImage/src/LibJPEG/jchuff.c | 1576 ++ plugins/FreeImage/src/LibJPEG/jcinit.c | 65 + plugins/FreeImage/src/LibJPEG/jcmainct.c | 293 + plugins/FreeImage/src/LibJPEG/jcmarker.c | 682 + plugins/FreeImage/src/LibJPEG/jcmaster.c | 858 + plugins/FreeImage/src/LibJPEG/jcomapi.c | 106 + plugins/FreeImage/src/LibJPEG/jconfig.h | 47 + plugins/FreeImage/src/LibJPEG/jconfig.txt | 164 + plugins/FreeImage/src/LibJPEG/jcparam.c | 632 + plugins/FreeImage/src/LibJPEG/jcprepct.c | 358 + plugins/FreeImage/src/LibJPEG/jcsample.c | 545 + plugins/FreeImage/src/LibJPEG/jctrans.c | 382 + plugins/FreeImage/src/LibJPEG/jdapimin.c | 396 + plugins/FreeImage/src/LibJPEG/jdapistd.c | 275 + plugins/FreeImage/src/LibJPEG/jdarith.c | 776 + plugins/FreeImage/src/LibJPEG/jdatadst.c | 267 + plugins/FreeImage/src/LibJPEG/jdatasrc.c | 275 + plugins/FreeImage/src/LibJPEG/jdcoefct.c | 741 + plugins/FreeImage/src/LibJPEG/jdcolor.c | 512 + plugins/FreeImage/src/LibJPEG/jdct.h | 393 + plugins/FreeImage/src/LibJPEG/jddctmgr.c | 384 + plugins/FreeImage/src/LibJPEG/jdhuff.c | 1541 ++ plugins/FreeImage/src/LibJPEG/jdinput.c | 661 + plugins/FreeImage/src/LibJPEG/jdmainct.c | 512 + plugins/FreeImage/src/LibJPEG/jdmarker.c | 1406 ++ plugins/FreeImage/src/LibJPEG/jdmaster.c | 531 + plugins/FreeImage/src/LibJPEG/jdmerge.c | 400 + plugins/FreeImage/src/LibJPEG/jdpostct.c | 290 + plugins/FreeImage/src/LibJPEG/jdsample.c | 361 + plugins/FreeImage/src/LibJPEG/jdtrans.c | 140 + plugins/FreeImage/src/LibJPEG/jerror.c | 252 + plugins/FreeImage/src/LibJPEG/jerror.h | 304 + plugins/FreeImage/src/LibJPEG/jfdctflt.c | 174 + plugins/FreeImage/src/LibJPEG/jfdctfst.c | 230 + plugins/FreeImage/src/LibJPEG/jfdctint.c | 4348 ++++ plugins/FreeImage/src/LibJPEG/jidctflt.c | 235 + plugins/FreeImage/src/LibJPEG/jidctfst.c | 368 + plugins/FreeImage/src/LibJPEG/jidctint.c | 5137 ++++ plugins/FreeImage/src/LibJPEG/jinclude.h | 91 + plugins/FreeImage/src/LibJPEG/jmemansi.c | 167 + plugins/FreeImage/src/LibJPEG/jmemdos.c | 638 + plugins/FreeImage/src/LibJPEG/jmemdosa.asm | 379 + plugins/FreeImage/src/LibJPEG/jmemmac.c | 289 + plugins/FreeImage/src/LibJPEG/jmemmgr.c | 1119 + plugins/FreeImage/src/LibJPEG/jmemname.c | 276 + plugins/FreeImage/src/LibJPEG/jmemnobs.c | 109 + plugins/FreeImage/src/LibJPEG/jmemsys.h | 198 + plugins/FreeImage/src/LibJPEG/jmorecfg.h | 369 + plugins/FreeImage/src/LibJPEG/jpegint.h | 426 + plugins/FreeImage/src/LibJPEG/jpeglib.h | 1160 + plugins/FreeImage/src/LibJPEG/jpegtran.c | 560 + plugins/FreeImage/src/LibJPEG/jquant1.c | 857 + plugins/FreeImage/src/LibJPEG/jquant2.c | 1311 + plugins/FreeImage/src/LibJPEG/jutils.c | 227 + plugins/FreeImage/src/LibJPEG/jversion.h | 14 + plugins/FreeImage/src/LibJPEG/rdbmp.c | 480 + plugins/FreeImage/src/LibJPEG/rdcolmap.c | 253 + plugins/FreeImage/src/LibJPEG/rdgif.c | 38 + plugins/FreeImage/src/LibJPEG/rdjpgcom.c | 515 + plugins/FreeImage/src/LibJPEG/rdppm.c | 459 + plugins/FreeImage/src/LibJPEG/rdrle.c | 387 + plugins/FreeImage/src/LibJPEG/rdswitch.c | 365 + plugins/FreeImage/src/LibJPEG/rdtarga.c | 500 + plugins/FreeImage/src/LibJPEG/transupp.c | 1597 ++ plugins/FreeImage/src/LibJPEG/transupp.h | 213 + plugins/FreeImage/src/LibJPEG/wrbmp.c | 442 + plugins/FreeImage/src/LibJPEG/wrgif.c | 399 + plugins/FreeImage/src/LibJPEG/wrjpgcom.c | 583 + plugins/FreeImage/src/LibJPEG/wrppm.c | 269 + plugins/FreeImage/src/LibJPEG/wrrle.c | 305 + plugins/FreeImage/src/LibJPEG/wrtarga.c | 253 + plugins/FreeImage/src/LibMNG/Changes | 1447 ++ plugins/FreeImage/src/LibMNG/LICENSE | 57 + plugins/FreeImage/src/LibMNG/README | 36 + plugins/FreeImage/src/LibMNG/README.autoconf | 213 + plugins/FreeImage/src/LibMNG/README.config | 104 + plugins/FreeImage/src/LibMNG/README.contrib | 95 + plugins/FreeImage/src/LibMNG/README.examples | 48 + plugins/FreeImage/src/LibMNG/README.footprint | 46 + plugins/FreeImage/src/LibMNG/README.packaging | 24 + plugins/FreeImage/src/LibMNG/libmng.h | 2932 +++ plugins/FreeImage/src/LibMNG/libmng_callback_xs.c | 1239 + plugins/FreeImage/src/LibMNG/libmng_chunk_descr.c | 6090 +++++ plugins/FreeImage/src/LibMNG/libmng_chunk_descr.h | 146 + plugins/FreeImage/src/LibMNG/libmng_chunk_io.c | 10740 ++++++++ plugins/FreeImage/src/LibMNG/libmng_chunk_io.h | 415 + plugins/FreeImage/src/LibMNG/libmng_chunk_prc.c | 4452 ++++ plugins/FreeImage/src/LibMNG/libmng_chunk_prc.h | 381 + plugins/FreeImage/src/LibMNG/libmng_chunk_xs.c | 7016 ++++++ plugins/FreeImage/src/LibMNG/libmng_chunks.h | 1026 + plugins/FreeImage/src/LibMNG/libmng_cms.c | 758 + plugins/FreeImage/src/LibMNG/libmng_cms.h | 92 + plugins/FreeImage/src/LibMNG/libmng_conf.h | 306 + plugins/FreeImage/src/LibMNG/libmng_data.h | 1029 + plugins/FreeImage/src/LibMNG/libmng_display.c | 7135 ++++++ plugins/FreeImage/src/LibMNG/libmng_display.h | 343 + plugins/FreeImage/src/LibMNG/libmng_dither.c | 58 + plugins/FreeImage/src/LibMNG/libmng_dither.h | 45 + plugins/FreeImage/src/LibMNG/libmng_error.c | 326 + plugins/FreeImage/src/LibMNG/libmng_error.h | 119 + plugins/FreeImage/src/LibMNG/libmng_filter.c | 978 + plugins/FreeImage/src/LibMNG/libmng_filter.h | 69 + plugins/FreeImage/src/LibMNG/libmng_hlapi.c | 2995 +++ plugins/FreeImage/src/LibMNG/libmng_jpeg.c | 1088 + plugins/FreeImage/src/LibMNG/libmng_jpeg.h | 57 + plugins/FreeImage/src/LibMNG/libmng_memory.h | 64 + plugins/FreeImage/src/LibMNG/libmng_object_prc.c | 6998 ++++++ plugins/FreeImage/src/LibMNG/libmng_object_prc.h | 690 + plugins/FreeImage/src/LibMNG/libmng_objects.h | 635 + plugins/FreeImage/src/LibMNG/libmng_pixels.c | 24610 +++++++++++++++++++ plugins/FreeImage/src/LibMNG/libmng_pixels.h | 1147 + plugins/FreeImage/src/LibMNG/libmng_prop_xs.c | 2799 +++ plugins/FreeImage/src/LibMNG/libmng_read.c | 1369 ++ plugins/FreeImage/src/LibMNG/libmng_read.h | 53 + plugins/FreeImage/src/LibMNG/libmng_trace.c | 1683 ++ plugins/FreeImage/src/LibMNG/libmng_trace.h | 1474 ++ plugins/FreeImage/src/LibMNG/libmng_types.h | 574 + plugins/FreeImage/src/LibMNG/libmng_write.c | 198 + plugins/FreeImage/src/LibMNG/libmng_write.h | 49 + plugins/FreeImage/src/LibMNG/libmng_zlib.c | 607 + plugins/FreeImage/src/LibMNG/libmng_zlib.h | 60 + plugins/FreeImage/src/LibPNG/ANNOUNCE | 42 + plugins/FreeImage/src/LibPNG/CHANGES | 3820 +++ plugins/FreeImage/src/LibPNG/INSTALL | 135 + plugins/FreeImage/src/LibPNG/KNOWNBUG | 29 + plugins/FreeImage/src/LibPNG/LICENSE | 111 + plugins/FreeImage/src/LibPNG/README | 202 + plugins/FreeImage/src/LibPNG/TODO | 27 + plugins/FreeImage/src/LibPNG/Y2KINFO | 55 + plugins/FreeImage/src/LibPNG/configure | 19 + plugins/FreeImage/src/LibPNG/libpng.3 | 5952 +++++ plugins/FreeImage/src/LibPNG/libpng.txt | 3352 +++ plugins/FreeImage/src/LibPNG/libpngpf.3 | 28 + plugins/FreeImage/src/LibPNG/png.5 | 74 + plugins/FreeImage/src/LibPNG/png.c | 2870 +++ plugins/FreeImage/src/LibPNG/png.h | 2658 ++ plugins/FreeImage/src/LibPNG/pngconf.h | 596 + plugins/FreeImage/src/LibPNG/pngdebug.h | 157 + plugins/FreeImage/src/LibPNG/pngerror.c | 685 + plugins/FreeImage/src/LibPNG/pngget.c | 1124 + plugins/FreeImage/src/LibPNG/pnginfo.h | 269 + plugins/FreeImage/src/LibPNG/pnglibconf.h | 187 + plugins/FreeImage/src/LibPNG/pngmem.c | 667 + plugins/FreeImage/src/LibPNG/pngpread.c | 1843 ++ plugins/FreeImage/src/LibPNG/pngpriv.h | 1629 ++ plugins/FreeImage/src/LibPNG/pngread.c | 1308 + plugins/FreeImage/src/LibPNG/pngrio.c | 176 + plugins/FreeImage/src/LibPNG/pngrtran.c | 5023 ++++ plugins/FreeImage/src/LibPNG/pngrutil.c | 4158 ++++ plugins/FreeImage/src/LibPNG/pngset.c | 1284 + plugins/FreeImage/src/LibPNG/pngstruct.h | 358 + plugins/FreeImage/src/LibPNG/pngtest.c | 1820 ++ plugins/FreeImage/src/LibPNG/pngtrans.c | 678 + plugins/FreeImage/src/LibPNG/pngwio.c | 254 + plugins/FreeImage/src/LibPNG/pngwrite.c | 1655 ++ plugins/FreeImage/src/LibPNG/pngwtran.c | 633 + plugins/FreeImage/src/LibPNG/pngwutil.c | 3180 +++ plugins/FreeImage/src/LibTIFF/ChangeLog | 4849 ++++ plugins/FreeImage/src/LibTIFF/LibTIFF.dsp | 293 + plugins/FreeImage/src/LibTIFF/SConstruct | 73 + plugins/FreeImage/src/LibTIFF/mkg3states.c | 451 + plugins/FreeImage/src/LibTIFF/t4.h | 292 + plugins/FreeImage/src/LibTIFF/tif_acorn.c | 526 + plugins/FreeImage/src/LibTIFF/tif_apple.c | 281 + plugins/FreeImage/src/LibTIFF/tif_atari.c | 250 + plugins/FreeImage/src/LibTIFF/tif_aux.c | 290 + plugins/FreeImage/src/LibTIFF/tif_close.c | 126 + plugins/FreeImage/src/LibTIFF/tif_codec.c | 160 + plugins/FreeImage/src/LibTIFF/tif_color.c | 287 + plugins/FreeImage/src/LibTIFF/tif_compress.c | 295 + plugins/FreeImage/src/LibTIFF/tif_config.h | 266 + plugins/FreeImage/src/LibTIFF/tif_config.h-vms | 46 + plugins/FreeImage/src/LibTIFF/tif_config.h.in | 309 + plugins/FreeImage/src/LibTIFF/tif_config.vc.h | 63 + plugins/FreeImage/src/LibTIFF/tif_dir.c | 1391 ++ plugins/FreeImage/src/LibTIFF/tif_dir.h | 211 + plugins/FreeImage/src/LibTIFF/tif_dirinfo.c | 884 + plugins/FreeImage/src/LibTIFF/tif_dirread.c | 2117 ++ plugins/FreeImage/src/LibTIFF/tif_dirwrite.c | 1436 ++ plugins/FreeImage/src/LibTIFF/tif_dumpmode.c | 126 + plugins/FreeImage/src/LibTIFF/tif_error.c | 80 + plugins/FreeImage/src/LibTIFF/tif_extension.c | 118 + plugins/FreeImage/src/LibTIFF/tif_fax3.c | 1626 ++ plugins/FreeImage/src/LibTIFF/tif_fax3.h | 538 + plugins/FreeImage/src/LibTIFF/tif_fax3sm.c | 1260 + plugins/FreeImage/src/LibTIFF/tif_flush.c | 74 + plugins/FreeImage/src/LibTIFF/tif_getimage.c | 2678 ++ plugins/FreeImage/src/LibTIFF/tif_jbig.c | 385 + plugins/FreeImage/src/LibTIFF/tif_jpeg.c | 2078 ++ plugins/FreeImage/src/LibTIFF/tif_luv.c | 1629 ++ plugins/FreeImage/src/LibTIFF/tif_lzw.c | 1129 + plugins/FreeImage/src/LibTIFF/tif_msdos.c | 193 + plugins/FreeImage/src/LibTIFF/tif_next.c | 154 + plugins/FreeImage/src/LibTIFF/tif_ojpeg.c | 2448 ++ plugins/FreeImage/src/LibTIFF/tif_open.c | 695 + plugins/FreeImage/src/LibTIFF/tif_packbits.c | 300 + plugins/FreeImage/src/LibTIFF/tif_pixarlog.c | 1371 ++ plugins/FreeImage/src/LibTIFF/tif_predict.c | 736 + plugins/FreeImage/src/LibTIFF/tif_predict.h | 77 + plugins/FreeImage/src/LibTIFF/tif_print.c | 642 + plugins/FreeImage/src/LibTIFF/tif_read.c | 750 + plugins/FreeImage/src/LibTIFF/tif_stream.cxx | 295 + plugins/FreeImage/src/LibTIFF/tif_strip.c | 366 + plugins/FreeImage/src/LibTIFF/tif_swab.c | 242 + plugins/FreeImage/src/LibTIFF/tif_thunder.c | 189 + plugins/FreeImage/src/LibTIFF/tif_tile.c | 280 + plugins/FreeImage/src/LibTIFF/tif_unix.c | 300 + plugins/FreeImage/src/LibTIFF/tif_version.c | 40 + plugins/FreeImage/src/LibTIFF/tif_vms.c | 595 + plugins/FreeImage/src/LibTIFF/tif_warning.c | 81 + plugins/FreeImage/src/LibTIFF/tif_win3.c | 232 + plugins/FreeImage/src/LibTIFF/tif_win32.c | 408 + plugins/FreeImage/src/LibTIFF/tif_write.c | 718 + plugins/FreeImage/src/LibTIFF/tif_zip.c | 419 + plugins/FreeImage/src/LibTIFF/tiff.h | 654 + plugins/FreeImage/src/LibTIFF/tiffconf.h-vms | 99 + plugins/FreeImage/src/LibTIFF/tiffconf.vc.h | 116 + plugins/FreeImage/src/LibTIFF/tiffio.h | 526 + plugins/FreeImage/src/LibTIFF/tiffio.hxx | 49 + plugins/FreeImage/src/LibTIFF/tiffiop.h | 353 + plugins/FreeImage/src/LibTIFF/tiffvers.h | 9 + plugins/FreeImage/src/LibTIFF/uvcode.h | 180 + plugins/FreeImage/src/Metadata/Exif.cpp | 859 + plugins/FreeImage/src/Metadata/FIRational.cpp | 176 + plugins/FreeImage/src/Metadata/FIRational.h | 108 + plugins/FreeImage/src/Metadata/FreeImageTag.cpp | 318 + plugins/FreeImage/src/Metadata/FreeImageTag.h | 474 + plugins/FreeImage/src/Metadata/IPTC.cpp | 325 + plugins/FreeImage/src/Metadata/TagConversion.cpp | 1094 + plugins/FreeImage/src/Metadata/TagLib.cpp | 1617 ++ plugins/FreeImage/src/Metadata/XTIFF.cpp | 661 + plugins/FreeImage/src/Plugin.h | 142 + plugins/FreeImage/src/Quantizers.h | 225 + plugins/FreeImage/src/ToneMapping.h | 44 + plugins/FreeImage/src/Utilities.h | 484 + plugins/FreeImage/src/Zlib/zconf.h | 468 + plugins/FreeImage/src/Zlib/zlib.h | 1732 ++ plugins/FreeImage/src/Zlib/zutil.h | 248 + plugins/FreeImage/src/main.cpp | 1255 + plugins/FreeImage/src/version.h | 20 + plugins/FreeImage/version.rc | 115 - 691 files changed, 284453 insertions(+), 285504 deletions(-) create mode 100644 plugins/FreeImage/Docs/freeimage-translation.txt delete mode 100644 plugins/FreeImage/FreeImage.rc delete mode 100644 plugins/FreeImage/Miranda/main.cpp delete mode 100644 plugins/FreeImage/Miranda/version.h delete mode 100644 plugins/FreeImage/Source/CacheFile.h delete mode 100644 plugins/FreeImage/Source/DeprecationManager/Deprecated.cpp delete mode 100644 plugins/FreeImage/Source/DeprecationManager/DeprecationMgr.cpp delete mode 100644 plugins/FreeImage/Source/DeprecationManager/DeprecationMgr.h delete mode 100644 plugins/FreeImage/Source/FreeImage.h delete mode 100644 plugins/FreeImage/Source/FreeImage/BitmapAccess.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/CacheFile.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/ColorLookup.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/Conversion.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/Conversion16_555.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/Conversion16_565.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/Conversion24.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/Conversion32.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/Conversion4.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/Conversion8.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/ConversionFloat.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/ConversionRGB16.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/ConversionRGBF.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/ConversionType.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/ConversionUINT16.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/FreeImage.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/FreeImageC.c delete mode 100644 plugins/FreeImage/Source/FreeImage/FreeImageIO.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/GetType.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/Halftoning.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/J2KHelper.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/MemoryIO.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/MultiPage.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/NNQuantizer.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PSDParser.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PSDParser.h delete mode 100644 plugins/FreeImage/Source/FreeImage/PixelAccess.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/Plugin.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginBMP.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginCUT.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginDDS.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginEXR.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginG3.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginGIF.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginHDR.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginICO.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginIFF.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginJ2K.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginJP2.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginJPEG.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginKOALA.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginMNG.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginPCD.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginPCX.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginPFM.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginPICT.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginPNG.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginPNM.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginPSD.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginRAS.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginRAW.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginSGI.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginTARGA.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginTIFF.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginWBMP.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginXBM.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/PluginXPM.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/TIFFLogLuv.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/ToneMapping.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/WuQuantizer.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/ZLibInterface.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/tmoColorConvert.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/tmoDrago03.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/tmoFattal02.cpp delete mode 100644 plugins/FreeImage/Source/FreeImage/tmoReinhard05.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageIO.h delete mode 100644 plugins/FreeImage/Source/FreeImageLib/FreeImageLib.dsp delete mode 100644 plugins/FreeImage/Source/FreeImageLib/FreeImageLib.vcproj delete mode 100644 plugins/FreeImage/Source/FreeImageLib/FreeImageLib.vpj delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/BSplineRotate.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/ClassicRotate.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Colors.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Display.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Filters.h delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/JPEGTransform.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/MultigridPoissonSolver.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Rescale.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Resize.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Resize.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/ansi2knr.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/cderror.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/cdjpeg.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/cdjpeg.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/change.log delete mode 100644 plugins/FreeImage/Source/LibJPEG/cjpeg.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/ckconfig.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/djpeg.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/example.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jaricom.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcapimin.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcapistd.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcarith.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jccoefct.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jccolor.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcdctmgr.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jchuff.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcinit.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcmainct.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcmarker.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcmaster.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcomapi.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jconfig.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/jconfig.txt delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcparam.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcprepct.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jcsample.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jctrans.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdapimin.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdapistd.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdarith.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdatadst.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdatasrc.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdcoefct.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdcolor.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdct.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/jddctmgr.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdhuff.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdinput.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdmainct.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdmarker.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdmaster.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdmerge.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdpostct.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdsample.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jdtrans.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jerror.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jerror.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/jfdctflt.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jfdctfst.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jfdctint.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jidctflt.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jidctfst.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jidctint.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jinclude.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/jmemansi.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jmemdos.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jmemdosa.asm delete mode 100644 plugins/FreeImage/Source/LibJPEG/jmemmac.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jmemmgr.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jmemname.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jmemnobs.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jmemsys.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/jmorecfg.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/jpegint.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/jpeglib.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/jpegtran.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jquant1.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jquant2.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jutils.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/jversion.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/rdbmp.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/rdcolmap.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/rdgif.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/rdjpgcom.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/rdppm.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/rdrle.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/rdswitch.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/rdtarga.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/transupp.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/transupp.h delete mode 100644 plugins/FreeImage/Source/LibJPEG/wrbmp.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/wrgif.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/wrjpgcom.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/wrppm.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/wrrle.c delete mode 100644 plugins/FreeImage/Source/LibJPEG/wrtarga.c delete mode 100644 plugins/FreeImage/Source/LibMNG/Changes delete mode 100644 plugins/FreeImage/Source/LibMNG/LICENSE delete mode 100644 plugins/FreeImage/Source/LibMNG/README delete mode 100644 plugins/FreeImage/Source/LibMNG/README.autoconf delete mode 100644 plugins/FreeImage/Source/LibMNG/README.config delete mode 100644 plugins/FreeImage/Source/LibMNG/README.contrib delete mode 100644 plugins/FreeImage/Source/LibMNG/README.examples delete mode 100644 plugins/FreeImage/Source/LibMNG/README.footprint delete mode 100644 plugins/FreeImage/Source/LibMNG/README.packaging delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_callback_xs.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_chunk_descr.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_chunk_descr.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_chunk_io.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_chunk_io.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_chunk_xs.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_chunks.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_cms.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_cms.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_conf.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_data.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_display.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_display.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_dither.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_dither.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_error.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_error.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_filter.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_filter.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_hlapi.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_jpeg.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_jpeg.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_memory.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_object_prc.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_object_prc.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_objects.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_pixels.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_pixels.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_prop_xs.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_read.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_read.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_trace.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_trace.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_types.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_write.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_write.h delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_zlib.c delete mode 100644 plugins/FreeImage/Source/LibMNG/libmng_zlib.h delete mode 100644 plugins/FreeImage/Source/LibPNG/ANNOUNCE delete mode 100644 plugins/FreeImage/Source/LibPNG/CHANGES delete mode 100644 plugins/FreeImage/Source/LibPNG/INSTALL delete mode 100644 plugins/FreeImage/Source/LibPNG/KNOWNBUG delete mode 100644 plugins/FreeImage/Source/LibPNG/LICENSE delete mode 100644 plugins/FreeImage/Source/LibPNG/README delete mode 100644 plugins/FreeImage/Source/LibPNG/TODO delete mode 100644 plugins/FreeImage/Source/LibPNG/Y2KINFO delete mode 100644 plugins/FreeImage/Source/LibPNG/configure delete mode 100644 plugins/FreeImage/Source/LibPNG/libpng.3 delete mode 100644 plugins/FreeImage/Source/LibPNG/libpng.txt delete mode 100644 plugins/FreeImage/Source/LibPNG/libpngpf.3 delete mode 100644 plugins/FreeImage/Source/LibPNG/png.5 delete mode 100644 plugins/FreeImage/Source/LibPNG/png.c delete mode 100644 plugins/FreeImage/Source/LibPNG/png.h delete mode 100644 plugins/FreeImage/Source/LibPNG/pngconf.h delete mode 100644 plugins/FreeImage/Source/LibPNG/pngdebug.h delete mode 100644 plugins/FreeImage/Source/LibPNG/pngerror.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngget.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pnginfo.h delete mode 100644 plugins/FreeImage/Source/LibPNG/pnglibconf.h delete mode 100644 plugins/FreeImage/Source/LibPNG/pngmem.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngpread.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngpriv.h delete mode 100644 plugins/FreeImage/Source/LibPNG/pngread.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngrio.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngrtran.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngrutil.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngset.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngstruct.h delete mode 100644 plugins/FreeImage/Source/LibPNG/pngtest.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngtrans.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngwio.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngwrite.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngwtran.c delete mode 100644 plugins/FreeImage/Source/LibPNG/pngwutil.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/ChangeLog delete mode 100644 plugins/FreeImage/Source/LibTIFF/LibTIFF.dsp delete mode 100644 plugins/FreeImage/Source/LibTIFF/SConstruct delete mode 100644 plugins/FreeImage/Source/LibTIFF/mkg3states.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/t4.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_acorn.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_apple.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_atari.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_aux.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_close.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_codec.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_color.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_compress.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_config.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_config.h-vms delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_config.h.in delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_config.vc.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_dir.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_dir.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_dirinfo.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_dirread.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_dirwrite.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_dumpmode.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_error.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_extension.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_fax3.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_fax3.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_fax3sm.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_flush.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_getimage.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_jbig.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_jpeg.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_luv.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_lzw.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_msdos.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_next.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_ojpeg.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_open.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_packbits.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_pixarlog.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_predict.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_predict.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_print.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_read.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_stream.cxx delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_strip.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_swab.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_thunder.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_tile.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_unix.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_version.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_vms.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_warning.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_win3.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_win32.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_write.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tif_zip.c delete mode 100644 plugins/FreeImage/Source/LibTIFF/tiff.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tiffconf.h-vms delete mode 100644 plugins/FreeImage/Source/LibTIFF/tiffconf.vc.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tiffio.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tiffio.hxx delete mode 100644 plugins/FreeImage/Source/LibTIFF/tiffiop.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/tiffvers.h delete mode 100644 plugins/FreeImage/Source/LibTIFF/uvcode.h delete mode 100644 plugins/FreeImage/Source/Metadata/Exif.cpp delete mode 100644 plugins/FreeImage/Source/Metadata/FIRational.cpp delete mode 100644 plugins/FreeImage/Source/Metadata/FIRational.h delete mode 100644 plugins/FreeImage/Source/Metadata/FreeImageTag.cpp delete mode 100644 plugins/FreeImage/Source/Metadata/FreeImageTag.h delete mode 100644 plugins/FreeImage/Source/Metadata/IPTC.cpp delete mode 100644 plugins/FreeImage/Source/Metadata/TagConversion.cpp delete mode 100644 plugins/FreeImage/Source/Metadata/TagLib.cpp delete mode 100644 plugins/FreeImage/Source/Metadata/XTIFF.cpp delete mode 100644 plugins/FreeImage/Source/Plugin.h delete mode 100644 plugins/FreeImage/Source/Quantizers.h delete mode 100644 plugins/FreeImage/Source/ToneMapping.h delete mode 100644 plugins/FreeImage/Source/Utilities.h delete mode 100644 plugins/FreeImage/Source/Zlib/zconf.h delete mode 100644 plugins/FreeImage/Source/Zlib/zlib.h delete mode 100644 plugins/FreeImage/Source/Zlib/zutil.h delete mode 100644 plugins/FreeImage/freeimage-translation.txt create mode 100644 plugins/FreeImage/res/FreeImage.rc create mode 100644 plugins/FreeImage/res/Version.rc create mode 100644 plugins/FreeImage/src/CacheFile.h create mode 100644 plugins/FreeImage/src/DeprecationManager/Deprecated.cpp create mode 100644 plugins/FreeImage/src/DeprecationManager/DeprecationMgr.cpp create mode 100644 plugins/FreeImage/src/DeprecationManager/DeprecationMgr.h create mode 100644 plugins/FreeImage/src/FreeImage.h create mode 100644 plugins/FreeImage/src/FreeImage/BitmapAccess.cpp create mode 100644 plugins/FreeImage/src/FreeImage/CacheFile.cpp create mode 100644 plugins/FreeImage/src/FreeImage/ColorLookup.cpp create mode 100644 plugins/FreeImage/src/FreeImage/Conversion.cpp create mode 100644 plugins/FreeImage/src/FreeImage/Conversion16_555.cpp create mode 100644 plugins/FreeImage/src/FreeImage/Conversion16_565.cpp create mode 100644 plugins/FreeImage/src/FreeImage/Conversion24.cpp create mode 100644 plugins/FreeImage/src/FreeImage/Conversion32.cpp create mode 100644 plugins/FreeImage/src/FreeImage/Conversion4.cpp create mode 100644 plugins/FreeImage/src/FreeImage/Conversion8.cpp create mode 100644 plugins/FreeImage/src/FreeImage/ConversionFloat.cpp create mode 100644 plugins/FreeImage/src/FreeImage/ConversionRGB16.cpp create mode 100644 plugins/FreeImage/src/FreeImage/ConversionRGBF.cpp create mode 100644 plugins/FreeImage/src/FreeImage/ConversionType.cpp create mode 100644 plugins/FreeImage/src/FreeImage/ConversionUINT16.cpp create mode 100644 plugins/FreeImage/src/FreeImage/FreeImage.cpp create mode 100644 plugins/FreeImage/src/FreeImage/FreeImageC.c create mode 100644 plugins/FreeImage/src/FreeImage/FreeImageIO.cpp create mode 100644 plugins/FreeImage/src/FreeImage/GetType.cpp create mode 100644 plugins/FreeImage/src/FreeImage/Halftoning.cpp create mode 100644 plugins/FreeImage/src/FreeImage/J2KHelper.cpp create mode 100644 plugins/FreeImage/src/FreeImage/MemoryIO.cpp create mode 100644 plugins/FreeImage/src/FreeImage/MultiPage.cpp create mode 100644 plugins/FreeImage/src/FreeImage/NNQuantizer.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PSDParser.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PSDParser.h create mode 100644 plugins/FreeImage/src/FreeImage/PixelAccess.cpp create mode 100644 plugins/FreeImage/src/FreeImage/Plugin.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginBMP.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginCUT.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginDDS.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginEXR.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginG3.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginGIF.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginHDR.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginICO.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginIFF.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginJ2K.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginJP2.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginJPEG.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginKOALA.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginMNG.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginPCD.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginPCX.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginPFM.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginPICT.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginPNG.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginPNM.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginPSD.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginRAS.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginRAW.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginSGI.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginTARGA.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginTIFF.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginWBMP.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginXBM.cpp create mode 100644 plugins/FreeImage/src/FreeImage/PluginXPM.cpp create mode 100644 plugins/FreeImage/src/FreeImage/TIFFLogLuv.cpp create mode 100644 plugins/FreeImage/src/FreeImage/ToneMapping.cpp create mode 100644 plugins/FreeImage/src/FreeImage/WuQuantizer.cpp create mode 100644 plugins/FreeImage/src/FreeImage/ZLibInterface.cpp create mode 100644 plugins/FreeImage/src/FreeImage/tmoColorConvert.cpp create mode 100644 plugins/FreeImage/src/FreeImage/tmoDrago03.cpp create mode 100644 plugins/FreeImage/src/FreeImage/tmoFattal02.cpp create mode 100644 plugins/FreeImage/src/FreeImage/tmoReinhard05.cpp create mode 100644 plugins/FreeImage/src/FreeImageIO.h create mode 100644 plugins/FreeImage/src/FreeImageToolkit/BSplineRotate.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/Channels.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/ClassicRotate.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/Colors.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/CopyPaste.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/Display.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/Filters.h create mode 100644 plugins/FreeImage/src/FreeImageToolkit/Flip.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/JPEGTransform.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/MultigridPoissonSolver.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/Rescale.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/Resize.cpp create mode 100644 plugins/FreeImage/src/FreeImageToolkit/Resize.h create mode 100644 plugins/FreeImage/src/LibJPEG/ansi2knr.c create mode 100644 plugins/FreeImage/src/LibJPEG/cderror.h create mode 100644 plugins/FreeImage/src/LibJPEG/cdjpeg.c create mode 100644 plugins/FreeImage/src/LibJPEG/cdjpeg.h create mode 100644 plugins/FreeImage/src/LibJPEG/change.log create mode 100644 plugins/FreeImage/src/LibJPEG/cjpeg.c create mode 100644 plugins/FreeImage/src/LibJPEG/ckconfig.c create mode 100644 plugins/FreeImage/src/LibJPEG/djpeg.c create mode 100644 plugins/FreeImage/src/LibJPEG/example.c create mode 100644 plugins/FreeImage/src/LibJPEG/jaricom.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcapimin.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcapistd.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcarith.c create mode 100644 plugins/FreeImage/src/LibJPEG/jccoefct.c create mode 100644 plugins/FreeImage/src/LibJPEG/jccolor.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcdctmgr.c create mode 100644 plugins/FreeImage/src/LibJPEG/jchuff.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcinit.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcmainct.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcmarker.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcmaster.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcomapi.c create mode 100644 plugins/FreeImage/src/LibJPEG/jconfig.h create mode 100644 plugins/FreeImage/src/LibJPEG/jconfig.txt create mode 100644 plugins/FreeImage/src/LibJPEG/jcparam.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcprepct.c create mode 100644 plugins/FreeImage/src/LibJPEG/jcsample.c create mode 100644 plugins/FreeImage/src/LibJPEG/jctrans.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdapimin.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdapistd.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdarith.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdatadst.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdatasrc.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdcoefct.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdcolor.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdct.h create mode 100644 plugins/FreeImage/src/LibJPEG/jddctmgr.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdhuff.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdinput.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdmainct.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdmarker.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdmaster.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdmerge.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdpostct.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdsample.c create mode 100644 plugins/FreeImage/src/LibJPEG/jdtrans.c create mode 100644 plugins/FreeImage/src/LibJPEG/jerror.c create mode 100644 plugins/FreeImage/src/LibJPEG/jerror.h create mode 100644 plugins/FreeImage/src/LibJPEG/jfdctflt.c create mode 100644 plugins/FreeImage/src/LibJPEG/jfdctfst.c create mode 100644 plugins/FreeImage/src/LibJPEG/jfdctint.c create mode 100644 plugins/FreeImage/src/LibJPEG/jidctflt.c create mode 100644 plugins/FreeImage/src/LibJPEG/jidctfst.c create mode 100644 plugins/FreeImage/src/LibJPEG/jidctint.c create mode 100644 plugins/FreeImage/src/LibJPEG/jinclude.h create mode 100644 plugins/FreeImage/src/LibJPEG/jmemansi.c create mode 100644 plugins/FreeImage/src/LibJPEG/jmemdos.c create mode 100644 plugins/FreeImage/src/LibJPEG/jmemdosa.asm create mode 100644 plugins/FreeImage/src/LibJPEG/jmemmac.c create mode 100644 plugins/FreeImage/src/LibJPEG/jmemmgr.c create mode 100644 plugins/FreeImage/src/LibJPEG/jmemname.c create mode 100644 plugins/FreeImage/src/LibJPEG/jmemnobs.c create mode 100644 plugins/FreeImage/src/LibJPEG/jmemsys.h create mode 100644 plugins/FreeImage/src/LibJPEG/jmorecfg.h create mode 100644 plugins/FreeImage/src/LibJPEG/jpegint.h create mode 100644 plugins/FreeImage/src/LibJPEG/jpeglib.h create mode 100644 plugins/FreeImage/src/LibJPEG/jpegtran.c create mode 100644 plugins/FreeImage/src/LibJPEG/jquant1.c create mode 100644 plugins/FreeImage/src/LibJPEG/jquant2.c create mode 100644 plugins/FreeImage/src/LibJPEG/jutils.c create mode 100644 plugins/FreeImage/src/LibJPEG/jversion.h create mode 100644 plugins/FreeImage/src/LibJPEG/rdbmp.c create mode 100644 plugins/FreeImage/src/LibJPEG/rdcolmap.c create mode 100644 plugins/FreeImage/src/LibJPEG/rdgif.c create mode 100644 plugins/FreeImage/src/LibJPEG/rdjpgcom.c create mode 100644 plugins/FreeImage/src/LibJPEG/rdppm.c create mode 100644 plugins/FreeImage/src/LibJPEG/rdrle.c create mode 100644 plugins/FreeImage/src/LibJPEG/rdswitch.c create mode 100644 plugins/FreeImage/src/LibJPEG/rdtarga.c create mode 100644 plugins/FreeImage/src/LibJPEG/transupp.c create mode 100644 plugins/FreeImage/src/LibJPEG/transupp.h create mode 100644 plugins/FreeImage/src/LibJPEG/wrbmp.c create mode 100644 plugins/FreeImage/src/LibJPEG/wrgif.c create mode 100644 plugins/FreeImage/src/LibJPEG/wrjpgcom.c create mode 100644 plugins/FreeImage/src/LibJPEG/wrppm.c create mode 100644 plugins/FreeImage/src/LibJPEG/wrrle.c create mode 100644 plugins/FreeImage/src/LibJPEG/wrtarga.c create mode 100644 plugins/FreeImage/src/LibMNG/Changes create mode 100644 plugins/FreeImage/src/LibMNG/LICENSE create mode 100644 plugins/FreeImage/src/LibMNG/README create mode 100644 plugins/FreeImage/src/LibMNG/README.autoconf create mode 100644 plugins/FreeImage/src/LibMNG/README.config create mode 100644 plugins/FreeImage/src/LibMNG/README.contrib create mode 100644 plugins/FreeImage/src/LibMNG/README.examples create mode 100644 plugins/FreeImage/src/LibMNG/README.footprint create mode 100644 plugins/FreeImage/src/LibMNG/README.packaging create mode 100644 plugins/FreeImage/src/LibMNG/libmng.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_callback_xs.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_chunk_descr.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_chunk_descr.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_chunk_io.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_chunk_io.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_chunk_prc.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_chunk_prc.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_chunk_xs.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_chunks.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_cms.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_cms.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_conf.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_data.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_display.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_display.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_dither.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_dither.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_error.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_error.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_filter.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_filter.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_hlapi.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_jpeg.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_jpeg.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_memory.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_object_prc.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_object_prc.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_objects.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_pixels.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_pixels.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_prop_xs.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_read.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_read.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_trace.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_trace.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_types.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_write.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_write.h create mode 100644 plugins/FreeImage/src/LibMNG/libmng_zlib.c create mode 100644 plugins/FreeImage/src/LibMNG/libmng_zlib.h create mode 100644 plugins/FreeImage/src/LibPNG/ANNOUNCE create mode 100644 plugins/FreeImage/src/LibPNG/CHANGES create mode 100644 plugins/FreeImage/src/LibPNG/INSTALL create mode 100644 plugins/FreeImage/src/LibPNG/KNOWNBUG create mode 100644 plugins/FreeImage/src/LibPNG/LICENSE create mode 100644 plugins/FreeImage/src/LibPNG/README create mode 100644 plugins/FreeImage/src/LibPNG/TODO create mode 100644 plugins/FreeImage/src/LibPNG/Y2KINFO create mode 100644 plugins/FreeImage/src/LibPNG/configure create mode 100644 plugins/FreeImage/src/LibPNG/libpng.3 create mode 100644 plugins/FreeImage/src/LibPNG/libpng.txt create mode 100644 plugins/FreeImage/src/LibPNG/libpngpf.3 create mode 100644 plugins/FreeImage/src/LibPNG/png.5 create mode 100644 plugins/FreeImage/src/LibPNG/png.c create mode 100644 plugins/FreeImage/src/LibPNG/png.h create mode 100644 plugins/FreeImage/src/LibPNG/pngconf.h create mode 100644 plugins/FreeImage/src/LibPNG/pngdebug.h create mode 100644 plugins/FreeImage/src/LibPNG/pngerror.c create mode 100644 plugins/FreeImage/src/LibPNG/pngget.c create mode 100644 plugins/FreeImage/src/LibPNG/pnginfo.h create mode 100644 plugins/FreeImage/src/LibPNG/pnglibconf.h create mode 100644 plugins/FreeImage/src/LibPNG/pngmem.c create mode 100644 plugins/FreeImage/src/LibPNG/pngpread.c create mode 100644 plugins/FreeImage/src/LibPNG/pngpriv.h create mode 100644 plugins/FreeImage/src/LibPNG/pngread.c create mode 100644 plugins/FreeImage/src/LibPNG/pngrio.c create mode 100644 plugins/FreeImage/src/LibPNG/pngrtran.c create mode 100644 plugins/FreeImage/src/LibPNG/pngrutil.c create mode 100644 plugins/FreeImage/src/LibPNG/pngset.c create mode 100644 plugins/FreeImage/src/LibPNG/pngstruct.h create mode 100644 plugins/FreeImage/src/LibPNG/pngtest.c create mode 100644 plugins/FreeImage/src/LibPNG/pngtrans.c create mode 100644 plugins/FreeImage/src/LibPNG/pngwio.c create mode 100644 plugins/FreeImage/src/LibPNG/pngwrite.c create mode 100644 plugins/FreeImage/src/LibPNG/pngwtran.c create mode 100644 plugins/FreeImage/src/LibPNG/pngwutil.c create mode 100644 plugins/FreeImage/src/LibTIFF/ChangeLog create mode 100644 plugins/FreeImage/src/LibTIFF/LibTIFF.dsp create mode 100644 plugins/FreeImage/src/LibTIFF/SConstruct create mode 100644 plugins/FreeImage/src/LibTIFF/mkg3states.c create mode 100644 plugins/FreeImage/src/LibTIFF/t4.h create mode 100644 plugins/FreeImage/src/LibTIFF/tif_acorn.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_apple.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_atari.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_aux.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_close.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_codec.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_color.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_compress.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_config.h create mode 100644 plugins/FreeImage/src/LibTIFF/tif_config.h-vms create mode 100644 plugins/FreeImage/src/LibTIFF/tif_config.h.in create mode 100644 plugins/FreeImage/src/LibTIFF/tif_config.vc.h create mode 100644 plugins/FreeImage/src/LibTIFF/tif_dir.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_dir.h create mode 100644 plugins/FreeImage/src/LibTIFF/tif_dirinfo.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_dirread.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_dirwrite.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_dumpmode.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_error.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_extension.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_fax3.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_fax3.h create mode 100644 plugins/FreeImage/src/LibTIFF/tif_fax3sm.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_flush.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_getimage.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_jbig.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_jpeg.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_luv.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_lzw.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_msdos.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_next.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_ojpeg.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_open.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_packbits.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_pixarlog.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_predict.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_predict.h create mode 100644 plugins/FreeImage/src/LibTIFF/tif_print.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_read.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_stream.cxx create mode 100644 plugins/FreeImage/src/LibTIFF/tif_strip.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_swab.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_thunder.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_tile.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_unix.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_version.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_vms.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_warning.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_win3.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_win32.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_write.c create mode 100644 plugins/FreeImage/src/LibTIFF/tif_zip.c create mode 100644 plugins/FreeImage/src/LibTIFF/tiff.h create mode 100644 plugins/FreeImage/src/LibTIFF/tiffconf.h-vms create mode 100644 plugins/FreeImage/src/LibTIFF/tiffconf.vc.h create mode 100644 plugins/FreeImage/src/LibTIFF/tiffio.h create mode 100644 plugins/FreeImage/src/LibTIFF/tiffio.hxx create mode 100644 plugins/FreeImage/src/LibTIFF/tiffiop.h create mode 100644 plugins/FreeImage/src/LibTIFF/tiffvers.h create mode 100644 plugins/FreeImage/src/LibTIFF/uvcode.h create mode 100644 plugins/FreeImage/src/Metadata/Exif.cpp create mode 100644 plugins/FreeImage/src/Metadata/FIRational.cpp create mode 100644 plugins/FreeImage/src/Metadata/FIRational.h create mode 100644 plugins/FreeImage/src/Metadata/FreeImageTag.cpp create mode 100644 plugins/FreeImage/src/Metadata/FreeImageTag.h create mode 100644 plugins/FreeImage/src/Metadata/IPTC.cpp create mode 100644 plugins/FreeImage/src/Metadata/TagConversion.cpp create mode 100644 plugins/FreeImage/src/Metadata/TagLib.cpp create mode 100644 plugins/FreeImage/src/Metadata/XTIFF.cpp create mode 100644 plugins/FreeImage/src/Plugin.h create mode 100644 plugins/FreeImage/src/Quantizers.h create mode 100644 plugins/FreeImage/src/ToneMapping.h create mode 100644 plugins/FreeImage/src/Utilities.h create mode 100644 plugins/FreeImage/src/Zlib/zconf.h create mode 100644 plugins/FreeImage/src/Zlib/zlib.h create mode 100644 plugins/FreeImage/src/Zlib/zutil.h create mode 100644 plugins/FreeImage/src/main.cpp create mode 100644 plugins/FreeImage/src/version.h delete mode 100644 plugins/FreeImage/version.rc diff --git a/plugins/FreeImage/Docs/freeimage-translation.txt b/plugins/FreeImage/Docs/freeimage-translation.txt new file mode 100644 index 0000000000..52329c17db --- /dev/null +++ b/plugins/FreeImage/Docs/freeimage-translation.txt @@ -0,0 +1,2 @@ +; Common strings that belong to many files +;[] diff --git a/plugins/FreeImage/FreeImage.rc b/plugins/FreeImage/FreeImage.rc deleted file mode 100644 index 9a5010d54c..0000000000 --- a/plugins/FreeImage/FreeImage.rc +++ /dev/null @@ -1,113 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Neutral resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) -#ifdef _WIN32 -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -#ifndef APSTUDIO_INVOKED - #include "version.rc" -#endif - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_OPENSUBCLASS, DIALOG - BEGIN - RIGHTMARGIN, 208 - TOPMARGIN, 7 - END - - IDD_AVATAROPTIONS, DIALOG - BEGIN - RIGHTMARGIN, 207 - BOTTOMMARGIN, 211 - END - - IDD_USER_AVATAR, DIALOG - BEGIN - LEFTMARGIN, 3 - RIGHTMARGIN, 218 - TOPMARGIN, 4 - BOTTOMMARGIN, 148 - END -END -#endif // APSTUDIO_INVOKED - -#endif // Neutral resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// German (Germany) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" -END - -#endif // APSTUDIO_INVOKED - -#endif // German (Germany) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/plugins/FreeImage/FreeImage_10.vcxproj b/plugins/FreeImage/FreeImage_10.vcxproj index f36dcdfc4d..27b52e0d07 100644 --- a/plugins/FreeImage/FreeImage_10.vcxproj +++ b/plugins/FreeImage/FreeImage_10.vcxproj @@ -74,7 +74,7 @@ Full OnlyExplicitInline Size - Source;Source\ZLib;..\..\include;%(AdditionalIncludeDirectories) + src;src\ZLib;..\..\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;FREEIMAGE_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true true @@ -102,7 +102,7 @@ Full OnlyExplicitInline Size - Source;Source\ZLib;..\..\include;%(AdditionalIncludeDirectories) + src;src\ZLib;..\..\include;%(AdditionalIncludeDirectories) WIN64;NDEBUG;_WINDOWS;_USRDLL;FREEIMAGE_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true true @@ -128,7 +128,7 @@ Disabled - Source;Source\ZLib;..\..\include;%(AdditionalIncludeDirectories) + src;src\ZLib;..\..\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;FREEIMAGE_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) false EnableFastChecks @@ -154,7 +154,7 @@ Disabled - Source;Source\ZLib;..\..\include;%(AdditionalIncludeDirectories) + src;src\ZLib;..\..\include;%(AdditionalIncludeDirectories) WIN64;_DEBUG;_WINDOWS;_USRDLL;FREEIMAGE_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) false EnableFastChecks @@ -185,170 +185,171 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/FreeImage/FreeImage_10.vcxproj.filters b/plugins/FreeImage/FreeImage_10.vcxproj.filters index 6176a320d8..af127af105 100644 --- a/plugins/FreeImage/FreeImage_10.vcxproj.filters +++ b/plugins/FreeImage/FreeImage_10.vcxproj.filters @@ -47,394 +47,394 @@ - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files - + Source Files\Plugins - + Source Files\Plugins - + Source Files\Plugins - + Source Files\Plugins - + Source Files\Plugins - + Source Files\Plugins - + Source Files\Plugins - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Quantizers - + Source Files\Quantizers - + Source Files\MultiPaging - + Source Files\MultiPaging - + Source Files\MultiPaging - + Source Files\Metadata - + Source Files\Metadata - + Source Files\Metadata - + Source Files\Metadata - + Source Files\Metadata - + Source Files\Metadata - + Source Files\Miranda - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Source Files\LibPNG\Source Files - + Toolkit Files - + Toolkit Files - + Toolkit Files - + Toolkit Files - + Toolkit Files - + Toolkit Files - + Toolkit Files - + Toolkit Files - + Toolkit Files - + Toolkit Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\LibJPEG\Source Files - + Source Files\Conversion - + Source Files\Conversion - + Source Files\Conversion @@ -442,93 +442,96 @@ Source Files + + Source Files + - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibPNG\Header Files - + Source Files\LibPNG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Source Files\LibJPEG\Header Files - + Toolkit Files - + Source Files\LibJPEG\Header Files - + Source Files\LibPNG\Header Files - + Source Files\LibPNG\Header Files - + Source Files\LibPNG\Header Files - + Source Files\LibPNG\Header Files diff --git a/plugins/FreeImage/Miranda/main.cpp b/plugins/FreeImage/Miranda/main.cpp deleted file mode 100644 index 370e743f94..0000000000 --- a/plugins/FreeImage/Miranda/main.cpp +++ /dev/null @@ -1,1260 +0,0 @@ -/* -Plugin of Miranda IM for reading/writing PNG images. -Copyright (c) 2004-6 George Hazan (ghazan@postman.ru) - -Portions of this code are gotten from the libpng codebase. -Copyright 2000, Willem van Schaik. For conditions of distribution and -use, see the copyright/license/disclaimer notice in png.h - -Miranda IM: the free icq client for MS Windows -Copyright (C) 2000-2002 Richard Hughes, Roland Rabien & Tristan Van de Vreede - -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. - -File name : $Source: /cvsroot/miranda/miranda/plugins/png2dib/png2dib.c,v $ -Revision : $Revision: 5041 $ -Last change on : $Date: 2007-03-06 22:13:28 +0100 (Di, 06 Mär 2007) $ -Last change by : $Author: rainwater $ - -*/ - -#include - -#include -#include - -#include -#include - -#include - -#include "newpluginapi.h" -#include "version.h" - -#include "../Source/libpng/png.h" - -static const PLUGININFOEX pluginInfoEx = { - sizeof(PLUGININFOEX), - __PLUGIN_NAME, - __VERSION_DWORD, - __DESCRIPTION, - __AUTHOR, - __AUTHOREMAIL, - __COPYRIGHT, - __AUTHORWEB, - UNICODE_AWARE, - // {7C070F7C-459E-46b7-8E6D-BC6EFAA22F78} - { 0x7c070f7c, 0x459e, 0x46b7, { 0x8e, 0x6d, 0xbc, 0x6e, 0xfa, 0xa2, 0x2f, 0x78 } } -}; - -/* -* freeimage helper functions -*/ - -// Correct alpha from bitmaps loaded without it (it cames with 0 and should be 255) -// originally in loadavatars... - -static void FI_CorrectBitmap32Alpha(HBITMAP hBitmap, BOOL force) -{ - BITMAP bmp; - DWORD dwLen; - BYTE *p; - int x, y; - BOOL fixIt; - - GetObject(hBitmap, sizeof(bmp), &bmp); - - if (bmp.bmBitsPixel != 32) - return; - - dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); - p = (BYTE *)malloc(dwLen); - if (p == NULL) - return; - memset(p, 0, dwLen); - - GetBitmapBits(hBitmap, dwLen, p); - - fixIt = TRUE; - for (y = 0; fixIt && y < bmp.bmHeight; ++y) { - BYTE *px = p + bmp.bmWidth * 4 * y; - - for (x = 0; fixIt && x < bmp.bmWidth; ++x) - { - if (px[3] != 0 && !force) - { - fixIt = FALSE; - } - else - { - px[3] = 255; - } - - px += 4; - } - } - - if (fixIt) - SetBitmapBits(hBitmap, dwLen, p); - - free(p); -} - -/* -* needed for per pixel transparent images. Such images should then be rendered by -* using AlphaBlend() with AC_SRC_ALPHA -* dwFlags will be set to AVS_PREMULTIPLIED -* return TRUE if the image has at least one pixel with transparency -*/ -static BOOL FreeImage_PreMultiply(HBITMAP hBitmap) -{ - BYTE *p = NULL; - DWORD dwLen; - int width, height, x, y; - BITMAP bmp; - BYTE alpha; - BOOL transp = FALSE; - - GetObject(hBitmap, sizeof(bmp), &bmp); - width = bmp.bmWidth; - height = bmp.bmHeight; - dwLen = width * height * 4; - p = (BYTE *)malloc(dwLen); - if (p != NULL) - { - GetBitmapBits(hBitmap, dwLen, p); - - for (y = 0; y < height; ++y) - { - BYTE *px = p + width * 4 * y; - - for (x = 0; x < width; ++x) - { - alpha = px[3]; - - if (alpha < 255) - { - transp = TRUE; - - px[0] = px[0] * alpha/255; - px[1] = px[1] * alpha/255; - px[2] = px[2] * alpha/255; - } - - px += 4; - } - } - - if (transp) - dwLen = SetBitmapBits(hBitmap, dwLen, p); - free(p); - } - - return transp; -} - -static HBITMAP FreeImage_CreateHBITMAPFromDIB(FIBITMAP *in) -{ - FIBITMAP *dib = NULL; - int bpp = FreeImage_GetBPP(in); - - if (bpp == 48) - dib = FreeImage_ConvertTo24Bits(in); - else if (FreeImage_GetBPP(in) > 32) - dib = FreeImage_ConvertTo32Bits(in); - else - dib = in; - - BYTE *ptPixels; - BITMAPINFO *info = FreeImage_GetInfo(dib); - HBITMAP hBmp = CreateDIBSection(NULL, info, DIB_RGB_COLORS, (void **)&ptPixels, NULL, 0); - if (ptPixels != NULL) - memmove(ptPixels, FreeImage_GetBits(dib), FreeImage_GetPitch(dib) * FreeImage_GetHeight(dib)); - - if (dib != in) - FreeImage_Unload(dib); - - return hBmp; -} - -static FIBITMAP *FreeImage_CreateDIBFromHBITMAP(HBITMAP hBmp) -{ - BITMAP bm; - - if(hBmp) { - GetObject(hBmp, sizeof(BITMAP), (LPSTR) &bm); - FIBITMAP *dib = FreeImage_Allocate(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel,0,0,0); - // 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); - HDC dc = GetDC(NULL); - int Success = GetDIBits(dc, hBmp, 0, FreeImage_GetHeight(dib), - FreeImage_GetBits(dib), FreeImage_GetInfo(dib), DIB_RGB_COLORS); - ReleaseDC(NULL, dc); - // restore BITMAPINFO members - FreeImage_GetInfoHeader(dib)->biClrUsed = nColors; - FreeImage_GetInfoHeader(dib)->biClrImportant = nColors; - return dib; - } - return NULL; -} - - -// Resize ///////////////////////////////////////////////////////////////////////////////////////// - - -// Returns a copy of the bitmap with the size especified -// !! the caller is responsible for destroying the original bitmap when it is no longer needed !! -// wParam = ResizeBitmap * -// lParam = NULL -// return NULL on error, ResizeBitmap->hBmp if don't need to resize or a new HBITMAP if resized - -static INT_PTR serviceBmpFilterResizeBitmap(WPARAM wParam,LPARAM lParam) -{ - BITMAP bminfo; - int width, height; - int xOrig, yOrig, widthOrig, heightOrig; - ResizeBitmap *info = (ResizeBitmap *) wParam; - - if (info == NULL || info->size != sizeof(ResizeBitmap) - || info->hBmp == NULL || info->max_width <= 0 - || info->max_height <= 0 - || (info->fit & ~RESIZEBITMAP_FLAG_DONT_GROW) < RESIZEBITMAP_STRETCH - || (info->fit & ~RESIZEBITMAP_FLAG_DONT_GROW) > RESIZEBITMAP_MAKE_SQUARE) - return 0; - - // Well, lets do it - - // Calc final size - GetObject(info->hBmp, sizeof(bminfo), &bminfo); - - width = info->max_width; - height = info->max_height; - - xOrig = 0; - yOrig = 0; - widthOrig = bminfo.bmWidth; - heightOrig = bminfo.bmHeight; - - if (widthOrig == 0 || heightOrig == 0) - return 0; - - switch(info->fit & ~RESIZEBITMAP_FLAG_DONT_GROW) - { - case RESIZEBITMAP_STRETCH: - { - // Do nothing - break; - } - case RESIZEBITMAP_KEEP_PROPORTIONS: - { - if (height * widthOrig / heightOrig <= width) - { - if (info->fit & RESIZEBITMAP_FLAG_DONT_GROW) - height = min(height, bminfo.bmHeight); - width = height * widthOrig / heightOrig; - } - else - { - if (info->fit & RESIZEBITMAP_FLAG_DONT_GROW) - width = min(width, bminfo.bmWidth); - height = width * heightOrig / widthOrig; - } - - break; - } - case RESIZEBITMAP_MAKE_SQUARE: - { - if (info->fit & RESIZEBITMAP_FLAG_DONT_GROW) - { - width = min(width, bminfo.bmWidth); - height = min(height, bminfo.bmHeight); - } - - width = height = min(width, height); - // Do not break. Use crop calcs to make size - } - case RESIZEBITMAP_CROP: - { - if (heightOrig * width / height >= widthOrig) - { - heightOrig = widthOrig * height / width; - yOrig = (bminfo.bmHeight - heightOrig) / 2; - } - else - { - widthOrig = heightOrig * width / height; - xOrig = (bminfo.bmWidth - widthOrig) / 2; - } - - break; - } - } - - if ((width == bminfo.bmWidth && height == bminfo.bmHeight) - || ((info->fit & RESIZEBITMAP_FLAG_DONT_GROW) - && !(info->fit & RESIZEBITMAP_MAKE_SQUARE) - && width > bminfo.bmWidth && height > bminfo.bmHeight)) - { - // Do nothing - return (int) info->hBmp; - } - else - { - FIBITMAP *dib = FreeImage_CreateDIBFromHBITMAP(info->hBmp); - if (dib == NULL) - return NULL; - - FIBITMAP *dib_tmp; - if (xOrig > 0 || yOrig > 0) - dib_tmp = FreeImage_Copy(dib, xOrig, yOrig, xOrig + widthOrig, yOrig + heightOrig); - else - dib_tmp = dib; - - if (dib_tmp == NULL) - { - FreeImage_Unload(dib); - return NULL; - } - - FIBITMAP *dib_new = FreeImage_Rescale(dib_tmp, width, height, FILTER_CATMULLROM); - - HBITMAP bitmap_new = FreeImage_CreateHBITMAPFromDIB(dib_new); - - if (dib_new != dib_tmp) - FreeImage_Unload(dib_new); - if (dib_tmp != dib) - FreeImage_Unload(dib_tmp); - FreeImage_Unload(dib); - - return (INT_PTR)bitmap_new; - } -} - - -FIBITMAP * -FreeImage_LoadFromMem(FREE_IMAGE_FORMAT fif, fiio_mem_handle *handle, int flags) { - //FreeImageIO io; - //SetMemIO(&io); - - if (handle && handle->data) { - FIMEMORY *hmem = FreeImage_OpenMemory((BYTE *)handle->data, handle->datalen); - FREE_IMAGE_FORMAT _fif = (fif != FIF_UNKNOWN) ? fif : FreeImage_GetFileTypeFromMemory(hmem, 0); - FIBITMAP *dib = FreeImage_LoadFromMemory(_fif, hmem, flags); - FreeImage_CloseMemory(hmem); - //handle->curpos = 0; - //return FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags); - } - - return NULL; -} - -FIMEMORY -*FreeImage_SaveToMem(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, fiio_mem_handle *handle, int flags) { - //FreeImageIO io; - //SetMemIO(&io); - - if (handle) { - FIMEMORY *hmem = FreeImage_OpenMemory(NULL, 0); - if(fif == FIF_UNKNOWN) - fif = FIF_BMP; - handle->curpos = 0; - FreeImage_SaveToMemory(fif, dib, hmem, flags); - FreeImage_AcquireMemory(hmem, (BYTE **)&handle->data, (DWORD *)&handle->datalen); - return hmem; - //handle->filelen = 0; - //handle->curpos = 0; - //return FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags); - } - return NULL; -} - -// ---------------------------------------------------------- - -/* -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 __stdcall fiio_mem_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) { - unsigned x; - for ( x=0; x= 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 __stdcall 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 __stdcall fiio_mem_TellProc(fi_handle handle) { - return FIIOMEM(curpos); -} - -*/ - -extern "C" DWORD __declspec(dllexport) getver( void ) -{ - return __VERSION_DWORD; -} - -// PNG image handler functions - -typedef struct { - char* mBuffer; - png_size_t mBufSize; - png_size_t mBufPtr; -} -HMemBufInfo; - -static void png_read_data( png_structp png_ptr, png_bytep data, png_size_t length ) -{ - HMemBufInfo* io = ( HMemBufInfo* )png_get_io_ptr(png_ptr); - if ( length + io->mBufPtr > io->mBufSize ) - length = io->mBufSize - io->mBufPtr; - - if ( length > 0 ) { - memcpy( data, io->mBuffer + io->mBufPtr, length ); - io->mBufPtr += length; - } - else png_error(png_ptr, "Read Error"); -} - -static void png_write_data( png_structp png_ptr, png_bytep data, png_size_t length ) -{ - HMemBufInfo* io = ( HMemBufInfo* )png_get_io_ptr(png_ptr); - if ( io->mBuffer != NULL ) - memcpy( io->mBuffer + io->mBufPtr, data, length ); - - io->mBufPtr += length; -} - -static void png_flush( png_structp png_ptr ) -{ -} - -/* -* Converting a *in memory* png image into a bitmap -*/ - -extern "C" BOOL __declspec(dllexport) mempng2dib(BYTE* pSource, DWORD cbSourceSize, BITMAPINFOHEADER** ppDibData ) -{ - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - HMemBufInfo sBuffer = { (char*)pSource, cbSourceSize, 8 }; - - BOOL bResult = FALSE; - png_uint_32 iWidth; - png_uint_32 iHeight; - png_color pBkgColor; - int iBitDepth; - int iColorType; - double dGamma; - png_color_16* pBackground; - png_byte ulChannels; - png_size_t ulRowBytes; - png_byte* pbImageData; - png_byte** ppbRowPointers = NULL; - int i; - png_uint_32 j; - int wDIRowBytes; - BYTE* pImageData; - - *ppDibData = NULL; - - if ( pSource == NULL || cbSourceSize == 0 ) - return FALSE; - - if ( !png_check_sig( pSource, 8 )) - return FALSE; - - // create the two png(-info) structures - png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); - if (!png_ptr) - return FALSE; - - info_ptr = png_create_info_struct(png_ptr); - if ( !info_ptr ) { - png_destroy_read_struct(&png_ptr, NULL, NULL); - return FALSE; - } - - // initialize the png structure - png_set_read_fn(png_ptr, (png_voidp)&sBuffer, png_read_data); - png_set_sig_bytes(png_ptr, 8); - - // read all PNG info up to image data - png_read_info(png_ptr, info_ptr); - - // get width, height, bit-depth and color-type - - png_get_IHDR(png_ptr, info_ptr, &iWidth, &iHeight, &iBitDepth, &iColorType, NULL, NULL, NULL); - - // expand images of all color-type and bit-depth to 3x8 bit RGB images - // let the library process things like alpha, transparency, background - - if ( iBitDepth == 16 ) - png_set_strip_16( png_ptr ); - if ( iColorType == PNG_COLOR_TYPE_PALETTE ) - png_set_expand( png_ptr ); - if ( iBitDepth < 8 ) - png_set_expand( png_ptr ); - if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS )) - png_set_expand( png_ptr ); - if ( iColorType == PNG_COLOR_TYPE_GRAY || iColorType == PNG_COLOR_TYPE_GRAY_ALPHA ) - png_set_gray_to_rgb( png_ptr ); - - // set the background color to draw transparent and alpha images over. - if (png_get_bKGD( png_ptr, info_ptr, &pBackground )) { - png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); - pBkgColor.red = (byte) pBackground->red; - pBkgColor.green = (byte) pBackground->green; - pBkgColor.blue = (byte) pBackground->blue; - } - - // if required set gamma conversion - if ( png_get_gAMA( png_ptr, info_ptr, &dGamma )) - png_set_gamma( png_ptr, (double) 2.2, dGamma ); - - // after the transformations have been registered update info_ptr data - png_read_update_info(png_ptr, info_ptr); - - // get again width, height and the new bit-depth and color-type - png_get_IHDR(png_ptr, info_ptr, &iWidth, &iHeight, &iBitDepth, &iColorType, NULL, NULL, NULL); - - // row_bytes is the width x number of channels - ulRowBytes = png_get_rowbytes(png_ptr, info_ptr); - ulChannels = png_get_channels(png_ptr, info_ptr); - wDIRowBytes = (WORD) (( ulChannels * iWidth + 3L) >> 2) << 2; - - // now we can allocate memory to store the image - { DWORD cbMemSize = sizeof( BITMAPINFOHEADER ); - cbMemSize += wDIRowBytes * iHeight; - if (( pbImageData = ( png_byte* )GlobalAlloc( LPTR, cbMemSize )) == NULL ) { - png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); - return FALSE; - } } - - // initialize the dib-structure - { BITMAPINFOHEADER* pbmih = ( BITMAPINFOHEADER* )pbImageData; - *ppDibData = pbmih; - - pbmih->biSize = sizeof( BITMAPINFOHEADER ); - pbmih->biWidth = iWidth; - pbmih->biHeight = iHeight; - pbmih->biPlanes = 1; - pbmih->biBitCount = ( WORD )( ulChannels * 8 ); - pbmih->biCompression = 0; - pbmih->biSizeImage = iWidth * iHeight * ulChannels; - - pbImageData += sizeof( BITMAPINFOHEADER ); - } - - pImageData = (BYTE*)malloc( ulRowBytes * iHeight ); - if ( pImageData == NULL ) { - png_destroy_read_struct(&png_ptr, NULL, NULL); - return FALSE; - } - - // and allocate memory for an array of row-pointers - ppbRowPointers = ( png_bytepp )alloca( iHeight * sizeof( png_bytep )); - - // set the individual row-pointers to point at the correct offsets - for ( j = 0; j < iHeight; j++ ) - ppbRowPointers[j] = ( png_bytep )&pImageData[ j*ulRowBytes ]; - - // now we can go ahead and just read the whole image - png_read_image( png_ptr, ppbRowPointers ); - png_read_end(png_ptr, NULL); - - // repack bytes to fill the bitmap - for ( i = iHeight-1; i >= 0; i-- ) - { - png_byte a; - png_bytep s = ppbRowPointers[i]; - BYTE* dest = pbImageData; pbImageData += wDIRowBytes; - - for ( j = 0; j < iWidth; j++ ) { - png_byte r = *s++; - png_byte g = *s++; - png_byte b = *s++; - if ( ulChannels == 4 ) - a = *s++; - - *dest++ = b; - *dest++ = g; - *dest++ = r; - if ( ulChannels == 4 ) - *dest++ = a; - } } - - free( pImageData ); - png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); - return TRUE; -} - -/* -* Converting a bitmap into a png image -*/ - -static BOOL sttCheckAlphaIsValid( BITMAPINFO* pbmi, png_byte* pDiData ) -{ - int ciChannels = pbmi->bmiHeader.biBitCount / 8, i, j; - int ulSrcRowBytes = ((( pbmi->bmiHeader.biWidth * ciChannels + 3 ) >> 2 ) << 2 ); - byte value = pDiData[ 3 ]; - - if ( ciChannels < 4 ) - return FALSE; - - if ( value != 0 && value != 0xFF ) - return TRUE; - - for ( i=0; i < pbmi->bmiHeader.biHeight; i++ ) { - png_byte* p = pDiData; pDiData += ulSrcRowBytes; - - for ( j=0; j < pbmi->bmiHeader.biWidth; j++, p += 4 ) - if ( p[3] != value ) - return TRUE; - } - - return FALSE; -} - -extern "C" BOOL __declspec(dllexport) dib2mempng( BITMAPINFO* pbmi, png_byte* pDiData, BYTE* pResult, long* pResultLen ) -{ - int ciBitDepth = 8; - int ciChannels = pbmi->bmiHeader.biBitCount / 8; - - png_uint_32 ulSrcRowBytes, ulDstRowBytes; - int i; - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - png_bytepp ppbRowPointers; - png_bytep pTempBuffer; - BOOL bIsAlphaValid; - - HMemBufInfo sBuffer = { (char *)pResult, 0, 0 }; - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); - if (!png_ptr) - return FALSE; - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr, (png_infopp) NULL); - return FALSE; - } - - // initialize the png structure - bIsAlphaValid = sttCheckAlphaIsValid( pbmi, pDiData ); - png_set_write_fn(png_ptr, (png_voidp)&sBuffer, png_write_data, png_flush); - - png_set_IHDR(png_ptr, info_ptr, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight, ciBitDepth, - ( bIsAlphaValid ) ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - // write the file header information - png_write_info(png_ptr, info_ptr); - - // swap the BGR pixels in the DiData structure to RGB - png_set_bgr(png_ptr); - - // row_bytes is the width x number of channels - ulSrcRowBytes = ((( pbmi->bmiHeader.biWidth * ciChannels + 3 ) >> 2 ) << 2 ); - ulDstRowBytes = ((( pbmi->bmiHeader.biWidth * ( ciChannels == 4 && bIsAlphaValid ? 4 : 3 ) + 3 ) >> 2 ) << 2 ); - - ppbRowPointers = (png_bytepp)alloca( pbmi->bmiHeader.biHeight * sizeof(png_bytep)); - - pTempBuffer = ( png_bytep )malloc( pbmi->bmiHeader.biHeight * ulDstRowBytes ); - if ( pTempBuffer != NULL ) { - png_bytep pDest = pTempBuffer; - for ( i = pbmi->bmiHeader.biHeight-1; i >= 0; i--) { - BYTE *s, *d; - int j; - s = pDiData; pDiData += ulSrcRowBytes; - d = ppbRowPointers[i] = pDest; pDest += ulDstRowBytes; - - if ( ciChannels >= 3 ) { - for ( j = 0; j < pbmi->bmiHeader.biWidth; j++ ) { - png_byte b = *s++; - png_byte g = *s++; - png_byte r = *s++; - png_byte a = 0; - - if ( ciChannels == 4 ) - a = *s++; - - *d++ = b; - *d++ = g; - *d++ = r; - if ( ciChannels == 4 && bIsAlphaValid ) - *d++ = a; - } } - else { - for ( j = 0; j < pbmi->bmiHeader.biWidth; j++ ) { - DWORD point; - if ( ciChannels == 1 ) { - *d++ = ( BYTE )( point & 0x03 ) << 6; - *d++ = ( BYTE )(( point & 0x0C ) >> 2 ) << 6; - *d++ = ( BYTE )(( point & 0x30 ) >> 4 ) << 6; - point = *s++; - } - else { - point = *( WORD* )s; - s += sizeof( WORD ); - *d++ = ( BYTE )(( point & 0x001F ) << 3 ); - *d++ = ( BYTE )((( point & 0x07e0 ) >> 6 ) << 3 ); - *d++ = ( BYTE )((( point & 0xF800 ) >> 11 ) << 3 ); - } } } } - - png_write_image (png_ptr, ppbRowPointers); - png_write_end(png_ptr, info_ptr); - - if ( pResultLen != NULL ) - *pResultLen = (long)sBuffer.mBufPtr; - - free( pTempBuffer ); - } - - png_destroy_write_struct(&png_ptr, &info_ptr ); - return TRUE; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// Standard Miranda structures & functions - -static HANDLE hDib2mempng = NULL; -static HANDLE hMempng2Dib = NULL; - -/////////////////////////////////////////////////////////////////////////////// -// Load - initializes the plugin instance - -static INT_PTR serviceDib2Png( WPARAM wParam, LPARAM lParam ) -{ - DIB2PNG* param = ( DIB2PNG* )lParam; - return dib2mempng( param->pbmi, param->pDiData, param->pResult, param->pResultLen ); -} - -static INT_PTR servicePng2Dib( WPARAM wParam, LPARAM lParam ) -{ - PNG2DIB* param = ( PNG2DIB* )lParam; - return mempng2dib( param->pSource, param->cbSourceSize, param->pResult ); -} - -FI_INTERFACE feif = {0}; - -/* -* caller MUST supply the desired version in wParam -* if it doesn't match, error will be returned -*/ - -static INT_PTR serviceGetInterface(WPARAM wParam, LPARAM lParam) -{ - FI_INTERFACE **ppfe = (FI_INTERFACE **)lParam; - - if ((DWORD)wParam != FI_IF_VERSION) - return CALLSERVICE_NOTFOUND; - - if(ppfe) { - *ppfe = &feif; - return S_OK; - } - else - return CALLSERVICE_NOTFOUND; -} - -static INT_PTR serviceLoad(WPARAM wParam, LPARAM lParam) -{ - char *lpszFilename = (char *)wParam; - if(lpszFilename==NULL) return 0; - FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; - - if(lParam & IMGL_WCHAR) - fif = FreeImage_GetFileTypeU((wchar_t *)lpszFilename, 0); - else - fif = FreeImage_GetFileType(lpszFilename, 0); - - if(fif == FIF_UNKNOWN) { - if(lParam & IMGL_WCHAR) - fif = FreeImage_GetFIFFromFilenameU((wchar_t *)lpszFilename); - else - fif = FreeImage_GetFIFFromFilename(lpszFilename); - } - // check that the plugin has reading capabilities ... - - if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { - // ok, let's load the file - FIBITMAP *dib; - - if(lParam & IMGL_WCHAR) - dib = FreeImage_LoadU(fif, (wchar_t *)lpszFilename, 0); - else - dib = FreeImage_Load(fif, lpszFilename, 0); - - if(dib == NULL || (lParam & IMGL_RETURNDIB)) - return (int)dib; - - HBITMAP hbm = FreeImage_CreateHBITMAPFromDIB(dib); - FreeImage_Unload(dib); - FI_CorrectBitmap32Alpha(hbm, FALSE); - return((INT_PTR)hbm); - } - return NULL; -} - -static INT_PTR serviceLoadFromMem(WPARAM wParam, LPARAM lParam) -{ - IMGSRVC_MEMIO *mio = (IMGSRVC_MEMIO *)wParam; - //fiio_mem_handle fiio; - - if(mio->iLen == 0 || mio->pBuf == NULL) - return 0; - - //fiio.curpos = 0; - //fiio.data = mio->pBuf; - //fiio.datalen = fiio.filelen = mio->iLen; - - FIMEMORY *hmem = FreeImage_OpenMemory((BYTE *)mio->pBuf, mio->iLen); - FREE_IMAGE_FORMAT fif = (mio->fif != FIF_UNKNOWN) ? mio->fif : mio->fif = FreeImage_GetFileTypeFromMemory(hmem, 0); - FIBITMAP *dib = FreeImage_LoadFromMemory(fif, hmem, mio->flags); - FreeImage_CloseMemory(hmem); - - //FIBITMAP *dib = FreeImage_LoadFromMem(mio->fif, &fiio, mio->flags); - - if(dib == NULL || (lParam & IMGL_RETURNDIB)) - return (INT_PTR)dib; - - HBITMAP hbm = FreeImage_CreateHBITMAPFromDIB(dib); - - FreeImage_Unload(dib); - return (INT_PTR)hbm; -} - -static INT_PTR serviceUnload(WPARAM wParam, LPARAM lParam) -{ - FIBITMAP *dib = (FIBITMAP *)wParam; - - if(dib) - FreeImage_Unload(dib); - - return 0; -} - -static INT_PTR serviceSave(WPARAM wParam, LPARAM lParam) -{ - IMGSRVC_INFO *isi = (IMGSRVC_INFO *)wParam; - FREE_IMAGE_FORMAT fif; - BOOL fUnload = FALSE; - FIBITMAP *dib = NULL; - - if(isi) { - if(isi->cbSize != sizeof(IMGSRVC_INFO)) - return 0; - - if(isi->szName || isi->wszName) { - if(isi->fif == FIF_UNKNOWN) { - if(lParam & IMGL_WCHAR) - fif = FreeImage_GetFIFFromFilenameU(isi->wszName); - else - fif = FreeImage_GetFIFFromFilename(isi->szName); - } - else - fif = isi->fif; - - if(fif == FIF_UNKNOWN) - fif = FIF_BMP; // default, save as bmp - - if(isi->hbm != 0 && (isi->dwMask & IMGI_HBITMAP) && !(isi->dwMask & IMGI_FBITMAP)) { - // create temporary dib, because we got a HBTIMAP passed - fUnload = TRUE; - FI_CorrectBitmap32Alpha(isi->hbm, FALSE); - dib = FreeImage_CreateDIBFromHBITMAP(isi->hbm); - } - else if(isi->dib != NULL && (isi->dwMask & IMGI_FBITMAP) && !(isi->dwMask & IMGI_HBITMAP)) - dib = isi->dib; - - int ret = 0; - if(dib) { - int flags = HIWORD(lParam); - - if(fif == FIF_PNG || fif == FIF_BMP || fif == FIF_JNG) - { - if(lParam & IMGL_WCHAR) - ret = FreeImage_SaveU(fif, dib, isi->wszName, flags); - else - ret = FreeImage_Save(fif, dib, isi->szName, flags); - } - else - { - FIBITMAP *dib_new = FreeImage_ConvertTo24Bits(dib); - if(lParam & IMGL_WCHAR) - ret = FreeImage_SaveU(fif, dib_new, isi->wszName, flags); - else - ret = FreeImage_Save(fif, dib_new, isi->szName, flags); - FreeImage_Unload(dib_new); - } - - if(fUnload) - FreeImage_Unload(dib); - return ret; - } - return 0; - } - - } - return 0; -} - -static INT_PTR serviceGetVersion(WPARAM wParam, LPARAM lParam) -{ - return FI_IF_VERSION; -} - -DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateClassic(FIBITMAP *dib, double angle) -{ - return FreeImage_Rotate(dib, angle, NULL); -} - -void FI_Populate(void) -{ - /* - * populate the interface - */ - - feif.version = FI_IF_VERSION; - - feif.FI__AllocateT = FreeImage_AllocateT; - feif.FI_Allocate = FreeImage_Allocate; - feif.FI_Clone = FreeImage_Clone; - feif.FI_Unload = FreeImage_Unload; - - feif.FI_Load = FreeImage_Load; - feif.FI_LoadFromHandle = FreeImage_LoadFromHandle; - feif.FI_LoadU = FreeImage_LoadU; - feif.FI_Save = FreeImage_Save; - feif.FI_SaveToHandle = FreeImage_SaveToHandle; - feif.FI_SaveU = FreeImage_SaveU; - - feif.FI_OpenMemory = FreeImage_OpenMemory; - feif.FI_CloseMemory = FreeImage_CloseMemory; - feif.FI_LoadFromMemory = FreeImage_LoadFromMemory; - feif.FI_SaveToMemory = FreeImage_SaveToMemory; - feif.FI_TellMemory = FreeImage_TellMemory; - feif.FI_SeekMemory = FreeImage_SeekMemory; - feif.FI_AcquireMemory = FreeImage_AcquireMemory; - feif.FI_ReadMemory = FreeImage_ReadMemory; - feif.FI_WriteMemory = FreeImage_WriteMemory; - feif.FI_LoadMultiBitmapFromMemory = FreeImage_LoadMultiBitmapFromMemory; - - feif.FI_OpenMultiBitmap = FreeImage_OpenMultiBitmap; - feif.FI_OpenMultiBitmapU = FreeImage_OpenMultiBitmapU; - feif.FI_CloseMultiBitmap = FreeImage_CloseMultiBitmap; - feif.FI_GetPageCount = FreeImage_GetPageCount; - feif.FI_AppendPage = FreeImage_AppendPage; - feif.FI_InsertPage = FreeImage_InsertPage; - feif.FI_DeletePage = FreeImage_DeletePage; - feif.FI_LockPage = FreeImage_LockPage; - feif.FI_UnlockPage = FreeImage_UnlockPage; - feif.FI_MovePage = FreeImage_MovePage; - feif.FI_GetLockedPageNumbers = FreeImage_GetLockedPageNumbers; - - feif.FI_GetFileType = FreeImage_GetFileType; - feif.FI_GetFileTypeU = FreeImage_GetFileTypeU; - feif.FI_GetFileTypeFromHandle = FreeImage_GetFileTypeFromHandle; - feif.FI_GetFileTypeFromMemory = FreeImage_GetFileTypeFromMemory; - feif.FI_GetImageType = FreeImage_GetImageType; - - feif.FI_GetBits = FreeImage_GetBits; - feif.FI_GetScanLine = FreeImage_GetScanLine; - feif.FI_GetPixelIndex = FreeImage_GetPixelIndex; - feif.FI_GetPixelColor = FreeImage_GetPixelColor; - feif.FI_SetPixelColor = FreeImage_SetPixelColor; - feif.FI_SetPixelIndex = FreeImage_SetPixelIndex; - - feif.FI_GetColorsUsed = FreeImage_GetColorsUsed; - feif.FI_GetBPP = FreeImage_GetBPP; - feif.FI_GetWidth = FreeImage_GetWidth; - feif.FI_GetHeight = FreeImage_GetHeight; - feif.FI_GetLine = FreeImage_GetLine; - feif.FI_GetPitch = FreeImage_GetPitch; - feif.FI_GetDIBSize = FreeImage_GetDIBSize; - feif.FI_GetPalette = FreeImage_GetPalette; - feif.FI_GetDotsPerMeterX = FreeImage_GetDotsPerMeterX; - feif.FI_GetDotsPerMeterY = FreeImage_GetDotsPerMeterY; - feif.FI_SetDotsPerMeterX = FreeImage_SetDotsPerMeterX; - feif.FI_SetDotsPerMeterY = FreeImage_SetDotsPerMeterY; - feif.FI_GetInfoHeader = FreeImage_GetInfoHeader; - feif.FI_GetInfo = FreeImage_GetInfo; - feif.FI_GetColorType = FreeImage_GetColorType; - feif.FI_GetRedMask = FreeImage_GetRedMask; - feif.FI_GetGreenMask = FreeImage_GetGreenMask; - feif.FI_GetBlueMask = FreeImage_GetBlueMask; - feif.FI_GetTransparencyCount = FreeImage_GetTransparencyCount; - feif.FI_GetTransparencyTable = FreeImage_GetTransparencyTable; - feif.FI_SetTransparent = FreeImage_SetTransparent; - feif.FI_SetTransparencyTable = FreeImage_SetTransparencyTable; - feif.FI_IsTransparent = FreeImage_IsTransparent; - feif.FI_HasBackgroundColor = FreeImage_HasBackgroundColor; - feif.FI_GetBackgroundColor = FreeImage_GetBackgroundColor; - feif.FI_SetBackgroundColor = FreeImage_SetBackgroundColor; - - feif.FI_ConvertTo4Bits = FreeImage_ConvertTo4Bits; - feif.FI_ConvertTo8Bits = FreeImage_ConvertTo8Bits; - feif.FI_ConvertToGreyscale = FreeImage_ConvertToGreyscale; - feif.FI_ConvertTo16Bits555 = FreeImage_ConvertTo16Bits555; - feif.FI_ConvertTo16Bits565 = FreeImage_ConvertTo16Bits565; - feif.FI_ConvertTo24Bits = FreeImage_ConvertTo24Bits; - feif.FI_ConvertTo32Bits = FreeImage_ConvertTo32Bits; - feif.FI_ColorQuantize = FreeImage_ColorQuantize; - feif.FI_ColorQuantizeEx = FreeImage_ColorQuantizeEx; - feif.FI_Threshold = FreeImage_Threshold; - feif.FI_Dither = FreeImage_Dither; - feif.FI_ConvertFromRawBits = FreeImage_ConvertFromRawBits; - feif.FI_ConvertToRawBits = FreeImage_ConvertToRawBits; - feif.FI_ConvertToRGBF = FreeImage_ConvertToRGBF; - feif.FI_ConvertToStandardType = FreeImage_ConvertToStandardType; - feif.FI_ConvertToType = FreeImage_ConvertToType; - - feif.FI_RegisterLocalPlugin = FreeImage_RegisterLocalPlugin; - feif.FI_RegisterExternalPlugin = FreeImage_RegisterExternalPlugin; - feif.FI_GetFIFCount = FreeImage_GetFIFCount; - feif.FI_SetPluginEnabled = FreeImage_SetPluginEnabled; - feif.FI_IsPluginEnabled = FreeImage_IsPluginEnabled; - feif.FI_GetFIFFromFormat = FreeImage_GetFIFFromFormat; - feif.FI_GetFIFFromMime = FreeImage_GetFIFFromMime; - feif.FI_GetFormatFromFIF = FreeImage_GetFormatFromFIF; - feif.FI_GetFIFExtensionList = FreeImage_GetFIFExtensionList; - feif.FI_GetFIFDescription = FreeImage_GetFIFDescription; - feif.FI_GetFIFRegExpr = FreeImage_GetFIFRegExpr; - feif.FI_GetFIFMimeType = FreeImage_GetFIFMimeType; - feif.FI_GetFIFFromFilename = FreeImage_GetFIFFromFilename; - feif.FI_GetFIFFromFilenameU = FreeImage_GetFIFFromFilenameU; - feif.FI_FIFSupportsReading = FreeImage_FIFSupportsReading; - feif.FI_FIFSupportsWriting = FreeImage_FIFSupportsWriting; - feif.FI_FIFSupportsExportBPP = FreeImage_FIFSupportsExportBPP; - feif.FI_FIFSupportsExportType = FreeImage_FIFSupportsExportType; - feif.FI_FIFSupportsICCProfiles = FreeImage_FIFSupportsICCProfiles; - - feif.FI_RotateClassic = FreeImage_RotateClassic; - feif.FI_RotateEx = FreeImage_RotateEx; - feif.FI_FlipHorizontal = FreeImage_FlipHorizontal; - feif.FI_FlipVertical = FreeImage_FlipVertical; - feif.FI_JPEGTransform = FreeImage_JPEGTransform; - - feif.FI_Rescale = FreeImage_Rescale; - feif.FI_MakeThumbnail = FreeImage_MakeThumbnail; - - feif.FI_AdjustCurve = FreeImage_AdjustCurve; - feif.FI_AdjustGamma = FreeImage_AdjustGamma; - feif.FI_AdjustBrightness = FreeImage_AdjustBrightness; - feif.FI_AdjustContrast = FreeImage_AdjustContrast; - feif.FI_Invert = FreeImage_Invert; - feif.FI_GetHistogram = FreeImage_GetHistogram; - - feif.FI_GetChannel = FreeImage_GetChannel; - feif.FI_SetChannel = FreeImage_SetChannel; - feif.FI_GetComplexChannel = FreeImage_GetComplexChannel; - feif.FI_SetComplexChannel = FreeImage_SetComplexChannel; - - feif.FI_Copy = FreeImage_Copy; - feif.FI_Paste = FreeImage_Paste; - feif.FI_Composite = FreeImage_Composite; - feif.FI_JPEGCrop = FreeImage_JPEGCrop; - - feif.FI_LoadFromMem = FreeImage_LoadFromMem; - feif.FI_SaveToMem = FreeImage_SaveToMem; - - feif.FI_CreateDIBFromHBITMAP = FreeImage_CreateDIBFromHBITMAP; - feif.FI_CreateHBITMAPFromDIB = FreeImage_CreateHBITMAPFromDIB; - - feif.FI_Premultiply = FreeImage_PreMultiply; - feif.FI_BmpFilterResizeBitmap = serviceBmpFilterResizeBitmap; - - feif.FI_IsLittleEndian = FreeImage_IsLittleEndian; - feif.FI_LookupX11Color = FreeImage_LookupX11Color; - feif.FI_LookupSVGColor = FreeImage_LookupSVGColor; - - feif.FI_GetICCProfile = FreeImage_GetICCProfile; - feif.FI_CreateICCProfile = FreeImage_CreateICCProfile; - feif.FI_DestroyICCProfile = FreeImage_DestroyICCProfile; - - feif.FI_ToneMapping = FreeImage_ToneMapping; - feif.FI_TmoDrago03 = FreeImage_TmoDrago03; - feif.FI_TmoReinhard05 = FreeImage_TmoReinhard05; - - feif.FI_ZLibCompress = FreeImage_ZLibCompress; - feif.FI_ZLibUncompress = FreeImage_ZLibUncompress; - feif.FI_ZLibGZip = FreeImage_ZLibGZip; - feif.FI_ZLibGUnzip = FreeImage_ZLibGUnzip; - feif.FI_ZLibCRC32 = FreeImage_ZLibCRC32; - - feif.FI_CreateTag = FreeImage_CreateTag; - feif.FI_DeleteTag = FreeImage_DeleteTag; - feif.FI_CloneTag = FreeImage_CloneTag; - - feif.FI_GetTagKey = FreeImage_GetTagKey; - feif.FI_GetTagDescription = FreeImage_GetTagDescription; - feif.FI_GetTagID = FreeImage_GetTagID; - feif.FI_GetTagType = FreeImage_GetTagType; - feif.FI_GetTagCount = FreeImage_GetTagCount; - feif.FI_GetTagLength = FreeImage_GetTagLength; - feif.FI_GetTagValue = FreeImage_GetTagValue; - - feif.FI_SetTagKey = FreeImage_SetTagKey; - feif.FI_SetTagDescription = FreeImage_SetTagDescription; - feif.FI_SetTagID = FreeImage_SetTagID; - feif.FI_SetTagType = FreeImage_SetTagType; - feif.FI_SetTagCount = FreeImage_SetTagCount; - feif.FI_SetTagLength = FreeImage_SetTagLength; - feif.FI_SetTagValue = FreeImage_SetTagValue; - - feif.FI_FindFirstMetadata = FreeImage_FindFirstMetadata; - feif.FI_FindNextMetadata = FreeImage_FindNextMetadata; - feif.FI_FindCloseMetadata = FreeImage_FindCloseMetadata; - feif.FI_SetMetadata = FreeImage_SetMetadata; - feif.FI_GetMetadata = FreeImage_GetMetadata; - - feif.FI_GetMetadataCount = FreeImage_GetMetadataCount; - feif.FI_TagToString = FreeImage_TagToString; - - feif.FI_CorrectBitmap32Alpha = FI_CorrectBitmap32Alpha; -} - -static HANDLE hGetIF, hLoad, hLoadFromMem, hSave, hUnload, hResize, hGetVersion; - -static int IMGSERVICE_Load() -{ - FI_Populate(); - - hDib2mempng = CreateServiceFunction( MS_DIB2PNG, serviceDib2Png ); - hMempng2Dib = CreateServiceFunction( MS_PNG2DIB, servicePng2Dib ); - hGetIF = CreateServiceFunction(MS_IMG_GETINTERFACE, serviceGetInterface); - hLoad = CreateServiceFunction(MS_IMG_LOAD, serviceLoad); - hLoadFromMem = CreateServiceFunction(MS_IMG_LOADFROMMEM, serviceLoadFromMem); - hSave = CreateServiceFunction(MS_IMG_SAVE, serviceSave); - hUnload = CreateServiceFunction(MS_IMG_UNLOAD, serviceUnload); - hResize = CreateServiceFunction(MS_IMG_RESIZE, serviceBmpFilterResizeBitmap); - hGetVersion = CreateServiceFunction(MS_IMG_GETIFVERSION, serviceGetVersion); - return 0; -} - -extern "C" int __declspec(dllexport) Load(void) -{ - return IMGSERVICE_Load(); -} - -/////////////////////////////////////////////////////////////////////////////// -// Unload - destroys the plugin instance - -static int IMGSERVICE_Unload( void ) -{ - DestroyServiceFunction( hDib2mempng ); - DestroyServiceFunction( hMempng2Dib ); - DestroyServiceFunction( hGetIF ); - DestroyServiceFunction( hLoad ); - DestroyServiceFunction( hLoadFromMem ); - DestroyServiceFunction( hSave ); - DestroyServiceFunction( hUnload ); - DestroyServiceFunction( hResize ); - DestroyServiceFunction( hGetVersion ); - return 0; -} - -extern "C" int __declspec(dllexport) Unload(void) -{ - return IMGSERVICE_Unload(); -} - -extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { { 0xece29554, 0x1cf0, 0x41da, { 0x85, 0x82, 0xfb, 0xe8, 0x45, 0x5c, 0x6b, 0xec } }, MIID_LAST}; - -extern "C" __declspec(dllexport) const PLUGININFOEX * MirandaPluginInfoEx(DWORD mirandaVersion) -{ - return &pluginInfoEx; -} diff --git a/plugins/FreeImage/Miranda/version.h b/plugins/FreeImage/Miranda/version.h deleted file mode 100644 index cb909c8a03..0000000000 --- a/plugins/FreeImage/Miranda/version.h +++ /dev/null @@ -1,12 +0,0 @@ -#define __FILEVERSION_STRING 0,11,0,1 -#define __VERSION_STRING "0.11.0.1" -#define __VERSION_DWORD PLUGIN_MAKE_VERSION(0, 11, 0, 1) - -#define __PLUGIN_NAME "Miranda Image services" -#define __INTERNAL_NAME "AdvaImg" -#define __FILENAME "AdvaImg.dll" -#define __DESCRIPTION "Generic image services for Miranda NG." -#define __AUTHOR "Nightwish, The FreeImage project (http://freeimage.sourceforge.net/)" -#define __AUTHOREMAIL "" -#define __AUTHORWEB "http://miranda-ng.org/" -#define __COPYRIGHT "© 2000-2012 Miranda-IM project, 2012 Miranda-NG project uses the FreeImage distribution" diff --git a/plugins/FreeImage/Source/CacheFile.h b/plugins/FreeImage/Source/CacheFile.h deleted file mode 100644 index a1e5e782c9..0000000000 --- a/plugins/FreeImage/Source/CacheFile.h +++ /dev/null @@ -1,92 +0,0 @@ -// ========================================================== -// 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 PageCache; - typedef std::list::iterator PageCacheIt; - typedef std::map PageMap; - typedef std::map::iterator PageMapIt; - -public : - CacheFile(const std::string 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 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/plugins/FreeImage/Source/DeprecationManager/Deprecated.cpp b/plugins/FreeImage/Source/DeprecationManager/Deprecated.cpp deleted file mode 100644 index 8ca5e71c5c..0000000000 --- a/plugins/FreeImage/Source/DeprecationManager/Deprecated.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// ========================================================== -// 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/plugins/FreeImage/Source/DeprecationManager/DeprecationMgr.cpp b/plugins/FreeImage/Source/DeprecationManager/DeprecationMgr.cpp deleted file mode 100644 index bf82dfa33b..0000000000 --- a/plugins/FreeImage/Source/DeprecationManager/DeprecationMgr.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// ========================================================== -// 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 -#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::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::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/plugins/FreeImage/Source/DeprecationManager/DeprecationMgr.h b/plugins/FreeImage/Source/DeprecationManager/DeprecationMgr.h deleted file mode 100644 index 9141f23a05..0000000000 --- a/plugins/FreeImage/Source/DeprecationManager/DeprecationMgr.h +++ /dev/null @@ -1,83 +0,0 @@ -// ========================================================== -// 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 called_from; - }; - - std::map 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/plugins/FreeImage/Source/FreeImage.h b/plugins/FreeImage/Source/FreeImage.h deleted file mode 100644 index a7090adf59..0000000000 --- a/plugins/FreeImage/Source/FreeImage.h +++ /dev/null @@ -1,1104 +0,0 @@ -// ========================================================== -// FreeImage 3 -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// -// Contributors: -// - see changes log named 'Whatsnew.txt', see header of each .h and .cpp file -// -// 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 15 -#define FREEIMAGE_RELEASE_SERIAL 3 - -// Compiler options --------------------------------------------------------- - -#include // 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 -typedef int32_t BOOL; -typedef uint8_t BYTE; -typedef uint16_t WORD; -typedef uint32_t DWORD; -typedef int32_t LONG; -typedef int64_t FIINT64; -typedef uint64_t FIUINT64; -#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; -typedef signed __int64 FIINT64; -typedef unsigned __int64 FIUINT64; -#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 - FIDT_LONG8 = 16, // 64-bit unsigned integer - FIDT_SLONG8 = 17, // 64-bit signed integer - FIDT_IFD8 = 18 // 64-bit unsigned integer (offset) -}; - -/** - 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 - FIMD_EXIF_RAW = 11 // Exif metadata as a raw buffer -}; - -/** - 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); -typedef BOOL (DLL_CALLCONV *FI_SupportsNoPixelsProc)(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; - FI_SupportsNoPixelsProc supports_no_pixels_proc; -}; - -typedef void (DLL_CALLCONV *FI_InitProc)(Plugin *plugin, int format_id); - -#endif // PLUGINS - - -// Load / Save flag constants ----------------------------------------------- - -#define FIF_LOAD_NOPIXELS 0x8000 // loading: load the image header only (not supported by all plugins) - -#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 JPEG_OPTIMIZE 0x20000 // on saving, compute optimal Huffman coding tables (can reduce a few percent of file size) -#define JPEG_BASELINE 0x40000 // save basic JPEG, without metadata or any markers -#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 PSD_CMYK 1 // reads tags for separated CMYK (default is conversion to RGB) -#define PSD_LAB 2 // reads tags for CIELab (default is conversion to RGB) -#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 RAW_HALFSIZE 4 // output a half-size color image -#define SGI_DEFAULT 0 -#define TARGA_DEFAULT 0 -#define TARGA_LOAD_RGB888 1 // If set the loader converts RGB555 and ARGB8888 -> RGB888. -#define TARGA_SAVE_RLE 2 // If set, the writer saves with RLE compression -#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 TIFF_LOGLUV 0x10000 // save using LogLuv 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); - -// Header loading routines -DLL_API BOOL DLL_CALLCONV FreeImage_HasPixels(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)); -DLL_API BOOL DLL_CALLCONV FreeImage_SaveMultiBitmapToMemory(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, FIMEMORY *stream, int flags); - -// 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); -DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsNoPixels(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_OpenMultiBitmapU(FREE_IMAGE_FORMAT fif, const wchar_t *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_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, 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); - -DLL_API FIBITMAP *DLL_CALLCONV FreeImage_GetThumbnail(FIBITMAP *dib); -DLL_API BOOL DLL_CALLCONV FreeImage_SetThumbnail(FIBITMAP *dib, FIBITMAP *thumbnail); - -// 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_ConvertToFloat(FIBITMAP *dib); -DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToRGBF(FIBITMAP *dib); -DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToUINT16(FIBITMAP *dib); -DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToRGB16(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 *dst, FIBITMAP *src, 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/plugins/FreeImage/Source/FreeImage/BitmapAccess.cpp b/plugins/FreeImage/Source/FreeImage/BitmapAccess.cpp deleted file mode 100644 index 584870f359..0000000000 --- a/plugins/FreeImage/Source/FreeImage/BitmapAccess.cpp +++ /dev/null @@ -1,1210 +0,0 @@ -// ========================================================== -// 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) -// - 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! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -#include -#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__) -#include -#endif // _WIN32 || _WIN64 || __MINGW32__ - -#include "FreeImage.h" -#include "FreeImageIO.h" -#include "Utilities.h" - -#include "../Metadata/FreeImageTag.h" - -// ---------------------------------------------------------- -// Metadata definitions -// ---------------------------------------------------------- - -// helper for map where value is a pointer to a FreeImage tag -typedef std::map TAGMAP; - -// helper for map -typedef std::map 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 - - BOOL has_pixels; // FALSE if the FIBITMAP only contains the header and no pixel data - - FIBITMAP *thumbnail; // optionally contains a thumbnail 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__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) - -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. - -@param header_only If TRUE, calculate a 'header only' FIBITMAP size, otherwise calculate a full FIBITMAP size -@param width -@param height -@param bpp -@see FreeImage_AllocateHeaderT -*/ -static size_t -FreeImage_GetImageSizeHeader(BOOL header_only, unsigned width, unsigned height, unsigned bpp) { - size_t 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); - if (!header_only) { - const size_t header_size = dib_size; - - // pixels are aligned on a 16 bytes boundary - dib_size += (size_t)CalculatePitch(CalculateLine(width, bpp)) * (size_t)height; - - // check for possible malloc overflow using a KISS integer overflow detection mechanism - { - /* - The following constant take into account the additionnal memory used by - aligned malloc functions as well as debug malloc functions. - It is supposed here that using a (8 * FIBITMAP_ALIGNMENT) risk margin will be enough - for the target compiler. - */ - const double FIBITMAP_MAX_MEMORY = (double)((size_t)-1) - 8 * FIBITMAP_ALIGNMENT; - const double dPitch = floor( ((double)bpp * width + 31.0) / 32.0 ) * 4.0; - const double dImageSize = (double)header_size + dPitch * height; - if(dImageSize != (double)dib_size) { - // here, we are sure to encounter a malloc overflow: try to avoid it ... - return 0; - } - if(dImageSize > FIBITMAP_MAX_MEMORY) { - // avoid possible overflow inside C allocation functions - return 0; - } - } - } - - return dib_size; -} - -FIBITMAP * DLL_CALLCONV -FreeImage_AllocateHeaderT(BOOL header_only, 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) { - width = abs(width); - 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(DWORD); - 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 - - size_t dib_size = FreeImage_GetImageSizeHeader(header_only, width, height, bpp); - - if(dib_size == 0) { - // memory allocation will fail (probably a malloc overflow) - free(bitmap); - return NULL; - } - - 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); - - fih->has_pixels = header_only ? FALSE : TRUE; - - // initialize FIICCPROFILE link - - FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap); - iccProfile->size = 0; - iccProfile->data = 0; - iccProfile->flags = 0; - - // initialize metadata models list - - fih->metadata = new(std::nothrow) METADATAMAP; - - // initialize attached thumbnail - - fih->thumbnail = NULL; - - // 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 - - if(bpp == 8) { - // build a default greyscale palette (very useful for image processing) - RGBQUAD *pal = FreeImage_GetPalette(bitmap); - for(int i = 0; i < 256; i++) { - pal[i].rgbRed = (BYTE)i; - pal[i].rgbGreen = (BYTE)i; - pal[i].rgbBlue = (BYTE)i; - } - } - - return bitmap; - } - - free(bitmap); - } - - return NULL; -} - -FIBITMAP * DLL_CALLCONV -FreeImage_AllocateHeader(BOOL header_only, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { - return FreeImage_AllocateHeaderT(header_only, FIT_BITMAP, width, height, bpp, red_mask, green_mask, blue_mask); -} - -FIBITMAP * DLL_CALLCONV -FreeImage_Allocate(int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { - return FreeImage_AllocateHeaderT(FALSE, 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) { - return FreeImage_AllocateHeaderT(FALSE, type, width, height, bpp, red_mask, green_mask, blue_mask); -} - -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 embedded thumbnail - FreeImage_Unload(FreeImage_GetThumbnail(dib)); - - // 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); - - // check for pixel availability ... - BOOL header_only = FreeImage_HasPixels(dib) ? FALSE : TRUE; - - // allocate a new dib - FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, 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 - - size_t dib_size = FreeImage_GetImageSizeHeader(header_only, 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; - - // reset thumbnail link for new_dib - ((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL; - - // 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(std::nothrow) TAGMAP(); - - if(dst_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; - } - } - } - - // copy the thumbnail - FreeImage_SetThumbnail(new_dib, FreeImage_GetThumbnail(dib)); - - return new_dib; - } - - return NULL; -} - -// ---------------------------------------------------------- - -FIBITMAP* DLL_CALLCONV -FreeImage_GetThumbnail(FIBITMAP *dib) { - return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->thumbnail : NULL; -} - -BOOL DLL_CALLCONV -FreeImage_SetThumbnail(FIBITMAP *dib, FIBITMAP *thumbnail) { - if(dib == NULL) { - return FALSE; - } - FIBITMAP *currentThumbnail = ((FREEIMAGEHEADER *)dib->data)->thumbnail; - if(currentThumbnail == thumbnail) { - return TRUE; - } - FreeImage_Unload(currentThumbnail); - - ((FREEIMAGEHEADER *)dib->data)->thumbnail = FreeImage_HasPixels(thumbnail) ? FreeImage_Clone(thumbnail) : NULL; - - return TRUE; -} - -// ---------------------------------------------------------- - -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; -} - -// ---------------------------------------------------------- - -BOOL DLL_CALLCONV -FreeImage_HasPixels(FIBITMAP *dib) { - return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->has_pixels : FALSE; -} - -// ---------------------------------------------------------- - -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) { - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - switch(image_type) { - case FIT_BITMAP: - if(FreeImage_GetBPP(dib) == 32) { - if(FreeImage_GetColorType(dib) == FIC_RGBALPHA) { - return TRUE; - } - } else { - return ((FREEIMAGEHEADER *)dib->data)->transparent ? TRUE : FALSE; - } - break; - case FIT_RGBA16: - case FIT_RGBAF: - return TRUE; - default: - break; - } - } - 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) { - count = MIN(count, 256); - 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(std::nothrow) TAGMAP(); - - if(dst_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; - } - } - } - - // clone resolution - FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src)); - FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src)); - - 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(std::nothrow) 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(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/plugins/FreeImage/Source/FreeImage/CacheFile.cpp b/plugins/FreeImage/Source/FreeImage/CacheFile.cpp deleted file mode 100644 index 309faf8faf..0000000000 --- a/plugins/FreeImage/Source/FreeImage/CacheFile.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// ========================================================== -// 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 std::string filename, BOOL keep_in_memory) : -m_file(NULL), -m_filename(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) { -} - -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/plugins/FreeImage/Source/FreeImage/ColorLookup.cpp b/plugins/FreeImage/Source/FreeImage/ColorLookup.cpp deleted file mode 100644 index 3e81abdb95..0000000000 --- a/plugins/FreeImage/Source/FreeImage/ColorLookup.cpp +++ /dev/null @@ -1,782 +0,0 @@ -// ========================================================== -// 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 { - const 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, or gray, 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, or gray, 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/plugins/FreeImage/Source/FreeImage/Conversion.cpp b/plugins/FreeImage/Source/FreeImage/Conversion.cpp deleted file mode 100644 index 3c14bab9dd..0000000000 --- a/plugins/FreeImage/Source/FreeImage/Conversion.cpp +++ /dev/null @@ -1,513 +0,0 @@ -// ========================================================== -// Bitmap conversion routines -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Jani Kajala (janik@remedy.fi) -// - 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 "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; - -// ========================================================== -// Utility functions declared in Utilities.h - -BOOL SwapRedBlue32(FIBITMAP* dib) { - if(FreeImage_GetImageType(dib) != FIT_BITMAP) { - return FALSE; - } - - const unsigned bytesperpixel = FreeImage_GetBPP(dib) / 8; - if(bytesperpixel > 4 || bytesperpixel < 3) { - return FALSE; - } - - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pitch = FreeImage_GetPitch(dib); - const unsigned lineSize = FreeImage_GetLine(dib); - - BYTE* line = FreeImage_GetBits(dib); - for(unsigned y = 0; y < height; ++y, line += pitch) { - for(BYTE* pixel = line; pixel < line + lineSize ; pixel += bytesperpixel) { - INPLACESWAP(pixel[0], pixel[2]); - } - } - - return TRUE; -} - -// ---------------------------------------------------------- - -static inline void -assignRGB(WORD r, WORD g, WORD b, WORD* out) { - out[0] = r; - out[1] = g; - out[2] = b; -} - -static inline void -assignRGB(BYTE r, BYTE g, BYTE b, BYTE* out) { - out[FI_RGBA_RED] = r; - out[FI_RGBA_GREEN] = g; - out[FI_RGBA_BLUE] = b; -} - -/** -CMYK -> CMY -> RGB conversion from http://www.easyrgb.com/ - -CMYK to CMY [0-1]: C,M,Y * (1 - K) + K -CMY to RGB [0-1]: (1 - C,M,Y) - -=> R,G,B = (1 - C,M,Y) * (1 - K) -mapped to [0-MAX_VAL]: -(MAX_VAL - C,M,Y) * (MAX_VAL - K) / MAX_VAL -*/ -template -static inline void -CMYKToRGB(T C, T M, T Y, T K, T* out) { - unsigned max_val = std::numeric_limits::max(); - - unsigned r = (max_val - C) * (max_val - K) / max_val; - unsigned g = (max_val - M) * (max_val - K) / max_val; - unsigned b = (max_val - Y) * (max_val - K) / max_val; - - // clamp values to [0..max_val] - T red = (T)CLAMP(r, (unsigned)0, max_val); - T green = (T)CLAMP(g, (unsigned)0, max_val); - T blue = (T)CLAMP(b, (unsigned)0, max_val); - - assignRGB(red, green, blue, out); -} - -template -static void -_convertCMYKtoRGBA(unsigned width, unsigned height, BYTE* line_start, unsigned pitch, unsigned samplesperpixel) { - const BOOL hasBlack = (samplesperpixel > 3) ? TRUE : FALSE; - const T MAX_VAL = std::numeric_limits::max(); - - T K = 0; - for(unsigned y = 0; y < height; y++) { - T *line = (T*)line_start; - - for(unsigned x = 0; x < width; x++) { - if(hasBlack) { - K = line[FI_RGBA_ALPHA]; - line[FI_RGBA_ALPHA] = MAX_VAL; // TODO write the first extra channel as alpha! - } - - CMYKToRGB(line[0], line[1], line[2], K, line); - - line += samplesperpixel; - } - line_start += pitch; - } -} - -BOOL -ConvertCMYKtoRGBA(FIBITMAP* dib) { - if (!FreeImage_HasPixels(dib)) { - return FALSE; - } - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - const unsigned bytesperpixel = FreeImage_GetBPP(dib)/8; - - unsigned channelSize = 1; - if (image_type == FIT_RGBA16 || image_type == FIT_RGB16) { - channelSize = sizeof(WORD); - } else if (!(image_type == FIT_BITMAP && (bytesperpixel > 2))) { - return FALSE; - } - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - BYTE *line_start = FreeImage_GetScanLine(dib, 0); - const unsigned pitch = FreeImage_GetPitch(dib); - - unsigned samplesperpixel = FreeImage_GetLine(dib) / width / channelSize; - - if(channelSize == sizeof(WORD)) { - _convertCMYKtoRGBA(width, height, line_start, pitch, samplesperpixel); - } else { - _convertCMYKtoRGBA(width, height, line_start, pitch, samplesperpixel); - } - - return TRUE; -} - -// ---------------------------------------------------------- - -/** -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; -} - -template -static void -CIELabToRGB(float L, float a, float b, T *rgb) { - float X, Y, Z; - float R, G, B; - const float max_val = std::numeric_limits::max(); - - CIELabToXYZ(L, a, b, &X, &Y, &Z); - XYZToRGB(X, Y, Z, &R, &G, &B); - - // clamp values to [0..max_val] - T red = (T)CLAMP(R * max_val, 0.0F, max_val); - T green = (T)CLAMP(G * max_val, 0.0F, max_val); - T blue = (T)CLAMP(B * max_val, 0.0F, max_val); - - assignRGB(red, green, blue, rgb); -} - -template -static void -_convertLABtoRGB(unsigned width, unsigned height, BYTE* line_start, unsigned pitch, unsigned samplesperpixel) { - const unsigned max_val = std::numeric_limits::max(); - const float sL = 100.F / max_val; - const float sa = 256.F / max_val; - const float sb = 256.F / max_val; - - for(unsigned y = 0; y < height; y++) { - T *line = (T*)line_start; - - for(unsigned x = 0; x < width; x++) { - CIELabToRGB(line[0]* sL, line[1]* sa - 128.F, line[2]* sb - 128.F, line); - - line += samplesperpixel; - } - line_start += pitch; - } -} - -BOOL -ConvertLABtoRGB(FIBITMAP* dib) { - if (!FreeImage_HasPixels(dib)) { - return FALSE; - } - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - const unsigned bytesperpixel = FreeImage_GetBPP(dib) / 8; - - unsigned channelSize = 1; - if (image_type == FIT_RGBA16 || image_type == FIT_RGB16) { - channelSize = sizeof(WORD); - } else if (!(image_type == FIT_BITMAP && (bytesperpixel > 2))) { - return FALSE; - } - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - BYTE *line_start = FreeImage_GetScanLine(dib, 0); - const unsigned pitch = FreeImage_GetPitch(dib); - - unsigned samplesperpixel = FreeImage_GetLine(dib) / width / channelSize; - - if(channelSize == 1) { - _convertLABtoRGB(width, height, line_start, pitch, samplesperpixel); - } - else { - _convertLABtoRGB(width, height, line_start, pitch, samplesperpixel); - } - - return TRUE; -} - -// ---------------------------------------------------------- - -FIBITMAP* -RemoveAlphaChannel(FIBITMAP* src) { - - if (!FreeImage_HasPixels(src)) { - return NULL; - } - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - switch(image_type) { - case FIT_BITMAP: - if(FreeImage_GetBPP(src) == 32) { - // convert to 24-bit - return FreeImage_ConvertTo24Bits(src); - } - break; - case FIT_RGBA16: - // convert to RGB16 - return FreeImage_ConvertToRGB16(src); - case FIT_RGBAF: - // convert to RGBF - return FreeImage_ConvertToRGBF(src); - default: - // unsupported image type - return NULL; - } - - return NULL; -} - - -// ========================================================== - -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 (FreeImage_HasPixels(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 (FreeImage_HasPixels(dib) && (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/plugins/FreeImage/Source/FreeImage/Conversion16_555.cpp b/plugins/FreeImage/Source/FreeImage/Conversion16_555.cpp deleted file mode 100644 index c0c4785704..0000000000 --- a/plugins/FreeImage/Source/FreeImage/Conversion16_555.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImage/Conversion16_565.cpp b/plugins/FreeImage/Source/FreeImage/Conversion16_565.cpp deleted file mode 100644 index 28e8255b4e..0000000000 --- a/plugins/FreeImage/Source/FreeImage/Conversion16_565.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImage/Conversion24.cpp b/plugins/FreeImage/Source/FreeImage/Conversion24.cpp deleted file mode 100644 index f04b946ef0..0000000000 --- a/plugins/FreeImage/Source/FreeImage/Conversion24.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImage/Conversion32.cpp b/plugins/FreeImage/Source/FreeImage/Conversion32.cpp deleted file mode 100644 index fad74671cd..0000000000 --- a/plugins/FreeImage/Source/FreeImage/Conversion32.cpp +++ /dev/null @@ -1,345 +0,0 @@ -// ========================================================== -// 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; - } -} - -// ---------------------------------------------------------- - -inline void -FreeImage_ConvertLine1To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { - 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] = (index < transparent_pixels) ? table[index] : 255; - target += 4; - } -} - -inline void -FreeImage_ConvertLine4To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { - 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; - target[FI_RGBA_ALPHA] = (LOWNIBBLE(source[x]) < transparent_pixels) ? table[LOWNIBBLE(source[x])] : 255; - - 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; - target[FI_RGBA_ALPHA] = (HINIBBLE(source[x] >> 4) < transparent_pixels) ? table[HINIBBLE(source[x]) >> 4] : 255; - } - - low_nibble = !low_nibble; - - target += 4; - } -} - -inline void -FreeImage_ConvertLine8To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { - 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] = (source[cols] < transparent_pixels) ? table[source[cols]] : 255; - target += 4; - } -} - -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertTo32Bits(FIBITMAP *dib) { - if (!FreeImage_HasPixels(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); - - BOOL bIsTransparent = FreeImage_IsTransparent(dib); - - switch(bpp) { - case 1: - { - if(bIsTransparent) { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine1To32MapTransparency(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - } - } else { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine1To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - } - - return new_dib; - } - - case 4: - { - if(bIsTransparent) { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine4To32MapTransparency(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - } - } else { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine4To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); - } - } - - return new_dib; - } - - case 8: - { - if(bIsTransparent) { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine8To32MapTransparency(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - } - } else { - for (int rows = 0; rows < height; rows++) { - FreeImage_ConvertLine8To32(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_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/plugins/FreeImage/Source/FreeImage/Conversion4.cpp b/plugins/FreeImage/Source/FreeImage/Conversion4.cpp deleted file mode 100644 index 7c09ac824a..0000000000 --- a/plugins/FreeImage/Source/FreeImage/Conversion4.cpp +++ /dev/null @@ -1,246 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImage/Conversion8.cpp b/plugins/FreeImage/Source/FreeImage/Conversion8.cpp deleted file mode 100644 index 867cf756ed..0000000000 --- a/plugins/FreeImage/Source/FreeImage/Conversion8.cpp +++ /dev/null @@ -1,327 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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)) * sizeof(BYTE)); - 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/plugins/FreeImage/Source/FreeImage/ConversionFloat.cpp b/plugins/FreeImage/Source/FreeImage/ConversionFloat.cpp deleted file mode 100644 index 181ff396e1..0000000000 --- a/plugins/FreeImage/Source/FreeImage/ConversionFloat.cpp +++ /dev/null @@ -1,192 +0,0 @@ -// ========================================================== -// 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 Float -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToFloat(FIBITMAP *dib) { - FIBITMAP *src = NULL; - FIBITMAP *dst = NULL; - - if (!FreeImage_HasPixels(dib)) return NULL; - - FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - - // check for allowed conversions - switch(src_type) { - case FIT_BITMAP: - { - // allow conversion from 8-bit - if ((FreeImage_GetBPP(dib) == 8) && (FreeImage_GetColorType(dib) == FIC_MINISBLACK)) { - src = dib; - } else { - src = FreeImage_ConvertToGreyscale(dib); - if (!src) return NULL; - } - break; - } - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - case FIT_RGBF: - case FIT_RGBAF: - src = dib; - break; - case FIT_FLOAT: - // float type : clone the src - return FreeImage_Clone(dib); - default: - return NULL; - } - - // allocate dst image - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - dst = FreeImage_AllocateT(FIT_FLOAT, width, height); - if (!dst) { - if(src != dib) { - FreeImage_Unload(src); - } - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // convert from src type to float - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - switch(src_type) { - case FIT_BITMAP: - { - for(unsigned y = 0; y < height; y++) { - const BYTE *src_pixel = (BYTE*)src_bits; - float *dst_pixel = (float*)dst_bits; - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x] = (float)(src_pixel[x]) / 255; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_UINT16: - { - for(unsigned y = 0; y < height; y++) { - const WORD *src_pixel = (WORD*)src_bits; - float *dst_pixel = (float*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x] = (float)(src_pixel[x]) / 65535; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGB16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGB16 *src_pixel = (FIRGB16*)src_bits; - float *dst_pixel = (float*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue) / 65535.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBA16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGBA16 *src_pixel = (FIRGBA16*)src_bits; - float *dst_pixel = (float*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue) / 65535.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBF: - { - 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++) { - // convert (assume pixel values are in the range [0..1]) - dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue); - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_RGBAF: - { - for(unsigned y = 0; y < height; y++) { - const FIRGBAF *src_pixel = (FIRGBAF*)src_bits; - float *dst_pixel = (float*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert (assume pixel values are in the range [0..1]) - dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue); - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - } - - if(src != dib) { - FreeImage_Unload(src); - } - - return dst; -} - diff --git a/plugins/FreeImage/Source/FreeImage/ConversionRGB16.cpp b/plugins/FreeImage/Source/FreeImage/ConversionRGB16.cpp deleted file mode 100644 index 6b9d17fbed..0000000000 --- a/plugins/FreeImage/Source/FreeImage/ConversionRGB16.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// ========================================================== -// 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 RGB16 -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToRGB16(FIBITMAP *dib) { - FIBITMAP *src = NULL; - FIBITMAP *dst = NULL; - - if (!FreeImage_HasPixels(dib)) return NULL; - - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - - // check for allowed conversions - switch(src_type) { - case FIT_BITMAP: - { - // convert to 24-bit if needed - if ((FreeImage_GetBPP(dib) == 24) || (FreeImage_GetBPP(dib) == 32)) { - src = dib; - } else { - src = FreeImage_ConvertTo24Bits(dib); - if (!src) return NULL; - } - break; - } - case FIT_UINT16: - // allow conversion from unsigned 16-bit - src = dib; - break; - case FIT_RGB16: - // RGB16 type : clone the src - return FreeImage_Clone(dib); - break; - case FIT_RGBA16: - // allow conversion from 64-bit RGBA (ignore the alpha channel) - src = dib; - break; - default: - return NULL; - } - - // allocate dst image - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - dst = FreeImage_AllocateT(FIT_RGB16, width, height); - if (!dst) { - if(src != dib) { - FreeImage_Unload(src); - } - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // convert from src type to RGB16 - - switch(src_type) { - case FIT_BITMAP: - { - // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(unsigned y = 0; y < height; y++) { - const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y); - FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - dst_bits[x].red = src_bits[FI_RGBA_RED] << 8; - dst_bits[x].green = src_bits[FI_RGBA_GREEN] << 8; - dst_bits[x].blue = src_bits[FI_RGBA_BLUE] << 8; - src_bits += bytespp; - } - } - } - break; - - case FIT_UINT16: - { - for(unsigned y = 0; y < height; y++) { - const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y); - FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert by copying greyscale channel to each R, G, B channels - dst_bits[x].red = src_bits[x]; - dst_bits[x].green = src_bits[x]; - dst_bits[x].blue = src_bits[x]; - } - } - } - break; - - case FIT_RGBA16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGBA16 *src_bits = (FIRGBA16*)FreeImage_GetScanLine(src, y); - FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert and skip alpha channel - dst_bits[x].red = src_bits[x].red; - dst_bits[x].green = src_bits[x].green; - dst_bits[x].blue = src_bits[x].blue; - } - } - } - break; - - default: - break; - } - - if(src != dib) { - FreeImage_Unload(src); - } - - return dst; -} - diff --git a/plugins/FreeImage/Source/FreeImage/ConversionRGBF.cpp b/plugins/FreeImage/Source/FreeImage/ConversionRGBF.cpp deleted file mode 100644 index 6b8739532f..0000000000 --- a/plugins/FreeImage/Source/FreeImage/ConversionRGBF.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// ========================================================== -// 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; - - if (!FreeImage_HasPixels(dib)) return 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_UINT16: - // allow conversion from 16-bit - src = dib; - break; - case FIT_RGB16: - // allow conversion from 48-bit RGB - src = dib; - break; - case FIT_RGBA16: - // allow conversion from 64-bit RGBA (ignore the alpha channel) - src = dib; - break; - case FIT_FLOAT: - // allow conversion from 32-bit float - src = dib; - break; - case FIT_RGBAF: - // allow conversion from 128-bit RGBAF - 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) { - if(src != dib) { - FreeImage_Unload(src); - } - 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.0F; - dst_pixel->green = (float)(src_pixel[FI_RGBA_GREEN]) / 255.0F; - dst_pixel->blue = (float)(src_pixel[FI_RGBA_BLUE]) / 255.0F; - - src_pixel += bytespp; - dst_pixel ++; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_UINT16: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const WORD *src_pixel = (WORD*)src_bits; - FIRGBF *dst_pixel = (FIRGBF*)dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert and scale to the range [0..1] - const float dst_value = (float)src_pixel[x] / 65535.0F; - dst_pixel[x].red = dst_value; - dst_pixel[x].green = dst_value; - dst_pixel[x].blue = dst_value; - } - 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.0F; - dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; - dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; - } - 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.0F; - dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; - dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; - } - src_bits += src_pitch; - dst_bits += dst_pitch; - } - } - break; - - case FIT_FLOAT: - { - const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); - BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); - - for(unsigned y = 0; y < height; y++) { - const float *src_pixel = (float*) src_bits; - FIRGBF *dst_pixel = (FIRGBF*) dst_bits; - - for(unsigned x = 0; x < width; x++) { - // convert by copying greyscale channel to each R, G, B channels - dst_pixel[x].red = src_pixel[x]; - dst_pixel[x].green = src_pixel[x]; - dst_pixel[x].blue = src_pixel[x]; - } - 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/plugins/FreeImage/Source/FreeImage/ConversionType.cpp b/plugins/FreeImage/Source/FreeImage/ConversionType.cpp deleted file mode 100644 index 23528b60fe..0000000000 --- a/plugins/FreeImage/Source/FreeImage/ConversionType.cpp +++ /dev/null @@ -1,689 +0,0 @@ -// ========================================================== -// 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 CONVERT_TYPE -{ -public: - FIBITMAP* convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type); -}; - -template FIBITMAP* -CONVERT_TYPE::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(FreeImage_GetScanLine(src, y)); - Tdst *dst_bits = reinterpret_cast(FreeImage_GetScanLine(dst, y)); - - for(unsigned x = 0; x < width; x++) { - *dst_bits++ = static_cast(*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 CONVERT_TO_BYTE -{ -public: - FIBITMAP* convert(FIBITMAP *src, BOOL scale_linear); -}; - -template FIBITMAP* -CONVERT_TO_BYTE::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(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(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(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 CONVERT_TO_COMPLEX -{ -public: - FIBITMAP* convert(FIBITMAP *src); -}; - -template FIBITMAP* -CONVERT_TO_COMPLEX::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(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 convertByteToUShort; -CONVERT_TYPE convertByteToShort; -CONVERT_TYPE convertByteToULong; -CONVERT_TYPE convertByteToLong; -CONVERT_TYPE convertByteToFloat; -CONVERT_TYPE convertByteToDouble; - -// Convert from type X to type BYTE -CONVERT_TO_BYTE convertUShortToByte; -CONVERT_TO_BYTE convertShortToByte; -CONVERT_TO_BYTE convertULongToByte; -CONVERT_TO_BYTE convertLongToByte; -CONVERT_TO_BYTE convertFloatToByte; -CONVERT_TO_BYTE convertDoubleToByte; - -// Convert from type X to type float -CONVERT_TYPE convertUShortToFloat; -CONVERT_TYPE convertShortToFloat; -CONVERT_TYPE convertULongToFloat; -CONVERT_TYPE convertLongToFloat; - -// Convert from type X to type double -CONVERT_TYPE convertUShortToDouble; -CONVERT_TYPE convertShortToDouble; -CONVERT_TYPE convertULongToDouble; -CONVERT_TYPE convertLongToDouble; -CONVERT_TYPE convertFloatToDouble; - -// Convert from type X to type FICOMPLEX -CONVERT_TO_COMPLEX convertByteToComplex; -CONVERT_TO_COMPLEX convertUShortToComplex; -CONVERT_TO_COMPLEX convertShortToComplex; -CONVERT_TO_COMPLEX convertULongToComplex; -CONVERT_TO_COMPLEX convertLongToComplex; -CONVERT_TO_COMPLEX convertFloatToComplex; -CONVERT_TO_COMPLEX 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 (!FreeImage_HasPixels(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); - } - - const unsigned src_bpp = FreeImage_GetBPP(src); - - switch(src_type) { - case FIT_BITMAP: - switch(dst_type) { - case FIT_UINT16: - dst = FreeImage_ConvertToUINT16(src); - break; - case FIT_INT16: - dst = (src_bpp == 8) ? convertByteToShort.convert(src, dst_type) : NULL; - break; - case FIT_UINT32: - dst = (src_bpp == 8) ? convertByteToULong.convert(src, dst_type) : NULL; - break; - case FIT_INT32: - dst = (src_bpp == 8) ? convertByteToLong.convert(src, dst_type) : NULL; - break; - case FIT_FLOAT: - dst = FreeImage_ConvertToFloat(src); - break; - case FIT_DOUBLE: - dst = (src_bpp == 8) ? convertByteToDouble.convert(src, dst_type) : NULL; - break; - case FIT_COMPLEX: - dst = (src_bpp == 8) ? convertByteToComplex.convert(src) : NULL; - break; - case FIT_RGB16: - dst = FreeImage_ConvertToRGB16(src); - 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 = FreeImage_ConvertToFloat(src); - break; - case FIT_DOUBLE: - dst = convertUShortToDouble.convert(src, dst_type); - break; - case FIT_COMPLEX: - dst = convertUShortToComplex.convert(src); - break; - case FIT_RGB16: - dst = FreeImage_ConvertToRGB16(src); - break; - case FIT_RGBA16: - break; - case FIT_RGBF: - dst = FreeImage_ConvertToRGBF(src); - 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: - dst = FreeImage_ConvertToRGBF(src); - 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: - dst = FreeImage_ConvertToUINT16(src); - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - dst = FreeImage_ConvertToFloat(src); - 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: - dst = FreeImage_ConvertToUINT16(src); - break; - case FIT_INT16: - break; - case FIT_UINT32: - break; - case FIT_INT32: - break; - case FIT_FLOAT: - dst = FreeImage_ConvertToFloat(src); - break; - case FIT_DOUBLE: - break; - case FIT_COMPLEX: - break; - case FIT_RGB16: - dst = FreeImage_ConvertToRGB16(src); - 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: - dst = FreeImage_ConvertToFloat(src); - 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: - dst = FreeImage_ConvertToFloat(src); - 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/plugins/FreeImage/Source/FreeImage/ConversionUINT16.cpp b/plugins/FreeImage/Source/FreeImage/ConversionUINT16.cpp deleted file mode 100644 index 3744cfe3b4..0000000000 --- a/plugins/FreeImage/Source/FreeImage/ConversionUINT16.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// ========================================================== -// 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 UINT16 -// ---------------------------------------------------------- - -FIBITMAP * DLL_CALLCONV -FreeImage_ConvertToUINT16(FIBITMAP *dib) { - FIBITMAP *src = NULL; - FIBITMAP *dst = NULL; - - if (!FreeImage_HasPixels(dib)) return NULL; - - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); - - // check for allowed conversions - switch(src_type) { - case FIT_BITMAP: - { - // convert to greyscale if needed - if ((FreeImage_GetBPP(dib) == 8) && (FreeImage_GetColorType(dib) == FIC_MINISBLACK)) { - src = dib; - } else { - src = FreeImage_ConvertToGreyscale(dib); - if (!src) return NULL; - } - break; - } - case FIT_UINT16: - // UINT16 type : clone the src - return FreeImage_Clone(dib); - break; - case FIT_RGB16: - // allow conversion from 48-bit RGB - src = dib; - break; - case FIT_RGBA16: - // allow conversion from 64-bit RGBA (ignore the alpha channel) - src = dib; - break; - default: - return NULL; - } - - // allocate dst image - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - dst = FreeImage_AllocateT(FIT_UINT16, width, height); - if (!dst) { - if(src != dib) { - FreeImage_Unload(src); - } - return NULL; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // convert from src type to UINT16 - - switch(src_type) { - case FIT_BITMAP: - { - for(unsigned y = 0; y < height; y++) { - const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y); - WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - dst_bits[x] = src_bits[x] << 8; - } - } - } - break; - - case FIT_RGB16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGB16 *src_bits = (FIRGB16*)FreeImage_GetScanLine(src, y); - WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert to grey - dst_bits[x] = (WORD)LUMA_REC709(src_bits[x].red, src_bits[x].green, src_bits[x].blue); - } - } - } - break; - - case FIT_RGBA16: - { - for(unsigned y = 0; y < height; y++) { - const FIRGBA16 *src_bits = (FIRGBA16*)FreeImage_GetScanLine(src, y); - WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - // convert to grey - dst_bits[x] = (WORD)LUMA_REC709(src_bits[x].red, src_bits[x].green, src_bits[x].blue); - } - } - } - break; - - default: - break; - } - - if(src != dib) { - FreeImage_Unload(src); - } - - return dst; -} - diff --git a/plugins/FreeImage/Source/FreeImage/FreeImage.cpp b/plugins/FreeImage/Source/FreeImage/FreeImage.cpp deleted file mode 100644 index b36f10aca1..0000000000 --- a/plugins/FreeImage/Source/FreeImage/FreeImage.cpp +++ /dev/null @@ -1,226 +0,0 @@ -// ========================================================== -// 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 -#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 { - DWORD i; - BYTE 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/plugins/FreeImage/Source/FreeImage/FreeImageC.c b/plugins/FreeImage/Source/FreeImage/FreeImageC.c deleted file mode 100644 index 9e8125955f..0000000000 --- a/plugins/FreeImage/Source/FreeImage/FreeImageC.c +++ /dev/null @@ -1,22 +0,0 @@ -// ========================================================== -// 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/plugins/FreeImage/Source/FreeImage/FreeImageIO.cpp b/plugins/FreeImage/Source/FreeImage/FreeImageIO.cpp deleted file mode 100644 index b289530be7..0000000000 --- a/plugins/FreeImage/Source/FreeImage/FreeImageIO.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// ========================================================== -// 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" - -// ===================================================================== -// File IO functions -// ===================================================================== - -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/plugins/FreeImage/Source/FreeImage/GetType.cpp b/plugins/FreeImage/Source/FreeImage/GetType.cpp deleted file mode 100644 index 76edc7f3f9..0000000000 --- a/plugins/FreeImage/Source/FreeImage/GetType.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// ========================================================== -// 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/plugins/FreeImage/Source/FreeImage/Halftoning.cpp b/plugins/FreeImage/Source/FreeImage/Halftoning.cpp deleted file mode 100644 index 1542fc9268..0000000000 --- a/plugins/FreeImage/Source/FreeImage/Halftoning.cpp +++ /dev/null @@ -1,474 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImage/J2KHelper.cpp b/plugins/FreeImage/Source/FreeImage/J2KHelper.cpp deleted file mode 100644 index 44b210aca0..0000000000 --- a/plugins/FreeImage/Source/FreeImage/J2KHelper.cpp +++ /dev/null @@ -1,500 +0,0 @@ -// ========================================================== -// 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: - if(FreeImage_GetBPP(dib) == 32) { - // 32-bit image with a fully opaque layer - numcomps = 4; - color_space = CLRSPC_SRGB; - } else { - // 24-bit image - 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/plugins/FreeImage/Source/FreeImage/MemoryIO.cpp b/plugins/FreeImage/Source/FreeImage/MemoryIO.cpp deleted file mode 100644 index 6ae3fb2e11..0000000000 --- a/plugins/FreeImage/Source/FreeImage/MemoryIO.cpp +++ /dev/null @@ -1,237 +0,0 @@ -// ========================================================== -// Memory Input/Output functions -// -// Design and implementation by -// - Ryan Rubley -// - 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) { - if(stream && stream->data) { - 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/plugins/FreeImage/Source/FreeImage/MultiPage.cpp b/plugins/FreeImage/Source/FreeImage/MultiPage.cpp deleted file mode 100644 index e5bcee3ded..0000000000 --- a/plugins/FreeImage/Source/FreeImage/MultiPage.cpp +++ /dev/null @@ -1,990 +0,0 @@ -// ========================================================== -// 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) -// - Volodymyr Goncharov (volodymyr.goncharov@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! -// ========================================================== - -#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) { - } - virtual ~BlockTypeS() {} -}; - -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 BlockList; -typedef std::list::iterator BlockListIterator; - -// ---------------------------------------------------------- - -FI_STRUCT (MULTIBITMAPHEADER) { - PluginNode *node; - FREE_IMAGE_FORMAT fif; - FreeImageIO *io; - fi_handle handle; - CacheFile *m_cachefile; - std::map locked_pages; - BOOL changed; - int page_count; - BlockList m_blocks; - char *m_filename; - BOOL read_only; - FREE_IMAGE_FORMAT cache_fif; - int load_flags; -}; - -// ===================================================================== -// Helper functions -// ===================================================================== - -inline void -ReplaceExtension(std::string& dst_filename, const std::string& src_filename, const std::string& dst_extension) { - size_t lastDot = src_filename.find_last_of('.'); - if (lastDot == std::string::npos) { - dst_filename = src_filename; - dst_filename += "."; - dst_filename += dst_extension; - } - else { - dst_filename = src_filename.substr(0, lastDot + 1); - dst_filename += dst_extension; - } -} - -// ===================================================================== -// 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_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory, int flags) { - - FILE *handle = NULL; - try { - // 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) { - std::auto_ptr io (new FreeImageIO); - - SetDefaultIO(io.get()); - - if (!create_new) { - handle = fopen(filename, "rb"); - if (handle == NULL) { - return NULL; - } - } - - std::auto_ptr bitmap (new FIMULTIBITMAP); - std::auto_ptr 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.get (); - header->handle = handle; - header->changed = FALSE; - header->read_only = read_only; - header->m_cachefile = NULL; - header->cache_fif = fif; - header->load_flags = flags; - - // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure - - bitmap->data = header.get(); - - // cache the page count - - header->page_count = FreeImage_InternalGetPageCount(bitmap.get()); - - // 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) { - std::string cache_name; - ReplaceExtension(cache_name, filename, "ficache"); - - std::auto_ptr cache_file (new CacheFile(cache_name, keep_cache_in_memory)); - - if (cache_file->open()) { - // we can use release() as std::bad_alloc won't be thrown from here on - header->m_cachefile = cache_file.release(); - } else { - // an error occured ... - fclose(handle); - return NULL; - } - } - // return the multibitmap - // std::bad_alloc won't be thrown from here on - header.release(); // now owned by bitmap - io.release(); // now owned by bitmap - return bitmap.release(); // now owned by caller - } - } - } catch (std::bad_alloc &) { - /** @todo report error */ - } - if (handle) - fclose(handle); - return NULL; -} - -FIMULTIBITMAP * DLL_CALLCONV -FreeImage_OpenMultiBitmapU(FREE_IMAGE_FORMAT fif, const wchar_t *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory, int flags) { - - // convert to single character - no national chars in extensions - char *extension = (char *)malloc(wcslen(filename)+1); - unsigned int i=0; - for (; i < wcslen(filename); i++) // convert 16-bit to 8-bit - extension[i] = (char)(filename[i] & 0x00FF); - // set terminating 0 - extension[i]=0; - FIMULTIBITMAP *fRet = FreeImage_OpenMultiBitmap(fif, extension, create_new, read_only, keep_cache_in_memory, flags); - free(extension); - - return fRet; -} - -FIMULTIBITMAP * DLL_CALLCONV -FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags) { - try { - BOOL read_only = FALSE; // modifications (if any) will be stored into the memory cache - - 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) { - std::auto_ptr bitmap (new FIMULTIBITMAP); - std::auto_ptr header (new MULTIBITMAPHEADER); - std::auto_ptr tmp_io (new FreeImageIO (*io)); - header->io = tmp_io.get(); - header->m_filename = NULL; - header->node = node; - header->fif = fif; - header->handle = handle; - header->changed = FALSE; - header->read_only = read_only; - header->m_cachefile = NULL; - header->cache_fif = fif; - header->load_flags = flags; - - // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure - - bitmap->data = header.get(); - - // cache the page count - - header->page_count = FreeImage_InternalGetPageCount(bitmap.get()); - - // allocate a continueus block to describe the bitmap - - header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1)); - - if (!read_only) { - // set up the cache - std::auto_ptr cache_file (new CacheFile("", TRUE)); - - if (cache_file->open()) { - header->m_cachefile = cache_file.release(); - } - } - tmp_io.release(); - header.release(); - return bitmap.release(); - } - } - } - } catch (std::bad_alloc &) { - /** @todo report error */ - } - return NULL; -} - -BOOL DLL_CALLCONV -FreeImage_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, FreeImageIO *io, fi_handle handle, int flags) { - if (!bitmap || !bitmap->data || !io || !handle) { - return FALSE; - } - - BOOL success = TRUE; - - // 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) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - // dst data - void *data = FreeImage_Open(node, io, handle, FALSE); - // src data - void *data_read = NULL; - - if(header->handle) { - // open src - 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 file using handle and io - - 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++) { - - // load the original source data - FIBITMAP *dib = header->node->m_plugin->load_proc(header->io, header->handle, j, header->load_flags, data_read); - - // save the data - success = node->m_plugin->save_proc(io, dib, handle, 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 = node->m_plugin->save_proc(io, dib, handle, count, flags, data); - count++; - - // unload the dib - - FreeImage_Unload(dib); - - break; - } - } - } else { - break; - } - } - - // close the files - - FreeImage_Close(header->node, header->io, header->handle, data_read); - - FreeImage_Close(node, io, handle, data); - - return success; - } - } - - return FALSE; -} - - -BOOL DLL_CALLCONV -FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) { - if (bitmap) { - BOOL success = TRUE; - - if (bitmap->data) { - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - // saves changes only of images loaded directly from a file - if (header->changed && header->m_filename) { - try { - // open a temp file - - std::string spool_name; - - ReplaceExtension(spool_name, header->m_filename, "fispool"); - - // open the spool file and the source file - - FILE *f = fopen(spool_name.c_str(), "w+b"); - - // saves changes - if (f == NULL) { - FreeImage_OutputMessageProc(header->fif, "Failed to open %s, %s", spool_name.c_str(), strerror(errno)); - success = FALSE; - } else { - success = FreeImage_SaveMultiBitmapToHandle(header->fif, bitmap, header->io, (fi_handle)f, flags); - - // close the files - - if (fclose(f) != 0) { - success = FALSE; - FreeImage_OutputMessageProc(header->fif, "Failed to close %s, %s", spool_name.c_str(), strerror(errno)); - } - } - if (header->handle) { - fclose((FILE *)header->handle); - } - - // applies changes to the destination file - - if (success) { - remove(header->m_filename); - success = (rename(spool_name.c_str(), header->m_filename) == 0) ? TRUE:FALSE; - if (!success) { - FreeImage_OutputMessageProc(header->fif, "Failed to rename %s to %s", spool_name.c_str(), header->m_filename); - } - } else { - remove(spool_name.c_str()); - } - } catch (std::bad_alloc &) { - success = FALSE; - } - - } 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; -} - -static BlockReference* -FreeImage_SavePageToBlock(MULTIBITMAPHEADER *header, FIBITMAP *data) { - if (header->read_only || !header->locked_pages.empty()) - return NULL; - - DWORD compressed_size = 0; - BYTE *compressed_data = NULL; - - // compress the bitmap data - - // open a memory handle - FIMEMORY *hmem = FreeImage_OpenMemory(); - if(hmem==NULL) return NULL; - // save the file to memory - if (!FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0)) { - FreeImage_CloseMemory(hmem); - return NULL; - } - // get the buffer from the memory stream - if (!FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size)) { - FreeImage_CloseMemory(hmem); - return NULL; - } - - // write the compressed data to the cache - int ref = header->m_cachefile->writeFile(compressed_data, compressed_size); - // get rid of the compressed data - FreeImage_CloseMemory(hmem); - - return new(std::nothrow) BlockReference(ref, compressed_size); -} - -void DLL_CALLCONV -FreeImage_AppendPage(FIMULTIBITMAP *bitmap, FIBITMAP *data) { - if (!bitmap || !data) - return; - - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - BlockReference *block = FreeImage_SavePageToBlock(header, data); - if(block==NULL) return; - - // 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) - return; - - if (page >= FreeImage_GetPageCount(bitmap)) - return; - - MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); - - BlockReference *block = FreeImage_SavePageToBlock(header, data); - if(block==NULL) return; - - // add a block - if (page > 0) { - BlockListIterator block_source = FreeImage_FindBlock(bitmap, page); - - header->m_blocks.insert(block_source, (BlockTypeS *)block); - } else { - header->m_blocks.push_front((BlockTypeS *)block); - } - - 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 : - delete *i; - header->m_blocks.erase(i); - break; - - case BLOCK_REFERENCE : - header->m_cachefile->deleteFile(((BlockReference *)(*i))->m_reference); - delete *i; - 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::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::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; -} - -// ===================================================================== -// Memory IO Multipage functions -// ===================================================================== - -FIMULTIBITMAP * DLL_CALLCONV -FreeImage_LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags) { - BOOL read_only = FALSE; // modifications (if any) will be stored into the memory cache - - // 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(std::nothrow) FreeImageIO; - - if (io) { - SetMemoryIO(io); - - FIMULTIBITMAP *bitmap = new(std::nothrow) FIMULTIBITMAP; - - if (bitmap) { - MULTIBITMAPHEADER *header = new(std::nothrow) MULTIBITMAPHEADER; - - if (header) { - header->m_filename = NULL; - header->node = node; - header->fif = fif; - header->io = io; - header->handle = (fi_handle)stream; - header->changed = FALSE; - header->read_only = read_only; - 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)); - - if (!read_only) { - // set up the cache - CacheFile *cache_file = new(std::nothrow) CacheFile("", TRUE); - - if (cache_file && cache_file->open()) { - header->m_cachefile = cache_file; - } - } - - return bitmap; - } - - delete bitmap; - } - - delete io; - } - } - } - - return NULL; -} - -BOOL DLL_CALLCONV -FreeImage_SaveMultiBitmapToMemory(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, FIMEMORY *stream, int flags) { - if (stream && stream->data) { - FreeImageIO io; - SetMemoryIO(&io); - - return FreeImage_SaveMultiBitmapToHandle(fif, bitmap, &io, (fi_handle)stream, flags); - } - - return FALSE; -} diff --git a/plugins/FreeImage/Source/FreeImage/NNQuantizer.cpp b/plugins/FreeImage/Source/FreeImage/NNQuantizer.cpp deleted file mode 100644 index 6eb9aeaf48..0000000000 --- a/plugins/FreeImage/Source/FreeImage/NNQuantizer.cpp +++ /dev/null @@ -1,507 +0,0 @@ -// 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/plugins/FreeImage/Source/FreeImage/PSDParser.cpp b/plugins/FreeImage/Source/FreeImage/PSDParser.cpp deleted file mode 100644 index 93573d01c0..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PSDParser.cpp +++ /dev/null @@ -1,1053 +0,0 @@ -// ========================================================== -// Photoshop Loader -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// 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 PSDP_BITMAP 0 -#define PSDP_GRAYSCALE 1 -#define PSDP_INDEXED 2 -#define PSDP_RGB 3 -#define PSDP_CMYK 4 -#define PSDP_MULTICHANNEL 7 -#define PSDP_DUOTONE 8 -#define PSDP_LAB 9 - -// PSD compression schemes -#define PSDP_COMPRESSION_NONE 0 // Raw data -#define PSDP_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; iread_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 - BYTE psd_reserved[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - if(memcmp(header.Reserved, psd_reserved, 6) != 0) { - FreeImage_OutputMessageProc(FIF_PSD, "Warning: file header reserved member is not equal to zero"); - } - // 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) ); - _BitsPerChannel = (short)psdGetValue( header.Depth, sizeof(header.Depth) ); - _ColourMode = (short)psdGetValue( header.Mode, sizeof(header.Mode) ); - - return true; - } - } - - return false; -} - -// -------------------------------------------------------------------------- - -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) ); - if ((_Opacity < 0) || (_Opacity > 100)) { - throw "Invalid DisplayInfo::Opacity value"; - } - - 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)); - if(_padding != 0) { - throw "Invalid DisplayInfo::Padding value"; - } - - return nBytes; -} - -// -------------------------------------------------------------------------- - -psdThumbnail::psdThumbnail() : -_Format(-1), _Width(-1), _Height(-1), _WidthBytes(-1), _Size(-1), _CompressedSize(-1), _BitPerPixel(-1), _Planes(-1), _dib(NULL) { -} - -psdThumbnail::~psdThumbnail() { - FreeImage_Unload(_dib); -} - -int psdThumbnail::Read(FreeImageIO *io, fi_handle handle, int iResourceSize, bool isBGR) { - BYTE ShortValue[2], IntValue[4]; - int nBytes=0, n; - - // remove the header size (28 bytes) from the total data size - int iTotalData = iResourceSize - 28; - - const long block_end = io->tell_proc(handle) + iTotalData; - - 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) ); - - const long JFIF_startpos = io->tell_proc(handle); - - if(_dib) { - FreeImage_Unload(_dib); - } - - if(_Format == 1) { - // kJpegRGB thumbnail image - _dib = FreeImage_LoadFromHandle(FIF_JPEG, io, handle); - if(isBGR) { - SwapRedBlue32(_dib); - } - // HACK: manually go to end of thumbnail, because (for some reason) LoadFromHandle consumes more bytes then available! - io->seek_proc(handle, block_end, SEEK_SET); - } - else { - // kRawRGB thumbnail image - // ### Unimplemented (should be trivial) - - // skip the thumbnail part - io->seek_proc(handle, iTotalData, SEEK_CUR); - return iResourceSize; - } - - nBytes += (block_end - JFIF_startpos); - - return nBytes; -} - -//--------------------------------------------------------------------------- - -psdICCProfile::psdICCProfile() : _ProfileSize(0), _ProfileData(NULL) { -} - -psdICCProfile::~psdICCProfile() { - clear(); -} - -void psdICCProfile::clear() { SAFE_DELETE_ARRAY(_ProfileData); _ProfileSize = 0;} - -int psdICCProfile::Read(FreeImageIO *io, fi_handle handle, int size) { - int nBytes = 0, n; - - clear(); - - _ProfileData = new (std::nothrow) BYTE[size]; - if(NULL != _ProfileData) { - n = (int)io->read_proc(_ProfileData, 1, size, handle); - _ProfileSize = size; - nBytes += n * sizeof(BYTE); - } - - return nBytes; -} - -//--------------------------------------------------------------------------- - -/** -Invert only color components, skipping Alpha/Black -(Can be useful as public/utility function) -*/ -static -BOOL invertColor(FIBITMAP* dib) { - FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); - const unsigned Bpp = FreeImage_GetBPP(dib)/8; - - if ((type == FIT_BITMAP && Bpp == 4) || type == FIT_RGBA16) { - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - BYTE *line_start = FreeImage_GetScanLine(dib, 0); - const unsigned pitch = FreeImage_GetPitch(dib); - const unsigned triBpp = Bpp - (Bpp == 4 ? 1 : 2); - - for(unsigned y = 0; y < height; y++) { - BYTE *line = line_start; - - for(unsigned x = 0; x < width; x++) { - for(unsigned b=0; b < triBpp; ++b) { - line[b] = ~line[b]; - } - - line += Bpp; - } - line_start += pitch; - } - - return TRUE; - } - else { - return FreeImage_Invert(dib); - } -} - -//--------------------------------------------------------------------------- - -psdParser::psdParser() { - _bThumbnailFilled = false; - _bDisplayInfoFilled = false; - _bResolutionInfoFilled = false; - _bResolutionInfoFilled_v2 = false; - _bCopyright = false; - _GlobalAngle = 30; - _ColourCount = -1; - _TransparentIndex = -1; - _fi_flags = 0; - _fi_format_id = FIF_UNKNOWN; -} - -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); - } - - if ( nBytes == nTotalBytes ) { - bSuccess = true; - } - - return bSuccess; -} - -bool psdParser::ReadImageResources(FreeImageIO *io, fi_handle handle, LONG length) { - psdImageResource oResource; - bool bSuccess = false; - - if(length > 0) { - oResource._Length = length; - } else { - 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) { - int n = 0; - oResource.Reset(); - - n = (int)io->read_proc(&oResource._OSType, sizeof(oResource._OSType), 1, handle); - nBytes += n * sizeof(oResource._OSType); - - if ( (nBytes % 2) != 0 ) { - return false; - } - - 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); - nBytes += _thumbnail.Read(io, handle, oResource._Size, 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 - unsigned skip_length = MIN(oResource._Size, nTotalBytes - nBytes); - io->seek_proc(handle, skip_length, SEEK_CUR); - nBytes += skip_length; - } - break; - } - } - } - } - - if (nBytes == nTotalBytes) { - bSuccess = true; - } - - return bSuccess; - -} - -FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) { - if(handle == NULL) - return NULL; - - bool header_only = (_fi_flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - WORD nCompression = 0; - io->read_proc(&nCompression, sizeof(nCompression), 1, handle); - -#ifndef FREEIMAGE_BIGENDIAN - SwapShort(&nCompression); -#endif - - if ((nCompression != PSDP_COMPRESSION_NONE && nCompression != PSDP_COMPRESSION_RLE)) { - FreeImage_OutputMessageProc(_fi_format_id, "Unsupported compression %d", nCompression); - return NULL; - } - - const unsigned nWidth = _headerInfo._Width; - const unsigned nHeight = _headerInfo._Height; - const unsigned nChannels = _headerInfo._Channels; - const unsigned depth = _headerInfo._BitsPerChannel; - const unsigned bytes = (depth == 1) ? 1 : depth / 8; - - // channel(plane) line (BYTE aligned) - const unsigned lineSize = (_headerInfo._BitsPerChannel == 1) ? (nWidth + 7) / 8 : nWidth * bytes; - - if(nCompression == PSDP_COMPRESSION_RLE && depth > 16) { - FreeImage_OutputMessageProc(_fi_format_id, "Unsupported RLE with depth %d", depth); - return NULL; - } - - // build output buffer - - FIBITMAP* bitmap = NULL; - unsigned dstCh = 0; - - short mode = _headerInfo._ColourMode; - - if(mode == PSDP_MULTICHANNEL && nChannels < 3) { - // CM - mode = PSDP_GRAYSCALE; // C as gray, M as extra channel - } - - bool needPalette = false; - switch (mode) { - case PSDP_BITMAP: - case PSDP_DUOTONE: - case PSDP_INDEXED: - case PSDP_GRAYSCALE: - dstCh = 1; - switch(depth) { - case 16: - bitmap = FreeImage_AllocateHeaderT(header_only, FIT_UINT16, nWidth, nHeight, depth*dstCh); - break; - case 32: - bitmap = FreeImage_AllocateHeaderT(header_only, FIT_FLOAT, nWidth, nHeight, depth*dstCh); - break; - default: // 1-, 8- - needPalette = true; - bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); - break; - } - break; - case PSDP_RGB: - case PSDP_LAB: - case PSDP_CMYK : - case PSDP_MULTICHANNEL : - // force PSDP_MULTICHANNEL CMY as CMYK - dstCh = (mode == PSDP_MULTICHANNEL && !header_only) ? 4 : MIN(nChannels, 4); - if(dstCh < 3) { - throw "Invalid number of channels"; - } - - switch(depth) { - case 16: - bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGB16 : FIT_RGBA16, nWidth, nHeight, depth*dstCh); - break; - case 32: - bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGBF : FIT_RGBAF, nWidth, nHeight, depth*dstCh); - break; - default: - bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); - break; - } - break; - default: - throw "Unsupported color mode"; - break; - } - if (!bitmap) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // write thumbnail - FreeImage_SetThumbnail(bitmap, _thumbnail.getDib()); - - // @todo Add some metadata model - - if(header_only) { - return bitmap; - } - - // Load pixels data - - const unsigned dstChannels = dstCh; - - const unsigned dstBpp = (depth == 1) ? 1 : FreeImage_GetBPP(bitmap)/8; - const unsigned dstLineSize = FreeImage_GetPitch(bitmap); - BYTE* const dst_first_line = FreeImage_GetScanLine(bitmap, nHeight - 1);//<*** flipped - - BYTE* line_start = new BYTE[lineSize]; //< fileline cache - - switch ( nCompression ) { - case PSDP_COMPRESSION_NONE: // raw data - { - for(unsigned c = 0; c < nChannels; c++) { - if(c >= dstChannels) { - // @todo write extra channels - break; - } - - const unsigned channelOffset = c * bytes; - - BYTE* dst_line_start = dst_first_line; - for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped - - io->read_proc(line_start, lineSize, 1, handle); - - for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; - line += bytes, dst_line += dstBpp) { -#ifdef FREEIMAGE_BIGENDIAN - memcpy(dst_line + channelOffset, line, bytes); -#else - // reverse copy bytes - for (unsigned b = 0; b < bytes; ++b) { - dst_line[channelOffset + b] = line[(bytes-1) - b]; - } -#endif // FREEIMAGE_BIGENDIAN - } - } //< h - }//< ch - - SAFE_DELETE_ARRAY(line_start); - - } - break; - - case PSDP_COMPRESSION_RLE: // RLE compression - { - - // The RLE-compressed data is preceeded by a 2-byte line size for each row in the data, - // store an array of these - - // later use this array as WORD rleLineSizeList[nChannels][nHeight]; - WORD *rleLineSizeList = new (std::nothrow) WORD[nChannels*nHeight]; - - if (!rleLineSizeList) { - FreeImage_Unload(bitmap); - SAFE_DELETE_ARRAY(line_start); - throw std::bad_alloc(); - } - - io->read_proc(rleLineSizeList, 2, nChannels * nHeight, handle); - - WORD largestRLELine = 0; - for(unsigned ch = 0; ch < nChannels; ++ch) { - for(unsigned h = 0; h < nHeight; ++h) { - const unsigned index = ch * nHeight + h; - -#ifndef FREEIMAGE_BIGENDIAN - SwapShort(&rleLineSizeList[index]); -#endif - if(largestRLELine < rleLineSizeList[index]) { - largestRLELine = rleLineSizeList[index]; - } - } - } - - BYTE* rle_line_start = new (std::nothrow) BYTE[largestRLELine]; - if (!rle_line_start) { - FreeImage_Unload(bitmap); - SAFE_DELETE_ARRAY(line_start); - SAFE_DELETE_ARRAY(rleLineSizeList); - throw std::bad_alloc(); - } - - // Read the RLE data (assume 8-bit) - - const BYTE* const line_end = line_start + lineSize; - - for (unsigned ch = 0; ch < nChannels; ch++) { - const unsigned channelOffset = ch * bytes; - - BYTE* dst_line_start = dst_first_line; - for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped - const unsigned index = ch * nHeight + h; - - // - read and uncompress line - - - const WORD rleLineSize = rleLineSizeList[index]; - - io->read_proc(rle_line_start, rleLineSize, 1, handle); - - for (BYTE* rle_line = rle_line_start, *line = line_start; - rle_line < rle_line_start + rleLineSize, line < line_end;) { - - int len = *rle_line++; - - // NOTE len is signed byte in PackBits RLE - - if ( len < 128 ) { //<- MSB is not set - // uncompressed packet - - // (len + 1) bytes of data are copied - - ++len; - - // assert we don't write beyound eol - memcpy(line, rle_line, line + len > line_end ? line_end - line : len); - line += len; - rle_line += len; - } - else if ( len > 128 ) { //< MSB is set - - // RLE compressed packet - - // One byte of data is repeated (–len + 1) times - - len ^= 0xFF; // same as (-len + 1) & 0xFF - len += 2; // - - // assert we don't write beyound eol - memset(line, *rle_line++, line + len > line_end ? line_end - line : len); - line += len; - - } - else if ( 128 == len ) { - // Do nothing - } - }//< rle_line - - // - write line to destination - - - if(ch >= dstChannels) { - // @todo write to extra channels - break; - } - - // byte by byte copy a single channel to pixel - for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; - line += bytes, dst_line += dstBpp) { - -#ifdef FREEIMAGE_BIGENDIAN - memcpy(dst_line + channelOffset, line, bytes); -#else - // reverse copy bytes - for (unsigned b = 0; b < bytes; ++b) { - dst_line[channelOffset + b] = line[(bytes-1) - b]; - } -#endif // FREEIMAGE_BIGENDIAN - } - }//< h - }//< ch - - SAFE_DELETE_ARRAY(line_start); - SAFE_DELETE_ARRAY(rleLineSizeList); - SAFE_DELETE_ARRAY(rle_line_start); - } - break; - - case 2: // ZIP without prediction, no specification - break; - - case 3: // ZIP with prediction, no specification - break; - - default: // Unknown format - break; - - } - - // --- Further process the bitmap --- - - if ((mode == PSDP_CMYK || mode == PSDP_MULTICHANNEL)) { - // CMYK values are "inverted", invert them back - - if(mode == PSDP_MULTICHANNEL) { - invertColor(bitmap); - } else { - FreeImage_Invert(bitmap); - } - - if ((_fi_flags & PSD_CMYK) == PSD_CMYK) { - // keep as CMYK - - if(mode == PSDP_MULTICHANNEL) { - //### we force CMY to be CMYK, but CMY has no ICC. - // Create empty profile and add the flag. - FreeImage_CreateICCProfile(bitmap, NULL, 0); - FreeImage_GetICCProfile(bitmap)->flags |= FIICC_COLOR_IS_CMYK; - } - } - else { - // convert to RGB - - ConvertCMYKtoRGBA(bitmap); - - // The ICC Profile is no longer valid - _iccProfile.clear(); - - // remove the pending A if not present in source - if(nChannels == 4 || nChannels == 3 ) { - FIBITMAP* t = RemoveAlphaChannel(bitmap); - if(t) { - FreeImage_Unload(bitmap); - bitmap = t; - } // else: silently fail - } - } - } - else if ( mode == PSDP_LAB && !((_fi_flags & PSD_LAB) == PSD_LAB)) { - ConvertLABtoRGB(bitmap); - } - else { - if (needPalette && FreeImage_GetPalette(bitmap)) { - - if(mode == PSDP_BITMAP) { - CREATE_GREYSCALE_PALETTE_REVERSE(FreeImage_GetPalette(bitmap), 2); - } - else if(mode == PSDP_INDEXED) { - if (!_colourModeData._plColourData || _colourModeData._Length != 768 || _ColourCount < 0) { - FreeImage_OutputMessageProc(_fi_format_id, "Indexed image has no palette. Using the default grayscale one."); - } else { - _colourModeData.FillPalette(bitmap); - } - } - // GRAYSCALE, DUOTONE - use default grayscale palette - } - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - if(FreeImage_GetImageType(bitmap) == FIT_BITMAP) { - SwapRedBlue32(bitmap); - } -#endif - } - - return bitmap; -} - -FIBITMAP* psdParser::Load(FreeImageIO *io, fi_handle handle, int s_format_id, int flags) { - FIBITMAP *Bitmap = NULL; - - _fi_flags = flags; - _fi_format_id = s_format_id; - - 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 (!ReadImageResources(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 - FreeImage_CreateICCProfile(Bitmap, _iccProfile._ProfileData, _iccProfile._ProfileSize); - if ((flags & PSD_CMYK) == PSD_CMYK) { - short mode = _headerInfo._ColourMode; - if ((mode == PSDP_CMYK) || (mode == PSDP_MULTICHANNEL)) { - FreeImage_GetICCProfile(Bitmap)->flags |= FIICC_COLOR_IS_CMYK; - } - } - - } catch(const char *text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - catch(const std::exception& e) { - FreeImage_OutputMessageProc(s_format_id, "%s", e.what()); - } - - return Bitmap; -} diff --git a/plugins/FreeImage/Source/FreeImage/PSDParser.h b/plugins/FreeImage/Source/FreeImage/PSDParser.h deleted file mode 100644 index 15ab5425ca..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PSDParser.h +++ /dev/null @@ -1,271 +0,0 @@ -// ========================================================== -// Photoshop Loader -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// 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]; //! Number 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 _BitsPerChannel;//! 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. - FIBITMAP * _dib; //! JFIF data as uncompressed dib. Note: For resource ID 1033 the data is in BGR format. - -public: - psdThumbnail(); - ~psdThumbnail(); - FIBITMAP* getDib() { return _dib; } - /** - @return Returns the number of bytes read - */ - int Read(FreeImageIO *io, fi_handle handle, int iResourceSize, bool isBGR); - -private: - psdThumbnail(const psdThumbnail&); - psdThumbnail& operator=(const psdThumbnail&); -}; - -class psdICCProfile { -public: - int _ProfileSize; - BYTE * _ProfileData; -public: - psdICCProfile(); - ~psdICCProfile(); - void clear(); - /** - @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; - - int _fi_flags; - int _fi_format_id; - -private: - /** Actually ignore it */ - bool ReadLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle); - FIBITMAP* ReadImageData(FreeImageIO *io, fi_handle handle); - -public: - psdParser(); - ~psdParser(); - FIBITMAP* Load(FreeImageIO *io, fi_handle handle, int s_format_id, int flags=0); - /** Also used by the TIFF plugin */ - bool ReadImageResources(FreeImageIO *io, fi_handle handle, LONG length=0); - /** Used by the TIFF plugin */ - FIBITMAP* GetThumbnail() { - return _thumbnail.getDib(); - } -}; - -#endif // PSDPARSER_H - diff --git a/plugins/FreeImage/Source/FreeImage/PixelAccess.cpp b/plugins/FreeImage/Source/FreeImage/PixelAccess.cpp deleted file mode 100644 index 158f9997b2..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PixelAccess.cpp +++ /dev/null @@ -1,209 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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) { - if (!FreeImage_HasPixels(dib)) { - return NULL; - } - return CalculateScanLine(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), scanline); -} - -BOOL DLL_CALLCONV -FreeImage_GetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value) { - BYTE shift; - - if (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImage/Plugin.cpp b/plugins/FreeImage/Source/FreeImage/Plugin.cpp deleted file mode 100644 index ce2863a72e..0000000000 --- a/plugins/FreeImage/Source/FreeImage/Plugin.cpp +++ /dev/null @@ -1,747 +0,0 @@ -// ===================================================================== -// 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 -#include -#else -#include -#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 - // note we have memset to 0, so all unset pointers should be NULL) - - 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_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::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::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::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::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(std::nothrow) 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(InitJNG); - //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); - //s_plugins->AddNode(InitEXR); - //s_plugins->AddNode(InitJ2K); - //s_plugins->AddNode(InitJP2); - //s_plugins->AddNode(InitPFM); - //s_plugins->AddNode(InitPICT); - //s_plugins->AddNode(InitRAW); - } - } -} - -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) { - // cannot save "header only" formats - if(FreeImage_HasPixels(dib) == FALSE) { - FreeImage_OutputMessageProc((int)fif, "FreeImage_SaveToHandle: cannot save \"header only\" formats"); - return FALSE; - } - - 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 = LoadLibraryA(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; -} - -BOOL DLL_CALLCONV -FreeImage_FIFSupportsNoPixels(FREE_IMAGE_FORMAT fif) { - if (s_plugins != NULL) { - PluginNode *node = s_plugins->FindNodeFromFIF(fif); - - return (node != NULL) ? - (node->m_plugin->supports_no_pixels_proc != NULL) ? - node->m_plugin->supports_no_pixels_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/plugins/FreeImage/Source/FreeImage/PluginBMP.cpp b/plugins/FreeImage/Source/FreeImage/PluginBMP.cpp deleted file mode 100644 index d69336f3f5..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginBMP.cpp +++ /dev/null @@ -1,1480 +0,0 @@ -// ========================================================== -// 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) -@return Returns TRUE if successful, returns FALSE otherwise -*/ -static BOOL -LoadPixelData(FreeImageIO *io, fi_handle handle, FIBITMAP *dib, int height, unsigned pitch, unsigned bit_count) { - unsigned count = 0; - - // Load pixel data - // NB: height can be < 0 for BMP data - if (height > 0) { - count = io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle); - if(count != 1) { - return FALSE; - } - } else { - int positiveHeight = abs(height); - for (int c = 0; c < positiveHeight; ++c) { - count = io->read_proc((void *)FreeImage_GetScanLine(dib, positiveHeight - c - 1), pitch, 1, handle); - if(count != 1) { - return FALSE; - } - } - } - - // 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 - - return TRUE; -} - -/** -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 { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // 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 - - unsigned 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 - unsigned bit_count = bih.biBitCount; - unsigned compression = bih.biCompression; - unsigned 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_AllocateHeader(header_only, 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 - - if(header_only) { - // header only mode - return dib; - } - - // 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 : - if ( LoadPixelData(io, handle, dib, height, pitch, bit_count)) { - return dib; - } else { - throw "Error encountered while decoding BMP data"; - } - break; - - 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_AllocateHeader(header_only, width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]); - } else { - dib = FreeImage_AllocateHeader(header_only, 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(header_only) { - // header only mode - return dib; - } - - // load pixel data and swap as needed if OS is Big Endian - - if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))) { - // seek to the actual pixel data - io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); - } - - 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_AllocateHeader(header_only, width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]); - } else { - if ( bit_count == 32 ) { - dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeader(header_only, 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); - - if(header_only) { - // header only mode - return dib; - } - - // 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 { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // 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 - - unsigned 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 - unsigned bit_count = bih.biBitCount; - unsigned compression = bih.biCompression; - unsigned 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_AllocateHeader(header_only, 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 - // note that it may contain RGB or RGBA values : we will calculate this - unsigned pal_size = (bitmap_bits_offset - sizeof(BITMAPFILEHEADER) - bih.biSize) / used_colors; - - io->seek_proc(handle, sizeof(BITMAPFILEHEADER) + bih.biSize, SEEK_SET); - - RGBQUAD *pal = FreeImage_GetPalette(dib); - - if(pal_size == 4) { - for (unsigned count = 0; count < used_colors; count++) { - FILE_BGRA bgra; - - io->read_proc(&bgra, sizeof(FILE_BGRA), 1, handle); - - pal[count].rgbRed = bgra.r; - pal[count].rgbGreen = bgra.g; - pal[count].rgbBlue = bgra.b; - } - } else if(pal_size == 3) { - for (unsigned 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; - } - } - - if(header_only) { - // header only mode - return dib; - } - - // 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_AllocateHeader(header_only, width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]); - } else { - dib = FreeImage_AllocateHeader(header_only, 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(header_only) { - // header only mode - return dib; - } - - 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_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeader(header_only, 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); - - if(header_only) { - // header only mode - return dib; - } - - // 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 { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - 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 - - unsigned used_colors = 0; - unsigned width = bios2_1x.biWidth; - unsigned height = bios2_1x.biHeight; // WARNING: height can be < 0 => check each read_proc using 'height' as a parameter - unsigned bit_count = bios2_1x.biBitCount; - unsigned 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_AllocateHeader(header_only, 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 (unsigned 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; - } - - if(header_only) { - // header only mode - return dib; - } - - // 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_AllocateHeader(header_only, 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); - - if(header_only) { - // header only mode - return dib; - } - - // 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_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeader(header_only, 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); - - if(header_only) { - // header only mode - return dib; - } - - // 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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (handle != NULL) { - BITMAPFILEHEADER bitmapfileheader; - DWORD type = 0; - - // we use this offset value to make seemingly absolute seeks relative in the file - - long offset_in_file = io->tell_proc(handle); - - // read the fileheader - - io->read_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle); -#ifdef FREEIMAGE_BIGENDIAN - SwapFileHeader(&bitmapfileheader); -#endif - - // check the signature - - if ((bitmapfileheader.bfType != 0x4D42) && (bitmapfileheader.bfType != 0x4142)) { - FreeImage_OutputMessageProc(s_format_id, FI_MSG_ERROR_MAGIC_NUMBER); - return NULL; - } - - // read the first byte of the infoheader - - io->read_proc(&type, sizeof(DWORD), 1, handle); - io->seek_proc(handle, 0 - (long)sizeof(DWORD), SEEK_CUR); -#ifdef FREEIMAGE_BIGENDIAN - SwapLong(&type); -#endif - - // call the appropriate load function for the found bitmap type - - switch(type) { - case 12: - // OS/2 and also all Windows versions since Windows 3.0 - return LoadOS21XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); - case 64: - // OS/2 - return LoadOS22XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); - case 40: - // BITMAPINFOHEADER - all Windows versions since Windows 3.0 - return LoadWindowsBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); - case 52: - // BITMAPV2INFOHEADER (undocumented) - break; - case 56: - // BITMAPV3INFOHEADER (undocumented) - break; - case 108: - // BITMAPV4HEADER - all Windows versions since Windows 95/NT4 (not supported) - break; - case 124: - // BITMAPV5HEADER - Windows 98/2000 and newer (not supported) - break; - default: - break; - } - - 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 = (BYTE*)malloc(FreeImage_GetPitch(dib) * 2 * sizeof(BYTE)); - - 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) { - free(buffer); - return FALSE; - } - } - - buffer[0] = RLE_COMMAND; - buffer[1] = RLE_ENDOFBITMAP; - - if (io->write_proc(buffer, 2, 1, handle) != 1) { - free(buffer); - return FALSE; - } - - free(buffer); -#ifdef FREEIMAGE_BIGENDIAN - } else if (bpp == 16) { - int padding = FreeImage_GetPitch(dib) - FreeImage_GetWidth(dib) * sizeof(WORD); - WORD pad = 0; - WORD pixel; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned 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(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned 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(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginCUT.cpp b/plugins/FreeImage/Source/FreeImage/PluginCUT.cpp deleted file mode 100644 index 746fa034a6..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginCUT.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// ========================================================== -// 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 { - WORD width; - WORD height; - LONG 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/x-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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - - if (!handle) { - return NULL; - } - - try { - CUTHEADER header; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // read the cut header - - if(io->read_proc(&header, 1, sizeof(CUTHEADER), handle) != sizeof(CUTHEADER)) { - throw FI_MSG_ERROR_PARSING; - } - -#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_AllocateHeader(header_only, header.width, header.height, 8); - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // 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; - } - - if(header_only) { - // header only mode - return dib; - } - - // unpack the RLE bitmap bits - - BYTE *bits = FreeImage_GetScanLine(dib, header.height - 1); - - unsigned i = 0, k = 0; - unsigned pitch = FreeImage_GetPitch(dib); - unsigned size = header.width * header.height; - BYTE count = 0, run = 0; - - while (i < size) { - if(io->read_proc(&count, 1, sizeof(BYTE), handle) != 1) { - throw FI_MSG_ERROR_PARSING; - } - - 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); - - if(io->read_proc(&run, 1, sizeof(BYTE), handle) != 1) { - throw FI_MSG_ERROR_PARSING; - } - - if(k + count <= header.width) { - memset(bits + k, run, count); - } else { - throw FI_MSG_ERROR_PARSING; - } - } else { - if(k + count <= header.width) { - if(io->read_proc(&bits[k], count, sizeof(BYTE), handle) != 1) { - throw FI_MSG_ERROR_PARSING; - } - } else { - throw FI_MSG_ERROR_PARSING; - } - } - - k += count; - i += count; - } - - return dib; - - } catch(const char* text) { - if(dib) { - FreeImage_Unload(dib); - } - FreeImage_OutputMessageProc(s_format_id, text); - 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginDDS.cpp b/plugins/FreeImage/Source/FreeImage/PluginDDS.cpp deleted file mode 100644 index 0a1667d7f1..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginDDS.cpp +++ /dev/null @@ -1,651 +0,0 @@ -// ========================================================== -// 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 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 { -public: - typedef DXT_INFO_1 INFO; -}; - -class DXT_BLOCKDECODER_3 : public DXT_BLOCKDECODER_BASE { -public: - typedef DXT_BLOCKDECODER_BASE 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 { -public: - typedef DXT_BLOCKDECODER_BASE 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 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 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(std::nothrow) Block[(width + 3) / 4]; - if (!input_buffer) return; - - 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 (pbDst, pbSrc, line, 4, 4); - pbSrc += INFO::bytesPerBlock; - pbDst += 4 * 4; - } - } - if (widthRest) { - DecodeDXTBlock (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 (pbDst, pbSrc, line, 4, heightRest); - pbSrc += INFO::bytesPerBlock; - pbDst += 4 * 4; - } - } - if (widthRest) { - DecodeDXTBlock (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 (io, handle, page, flags, data, dib, width, height, line); - break; - case 3: - LoadDXT_Helper (io, handle, page, flags, data, dib, width, height, line); - break; - case 5: - LoadDXT_Helper (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/x-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 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/plugins/FreeImage/Source/FreeImage/PluginEXR.cpp b/plugins/FreeImage/Source/FreeImage/PluginEXR.cpp deleted file mode 100644 index b9963a11b2..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginEXR.cpp +++ /dev/null @@ -1,764 +0,0 @@ -// ========================================================== -// EXR Loader and writer -// -// 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 "../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/IlmImf/ImfPreviewImage.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/x-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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - bool bUseRgbaInterface = false; - FIBITMAP *dib = NULL; - - if (!handle) { - return NULL; - } - - try { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // save the stream starting point - const 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(); - - 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 ((components == 1) && channels.findChannel("Y")) { - image_type = FIT_FLOAT; - components = 1; - } else { - 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; - // ignore the other channel - components = 1; - } - } 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")) { - if(channels.findChannel("A")) { - if(components > 4) { - std::string msg = "Warning: converting color model " + exr_color_model + " to RGBA color model"; - FreeImage_OutputMessageProc(s_format_id, msg.c_str()); - } - image_type = FIT_RGBAF; - // ignore other layers if there is more than one alpha layer - components = 4; - } else { - std::string msg = "Warning: converting color model " + exr_color_model + " to RGB color model"; - FreeImage_OutputMessageProc(s_format_id, msg.c_str()); - - image_type = FIT_RGBF; - // ignore other channels - components = 3; - } - } - } - - if(image_type == FIT_UNKNOWN) { - THROW (Iex::InputExc, "Unsupported color model: " << exr_color_model); - } - - // allocate a new dib - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, 0); - if (!dib) THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY); - - // try to load the preview image - // -------------------------------------------------------------- - - if(file.header().hasPreviewImage()) { - const Imf::PreviewImage& preview = file.header().previewImage(); - const unsigned thWidth = preview.width(); - const unsigned thHeight = preview.height(); - - FIBITMAP* thumbnail = FreeImage_Allocate(thWidth, thHeight, 32); - if(thumbnail) { - const Imf::PreviewRgba *src_line = preview.pixels(); - BYTE *dst_line = FreeImage_GetScanLine(thumbnail, thHeight - 1); - const unsigned dstPitch = FreeImage_GetPitch(thumbnail); - - for (unsigned y = 0; y < thHeight; ++y) { - const Imf::PreviewRgba *src_pixel = src_line; - RGBQUAD* dst_pixel = (RGBQUAD*)dst_line; - - for(unsigned x = 0; x < thWidth; ++x) { - dst_pixel->rgbRed = src_pixel->r; - dst_pixel->rgbGreen = src_pixel->g; - dst_pixel->rgbBlue = src_pixel->b; - dst_pixel->rgbReserved = src_pixel->a; - src_pixel++; - dst_pixel++; - } - src_line += thWidth; - dst_line -= dstPitch; - } - FreeImage_SetThumbnail(dib, thumbnail); - FreeImage_Unload(thumbnail); - } - } - - if(header_only) { - // header only mode - return dib; - } - - // load pixels - // -------------------------------------------------------------- - - const BYTE *bits = FreeImage_GetBits(dib); // pointer to our pixel buffer - const size_t bytespp = sizeof(float) * components; // size of our pixel in bytes - const 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 (used when loading RY BY Y images ) - - 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 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; - - // allow dataWindow with minimal bounds different form zero - size_t offset = - dataWindow.min.x * bytespp - dataWindow.min.y * pitch; - - if(components == 1) { - frameBuffer.insert ("Y", // name - Imf::Slice (pixelType, // type - (char*)(bits + offset), // 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) + offset), // 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; -} - -/** -Set the preview image using the dib embedded thumbnail -*/ -static BOOL -SetPreviewImage(FIBITMAP *dib, Imf::Header& header) { - if (!FreeImage_GetThumbnail(dib)) { - return FALSE; - } - FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); - - if ((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 32)) { - // invalid thumbnail - ignore it - FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL); - } else { - const unsigned thWidth = FreeImage_GetWidth(thumbnail); - const unsigned thHeight = FreeImage_GetHeight(thumbnail); - - Imf::PreviewImage preview(thWidth, thHeight); - - // copy thumbnail to 32-bit RGBA preview image - - const BYTE* src_line = FreeImage_GetScanLine(thumbnail, thHeight - 1); - Imf::PreviewRgba* dst_line = preview.pixels(); - const unsigned srcPitch = FreeImage_GetPitch(thumbnail); - - for (unsigned y = 0; y < thHeight; y++) { - const RGBQUAD* src_pixel = (RGBQUAD*)src_line; - Imf::PreviewRgba* dst_pixel = dst_line; - - for(unsigned x = 0; x < thWidth; x++) { - dst_pixel->r = src_pixel->rgbRed; - dst_pixel->g = src_pixel->rgbGreen; - dst_pixel->b = src_pixel->rgbBlue; - dst_pixel->a = src_pixel->rgbReserved; - - src_pixel++; - dst_pixel++; - } - - src_line -= srcPitch; - dst_line += thWidth; - } - - header.setPreviewImage(preview); - } - - return TRUE; -} - -/** -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 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); - - // handle thumbnail - SetPreviewImage(dib, header); - - // 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(std::nothrow) 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginG3.cpp b/plugins/FreeImage/Source/FreeImage/PluginG3.cpp deleted file mode 100644 index c383a455b7..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginG3.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// ========================================================== -// 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 "../LibTIFF4/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 tmsize_t -_g3ReadProc(thandle_t handle, void *buf, tmsize_t size) { - // returns an error when reading the TIFF header - return 0; -} - -static tmsize_t -_g3WriteProc(thandle_t handle, void *buf, tmsize_t size) { - // returns ok when writing the TIFF header - return size; -} - -static toff_t -_g3SeekProc(thandle_t handle, toff_t off, int whence) { - return 0; -} - -static int -_g3CloseProc(thandle_t handle) { - return 0; -} - -static toff_t -_g3SizeProc(thandle_t handle) { - return 0; -} - -static int -_g3MapProc(thandle_t, void** base, toff_t* size) { - return 0; -} - -static void -_g3UnmapProc(thandle_t, void* base, toff_t size) { -} - -// -------------------------------------------------------------- - -static tmsize_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, uint8 *tif_rawdata, tmsize_t tif_rawdatasize) { - return ((tmsize_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, (uint16) 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/plugins/FreeImage/Source/FreeImage/PluginGIF.cpp b/plugins/FreeImage/Source/FreeImage/PluginGIF.cpp deleted file mode 100644 index 7af1d821d8..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginGIF.cpp +++ /dev/null @@ -1,1398 +0,0 @@ -// ========================================================== -// GIF Loader and Writer -// -// Design and implementation by -// - Ryan Rubley -// - Raphaël Gaquer -// -// 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 application_extension_offsets; - std::vector comment_extension_offsets; - std::vector graphic_control_extension_offsets; - std::vector 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 = new(std::nothrow) 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(std::nothrow) BYTE[len]; - m_bufferRealSize = len; - } else if ( len > m_bufferRealSize ) { - delete [] m_buffer; - m_buffer = new(std::nothrow) 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 : - // | - 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(std::nothrow) 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; - 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(std::nothrow) 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(std::nothrow) 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 + w - b, 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/plugins/FreeImage/Source/FreeImage/PluginHDR.cpp b/plugins/FreeImage/Source/FreeImage/PluginHDR.cpp deleted file mode 100644 index a0334e1143..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginHDR.cpp +++ /dev/null @@ -1,719 +0,0 @@ -// ========================================================== -// 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 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]; - - const 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/vnd.radiance"; -} - -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 FALSE; -} - -static BOOL DLL_CALLCONV -SupportsExportType(FREE_IMAGE_TYPE type) { - return (type == FIT_RGBF) ? TRUE : FALSE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - - if (!handle) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - 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_AllocateHeaderT(header_only, FIT_RGBF, width, height); - if (!dib) { - throw FI_MSG_ERROR_MEMORY; - } - - // set the metadata as comments - rgbe_ReadMetadata(dib, &header_info); - - if(header_only) { - // header only mode - return dib; - } - - // 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; - } - } - - } - 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginICO.cpp b/plugins/FreeImage/Source/FreeImage/PluginICO.cpp deleted file mode 100644 index d0ece3514c..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginICO.cpp +++ /dev/null @@ -1,805 +0,0 @@ -// ========================================================== -// 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& 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/vnd.microsoft.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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static void * DLL_CALLCONV -Open(FreeImageIO *io, fi_handle handle, BOOL read) { - // Allocate memory for the header structure - ICONHEADER *lpIH = (ICONHEADER*)malloc(sizeof(ICONHEADER)); - if(lpIH == 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* -LoadStandardIcon(FreeImageIO *io, fi_handle handle, int flags, BOOL header_only) { - FIBITMAP *dib = NULL; - - // 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 - unsigned bit_count = bmih.biBitCount; - unsigned line = CalculateLine(width, bit_count); - unsigned pitch = CalculatePitch(line); - - // allocate memory for one icon - - dib = FreeImage_AllocateHeader(header_only, 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(unsigned i = 0; i < CalculateUsedPaletteEntries(bit_count); i++) { - INPLACESWAP(pal[i].rgbRed, pal[i].rgbBlue); - } -#endif - } - - if(header_only) { - // header only mode - return dib; - } - - // 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 dib; -} - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (page == -1) { - page = 0; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - 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)); - if(icon_list == NULL) { - return NULL; - } - 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); - - if ((icon_list[page].bWidth == 0) && (icon_list[page].bHeight == 0)) { - // Vista icon support - dib = FreeImage_LoadFromHandle(FIF_PNG, io, handle, header_only ? FIF_LOAD_NOPIXELS : PNG_DEFAULT); - } - else { - // standard icon support - // see http://msdn.microsoft.com/en-us/library/ms997538.aspx - dib = LoadStandardIcon(io, handle, flags, header_only); - } - - free(icon_list); - - return 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 -SaveStandardIcon(FreeImageIO *io, FIBITMAP *dib, fi_handle handle) { - BITMAPINFOHEADER *bmih = NULL; - - // write the BITMAPINFOHEADER - bmih = FreeImage_GetInfoHeader(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(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; - io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle); - } - } - - // write the bits - int width = bmih->biWidth; - int height = bmih->biHeight; - unsigned bit_count = bmih->biBitCount; - unsigned line = CalculateLine(width, bit_count); - unsigned 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(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned 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; - } - } - } else -#endif -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - if (bit_count == 24) { - FILE_BGR bgr; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned 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; - } - } - } else if (bit_count == 32) { - FILE_BGRA bgra; - for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { - BYTE *line = FreeImage_GetScanLine(dib, y); - for(unsigned 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; - } - } - } else -#endif -#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - { -#endif - BYTE *xor_mask = FreeImage_GetBits(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 (!and_mask) { - return FALSE; - } - - 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); - - return TRUE; -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - ICONHEADER *icon_header = NULL; - std::vector vPages; - int k; - - if (!dib || !handle || !data) { - return FALSE; - } - - // check format limits - unsigned w = FreeImage_GetWidth(dib); - unsigned h = FreeImage_GetHeight(dib); - if ((w < 16) || (w > 256) || (h < 16) || (h > 256) || (w != h)) { - FreeImage_OutputMessageProc(s_format_id, "Unsupported icon size: width x height = %d x %d", w, h); - return FALSE; - } - - if (page == -1) { - page = 0; - } - - // get the icon header - icon_header = (ICONHEADER*)data; - - try { - FIBITMAP *icon_dib = NULL; - - // load all icons - for(k = 0; k < icon_header->idCount; k++) { - icon_dib = Load(io, handle, k, flags, data); - if (!icon_dib) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - 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)); - if (!icon_list) { - throw FI_MSG_ERROR_MEMORY; - } - memset(icon_list, 0, icon_header->idCount * sizeof(ICONDIRENTRY)); - - for(k = 0; k < icon_header->idCount; k++) { - icon_dib = (FIBITMAP*)vPages[k]; - - // convert internal format to ICONDIRENTRY - // take into account Vista icons whose size is 256x256 - const BITMAPINFOHEADER *bmih = FreeImage_GetInfoHeader(icon_dib); - icon_list[k].bWidth = (bmih->biWidth > 255) ? 0 : (BYTE)bmih->biWidth; - icon_list[k].bHeight = (bmih->biHeight > 255) ? 0 : (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)); - } - // initial guess (correct only for standard icons) - icon_list[k].dwBytesInRes = CalculateImageSize(icon_dib); - icon_list[k].dwImageOffset = CalculateImageOffset(vPages, k); - } - - // make a room for icon dir entries, until later update - const long directory_start = io->tell_proc(handle); - io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle); - - // write the image bits for each image - - DWORD dwImageOffset = (DWORD)io->tell_proc(handle); - - for(k = 0; k < icon_header->idCount; k++) { - icon_dib = (FIBITMAP*)vPages[k]; - - if ((icon_list[k].bWidth == 0) && (icon_list[k].bHeight == 0)) { - // Vista icon support - FreeImage_SaveToHandle(FIF_PNG, icon_dib, io, handle, PNG_DEFAULT); - } - else { - // standard icon support - // see http://msdn.microsoft.com/en-us/library/ms997538.aspx - SaveStandardIcon(io, icon_dib, handle); - } - - // update ICONDIRENTRY members - DWORD dwBytesInRes = (DWORD)io->tell_proc(handle) - dwImageOffset; - icon_list[k].dwImageOffset = dwImageOffset; - icon_list[k].dwBytesInRes = dwBytesInRes; - dwImageOffset += dwBytesInRes; - } - - // update the icon descriptions - const long current_pos = io->tell_proc(handle); - io->seek_proc(handle, directory_start, SEEK_SET); -#ifdef FREEIMAGE_BIGENDIAN - SwapIconDirEntries(icon_list, icon_header->idCount); -#endif - io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle); - io->seek_proc(handle, current_pos, SEEK_SET); - - free(icon_list); - - // free the vector class - for(k = 0; k < icon_header->idCount; k++) { - icon_dib = (FIBITMAP*)vPages[k]; - FreeImage_Unload(icon_dib); - } - - return TRUE; - - } catch(const char *text) { - // free the vector class - for(size_t k = 0; k < vPages.size(); k++) { - FIBITMAP *icon_dib = (FIBITMAP*)vPages[k]; - FreeImage_Unload(icon_dib); - } - FreeImage_OutputMessageProc(s_format_id, text); - 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginIFF.cpp b/plugins/FreeImage/Source/FreeImage/PluginIFF.cpp deleted file mode 100644 index b6cd45d6db..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginIFF.cpp +++ /dev/null @@ -1,459 +0,0 @@ -// ========================================================== -// 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/x-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); - if(pal != NULL) { - unsigned palette_entries = MIN((unsigned)ch_size / 3, FreeImage_GetColorsUsed(dib)); - for (unsigned k = 0; k < palette_entries; 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/plugins/FreeImage/Source/FreeImage/PluginJ2K.cpp b/plugins/FreeImage/Source/FreeImage/PluginJ2K.cpp deleted file mode 100644 index 6e772afdaa..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginJ2K.cpp +++ /dev/null @@ -1,339 +0,0 @@ -// ========================================================== -// 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(¶meters); - - 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, ¶meters); - - // 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(¶meters); - - parameters.tcp_numlayers = 0; - // 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, ¶meters); - if (!image) return FALSE; - - // decide if MCT should be used - parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0; - - // 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, ¶meters, 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/plugins/FreeImage/Source/FreeImage/PluginJP2.cpp b/plugins/FreeImage/Source/FreeImage/PluginJP2.cpp deleted file mode 100644 index ed1cb267bb..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginJP2.cpp +++ /dev/null @@ -1,339 +0,0 @@ -// ========================================================== -// 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(¶meters); - - 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, ¶meters); - - // 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(¶meters); - - parameters.tcp_numlayers = 0; - // 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, ¶meters); - if (!image) return FALSE; - - // decide if MCT should be used - parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0; - - // 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, ¶meters, 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/plugins/FreeImage/Source/FreeImage/PluginJPEG.cpp b/plugins/FreeImage/Source/FreeImage/PluginJPEG.cpp deleted file mode 100644 index b69ace95bc..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginJPEG.cpp +++ /dev/null @@ -1,1801 +0,0 @@ -// ========================================================== -// 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) -// - 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! -// ========================================================== - -#ifdef _MSC_VER -#pragma warning (disable : 4786) // identifier was truncated to 'number' characters -#endif - -extern "C" { -#define XMD_H -#undef FAR -#include - -#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 - -#define MAX_JFXX_THUMB_SIZE (MAX_BYTES_IN_MARKER - 5 - 1) - -#define JFXX_TYPE_JPEG 0x10 // JFIF extension marker: JPEG-compressed thumbnail image -#define JFXX_TYPE_8bit 0x11 // JFIF extension marker: palette thumbnail image -#define JFXX_TYPE_24bit 0x13 // JFIF extension marker: RGB thumbnail image - -// ---------------------------------------------------------- -// 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 -// ---------------------------------------------------------- - -/** Fatal errors (print message and exit) */ -static inline void -JPEG_EXIT(j_common_ptr cinfo, int code) { - freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; - error_ptr->pub.msg_code = code; - error_ptr->pub.error_exit(cinfo); -} - -/** Nonfatal errors (we can keep going, but the data is probably corrupt) */ -static inline void -JPEG_WARNING(j_common_ptr cinfo, int code) { - freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; - error_ptr->pub.msg_code = code; - error_ptr->pub.emit_message(cinfo, -1); -} - -/** - 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) { - freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; - - // always display the message - error_ptr->pub.output_message(cinfo); - - // allow JPEG with unknown markers - if(error_ptr->pub.msg_code != JERR_UNKNOWN_MARKER) { - - // let the memory manager delete any temp files before we die - jpeg_destroy(cinfo); - - // return control to the setjmp point - longjmp(error_ptr->setjmp_buffer, 1); - } -} - -/** - 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]; - freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; - - // create the message - error_ptr->pub.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) { - // let the memory manager delete any temp files before we die - jpeg_destroy((j_common_ptr)cinfo); - - JPEG_EXIT((j_common_ptr)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) { - // let the memory manager delete any temp files before we die - jpeg_destroy((j_common_ptr)cinfo); - - JPEG_EXIT((j_common_ptr)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 - - // let the memory manager delete any temp files before we die - jpeg_destroy((j_common_ptr)cinfo); - - JPEG_EXIT((j_common_ptr)cinfo, JERR_INPUT_EMPTY); - } - - JPEG_WARNING((j_common_ptr)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) -*/ -static 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) - const char *xmp_signature = "http://ns.adobe.com/xap/1.0/"; - // XMP signature is 29 bytes long - const size_t xmp_signature_size = strlen(xmp_signature) + 1; - - size_t length = datalen; - BYTE *profile = (BYTE*)dataptr; - - if(length <= xmp_signature_size) { - // avoid reading corrupted or empty data - return FALSE; - } - - // verify the identifying string - - if(memcmp(xmp_signature, profile, strlen(xmp_signature)) == 0) { - // XMP profile - - profile += xmp_signature_size; - length -= xmp_signature_size; - - // 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_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 -*/ -static BOOL -jpeg_read_exif_profile_raw(FIBITMAP *dib, const BYTE *profile, unsigned int length) { - // marker identifying string for Exif = "Exif\0\0" - BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; - - // verify the identifying string - if(memcmp(exif_signature, profile, sizeof(exif_signature)) != 0) { - // not an Exif profile - return FALSE; - } - - // create a tag - FITAG *tag = FreeImage_CreateTag(); - if(tag) { - FreeImage_SetTagID(tag, EXIF_MARKER); // (JPEG_APP0 + 1) => EXIF marker / Adobe XMP marker - FreeImage_SetTagKey(tag, g_TagLib_ExifRawFieldName); - FreeImage_SetTagLength(tag, (DWORD)length); - FreeImage_SetTagCount(tag, (DWORD)length); - FreeImage_SetTagType(tag, FIDT_BYTE); - FreeImage_SetTagValue(tag, profile); - - // store the tag - FreeImage_SetMetadata(FIMD_EXIF_RAW, dib, FreeImage_GetTagKey(tag), tag); - - // destroy the tag - FreeImage_DeleteTag(tag); - - return TRUE; - } - - return FALSE; -} - -/** - Read JFIF "JFXX" extension APP0 marker - @param dib Input FIBITMAP - @param dataptr Pointer to the APP0 marker - @param datalen APP0 marker length - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -jpeg_read_jfxx(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { - if(datalen < 6) { - return FALSE; - } - - const int id_length = 5; - const BYTE *data = dataptr + id_length; - unsigned remaining = datalen - id_length; - - const BYTE type = *data; - ++data, --remaining; - - switch(type) { - case JFXX_TYPE_JPEG: - { - // load the thumbnail - FIMEMORY* hmem = FreeImage_OpenMemory(const_cast(data), remaining); - FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem); - FreeImage_CloseMemory(hmem); - // store the thumbnail - FreeImage_SetThumbnail(dib, thumbnail); - // then delete it - FreeImage_Unload(thumbnail); - break; - } - case JFXX_TYPE_8bit: - // colormapped uncompressed thumbnail (no supported) - break; - case JFXX_TYPE_24bit: - // truecolor uncompressed thumbnail (no supported) - break; - default: - break; - } - - return TRUE; -} - - -/** - 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_APP0: - // JFIF is handled by libjpeg already, handle JFXX - if(memcmp(marker->data, "JFIF" , 5) == 0) { - continue; - } - if(memcmp(marker->data, "JFXX" , 5) == 0) { - if (!cinfo->saw_JFIF_marker || cinfo->JFIF_minor_version < 2) { - FreeImage_OutputMessageProc(s_format_id, "Warning: non-standard JFXX segment"); - } - jpeg_read_jfxx(dib, marker->data, marker->data_length); - } - // other values such as 'Picasa' : ignore safely unknown APP0 marker - break; - 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); - jpeg_read_exif_profile_raw(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) - const 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_APP1 marker (Exif profile) - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -jpeg_write_exif_profile_raw(j_compress_ptr cinfo, FIBITMAP *dib) { - // marker identifying string for Exif = "Exif\0\0" - BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; - - FITAG *tag_exif = NULL; - FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag_exif); - - if(tag_exif) { - const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_exif); - - // verify the identifying string - if(memcmp(exif_signature, tag_value, sizeof(exif_signature)) != 0) { - // not an Exif profile - return FALSE; - } - - if(NULL != tag_value) { - DWORD tag_length = FreeImage_GetTagLength(tag_exif); - - BYTE *profile = (BYTE*)malloc(tag_length * sizeof(BYTE)); - if(profile == NULL) return FALSE; - - for(DWORD i = 0; i < tag_length; i += 65504L) { - unsigned length = MIN((long)(tag_length - i), 65504L); - - memcpy(profile, tag_value + i, length); - jpeg_write_marker(cinfo, EXIF_MARKER, profile, length); - } - - free(profile); - - return TRUE; - } - } - - return FALSE; -} - -/** - Write thumbnail (JFXX segment, JPEG compressed) -*/ -static BOOL -jpeg_write_jfxx(j_compress_ptr cinfo, FIBITMAP *dib) { - // get the thumbnail to be stored - FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); - if (!thumbnail) { - return TRUE; - } - // check for a compatible output format - if ((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 8) && (FreeImage_GetBPP(thumbnail) != 24)) { - FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL); - return FALSE; - } - - // stores the thumbnail as a baseline JPEG into a memory block - // return the memory block only if its size is within JFXX marker size limit! - FIMEMORY *stream = FreeImage_OpenMemory(); - - if(FreeImage_SaveToMemory(FIF_JPEG, thumbnail, stream, JPEG_BASELINE)) { - // check that the memory block size is within JFXX marker size limit - FreeImage_SeekMemory(stream, 0, SEEK_END); - const long eof = FreeImage_TellMemory(stream); - if(eof > MAX_JFXX_THUMB_SIZE) { - FreeImage_OutputMessageProc(s_format_id, "Warning: attached thumbnail is %d bytes larger than maximum supported size - Thumbnail saving aborted", eof - MAX_JFXX_THUMB_SIZE); - FreeImage_CloseMemory(stream); - return FALSE; - } - } else { - FreeImage_CloseMemory(stream); - return FALSE; - } - - BYTE* thData = NULL; - DWORD thSize = 0; - - FreeImage_AcquireMemory(stream, &thData, &thSize); - - BYTE id_length = 5; //< "JFXX" - BYTE type = JFXX_TYPE_JPEG; - - DWORD totalsize = id_length + sizeof(type) + thSize; - jpeg_write_m_header(cinfo, JPEG_APP0, totalsize); - - jpeg_write_m_byte(cinfo, 'J'); - jpeg_write_m_byte(cinfo, 'F'); - jpeg_write_m_byte(cinfo, 'X'); - jpeg_write_m_byte(cinfo, 'X'); - jpeg_write_m_byte(cinfo, '\0'); - - jpeg_write_m_byte(cinfo, type); - - // write thumbnail to destination. - // We "cram it straight into the data destination module", because write_m_byte is slow - - freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest; - - BYTE* & out = dest->pub.next_output_byte; - size_t & bufRemain = dest->pub.free_in_buffer; - - const BYTE *thData_end = thData + thSize; - - while(thData < thData_end) { - *(out)++ = *(thData)++; - if (--bufRemain == 0) { - // buffer full - flush - if (!dest->pub.empty_output_buffer(cinfo)) { - break; - } - } - } - - FreeImage_CloseMemory(stream); - - return TRUE; -} - -/** - Write JPEG special markers -*/ -static BOOL -write_markers(j_compress_ptr cinfo, FIBITMAP *dib) { - // write thumbnail as a JFXX marker - jpeg_write_jfxx(cinfo, 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); - - // write Exif raw data - jpeg_write_exif_profile_raw(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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (handle) { - FIBITMAP *dib = NULL; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // set up the jpeglib structures - - struct jpeg_decompress_struct cinfo; - ErrorManager fi_error_mgr; - - try { - - // step 1: allocate and initialize JPEG decompression object - - // we set up the normal JPEG error routines, then override error_exit & output_message - cinfo.err = jpeg_std_error(&fi_error_mgr.pub); - fi_error_mgr.pub.error_exit = jpeg_error_exit; - fi_error_mgr.pub.output_message = jpeg_output_message; - - // establish the setjmp return context for jpeg_error_exit to use - if (setjmp(fi_error_mgr.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); - throw (const char*)NULL; - } - - 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_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if (!dib) throw FI_MSG_ERROR_DIB_MEMORY; - FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK; - } else { - // load as CMYK and convert to RGB - dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if (!dib) throw FI_MSG_ERROR_DIB_MEMORY; - } - } else { - // RGB or greyscale image - dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 8 * cinfo.num_components, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if (!dib) throw FI_MSG_ERROR_DIB_MEMORY; - - 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 6: read special markers - - read_markers(&cinfo, dib); - - // --- header only mode => clean-up and return - - if (header_only) { - // release JPEG decompression object - jpeg_destroy_decompress(&cinfo); - // return header data - return dib; - } - - // step 7a: 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 < cinfo.output_width; x++) { - WORD K = (WORD)src[3]; - dst[FI_RGBA_RED] = (BYTE)((K * src[0]) / 255); // C -> R - dst[FI_RGBA_GREEN] = (BYTE)((K * src[1]) / 255); // M -> G - dst[FI_RGBA_BLUE] = (BYTE)((K * src[2]) / 255); // Y -> B - src += 4; - dst += 3; - } - } - } else if ((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) == JPEG_CMYK)) { - // convert from LibJPEG CMYK to standard CMYK - - 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 < cinfo.output_width; x++) { - // CMYK pixels are inverted - dst[0] = ~src[0]; // C - dst[1] = ~src[1]; // M - dst[2] = ~src[2]; // Y - dst[3] = ~src[3]; // K - src += 4; - dst += 4; - } - } - - } 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 7b: 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 - SwapRedBlue32(dib); -#endif - } - - // step 8: finish decompression - - jpeg_finish_decompress(&cinfo); - - // step 9: release JPEG decompression object - - jpeg_destroy_decompress(&cinfo); - - // check for automatic Exif rotation - if (!header_only && ((flags & JPEG_EXIFROTATE) == JPEG_EXIFROTATE)) { - rotate_exif(&dib); - } - - // everything went well. return the loaded dib - - return dib; - - } catch (const char *text) { - jpeg_destroy_decompress(&cinfo); - if(NULL != 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)) { - 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; - ErrorManager fi_error_mgr; - - // Step 1: allocate and initialize JPEG compression object - - // we set up the normal JPEG error routines, then override error_exit & output_message - cinfo.err = jpeg_std_error(&fi_error_mgr.pub); - fi_error_mgr.pub.error_exit = jpeg_error_exit; - fi_error_mgr.pub.output_message = jpeg_output_message; - - // establish the setjmp return context for jpeg_error_exit to use - if (setjmp(fi_error_mgr.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_compress(&cinfo); - throw (const char*)NULL; - } - - // 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); - } - - // compute optimal Huffman coding tables for the image - if ((flags & JPEG_OPTIMIZE) == JPEG_OPTIMIZE) { - cinfo.optimize_coding = TRUE; - } - - // 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 - - // thumbnail support (JFIF 1.02 extension markers) - if(FreeImage_GetThumbnail(dib) != NULL) { - cinfo.write_JFIF_header = 1; //<### force it, though when color is CMYK it will be incorrect - cinfo.JFIF_minor_version = 2; - } - - // baseline JPEG support - if ((flags & JPEG_BASELINE) == JPEG_BASELINE) { - cinfo.write_JFIF_header = 0; // No marker for non-JFIF colorspaces - cinfo.write_Adobe_marker = 0; // write no Adobe marker by default - } - - // 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 - - if ((flags & JPEG_BASELINE) != JPEG_BASELINE) { - 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) { - if(text) { - FreeImage_OutputMessageProc(s_format_id, text); - } - 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginKOALA.cpp b/plugins/FreeImage/Source/FreeImage/PluginKOALA.cpp deleted file mode 100644 index 6c3ae52254..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginKOALA.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// ========================================================== -// 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/x-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/plugins/FreeImage/Source/FreeImage/PluginMNG.cpp b/plugins/FreeImage/Source/FreeImage/PluginMNG.cpp deleted file mode 100644 index 6d2f50ecec..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginMNG.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// ========================================================== -// MNG loader -// -// Design and implementation by -// - Herve 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; - -// ---------------------------------------------------------- - -#define MNG_SIGNATURE_SIZE 8 // size of the signature - -// ---------------------------------------------------------- - -// ---------------------------------------------------------- -// mng interface (see MNGHelper.cpp) -// ---------------------------------------------------------- - -FIBITMAP* mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, int flags = 0); - - -// ========================================================== -// Plugin Implementation -// ========================================================== - -static const char * DLL_CALLCONV -Format() { - return "MNG"; -} - -static const char * DLL_CALLCONV -Description() { - return "Multiple-image 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 -Validate(FreeImageIO *io, fi_handle handle) { - BYTE mng_signature[8] = { 138, 77, 78, 71, 13, 10, 26, 10 }; - BYTE signature[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - io->read_proc(&signature, 1, MNG_SIGNATURE_SIZE, handle); - - return (memcmp(mng_signature, signature, MNG_SIGNATURE_SIZE) == 0) ? TRUE : 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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return 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) { - long offset = MNG_SIGNATURE_SIZE; // move to skip first 8 bytes of signature - - // check the signature (8 bytes) - if(Validate(io, handle) == FALSE) { - return NULL; - } - - // parse chunks and decode a jng or mng bitmap - return mng_ReadChunks(s_format_id, io, handle, offset, flags); -} - - -// ========================================================== -// 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 = Validate; - plugin->mime_proc = MimeType; - plugin->supports_export_bpp_proc = SupportsExportDepth; - plugin->supports_export_type_proc = SupportsExportType; - plugin->supports_icc_profiles_proc = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginPCD.cpp b/plugins/FreeImage/Source/FreeImage/PluginPCD.cpp deleted file mode 100644 index 87cbe967b2..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginPCD.cpp +++ /dev/null @@ -1,251 +0,0 @@ -// ========================================================== -// 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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - unsigned width; - unsigned height; - const unsigned bpp = 24; - int scan_line_add = 1; - int start_scan_line = 0; - - BYTE *y1 = NULL, *y2 = NULL, *cbcr = NULL; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // 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; - } - - try { - // allocate the dib and write out the header - dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if (!dib) throw FI_MSG_ERROR_DIB_MEMORY; - - if(header_only) { - return dib; - } - - // 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 = (BYTE*)malloc(width * sizeof(BYTE)); - BYTE *y2 = (BYTE*)malloc(width * sizeof(BYTE)); - BYTE *cbcr = (BYTE*)malloc(width * sizeof(BYTE)); - if (!y1 || !y2 || !cbcr) throw FI_MSG_ERROR_MEMORY; - - 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 (unsigned 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 *bits = FreeImage_GetScanLine(dib, start_scan_line); - for (unsigned x = 0; x < width; x++) { - int r, g, b; - - YUV2RGB(yl[i][x], cbcr[x / 2], cbcr[(width / 2) + (x / 2)], r, g, b); - - bits[FI_RGBA_BLUE] = (BYTE)b; - bits[FI_RGBA_GREEN] = (BYTE)g; - bits[FI_RGBA_RED] = (BYTE)r; - bits += 3; - } - - start_scan_line += scan_line_add; - } - } - - free(cbcr); - free(y2); - free(y1); - - return dib; - - } catch(const char *text) { - if(dib) FreeImage_Unload(dib); - if(cbcr) free(cbcr); - if(y2) free(y2); - if(y1) free(y1); - - FreeImage_OutputMessageProc(s_format_id, text); - - return NULL; - } -} - -// ========================================================== -// 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginPCX.cpp b/plugins/FreeImage/Source/FreeImage/PluginPCX.cpp deleted file mode 100644 index a6feb5fea7..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginPCX.cpp +++ /dev/null @@ -1,659 +0,0 @@ -// ========================================================== -// 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 BOOL -pcx_validate(FreeImageIO *io, fi_handle handle) { - BYTE pcx_signature = 0x0A; - BYTE signature[4] = { 0, 0, 0, 0 }; - - if(io->read_proc(&signature, 1, 4, handle) != 4) { - return FALSE; - } - // magic number (0x0A = ZSoft Z) - if(signature[0] == pcx_signature) { - // version - if(signature[1] <= 5) { - // encoding - if ((signature[2] == 0) || (signature[2] == 1)) { - // bits per pixel per plane - if ((signature[3] == 1) || (signature[3] == 8)) { - return TRUE; - } - } - } - } - - return FALSE; -} - -static unsigned -readline(FreeImageIO &io, fi_handle handle, BYTE *buffer, unsigned 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; - unsigned 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)++); - } else { - count = 1; - } - } - - count--; - - *(buffer + written++) = value; - } - - } else { - // normal read - - written = 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) { - return pcx_validate(io, handle); -} - -/*! - 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; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -/*! - 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; - BOOL bIsRLE; // True if the file is run-length encoded - - if (!handle) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - // check PCX identifier - - long start_pos = io->tell_proc(handle); - BOOL validated = pcx_validate(io, handle); - io->seek_proc(handle, start_pos, SEEK_SET); - if (!validated) { - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // process the header - - PCXHEADER header; - - if(io->read_proc(&header, sizeof(PCXHEADER), 1, handle) != 1) { - throw FI_MSG_ERROR_PARSING; - } -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - - // allocate a new DIB - - unsigned width = header.window[2] - header.window[0] + 1; - unsigned height = header.window[3] - header.window[1] + 1; - unsigned bitcount = header.bpp * header.planes; - - if (bitcount == 24) { - dib = FreeImage_AllocateHeader(header_only, width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeader(header_only, 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; - } - - if(header_only) { - // header only mode - return dib; - } - - // calculate the line length for the PCX and the DIB - - // length of raster line in bytes - unsigned linelength = header.bytes_per_line * header.planes; - // length of DIB line (rounded to DWORD) in bytes - unsigned pitch = FreeImage_GetPitch(dib); - - // run-length encoding ? - - bIsRLE = (header.encoding == 1) ? TRUE : FALSE; - - // load image data - // --------------- - - line = (BYTE*)malloc(linelength * sizeof(BYTE)); - if (!line) throw FI_MSG_ERROR_MEMORY; - - ReadBuf = (BYTE*)malloc(IO_BUF_SIZE * sizeof(BYTE)); - if (!ReadBuf) throw FI_MSG_ERROR_MEMORY; - - bits = FreeImage_GetScanLine(dib, height - 1); - - int ReadPos = IO_BUF_SIZE; - - if ((header.planes == 1) && ((header.bpp == 1) || (header.bpp == 8))) { - BYTE skip; - unsigned written; - - for (unsigned y = 0; y < height; y++) { - written = readline(*io, handle, bits, linelength, bIsRLE, ReadBuf, &ReadPos); - - // skip trailing garbage at the end of the scanline - - for (unsigned 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; - unsigned index; - BYTE *buffer; - unsigned x, y, written; - - buffer = (BYTE*)malloc(width * sizeof(BYTE)); - if (!buffer) throw FI_MSG_ERROR_MEMORY; - - for (y = 0; y < height; y++) { - written = readline(*io, handle, line, linelength, bIsRLE, 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 = (unsigned)((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 (unsigned count = written; count < linelength; count++) { - if (ReadPos < IO_BUF_SIZE) { - ReadPos++; - } else { - io->read_proc(&skip, sizeof(BYTE), 1, handle); - } - } - - bits -= pitch; - } - - free(buffer); - - } else if ((header.planes == 3) && (header.bpp == 8)) { - BYTE *pline; - - for (unsigned y = 0; y < height; y++) { - readline(*io, handle, line, linelength, bIsRLE, 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; - unsigned 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; - } - - free(line); - free(ReadBuf); - - return dib; - - } catch (const char *text) { - // free allocated memory - - if (dib != NULL) { - FreeImage_Unload(dib); - } - if (line != NULL) { - free(line); - } - if (ReadBuf != NULL) { - free(ReadBuf); - } - - FreeImage_OutputMessageProc(s_format_id, text); - } - - 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginPFM.cpp b/plugins/FreeImage/Source/FreeImage/PluginPFM.cpp deleted file mode 100644 index 8ccbd48ba5..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginPFM.cpp +++ /dev/null @@ -1,402 +0,0 @@ -// ========================================================== -// 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/x-portable-floatmap"; -} - -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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -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; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - 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_AllocateHeaderT(header_only, image_type, width, height); - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - if(header_only) { - // header only mode - return dib; - } - - // 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginPICT.cpp b/plugins/FreeImage/Source/FreeImage/PluginPICT.cpp deleted file mode 100644 index 0c44cb2d1f..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginPICT.cpp +++ /dev/null @@ -1,1342 +0,0 @@ -// ========================================================== -// 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 -{ - const char * name; - int len; - const 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> 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; - long currentPos = 0; - - while ( !done ) { - WORD opcode = 0; - - // get the current stream position (used to avoid infinite loops) - currentPos = io->tell_proc(handle); - - 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; - } - - if(currentPos == io->tell_proc(handle)) { - // we probaly reached the end of file as we can no longer move forward ... - throw "Invalid PICT file"; - } - } - - 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/plugins/FreeImage/Source/FreeImage/PluginPNG.cpp b/plugins/FreeImage/Source/FreeImage/PluginPNG.cpp deleted file mode 100644 index ad398a87e8..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginPNG.cpp +++ /dev/null @@ -1,953 +0,0 @@ -// ========================================================== -// 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 - -#include "FreeImage.h" -#include "Utilities.h" - -#include "../Metadata/FreeImageTag.h" - -// ---------------------------------------------------------- - -#define PNG_BYTES_TO_CHECK 8 - -// ---------------------------------------------------------- - -#include "../ZLib/zlib.h" -#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) { - (png_structp)png_ptr; - // empty flush implementation -} - -static void -error_handler(png_structp png_ptr, const char *error) { - (png_structp)png_ptr; - throw error; -} - -// in FreeImage warnings disabled - -static void -warning_handler(png_structp png_ptr, const char *warning) { - (png_structp)png_ptr; - (char*)warning; -} - -// ========================================================== -// Metadata routines -// ========================================================== - -static BOOL -ReadMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) { - // XMP keyword - const 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++) { - // create a tag - tag = FreeImage_CreateTag(); - if (!tag) return FALSE; - - DWORD tag_length = (DWORD) MAX(text_ptr[i].text_length, text_ptr[i].itxt_length); - - 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 - const 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 = (char*)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 BOOL DLL_CALLCONV -SupportsNoPixels() { - 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) { - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - 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 = png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr); - - // 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 - // but *do not* expand fully transparent palette entries to a full alpha channel - - if (pixel_depth == 2) { - png_set_expand_gray_1_2_4_to_8(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; - } - - // 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") - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { - 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_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth); - } - break; - - case PNG_COLOR_TYPE_RGB_ALPHA: - if(image_type == FIT_BITMAP) { - dib = FreeImage_AllocateHeader(header_only, width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth); - } - break; - - case PNG_COLOR_TYPE_PALETTE: - dib = FreeImage_AllocateHeader(header_only, width, height, pixel_depth); - - png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries); - - palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib)); - 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; - } - break; - - case PNG_COLOR_TYPE_GRAY: - dib = FreeImage_AllocateHeaderT(header_only, 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)); - } - } - break; - - default: - throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; - } - - // store the transparency table - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - // array of alpha (transparency) entries for palette - png_bytep trans_alpha = NULL; - // number of transparent entries - int num_trans = 0; - // graylevel or color sample values of the single transparent color for non-paletted images - png_color_16p trans_color = NULL; - - png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color); - - if ((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) { - // single transparent color - if (trans_color->gray < palette_entries) { - BYTE table[256]; - memset(table, 0xFF, palette_entries); - table[trans_color->gray] = 0; - FreeImage_SetTransparencyTable(dib, table, palette_entries); - } - } else if ((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) { - // transparency table - FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans); - } - } - - // store the background color - - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) { - // 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; - - 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 = PNG_RESOLUTION_UNKNOWN; - - png_get_pHYs(png_ptr,info_ptr, &res_x, &res_y, &res_unit_type); - - if (res_unit_type == PNG_RESOLUTION_METER) { - 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_bytep 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_AllocateHeader) - - FreeImage_CreateICCProfile(dib, profile_data, profile_length); - } - - // --- header only mode => clean-up and return - - if (header_only) { - // 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; - } - - // set the individual row_pointers to point at the correct offsets - - row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep)); - - if (!row_pointers) { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - FreeImage_Unload(dib); - return NULL; - } - - // read in the bitmap bits via the pointer table - // allow loading of PNG with minor errors (such as images with several IDAT chunks) - - for (png_uint_32 k = 0; k < height; k++) { - row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k); - } - - png_set_benign_errors(png_ptr, 1); - 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, PNG_RESOLUTION_METER); - } - - // 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_const_bytep)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 (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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginPNM.cpp b/plugins/FreeImage/Source/FreeImage/PluginPNM.cpp deleted file mode 100644 index a30f858851..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginPNM.cpp +++ /dev/null @@ -1,831 +0,0 @@ -// ========================================================== -// 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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -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; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - 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_AllocateHeader(header_only, width, height, 1); - break; - - case '2': - case '5': - if(maxval > 255) { - // 16-bit greyscale - image_type = FIT_UINT16; - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height); - } else { - // 8-bit greyscale - dib = FreeImage_AllocateHeader(header_only, width, height, 8); - } - break; - - case '3': - case '6': - if(maxval > 255) { - // 48-bit RGB - image_type = FIT_RGB16; - dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height); - } else { - // 24-bit RGB - dib = FreeImage_AllocateHeader(header_only, 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; - } - - // Build a greyscale palette if needed - - if(image_type == FIT_BITMAP) { - switch(id_two) { - case '1': - case '4': - 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 '2': - case '5': - pal = FreeImage_GetPalette(dib); - for (i = 0; i < 256; i++) { - pal[i].rgbRed = - pal[i].rgbGreen = - pal[i].rgbBlue = (BYTE)i; - } - break; - - default: - break; - } - } - - if(header_only) { - // header only mode - return dib; - } - - // Read the image... - - switch(id_two) { - case '1': - case '4': - // 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) { - // 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; -} - -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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginPSD.cpp b/plugins/FreeImage/Source/FreeImage/PluginPSD.cpp deleted file mode 100644 index e453a31789..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginPSD.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// ========================================================== -// Photoshop Loader -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// 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/vnd.adobe.photoshop"; -} - -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 BOOL DLL_CALLCONV -SupportsNoPixels() { - 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, flags); - - 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginRAS.cpp b/plugins/FreeImage/Source/FreeImage/PluginRAS.cpp deleted file mode 100644 index 08fc0c9e17..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginRAS.cpp +++ /dev/null @@ -1,512 +0,0 @@ -// ========================================================== -// 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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -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) { - return NULL; - } - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - 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_AllocateHeader(header_only, header.width, header.height, header.depth); - break; - - case 24: - dib = FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - break; - - case 32: - dib = FreeImage_AllocateHeader(header_only, 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; - } - } - - if(header_only) { - // header only mode - return dib; - } - - // 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; - - unsigned 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; -} - -// ========================================================== -// 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginRAW.cpp b/plugins/FreeImage/Source/FreeImage/PluginRAW.cpp deleted file mode 100644 index 4611824f4d..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginRAW.cpp +++ /dev/null @@ -1,542 +0,0 @@ -// ========================================================== -// 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 "../LibRawLite/libraw/libraw.h" - -#include "FreeImage.h" -#include "Utilities.h" -#include "../Metadata/FreeImageTag.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 void * make_jas_stream() { - return NULL; - } - 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(INT64 offset, int origin) { - if(substream) return substream->seek(offset, origin); - return _io->seek_proc(_handle, (long)offset, origin); - } - virtual INT64 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 - WORD *raw_data = (WORD*)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 -@param flags JPEG load flags -@return Returns the loaded dib if successfull, returns NULL otherwise -*/ -static FIBITMAP * -libraw_LoadEmbeddedPreview(LibRaw& RawProcessor, int flags) { - FIBITMAP *dib = NULL; - libraw_processed_image_t *thumb_image = NULL; - - try { - // unpack data - if(RawProcessor.unpack_thumb() != LIBRAW_SUCCESS) { - // run silently "LibRaw : failed to run unpack_thumb" - return NULL; - } - - // 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) { - // 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 - RawProcessor.dcraw_clear_mem(thumb_image); - - return dib; - - } catch(const char *text) { - // clean-up and return - if(thumb_image) { - RawProcessor.dcraw_clear_mem(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 - // ----------------------- - - // (-6) 16-bit or 8-bit - RawProcessor.imgdata.params.output_bps = bitspersample; - // (-g power toe_slope) - if(bitspersample == 16) { - // set -g 1 1 for linear curve - RawProcessor.imgdata.params.gamm[0] = 1; - RawProcessor.imgdata.params.gamm[1] = 1; - } else if(bitspersample == 8) { - // by default settings for rec. BT.709 are used: power 2.222 (i.e. gamm[0]=1/2.222) and slope 4.5 - RawProcessor.imgdata.params.gamm[0] = 1/2.222; - RawProcessor.imgdata.params.gamm[1] = 4.5; - } - // (-W) Don't use automatic increase of brightness by histogram - RawProcessor.imgdata.params.no_auto_bright = 1; - // (-a) Use automatic white balance obtained after averaging over the entire image - 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 - RawProcessor.dcraw_clear_mem(processed_image); - - return dib; - - } catch(const char *text) { - // clean-up and return - if(processed_image) { - RawProcessor.dcraw_clear_mem(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() { - /** - Below are known RAW file extensions that you can check using FreeImage_GetFIFFromFormat. - If a file extension is not listed, that doesn't mean that you cannot load it. - Using FreeImage_GetFileType is the best way to know if a RAW file format is supported. - */ - static const char *raw_extensions = - "3fr," // Hasselblad Digital Camera Raw Image Format. - "arw," // Sony Digital Camera Raw Image Format for Alpha devices. - "bay," // Casio Digital Camera Raw File Format. - "bmq," // NuCore Raw Image File. - "cap," // Phase One Digital Camera Raw Image Format. - "cine," // Phantom Software 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," // Sinar 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. - "drf," // Kodak Digital Camera Raw Image Format. - "dsc," // Kodak Digital Camera Raw Image Format. - "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. - "ia," // Sinar Raw Image File. - "iiq," // Phase One Digital Camera Raw Image Format. - "k25," // Kodak DC25 Digital Camera Raw Image Format. - "kc2," // Kodak DCS200 Digital Camera Raw Image Format. - "kdc," // Kodak Digital Camera Raw Image Format. - "mdc," // Minolta RD175 Digital Camera Raw Image Format. - "mef," // Mamiya Digital Camera Raw Image Format. - "mos," // Leaf Raw Image File. - "mrw," // Minolta Dimage Digital Camera Raw Image Format. - "nef," // Nikon Digital Camera Raw Image Format. - "nrw," // Nikon Digital Camera Raw Image Format. - "orf," // Olympus Digital Camera Raw Image Format. - "pef," // Pentax Digital Camera Raw Image Format. - "ptx," // Pentax Digital Camera Raw Image Format. - "pxn," // Logitech Digital Camera Raw Image Format. - "qtk," // Apple Quicktake 100/150 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. - "rw2," // Panasonic LX3 Digital Camera Raw Image Format. - "rwl," // Leica Camera Raw Image Format. - "rwz," // Rawzor Digital Camera Raw Image Format. - "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. - "srw," // Samsung Raw Image Format. - "sti"; // Sinar Capture Shop Raw Image File. -// "x3f" // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor. - return raw_extensions; -} - -static const char * DLL_CALLCONV -RegExpr() { - return NULL; -} - -static const char * DLL_CALLCONV -MimeType() { - return "image/x-dcraw"; -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - LibRaw RawProcessor; - BOOL bSuccess = TRUE; - - // wrap the input datastream - LibRaw_freeimage_datastream datastream(io, handle); - - // open the datastream - if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) { - bSuccess = FALSE; // LibRaw : failed to open input stream (unknown format) - } - - // clean-up internal memory allocations - RawProcessor.recycle(); - - return bSuccess; -} - -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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - LibRaw RawProcessor; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - // wrap the input datastream - LibRaw_freeimage_datastream datastream(io, handle); - - // set decoding parameters - // the following parameters affect data reading - // -------------------------------------------- - - // (-s [0..N-1]) Select one raw image from input file - RawProcessor.imgdata.params.shot_select = 0; - // (-w) Use camera white balance, if possible (otherwise, fallback to auto_wb) - RawProcessor.imgdata.params.use_camera_wb = 1; - // (-h) outputs the image in 50% size - RawProcessor.imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0; - - // open the datastream - if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) { - throw "LibRaw : failed to open input stream (unknown format)"; - } - - if(header_only) { - // header only mode - dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor.imgdata.sizes.width, RawProcessor.imgdata.sizes.height); - } - else if ((flags & RAW_PREVIEW) == RAW_PREVIEW) { - // try to get the embedded JPEG - dib = libraw_LoadEmbeddedPreview(RawProcessor, 0); - if (!dib) { - // no JPEG preview: try to load as 8-bit/sample (i.e. RGB 24-bit) - dib = libraw_LoadRawData(RawProcessor, 8); - } - } - else if ((flags & RAW_DISPLAY) == RAW_DISPLAY) { - // load raw data as 8-bit/sample (i.e. RGB 24-bit) - dib = libraw_LoadRawData(RawProcessor, 8); - } - else { - // default: load raw data as linear 16-bit/sample (i.e. RGB 48-bit) - dib = libraw_LoadRawData(RawProcessor, 16); - } - - // save ICC profile if present - if(dib && (NULL != RawProcessor.imgdata.color.profile)) { - FreeImage_CreateICCProfile(dib, RawProcessor.imgdata.color.profile, RawProcessor.imgdata.color.profile_length); - } - - // try to get JPEG embedded Exif metadata - if(dib && !((flags & RAW_PREVIEW) == RAW_PREVIEW)) { - FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS); - if(metadata_dib) { - FreeImage_CloneMetadata(dib, metadata_dib); - FreeImage_Unload(metadata_dib); - } - } - - // 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 = SupportsICCProfiles; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginSGI.cpp b/plugins/FreeImage/Source/FreeImage/PluginSGI.cpp deleted file mode 100644 index 3ac189e0ef..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginSGI.cpp +++ /dev/null @@ -1,425 +0,0 @@ -// ========================================================== -// 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/x-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; iformat_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/plugins/FreeImage/Source/FreeImage/PluginTARGA.cpp b/plugins/FreeImage/Source/FreeImage/PluginTARGA.cpp deleted file mode 100644 index 4e3f1a720a..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginTARGA.cpp +++ /dev/null @@ -1,1565 +0,0 @@ -// ========================================================== -// 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 tagTGAEXTENSIONAREA { - WORD extension_size; // Size in bytes of the extension area, always 495 - char author_name[41]; // Name of the author. If not used, bytes should be set to NULL (\0) or spaces - char author_comments[324]; // A comment, organized as four lines, each consisting of 80 characters plus a NULL - WORD datetime_stamp[6]; // Date and time at which the image was created - char job_name[41]; // Job ID - WORD job_time[3]; // Hours, minutes and seconds spent creating the file (for billing, etc.) - char software_id[41]; // The application that created the file - BYTE software_version[3]; - DWORD key_color; - WORD pixel_aspect_ratio[2]; - WORD gamma_value[2]; - DWORD color_correction_offset; // Number of bytes from the beginning of the file to the color correction table if present - DWORD postage_stamp_offset; // Number of bytes from the beginning of the file to the postage stamp image if present - DWORD scan_line_offset; // Number of bytes from the beginning of the file to the scan lines table if present - BYTE attributes_type; // Specifies the alpha channel -} TGAEXTENSIONAREA; - -typedef struct tagTGAFOOTER { - DWORD extension_offset; // extension area offset : offset in bytes from the beginning of the file - DWORD developer_offset; // developer directory offset : offset in bytes from the beginning of the file - char signature[18]; // signature string : contains "TRUEVISION-XFILE.\0" -} TGAFOOTER; - -#ifdef _WIN32 -#pragma pack(pop) -#else -#pragma pack() -#endif - -static const char *FI_MSG_ERROR_CORRUPTED = "Image data corrupted"; - -// ---------------------------------------------------------- -// 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 - -// ========================================================== -// Thumbnail functions -// ========================================================== - -class TargaThumbnail -{ -public: - TargaThumbnail() : _w(0), _h(0), _depth(0), _data(NULL) { - } - ~TargaThumbnail() { - if(_data) { - free(_data); - } - } - - BOOL isNull() const { - return (_data == NULL); - } - - BOOL read(FreeImageIO *io, fi_handle handle, size_t size) { - io->read_proc(&_w, 1, 1, handle); - io->read_proc(&_h, 1, 1, handle); - - const size_t sizeofData = size - 2; - _data = (BYTE*)malloc(sizeofData); - if(_data) { - return (io->read_proc(_data, 1, (unsigned)sizeofData, handle) == sizeofData); - } - return FALSE; - } - - void setDepth(BYTE dp) { - _depth = dp; - } - - FIBITMAP* toFIBITMAP(); - -private: - BYTE _w; - BYTE _h; - BYTE _depth; - BYTE* _data; -}; - -#ifdef FREEIMAGE_BIGENDIAN -static void -swapShortPixels(FIBITMAP* dib) { - if(FreeImage_GetImageType(dib) != FIT_BITMAP) { - return; - } - - const unsigned Bpp = FreeImage_GetBPP(dib)/8; - if(Bpp != 2) { - return; - } - - BYTE* bits = FreeImage_GetBits(dib); - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pitch = FreeImage_GetPitch(dib); - - BYTE* line = bits; - for(unsigned y = 0; y < height; y++, line += pitch) { - for(BYTE* pixel = line; pixel < line + pitch ; pixel += Bpp) { - SwapShort((WORD*)pixel); - } - } -} -#endif // FREEIMAGE_BIGENDIAN - -FIBITMAP* TargaThumbnail::toFIBITMAP() { - if(isNull() || _depth == 0) { - return NULL; - } - - const unsigned line_size = _depth * _w / 8; - FIBITMAP* dib = FreeImage_Allocate(_w, _h, _depth); - if (!dib) { - return NULL; - } - - const BYTE* line = _data; - const BYTE height = _h; - for (BYTE h = 0; h < height; ++h, line += line_size) { - BYTE* dst_line = FreeImage_GetScanLine(dib, height - 1 - h); - memcpy(dst_line, line, line_size); - } - -#ifdef FREEIMAGE_BIGENDIAN - swapShortPixels(dib); -#endif - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - SwapRedBlue32(dib); -#endif - - return dib; -} -// ========================================================== -// Internal functions -// ========================================================== - -/** This class is used when loading RLE compressed images, it implements io cache of fixed size. - In general RLE compressed images *should* be compressed line by line with line sizes stored in Scan Line Table section. - In reality, however there are images not obeying the specification, compressing image data continuously across lines, - making it impossible to load the file cached at every line. -*/ -class IOCache -{ -public: - IOCache(FreeImageIO *io, fi_handle handle, size_t size) : - _ptr(NULL), _begin(NULL), _end(NULL), _size(size), _io(io), _handle(handle) { - _begin = (BYTE*)malloc(size); - if (_begin) { - _end = _begin + _size; - _ptr = _end; // will force refill on first access - } - } - - ~IOCache() { - if (_begin != NULL) { - free(_begin); - } - } - - BOOL isNull() { return _begin == NULL;} - - inline - BYTE getByte() { - if (_ptr >= _end) { - // need refill - _ptr = _begin; - _io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle); //### EOF - no problem? - } - - BYTE result = *_ptr; - - _ptr++; - - return result; - } - - inline - BYTE* getBytes(size_t count /*must be < _size!*/) { - if (_ptr + count >= _end) { - - // need refill - - // 'count' bytes might span two cache bounds, - // SEEK back to add the remains of the current cache again into the new one - - long read = long(_ptr - _begin); - long remaining = long(_size - read); - - _io->seek_proc(_handle, -remaining, SEEK_CUR); - - _ptr = _begin; - _io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle); //### EOF - no problem? - } - - BYTE *result = _ptr; - - _ptr += count; - - return result; - } - -private: - IOCache& operator=(const IOCache& src); // deleted - IOCache(const IOCache& other); // deleted - -private: - BYTE *_ptr; - BYTE *_begin; - BYTE *_end; - const size_t _size; - const FreeImageIO *_io; - const fi_handle _handle; -}; - -#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 -SwapExtensionArea(TGAEXTENSIONAREA *ex) { - SwapShort(&ex->extension_size); - SwapShort(&ex->datetime_stamp[0]); - SwapShort(&ex->datetime_stamp[1]); - SwapShort(&ex->datetime_stamp[2]); - SwapShort(&ex->datetime_stamp[3]); - SwapShort(&ex->datetime_stamp[4]); - SwapShort(&ex->datetime_stamp[5]); - SwapShort(&ex->job_time[0]); - SwapShort(&ex->job_time[1]); - SwapShort(&ex->job_time[2]); - SwapLong (&ex->key_color); - SwapShort(&ex->pixel_aspect_ratio[0]); - SwapShort(&ex->pixel_aspect_ratio[1]); - SwapShort(&ex->gamma_value[0]); - SwapShort(&ex->gamma_value[1]); - SwapLong (&ex->color_correction_offset); - SwapLong (&ex->postage_stamp_offset); - SwapLong (&ex->scan_line_offset); -} - -static void -SwapFooter(TGAFOOTER *footer) { - SwapLong(&footer->extension_offset); - SwapLong(&footer->developer_offset); -} - -#endif // FREEIMAGE_BIGENDIAN - -// ========================================================== -// 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/x-tga"; -} - -static BOOL -isTARGA20(FreeImageIO *io, fi_handle handle) { - const unsigned sizeofSig = 18; - // tga_signature = "TRUEVISION-XFILE." (TGA 2.0 only) - BYTE tga_signature[sizeofSig] = { 84, 82, 85, 69, 86, 73, 83, 73, 79, 78, 45, 88, 70, 73, 76, 69, 46, 0 }; - // get the start offset - const long start_offset = io->tell_proc(handle); - // get the end-of-file - io->seek_proc(handle, 0, SEEK_END); - const long eof = io->tell_proc(handle); - // read the signature - - io->seek_proc(handle, start_offset + eof - sizeofSig, SEEK_SET); - BYTE signature[sizeofSig]; - io->read_proc(&signature, 1, sizeofSig, handle); - - // rewind - io->seek_proc(handle, start_offset, SEEK_SET); - - return (memcmp(tga_signature, signature, sizeofSig) == 0); -} - -static BOOL DLL_CALLCONV -Validate(FreeImageIO *io, fi_handle handle) { - if(isTARGA20(io, handle)) { - return TRUE; - } - - // not a 2.0 image, try testing if it's a valid TGA anyway (not robust) - BOOL bResult = FALSE; - - const long start_offset = io->tell_proc(handle); - - TGAHEADER header; - io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle); - - // rewind - io->seek_proc(handle, start_offset, SEEK_SET); - - switch(header.image_type) { - case TGA_CMAP : - case TGA_RGB: - case TGA_MONO : - case TGA_RLECMAP: - case TGA_RLERGB: - case TGA_RLEMONO: - switch(header.is_pixel_depth) { - case 8 : - case 16: - case 24: - case 32: - bResult = TRUE; - break; - default: - bResult = FALSE; - break; - } - break; - default: - bResult = FALSE; - break; - } - - return bResult; -} - -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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -/** -Used for all 32 and 24 bit loading of uncompressed images -*/ -static void -loadTrueColor(FIBITMAP* dib, int width, int height, int file_pixel_size, FreeImageIO* io, fi_handle handle, BOOL as24bit) { - const int pixel_size = as24bit ? 3 : file_pixel_size; - - // input line cache - BYTE* file_line = (BYTE*)malloc( width * file_pixel_size); - - if (!file_line) { - throw FI_MSG_ERROR_MEMORY; - } - - for (int y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - io->read_proc(file_line, file_pixel_size, width, handle); - BYTE *bgra = file_line; - - for (int x = 0; x < width; x++) { - - bits[FI_RGBA_BLUE] = bgra[0]; - bits[FI_RGBA_GREEN] = bgra[1]; - bits[FI_RGBA_RED] = bgra[2]; - - if (!as24bit) { - bits[FI_RGBA_ALPHA] = bgra[3]; - } - - bgra += file_pixel_size; - - bits += pixel_size; - } - } - - free(file_line); -} - -/** -For the generic RLE loader we need to abstract away the pixel format. -We use a specific overload based on bits-per-pixel for each type of pixel -*/ - -template -inline static void -_assignPixel(BYTE* bits, BYTE* val, BOOL as24bit = FALSE) { - // static assert should go here - assert(FALSE); -} - -template <> -inline void -_assignPixel<8>(BYTE* bits, BYTE* val, BOOL as24bit) { - *bits = *val; -} - -template <> -inline void -_assignPixel<16>(BYTE* bits, BYTE* val, BOOL as24bit) { - WORD value(*reinterpret_cast(val)); - -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&value); -#endif - - if (as24bit) { - bits[FI_RGBA_BLUE] = (BYTE)((((value & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F); - bits[FI_RGBA_GREEN] = (BYTE)((((value & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F); - bits[FI_RGBA_RED] = (BYTE)((((value & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F); - - } else { - *reinterpret_cast(bits) = 0x7FFF & value; - } -} - -template <> -inline void -_assignPixel<24>(BYTE* bits, BYTE* val, BOOL as24bit) { - bits[FI_RGBA_BLUE] = val[0]; - bits[FI_RGBA_GREEN] = val[1]; - bits[FI_RGBA_RED] = val[2]; -} - -template <> -inline void -_assignPixel<32>(BYTE* bits, BYTE* val, BOOL as24bit) { - if (as24bit) { - _assignPixel<24>(bits, val, TRUE); - - } else { -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - *(reinterpret_cast(bits)) = *(reinterpret_cast (val)); -#else // NOTE This is faster then doing reinterpret_cast to int + INPLACESWAP ! - bits[FI_RGBA_BLUE] = val[0]; - bits[FI_RGBA_GREEN] = val[1]; - bits[FI_RGBA_RED] = val[2]; - bits[FI_RGBA_ALPHA] = val[3]; -#endif - } -} - -/** -Generic RLE loader -*/ -template -static void -loadRLE(FIBITMAP* dib, int width, int height, FreeImageIO* io, fi_handle handle, long eof, BOOL as24bit) { - const int file_pixel_size = bPP/8; - const int pixel_size = as24bit ? 3 : file_pixel_size; - - const BYTE bpp = as24bit ? 24 : bPP; - const int line_size = CalculateLine(width, bpp); - - // Note, many of the params can be computed inside the function. - // However, because this is a template function, it will lead to redundant code duplication. - - BYTE rle; - BYTE *line_bits; - - // this is used to guard against writing beyond the end of the image (on corrupted rle block) - const BYTE* dib_end = FreeImage_GetScanLine(dib, height);//< one-past-end row - - // Compute the rough size of a line... - long pixels_offset = io->tell_proc(handle); - long sz = ((eof - pixels_offset) / height); - - // ...and allocate cache of this size (yields good results) - IOCache cache(io, handle, sz); - if(cache.isNull()) { - FreeImage_Unload(dib); - dib = NULL; - return; - } - - int x = 0, y = 0; - - line_bits = FreeImage_GetScanLine(dib, y); - - while (y < height) { - - rle = cache.getByte(); - - BOOL has_rle = rle & 0x80; - rle &= ~0x80; // remove type-bit - - BYTE packet_count = rle + 1; - - //packet_count might be corrupt, test if we are not about to write beyond the last image bit - - if ((line_bits+x) + packet_count*pixel_size > dib_end) { - FreeImage_OutputMessageProc(s_format_id, FI_MSG_ERROR_CORRUPTED); - // return what is left from the bitmap - return; - } - - if (has_rle) { - - // read a pixel value from file... - BYTE *val = cache.getBytes(file_pixel_size); - - //...and fill packet_count pixels with it - - for (int ix = 0; ix < packet_count; ix++) { - _assignPixel((line_bits+x), val, as24bit); - x += pixel_size; - - if (x >= line_size) { - x = 0; - y++; - line_bits = FreeImage_GetScanLine(dib, y); - } - } - - } else { - // no rle commpresion - - // copy packet_count pixels from file to dib - for (int ix = 0; ix < packet_count; ix++) { - BYTE *val = cache.getBytes(file_pixel_size); - _assignPixel((line_bits+x), val, as24bit); - x += pixel_size; - - if (x >= line_size) { - x = 0; - y++; - line_bits = FreeImage_GetScanLine(dib, y); - } - } //< packet_count - } //< has_rle - - } //< while height - -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - FIBITMAP *dib = NULL; - - if (!handle) { - return NULL; - } - - try { - - const BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - // 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 footer - - TargaThumbnail thumbnail; - if(isTARGA20(io, handle)) { - TGAFOOTER footer; - const long footer_offset = start_offset + eof - sizeof(footer); - - io->seek_proc(handle, footer_offset, SEEK_SET); - io->read_proc(&footer, sizeof(tagTGAFOOTER), 1, handle); - -#ifdef FREEIMAGE_BIGENDIAN - SwapFooter(&footer); -#endif - BOOL hasExtensionArea = footer.extension_offset > 0; - if(hasExtensionArea) { - TGAEXTENSIONAREA extensionarea; - io->seek_proc(handle, footer.extension_offset, SEEK_SET); - io->read_proc(&extensionarea, sizeof(extensionarea), 1, handle); - -#ifdef FREEIMAGE_BIGENDIAN - SwapExtensionArea(&extensionarea); -#endif - - DWORD postage_stamp_offset = extensionarea.postage_stamp_offset; - BOOL hasThumbnail = (postage_stamp_offset > 0) && (postage_stamp_offset < (DWORD)footer_offset); - if(hasThumbnail) { - io->seek_proc(handle, postage_stamp_offset, SEEK_SET); - thumbnail.read(io, handle, footer_offset - postage_stamp_offset); - } - } - } - - // read and process the bitmap's header - - TGAHEADER header; - - io->seek_proc(handle, start_offset, SEEK_SET); - io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle); - -#ifdef FREEIMAGE_BIGENDIAN - SwapHeader(&header); -#endif - - thumbnail.setDepth(header.is_pixel_depth); - - const int line = CalculateLine(header.is_width, header.is_pixel_depth); - const int pixel_bits = header.is_pixel_depth; - const int pixel_size = pixel_bits/8; - - int fliphoriz = (header.is_image_descriptor & 0x10) ? 1 : 0; - 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_AllocateHeader(header_only, header.is_width, header.is_height, 8); - - if (dib == NULL) { - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // read the palette (even if header only) - - RGBQUAD *palette = FreeImage_GetPalette(dib); - - if (header.color_map_type > 0) { - 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; - - } // switch(header.cm_size) - - free(cmap); - } - - // handle thumbnail - - FIBITMAP* th = thumbnail.toFIBITMAP(); - if(th) { - RGBQUAD* pal = FreeImage_GetPalette(dib); - RGBQUAD* dst_pal = FreeImage_GetPalette(th); - if(dst_pal && pal) { - for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++) { - dst_pal[i] = pal[i]; - } - } - - FreeImage_SetTransparencyTable(th, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - - FreeImage_SetThumbnail(dib, th); - FreeImage_Unload(th); - } - - if(header_only) { - return dib; - } - - // read in the bitmap bits - - switch (header.image_type) { - case TGA_CMAP: - case TGA_MONO: { - BYTE *bits = NULL; - - for (unsigned count = 0; count < header.is_height; count++) { - bits = FreeImage_GetScanLine(dib, count); - io->read_proc(bits, sizeof(BYTE), line, handle); - } - } - break; - - case TGA_RLECMAP: - case TGA_RLEMONO: { //(8 bit) - loadRLE<8>(dib, header.is_width, header.is_height, io, handle, eof, FALSE); - } - break; - - default : - FreeImage_Unload(dib); - return NULL; - } - } - break; // header.is_pixel_depth == 8 - - case 15 : - - case 16 : { - int pixel_bits = 16; - - // allocate the dib - - if (TARGA_LOAD_RGB888 & flags) { - pixel_bits = 24; - dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - - } else { - dib = FreeImage_AllocateHeader(header_only, 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; - } - - // handle thumbnail - - FIBITMAP* th = thumbnail.toFIBITMAP(); - if(th) { - if(TARGA_LOAD_RGB888 & flags) { - FIBITMAP* t = FreeImage_ConvertTo24Bits(th); - FreeImage_Unload(th); - th = t; - } - - FreeImage_SetThumbnail(dib, th); - FreeImage_Unload(th); - } - - if(header_only) { - return dib; - } - - int line = CalculateLine(header.is_width, pixel_bits); - - const unsigned pixel_size = unsigned(pixel_bits) / 8; - const unsigned src_pixel_size = sizeof(WORD); - - // 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) - // input line cache - BYTE *in_line = (BYTE*)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 = FreeImage_GetScanLine(dib, y); - io->read_proc(in_line, src_pixel_size, header.is_width, handle); - - BYTE *val = in_line; - for (int x = 0; x < line; x += pixel_size) { - - _assignPixel<16>(bits+x, val, TARGA_LOAD_RGB888 & flags); - - val += src_pixel_size; - } - } - - free(in_line); - } - break; - - case TGA_RLERGB: { //(16 bit) - loadRLE<16>(dib, header.is_width, header.is_height, io, handle, eof, TARGA_LOAD_RGB888 & flags); - } - break; - - default : - FreeImage_Unload(dib); - return NULL; - } - } - break; // header.is_pixel_depth == 15 or 16 - - case 24 : { - - dib = FreeImage_AllocateHeader(header_only, 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; - } - - FIBITMAP* th = thumbnail.toFIBITMAP(); - if(th) { - FreeImage_SetThumbnail(dib, th); - FreeImage_Unload(th); - } - - if(header_only) { - return dib; - } - - // read in the bitmap bits - - switch (header.image_type) { - case TGA_RGB: { //(24 bit) - //uncompressed - loadTrueColor(dib, header.is_width, header.is_height, pixel_size,io, handle, TRUE); - } - break; - - case TGA_RLERGB: { //(24 bit) - loadRLE<24>(dib, header.is_width, header.is_height, io, handle, eof, TRUE); - } - break; - - default : - FreeImage_Unload(dib); - return NULL; - } - } - break; // header.is_pixel_depth == 24 - - case 32 : { - int pixel_bits = 32; - - if (TARGA_LOAD_RGB888 & flags) { - pixel_bits = 24; - } - - dib = FreeImage_AllocateHeader(header_only, 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; - } - - // handle thumbnail - - FIBITMAP* th = thumbnail.toFIBITMAP(); - if(th) { - if(TARGA_LOAD_RGB888 & flags) { - FIBITMAP* t = FreeImage_ConvertTo24Bits(th); - FreeImage_Unload(th); - th = t; - } - FreeImage_SetThumbnail(dib, th); - FreeImage_Unload(th); - } - - if(header_only) { - return dib; - } - - // read in the bitmap bits - - switch (header.image_type) { - case TGA_RGB: { //(32 bit) - // uncompressed - loadTrueColor(dib, header.is_width, header.is_height, 4 /*file_pixel_size*/, io, handle, TARGA_LOAD_RGB888 & flags); - } - break; - - case TGA_RLERGB: { //(32 bit) - loadRLE<32>(dib, header.is_width, header.is_height, io, handle, eof, TARGA_LOAD_RGB888 & flags); - } - break; - - default : - FreeImage_Unload(dib); - return NULL; - } - } - break; // header.is_pixel_depth == 32 - - } // switch(header.is_pixel_depth) - - if (flipvert) { - FreeImage_FlipVertical(dib); - } - - if (fliphoriz) { - FreeImage_FlipHorizontal(dib); - } - - return dib; - - } catch (const char *message) { - if (dib) { - FreeImage_Unload(dib); - } - - FreeImage_OutputMessageProc(s_format_id, message); - - return NULL; - } -} - -// -------------------------------------------------------------------------- - -static BOOL -hasValidThumbnail(FIBITMAP* dib) { - FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); - - return thumbnail - && SupportsExportType(FreeImage_GetImageType(thumbnail)) - && SupportsExportDepth(FreeImage_GetBPP(thumbnail)) - // Requirements according to the specification: - && FreeImage_GetBPP(thumbnail) == FreeImage_GetBPP(dib) - && FreeImage_GetImageType(thumbnail) == FreeImage_GetImageType(dib) - && FreeImage_GetWidth(thumbnail) <= 255 - && FreeImage_GetHeight(thumbnail) <= 255; -} - -/** -Writes the ready RLE packet to buffer -*/ -static inline void -flushPacket(BYTE*& dest, unsigned pixel_size, BYTE* packet_begin, BYTE*& packet, BYTE& packet_count, BOOL& has_rle) { - if (packet_count) { - const BYTE type_bit = has_rle ? 0x80 : 0x0; - const BYTE write_count = has_rle ? 1 : packet_count; - - // build packet header: zero-based count + type bit - assert(packet_count >= 1); - BYTE rle = packet_count - 1; - rle |= type_bit; - - // write packet header - *dest = rle; - ++dest; - - // write packet data - memcpy(dest, packet_begin, write_count * pixel_size); - dest += write_count * pixel_size; - - // reset state - packet_count = 0; - packet = packet_begin; - has_rle = FALSE; - } -} - - -static inline void -writeToPacket(BYTE* packet, BYTE* pixel, unsigned pixel_size) { - // Take care of channel and byte order here, because packet will be flushed straight to the file - switch (pixel_size) { - case 1: - *packet = *pixel; - break; - - case 2: { - WORD val(*(WORD*)pixel); -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&val); -#endif - *(WORD*)packet = val; - } - break; - - case 3: { - packet[0] = pixel[FI_RGBA_BLUE]; - packet[1] = pixel[FI_RGBA_GREEN]; - packet[2] = pixel[FI_RGBA_RED]; - } - break; - - case 4: { -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - *(reinterpret_cast(packet)) = *(reinterpret_cast (pixel)); -#else - packet[0] = pixel[FI_RGBA_BLUE]; - packet[1] = pixel[FI_RGBA_GREEN]; - packet[2] = pixel[FI_RGBA_RED]; - packet[3] = pixel[FI_RGBA_ALPHA]; -#endif - } - break; - - default: - assert(FALSE); - } -} - -static inline BOOL -isEqualPixel(BYTE* lhs, BYTE* rhs, unsigned pixel_size) { - switch (pixel_size) { - case 1: - return *lhs == *rhs; - - case 2: - return *(WORD*)lhs == *(WORD*)rhs; - - case 3: - return *(WORD*)lhs == *(WORD*)rhs && lhs[2] == rhs[2]; - - case 4: - return *(unsigned*)lhs == *(unsigned*)rhs; - - default: - assert(FALSE); - return FALSE; - } -} - -static void -saveRLE(FIBITMAP* dib, FreeImageIO* io, fi_handle handle) { - // Image is compressed line by line, packets don't span multiple lines (TGA2.0 recommendation) - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned height = FreeImage_GetHeight(dib); - const unsigned pixel_size = FreeImage_GetBPP(dib)/8; - const unsigned line_size = FreeImage_GetLine(dib); - - const BYTE max_packet_size = 128; - BYTE packet_count = 0; - BOOL has_rle = FALSE; - - // packet (compressed or not) to be written to line - - BYTE* const packet_begin = (BYTE*)malloc(max_packet_size * pixel_size); - BYTE* packet = packet_begin; - - // line to be written to disk - // Note: we need some extra bytes for anti-commpressed lines. The worst case is: - // 8 bit images were every 3th pixel is different. - // Rle packet becomes two pixels, but nothing is compressed: two byte pixels are transformed into byte header and byte pixel value - // After every rle packet there is a non-rle packet of one pixel: an extra byte for the header will be added for it - // In the end we gain no bytes from compression, but also must insert a byte at every 3th pixel - - // add extra space for anti-commpressed lines - size_t extra_space = (size_t)ceil(width / 3.0); - BYTE* const line_begin = (BYTE*)malloc(width * pixel_size + extra_space); - BYTE* line = line_begin; - - BYTE *current = (BYTE*)malloc(pixel_size); - BYTE *next = (BYTE*)malloc(pixel_size); - - for(unsigned y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - - // rewind line pointer - line = line_begin; - - for(unsigned x = 0; x < line_size; x += pixel_size) { - - AssignPixel(current, (bits + x), pixel_size); - - // read next pixel from dib - - if ( x + 1*pixel_size < line_size) { - AssignPixel(next, (bits + x + 1*pixel_size), pixel_size); - - } else { - // last pixel in line - - // include current pixel and flush - if (!has_rle) { - - writeToPacket(packet, current, pixel_size); - packet += pixel_size; - - } - - assert(packet_count < max_packet_size); - - ++packet_count; - - flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); - - // start anew on next line - break; - } - - if(isEqualPixel(current, next, pixel_size)) { - - // has rle - - if (!has_rle) { - // flush non rle packet - - flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); - - // start a rle packet - - has_rle = TRUE; - - writeToPacket(packet, current, pixel_size); - packet += pixel_size; - } - - // otherwise do nothing. We will just increase the count at the end - - } else { - - // no rle - - if(has_rle) { - // flush rle packet - - // include current pixel first - assert(packet_count < max_packet_size); - ++packet_count; - - flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); - - // start anew on the next pixel - continue; - - } else { - - writeToPacket(packet, current, pixel_size); - packet += pixel_size; - } - - } - - // increase counter on every pixel - - ++packet_count; - - if(packet_count == max_packet_size) { - flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); - } - - }//for width - - // write line to disk - io->write_proc(line_begin, 1, (unsigned)(line - line_begin), handle); - - }//for height - - free(line_begin); - free(packet_begin); - free(current); - free(next); -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - if ((dib == NULL) || (handle == NULL)) { - return FALSE; - } - - RGBQUAD *palette = FreeImage_GetPalette(dib); - const unsigned 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 = (TARGA_SAVE_RLE & flags) ? TGA_RLECMAP : 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 = (TARGA_SAVE_RLE & flags) ? TGA_RLERGB : 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 - - - if (TARGA_SAVE_RLE & flags) { - - saveRLE(dib, io, handle); - - } else { - - // -- no rle compression -- - - const unsigned width = header.is_width; - const unsigned height = header.is_height; - const unsigned pixel_size = bpp/8; - - BYTE *line, *const line_begin = (BYTE*)malloc(width * pixel_size); - BYTE *line_source = line_begin; - - for (unsigned y = 0; y < height; y++) { - BYTE *scanline = FreeImage_GetScanLine(dib, y); - - // rewind the line pointer - line = line_begin; - - switch (bpp) { - case 8: { - // don't copy line, read straight from dib - line_source = scanline; - } - break; - - case 16: { - for (unsigned x = 0; x < width; x++) { - WORD pixel = *(((WORD *)scanline) + x); - -#ifdef FREEIMAGE_BIGENDIAN - SwapShort(&pixel); -#endif - *(WORD*)line = pixel; - - line += pixel_size; - } - } - break; - - case 24: { - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - line_source = scanline; -#else - for (unsigned x = 0; x < width; ++x) { - RGBTRIPLE* trip = ((RGBTRIPLE *)scanline) + x; - line[0] = trip->rgbtBlue; - line[1] = trip->rgbtGreen; - line[2] = trip->rgbtRed; - - line += pixel_size; - } -#endif - } - break; - - case 32: { - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - line_source = scanline; -#else - for (unsigned x = 0; x < width; ++x) { - RGBQUAD* quad = ((RGBQUAD *)scanline) + x; - line[0] = quad->rgbBlue; - line[1] = quad->rgbGreen; - line[2] = quad->rgbRed; - line[3] = quad->rgbReserved; - - line += pixel_size; - } -#endif - } - break; - - }//switch(bpp) - - // write line to disk - - io->write_proc(line_source, pixel_size, width, handle); - - }//for height - - free(line_begin); - } - - - long extension_offset = 0 ; - if(hasValidThumbnail(dib)) { - // write extension area - - extension_offset = io->tell_proc(handle); - - TGAEXTENSIONAREA ex; - memset(&ex, 0, sizeof(ex)); - - assert(sizeof(ex) == 495); - ex.extension_size = sizeof(ex); - ex.postage_stamp_offset = extension_offset + ex.extension_size + 0 /*< no Scan Line Table*/; - ex.attributes_type = FreeImage_GetBPP(dib) == 32 ? 3 /*< useful Alpha channel data*/ : 0 /*< no Alpha data*/; - -#ifdef FREEIMAGE_BIGENDIAN - SwapExtensionArea(&ex); -#endif - - io->write_proc(&ex, sizeof(ex), 1, handle); - - // (no Scan Line Table) - - // write thumbnail - - io->seek_proc(handle, ex.postage_stamp_offset, SEEK_SET); - - FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); - BYTE width = (BYTE)FreeImage_GetWidth(thumbnail); - BYTE height = (BYTE)FreeImage_GetHeight(thumbnail); - - io->write_proc(&width, 1, 1, handle); - io->write_proc(&height, 1, 1, handle); - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB - SwapRedBlue32(dib); -#endif - -#ifdef FREEIMAGE_BIGENDIAN - swapShortPixels(dib); -#endif - - const unsigned line_size = FreeImage_GetLine(thumbnail); - - for (BYTE h = 0; h < height; ++h) { - BYTE* src_line = FreeImage_GetScanLine(thumbnail, height - 1 - h); - io->write_proc(src_line, 1, line_size, handle); - } - } - - // (no Color Correction Table) - - // write the footer - - TGAFOOTER footer; - footer.extension_offset = extension_offset; - footer.developer_offset = 0; - strcpy(footer.signature, "TRUEVISION-XFILE."); - - -#ifdef FREEIMAGE_BIGENDIAN - SwapFooter(&footer); -#endif - - io->write_proc(&footer, sizeof(footer), 1, handle); - - return TRUE; -} - -// ========================================================== -// 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginTIFF.cpp b/plugins/FreeImage/Source/FreeImage/PluginTIFF.cpp deleted file mode 100644 index 54f81e0938..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginTIFF.cpp +++ /dev/null @@ -1,2629 +0,0 @@ -// ========================================================== -// 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) -// - 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! -// ========================================================== - -#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 "FreeImage.h" -#include "Utilities.h" -#include "../LibTIFF4/tiffiop.h" -#include "../Metadata/FreeImageTag.h" -#include "../OpenEXR/Half/half.h" - -#include "FreeImageIO.h" -#include "PSDParser.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); -BOOL tiff_write_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, - LoadAsLogLuv = 5, - LoadAsHalfFloat = 6 -} TIFFLoadMethod; - -// ---------------------------------------------------------- -// local prototypes -// ---------------------------------------------------------- - -static tmsize_t _tiffReadProc(thandle_t handle, void* buf, tmsize_t size); -static tmsize_t _tiffWriteProc(thandle_t handle, void* buf, tmsize_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, void** pbase, toff_t* psize); -static void _tiffUnmapProc(thandle_t fd, void* 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(BOOL header_only, 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); - -static void ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib); - - -// ========================================================== -// Plugin Interface -// ========================================================== - -static int s_format_id; - -typedef struct { - FreeImageIO *io; - fi_handle handle; - TIFF *tif; -} fi_TIFFIO; - -// ---------------------------------------------------------- -// libtiff interface -// ---------------------------------------------------------- - -static tmsize_t -_tiffReadProc(thandle_t handle, void *buf, tmsize_t size) { - fi_TIFFIO *fio = (fi_TIFFIO*)handle; - return fio->io->read_proc(buf, size, 1, fio->handle) * size; -} - -static tmsize_t -_tiffWriteProc(thandle_t handle, void *buf, tmsize_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 - -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, void** base, toff_t* size) { - return 0; -} - -static void -_tiffUnmapProc(thandle_t, void* base, toff_t size) { -} - -/** -Open a TIFF file descriptor for reading or writing -@param handle File handle -@param name Name of the file handle -@param mode Specifies if the file is to be opened for reading ("r") or writing ("w") -*/ -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 reading or writing -@param name -@param mode -*/ -TIFF* -TIFFOpen(const char* name, const char* mode) { - return 0; -} - -// ---------------------------------------------------------- -// TIFF library FreeImage-specific routines. -// ---------------------------------------------------------- - -void* -_TIFFmalloc(tmsize_t s) { - return malloc(s); -} - -void -_TIFFfree(void *p) { - free(p); -} - -void* -_TIFFrealloc(void* p, tmsize_t s) { - return realloc(p, s); -} - -void -_TIFFmemset(void* p, int v, tmsize_t c) { - memset(p, v, (size_t) c); -} - -void -_TIFFmemcpy(void* d, const void* s, tmsize_t c) { - memcpy(d, s, (size_t) c); -} - -int -_TIFFmemcmp(const void* p1, const void* p2, tmsize_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<= 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 header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full 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(BOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel) { - FIBITMAP *dib = NULL; - - if ((width < 0) || (height < 0)) { - // check for malicious images - return NULL; - } - - int bpp = bitspersample * samplesperpixel; - - if(fit == FIT_BITMAP) { - // standard bitmap type - - if(bpp == 16) { - - if ((samplesperpixel == 2) && (bitspersample == 8)) { - // 8-bit indexed + 8-bit alpha channel -> convert to 8-bit transparent - dib = FreeImage_AllocateHeader(header_only, width, height, 8); - } else { - // 16-bit RGB -> expect it to be 565 - dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK); - } - - } - else { - - dib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } - - - } else { - // other bitmap types - - dib = FreeImage_AllocateHeaderT(header_only, 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 48: - // 3 x half float => convert to RGBF - if ((samplesperpixel == 3) && (bitspersample == 16)) { - fit = FIT_RGBF; - } - break; - case 64: - if(samplesperpixel == 2) { - fit = FIT_FLOAT; - } else { - fit = FIT_DOUBLE; - } - break; - case 96: - fit = FIT_RGBF; - break; - default: - if(bpp >= 128) { - fit = FIT_RGBAF; - } - 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(bitspersample == 16) { - 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 96: - 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) { - BOOL bResult = FALSE; - toff_t exif_offset = 0; - - // read EXIF-TIFF tags - bResult = 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; - } - - // read all known exif tags - bResult = tiff_read_exif_tags(tiff, TagLib::EXIF_EXIF, dib); - } - - return bResult; -} - -/** -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 the Exif profile to TIFF - @param dib Input FIBITMAP - @param tiff LibTIFF TIFF handle - @return Returns TRUE if successful, FALSE otherwise -*/ -static BOOL -tiff_write_exif_profile(TIFF *tiff, FIBITMAP *dib) { - BOOL bResult = FALSE; - uint32 exif_offset = 0; - - // write EXIF_MAIN tags, EXIF_EXIF not supported yet - bResult = tiff_write_exif_tags(tiff, TagLib::EXIF_MAIN, dib); - - return bResult; -} - -/** -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); - - // EXIF_MAIN tags - tiff_write_exif_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) || - (type == FIT_RGBAF) - ); -} - -static BOOL DLL_CALLCONV -SupportsICCProfiles() { - return TRUE; -} - -static BOOL DLL_CALLCONV -SupportsNoPixels() { - 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 -@param samplesperpixel TIFFTAG_SAMPLESPERPIXEL tiff tag -@return Returns FALSE if a uncommon bit-depth is encountered, returns TRUE otherwise -*/ -static BOOL -IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesperpixel) { - - 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)-1; - uint16 samplesperpixel = (uint16)-1; - uint16 photometric = (uint16)-1; - uint16 planar_config = (uint16)-1; - - 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(image_type == FIT_RGBF) { - if ((samplesperpixel == 3) && (bitspersample == 16)) { - // load 3 x 16-bit half as RGBF - loadMethod = LoadAsHalfFloat; - } - } - break; - case PHOTOMETRIC_YCBCR: - case PHOTOMETRIC_CIELAB: - case PHOTOMETRIC_ICCLAB: - case PHOTOMETRIC_ITULAB: - loadMethod = LoadAsRBGA; - break; - case PHOTOMETRIC_LOGLUV: - loadMethod = LoadAsLogLuv; - break; - case PHOTOMETRIC_SEPARATED: - // 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 (!bIsTiled) { - 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 > 1) && (bitspersample == 8)) { - loadMethod = LoadAs8BitTrns; - } else { - loadMethod = LoadAsGenericStrip; - } - break; - default: - loadMethod = LoadAsGenericStrip; - break; - } - - if ((loadMethod == LoadAsGenericStrip) && bIsTiled) { - loadMethod = LoadAsTiled; - } - - return loadMethod; -} - -// ========================================================== -// TIFF thumbnail routines -// ========================================================== - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data); - -/** -Read embedded thumbnail -*/ -static void -ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib) { - FIBITMAP* thumbnail = NULL; - - // read exif thumbnail (IFD 1) ... - - uint32 exif_offset = 0; - if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) { - - if(TIFFLastDirectory(tiff) != 0) { - // save current position - long tell_pos = io->tell_proc(handle); - uint16 cur_dir = TIFFCurrentDirectory(tiff); - - // load the thumbnail - int page = 1; - int flags = TIFF_DEFAULT; - thumbnail = Load(io, handle, page, flags, data); - // store the thumbnail (remember to release it later ...) - FreeImage_SetThumbnail(dib, thumbnail); - - // restore current position - io->seek_proc(handle, tell_pos, SEEK_SET); - TIFFSetDirectory(tiff, cur_dir); - } - } - - // ... or read the first subIFD - - if (!thumbnail) { - uint16 subIFD_count = 0; - uint64* subIFD_offsets = NULL; - // ### Theoretically this should also read the first subIFD from a Photoshop-created file with "pyramid". - // It does not however - the tag is there (using Tag Viewer app) but libtiff refuses to read it - if(TIFFGetField(tiff, TIFFTAG_SUBIFD, &subIFD_count, &subIFD_offsets)) { - if(subIFD_count > 0) { - // save current position - long tell_pos = io->tell_proc(handle); - uint16 cur_dir = TIFFCurrentDirectory(tiff); - if(TIFFSetSubDirectory(tiff, subIFD_offsets[0])) { - // load the thumbnail - int page = -1; - int flags = TIFF_DEFAULT; - thumbnail = Load(io, handle, page, flags, data); - // store the thumbnail (remember to release it later ...) - FreeImage_SetThumbnail(dib, thumbnail); - } - // restore current position - io->seek_proc(handle, tell_pos, SEEK_SET); - TIFFSetDirectory(tiff, cur_dir); - } - } - } - - // ... or read Photoshop thumbnail - - if (!thumbnail) { - uint32 ps_size = 0; - void *ps_data = NULL; - - if(TIFFGetField(tiff, TIFFTAG_PHOTOSHOP, &ps_size, &ps_data)) { - FIMEMORY *handle = FreeImage_OpenMemory((BYTE*)ps_data, ps_size); - - FreeImageIO io; - SetMemoryIO(&io); - - psdParser parser; - parser.ReadImageResources(&io, handle, ps_size); - - FreeImage_SetThumbnail(dib, parser.GetThumbnail()); - - FreeImage_CloseMemory(handle); - } - - } - - // release thumbnail - FreeImage_Unload(thumbnail); -} - -// -------------------------------------------------------------------------- - -static FIBITMAP * DLL_CALLCONV -Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { - if (!handle || !data ) { - return NULL; - } - - TIFF *tif = NULL; - uint32 height = 0; - uint32 width = 0; - uint16 bitspersample = 1; - uint16 samplesperpixel = 1; - uint32 rowsperstrip = (uint32)-1; - uint16 photometric = PHOTOMETRIC_MINISWHITE; - uint16 compression = (uint16)-1; - uint16 planar_config; - - FIBITMAP *dib = NULL; - uint32 iccSize = 0; // ICC profile length - void *iccBuf = NULL; // ICC profile data - - const BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - try { - fi_TIFFIO *fio = (fi_TIFFIO*)data; - tif = fio->tif; - - if (page != -1) { - if (!tif || !TIFFSetDirectory(tif, (uint16)page)) { - throw "Error encountered while opening TIFF file"; - } - } - - const BOOL asCMYK = (flags & TIFF_CMYK) == TIFF_CMYK; - - // 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(IsValidBitsPerSample(photometric, bitspersample, samplesperpixel) == 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 = NULL; - - if (!header_only) { - - 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, 1)) { - _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) { // TODO Write to Extra Channels - 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(header_only, image_type, width, height, bitspersample, samplesperpixel); - if (dib == NULL) { - // free the raster pointer and output an error if allocation failed - if(raster) { - _TIFFfree(raster); - } - throw FI_MSG_ERROR_DIB_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - if (!header_only) { - - // 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); - } - - // ### Not correct when header only - FreeImage_SetTransparent(dib, has_alpha); - - } else if(loadMethod == LoadAs8BitTrns) { - // --------------------------------------------------------------------------------- - // 8-bit + 8-bit alpha layer loading - // --------------------------------------------------------------------------------- - - // create a new 8-bit DIB - dib = CreateImageType(header_only, image_type, width, height, bitspersample, MIN(2, 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) - - const tmsize_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 saved 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 && !header_only) { - - 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 && !header_only) { - tmsize_t stripsize = TIFFStripSize(tif) * sizeof(BYTE); - BYTE *buf = (BYTE*)malloc(2 * stripsize); - if(buf == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - 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 - // --------------------------------------------------------------------------------- - - // 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); - - // We use a temp dib to store the alpha for the CMYKA to RGBA conversion - // NOTE this is until we have Extra channels implementation. - // Also then it will be possible to merge LoadAsCMYK with LoadAsGenericStrip - - FIBITMAP *alpha = NULL; - unsigned alpha_pitch = 0; - BYTE *alpha_bits = NULL; - unsigned alpha_Bpp = 0; - - if(isCMYKA && !asCMYK && !header_only) { - if(bitspersample == 16) { - alpha = FreeImage_AllocateT(FIT_UINT16, width, height); - } else if (bitspersample == 8) { - alpha = FreeImage_Allocate(width, height, 8); - } - - if (!alpha) { - FreeImage_OutputMessageProc(s_format_id, "Failed to allocate temporary alpha channel"); - } else { - alpha_bits = FreeImage_GetScanLine(alpha, height - 1); - alpha_pitch = FreeImage_GetPitch(alpha); - alpha_Bpp = FreeImage_GetBPP(alpha) / 8; - } - - } - - // create a new DIB - const uint16 chCount = MIN(samplesperpixel, 4); - dib = CreateImageType(header_only, image_type, width, height, bitspersample, chCount); - if (dib == NULL) { - FreeImage_Unload(alpha); - throw FI_MSG_ERROR_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - if (!header_only) { - - // calculate the line + pitch (separate for scr & dest) - - const tmsize_t src_line = TIFFScanlineSize(tif); - const tmsize_t dst_line = FreeImage_GetLine(dib); - const unsigned dib_pitch = FreeImage_GetPitch(dib); - const unsigned dibBpp = FreeImage_GetBPP(dib) / 8; - const unsigned Bpc = dibBpp / chCount; - const unsigned srcBpp = bitspersample * samplesperpixel / 8; - - assert(Bpc <= 2); //< CMYK is only BYTE or SHORT - - // 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 - - BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); - if(buf == NULL) { - FreeImage_Unload(alpha); - throw FI_MSG_ERROR_MEMORY; - } - - if(planar_config == PLANARCONFIG_CONTIG) { - - // - loop for strip blocks - - - for (uint32 y = 0; y < height; y += rowsperstrip) { - const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, strips * src_line) == -1) { - free(buf); - FreeImage_Unload(alpha); - throw FI_MSG_ERROR_PARSING; - } - - // - loop for strips - - - if(src_line != dst_line) { - // CMYKA+ - if(alpha) { - for (int l = 0; l < strips; l++) { - for(BYTE *pixel = bits, *al_pixel = alpha_bits, *src_pixel = buf + l * src_line; pixel < bits + dib_pitch; pixel += dibBpp, al_pixel += alpha_Bpp, src_pixel += srcBpp) { - // copy pixel byte by byte - BYTE b = 0; - for ( ; b < dibBpp; ++b) { - pixel[b] = src_pixel[b]; - } - // TODO write the remaining bytes to extra channel(s) - - // HACK write the first alpha to a separate dib (assume BYTE or WORD) - al_pixel[0] = src_pixel[b]; - if(Bpc > 1) { - al_pixel[1] = src_pixel[b + 1]; - } - - } - bits -= dib_pitch; - alpha_bits -= alpha_pitch; - } - } - else { - // alpha/extra channels alloc failed - for (int l = 0; l < strips; l++) { - for(BYTE* pixel = bits, * src_pixel = buf + l * src_line; pixel < bits + dst_line; pixel += dibBpp, src_pixel += srcBpp) { - AssignPixel(pixel, src_pixel, dibBpp); - } - bits -= dib_pitch; - } - } - } - else { - // CMYK to CMYK - for (int l = 0; l < strips; l++) { - BYTE *b = buf + l * src_line; - memcpy(bits, b, src_line); - bits -= dib_pitch; - } - } - - } // height - - } - else if(planar_config == PLANARCONFIG_SEPARATE) { - - BYTE *dib_strip = bits; - BYTE *al_strip = alpha_bits; - - // - loop for strip blocks - - - for (uint32 y = 0; y < height; y += rowsperstrip) { - const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); - - // - loop for channels (planes) - - - for(uint16 sample = 0; sample < samplesperpixel; sample++) { - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), buf, strips * src_line) == -1) { - free(buf); - FreeImage_Unload(alpha); - throw FI_MSG_ERROR_PARSING; - } - - BYTE *dst_strip = dib_strip; - unsigned dst_pitch = dib_pitch; - uint16 ch = sample; - unsigned Bpp = dibBpp; - - if(sample >= chCount) { - // TODO Write to Extra Channel - - // HACK redirect write to temp alpha - if(alpha && sample == chCount) { - - dst_strip = al_strip; - dst_pitch = alpha_pitch; - - ch = 0; - Bpp = alpha_Bpp; - } - else { - break; - } - } - - const unsigned channelOffset = ch * Bpc; - - // - loop for strips in block - - - BYTE *src_line_begin = buf; - BYTE *dst_line_begin = dst_strip; - for (int l = 0; l < strips; l++, src_line_begin += src_line, dst_line_begin -= dst_pitch ) { - // - loop for pixels in strip - - - const BYTE* const src_line_end = src_line_begin + src_line; - for (BYTE *src_bits = src_line_begin, * dst_bits = dst_line_begin; src_bits < src_line_end; src_bits += Bpc, dst_bits += Bpp) { - AssignPixel(dst_bits + channelOffset, src_bits, Bpc); - } // line - - } // strips - - } // channels - - // done with a strip block, incr to the next - dib_strip -= strips * dib_pitch; - al_strip -= strips * alpha_pitch; - - } //< height - - } - - free(buf); - - if (!asCMYK) { - ConvertCMYKtoRGBA(dib); - - // The ICC Profile is invalid, clear it - iccSize = 0; - iccBuf = NULL; - - if(isCMYKA) { - // HACK until we have Extra channels. (ConvertCMYKtoRGBA will then do the work) - - FreeImage_SetChannel(dib, alpha, FICC_ALPHA); - FreeImage_Unload(alpha); - alpha = NULL; - } - else { - FIBITMAP *t = RemoveAlphaChannel(dib); - if(t) { - FreeImage_Unload(dib); - dib = t; - } - else { - FreeImage_OutputMessageProc(s_format_id, "Cannot allocate memory for buffer. CMYK image converted to RGB + pending Alpha"); - } - } - } - - } // !header_only - - } else if(loadMethod == LoadAsGenericStrip) { - // --------------------------------------------------------------------------------- - // Generic loading - // --------------------------------------------------------------------------------- - - // create a new DIB - const uint16 chCount = MIN(samplesperpixel, 4); - dib = CreateImageType(header_only, image_type, width, height, bitspersample, chCount); - 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); - - if (!header_only) { - // calculate the line + pitch (separate for scr & dest) - - const tmsize_t src_line = TIFFScanlineSize(tif); - const tmsize_t dst_line = FreeImage_GetLine(dib); - const unsigned dst_pitch = FreeImage_GetPitch(dib); - const unsigned Bpp = FreeImage_GetBPP(dib) / 8; - const unsigned srcBpp = bitspersample * samplesperpixel / 8; - - // 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 - - BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); - if(buf == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - BOOL bThrowMessage = FALSE; - - if(planar_config == PLANARCONFIG_CONTIG) { - - for (uint32 y = 0; y < height; y += rowsperstrip) { - int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, strips * 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; - */ - } - if(src_line == dst_line) { - // channel count match - for (int l = 0; l < strips; l++) { - memcpy(bits, buf + l * src_line, src_line); - bits -= dst_pitch; - } - } - else { - for (int l = 0; l < strips; l++) { - for(BYTE *pixel = bits, *src_pixel = buf + l * src_line; pixel < bits + dst_pitch; pixel += Bpp, src_pixel += srcBpp) { - AssignPixel(pixel, src_pixel, Bpp); - } - bits -= dst_pitch; - } - } - } - } - else if(planar_config == PLANARCONFIG_SEPARATE) { - - const unsigned Bpc = bitspersample / 8; - BYTE* dib_strip = bits; - // - loop for strip blocks - - - for (uint32 y = 0; y < height; y += rowsperstrip) { - const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); - - // - loop for channels (planes) - - - for(uint16 sample = 0; sample < samplesperpixel; sample++) { - - if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), buf, strips * src_line) == -1) { - // ignore errors as they can be frequent and not really valid errors, especially with fax images - bThrowMessage = TRUE; - } - - if(sample >= chCount) { - // TODO Write to Extra Channel - break; - } - - const unsigned channelOffset = sample * Bpc; - - // - loop for strips in block - - - BYTE* src_line_begin = buf; - BYTE* dst_line_begin = dib_strip; - for (int l = 0; l < strips; l++, src_line_begin += src_line, dst_line_begin -= dst_pitch ) { - - // - loop for pixels in strip - - - const BYTE* const src_line_end = src_line_begin + src_line; - - for (BYTE* src_bits = src_line_begin, * dst_bits = dst_line_begin; src_bits < src_line_end; src_bits += Bpc, dst_bits += Bpp) { - // actually assigns channel - AssignPixel(dst_bits + channelOffset, src_bits, Bpc); - } // line - - } // strips - - } // channels - - // done with a strip block, incr to the next - dib_strip -= strips * dst_pitch; - - } // height - - } - free(buf); - - if(bThrowMessage) { - FreeImage_OutputMessageProc(s_format_id, "Warning: parsing error. Image may be incomplete or contain invalid data !"); - } - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - SwapRedBlue32(dib); -#endif - - } // !header only - - } else if(loadMethod == LoadAsTiled) { - // --------------------------------------------------------------------------------- - // Tiled image loading - // --------------------------------------------------------------------------------- - - uint32 tileWidth, tileHeight; - uint32 src_line = 0; - - // create a new DIB - dib = CreateImageType( header_only, 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"; - } - - // read the tiff lines and save them in the DIB - - if(planar_config == PLANARCONFIG_CONTIG && !header_only) { - - // get the maximum number of bytes required to contain a tile - tmsize_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 saved from up to down - // In a DIB the lines must be saved from down to up - - BYTE *bits = FreeImage_GetScanLine(dib, height - 1); - - 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; - } - -#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR - SwapRedBlue32(dib); -#endif - free(tileBuffer); - } - else if(planar_config == PLANARCONFIG_SEPARATE) { - throw "Separated tiled TIFF images are not supported"; - } - - - } else if(loadMethod == LoadAsLogLuv) { - // --------------------------------------------------------------------------------- - // RGBF LogLuv compressed loading - // --------------------------------------------------------------------------------- - - double stonits; // input conversion to nits - if (!TIFFGetField(tif, TIFFTAG_STONITS, &stonits)) { - stonits = 1; - } - - // create a new DIB - dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel); - if (dib == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - if(planar_config == PLANARCONFIG_CONTIG && !header_only) { - // calculate the line + pitch (separate for scr & dest) - - tmsize_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 - - 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 happen according to the LogLuv specification - throw "Unable to handle PLANARCONFIG_SEPARATE LogLuv images"; - } - - } else if(loadMethod == LoadAsHalfFloat) { - // --------------------------------------------------------------------------------- - // RGBF loading from a half format - // --------------------------------------------------------------------------------- - - // create a new DIB - dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel); - if (dib == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - // fill in the resolution (english or universal) - - ReadResolution(tif, dib); - - if (!header_only) { - - // calculate the line + pitch (separate for scr & dest) - - tmsize_t src_line = TIFFScanlineSize(tif); - unsigned 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) { - uint32 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 half (16-bit) to float (32-bit) - // !!! use OpenEXR half helper class - - half half_value; - - for (uint32 l = 0; l < nrow; l++) { - WORD *src_pixel = (WORD*)(buf + l * src_line); - float *dst_pixel = (float*)bits; - - for(tmsize_t x = 0; x < (tmsize_t)(src_line / sizeof(WORD)); x++) { - half_value.setBits(src_pixel[x]); - dst_pixel[x] = half_value; - } - - bits -= dst_pitch; - } - } - - free(buf); - } - else if(planar_config == PLANARCONFIG_SEPARATE) { - // this use case was never encountered yet - throw "Unable to handle PLANARCONFIG_SEPARATE RGB half float images"; - } - - } // !header only - - } 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 && asCMYK) { - FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK; - } - - // copy TIFF metadata (must be done after FreeImage_Allocate) - - ReadMetadata(tif, dib); - - // copy TIFF thumbnail (must be done after FreeImage_Allocate) - - ReadThumbnail(io, handle, data, tif, dib); - - return (FIBITMAP *)dib; - - } catch (const char *message) { - if(dib) { - FreeImage_Unload(dib); - } - if(message) { - FreeImage_OutputMessageProc(s_format_id, message); - } - return NULL; - } - -} - -// -------------------------------------------------------------------------- - -static BOOL -SaveOneTIFF(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data, unsigned ifd, unsigned ifdCount) { - if (!dib || !handle || !data) { - return FALSE; - } - - try { - fi_TIFFIO *fio = (fi_TIFFIO*)data; - TIFF *out = fio->tif; - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - const uint32 width = FreeImage_GetWidth(dib); - const uint32 height = FreeImage_GetHeight(dib); - const uint16 bitsperpixel = (uint16)FreeImage_GetBPP(dib); - - const FIICCPROFILE* iccProfile = FreeImage_GetICCProfile(dib); - - // setup out-variables based on dib and flag options - - uint16 bitspersample; - uint16 samplesperpixel; - uint16 photometric; - - 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; - 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 { - 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; - // the library converts to and from floating-point XYZ CIE values - if ((flags & TIFF_LOGLUV) == TIFF_LOGLUV) { - photometric = PHOTOMETRIC_LOGLUV; - TIFFSetField(out, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT); - // TIFFSetField(out, TIFFTAG_STONITS, 1.0); // assume unknown - } - else { - // store with default compression (LZW) or with input compression flag - photometric = PHOTOMETRIC_RGB; - } - - } else if (image_type == FIT_RGBAF) { - // 128-bit RGBAF => store with default compression (LZW) or with input compression flag - - samplesperpixel = 4; - bitspersample = bitsperpixel / samplesperpixel; - photometric = PHOTOMETRIC_RGB; - } 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_FILLORDER, FILLORDER_MSB2LSB); - TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, (uint32) -1)); - - // handle metrics - - WriteResolution(out, dib); - - // multi-paging - - if (page >= 0) { - char page_number[20]; - sprintf(page_number, "Page %d", page); - - TIFFSetField(out, TIFFTAG_SUBFILETYPE, (uint32)FILETYPE_PAGE); - TIFFSetField(out, TIFFTAG_PAGENUMBER, (uint16)page, (uint16)0); - TIFFSetField(out, TIFFTAG_PAGENAME, page_number); - - } else { - // is it a thumbnail ? - TIFFSetField(out, TIFFTAG_SUBFILETYPE, (ifd == 0) ? (uint32)0 : (uint32)FILETYPE_REDUCEDIMAGE); - } - - // 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 tag - - WriteCompression(out, bitspersample, samplesperpixel, photometric, flags); - - // metadata - - WriteMetadata(out, dib); - - // thumbnail tag - - if ((ifd == 0) && (ifdCount > 1)) { - uint16 nsubifd = 1; - uint64 subifd[1]; - subifd[0] = 0; - TIFFSetField(out, TIFFTAG_SUBIFD, nsubifd, subifd); - } - - // read the DIB lines from bottom to top - // and save them in the TIF - // ------------------------------------- - - const uint32 pitch = 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 (int y = height - 1; y >= 0; y--) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - - BYTE *p = bits, *b = buffer; - - for(uint32 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 (uint32 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 (uint32 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 (uint32 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; - } - }//< switch (bitsperpixel) - - } else if(image_type == FIT_RGBF && (flags & TIFF_LOGLUV) == TIFF_LOGLUV) { - // 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 (uint32 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 { - // just dump the dib (tiff supports all dib types) - - BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE)); - if(buffer == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - - for (uint32 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); - } - - // write out the directory tag if we wrote a page other than -1 or if we have a thumbnail to write later - - if ( (page >= 0) || ((ifd == 0) && (ifdCount > 1)) ) { - TIFFWriteDirectory(out); - // else: TIFFClose will WriteDirectory - } - - return TRUE; - - } catch(const char *text) { - FreeImage_OutputMessageProc(s_format_id, text); - return FALSE; - } -} - -static BOOL DLL_CALLCONV -Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { - BOOL bResult = FALSE; - - // handle thumbnail as SubIFD - const BOOL bHasThumbnail = (FreeImage_GetThumbnail(dib) != NULL); - const unsigned ifdCount = bHasThumbnail ? 2 : 1; - - FIBITMAP *bitmap = dib; - - for(unsigned ifd = 0; ifd < ifdCount; ifd++) { - // redirect dib to thumbnail for the second pass - if(ifd == 1) { - bitmap = FreeImage_GetThumbnail(dib); - } - - bResult = SaveOneTIFF(io, bitmap, handle, page, flags, data, ifd, ifdCount); - if (!bResult) { - return FALSE; - } - } - - return bResult; -} - -// ========================================================== -// 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} diff --git a/plugins/FreeImage/Source/FreeImage/PluginWBMP.cpp b/plugins/FreeImage/Source/FreeImage/PluginWBMP.cpp deleted file mode 100644 index 2ff8f023c3..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginWBMP.cpp +++ /dev/null @@ -1,372 +0,0 @@ -// ========================================================== -// Wireless Bitmap Format Loader and Writer -// -// 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 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/plugins/FreeImage/Source/FreeImage/PluginXBM.cpp b/plugins/FreeImage/Source/FreeImage/PluginXBM.cpp deleted file mode 100644 index 140029e862..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginXBM.cpp +++ /dev/null @@ -1,399 +0,0 @@ -// ========================================================== -// XBM Loader -// -// Design and implementation by -// - Hervé Drolon -// 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/plugins/FreeImage/Source/FreeImage/PluginXPM.cpp b/plugins/FreeImage/Source/FreeImage/PluginXPM.cpp deleted file mode 100644 index 16db443c47..0000000000 --- a/plugins/FreeImage/Source/FreeImage/PluginXPM.cpp +++ /dev/null @@ -1,487 +0,0 @@ -// ========================================================== -// 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/x-xpixmap"; -} - -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 BOOL DLL_CALLCONV -SupportsNoPixels() { - return TRUE; -} - -// ---------------------------------------------------------- - -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; - - BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; - - //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_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dib = FreeImage_AllocateHeader(header_only, width, height, 8); - } - - //build a map of color chars to rgb values - std::map 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 - - if(header_only) { - // header only mode - return dib; - } - - //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 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 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; - plugin->supports_no_pixels_proc = SupportsNoPixels; -} - diff --git a/plugins/FreeImage/Source/FreeImage/TIFFLogLuv.cpp b/plugins/FreeImage/Source/FreeImage/TIFFLogLuv.cpp deleted file mode 100644 index 124b25f64f..0000000000 --- a/plugins/FreeImage/Source/FreeImage/TIFFLogLuv.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// ========================================================== -// 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" - // 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/plugins/FreeImage/Source/FreeImage/ToneMapping.cpp b/plugins/FreeImage/Source/FreeImage/ToneMapping.cpp deleted file mode 100644 index 33ae08ea59..0000000000 --- a/plugins/FreeImage/Source/FreeImage/ToneMapping.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// ========================================================== -// 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(FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImage/WuQuantizer.cpp b/plugins/FreeImage/Source/FreeImage/WuQuantizer.cpp deleted file mode 100644 index 532fbfc3e6..0000000000 --- a/plugins/FreeImage/Source/FreeImage/WuQuantizer.cpp +++ /dev/null @@ -1,538 +0,0 @@ -/////////////////////////////////////////////////////////////////////// -// 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" - -/////////////////////////////////////////////////////////////////////// - -// Size of a 3D array : 33 x 33 x 33 -#define SIZE_3D 35937 - -// 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(SIZE_3D * sizeof(float)); - wt = (LONG*)malloc(SIZE_3D * sizeof(LONG)); - mr = (LONG*)malloc(SIZE_3D * sizeof(LONG)); - mg = (LONG*)malloc(SIZE_3D * sizeof(LONG)); - mb = (LONG*)malloc(SIZE_3D * 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, SIZE_3D * sizeof(float)); - memset(wt, 0, SIZE_3D * sizeof(LONG)); - memset(mr, 0, SIZE_3D * sizeof(LONG)); - memset(mg, 0, SIZE_3D * sizeof(LONG)); - memset(mb, 0, SIZE_3D * 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; - unsigned 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 < SIZE_3D; i++) { - if ( vwt[i] > max ) max = vwt[i]; - } - 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) { - unsigned 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(SIZE_3D * sizeof(BYTE)); - if (tag == NULL) { - throw FI_MSG_ERROR_MEMORY; - } - memset(tag, 0, SIZE_3D * sizeof(BYTE)); - - 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 (unsigned y = 0; y < height; y++) { - BYTE *new_bits = FreeImage_GetBits(new_dib) + (y * npitch); - - for (unsigned 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/plugins/FreeImage/Source/FreeImage/ZLibInterface.cpp b/plugins/FreeImage/Source/FreeImage/ZLibInterface.cpp deleted file mode 100644 index 3ab6d321f2..0000000000 --- a/plugins/FreeImage/Source/FreeImage/ZLibInterface.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// ========================================================== -// 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/zlib.h" -#include "FreeImage.h" -#include "Utilities.h" -#include "../ZLib/zutil.h" /* must be the last header because of error C3163 in VS2008 (_vsnprintf defined in stdio.h) */ - -/** -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/plugins/FreeImage/Source/FreeImage/tmoColorConvert.cpp b/plugins/FreeImage/Source/FreeImage/tmoColorConvert.cpp deleted file mode 100644 index 367cb13c96..0000000000 --- a/plugins/FreeImage/Source/FreeImage/tmoColorConvert.cpp +++ /dev/null @@ -1,479 +0,0 @@ -// ========================================================== -// 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.
-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; - - 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++) { - 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; - } - const float W = result[0] + result[1] + result[2]; - const 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.
-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; - - 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++) { - 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.
-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; - - const unsigned width = FreeImage_GetWidth(Yxy); - const unsigned height = FreeImage_GetHeight(Yxy); - const 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-5F + 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; - - const unsigned width = FreeImage_GetWidth(src); - const 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; - - const unsigned src_pitch = FreeImage_GetPitch(src); - const 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.0F * red + 0.5F); - dst_pixel[FI_RGBA_GREEN] = (BYTE)(255.0F * green + 0.5F); - dst_pixel[FI_RGBA_BLUE] = (BYTE)(255.0F * blue + 0.5F); - 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; - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - FIBITMAP *dst = FreeImage_AllocateT(FIT_FLOAT, width, height); - if (!dst) return NULL; - - const unsigned src_pitch = FreeImage_GetPitch(src); - const 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++) { - const float L = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, 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-5F + 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 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
-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/plugins/FreeImage/Source/FreeImage/tmoDrago03.cpp b/plugins/FreeImage/Source/FreeImage/tmoDrago03.cpp deleted file mode 100644 index b820bb3577..0000000000 --- a/plugins/FreeImage/Source/FreeImage/tmoDrago03.cpp +++ /dev/null @@ -1,295 +0,0 @@ -// ========================================================== -// 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 : (1.099F * pow(*pixel, fgamma) - 0.099F); - 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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImage/tmoFattal02.cpp b/plugins/FreeImage/Source/FreeImage/tmoFattal02.cpp deleted file mode 100644 index bcd4524523..0000000000 --- a/plugins/FreeImage/Source/FreeImage/tmoFattal02.cpp +++ /dev/null @@ -1,689 +0,0 @@ -// ========================================================== -// 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) { - 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); - - const unsigned width = FreeImage_GetWidth(dib); - const unsigned 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); - - const unsigned 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(unsigned y = 0; y < height; y++) { - // work on line y - for(unsigned 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(unsigned x = 0; x < width; x++) { - // work on column x - for(unsigned y = 2; y < height - 2; y++) { - const unsigned 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) { - FIBITMAP *G = NULL; - - try { - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(H); - if(image_type != FIT_FLOAT) throw(1); - - const unsigned width = FreeImage_GetWidth(H); - const unsigned height = FreeImage_GetHeight(H); - - G = FreeImage_AllocateT(image_type, width, height); - if (!G) throw(1); - - const unsigned 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(unsigned y = 0; y < height; y++) { - const unsigned n = (y == 0 ? 0 : y-1); - const unsigned s = (y+1 == height ? y : y+1); - for(unsigned x = 0; x < width; x++) { - const unsigned w = (x == 0 ? 0 : x-1); - const unsigned e = (x+1 == width ? x : x+1); - // central difference - const float gx = (src_pixel[y*pitch+e] - src_pixel[y*pitch+w]) / divider; // [Hk(x+1, y) - Hk(x-1, y)] / 2**(k+1) - const 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) { - 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]; - - const unsigned width = FreeImage_GetWidth(Gk); - const unsigned height = FreeImage_GetHeight(Gk); - const unsigned 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(unsigned y = 0; y < height; y++) { - for(unsigned 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(unsigned y = 0; y < height; y++) { - for(unsigned 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) { - 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); - - const unsigned width = FreeImage_GetWidth(H); - const unsigned 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); - - const unsigned 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(unsigned y = 0; y < height; y++) { - const unsigned s = (y+1 == height ? y : y+1); - for(unsigned x = 0; x < width; x++) { - const unsigned e = (x+1 == width ? x : x+1); - // forward difference - const unsigned 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(unsigned y0 = 0; y0 < height; y0++) { - for(unsigned x = 0; x < width; x++) { - // backward difference approximation - // divG = Gx(x, y) - Gx(x-1, y) + Gy(x, y) - Gy(x, y-1) - const unsigned index = y0*pitch + x; - divg[index] = gx[index] + gy[index]; - if(x > 0) divg[index] -= gx[index-1]; - if(y0 > 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) { - FIBITMAP *H = NULL; - - try { - // get the luminance channel - FIBITMAP *H = FreeImage_Clone(Y); - if (!H) throw(1); - - const unsigned width = FreeImage_GetWidth(H); - const unsigned height = FreeImage_GetHeight(H); - const unsigned pitch = FreeImage_GetPitch(H); - - // find max & min luminance values - float maxLum = -1e20F, minLum = 1e20F; - - BYTE *bits = (BYTE*)FreeImage_GetBits(H); - for(unsigned y = 0; y < height; y++) { - const float *pixel = (float*)bits; - for(unsigned 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(unsigned y0 = 0; y0 < height; y0++) { - float *pixel = (float*)bits; - for(unsigned 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) { - const unsigned width = FreeImage_GetWidth(Y); - const unsigned height = FreeImage_GetHeight(Y); - const unsigned pitch = FreeImage_GetPitch(Y); - - BYTE *bits = (BYTE*)FreeImage_GetBits(Y); - for(unsigned y = 0; y < height; y++) { - float *pixel = (float*)bits; - for(unsigned 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 unsigned 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 - const unsigned width = FreeImage_GetWidth(H); - const unsigned height = FreeImage_GetHeight(H); - unsigned 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; - - if (!FreeImage_HasPixels(dib)) return NULL; - - try { - - // 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 - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - - const unsigned rgb_pitch = FreeImage_GetPitch(src); - const unsigned 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(unsigned y = 0; y < height; y++) { - float *Lin = (float*)bits_yin; - float *Lout = (float*)bits_yout; - float *color = (float*)bits; - for(unsigned x = 0; x < width; x++) { - for(unsigned 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/plugins/FreeImage/Source/FreeImage/tmoReinhard05.cpp b/plugins/FreeImage/Source/FreeImage/tmoReinhard05.cpp deleted file mode 100644 index 969aa4c950..0000000000 --- a/plugins/FreeImage/Source/FreeImage/tmoReinhard05.cpp +++ /dev/null @@ -1,260 +0,0 @@ -// ========================================================== -// 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
-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 (!FreeImage_HasPixels(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
-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/plugins/FreeImage/Source/FreeImageIO.h b/plugins/FreeImage/Source/FreeImageIO.h deleted file mode 100644 index b251d474f6..0000000000 --- a/plugins/FreeImage/Source/FreeImageIO.h +++ /dev/null @@ -1,48 +0,0 @@ -// ========================================================== -// 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/plugins/FreeImage/Source/FreeImageLib/FreeImageLib.dsp b/plugins/FreeImage/Source/FreeImageLib/FreeImageLib.dsp deleted file mode 100644 index 4f65350c38..0000000000 --- a/plugins/FreeImage/Source/FreeImageLib/FreeImageLib.dsp +++ /dev/null @@ -1,448 +0,0 @@ -# Microsoft Developer Studio Project File - Name="FreeImageLib" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=FreeImageLib - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "FreeImageLib.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "FreeImageLib.mak" CFG="FreeImageLib - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "FreeImageLib - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "FreeImageLib - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "FreeImageLib - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\\" /I "..\ZLib" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "FREEIMAGE_LIB" /YX /FD /c -# ADD BASE RSC /l 0x413 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"Release\FreeImage.lib" -# Begin Special Build Tool -SOURCE="$(InputPath)" -PostBuild_Cmds=copy Release\FreeImage.lib ..\..\Dist copy ..\FreeImage.h ..\..\Dist -# End Special Build Tool - -!ELSEIF "$(CFG)" == "FreeImageLib - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\\" /I "..\ZLib" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "FREEIMAGE_LIB" /YX /FD /GZ /c -# ADD BASE RSC /l 0x413 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"Debug\FreeImaged.lib" -# Begin Special Build Tool -SOURCE="$(InputPath)" -PostBuild_Cmds=copy Debug\FreeImaged.lib ..\..\Dist copy ..\FreeImage.h ..\..\Dist -# End Special Build Tool - -!ENDIF - -# Begin Target - -# Name "FreeImageLib - Win32 Release" -# Name "FreeImageLib - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Group "Quantizers" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\FreeImage\NNQuantizer.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\WuQuantizer.cpp -# End Source File -# End Group -# Begin Group "Conversion" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\FreeImage\Conversion.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\Conversion16_555.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\Conversion16_565.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\Conversion24.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\Conversion32.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\Conversion4.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\Conversion8.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\ConversionRGBF.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\ConversionType.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\Halftoning.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\tmoColorConvert.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\tmoDrago03.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\tmoReinhard05.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\ToneMapping.cpp -# End Source File -# End Group -# Begin Group "Plugins" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\FreeImage\Plugin.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginBMP.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginCUT.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginDDS.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginG3.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginGIF.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginHDR.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginICO.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginIFF.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginJPEG.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginKOALA.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginMNG.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginPCD.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginPCX.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginPNG.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginPNM.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginPSD.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginRAS.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginSGI.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginTARGA.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginTIFF.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginWBMP.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginXBM.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PluginXPM.cpp -# End Source File -# End Group -# Begin Group "DeprecationMgr" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\DeprecationManager\DeprecationMgr.cpp -# End Source File -# End Group -# Begin Group "MultiPaging" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\FreeImage\CacheFile.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\MultiPage.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\ZLibInterface.cpp -# End Source File -# End Group -# Begin Group "Metadata" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\Metadata\Exif.cpp -# End Source File -# Begin Source File - -SOURCE=..\Metadata\FIRational.cpp -# End Source File -# Begin Source File - -SOURCE=..\Metadata\FreeImageTag.cpp -# End Source File -# Begin Source File - -SOURCE=..\Metadata\IPTC.cpp -# End Source File -# Begin Source File - -SOURCE=..\Metadata\TagConversion.cpp -# End Source File -# Begin Source File - -SOURCE=..\Metadata\TagLib.cpp -# End Source File -# Begin Source File - -SOURCE=..\Metadata\XTIFF.cpp -# End Source File -# End Group -# Begin Source File - -SOURCE=..\FreeImage\BitmapAccess.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\ColorLookup.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\FreeImage.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\FreeImageIO.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\GetType.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\MemoryIO.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImage\PixelAccess.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=..\CacheFile.h -# End Source File -# Begin Source File - -SOURCE=..\DeprecationManager\DeprecationMgr.h -# End Source File -# Begin Source File - -SOURCE=..\Metadata\FIRational.h -# End Source File -# Begin Source File - -SOURCE=..\FreeImage.h -# End Source File -# Begin Source File - -SOURCE=..\FreeImageIO.h -# End Source File -# Begin Source File - -SOURCE=..\Metadata\FreeImageTag.h -# End Source File -# Begin Source File - -SOURCE=..\Plugin.h -# End Source File -# Begin Source File - -SOURCE=..\Quantizers.h -# End Source File -# Begin Source File - -SOURCE=..\ToneMapping.h -# End Source File -# Begin Source File - -SOURCE=..\Utilities.h -# End Source File -# End Group -# Begin Group "Toolkit Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\FreeImageToolkit\BSplineRotate.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\Channels.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\ClassicRotate.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\Colors.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\CopyPaste.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\Display.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\Flip.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\JPEGTransform.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\Rescale.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\Resize.cpp -# End Source File -# Begin Source File - -SOURCE=..\FreeImageToolkit\Resize.h -# End Source File -# End Group -# Begin Source File - -SOURCE=..\..\Whatsnew.txt -# End Source File -# End Target -# End Project diff --git a/plugins/FreeImage/Source/FreeImageLib/FreeImageLib.vcproj b/plugins/FreeImage/Source/FreeImageLib/FreeImageLib.vcproj deleted file mode 100644 index bac460eb48..0000000000 --- a/plugins/FreeImage/Source/FreeImageLib/FreeImageLib.vcproj +++ /dev/null @@ -1,411 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/FreeImage/Source/FreeImageLib/FreeImageLib.vpj b/plugins/FreeImage/Source/FreeImageLib/FreeImageLib.vpj deleted file mode 100644 index 378f3f2311..0000000000 --- a/plugins/FreeImage/Source/FreeImageLib/FreeImageLib.vpj +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/FreeImage/Source/FreeImageToolkit/BSplineRotate.cpp b/plugins/FreeImage/Source/FreeImageToolkit/BSplineRotate.cpp deleted file mode 100644 index e4be1d0bd2..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/BSplineRotate.cpp +++ /dev/null @@ -1,730 +0,0 @@ -// ========================================================== -// 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 -#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.
- 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; - - if (!FreeImage_HasPixels(dib)) return 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/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp deleted file mode 100644 index f6e6c5509c..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp +++ /dev/null @@ -1,488 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImageToolkit/ClassicRotate.cpp b/plugins/FreeImage/Source/FreeImageToolkit/ClassicRotate.cpp deleted file mode 100644 index d38d8c1bcd..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/ClassicRotate.cpp +++ /dev/null @@ -1,917 +0,0 @@ -// ========================================================== -// Bitmap rotation by means of 3 shears. -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Thorsten Radde (support@IdealSoftware.com) -// - 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! -// ========================================================== - -/* - ============================================================ - 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 - -// -------------------------------------------------------------------------- - -/** -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 void -HorizontalSkewT(FIBITMAP *src, FIBITMAP *dst, int row, int iOffset, double weight, const void *bkcolor = NULL) { - int iXPos; - - const unsigned src_width = FreeImage_GetWidth(src); - const 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(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 - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - // calculate the number of samples per pixel - const 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); - } - AssignPixel((BYTE*)&pxlOldLeft[0], (BYTE*)bkcolor, bytespp); - } else { - if(iOffset > 0) { - memset(dst_bits, 0, iOffset * bytespp); - } - memset(&pxlOldLeft[0], 0, bytespp); - } - - for(unsigned i = 0; i < src_width; i++) { - // loop through row pixels - AssignPixel((BYTE*)&pxlSrc[0], (BYTE*)src_bits, bytespp); - // calculate weights - for(unsigned j = 0; j < samples; j++) { - pxlLeft[j] = static_cast(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(unsigned j = 0; j < samples; j++) { - pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]); - } - AssignPixel((BYTE*)&dst_bits[iXPos*bytespp], (BYTE*)&pxlSrc[0], bytespp); - } - // save leftover for next pixel in scan - AssignPixel((BYTE*)&pxlOldLeft[0], (BYTE*)&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 - AssignPixel((BYTE*)dst_bits, (BYTE*)&pxlOldLeft[0], bytespp); - - // clear to the right of the skewed line with background - dst_bits += bytespp; - if(bkcolor) { - for(unsigned 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(src, dst, row, iOffset, dWeight, bkcolor); - break; - } - break; - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - HorizontalSkewT(src, dst, row, iOffset, dWeight, bkcolor); - break; - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - HorizontalSkewT(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 void -VerticalSkewT(FIBITMAP *src, FIBITMAP *dst, int col, int iOffset, double weight, const void *bkcolor = NULL) { - 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(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 - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - // calculate the number of samples per pixel - const unsigned samples = bytespp / sizeof(T); - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - const 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(unsigned i = 0; i < src_height; i++) { - // loop through column pixels - AssignPixel((BYTE*)(&pxlSrc[0]), src_bits, bytespp); - // calculate weights - for(unsigned j = 0; j < samples; j++) { - pxlLeft[j] = static_cast(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(unsigned j = 0; j < samples; j++) { - pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]); - } - dst_bits = FreeImage_GetScanLine(dst, iYPos) + index; - AssignPixel(dst_bits, (BYTE*)(&pxlSrc[0]), bytespp); - } - // save leftover for next pixel in scan - AssignPixel((BYTE*)(&pxlOldLeft[0]), (BYTE*)(&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 - AssignPixel((BYTE*)(dst_bits), (BYTE*)(&pxlOldLeft[0]), bytespp); - - // clear below skewed line with background - if(bkcolor) { - while(++iYPos < (int)dst_height) { - dst_bits += dst_pitch; - AssignPixel((BYTE*)(dst_bits), (BYTE*)(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(src, dst, col, iOffset, dWeight, bkcolor); - break; - } - break; - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - VerticalSkewT(src, dst, col, iOffset, dWeight, bkcolor); - break; - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - VerticalSkewT(src, dst, col, iOffset, dWeight, bkcolor); - break; - } -} - -/** -Rotates an image by 90 degrees (counter clockwise). -Precise rotation, no filters required.
-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) { - - const unsigned bpp = FreeImage_GetBPP(src); - - const unsigned src_width = FreeImage_GetWidth(src); - const unsigned src_height = FreeImage_GetHeight(src); - const unsigned dst_width = src_height; - const unsigned 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 - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - switch(image_type) { - case FIT_BITMAP: - if(bpp == 1) { - // speedy rotate for BW images - - BYTE *bsrc = FreeImage_GetBits(src); - BYTE *bdest = FreeImage_GetBits(dst); - - BYTE *dbitsmax = bdest + dst_height * dst_pitch - 1; - - for(unsigned y = 0; y < src_height; y++) { - // figure out the column we are going to be copying to - const div_t div_r = div(y, 8); - // set bit pos of src column byte - const BYTE bitpos = (BYTE)(128 >> div_r.rem); - BYTE *srcdisp = bsrc + y * src_pitch; - for(unsigned x = 0; x < src_pitch; x++) { - // get source bits - BYTE *sbits = srcdisp + x; - // get destination column - BYTE *nrow = bdest + (dst_height - 1 - (x * 8)) * dst_pitch + div_r.quot; - for (int z = 0; z < 8; z++) { - // get destination byte - 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. - - 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) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - // for all image blocks of RBLOCK*RBLOCK pixels - - // x-segment - for(unsigned xs = 0; xs < dst_width; xs += RBLOCK) { - // y-segment - for(unsigned ys = 0; ys < dst_height; ys += RBLOCK) { - for(unsigned y = ys; y < MIN(dst_height, ys + RBLOCK); y++) { // do rotation - const unsigned 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(unsigned x = xs; x < MIN(dst_width, xs + RBLOCK); x++) { - // dst.SetPixel(x, y, src.GetPixel(y2, x)); - AssignPixel(dst_bits, src_bits, bytespp); - 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 - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(unsigned y = 0; y < dst_height; y++) { - BYTE *src_bits = bsrc + (src_width - 1 - y) * bytespp; - BYTE *dst_bits = bdest + (y * dst_pitch); - for(unsigned x = 0; x < dst_width; x++) { - AssignPixel(dst_bits, src_bits, bytespp); - 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; - - const int bpp = FreeImage_GetBPP(src); - - const int src_width = FreeImage_GetWidth(src); - const int src_height = FreeImage_GetHeight(src); - const int dst_width = src_width; - const 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)); - } - } - break; - } - // else if ((bpp == 8) || (bpp == 24) || (bpp == 32)) FALL TROUGH - 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 - const 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) - AssignPixel(dst_bits, src_bits, bytespp); - src_bits += bytespp; - dst_bits -= bytespp; - } - } - } - break; - } - - return dst; -} - -/** -Rotates an image by 270 degrees (counter clockwise). -Precise rotation, no filters required.
-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 x2, dlineup; - - const unsigned bpp = FreeImage_GetBPP(src); - - const unsigned src_width = FreeImage_GetWidth(src); - const unsigned src_height = FreeImage_GetHeight(src); - const unsigned dst_width = src_height; - const unsigned 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 - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - switch(image_type) { - case FIT_BITMAP: - if(bpp == 1) { - // speedy rotate for BW images - - BYTE *bsrc = FreeImage_GetBits(src); - BYTE *bdest = FreeImage_GetBits(dst); - BYTE *dbitsmax = bdest + dst_height * dst_pitch - 1; - dlineup = 8 * dst_pitch - dst_width; - - for(unsigned y = 0; y < src_height; y++) { - // figure out the column we are going to be copying to - const div_t div_r = div(y + dlineup, 8); - // set bit pos of src column byte - const BYTE bitpos = (BYTE)(1 << div_r.rem); - const BYTE *srcdisp = bsrc + y * src_pitch; - for(unsigned x = 0; x < src_pitch; x++) { - // get source bits - const BYTE *sbits = srcdisp + x; - // get destination column - BYTE *nrow = bdest + (x * 8) * dst_pitch + dst_pitch - 1 - div_r.quot; - for(unsigned z = 0; z < 8; z++) { - // get destination byte - 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. - - 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) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - // for all image blocks of RBLOCK*RBLOCK pixels - - // x-segment - for(unsigned xs = 0; xs < dst_width; xs += RBLOCK) { - // y-segment - for(unsigned ys = 0; ys < dst_height; ys += RBLOCK) { - for(unsigned 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(unsigned y = ys; y < MIN(dst_height, ys + RBLOCK); y++) { - // dst.SetPixel(x, y, src.GetPixel(y, x2)); - AssignPixel(dst_bits, src_bits, bytespp); - 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 - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(unsigned 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(unsigned x = 0; x < dst_width; x++) { - AssignPixel(dst_bits, src_bits, bytespp); - 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; - - const unsigned bpp = FreeImage_GetBPP(src); - - const double dRadAngle = dAngle * ROTATE_PI / double(180); // Angle in radians - const double dSinE = sin(dRadAngle); - const double dTan = tan(dRadAngle / 2); - - const unsigned src_width = FreeImage_GetWidth(src); - const unsigned src_height = FreeImage_GetHeight(src); - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - // Calc first shear (horizontal) destination image dimensions - const unsigned width_1 = src_width + unsigned((double)src_height * fabs(dTan) + 0.5); - const 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 - const 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 - const unsigned width_3 = unsigned(double(src_height) * fabs(dSinE) + double(src_width) * cos(dRadAngle) + 0.5) + 1; - const 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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImageToolkit/Colors.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Colors.cpp deleted file mode 100644 index 8b9bbd6482..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Colors.cpp +++ /dev/null @@ -1,967 +0,0 @@ -// ========================================================== -// Color manipulation routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Carsten Klein (c.klein@datagis.com) -// - 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" - -// ---------------------------------------------------------- -// 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) { - - if (!FreeImage_HasPixels(src)) return FALSE; - - unsigned i, x, y, k; - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - const unsigned bpp = FreeImage_GetBPP(src); - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - if(image_type == FIT_BITMAP) { - 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 < height; y++) { - BYTE *bits = FreeImage_GetScanLine(src, y); - - for (x = 0; x < FreeImage_GetLine(src); x++) { - bits[x] = ~bits[x]; - } - } - } - - break; - } - - case 24 : - case 32 : - { - // Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / width; - - for(y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < width; x++) { - for(k = 0; k < bytespp; k++) { - bits[k] = ~bits[k]; - } - bits += bytespp; - } - } - - break; - } - default: - return FALSE; - } - } - else if ((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) { - // Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) - const unsigned wordspp = (FreeImage_GetLine(src) / width) / sizeof(WORD); - - for(y = 0; y < height; y++) { - WORD *bits = (WORD*)FreeImage_GetScanLine(src, y); - for(x = 0; x < width; x++) { - for(k = 0; k < wordspp; k++) { - bits[k] = ~bits[k]; - } - bits += wordspp; - } - } - } - else { - // anything else ... - return FALSE; - } - - 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.
-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.
-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. The size of 'LUT' is assumed to be 256. -@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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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
-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 (!FreeImage_HasPixels(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
-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 (!FreeImage_HasPixels(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. The size of 'histo' is assumed to be 256. -@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 (!FreeImage_HasPixels(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(). The - size of 'LUT' is assumed to be 256. - @param brightness Percentage brightness value where -100 <= brightness <= 100
- 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
- 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
- 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
- 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 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 (!FreeImage_HasPixels(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 count colors specified in srccolors to - these specified in dstcolors. Thereby, color srccolors[N], - if found in the image, will be replaced by color dstcolors[N]. If - parameter swap is TRUE, additionally all colors specified in - dstcolors are also mapped to these specified in srccolors. For - high color images, the actual image data will be modified whereas, for - palletized images only the palette will be changed.
- - The function returns the number of pixels changed or zero, if no pixels were - changed. - - Both arrays srccolors and dstcolors are assumed not to hold less - than count colors.
- - 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).
- - Note, that this behaviour is different from what FreeImage_ApplyPaletteIndexMapping() - does, which modifies the actual image data on palletized images. - - @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 - srccolors and dstcolors. - @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 (!FreeImage_HasPixels(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 color_a and 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.
- - Note, that this behaviour is different from what FreeImage_SwapPaletteIndices() - does, which modifies the actual image data on palletized images.
- - This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:
- return FreeImage_ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, TRUE); - - @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 count palette indices specified in - srcindices to these specified in dstindices. Thereby, index - srcindices[N], if present in the image, will be replaced by index - dstindices[N]. If parameter swap is TRUE, additionally all indices - specified in dstindices are also mapped to these specified in - srcindices.
- - The function returns the number of pixels changed or zero, if no pixels were - changed. - - Both arrays srcindices and dstindices are assumed not to hold less - than count indices.
- - Note, that this behaviour is different from what FreeImage_ApplyColorMapping() - does, which modifies the actual image data on palletized images. - - @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 - srcindices and dstindices. - @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 (!FreeImage_HasPixels(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 index_a and - index_b on a palletized image. Therefore, not the palette, but the - actual image data will be modified.
- - Note, that this behaviour is different from what FreeImage_SwapColors() does - on palletized images, which only swaps the colors in the palette.
- - This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:
- return FreeImage_ApplyPaletteIndexMapping(dib, index_a, index_b, 1, TRUE); - - @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/plugins/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp b/plugins/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp deleted file mode 100644 index 753fdc736e..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp +++ /dev/null @@ -1,747 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp deleted file mode 100644 index 3e4807042d..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// ========================================================== -// 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:
-output = alpha * foreground + (1-alpha) * background
-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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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] + 127) / 255 ); - bits[FI_RGBA_GREEN] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_GREEN] + 127) / 255 ); - bits[FI_RGBA_RED] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_RED] + 127) / 255 ); - } - } - } - return TRUE; -} - diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Filters.h b/plugins/FreeImage/Source/FreeImageToolkit/Filters.h deleted file mode 100644 index 7a45c493f4..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Filters.h +++ /dev/null @@ -1,287 +0,0 @@ -// ========================================================== -// 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.
- Filters used in this library have been mainly taken from the following references :
-Main reference :
-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 - -Heckbert references :
-
    -
  • Oppenheim A.V., Schafer R.W., Digital Signal Processing, Prentice-Hall, 1975 -
  • Hamming R.W., Digital Filters, Prentice-Hall, Englewood Cliffs, NJ, 1983 -
  • Pratt W.K., Digital Image Processing, John Wiley and Sons, 1978 -
  • 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. -
- -*/ -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
- Box, pulse, Fourier window, 1st order (constant) b-spline.

- - Reference :
- Glassner A.S., Principles of digital image synthesis. Morgan Kaufmann Publishers, Inc, San Francisco, Vol. 2, 1995 -*/ -class CBoxFilter : public CGenericFilter -{ -public: - /** - Constructor
- 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
- - 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.

- - Reference :
- 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
- 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
- - When using CBicubicFilter filters, you have to set parameters b and c such that
- b + 2 * c = 1
- in order to use the numerically most accurate filter.
- This gives for b = 0 the maximum value for c = 0.5, which is the Catmull-Rom - spline and a good suggestion for sharpness.

- - - References :
-
    -
  • 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. -
  • 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. -
- -*/ -class CCatmullRomFilter : public CGenericFilter -{ -public: - - /** - Constructor
- 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
- - 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.

- -*/ -class CLanczos3Filter : public CGenericFilter -{ -public: - /** - Constructor
- 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
- -*/ -class CBSplineFilter : public CGenericFilter -{ -public: - - /** - Constructor
- 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
- 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/plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp deleted file mode 100644 index c7898a7813..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImageToolkit/JPEGTransform.cpp b/plugins/FreeImage/Source/FreeImageToolkit/JPEGTransform.cpp deleted file mode 100644 index 2d7399dcb2..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/JPEGTransform.cpp +++ /dev/null @@ -1,410 +0,0 @@ -// ========================================================== -// 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 - -#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 - - // Prepare transformation workspace - // Fails right away if perfect flag is TRUE and transformation is not perfect - if ( !jtransform_request_workspace(&srcinfo, &transfoptions)) { - FreeImage_OutputMessageProc(FIF_JPEG, "Transformation is not perfect"); - throw(1); - } - - // 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/plugins/FreeImage/Source/FreeImageToolkit/MultigridPoissonSolver.cpp b/plugins/FreeImage/Source/FreeImageToolkit/MultigridPoissonSolver.cpp deleted file mode 100644 index a31961447a..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/MultigridPoissonSolver.cpp +++ /dev/null @@ -1,505 +0,0 @@ -// ========================================================== -// 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 multigrid 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 (!FreeImage_HasPixels(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++; - if ((1 << size) < MAX(width, height)) { - size++; - } - // size must be of the form 2^j + 1 for some integer j - size = 1 + (1 << size); - - // 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/plugins/FreeImage/Source/FreeImageToolkit/Rescale.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Rescale.cpp deleted file mode 100644 index e79e5f456c..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Rescale.cpp +++ /dev/null @@ -1,231 +0,0 @@ -// ========================================================== -// 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 (!FreeImage_HasPixels(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(std::nothrow) CBoxFilter(); - break; - case FILTER_BICUBIC: - pFilter = new(std::nothrow) CBicubicFilter(); - break; - case FILTER_BILINEAR: - pFilter = new(std::nothrow) CBilinearFilter(); - break; - case FILTER_BSPLINE: - pFilter = new(std::nothrow) CBSplineFilter(); - break; - case FILTER_CATMULLROM: - pFilter = new(std::nothrow) CCatmullRomFilter(); - break; - case FILTER_LANCZOS3: - pFilter = new(std::nothrow) CLanczos3Filter(); - break; - } - - if (!pFilter) { - return NULL; - } - - 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); - FreeImage_Unload(src24); src24 = NULL; - // color quantize to 8-bit - dst = FreeImage_ColorQuantize(dst24, FIQ_NNQUANT); - // free and return - 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 (!FreeImage_HasPixels(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/plugins/FreeImage/Source/FreeImageToolkit/Resize.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Resize.cpp deleted file mode 100644 index 5421bd47ab..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Resize.cpp +++ /dev/null @@ -1,656 +0,0 @@ -// ========================================================== -// 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, unsigned uDstSize, unsigned uSrcSize) { - unsigned u; - double dWidth; - double dFScale = 1.0; - const double dFilterWidth = pFilter->GetWidth(); - - // scale factor - const 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 - const double dOffset = (0.5 / dScale) - 0.5; - - - for(u = 0; u < m_LineLength; u++) { - // scan through line of contributions - const 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 - const 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(unsigned 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
- This class performs filtered zoom. It scales an image to the desired dimensions with - any of the CGenericFilter derived filter class.
- It works with 8-, 24- and 32-bit buffers.

- - References :
- [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) { - unsigned src_width = FreeImage_GetWidth(src); - unsigned 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(unsigned 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(unsigned 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. - --- The theory --- - Try to minimize calculations by counting the number of convolution multiplies - if(dst_width*src_height <= src_width*dst_height) { - // xy filtering - } else { - // yx filtering - } - --- The practice --- - Try to minimize calculations by counting the number of vertical convolutions (the most time consuming task) - if(dst_width*dst_height <= src_width*dst_height) { - // xy filtering - } else { - // yx filtering - } - */ - - if(dst_width <= 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: - { - const BYTE *src_bits = FreeImage_GetBits(src); - BYTE *dst_bits = FreeImage_GetBits(dst); - memcpy(dst_bits, src_bits, dst_height * FreeImage_GetPitch(dst)); - } - break; - } - } - else { - - // 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 - const 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; - const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(x, i-iLeft); - - const 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)CLAMP((int)(value + 0.5), 0, 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) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(unsigned y = 0; y < dst_height; y++) { - // scale each row - const 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 = 32 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(x, i-iLeft); - - unsigned index = i * bytespp; // pixel index - 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)CLAMP((int)(value[j] + 0.5), 0, 0xFF); - } - - 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) - const unsigned wordspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(WORD); - - for(unsigned y = 0; y < dst_height; y++) { - // scale each row - const 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 = 64 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(x, i-iLeft); - - unsigned index = i * wordspp; // pixel index - 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)CLAMP((int)(value[j] + 0.5), 0, 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) - const unsigned floatspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(float); - - for(unsigned y = 0; y < dst_height; y++) { - // scale each row - const 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 = 128 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(x, i-iLeft); - - unsigned index = i * floatspp; // pixel index - 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: - { - const BYTE *src_bits = FreeImage_GetBits(src); - BYTE *dst_bits = FreeImage_GetBits(dst); - memcpy(dst_bits, src_bits, dst_height * FreeImage_GetPitch(dst)); - } - break; - } - - } - else { - - // 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; - - const unsigned src_pitch = FreeImage_GetPitch(src); - const 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; - const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary - - BYTE *src_bits = FreeImage_GetScanLine(src, iLeft); - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(y, i-iLeft); - - const 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)CLAMP((int)(value + 0.5), 0, 0xFF); - - 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) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - for(unsigned x = 0; x < dst_width; x++) { - const unsigned index = x * bytespp; // pixel index - - // 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 = 32 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary - - const BYTE *src_bits = FreeImage_GetScanLine(src, iLeft) + index; - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const 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)CLAMP((int)(value[j] + 0.5), 0, 0xFF); - } - - 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) - const unsigned wordspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(WORD); - - const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(WORD); - const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(WORD); - - for(unsigned x = 0; x < dst_width; x++) { - const unsigned index = x * wordspp; // pixel index - - // 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 = 64 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary - - const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, iLeft) + index; - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const 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)CLAMP((int)(value[j] + 0.5), 0, 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) - const unsigned floatspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(float); - - const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(float); - const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(float); - - for(unsigned x = 0; x < dst_width; x++) { - const unsigned index = x * floatspp; // pixel index - - // 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 = 128 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary - - const float *src_bits = (float*)FreeImage_GetScanLine(src, iLeft) + index; - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const 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/plugins/FreeImage/Source/FreeImageToolkit/Resize.h b/plugins/FreeImage/Source/FreeImageToolkit/Resize.h deleted file mode 100644 index 0d5d0b451a..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Resize.h +++ /dev/null @@ -1,145 +0,0 @@ -// ========================================================== -// 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.
- This class stores contribution information for an entire line (row or column). -*/ -class CWeightsTable -{ -/** - Sampled filter weight table.
- Contribution information for a single pixel -*/ -typedef struct { - /// Normalized weights of neighboring pixels - double *Weights; - /// Bounds of source pixels window - unsigned Left, Right; -} Contribution; - -private: - /// Row (or column) of contribution weights - Contribution *m_WeightTable; - /// Filter window size (of affecting source pixels) - unsigned m_WindowSize; - /// Length of line (no. of rows / cols) - unsigned m_LineLength; - -public: - /** - Constructor
- Allocate and compute the weights table - @param pFilter Filter used for upsampling or downsampling - @param uDstSize Length (in pixels) of the destination line buffer - @param uSrcSize Length (in pixels) of the source line buffer - */ - CWeightsTable(CGenericFilter *pFilter, unsigned uDstSize, unsigned uSrcSize); - - /** - Destructor
- 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(unsigned dst_pos, unsigned 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 - */ - unsigned getLeftBoundary(unsigned 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 - */ - unsigned getRightBoundary(unsigned dst_pos) { - return m_WeightTable[dst_pos].Right; - } -}; - -// --------------------------------------------- - -/** - CResizeEngine
- This class performs filtered zoom. It scales an image to the desired dimensions with - any of the CGenericFilter derived filter class.
- It works with 8-, 24- and 32-bit buffers.

- - References :
- [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/plugins/FreeImage/Source/LibJPEG/ansi2knr.c b/plugins/FreeImage/Source/LibJPEG/ansi2knr.c deleted file mode 100644 index dcfb5d9255..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/ansi2knr.c +++ /dev/null @@ -1,739 +0,0 @@ -/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. */ - -/*$Id: ansi2knr.c,v 1.6 2012/01/29 12:23:24 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, <>) - * 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 - * . 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 - - 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 - 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 - 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 - ) - 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 - - 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 ; - 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 ; - properly erase prototype args in function parameters, - contributed by Jim Avera ; - 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 -#endif - -#include -#include - -#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 -# else -# include -# endif - -#else /* not HAVE_CONFIG_H */ - -/* Otherwise do it the hard way */ - -# ifdef BSD -# include -# else -# ifdef VMS - extern int strlen(), strncmp(); -# else -# include -# endif -# endif - -#endif /* not HAVE_CONFIG_H */ - -#if STDC_HEADERS -# include -#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 -# 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/plugins/FreeImage/Source/LibJPEG/cderror.h b/plugins/FreeImage/Source/LibJPEG/cderror.h deleted file mode 100644 index e19c475c5c..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/cderror.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * cderror.h - * - * Copyright (C) 1994-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 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_EMPTY, "Empty BMP image") -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/plugins/FreeImage/Source/LibJPEG/cdjpeg.c b/plugins/FreeImage/Source/LibJPEG/cdjpeg.c deleted file mode 100644 index 89fe633728..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/cdjpeg.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * 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 /* to declare isupper(), tolower() */ -#ifdef NEED_SIGNAL_CATCHER -#include /* to declare signal() */ -#endif -#ifdef USE_SETMODE -#include /* to declare setmode()'s parameter macros */ -/* If you have setmode() but not , just delete this line: */ -#include /* 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/plugins/FreeImage/Source/LibJPEG/cdjpeg.h b/plugins/FreeImage/Source/LibJPEG/cdjpeg.h deleted file mode 100644 index ed024ac3ae..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/cdjpeg.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/change.log b/plugins/FreeImage/Source/LibJPEG/change.log deleted file mode 100644 index ce71abd2eb..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/change.log +++ /dev/null @@ -1,346 +0,0 @@ -CHANGE LOG for Independent JPEG Group's JPEG software - - -Version 8d 15-Jan-2012 ------------------------ - -Add cjpeg -rgb option to create RGB JPEG files. -Using this switch suppresses the conversion from RGB -colorspace input to the default YCbCr JPEG colorspace. -This feature allows true lossless JPEG coding of RGB color images. -The recommended command for this purpose is currently -cjpeg -rgb -block 1 -arithmetic. -SmartScale capable decoder (introduced with IJG JPEG 8) required. -Thank to Michael Koch for the initial suggestion. - -Add option to disable the region adjustment in the transupp crop code. -Thank to Jeffrey Friedl for the suggestion. - -Thank to Richard Jones and Edd Dawson for various minor corrections. - -Thank to Akim Demaille for configure.ac cleanup. - - -Version 8c 16-Jan-2011 ------------------------ - -Add option to compression library and cjpeg (-block N) to use -different DCT block size. -All N from 1 to 16 are possible. Default is 8 (baseline format). -Larger values produce higher compression, -smaller values produce higher quality. -SmartScale capable decoder (introduced with IJG JPEG 8) required. - - -Version 8b 16-May-2010 ------------------------ - -Repair problem in new memory source manager with corrupt JPEG data. -Thank to Ted Campbell and Samuel Chun for the report. - -Repair problem in Makefile.am test target. -Thank to anonymous user for the report. - -Support MinGW installation with automatic configure. -Thank to Volker Grabsch for the suggestion. - - -Version 8a 28-Feb-2010 ------------------------ - -Writing tables-only datastreams via jpeg_write_tables works again. - -Support 32-bit BMPs (RGB image with Alpha channel) for read in cjpeg. -Thank to Brett Blackham for the suggestion. - -Improve accuracy in floating point IDCT calculation. -Thank to Robert Hooke for the hint. - - -Version 8 10-Jan-2010 ----------------------- - -jpegtran now supports the same -scale option as djpeg for "lossless" resize. -An implementation of the JPEG SmartScale extension is required for this -feature. A (draft) specification of the JPEG SmartScale extension is -available as a contributed document at ITU and ISO. Revision 2 or later -of the document is required (latest document version is Revision 3). -The SmartScale extension will enable more features beside lossless resize -in future implementations, as described in the document (new compression -options). - -Add sanity check in BMP reader module to avoid cjpeg crash for empty input -image (thank to Isaev Ildar of ISP RAS, Moscow, RU for reporting this error). - -Add data source and destination managers for read from and write to -memory buffers. New API functions jpeg_mem_src and jpeg_mem_dest. -Thank to Roberto Boni from Italy for the suggestion. - - -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/plugins/FreeImage/Source/LibJPEG/cjpeg.c b/plugins/FreeImage/Source/LibJPEG/cjpeg.c deleted file mode 100644 index a999eeef1c..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/cjpeg.c +++ /dev/null @@ -1,643 +0,0 @@ -/* - * cjpeg.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2003-2011 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 /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* 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"); - fprintf(stderr, " -rgb Create RGB 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 C_ARITH_CODING_SUPPORTED - fprintf(stderr, " -arithmetic Use arithmetic coding\n"); -#endif -#ifdef DCT_SCALING_SUPPORTED - fprintf(stderr, " -block N DCT block size (1..16; default is 8)\n"); -#endif -#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"); - 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", 2)) { - /* Force baseline-compatible output (8-bit quantizer values). */ - force_baseline = TRUE; - - } else if (keymatch(arg, "block", 2)) { - /* Set DCT block size. */ -#if defined DCT_SCALING_SUPPORTED && JPEG_LIB_VERSION_MAJOR >= 8 && \ - (JPEG_LIB_VERSION_MAJOR > 8 || JPEG_LIB_VERSION_MINOR >= 3) - int val; - - if (++argn >= argc) /* advance to next argument */ - usage(); - if (sscanf(argv[argn], "%d", &val) != 1) - usage(); - if (val < 1 || val > 16) - usage(); - cinfo->block_size = val; -#else - fprintf(stderr, "%s: sorry, block size setting not supported\n", - progname); - exit(EXIT_FAILURE); -#endif - - } 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, "rgb", 3)) { - /* Force an RGB JPEG file to be generated. */ - jpeg_set_colorspace(cinfo, JCS_RGB); - - } 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/plugins/FreeImage/Source/LibJPEG/ckconfig.c b/plugins/FreeImage/Source/LibJPEG/ckconfig.c deleted file mode 100644 index fb9429af08..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/ckconfig.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * 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 -#endif - -#define HAVE_STDLIB_H /* same thing for stdlib.h */ -#ifdef HAVE_STDLIB_H -#include -#endif - -#include /* 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 -#else -#include -#endif - -/* On some systems (especially older Unix machines), type size_t is - * defined only in the include file . 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 -#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 " 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 " with - * "typedef unsigned int size_t;". - */ - -#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */ - -#ifdef NEED_SPECIAL_INCLUDE -#include -#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/plugins/FreeImage/Source/LibJPEG/djpeg.c b/plugins/FreeImage/Source/LibJPEG/djpeg.c deleted file mode 100644 index 363c628cbe..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/djpeg.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * 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 /* to declare isprint() */ - -#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ -#ifdef __MWERKS__ -#include /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* 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/plugins/FreeImage/Source/LibJPEG/example.c b/plugins/FreeImage/Source/LibJPEG/example.c deleted file mode 100644 index e21cf12126..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/example.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * 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 - -/* - * 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" - -/* - * is used for the optional error recovery mechanism shown in - * the second part of the example. - */ - -#include - - - -/******************** 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/plugins/FreeImage/Source/LibJPEG/jaricom.c b/plugins/FreeImage/Source/LibJPEG/jaricom.c deleted file mode 100644 index 690068861f..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jaricom.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * jaricom.c - * - * Developed 1997-2011 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.3 in the JPEG spec (D.2 in the draft), - * 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(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b) - -const INT32 jpeg_aritab[113+1] = { -/* - * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS - */ - V( 0, 0x5a1d, 1, 1, 1 ), - V( 1, 0x2586, 14, 2, 0 ), - V( 2, 0x1114, 16, 3, 0 ), - V( 3, 0x080b, 18, 4, 0 ), - V( 4, 0x03d8, 20, 5, 0 ), - V( 5, 0x01da, 23, 6, 0 ), - V( 6, 0x00e5, 25, 7, 0 ), - V( 7, 0x006f, 28, 8, 0 ), - V( 8, 0x0036, 30, 9, 0 ), - V( 9, 0x001a, 33, 10, 0 ), - V( 10, 0x000d, 35, 11, 0 ), - V( 11, 0x0006, 9, 12, 0 ), - V( 12, 0x0003, 10, 13, 0 ), - V( 13, 0x0001, 12, 13, 0 ), - V( 14, 0x5a7f, 15, 15, 1 ), - V( 15, 0x3f25, 36, 16, 0 ), - V( 16, 0x2cf2, 38, 17, 0 ), - V( 17, 0x207c, 39, 18, 0 ), - V( 18, 0x17b9, 40, 19, 0 ), - V( 19, 0x1182, 42, 20, 0 ), - V( 20, 0x0cef, 43, 21, 0 ), - V( 21, 0x09a1, 45, 22, 0 ), - V( 22, 0x072f, 46, 23, 0 ), - V( 23, 0x055c, 48, 24, 0 ), - V( 24, 0x0406, 49, 25, 0 ), - V( 25, 0x0303, 51, 26, 0 ), - V( 26, 0x0240, 52, 27, 0 ), - V( 27, 0x01b1, 54, 28, 0 ), - V( 28, 0x0144, 56, 29, 0 ), - V( 29, 0x00f5, 57, 30, 0 ), - V( 30, 0x00b7, 59, 31, 0 ), - V( 31, 0x008a, 60, 32, 0 ), - V( 32, 0x0068, 62, 33, 0 ), - V( 33, 0x004e, 63, 34, 0 ), - V( 34, 0x003b, 32, 35, 0 ), - V( 35, 0x002c, 33, 9, 0 ), - V( 36, 0x5ae1, 37, 37, 1 ), - V( 37, 0x484c, 64, 38, 0 ), - V( 38, 0x3a0d, 65, 39, 0 ), - V( 39, 0x2ef1, 67, 40, 0 ), - V( 40, 0x261f, 68, 41, 0 ), - V( 41, 0x1f33, 69, 42, 0 ), - V( 42, 0x19a8, 70, 43, 0 ), - V( 43, 0x1518, 72, 44, 0 ), - V( 44, 0x1177, 73, 45, 0 ), - V( 45, 0x0e74, 74, 46, 0 ), - V( 46, 0x0bfb, 75, 47, 0 ), - V( 47, 0x09f8, 77, 48, 0 ), - V( 48, 0x0861, 78, 49, 0 ), - V( 49, 0x0706, 79, 50, 0 ), - V( 50, 0x05cd, 48, 51, 0 ), - V( 51, 0x04de, 50, 52, 0 ), - V( 52, 0x040f, 50, 53, 0 ), - V( 53, 0x0363, 51, 54, 0 ), - V( 54, 0x02d4, 52, 55, 0 ), - V( 55, 0x025c, 53, 56, 0 ), - V( 56, 0x01f8, 54, 57, 0 ), - V( 57, 0x01a4, 55, 58, 0 ), - V( 58, 0x0160, 56, 59, 0 ), - V( 59, 0x0125, 57, 60, 0 ), - V( 60, 0x00f6, 58, 61, 0 ), - V( 61, 0x00cb, 59, 62, 0 ), - V( 62, 0x00ab, 61, 63, 0 ), - V( 63, 0x008f, 61, 32, 0 ), - V( 64, 0x5b12, 65, 65, 1 ), - V( 65, 0x4d04, 80, 66, 0 ), - V( 66, 0x412c, 81, 67, 0 ), - V( 67, 0x37d8, 82, 68, 0 ), - V( 68, 0x2fe8, 83, 69, 0 ), - V( 69, 0x293c, 84, 70, 0 ), - V( 70, 0x2379, 86, 71, 0 ), - V( 71, 0x1edf, 87, 72, 0 ), - V( 72, 0x1aa9, 87, 73, 0 ), - V( 73, 0x174e, 72, 74, 0 ), - V( 74, 0x1424, 72, 75, 0 ), - V( 75, 0x119c, 74, 76, 0 ), - V( 76, 0x0f6b, 74, 77, 0 ), - V( 77, 0x0d51, 75, 78, 0 ), - V( 78, 0x0bb6, 77, 79, 0 ), - V( 79, 0x0a40, 77, 48, 0 ), - V( 80, 0x5832, 80, 81, 1 ), - V( 81, 0x4d1c, 88, 82, 0 ), - V( 82, 0x438e, 89, 83, 0 ), - V( 83, 0x3bdd, 90, 84, 0 ), - V( 84, 0x34ee, 91, 85, 0 ), - V( 85, 0x2eae, 92, 86, 0 ), - V( 86, 0x299a, 93, 87, 0 ), - V( 87, 0x2516, 86, 71, 0 ), - V( 88, 0x5570, 88, 89, 1 ), - V( 89, 0x4ca9, 95, 90, 0 ), - V( 90, 0x44d9, 96, 91, 0 ), - V( 91, 0x3e22, 97, 92, 0 ), - V( 92, 0x3824, 99, 93, 0 ), - V( 93, 0x32b4, 99, 94, 0 ), - V( 94, 0x2e17, 93, 86, 0 ), - V( 95, 0x56a8, 95, 96, 1 ), - V( 96, 0x4f46, 101, 97, 0 ), - V( 97, 0x47e5, 102, 98, 0 ), - V( 98, 0x41cf, 103, 99, 0 ), - V( 99, 0x3c3d, 104, 100, 0 ), - V( 100, 0x375e, 99, 93, 0 ), - V( 101, 0x5231, 105, 102, 0 ), - V( 102, 0x4c0f, 106, 103, 0 ), - V( 103, 0x4639, 107, 104, 0 ), - V( 104, 0x415e, 103, 99, 0 ), - V( 105, 0x5627, 105, 106, 1 ), - V( 106, 0x50e7, 108, 107, 0 ), - V( 107, 0x4b85, 109, 103, 0 ), - V( 108, 0x5597, 110, 109, 0 ), - V( 109, 0x504f, 111, 107, 0 ), - V( 110, 0x5a10, 110, 111, 1 ), - V( 111, 0x5522, 112, 109, 0 ), - V( 112, 0x59eb, 112, 111, 1 ), -/* - * This last entry is used for fixed probability estimate of 0.5 - * as suggested in Section 10.3 Table 5 of ITU-T Rec. T.851. - */ - V( 113, 0x5a1d, 113, 113, 0 ) -}; diff --git a/plugins/FreeImage/Source/LibJPEG/jcapimin.c b/plugins/FreeImage/Source/LibJPEG/jcapimin.c deleted file mode 100644 index 639ce86f44..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcapimin.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * jcapimin.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * Modified 2003-2010 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 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; - } - - /* Must do it here for emit_dqt in case jpeg_write_tables is used */ - cinfo->block_size = DCTSIZE; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - - 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/plugins/FreeImage/Source/LibJPEG/jcapistd.c b/plugins/FreeImage/Source/LibJPEG/jcapistd.c deleted file mode 100644 index c0320b1b19..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcapistd.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jcarith.c b/plugins/FreeImage/Source/LibJPEG/jcarith.c deleted file mode 100644 index 033f67069e..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcarith.c +++ /dev/null @@ -1,937 +0,0 @@ -/* - * jcarith.c - * - * Developed 1997-2011 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]; - - /* Statistics bin for coding with fixed probability 0.5 */ - unsigned char fixed_bin[4]; -} 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. - * - * 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) -{ - 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.3(D.2): - * Qe values and probability estimation state machine - */ - sv = *st; - qe = jpeg_aritab[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); - - /* Re-initialize statistics areas */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* DC needs no table for refinement scan */ - if (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; - } - /* AC needs no table when not present */ - if (cinfo->Se) { - 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) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ - else if (m > (int) ((1L << 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; - const int * natural_order; - - /* 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--; - } - - natural_order = cinfo->natural_order; - - /* 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; ke > 0; 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)[natural_order[ke]]) >= 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 */ - for (;;) { - if ((v = (*block)[natural_order[k]]) >= 0) { - if (v >>= cinfo->Al) { - arith_encode(cinfo, st + 1, 1); - arith_encode(cinfo, entropy->fixed_bin, 0); - break; - } - } else { - v = -v; - if (v >>= cinfo->Al) { - arith_encode(cinfo, st + 1, 1); - arith_encode(cinfo, entropy->fixed_bin, 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; - 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--; - } - - st = entropy->fixed_bin; /* use fixed probability estimation */ - Al = cinfo->Al; - - /* Encode the MCU data blocks */ - for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { - /* 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; - const int * natural_order; - - /* 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--; - } - - natural_order = cinfo->natural_order; - - /* 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; ke > 0; 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)[natural_order[ke]]) >= 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 > 0; kex--) - if ((v = (*block)[natural_order[kex]]) >= 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 */ - for (;;) { - if ((v = (*block)[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->fixed_bin, 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->fixed_bin, 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; - const int * natural_order; - - /* 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--; - } - - natural_order = cinfo->natural_order; - - /* 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) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ - else if (m > (int) ((1L << 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 */ - - if ((ke = cinfo->lim_Se) == 0) continue; - tbl = compptr->ac_tbl_no; - - /* Establish EOB (end-of-block) index */ - do { - if ((*block)[natural_order[ke]]) break; - } while (--ke); - - /* Figure F.5: Encode_AC_Coefficients */ - for (k = 0; k < ke;) { - st = entropy->ac_stats[tbl] + 3 * k; - arith_encode(cinfo, st, 0); /* EOB decision */ - while ((v = (*block)[natural_order[++k]]) == 0) { - arith_encode(cinfo, st + 1, 0); - st += 3; - } - arith_encode(cinfo, st + 1, 1); - /* Figure F.6: Encoding nonzero value v */ - /* Figure F.7: Encoding the sign of v */ - if (v > 0) { - arith_encode(cinfo, entropy->fixed_bin, 0); - } else { - v = -v; - arith_encode(cinfo, entropy->fixed_bin, 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 < cinfo->lim_Se */ - if (k < cinfo->lim_Se) { - st = entropy->ac_stats[tbl] + 3 * k; - 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; - - /* Allocate & initialize requested statistics areas */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* DC needs no table for refinement scan */ - if (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; - } - /* AC needs no table when not present */ - if (cinfo->Se) { - 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; - } - - /* Initialize index for fixed probability estimation */ - entropy->fixed_bin[0] = 113; -} diff --git a/plugins/FreeImage/Source/LibJPEG/jccoefct.c b/plugins/FreeImage/Source/LibJPEG/jccoefct.c deleted file mode 100644 index 924a703dda..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jccoefct.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * jccoefct.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * Modified 2003-2011 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 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. */ - FMEMZERO((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. */ - FMEMZERO((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 */ - FMEMZERO((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]; - FMEMZERO((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/plugins/FreeImage/Source/LibJPEG/jccolor.c b/plugins/FreeImage/Source/LibJPEG/jccolor.c deleted file mode 100644 index 3e2d0e9277..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jccolor.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * jccolor.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2011 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 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< 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. - * No colorspace conversion, but change from interleaved - * to separate-planes representation. - */ - -METHODDEF(void) -rgb_convert (j_compress_ptr cinfo, - JSAMPARRAY input_buf, JSAMPIMAGE output_buf, - JDIMENSION output_row, int num_rows) -{ - 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++) { - /* We can dispense with GETJSAMPLE() here */ - outptr0[col] = inptr[RGB_RED]; - outptr1[col] = inptr[RGB_GREEN]; - outptr2[col] = inptr[RGB_BLUE]; - inptr += RGB_PIXELSIZE; - } - } -} - - -/* - * 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 (cinfo->input_components != RGB_PIXELSIZE) - ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); - break; - - 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 || - cinfo->in_color_space == JCS_YCbCr) - 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 - 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) - cconvert->pub.color_convert = rgb_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/plugins/FreeImage/Source/LibJPEG/jcdctmgr.c b/plugins/FreeImage/Source/LibJPEG/jcdctmgr.c deleted file mode 100644 index 0bbdbb685d..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcdctmgr.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jchuff.c b/plugins/FreeImage/Source/LibJPEG/jchuff.c deleted file mode 100644 index 257d7aa1f5..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jchuff.c +++ /dev/null @@ -1,1576 +0,0 @@ -/* - * 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) */ - - /* 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... */ -} 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)<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)<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_dc_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) -{ - if (entropy->gather_statistics) - entropy->dc_count_ptrs[tbl_no][symbol]++; - else { - c_derived_tbl * tbl = entropy->dc_derived_tbls[tbl_no]; - emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); - } -} - - -INLINE -LOCAL(void) -emit_ac_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) -{ - if (entropy->gather_statistics) - entropy->ac_count_ptrs[tbl_no][symbol]++; - else { - c_derived_tbl * tbl = entropy->ac_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_ac_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_dc_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, Al; - const int * natural_order; - 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); - - Se = cinfo->Se; - Al = cinfo->Al; - natural_order = cinfo->natural_order; - - /* 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)[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_ac_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_ac_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, Al; - const int * natural_order; - 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); - - Se = cinfo->Se; - Al = cinfo->Al; - natural_order = cinfo->natural_order; - - /* 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)[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_ac_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_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); - - /* Emit output bit for newly-nonzero coef */ - temp = ((*block)[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; - int Se = state->cinfo->lim_Se; - const int * natural_order = state->cinfo->natural_order; - - /* 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 <= Se; k++) { - if ((temp = block[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; - int Se = cinfo->lim_Se; - const int * natural_order = cinfo->natural_order; - - /* 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 <= Se; k++) { - if ((temp = block[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, tbl; - jpeg_component_info * compptr; - JHUFF_TBL **htblptr; - boolean did_dc[NUM_HUFF_TBLS]; - boolean did_ac[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_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]; - /* DC needs no table for refinement scan */ - if (cinfo->Ss == 0 && cinfo->Ah == 0) { - tbl = compptr->dc_tbl_no; - if (! did_dc[tbl]) { - htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; - if (*htblptr == NULL) - *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); - jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[tbl]); - did_dc[tbl] = TRUE; - } - } - /* AC needs no table when not present */ - if (cinfo->Se) { - tbl = compptr->ac_tbl_no; - if (! did_ac[tbl]) { - 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->ac_count_ptrs[tbl]); - did_ac[tbl] = 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, 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)); - } - } - - /* Initialize AC stuff */ - entropy->ac_tbl_no = cinfo->cur_comp_info[0]->ac_tbl_no; - 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]; - /* DC needs no table for refinement scan */ - if (cinfo->Ss == 0 && cinfo->Ah == 0) { - tbl = compptr->dc_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->dc_count_ptrs[tbl] == NULL) - entropy->dc_count_ptrs[tbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->dc_count_ptrs[tbl], 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, tbl, - & entropy->dc_derived_tbls[tbl]); - } - /* Initialize DC predictions to 0 */ - entropy->saved.last_dc_val[ci] = 0; - } - /* AC needs no table when not present */ - if (cinfo->Se) { - tbl = compptr->ac_tbl_no; - if (gather_statistics) { - if (tbl < 0 || tbl >= NUM_HUFF_TBLS) - ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); - if (entropy->ac_count_ptrs[tbl] == NULL) - entropy->ac_count_ptrs[tbl] = (long *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - 257 * SIZEOF(long)); - MEMZERO(entropy->ac_count_ptrs[tbl], 257 * SIZEOF(long)); - } else { - jpeg_make_c_derived_tbl(cinfo, FALSE, tbl, - & entropy->ac_derived_tbls[tbl]); - } - } - } - - /* 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; - - /* 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; - } - - if (cinfo->progressive_mode) - entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ -} diff --git a/plugins/FreeImage/Source/LibJPEG/jcinit.c b/plugins/FreeImage/Source/LibJPEG/jcinit.c deleted file mode 100644 index 0ba310f217..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcinit.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jcmainct.c b/plugins/FreeImage/Source/LibJPEG/jcmainct.c deleted file mode 100644 index 7de75d1675..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcmainct.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jcmarker.c b/plugins/FreeImage/Source/LibJPEG/jcmarker.c deleted file mode 100644 index 606c19af39..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcmarker.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * jcmarker.c - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2003-2010 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 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 <= cinfo->lim_Se; i++) { - if (qtbl->quantval[cinfo->natural_order[i]] > 255) - prec = 1; - } - - if (! qtbl->sent_table) { - emit_marker(cinfo, M_DQT); - - emit_2bytes(cinfo, - prec ? cinfo->lim_Se * 2 + 2 + 1 + 2 : cinfo->lim_Se + 1 + 1 + 2); - - emit_byte(cinfo, index + (prec<<4)); - - for (i = 0; i <= cinfo->lim_Se; i++) { - /* The table entries must be emitted in zigzag order. */ - unsigned int qval = qtbl->quantval[cinfo->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 needs no table for refinement scan */ - if (cinfo->Ss == 0 && cinfo->Ah == 0) - dc_in_use[compptr->dc_tbl_no] = 1; - /* AC needs no table when not present */ - if (cinfo->Se) - 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]; - - if (length) { - 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); - - /* 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. - */ - - /* DC needs no table for refinement scan */ - td = cinfo->Ss == 0 && cinfo->Ah == 0 ? compptr->dc_tbl_no : 0; - /* AC needs no table when not present */ - ta = cinfo->Se ? compptr->ac_tbl_no : 0; - - 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_pseudo_sos (j_compress_ptr cinfo) -/* Emit a pseudo SOS marker */ -{ - emit_marker(cinfo, M_SOS); - - emit_2bytes(cinfo, 2 + 1 + 3); /* length */ - - emit_byte(cinfo, 0); /* Ns */ - - emit_byte(cinfo, 0); /* Ss */ - emit_byte(cinfo, cinfo->block_size * cinfo->block_size - 1); /* Se */ - emit_byte(cinfo, 0); /* Ah/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, and a conditional pseudo SOS marker. - * 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 || cinfo->block_size != DCTSIZE) { - 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 */ - } - - /* Check to emit pseudo SOS marker */ - if (cinfo->progressive_mode && cinfo->block_size != DCTSIZE) - emit_pseudo_sos(cinfo); -} - - -/* - * 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]; - /* DC needs no table for refinement scan */ - if (cinfo->Ss == 0 && cinfo->Ah == 0) - emit_dht(cinfo, compptr->dc_tbl_no, FALSE); - /* AC needs no table when not present */ - if (cinfo->Se) - 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/plugins/FreeImage/Source/LibJPEG/jcmaster.c b/plugins/FreeImage/Source/LibJPEG/jcmaster.c deleted file mode 100644 index caf80a53b3..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcmaster.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - * jcmaster.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2003-2011 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 - - /* Sanity check on input image dimensions to prevent overflow in - * following calculation. - * We do check jpeg_width and jpeg_height in initial_setup below, - * but image_width and image_height can come from arbitrary data, - * and we need some space for multiplication by block_size. - */ - if (((long) cinfo->image_width >> 24) || ((long) cinfo->image_height >> 24)) - ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); - - /* Compute actual JPEG image dimensions and DCT scaling choices. */ - if (cinfo->scale_num >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/1 scaling */ - cinfo->jpeg_width = cinfo->image_width * cinfo->block_size; - cinfo->jpeg_height = cinfo->image_height * cinfo->block_size; - cinfo->min_DCT_h_scaled_size = 1; - cinfo->min_DCT_v_scaled_size = 1; - } else if (cinfo->scale_num * 2 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/2 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 2L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 2L); - cinfo->min_DCT_h_scaled_size = 2; - cinfo->min_DCT_v_scaled_size = 2; - } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/3 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 3L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 3L); - cinfo->min_DCT_h_scaled_size = 3; - cinfo->min_DCT_v_scaled_size = 3; - } else if (cinfo->scale_num * 4 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/4 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 4L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 4L); - cinfo->min_DCT_h_scaled_size = 4; - cinfo->min_DCT_v_scaled_size = 4; - } else if (cinfo->scale_num * 5 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/5 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 5L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 5L); - cinfo->min_DCT_h_scaled_size = 5; - cinfo->min_DCT_v_scaled_size = 5; - } else if (cinfo->scale_num * 6 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/6 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 6L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 6L); - cinfo->min_DCT_h_scaled_size = 6; - cinfo->min_DCT_v_scaled_size = 6; - } else if (cinfo->scale_num * 7 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/7 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 7L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 7L); - cinfo->min_DCT_h_scaled_size = 7; - cinfo->min_DCT_v_scaled_size = 7; - } else if (cinfo->scale_num * 8 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/8 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 8L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 8L); - cinfo->min_DCT_h_scaled_size = 8; - cinfo->min_DCT_v_scaled_size = 8; - } else if (cinfo->scale_num * 9 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/9 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 9L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 9L); - cinfo->min_DCT_h_scaled_size = 9; - cinfo->min_DCT_v_scaled_size = 9; - } else if (cinfo->scale_num * 10 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/10 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 10L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 10L); - cinfo->min_DCT_h_scaled_size = 10; - cinfo->min_DCT_v_scaled_size = 10; - } else if (cinfo->scale_num * 11 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/11 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 11L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 11L); - cinfo->min_DCT_h_scaled_size = 11; - cinfo->min_DCT_v_scaled_size = 11; - } else if (cinfo->scale_num * 12 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/12 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 12L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 12L); - cinfo->min_DCT_h_scaled_size = 12; - cinfo->min_DCT_v_scaled_size = 12; - } else if (cinfo->scale_num * 13 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/13 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 13L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 13L); - cinfo->min_DCT_h_scaled_size = 13; - cinfo->min_DCT_v_scaled_size = 13; - } else if (cinfo->scale_num * 14 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/14 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 14L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 14L); - cinfo->min_DCT_h_scaled_size = 14; - cinfo->min_DCT_v_scaled_size = 14; - } else if (cinfo->scale_num * 15 >= cinfo->scale_denom * cinfo->block_size) { - /* Provide block_size/15 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 15L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 15L); - cinfo->min_DCT_h_scaled_size = 15; - cinfo->min_DCT_v_scaled_size = 15; - } else { - /* Provide block_size/16 scaling */ - cinfo->jpeg_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 16L); - cinfo->jpeg_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 16L); - 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) -jpeg_calc_trans_dimensions (j_compress_ptr cinfo) -{ - if (cinfo->min_DCT_h_scaled_size != cinfo->min_DCT_v_scaled_size) - ERREXIT2(cinfo, JERR_BAD_DCTSIZE, - cinfo->min_DCT_h_scaled_size, cinfo->min_DCT_v_scaled_size); - - cinfo->block_size = cinfo->min_DCT_h_scaled_size; -} - - -LOCAL(void) -initial_setup (j_compress_ptr cinfo, boolean transcode_only) -/* Do computations that are needed before master selection phase */ -{ - int ci, ssize; - jpeg_component_info *compptr; - long samplesperrow; - JDIMENSION jd_samplesperrow; - - if (transcode_only) - jpeg_calc_trans_dimensions(cinfo); - else - jpeg_calc_jpeg_dimensions(cinfo); - - /* Sanity check on block_size */ - if (cinfo->block_size < 1 || cinfo->block_size > 16) - ERREXIT2(cinfo, JERR_BAD_DCTSIZE, cinfo->block_size, cinfo->block_size); - - /* Derive natural_order from block_size */ - switch (cinfo->block_size) { - case 2: cinfo->natural_order = jpeg_natural_order2; break; - case 3: cinfo->natural_order = jpeg_natural_order3; break; - case 4: cinfo->natural_order = jpeg_natural_order4; break; - case 5: cinfo->natural_order = jpeg_natural_order5; break; - case 6: cinfo->natural_order = jpeg_natural_order6; break; - case 7: cinfo->natural_order = jpeg_natural_order7; break; - default: cinfo->natural_order = jpeg_natural_order; break; - } - - /* Derive lim_Se from block_size */ - cinfo->lim_Se = cinfo->block_size < DCTSIZE ? - cinfo->block_size * cinfo->block_size - 1 : DCTSIZE2-1; - - /* 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 * cinfo->block_size)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->jpeg_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - /* 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 * cinfo->block_size)); - 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 * cinfo->block_size)); - /* 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 * cinfo->block_size)); -} - - -#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); - } - } -} - - -LOCAL(void) -reduce_script (j_compress_ptr cinfo) -/* Adapt scan script for use with reduced block size; - * assume that script has been validated before. - */ -{ - jpeg_scan_info * scanptr; - int idxout, idxin; - - /* Circumvent const declaration for this function */ - scanptr = (jpeg_scan_info *) cinfo->scan_info; - idxout = 0; - - for (idxin = 0; idxin < cinfo->num_scans; idxin++) { - /* After skipping, idxout becomes smaller than idxin */ - if (idxin != idxout) - /* Copy rest of data; - * note we stay in given chunk of allocated memory. - */ - scanptr[idxout] = scanptr[idxin]; - if (scanptr[idxout].Ss > cinfo->lim_Se) - /* Entire scan out of range - skip this entry */ - continue; - if (scanptr[idxout].Se > cinfo->lim_Se) - /* Limit scan to end of block */ - scanptr[idxout].Se = cinfo->lim_Se; - idxout++; - } - - cinfo->num_scans = idxout; -} - -#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]]; - } - if (cinfo->progressive_mode) { - cinfo->Ss = scanptr->Ss; - cinfo->Se = scanptr->Se; - cinfo->Ah = scanptr->Ah; - cinfo->Al = scanptr->Al; - return; - } - } - 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 = cinfo->block_size * cinfo->block_size - 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 * cinfo->block_size)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->jpeg_height, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - - 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, transcode_only); - - if (cinfo->scan_info != NULL) { -#ifdef C_MULTISCAN_FILES_SUPPORTED - validate_script(cinfo); - if (cinfo->block_size < DCTSIZE) - reduce_script(cinfo); -#else - ERREXIT(cinfo, JERR_NOT_COMPILED); -#endif - } else { - cinfo->progressive_mode = FALSE; - cinfo->num_scans = 1; - } - - if ((cinfo->progressive_mode || cinfo->block_size < DCTSIZE) && - !cinfo->arith_code) /* TEMPORARY HACK ??? */ - /* assume default tables no good for progressive or downscale mode */ - cinfo->optimize_coding = TRUE; - - /* 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/plugins/FreeImage/Source/LibJPEG/jcomapi.c b/plugins/FreeImage/Source/LibJPEG/jcomapi.c deleted file mode 100644 index 9b1fa7568a..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcomapi.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jconfig.h b/plugins/FreeImage/Source/LibJPEG/jconfig.h deleted file mode 100644 index 44e5c52ee5..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jconfig.h +++ /dev/null @@ -1,47 +0,0 @@ -/* 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 */ diff --git a/plugins/FreeImage/Source/LibJPEG/jconfig.txt b/plugins/FreeImage/Source/LibJPEG/jconfig.txt deleted file mode 100644 index 27086a3644..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jconfig.txt +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 file. - */ -#define HAVE_STDDEF_H - -/* Define this if your system has an ANSI-conforming file. - */ -#define HAVE_STDLIB_H - -/* Define this if your system does not have an ANSI/SysV , - * but does have a BSD-style . - */ -#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 - * 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 - -/* Define "boolean" as unsigned char, not int, on Windows systems. - */ -#ifdef _WIN32 -#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 - - -/* - * 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/plugins/FreeImage/Source/LibJPEG/jcparam.c b/plugins/FreeImage/Source/LibJPEG/jcparam.c deleted file mode 100644 index 1c81d2ec59..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcparam.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jcprepct.c b/plugins/FreeImage/Source/LibJPEG/jcprepct.c deleted file mode 100644 index be44cc4b45..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcprepct.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jcsample.c b/plugins/FreeImage/Source/LibJPEG/jcsample.c deleted file mode 100644 index 4d36f85f35..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jcsample.c +++ /dev/null @@ -1,545 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jctrans.c b/plugins/FreeImage/Source/LibJPEG/jctrans.c deleted file mode 100644 index f7d7b81491..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jctrans.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * jctrans.c - * - * Copyright (C) 1995-1998, Thomas G. Lane. - * Modified 2000-2011 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 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; - dstinfo->jpeg_width = srcinfo->output_width; - dstinfo->jpeg_height = srcinfo->output_height; - dstinfo->min_DCT_h_scaled_size = srcinfo->min_DCT_h_scaled_size; - dstinfo->min_DCT_v_scaled_size = srcinfo->min_DCT_v_scaled_size; - /* 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) -{ - /* 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)); - FMEMZERO((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/plugins/FreeImage/Source/LibJPEG/jdapimin.c b/plugins/FreeImage/Source/LibJPEG/jdapimin.c deleted file mode 100644 index 7f1ce4c05b..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdapimin.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * 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 = cinfo->block_size; /* 1:1 scaling */ - cinfo->scale_denom = cinfo->block_size; - 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/plugins/FreeImage/Source/LibJPEG/jdapistd.c b/plugins/FreeImage/Source/LibJPEG/jdapistd.c deleted file mode 100644 index 9d74537772..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdapistd.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jdarith.c b/plugins/FreeImage/Source/LibJPEG/jdarith.c deleted file mode 100644 index 092f8af5fe..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdarith.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * jdarith.c - * - * Developed 1997-2011 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]; - - /* Statistics bin for coding with fixed probability 0.5 */ - unsigned char fixed_bin[4]; -} 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. - * - * 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) -{ - 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.3(D.2): - * Qe values and probability estimation state machine - */ - sv = *st; - qe = jpeg_aritab[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); - - /* Re-initialize statistics areas */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (! cinfo->progressive_mode || (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 && cinfo->lim_Se) || - (cinfo->progressive_mode && 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) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ - else if (m > (int) ((1L << 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; - const int * natural_order; - - /* 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 */ - - natural_order = cinfo->natural_order; - - /* 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 */ - sign = arith_decode(cinfo, entropy->fixed_bin); - 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)[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; - 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--; - } - - st = entropy->fixed_bin; /* use fixed probability estimation */ - 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++) { - /* 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; - const int * natural_order; - - /* 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 */ - - natural_order = cinfo->natural_order; - - /* 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; kex > 0; kex--) - if ((*block)[natural_order[kex]]) 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 + 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 */ - if (arith_decode(cinfo, entropy->fixed_bin)) - *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; - const int * natural_order; - - /* 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 */ - - natural_order = cinfo->natural_order; - - /* 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) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) - entropy->dc_context[ci] = 0; /* zero diff category */ - else if (m > (int) ((1L << 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 */ - - if (cinfo->lim_Se == 0) continue; - tbl = compptr->ac_tbl_no; - k = 0; - - /* Figure F.20: Decode_AC_coefficients */ - do { - st = entropy->ac_stats[tbl] + 3 * k; - if (arith_decode(cinfo, st)) break; /* EOB flag */ - for (;;) { - k++; - if (arith_decode(cinfo, st + 1)) break; - st += 3; - if (k >= cinfo->lim_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 */ - sign = arith_decode(cinfo, entropy->fixed_bin); - 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)[natural_order[k]] = (JCOEF) v; - } while (k < cinfo->lim_Se); - } - - 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 > cinfo->lim_Se) - 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. - */ - if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || - (cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); - /* Select MCU decoding routine */ - entropy->pub.decode_mcu = decode_mcu; - } - - /* Allocate & initialize requested statistics areas */ - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - if (! cinfo->progressive_mode || (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 && cinfo->lim_Se) || - (cinfo->progressive_mode && 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; - } - - /* Initialize index for fixed probability estimation */ - entropy->fixed_bin[0] = 113; - - 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/plugins/FreeImage/Source/LibJPEG/jdatadst.c b/plugins/FreeImage/Source/LibJPEG/jdatadst.c deleted file mode 100644 index 6981fb73de..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdatadst.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * jdatadst.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2009-2012 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 compression data destination routines for the case of - * emitting JPEG data to memory or 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" - -#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ -extern void * malloc JPP((size_t size)); -extern void free JPP((void *ptr)); -#endif - - -/* 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 */ - - -/* Expanded data destination object for memory output */ - -typedef struct { - struct jpeg_destination_mgr pub; /* public fields */ - - unsigned char ** outbuffer; /* target buffer */ - unsigned long * outsize; - unsigned char * newbuffer; /* newly allocated buffer */ - JOCTET * buffer; /* start of buffer */ - size_t bufsize; -} my_mem_destination_mgr; - -typedef my_mem_destination_mgr * my_mem_dest_ptr; - - -/* - * 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; -} - -METHODDEF(void) -init_mem_destination (j_compress_ptr cinfo) -{ - /* no work necessary here */ -} - - -/* - * 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; -} - -METHODDEF(boolean) -empty_mem_output_buffer (j_compress_ptr cinfo) -{ - size_t nextsize; - JOCTET * nextbuffer; - my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; - - /* Try to allocate new buffer with double size */ - nextsize = dest->bufsize * 2; - nextbuffer = (JOCTET *) malloc(nextsize); - - if (nextbuffer == NULL) - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); - - MEMCOPY(nextbuffer, dest->buffer, dest->bufsize); - - if (dest->newbuffer != NULL) - free(dest->newbuffer); - - dest->newbuffer = nextbuffer; - - dest->pub.next_output_byte = nextbuffer + dest->bufsize; - dest->pub.free_in_buffer = dest->bufsize; - - dest->buffer = nextbuffer; - dest->bufsize = nextsize; - - 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); -} - -METHODDEF(void) -term_mem_destination (j_compress_ptr cinfo) -{ - my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; - - *dest->outbuffer = dest->buffer; - *dest->outsize = dest->bufsize - dest->pub.free_in_buffer; -} - - -/* - * 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; -} - - -/* - * Prepare for output to a memory buffer. - * The caller may supply an own initial buffer with appropriate size. - * Otherwise, or when the actual data output exceeds the given size, - * the library adapts the buffer size as necessary. - * The standard library functions malloc/free are used for allocating - * larger memory, so the buffer is available to the application after - * finishing compression, and then the application is responsible for - * freeing the requested memory. - */ - -GLOBAL(void) -jpeg_mem_dest (j_compress_ptr cinfo, - unsigned char ** outbuffer, unsigned long * outsize) -{ - my_mem_dest_ptr dest; - - if (outbuffer == NULL || outsize == NULL) /* sanity check */ - ERREXIT(cinfo, JERR_BUFFER_SIZE); - - /* The destination object is made permanent so that multiple JPEG images - * can be written to the same buffer without re-executing jpeg_mem_dest. - */ - 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_mem_destination_mgr)); - } - - dest = (my_mem_dest_ptr) cinfo->dest; - dest->pub.init_destination = init_mem_destination; - dest->pub.empty_output_buffer = empty_mem_output_buffer; - dest->pub.term_destination = term_mem_destination; - dest->outbuffer = outbuffer; - dest->outsize = outsize; - dest->newbuffer = NULL; - - if (*outbuffer == NULL || *outsize == 0) { - /* Allocate initial buffer */ - dest->newbuffer = *outbuffer = (unsigned char *) malloc(OUTPUT_BUF_SIZE); - if (dest->newbuffer == NULL) - ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); - *outsize = OUTPUT_BUF_SIZE; - } - - dest->pub.next_output_byte = dest->buffer = *outbuffer; - dest->pub.free_in_buffer = dest->bufsize = *outsize; -} diff --git a/plugins/FreeImage/Source/LibJPEG/jdatasrc.c b/plugins/FreeImage/Source/LibJPEG/jdatasrc.c deleted file mode 100644 index 7be59a88a1..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdatasrc.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * jdatasrc.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2009-2011 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 decompression data source routines for the case of - * reading JPEG data from memory or 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; -} - -METHODDEF(void) -init_mem_source (j_decompress_ptr cinfo) -{ - /* no work necessary here */ -} - - -/* - * 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; -} - -METHODDEF(boolean) -fill_mem_input_buffer (j_decompress_ptr cinfo) -{ - static const JOCTET mybuffer[4] = { - (JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0 - }; - - /* The whole JPEG data is expected to reside in the supplied memory - * buffer, so any request for more data beyond the given buffer size - * is treated as an error. - */ - WARNMS(cinfo, JWRN_JPEG_EOF); - - /* Insert a fake EOI marker */ - - cinfo->src->next_input_byte = mybuffer; - cinfo->src->bytes_in_buffer = 2; - - 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) -{ - struct jpeg_source_mgr * src = 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->bytes_in_buffer) { - num_bytes -= (long) src->bytes_in_buffer; - (void) (*src->fill_input_buffer) (cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->next_input_byte += (size_t) num_bytes; - src->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 */ -} - - -/* - * Prepare for input from a supplied memory buffer. - * The buffer must contain the whole JPEG data. - */ - -GLOBAL(void) -jpeg_mem_src (j_decompress_ptr cinfo, - unsigned char * inbuffer, unsigned long insize) -{ - struct jpeg_source_mgr * src; - - if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ - ERREXIT(cinfo, JERR_INPUT_EMPTY); - - /* The source object is made permanent so that a series of JPEG images - * can be read from the same buffer by calling jpeg_mem_src only before - * the first one. - */ - 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(struct jpeg_source_mgr)); - } - - src = cinfo->src; - src->init_source = init_mem_source; - src->fill_input_buffer = fill_mem_input_buffer; - src->skip_input_data = skip_input_data; - src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->term_source = term_source; - src->bytes_in_buffer = (size_t) insize; - src->next_input_byte = (JOCTET *) inbuffer; -} diff --git a/plugins/FreeImage/Source/LibJPEG/jdcoefct.c b/plugins/FreeImage/Source/LibJPEG/jdcoefct.c deleted file mode 100644 index ed02fc378f..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdcoefct.c +++ /dev/null @@ -1,741 +0,0 @@ -/* - * jdcoefct.c - * - * Copyright (C) 1994-1997, Thomas G. Lane. - * Modified 2002-2011 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 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. */ - if (cinfo->lim_Se) /* can bypass in DC only case */ - FMEMZERO((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< 0 && pred >= (1<= 0) { - pred = (int) (((Q10<<7) + num) / (Q10<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q20<<7) + num) / (Q20<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q11<<7) + num) / (Q11<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { - pred = (int) (((Q02<<7) + num) / (Q02<<8)); - if (Al > 0 && pred >= (1< 0 && pred >= (1<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; - } - if (cinfo->lim_Se == 0) /* DC only case: want to bypass later */ - FMEMZERO((void FAR *) buffer, - (size_t) (D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK))); - 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/plugins/FreeImage/Source/LibJPEG/jdcolor.c b/plugins/FreeImage/Source/LibJPEG/jdcolor.c deleted file mode 100644 index 83e4d069ab..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdcolor.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * jdcolor.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2011 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 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 */ - - /* Private state for RGB->Y conversion */ - INT32 * rgb_y_tab; /* => table for RGB to Y conversion */ -} my_color_deconverter; - -typedef my_color_deconverter * my_cconvert_ptr; - - -/**************** YCbCr -> RGB conversion: most common case **************/ -/**************** RGB -> Y conversion: less 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 - * - * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B - * - * 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<Y conversion and divide it up into - * three parts, instead of doing three 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 three 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 TABLE_SIZE (3*(MAXJSAMPLE+1)) - - -/* - * 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 **************/ - - -/* - * Initialize for RGB->grayscale colorspace conversion. - */ - -LOCAL(void) -build_rgb_y_table (j_decompress_ptr cinfo) -{ - my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; - INT32 * rgb_y_tab; - INT32 i; - - /* Allocate and fill in the conversion tables. */ - cconvert->rgb_y_tab = rgb_y_tab = (INT32 *) - (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, - (TABLE_SIZE * SIZEOF(INT32))); - - for (i = 0; i <= MAXJSAMPLE; i++) { - rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i; - rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i; - rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; - } -} - - -/* - * Convert RGB to grayscale. - */ - -METHODDEF(void) -rgb_gray_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 r, g, b; - register INT32 * ctab = cconvert->rgb_y_tab; - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - 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++) { - r = GETJSAMPLE(inptr0[col]); - g = GETJSAMPLE(inptr1[col]); - b = GETJSAMPLE(inptr2[col]); - /* Y */ - outptr[col] = (JSAMPLE) - ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) - >> SCALEBITS); - } - } -} - - -/* - * No colorspace change, but conversion from separate-planes - * to interleaved representation. - */ - -METHODDEF(void) -rgb_convert (j_decompress_ptr cinfo, - JSAMPIMAGE input_buf, JDIMENSION input_row, - JSAMPARRAY output_buf, int num_rows) -{ - register JSAMPROW outptr; - register JSAMPROW inptr0, inptr1, inptr2; - register JDIMENSION col; - JDIMENSION num_cols = cinfo->output_width; - - 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++) { - /* We can dispense with GETJSAMPLE() here */ - outptr[RGB_RED] = inptr0[col]; - outptr[RGB_GREEN] = inptr1[col]; - outptr[RGB_BLUE] = inptr2[col]; - outptr += RGB_PIXELSIZE; - } - } -} - - -/* - * 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 if (cinfo->jpeg_color_space == JCS_RGB) { - cconvert->pub.color_convert = rgb_gray_convert; - build_rgb_y_table(cinfo); - } 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) { - cconvert->pub.color_convert = rgb_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/plugins/FreeImage/Source/LibJPEG/jdct.h b/plugins/FreeImage/Source/LibJPEG/jdct.h deleted file mode 100644 index 360dec80c9..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdct.h +++ /dev/null @@ -1,393 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jddctmgr.c b/plugins/FreeImage/Source/LibJPEG/jddctmgr.c deleted file mode 100644 index 0ded9d5741..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jddctmgr.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * jddctmgr.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2002-2010 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 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 - * We apply a further scale factor of 1/8. - */ - 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] * 0.125); - 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/plugins/FreeImage/Source/LibJPEG/jdhuff.c b/plugins/FreeImage/Source/LibJPEG/jdhuff.c deleted file mode 100644 index 06f92fe47f..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdhuff.c +++ /dev/null @@ -1,1541 +0,0 @@ -/* - * 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< 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. */ - boolean insufficient_data; /* set TRUE after emitting warning */ - 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 } -}; - -static const int jpeg_zigzag_order7[7][7] = { - { 0, 1, 5, 6, 14, 15, 27 }, - { 2, 4, 7, 13, 16, 26, 28 }, - { 3, 8, 12, 17, 25, 29, 38 }, - { 9, 11, 18, 24, 30, 37, 39 }, - { 10, 19, 23, 31, 36, 40, 45 }, - { 20, 22, 32, 35, 41, 44, 46 }, - { 21, 33, 34, 42, 43, 47, 48 } -}; - -static const int jpeg_zigzag_order6[6][6] = { - { 0, 1, 5, 6, 14, 15 }, - { 2, 4, 7, 13, 16, 25 }, - { 3, 8, 12, 17, 24, 26 }, - { 9, 11, 18, 23, 27, 32 }, - { 10, 19, 22, 28, 31, 33 }, - { 20, 21, 29, 30, 34, 35 } -}; - -static const int jpeg_zigzag_order5[5][5] = { - { 0, 1, 5, 6, 14 }, - { 2, 4, 7, 13, 15 }, - { 3, 8, 12, 16, 21 }, - { 9, 11, 17, 20, 22 }, - { 10, 18, 19, 23, 24 } -}; - -static const int jpeg_zigzag_order4[4][4] = { - { 0, 1, 5, 6 }, - { 2, 4, 7, 12 }, - { 3, 8, 11, 13 }, - { 9, 10, 14, 15 } -}; - -static const int jpeg_zigzag_order3[3][3] = { - { 0, 1, 5 }, - { 2, 4, 6 }, - { 3, 7, 8 } -}; - -static const int jpeg_zigzag_order2[2][2] = { - { 0, 1 }, - { 2, 3 } -}; - - -/* - * 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 (! ((huff_entropy_ptr) cinfo->entropy)->insufficient_data) { - WARNMS(cinfo, JWRN_HIT_MARKER); - ((huff_entropy_ptr) 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->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->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; - register int s, k, r; - unsigned int EOBRUN; - int Se, Al; - const int * natural_order; - 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->insufficient_data) { - - Se = cinfo->Se; - Al = cinfo->Al; - natural_order = cinfo->natural_order; - - /* 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)[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; - register int s, k, r; - unsigned int EOBRUN; - int Se, p1, m1; - const int * natural_order; - 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->insufficient_data) { - - Se = cinfo->Se; - p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ - m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ - natural_order = cinfo->natural_order; - - /* 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 + 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 = 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 + 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, - * partial blocks. - */ - -METHODDEF(boolean) -decode_mcu_sub (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) -{ - huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; - const int * natural_order; - int Se, 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->insufficient_data) { - - natural_order = cinfo->natural_order; - Se = cinfo->lim_Se; - - /* 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 natural_order[] will save us - * if k > Se, which could happen if the data is corrupted. - */ - (*block)[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 <= Se; 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; -} - - -/* - * Decode one MCU's worth of Huffman-compressed coefficients, - * full-size blocks. - */ - -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->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, tbl, 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 > cinfo->lim_Se) - 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 */ - tbl = compptr->dc_tbl_no; - jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->derived_tbls[tbl]); - } - } else { - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->derived_tbls[tbl]); - /* remember the single active table */ - entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; - } - /* 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->Ah != 0 || cinfo->Al != 0 || - ((cinfo->is_baseline || cinfo->Se < DCTSIZE2) && - cinfo->Se != cinfo->lim_Se)) - WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); - - /* Select MCU decoding routine */ - /* We retain the hard-coded case for full-size blocks. - * This is not necessary, but it appears that this version is slightly - * more performant in the given implementation. - * With an improved implementation we would prefer a single optimized - * function. - */ - if (cinfo->lim_Se != DCTSIZE2-1) - entropy->pub.decode_mcu = decode_mcu_sub; - else - entropy->pub.decode_mcu = decode_mcu; - - for (ci = 0; ci < cinfo->comps_in_scan; ci++) { - compptr = cinfo->cur_comp_info[ci]; - /* Compute derived values for Huffman tables */ - /* We may do this more than once for a table, but it's not expensive */ - tbl = compptr->dc_tbl_no; - jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, - & entropy->dc_derived_tbls[tbl]); - if (cinfo->lim_Se) { /* AC needs no table when not present */ - tbl = compptr->ac_tbl_no; - jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, - & entropy->ac_derived_tbls[tbl]); - } - /* 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; - i = compptr->DCT_h_scaled_size; - switch (cinfo->lim_Se) { - case (1*1-1): - entropy->coef_limit[blkn] = 1; - break; - case (2*2-1): - if (ci <= 0 || ci > 2) ci = 2; - if (i <= 0 || i > 2) i = 2; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order2[ci - 1][i - 1]; - break; - case (3*3-1): - if (ci <= 0 || ci > 3) ci = 3; - if (i <= 0 || i > 3) i = 3; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order3[ci - 1][i - 1]; - break; - case (4*4-1): - if (ci <= 0 || ci > 4) ci = 4; - if (i <= 0 || i > 4) i = 4; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order4[ci - 1][i - 1]; - break; - case (5*5-1): - if (ci <= 0 || ci > 5) ci = 5; - if (i <= 0 || i > 5) i = 5; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order5[ci - 1][i - 1]; - break; - case (6*6-1): - if (ci <= 0 || ci > 6) ci = 6; - if (i <= 0 || i > 6) i = 6; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order6[ci - 1][i - 1]; - break; - case (7*7-1): - if (ci <= 0 || ci > 7) ci = 7; - if (i <= 0 || i > 7) i = 7; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order7[ci - 1][i - 1]; - break; - default: - if (ci <= 0 || ci > 8) ci = 8; - if (i <= 0 || i > 8) i = 8; - entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1]; - break; - } - } 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->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/plugins/FreeImage/Source/LibJPEG/jdinput.c b/plugins/FreeImage/Source/LibJPEG/jdinput.c deleted file mode 100644 index 2c5c717b9c..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdinput.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * 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 */ - - int inheaders; /* Nonzero 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. - */ - - -/* - * 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. - */ - -GLOBAL(void) -jpeg_core_output_dimensions (j_decompress_ptr cinfo) -/* Do computations that are needed before master selection phase. - * This function is used for transcoding and full decompression. - */ -{ -#ifdef IDCT_SCALING_SUPPORTED - int ci; - jpeg_component_info *compptr; - - /* Compute actual output image dimensions and DCT scaling choices. */ - if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom) { - /* Provide 1/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 1; - cinfo->min_DCT_v_scaled_size = 1; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 2) { - /* Provide 2/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 2L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 2L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 2; - cinfo->min_DCT_v_scaled_size = 2; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 3) { - /* Provide 3/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 3L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 3L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 3; - cinfo->min_DCT_v_scaled_size = 3; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 4) { - /* Provide 4/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 4L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 4L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 4; - cinfo->min_DCT_v_scaled_size = 4; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 5) { - /* Provide 5/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 5L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 5L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 5; - cinfo->min_DCT_v_scaled_size = 5; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 6) { - /* Provide 6/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 6L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 6L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 6; - cinfo->min_DCT_v_scaled_size = 6; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 7) { - /* Provide 7/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 7L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 7L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 7; - cinfo->min_DCT_v_scaled_size = 7; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 8) { - /* Provide 8/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 8L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 8L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 8; - cinfo->min_DCT_v_scaled_size = 8; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 9) { - /* Provide 9/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 9L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 9L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 9; - cinfo->min_DCT_v_scaled_size = 9; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 10) { - /* Provide 10/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 10L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 10L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 10; - cinfo->min_DCT_v_scaled_size = 10; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 11) { - /* Provide 11/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 11L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 11L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 11; - cinfo->min_DCT_v_scaled_size = 11; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 12) { - /* Provide 12/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 12L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 12L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 12; - cinfo->min_DCT_v_scaled_size = 12; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 13) { - /* Provide 13/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 13L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 13L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 13; - cinfo->min_DCT_v_scaled_size = 13; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 14) { - /* Provide 14/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 14L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 14L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 14; - cinfo->min_DCT_v_scaled_size = 14; - } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 15) { - /* Provide 15/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 15L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 15L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 15; - cinfo->min_DCT_v_scaled_size = 15; - } else { - /* Provide 16/block_size scaling */ - cinfo->output_width = (JDIMENSION) - jdiv_round_up((long) cinfo->image_width * 16L, (long) cinfo->block_size); - cinfo->output_height = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * 16L, (long) cinfo->block_size); - cinfo->min_DCT_h_scaled_size = 16; - cinfo->min_DCT_v_scaled_size = 16; - } - - /* Recompute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size; - compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size; - } - -#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, - * and has computed unscaled downsampled_width and downsampled_height. - */ - -#endif /* IDCT_SCALING_SUPPORTED */ -} - - -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); - } - - /* Derive block_size, natural_order, and lim_Se */ - if (cinfo->is_baseline || (cinfo->progressive_mode && - cinfo->comps_in_scan)) { /* no pseudo SOS marker */ - cinfo->block_size = DCTSIZE; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - } else - switch (cinfo->Se) { - case (1*1-1): - cinfo->block_size = 1; - cinfo->natural_order = jpeg_natural_order; /* not needed */ - cinfo->lim_Se = cinfo->Se; - break; - case (2*2-1): - cinfo->block_size = 2; - cinfo->natural_order = jpeg_natural_order2; - cinfo->lim_Se = cinfo->Se; - break; - case (3*3-1): - cinfo->block_size = 3; - cinfo->natural_order = jpeg_natural_order3; - cinfo->lim_Se = cinfo->Se; - break; - case (4*4-1): - cinfo->block_size = 4; - cinfo->natural_order = jpeg_natural_order4; - cinfo->lim_Se = cinfo->Se; - break; - case (5*5-1): - cinfo->block_size = 5; - cinfo->natural_order = jpeg_natural_order5; - cinfo->lim_Se = cinfo->Se; - break; - case (6*6-1): - cinfo->block_size = 6; - cinfo->natural_order = jpeg_natural_order6; - cinfo->lim_Se = cinfo->Se; - break; - case (7*7-1): - cinfo->block_size = 7; - cinfo->natural_order = jpeg_natural_order7; - cinfo->lim_Se = cinfo->Se; - break; - case (8*8-1): - cinfo->block_size = 8; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (9*9-1): - cinfo->block_size = 9; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (10*10-1): - cinfo->block_size = 10; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (11*11-1): - cinfo->block_size = 11; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (12*12-1): - cinfo->block_size = 12; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (13*13-1): - cinfo->block_size = 13; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (14*14-1): - cinfo->block_size = 14; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (15*15-1): - cinfo->block_size = 15; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - case (16*16-1): - cinfo->block_size = 16; - cinfo->natural_order = jpeg_natural_order; - cinfo->lim_Se = DCTSIZE2-1; - break; - default: - ERREXIT4(cinfo, JERR_BAD_PROGRESSION, - cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); - break; - } - - /* We initialize DCT_scaled_size and min_DCT_scaled_size to block_size. - * In the full decompressor, - * this will be overridden by jpeg_calc_output_dimensions in jdmaster.c; - * but in the transcoder, - * jpeg_calc_output_dimensions is not used, so we must do it here. - */ - cinfo->min_DCT_h_scaled_size = cinfo->block_size; - cinfo->min_DCT_v_scaled_size = cinfo->block_size; - - /* Compute dimensions of components */ - for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; - ci++, compptr++) { - compptr->DCT_h_scaled_size = cinfo->block_size; - compptr->DCT_v_scaled_size = cinfo->block_size; - /* 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 * cinfo->block_size)); - compptr->height_in_blocks = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - /* 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 * cinfo->block_size)); - - /* 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 * cinfo->block_size)); - cinfo->MCU_rows_in_scan = (JDIMENSION) - jdiv_round_up((long) cinfo->image_height, - (long) (cinfo->max_v_samp_factor * cinfo->block_size)); - - 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. - * - * Note: This function should NOT return a pseudo SOS marker (with zero - * component number) to the caller. A pseudo marker received by - * read_markers is processed and then skipped for other 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; - - for (;;) { /* Loop to pass pseudo SOS marker */ - val = (*cinfo->marker->read_markers) (cinfo); - - switch (val) { - case JPEG_REACHED_SOS: /* Found SOS */ - if (inputctl->inheaders) { /* 1st SOS */ - if (inputctl->inheaders == 1) - initial_setup(cinfo); - if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ - inputctl->inheaders = 2; - break; - } - inputctl->inheaders = 0; - /* 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! */ - if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ - break; - start_input_pass(cinfo); - } - return val; - 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; - } - return val; - case JPEG_SUSPENDED: - return val; - default: - 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 = 1; - /* 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 = 1; -} diff --git a/plugins/FreeImage/Source/LibJPEG/jdmainct.c b/plugins/FreeImage/Source/LibJPEG/jdmainct.c deleted file mode 100644 index 02723ca732..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdmainct.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jdmarker.c b/plugins/FreeImage/Source/LibJPEG/jdmarker.c deleted file mode 100644 index f2a9cc4295..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdmarker.c +++ /dev/null @@ -1,1406 +0,0 @@ -/* - * jdmarker.c - * - * Copyright (C) 1991-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 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_baseline, boolean is_prog, - boolean is_arith) -/* Process a SOFn marker */ -{ - INT32 length; - int c, ci; - jpeg_component_info * compptr; - INPUT_VARS(cinfo); - - cinfo->is_baseline = is_baseline; - 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 > MAX_COMPS_IN_SCAN || - (n == 0 && !cinfo->progressive_mode)) - /* pseudo SOS marker only allowed in progressive mode */ - 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 (non-pseudo) SOS marker */ - if (n) 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, count, i; - int n, prec; - unsigned int tmp; - JQUANT_TBL *quant_ptr; - const int *natural_order; - INPUT_VARS(cinfo); - - INPUT_2BYTES(cinfo, length, return FALSE); - length -= 2; - - while (length > 0) { - length--; - 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]; - - if (prec) { - if (length < DCTSIZE2 * 2) { - /* Initialize full table for safety. */ - for (i = 0; i < DCTSIZE2; i++) { - quant_ptr->quantval[i] = 1; - } - count = length >> 1; - } else - count = DCTSIZE2; - } else { - if (length < DCTSIZE2) { - /* Initialize full table for safety. */ - for (i = 0; i < DCTSIZE2; i++) { - quant_ptr->quantval[i] = 1; - } - count = length; - } else - count = DCTSIZE2; - } - - switch (count) { - case (2*2): natural_order = jpeg_natural_order2; break; - case (3*3): natural_order = jpeg_natural_order3; break; - case (4*4): natural_order = jpeg_natural_order4; break; - case (5*5): natural_order = jpeg_natural_order5; break; - case (6*6): natural_order = jpeg_natural_order6; break; - case (7*7): natural_order = jpeg_natural_order7; break; - default: natural_order = jpeg_natural_order; break; - } - - for (i = 0; i < count; 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[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 -= count; - if (prec) length -= count; - } - - 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. - * - * Note: This function may return a pseudo SOS marker (with zero - * component number) for treat by input controller's consume_input. - * consume_input itself should filter out (skip) the pseudo marker - * after processing for the caller. - */ - -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 */ - if (! get_sof(cinfo, TRUE, FALSE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF1: /* Extended sequential, Huffman */ - if (! get_sof(cinfo, FALSE, FALSE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF2: /* Progressive, Huffman */ - if (! get_sof(cinfo, FALSE, TRUE, FALSE)) - return JPEG_SUSPENDED; - break; - - case M_SOF9: /* Extended sequential, arithmetic */ - if (! get_sof(cinfo, FALSE, FALSE, TRUE)) - return JPEG_SUSPENDED; - break; - - case M_SOF10: /* Progressive, arithmetic */ - if (! get_sof(cinfo, FALSE, 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/plugins/FreeImage/Source/LibJPEG/jdmaster.c b/plugins/FreeImage/Source/LibJPEG/jdmaster.c deleted file mode 100644 index fef72a21b4..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdmaster.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * jdmaster.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2002-2011 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. - * This function is used for full decompression. - */ -{ -#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); - - /* Compute core output image dimensions and DCT scaling choices. */ - jpeg_core_output_dimensions(cinfo); - -#ifdef IDCT_SCALING_SUPPORTED - - /* 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 * cinfo->block_size)); - 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 * cinfo->block_size)); - } - -#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: - cinfo->out_color_components = RGB_PIXELSIZE; - break; - 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/plugins/FreeImage/Source/LibJPEG/jdmerge.c b/plugins/FreeImage/Source/LibJPEG/jdmerge.c deleted file mode 100644 index 37444468c2..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdmerge.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * 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<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/plugins/FreeImage/Source/LibJPEG/jdpostct.c b/plugins/FreeImage/Source/LibJPEG/jdpostct.c deleted file mode 100644 index 571563d728..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdpostct.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jdsample.c b/plugins/FreeImage/Source/LibJPEG/jdsample.c deleted file mode 100644 index 7bc8885b02..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdsample.c +++ /dev/null @@ -1,361 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jdtrans.c b/plugins/FreeImage/Source/LibJPEG/jdtrans.c deleted file mode 100644 index 22dd47fb5c..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jdtrans.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * jdtrans.c - * - * Copyright (C) 1995-1997, Thomas G. Lane. - * Modified 2000-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 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; - - /* Compute output image dimensions and related values. */ - jpeg_core_output_dimensions(cinfo); - - /* 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/plugins/FreeImage/Source/LibJPEG/jerror.c b/plugins/FreeImage/Source/LibJPEG/jerror.c deleted file mode 100644 index 3da7be86a0..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jerror.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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 -#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/plugins/FreeImage/Source/LibJPEG/jerror.h b/plugins/FreeImage/Source/LibJPEG/jerror.h deleted file mode 100644 index 1cfb2b19d8..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jerror.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jfdctflt.c b/plugins/FreeImage/Source/LibJPEG/jfdctflt.c deleted file mode 100644 index 74d0d862dc..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jfdctflt.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jfdctfst.c b/plugins/FreeImage/Source/LibJPEG/jfdctfst.c deleted file mode 100644 index 8cad5f2293..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jfdctfst.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jfdctint.c b/plugins/FreeImage/Source/LibJPEG/jfdctint.c deleted file mode 100644 index 1dde58c499..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jfdctint.c +++ /dev/null @@ -1,4348 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jidctflt.c b/plugins/FreeImage/Source/LibJPEG/jidctflt.c deleted file mode 100644 index 23ae9d333b..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jidctflt.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * jidctflt.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * Modified 2010 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 - * 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 = cinfo->sample_range_limit; - int ctr; - FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ - - /* 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 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ - tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 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*3] = tmp3 + tmp4; - wsptr[DCTSIZE*4] = tmp3 - tmp4; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. */ - - 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 */ - - /* Apply signed->unsigned and prepare float->int conversion */ - z5 = wsptr[0] + ((FAST_FLOAT) CENTERJSAMPLE + (FAST_FLOAT) 0.5); - tmp10 = z5 + wsptr[4]; - tmp11 = z5 - 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 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ - tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 - tmp5; - - /* Final output stage: float->int conversion and range-limit */ - - outptr[0] = range_limit[((int) (tmp0 + tmp7)) & RANGE_MASK]; - outptr[7] = range_limit[((int) (tmp0 - tmp7)) & RANGE_MASK]; - outptr[1] = range_limit[((int) (tmp1 + tmp6)) & RANGE_MASK]; - outptr[6] = range_limit[((int) (tmp1 - tmp6)) & RANGE_MASK]; - outptr[2] = range_limit[((int) (tmp2 + tmp5)) & RANGE_MASK]; - outptr[5] = range_limit[((int) (tmp2 - tmp5)) & RANGE_MASK]; - outptr[3] = range_limit[((int) (tmp3 + tmp4)) & RANGE_MASK]; - outptr[4] = range_limit[((int) (tmp3 - tmp4)) & RANGE_MASK]; - - wsptr += DCTSIZE; /* advance pointer to next row */ - } -} - -#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibJPEG/jidctfst.c b/plugins/FreeImage/Source/LibJPEG/jidctfst.c deleted file mode 100644 index dba4216fb9..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jidctfst.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jidctint.c b/plugins/FreeImage/Source/LibJPEG/jidctint.c deleted file mode 100644 index dcdf7ce454..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jidctint.c +++ /dev/null @@ -1,5137 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/jinclude.h b/plugins/FreeImage/Source/LibJPEG/jinclude.h deleted file mode 100644 index 0a4f15146a..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jinclude.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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 . - * Otherwise, we get them from or ; we may have to - * pull in as well. - * Note that the core JPEG library does not require ; - * 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 . - */ - -#ifdef HAVE_STDDEF_H -#include -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif - -#ifdef NEED_SYS_TYPES_H -#include -#endif - -#include - -/* - * We need memory copying and zeroing functions, plus strncpy(). - * ANSI and System V implementations declare these in . - * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). - * Some systems may declare memset and memcpy in . - * - * 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 -#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 -#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/plugins/FreeImage/Source/LibJPEG/jmemansi.c b/plugins/FreeImage/Source/LibJPEG/jmemansi.c deleted file mode 100644 index b5da4743fb..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jmemansi.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 /* 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/plugins/FreeImage/Source/LibJPEG/jmemdos.c b/plugins/FreeImage/Source/LibJPEG/jmemdos.c deleted file mode 100644 index 0955047ecc..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jmemdos.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * 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 /* 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 /* 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 /* 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/plugins/FreeImage/Source/LibJPEG/jmemdosa.asm b/plugins/FreeImage/Source/LibJPEG/jmemdosa.asm deleted file mode 100644 index c6ec48b346..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jmemdosa.asm +++ /dev/null @@ -1,379 +0,0 @@ -; -; 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/plugins/FreeImage/Source/LibJPEG/jmemmac.c b/plugins/FreeImage/Source/LibJPEG/jmemmac.c deleted file mode 100644 index a6f043ed46..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jmemmac.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * 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 /* we use the MacOS memory manager */ -#include /* we use the MacOS File stuff */ -#include /* we use the MacOS HFS stuff */ -#include /* for smSystemScript */ -#include /* we use Gestalt to test for specific functionality */ - -#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<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/plugins/FreeImage/Source/LibJPEG/jmemmgr.c b/plugins/FreeImage/Source/LibJPEG/jmemmgr.c deleted file mode 100644 index f0e83fb950..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jmemmgr.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * jmemmgr.c - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 2011 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 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 /* 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) { - FMEMZERO((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) { - FMEMZERO((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/plugins/FreeImage/Source/LibJPEG/jmemname.c b/plugins/FreeImage/Source/LibJPEG/jmemname.c deleted file mode 100644 index e28b212f48..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jmemname.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * 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 /* 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 , 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 /* 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 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/plugins/FreeImage/Source/LibJPEG/jmemnobs.c b/plugins/FreeImage/Source/LibJPEG/jmemnobs.c deleted file mode 100644 index eb8c337725..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jmemnobs.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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 /* 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/plugins/FreeImage/Source/LibJPEG/jmemsys.h b/plugins/FreeImage/Source/LibJPEG/jmemsys.h deleted file mode 100644 index 6c3c6d348f..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jmemsys.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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 -#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/plugins/FreeImage/Source/LibJPEG/jmorecfg.h b/plugins/FreeImage/Source/LibJPEG/jmorecfg.h deleted file mode 100644 index 6c085c36a6..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jmorecfg.h +++ /dev/null @@ -1,369 +0,0 @@ -/* - * jmorecfg.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 1997-2011 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 _BASETSD_H /* MinGW is slightly different */ -#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ -typedef long INT32; -#endif -#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. 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/plugins/FreeImage/Source/LibJPEG/jpegint.h b/plugins/FreeImage/Source/LibJPEG/jpegint.h deleted file mode 100644 index c0d5c14202..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jpegint.h +++ /dev/null @@ -1,426 +0,0 @@ -/* - * jpegint.h - * - * Copyright (C) 1991-1997, Thomas G. Lane. - * Modified 1997-2011 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)); -}; - -/* 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 jzero_far jZeroFar -#define jcopy_sample_rows jCopySamples -#define jcopy_block_row jCopyBlocks -#define jpeg_zigzag_order jZIGTable -#define jpeg_natural_order jZAGTable -#define jpeg_natural_order7 jZAG7Table -#define jpeg_natural_order6 jZAG6Table -#define jpeg_natural_order5 jZAG5Table -#define jpeg_natural_order4 jZAG4Table -#define jpeg_natural_order3 jZAG3Table -#define jpeg_natural_order2 jZAG2Table -#define jpeg_aritab jAriTab -#endif /* NEED_SHORT_EXTERNAL_NAMES */ - - -/* 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 in jutils.c do it the hard way. - */ - -#ifndef NEED_FAR_POINTERS /* normal case, same as regular macro */ -#define FMEMZERO(target,size) MEMZERO(target,size) -#else /* 80x86 case */ -#ifdef USE_FMEM -#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) -#else -EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); -#define FMEMZERO(target,size) jzero_far(target, size) -#endif -#endif - - -/* 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)); -/* 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 */ -extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */ -extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */ -extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */ -extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */ -extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */ -extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */ - -/* Arithmetic coding probability estimation tables in jaricom.c */ -extern const INT32 jpeg_aritab[]; - -/* 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/plugins/FreeImage/Source/LibJPEG/jpeglib.h b/plugins/FreeImage/Source/LibJPEG/jpeglib.h deleted file mode 100644 index 1327cffa96..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jpeglib.h +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * jpeglib.h - * - * Copyright (C) 1991-1998, Thomas G. Lane. - * Modified 2002-2011 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 IDs for the JPEG library. - * Might be useful for tests like "#if JPEG_LIB_VERSION >= 80". - */ - -#define JPEG_LIB_VERSION 80 /* Compatibility version 8.0 */ -#define JPEG_LIB_VERSION_MAJOR 8 -#define JPEG_LIB_VERSION_MINOR 4 - - -/* 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 coefficients */ -#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_h_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 */ - - int block_size; /* the basic DCT block size: 1..16 */ - const int * natural_order; /* natural-order position array */ - int lim_Se; /* min( Se, DCTSIZE2-1 ) */ - - /* - * 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 is_baseline; /* TRUE if Baseline SOF0 encountered */ - 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 */ - - /* These fields are derived from Se of first SOS marker. - */ - int block_size; /* the basic DCT block size: 1..16 */ - const int * natural_order; /* natural-order position array for entropy decode */ - int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ - - /* 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_mem_dest jMemDest -#define jpeg_mem_src jMemSrc -#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_core_output_dimensions jCoreDimensions -#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)); - -/* Data source and destination managers: memory buffers. */ -EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, - unsigned char ** outbuffer, - unsigned long * outsize)); -EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, - unsigned char * inbuffer, - unsigned long insize)); - -/* 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_core_output_dimensions JPP((j_decompress_ptr cinfo)); -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/plugins/FreeImage/Source/LibJPEG/jpegtran.c b/plugins/FreeImage/Source/LibJPEG/jpegtran.c deleted file mode 100644 index 2193ffe377..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jpegtran.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - * jpegtran.c - * - * Copyright (C) 1995-2011, 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 a command-line user interface for JPEG transcoding. - * It is very similar to cjpeg.c, and partly to djpeg.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 /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* 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 char * scaleoption; /* -scale 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 - fprintf(stderr, "Switches for modifying the image:\n"); -#if TRANSFORMS_SUPPORTED - 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"); -#endif - fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); -#if TRANSFORMS_SUPPORTED - fprintf(stderr, " -transpose Transpose image\n"); - fprintf(stderr, " -transverse Transverse transpose image\n"); - fprintf(stderr, " -trim Drop non-transformable edge blocks\n"); -#endif - fprintf(stderr, "Switches for advanced users:\n"); -#ifdef C_ARITH_CODING_SUPPORTED - fprintf(stderr, " -arithmetic Use arithmetic coding\n"); -#endif - 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_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; - scaleoption = NULL; - copyoption = JCOPYOPT_DEFAULT; - transformoption.transform = JXFORM_NONE; - transformoption.perfect = FALSE; - transformoption.trim = 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, "scale", 4)) { - /* Scale the output image by a fraction M/N. */ - if (++argn >= argc) /* advance to next argument */ - usage(); - scaleoption = argv[argn]; - /* We must postpone processing until decompression startup. */ - - } 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); - - /* Adjust default decompression parameters */ - if (scaleoption != NULL) - if (sscanf(scaleoption, "%d/%d", - &srcinfo.scale_num, &srcinfo.scale_denom) < 1) - usage(); - - /* 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 - /* Fail right away if -perfect is given and transformation is not perfect. - */ - if (!jtransform_request_workspace(&srcinfo, &transformoption)) { - fprintf(stderr, "%s: transformation is not perfect\n", progname); - exit(EXIT_FAILURE); - } -#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/plugins/FreeImage/Source/LibJPEG/jquant1.c b/plugins/FreeImage/Source/LibJPEG/jquant1.c deleted file mode 100644 index 9d11f70669..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jquant1.c +++ /dev/null @@ -1,857 +0,0 @@ -/* - * jquant1.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2011 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 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 */ - FMEMZERO((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 */ - FMEMZERO((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++) - FMEMZERO((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/plugins/FreeImage/Source/LibJPEG/jquant2.c b/plugins/FreeImage/Source/LibJPEG/jquant2.c deleted file mode 100644 index 38fc2af7a5..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jquant2.c +++ /dev/null @@ -1,1311 +0,0 @@ -/* - * jquant2.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2011 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 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<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<>1)) * count; - c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; - c2total += ((c2 << C2_SHIFT) + ((1<>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<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. */ - FMEMZERO((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++) { - FMEMZERO((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/plugins/FreeImage/Source/LibJPEG/jutils.c b/plugins/FreeImage/Source/LibJPEG/jutils.c deleted file mode 100644 index 5b16b6d03c..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jutils.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * jutils.c - * - * Copyright (C) 1991-1996, Thomas G. Lane. - * Modified 2009-2011 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 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 -}; - -const int jpeg_natural_order7[7*7+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, 14, 21, 28, 35, - 42, 49, 50, 43, 36, 29, 22, 30, - 37, 44, 51, 52, 45, 38, 46, 53, - 54, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order6[6*6+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 41, 34, 27, - 20, 13, 21, 28, 35, 42, 43, 36, - 29, 37, 44, 45, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order5[5*5+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 12, - 19, 26, 33, 34, 27, 20, 28, 35, - 36, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order4[4*4+16] = { - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 25, 18, 11, 19, 26, 27, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order3[3*3+16] = { - 0, 1, 8, 16, 9, 2, 10, 17, - 18, - 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ - 63, 63, 63, 63, 63, 63, 63, 63 -}; - -const int jpeg_natural_order2[2*2+16] = { - 0, 1, 8, 9, - 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 macro */ -#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,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)) -#else -/* This function is for use by the FMEMZERO macro defined in jpegint.h. - * Do not call this function directly, use the FMEMZERO macro instead. - */ -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. */ -{ - register char FAR * ptr = (char FAR *) target; - register size_t count; - - for (count = bytestozero; count > 0; count--) { - *ptr++ = 0; - } -} -#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 -} diff --git a/plugins/FreeImage/Source/LibJPEG/jversion.h b/plugins/FreeImage/Source/LibJPEG/jversion.h deleted file mode 100644 index 5d4915103e..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/jversion.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * jversion.h - * - * Copyright (C) 1991-2012, 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 "8d 15-Jan-2012" - -#define JCOPYRIGHT "Copyright (C) 2012, Thomas G. Lane, Guido Vollbeding" diff --git a/plugins/FreeImage/Source/LibJPEG/rdbmp.c b/plugins/FreeImage/Source/LibJPEG/rdbmp.c deleted file mode 100644 index dfdf96ff5c..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/rdbmp.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - * rdbmp.c - * - * Copyright (C) 1994-1996, Thomas G. Lane. - * Modified 2009-2010 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 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; -} - - -METHODDEF(JDIMENSION) -get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) -/* This version is for reading 32-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++; - inptr++; /* skip the 4th byte (Alpha channel) */ - 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, get_24bit_row, or get_32bit_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; - case 32: - source->pub.get_pixel_rows = get_32bit_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; - INT32 biHeight; - 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; - } - 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; - case 32: /* RGB image + Alpha channel */ - TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); - break; - default: - ERREXIT(cinfo, JERR_BMP_BADDEPTH); - break; - } - 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); - return; - } - - if (biWidth <= 0 || biHeight <= 0) - ERREXIT(cinfo, JERR_BMP_EMPTY); - if (biPlanes != 1) - ERREXIT(cinfo, JERR_BMP_BADPLANES); - - /* 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 if (source->bits_per_pixel == 32) - row_width = (JDIMENSION) (biWidth * 4); - 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/plugins/FreeImage/Source/LibJPEG/rdcolmap.c b/plugins/FreeImage/Source/LibJPEG/rdcolmap.c deleted file mode 100644 index eebf8346c5..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/rdcolmap.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/rdgif.c b/plugins/FreeImage/Source/LibJPEG/rdgif.c deleted file mode 100644 index b0757e718f..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/rdgif.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/rdjpgcom.c b/plugins/FreeImage/Source/LibJPEG/rdjpgcom.c deleted file mode 100644 index ab09b443ff..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/rdjpgcom.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * 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, */ - -#ifdef HAVE_LOCALE_H -#include /* Bill Allombert: use locale for isprint */ -#endif -#include /* to declare isupper(), tolower() */ -#ifdef USE_SETMODE -#include /* to declare setmode()'s parameter macros */ -/* If you have setmode() but not , just delete this line: */ -#include /* to declare setmode() */ -#endif - -#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ -#ifdef __MWERKS__ -#include /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* 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/plugins/FreeImage/Source/LibJPEG/rdppm.c b/plugins/FreeImage/Source/LibJPEG/rdppm.c deleted file mode 100644 index 9dcd2dc216..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/rdppm.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/rdrle.c b/plugins/FreeImage/Source/LibJPEG/rdrle.c deleted file mode 100644 index df871e00a4..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/rdrle.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * 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 - -/* - * 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/plugins/FreeImage/Source/LibJPEG/rdswitch.c b/plugins/FreeImage/Source/LibJPEG/rdswitch.c deleted file mode 100644 index 5eebcc1e5c..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/rdswitch.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * 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 /* 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/plugins/FreeImage/Source/LibJPEG/rdtarga.c b/plugins/FreeImage/Source/LibJPEG/rdtarga.c deleted file mode 100644 index d7ffc33ebd..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/rdtarga.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/transupp.c b/plugins/FreeImage/Source/LibJPEG/transupp.c deleted file mode 100644 index 016f383d4f..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/transupp.c +++ /dev/null @@ -1,1597 +0,0 @@ -/* - * transupp.c - * - * Copyright (C) 1997-2011, 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 /* 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->output_width / - (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); - - 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->output_width / - (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); - - 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->output_height / - (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); - - 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->output_height / - (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); - - 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->output_width / - (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); - - 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->output_width / - (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); - MCU_rows = srcinfo->output_height / - (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); - - 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->output_height / - (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); - MCU_rows = srcinfo->output_width / - (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); - - 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 - * [f]x[f]{+-}{+-} - * 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; - if (*spec == 'f' || *spec == 'F') { - spec++; - info->crop_width_set = JCROP_FORCE; - } else - info->crop_width_set = JCROP_POS; - } - if (*spec == 'x' || *spec == 'X') { - /* fetch height */ - spec++; - if (! jt_read_integer(&spec, &info->crop_height)) - return FALSE; - if (*spec == 'f' || *spec == 'F') { - spec++; - info->crop_height_set = JCROP_FORCE; - } else - 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->iMCU_sample_width; - if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == - full_width / info->iMCU_sample_width) - info->output_width = MCU_cols * info->iMCU_sample_width; -} - -LOCAL(void) -trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) -{ - JDIMENSION MCU_rows; - - MCU_rows = info->output_height / info->iMCU_sample_height; - if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == - full_height / info->iMCU_sample_height) - info->output_height = MCU_rows * info->iMCU_sample_height; -} - - -/* 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). - * - * This function returns FALSE right away if -perfect is given - * and transformation is not perfect. Otherwise returns TRUE. - */ - -GLOBAL(boolean) -jtransform_request_workspace (j_decompress_ptr srcinfo, - jpeg_transform_info *info) -{ - jvirt_barray_ptr *coef_arrays; - boolean need_workspace, transpose_it; - jpeg_component_info *compptr; - JDIMENSION xoffset, yoffset; - JDIMENSION 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; - - /* Compute output image dimensions and related values. */ - jpeg_core_output_dimensions(srcinfo); - - /* Return right away if -perfect is given and transformation is not perfect. - */ - if (info->perfect) { - if (info->num_components == 1) { - if (!jtransform_perfect_transform(srcinfo->output_width, - srcinfo->output_height, - srcinfo->min_DCT_h_scaled_size, - srcinfo->min_DCT_v_scaled_size, - info->transform)) - return FALSE; - } else { - if (!jtransform_perfect_transform(srcinfo->output_width, - srcinfo->output_height, - srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size, - srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size, - info->transform)) - return FALSE; - } - } - - /* 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->output_height; - info->output_height = srcinfo->output_width; - if (info->num_components == 1) { - info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; - info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; - } else { - info->iMCU_sample_width = - srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; - info->iMCU_sample_height = - srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; - } - break; - default: - info->output_width = srcinfo->output_width; - info->output_height = srcinfo->output_height; - if (info->num_components == 1) { - info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; - info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; - } else { - info->iMCU_sample_width = - srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; - info->iMCU_sample_height = - srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; - } - 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 */ - if (info->crop_width_set == JCROP_FORCE) - info->output_width = info->crop_width; - else - info->output_width = - info->crop_width + (xoffset % info->iMCU_sample_width); - if (info->crop_height_set == JCROP_FORCE) - info->output_height = info->crop_height; - else - info->output_height = - info->crop_height + (yoffset % info->iMCU_sample_height); - /* Save x/y offsets measured in iMCUs */ - info->x_crop_offset = xoffset / info->iMCU_sample_width; - info->y_crop_offset = yoffset / info->iMCU_sample_height; - } 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->output_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->output_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->output_height); - trim_bottom_edge(info, srcinfo->output_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->output_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->output_width); - trim_bottom_edge(info, srcinfo->output_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->output_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->iMCU_sample_width); - height_in_iMCUs = (JDIMENSION) - jdiv_round_up((long) info->output_height, - (long) info->iMCU_sample_height); - 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; - } else - info->workspace_coef_arrays = NULL; - - return TRUE; -} - - -/* 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; - JDIMENSION jtemp; - UINT16 qtemp; - - /* Transpose image dimensions */ - jtemp = dstinfo->image_width; - dstinfo->image_width = dstinfo->image_height; - dstinfo->image_height = jtemp; - itemp = dstinfo->min_DCT_h_scaled_size; - dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; - dstinfo->min_DCT_v_scaled_size = itemp; - - /* 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 rotate/flip, resize, and crop operations. - */ - dstinfo->jpeg_width = info->output_width; - dstinfo->jpeg_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->jpeg_width != srcinfo->image_width || - dstinfo->jpeg_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->jpeg_width, dstinfo->jpeg_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 * cinfo.block_size - * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size - * 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/plugins/FreeImage/Source/LibJPEG/transupp.h b/plugins/FreeImage/Source/LibJPEG/transupp.h deleted file mode 100644 index 9aa0af385a..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/transupp.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * transupp.h - * - * Copyright (C) 1997-2011, 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 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.) - * The adjustment of the region dimensions may be optionally disabled. - * - * We also provide a lossless-resize option, which is kind of a lossless-crop - * operation in the DCT coefficient block domain - it discards higher-order - * coefficients and losslessly preserves lower-order coefficients of a - * sub-block. - * - * Rotate/flip transform, resize, and crop can be requested together in a - * single invocation. The crop is applied last --- that is, the crop region - * is specified in terms of the destination image after transform/resize. - * - * 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 for xoffset or yoffset, - * positive or forced for width or height. - */ - -typedef enum { - JCROP_UNSET, - JCROP_POS, - JCROP_NEG, - JCROP_FORCE -} 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; /* (forced disables adjustment) */ - JDIMENSION crop_height; /* Height of selected region */ - JCROP_CODE crop_height_set; /* (forced disables adjustment) */ - 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 iMCU_sample_width; /* destination iMCU size */ - int iMCU_sample_height; -} 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(boolean) 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/plugins/FreeImage/Source/LibJPEG/wrbmp.c b/plugins/FreeImage/Source/LibJPEG/wrbmp.c deleted file mode 100644 index 2b8146e2c0..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/wrbmp.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibJPEG/wrgif.c b/plugins/FreeImage/Source/LibJPEG/wrgif.c deleted file mode 100644 index 13f953b567..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/wrgif.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * 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 . - * 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/plugins/FreeImage/Source/LibJPEG/wrjpgcom.c b/plugins/FreeImage/Source/LibJPEG/wrjpgcom.c deleted file mode 100644 index 7d10ee66e8..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/wrjpgcom.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * 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, */ - -#ifndef HAVE_STDLIB_H /* should declare malloc() */ -extern void * malloc (); -#endif -#include /* to declare isupper(), tolower() */ -#ifdef USE_SETMODE -#include /* to declare setmode()'s parameter macros */ -/* If you have setmode() but not , just delete this line: */ -#include /* to declare setmode() */ -#endif - -#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ -#ifdef __MWERKS__ -#include /* Metrowerks needs this */ -#include /* ... and this */ -#endif -#ifdef THINK_C -#include /* 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/plugins/FreeImage/Source/LibJPEG/wrppm.c b/plugins/FreeImage/Source/LibJPEG/wrppm.c deleted file mode 100644 index 1e56d9c50e..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/wrppm.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * 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<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/plugins/FreeImage/Source/LibJPEG/wrrle.c b/plugins/FreeImage/Source/LibJPEG/wrrle.c deleted file mode 100644 index 7a00c0dd11..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/wrrle.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * 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 - -/* - * 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/plugins/FreeImage/Source/LibJPEG/wrtarga.c b/plugins/FreeImage/Source/LibJPEG/wrtarga.c deleted file mode 100644 index 65662738d9..0000000000 --- a/plugins/FreeImage/Source/LibJPEG/wrtarga.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * 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/plugins/FreeImage/Source/LibMNG/Changes b/plugins/FreeImage/Source/LibMNG/Changes deleted file mode 100644 index fbf2ac572f..0000000000 --- a/plugins/FreeImage/Source/LibMNG/Changes +++ /dev/null @@ -1,1447 +0,0 @@ ------------------------------------------------------------ - -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 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/plugins/FreeImage/Source/LibMNG/LICENSE b/plugins/FreeImage/Source/LibMNG/LICENSE deleted file mode 100644 index 5878e32a2a..0000000000 --- a/plugins/FreeImage/Source/LibMNG/LICENSE +++ /dev/null @@ -1,57 +0,0 @@ -/* ************************************************************************** */ -/* * * */ -/* * 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/plugins/FreeImage/Source/LibMNG/README b/plugins/FreeImage/Source/LibMNG/README deleted file mode 100644 index 35b12596f1..0000000000 --- a/plugins/FreeImage/Source/LibMNG/README +++ /dev/null @@ -1,36 +0,0 @@ -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/plugins/FreeImage/Source/LibMNG/README.autoconf b/plugins/FreeImage/Source/LibMNG/README.autoconf deleted file mode 100644 index 97167b7d74..0000000000 --- a/plugins/FreeImage/Source/LibMNG/README.autoconf +++ /dev/null @@ -1,213 +0,0 @@ -********************************************************************** -********************************************************************** - - ***** 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/plugins/FreeImage/Source/LibMNG/README.config b/plugins/FreeImage/Source/LibMNG/README.config deleted file mode 100644 index 97fcb31606..0000000000 --- a/plugins/FreeImage/Source/LibMNG/README.config +++ /dev/null @@ -1,104 +0,0 @@ -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/plugins/FreeImage/Source/LibMNG/README.contrib b/plugins/FreeImage/Source/LibMNG/README.contrib deleted file mode 100644 index 2d51ac50a1..0000000000 --- a/plugins/FreeImage/Source/LibMNG/README.contrib +++ /dev/null @@ -1,95 +0,0 @@ -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/plugins/FreeImage/Source/LibMNG/README.examples b/plugins/FreeImage/Source/LibMNG/README.examples deleted file mode 100644 index 9f23b5077b..0000000000 --- a/plugins/FreeImage/Source/LibMNG/README.examples +++ /dev/null @@ -1,48 +0,0 @@ -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/plugins/FreeImage/Source/LibMNG/README.footprint b/plugins/FreeImage/Source/LibMNG/README.footprint deleted file mode 100644 index ae47da2c1a..0000000000 --- a/plugins/FreeImage/Source/LibMNG/README.footprint +++ /dev/null @@ -1,46 +0,0 @@ -/* - 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/plugins/FreeImage/Source/LibMNG/README.packaging b/plugins/FreeImage/Source/LibMNG/README.packaging deleted file mode 100644 index 32fb2da8be..0000000000 --- a/plugins/FreeImage/Source/LibMNG/README.packaging +++ /dev/null @@ -1,24 +0,0 @@ -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/plugins/FreeImage/Source/LibMNG/libmng.h b/plugins/FreeImage/Source/LibMNG/libmng.h deleted file mode 100644 index 8513bf1127..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng.h +++ /dev/null @@ -1,2932 +0,0 @@ -/* ************************************************************************** */ -/* * * */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_callback_xs.c b/plugins/FreeImage/Source/LibMNG/libmng_callback_xs.c deleted file mode 100644 index e8f1efeb66..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_callback_xs.c +++ /dev/null @@ -1,1239 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_chunk_descr.c b/plugins/FreeImage/Source/LibMNG/libmng_chunk_descr.c deleted file mode 100644 index 5a4bfa0381..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_chunk_descr.c +++ /dev/null @@ -1,6090 +0,0 @@ -/* ************************************************************************** */ -/* * 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 /* 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/plugins/FreeImage/Source/LibMNG/libmng_chunk_descr.h b/plugins/FreeImage/Source/LibMNG/libmng_chunk_descr.h deleted file mode 100644 index 5126cb2775..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_chunk_descr.h +++ /dev/null @@ -1,146 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_chunk_io.c b/plugins/FreeImage/Source/LibMNG/libmng_chunk_io.c deleted file mode 100644 index a75945f063..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_chunk_io.c +++ /dev/null @@ -1,10740 +0,0 @@ -/** ************************************************************************* */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_chunk_io.h b/plugins/FreeImage/Source/LibMNG/libmng_chunk_io.h deleted file mode 100644 index b47f8639b9..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_chunk_io.h +++ /dev/null @@ -1,415 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.c b/plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.c deleted file mode 100644 index 6c8e5897f5..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.c +++ /dev/null @@ -1,4452 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.h b/plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.h deleted file mode 100644 index 96db17498e..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_chunk_prc.h +++ /dev/null @@ -1,381 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_chunk_xs.c b/plugins/FreeImage/Source/LibMNG/libmng_chunk_xs.c deleted file mode 100644 index 1c4ec2e50d..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_chunk_xs.c +++ /dev/null @@ -1,7016 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_chunks.h b/plugins/FreeImage/Source/LibMNG/libmng_chunks.h deleted file mode 100644 index 6c50d8b867..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_chunks.h +++ /dev/null @@ -1,1026 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_cms.c b/plugins/FreeImage/Source/LibMNG/libmng_cms.c deleted file mode 100644 index f215271f2a..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_cms.c +++ /dev/null @@ -1,758 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_cms.h b/plugins/FreeImage/Source/LibMNG/libmng_cms.h deleted file mode 100644 index d442a3fa6a..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_cms.h +++ /dev/null @@ -1,92 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_conf.h b/plugins/FreeImage/Source/LibMNG/libmng_conf.h deleted file mode 100644 index 5f6fdb91a5..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_conf.h +++ /dev/null @@ -1,306 +0,0 @@ -/* ************************************************************************** */ -/* * * */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_data.h b/plugins/FreeImage/Source/LibMNG/libmng_data.h deleted file mode 100644 index dd715b0989..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_data.h +++ /dev/null @@ -1,1029 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_display.c b/plugins/FreeImage/Source/LibMNG/libmng_display.c deleted file mode 100644 index 65a5c31d95..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_display.c +++ /dev/null @@ -1,7135 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_display.h b/plugins/FreeImage/Source/LibMNG/libmng_display.h deleted file mode 100644 index 3dc6ca2d91..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_display.h +++ /dev/null @@ -1,343 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_dither.c b/plugins/FreeImage/Source/LibMNG/libmng_dither.c deleted file mode 100644 index 3ba2a7069c..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_dither.c +++ /dev/null @@ -1,58 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_dither.h b/plugins/FreeImage/Source/LibMNG/libmng_dither.h deleted file mode 100644 index 250c0b9d28..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_dither.h +++ /dev/null @@ -1,45 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_error.c b/plugins/FreeImage/Source/LibMNG/libmng_error.c deleted file mode 100644 index 89501a2eae..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_error.c +++ /dev/null @@ -1,326 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_error.h b/plugins/FreeImage/Source/LibMNG/libmng_error.h deleted file mode 100644 index 14eb450a28..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_error.h +++ /dev/null @@ -1,119 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_filter.c b/plugins/FreeImage/Source/LibMNG/libmng_filter.c deleted file mode 100644 index ad57a3be90..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_filter.c +++ /dev/null @@ -1,978 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_filter.h b/plugins/FreeImage/Source/LibMNG/libmng_filter.h deleted file mode 100644 index 5ff4cb609b..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_filter.h +++ /dev/null @@ -1,69 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_hlapi.c b/plugins/FreeImage/Source/LibMNG/libmng_hlapi.c deleted file mode 100644 index ef0c2e1484..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_hlapi.c +++ /dev/null @@ -1,2995 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_jpeg.c b/plugins/FreeImage/Source/LibMNG/libmng_jpeg.c deleted file mode 100644 index 409f6df74d..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_jpeg.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_jpeg.h b/plugins/FreeImage/Source/LibMNG/libmng_jpeg.h deleted file mode 100644 index ef9dbf204d..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_jpeg.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_memory.h b/plugins/FreeImage/Source/LibMNG/libmng_memory.h deleted file mode 100644 index 9da16a460b..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_memory.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_object_prc.c b/plugins/FreeImage/Source/LibMNG/libmng_object_prc.c deleted file mode 100644 index 570d346aa6..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_object_prc.c +++ /dev/null @@ -1,6998 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_object_prc.h b/plugins/FreeImage/Source/LibMNG/libmng_object_prc.h deleted file mode 100644 index 46d201ca0e..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_object_prc.h +++ /dev/null @@ -1,690 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_objects.h b/plugins/FreeImage/Source/LibMNG/libmng_objects.h deleted file mode 100644 index ab7290fdf3..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_objects.h +++ /dev/null @@ -1,635 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_pixels.c b/plugins/FreeImage/Source/LibMNG/libmng_pixels.c deleted file mode 100644 index 9990ee67bb..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_pixels.c +++ /dev/null @@ -1,24610 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_pixels.h b/plugins/FreeImage/Source/LibMNG/libmng_pixels.h deleted file mode 100644 index 203d1c1f99..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_pixels.h +++ /dev/null @@ -1,1147 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_prop_xs.c b/plugins/FreeImage/Source/LibMNG/libmng_prop_xs.c deleted file mode 100644 index d4afc87d09..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_prop_xs.c +++ /dev/null @@ -1,2799 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_read.c b/plugins/FreeImage/Source/LibMNG/libmng_read.c deleted file mode 100644 index 3a6e49fcac..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_read.c +++ /dev/null @@ -1,1369 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_read.h b/plugins/FreeImage/Source/LibMNG/libmng_read.h deleted file mode 100644 index e6399532b7..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_read.h +++ /dev/null @@ -1,53 +0,0 @@ -/* ************************************************************************** */ -/* * * */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_trace.c b/plugins/FreeImage/Source/LibMNG/libmng_trace.c deleted file mode 100644 index ffb7b57d2e..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_trace.c +++ /dev/null @@ -1,1683 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_trace.h b/plugins/FreeImage/Source/LibMNG/libmng_trace.h deleted file mode 100644 index d8621c34c3..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_trace.h +++ /dev/null @@ -1,1474 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_types.h b/plugins/FreeImage/Source/LibMNG/libmng_types.h deleted file mode 100644 index 08086b69f2..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_types.h +++ /dev/null @@ -1,574 +0,0 @@ -/* ************************************************************************** */ -/* * 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 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 -#endif - -#ifdef MNG_INCLUDE_LCMS /* little cms by Marti Maria Saguer */ -#ifndef ZLIB_DLL -#undef FAR -#endif -#include -#endif /* MNG_INCLUDE_LCMS */ - -#ifdef MNG_INCLUDE_IJG6B /* IJG's jpgsrc6b */ -#include -#ifdef MNG_USE_SETJMP -#include /* 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 /* "calloc" & "free" & "abs" */ -#endif - -#include /* get proper integer widths */ - -#ifdef WIN32 -#if defined __BORLANDC__ -#include /* defines "memcpy" for BCB */ -#else -#include /* defines "memcpy" for other win32 platforms */ -#endif -#include /* "strncmp" + "strcmp" */ -#else /* WIN32 */ -#ifdef BSD -#include /* defines "memcpy", etc for BSD (?) */ -#else -#include /* defines "memcpy", etc for all others (???) */ -#endif -#endif /* WIN32 */ - -#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS) -#include /* 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/plugins/FreeImage/Source/LibMNG/libmng_write.c b/plugins/FreeImage/Source/LibMNG/libmng_write.c deleted file mode 100644 index 22ed3a01e4..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_write.c +++ /dev/null @@ -1,198 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_write.h b/plugins/FreeImage/Source/LibMNG/libmng_write.h deleted file mode 100644 index 31e5d1b622..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_write.h +++ /dev/null @@ -1,49 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_zlib.c b/plugins/FreeImage/Source/LibMNG/libmng_zlib.c deleted file mode 100644 index 894bc74ac7..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_zlib.c +++ /dev/null @@ -1,607 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibMNG/libmng_zlib.h b/plugins/FreeImage/Source/LibMNG/libmng_zlib.h deleted file mode 100644 index 4309344ded..0000000000 --- a/plugins/FreeImage/Source/LibMNG/libmng_zlib.h +++ /dev/null @@ -1,60 +0,0 @@ -/* ************************************************************************** */ -/* * 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/plugins/FreeImage/Source/LibPNG/ANNOUNCE b/plugins/FreeImage/Source/LibPNG/ANNOUNCE deleted file mode 100644 index e8498a379c..0000000000 --- a/plugins/FreeImage/Source/LibPNG/ANNOUNCE +++ /dev/null @@ -1,42 +0,0 @@ - -Libpng 1.5.9 - February 18, 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.5.9.tar.xz (LZMA-compressed, recommended) - libpng-1.5.9.tar.gz - libpng-1.5.9.tar.bz2 - -Source files with CRLF line endings (for Windows), without the -"configure" script - - lpng159.7z (LZMA-compressed, recommended) - lpng159.zip - -Other information: - - libpng-1.5.9-README.txt - libpng-1.5.9-LICENSE.txt - -Changes since the last public release (1.5.8): - - Rebuilt configure scripts in the tar distributions. - Removed two unused definitions from scripts/pnglibconf.h.prebuilt - Removed some unused arrays (with #ifdef) from png_read_push_finish_row(). - Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h - Fixed CVE-2011-3026 buffer overrun bug. Deal more correctly with the test - on iCCP chunk length. Also removed spurious casts that may hide problems - on 16-bit systems. - -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/plugins/FreeImage/Source/LibPNG/CHANGES b/plugins/FreeImage/Source/LibPNG/CHANGES deleted file mode 100644 index fb3a90be8c..0000000000 --- a/plugins/FreeImage/Source/LibPNG/CHANGES +++ /dev/null @@ -1,3820 +0,0 @@ -#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_ functions to be - png_set_. We now have corresponding png_get_ - 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() behavior - 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 behavior - Tested NODIV support and made it default behavior (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 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". - comment out (with #ifdef) all the new declarations 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 " 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. - Added #ifdef to remove some redundancy 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 - Use #ifdef to comment out 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 (CVE-2006-7244) - -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.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.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 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.4.0beta1 [April 20, 2006] - Enabled iTXt support (changes png_struct, thus requires so-number change). - Cleaned up PNG_ASSEMBLER_CODE_SUPPORTED vs PNG_MMX_CODE_SUPPORTED - Eliminated PNG_1_0_X and PNG_1_2_X macros. - Removed deprecated functions png_read_init, png_write_init, png_info_init, - png_permit_empty_plte, png_set_gray_1_2_4_to_8, png_check_sig, and - removed the deprecated macro PNG_MAX_UINT. - Moved "PNG_INTERNAL" parts of png.h and pngconf.h into pngintrn.h - Removed many WIN32_WCE #ifdefs (Cosmin). - Reduced dependency on C-runtime library when on Windows (Simon-Pierre) - Replaced sprintf() with png_sprintf() (Simon-Pierre) - -Version 1.4.0beta2 [April 20, 2006] - Revised makefiles and configure to avoid making links to libpng.so.* - Moved some leftover MMX-related defines from pngconf.h to pngintrn.h - Updated scripts/pngos2.def, pngw32.def, and projects/wince/png32ce.def - -Version 1.4.0beta3 [May 10, 2006] - Updated scripts/pngw32.def to comment out MMX functions. - Added PNG_NO_GET_INT_32 and PNG_NO_SAVE_INT_32 macros. - Scripts/libpng.pc.in contained "configure" style version info and would - not work with makefiles. - Revised pngconf.h and added pngconf.h.in, so makefiles and configure can - pass defines to libpng and applications. - -Version 1.4.0beta4 [May 11, 2006] - Revised configure.ac, Makefile.am, and many of the makefiles to write - their defines in pngconf.h. - -Version 1.4.0beta5 [May 15, 2006] - Added a missing semicolon in Makefile.am and Makefile.in - Deleted extraneous square brackets from configure.ac - -Version 1.4.0beta6 [June 2, 2006] - Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid - buffer overflow. - Changed sonum from 0 to 1. - Removed unused prototype for png_check_sig() from png.h - -Version 1.4.0beta7 [June 16, 2006] - Exported png_write_sig (Cosmin). - Optimized buffer in png_handle_cHRM() (Cosmin). - Set pHYs = 2835 x 2835 pixels per meter, and added - sCAL = 0.352778e-3 x 0.352778e-3 meters, in pngtest.png (Cosmin). - Added png_set_benign_errors(), png_benign_error(), png_chunk_benign_error(). - Added typedef for png_int_32 and png_uint_32 on 64-bit systems. - Added "(unsigned long)" typecast on png_uint_32 variables in printf lists. - -Version 1.4.0beta8 [June 22, 2006] - Added demonstration of user chunk support in pngtest.c, to support the - public sTER chunk and a private vpAg chunk. - -Version 1.4.0beta9 [July 3, 2006] - Removed ordinals from scripts/pngw32.def and removed png_info_int and - png_set_gray_1_2_4_to_8 entries. - Inline call of png_get_uint_32() in png_get_uint_31(). - Use png_get_uint_31() to get vpAg width and height in pngtest.c - Removed WINCE and Netware projects. - Removed standalone Y2KINFO file. - -Version 1.4.0beta10 [July 12, 2006] - Eliminated automatic copy of pngconf.h to pngconf.h.in from configure and - some makefiles, because it was not working reliably. Instead, distribute - pngconf.h.in along with pngconf.h and cause configure and some of the - makefiles to update pngconf.h from pngconf.h.in. - Added pngconf.h to DEPENDENCIES in Makefile.am - -Version 1.4.0beta11 [August 19, 2006] - Removed AC_FUNC_MALLOC from configure.ac. - Added a warning when writing iCCP profile with mismatched profile length. - Patched pnggccrd.c to assemble on x86_64 platforms. - Moved chunk header reading into a separate function png_read_chunk_header() - in pngrutil.c. The chunk header (len+sig) is now serialized in a single - operation (Cosmin). - Implemented support for I/O states. Added png_ptr member io_state, and - functions png_get_io_chunk_name() and png_get_io_state() in pngget.c - (Cosmin). - Added png_get_io_chunk_name and png_get_io_state to scripts/*.def (Cosmin). - Renamed scripts/pngw32.* to scripts/pngwin.* (Cosmin). - Removed the include directories and libraries from CFLAGS and LDFLAGS - in scripts/makefile.gcc (Cosmin). - Used png_save_uint_32() to set vpAg width and height in pngtest.c (Cosmin). - Cast to proper type when getting/setting vpAg units in pngtest.c (Cosmin). - Added pngintrn.h to the Visual C++ projects (Cosmin). - Removed scripts/list (Cosmin). - Updated copyright year in scripts/pngwin.def (Cosmin). - Removed PNG_TYPECAST_NULL and used standard NULL consistently (Cosmin). - Disallowed the user to redefine png_size_t, and enforced a consistent use - of png_size_t across libpng (Cosmin). - Changed the type of png_ptr->rowbytes, PNG_ROWBYTES() and friends - to png_size_t (Cosmin). - Removed png_convert_size() and replaced png_sizeof with sizeof (Cosmin). - Removed some unnecessary type casts (Cosmin). - Changed prototype of png_get_compression_buffer_size() and - png_set_compression_buffer_size() to work with png_size_t instead of - png_uint_32 (Cosmin). - Removed png_memcpy_check() and png_memset_check() (Cosmin). - Fixed a typo (png_byte --> png_bytep) in libpng.3 and libpng.txt (Cosmin). - Clarified that png_zalloc() does not clear the allocated memory, - and png_zalloc() and png_zfree() cannot be PNGAPI (Cosmin). - Renamed png_mem_size_t to png_alloc_size_t, fixed its definition in - pngconf.h, and used it in all memory allocation functions (Cosmin). - Renamed pngintrn.h to pngpriv.h, added a comment at the top of the file - mentioning that the symbols declared in that file are private, and - updated the scripts and the Visual C++ projects accordingly (Cosmin). - Removed circular references between pngconf.h and pngconf.h.in in - scripts/makefile.vc*win32 (Cosmin). - Removing trailing '.' from the warning and error messages (Cosmin). - Added pngdefs.h that is built by makefile or configure, instead of - pngconf.h.in (Glenn). - Detect and fix attempt to write wrong iCCP profile length. - -Version 1.4.0beta12 [October 19, 2006] - Changed "logical" to "bitwise" in the documentation. - Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h - Add a typecast to stifle compiler warning in pngrutil.c - -Version 1.4.0beta13 [November 10, 2006] - Fix potential buffer overflow in sPLT chunk handler. - Fix Makefile.am to not try to link to noexistent files. - -Version 1.4.0beta14 [November 15, 2006] - Check all exported functions for NULL png_ptr. - -Version 1.4.0beta15 [November 17, 2006] - Relocated two 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 - Add "install: all" in Makefile.am so "configure; make install" will work. - -Version 1.4.0beta16 [November 17, 2006] - Added a typecast in png_zalloc(). - -Version 1.4.0beta17 [December 4, 2006] - Changed "new_key[79] = '\0';" to "(*new_key)[79] = '\0';" in pngwutil.c - Add "png_bytep" typecast to profile while calculating length in pngwutil.c - -Version 1.4.0beta18 [December 7, 2006] - Added scripts/CMakeLists.txt - -Version 1.4.0beta19 [May 16, 2007] - Revised scripts/CMakeLists.txt - Rebuilt configure and Makefile.in with newer tools. - Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. - Added scripts/makefile.nommx - -Version 1.4.0beta20 [July 9, 2008] - Moved several PNG_HAVE_* macros from pngpriv.h to png.h because applications - calling set_unknown_chunk_location() need them. - Moved several macro definitions from pngpriv.h to pngconf.h - Merge with changes to the 1.2.X branch, as of 1.2.30beta04. - Deleted all use of the MMX assembler code and Intel-licensed optimizations. - Revised makefile.mingw - -Version 1.4.0beta21 [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.4.0beta22 [July 21, 2008] - Change "purpose" and "buffer" to png_ptr->chunkdata to avoid memory leaking. - -Version 1.4.0beta23 [July 22, 2008] - Change "chunkdata = NULL" to "png_ptr->chunkdata = NULL" several places in - png_decompress_chunk(). - -Version 1.4.0beta24 [July 25, 2008] - Change 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. - Define PNG_NO_ERROR_NUMBERS by default in pngconf.h - -Version 1.4.0beta25 [July 30, 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. - Added png_push_have_buffer() function to pngpread.c - Eliminated PNG_BIG_ENDIAN_SUPPORTED and associated png_get_* macros. - Made inline expansion of png_get_*() optional with PNG_USE_READ_MACROS. - Eliminated all PNG_USELESS_TESTS and PNG_CORRECT_PALETTE_SUPPORTED code. - Synced contrib directory and configure files with libpng-1.2.30beta06. - Eliminated no-longer-used pngdefs.h (but it's still built in the makefiles) - Relocated a misplaced "#endif /* PNG_NO_WRITE_FILTER */" in pngwutil.c - -Version 1.4.0beta26 [August 4, 2008] - Removed png_push_have_buffer() function in pngpread.c. It increased the - compiled library size slightly. - 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. - Updated contrib/visupng/cexcept.h to version 2.0.1 - Added PNG_LITERAL_CHARACTER macros for #, [, and ]. - -Version 1.4.0beta27 [August 5, 2008] - Revised usage of PNG_LITERAL_SHARP in pngerror.c. - Moved newline character from individual png_debug messages into the - png_debug macros. - Allow user to #define their own png_debug, png_debug1, and png_debug2. - -Version 1.4.0beta28 [August 5, 2008] - Revised usage of PNG_LITERAL_SHARP in pngerror.c. - Added PNG_STRING_NEWLINE macro - -Version 1.4.0beta29 [August 9, 2008] - Revised usage of PNG_STRING_NEWLINE to work on non-ISO compilers. - Added PNG_STRING_COPYRIGHT macro. - Added non-ISO versions of png_debug macros. - -Version 1.4.0beta30 [August 14, 2008] - Added premultiplied alpha feature (Volker Wiendl). - -Version 1.4.0beta31 [August 18, 2008] - Moved png_set_premultiply_alpha from pngtrans.c to pngrtran.c - Removed extra crc check at the end of png_handle_cHRM(). Bug introduced - in libpng-1.4.0beta20. - -Version 1.4.0beta32 [August 19, 2008] - Added PNG_WRITE_FLUSH_SUPPORTED block around new png_flush() call. - Revised PNG_NO_STDIO version of png_write_flush() - -Version 1.4.0beta33 [August 20, 2008] - Added png_get|set_chunk_cache_max() to limit the total number of sPLT, - text, and unknown chunks that can be stored. - -Version 1.4.0beta34 [September 6, 2008] - Shortened tIME_string to 29 bytes in pngtest.c - Fixed off-by-one error introduced in png_push_read_zTXt() function in - libpng-1.2.30beta04/pngpread.c (Harald van Dijk) - -Version 1.4.0beta35 [October 6, 2008] - Changed "trans_values" to "trans_color". - Changed so-number from 0 to 14. Some OS do not like 0. - 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.4.0beta36 [October 25, 2008] - Sync with tEXt vulnerability fix in libpng-1.2.33rc02. - -Version 1.4.0beta37 [November 13, 2008] - Added png_check_cHRM in png.c and moved checking from pngget.c, pngrutil.c, - and pngwrite.c - -Version 1.4.0beta38 [November 22, 2008] - Added check for zero-area RGB cHRM triangle in png_check_cHRM() and - png_check_cHRM_fixed(). - -Version 1.4.0beta39 [November 23, 2008] - Revised png_warning() to write its message on standard output by default - when warning_fn is NULL. - -Version 1.4.0beta40 [November 24, 2008] - Eliminated png_check_cHRM(). Instead, always use 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. - -Version 1.4.0beta41 [November 26, 2008] - Fixed string vs pointer-to-string error in png_check_keyword(). - Rearranged test expressions in png_check_cHRM_fixed() to avoid internal - overflows. - Added PNG_NO_CHECK_cHRM conditional. - -Version 1.4.0beta42, 43 [December 1, 2008] - Merge png_debug with version 1.2.34beta04. - -Version 1.4.0beta44 [December 6, 2008] - Removed redundant check for key==NULL before calling png_check_keyword() - to ensure that new_key gets initialized and removed extra warning - (Merge with version 1.2.34beta05 -- Arvan Pritchard). - -Version 1.4.0beta45 [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.4.0beta46 [December 10, 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.4.0beta47 [December 15, 2008] - Support for dithering was disabled by default, because it has never - been well tested and doesn't work very well. The code has not - been removed, however, and can be enabled by building libpng with - PNG_READ_DITHER_SUPPORTED defined. - -Version 1.4.0beta48 [February 14, 2009] - Added new exported function png_calloc(). - Combined several instances of png_malloc(); png_memset() into png_calloc(). - Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 - but was never defined. - -Version 1.4.0beta49 [February 28, 2009] - Added png_fileno() macro to pngconf.h, used in pngwio.c - Corrected order of #ifdef's in png_debug definition in png.h - Fixed bug introduced in libpng-1.4.0beta48 with the memset arguments - for pcal_params. - Fixed order of #ifdef directives in the png_debug defines in png.h - (bug introduced in libpng-1.2.34/1.4.0beta29). - Revised comments in png_set_read_fn() and png_set_write_fn(). - -Version 1.4.0beta50 [March 18, 2009] - Use png_calloc() instead of png_malloc() to allocate big_row_buf when - reading an interlaced file, to avoid a possible UMR. - Undid revision of PNG_NO_STDIO version of png_write_flush(). Users - having trouble with fflush() can build with PNG_NO_WRITE_FLUSH defined - or supply their own flush_fn() replacement. - Revised libpng*.txt and png.h documentation about use of png_write_flush() - and png_set_write_fn(). - Removed fflush() from pngtest.c. - Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h - -Version 1.4.0beta51 [March 21, 2009] - Removed new png_fileno() macro from pngconf.h . - -Version 1.4.0beta52 [March 27, 2009] - Relocated png_do_chop() ahead of building gamma tables in pngrtran.c - This avoids building 16-bit gamma tables unnecessarily. - Removed fflush() from pngtest.c. - Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h - Added a section on differences between 1.0.x and 1.2.x to libpng.3/libpng.txt - -Version 1.4.0beta53 [April 1, 2009] - Removed some remaining MMX macros from pngpriv.h - Fixed potential memory leak of "new_name" in png_write_iCCP() (Ralph Giles) - -Version 1.4.0beta54 [April 13, 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. - Eliminated internal use of setjmp() in pngread.c and pngwrite.c - Reordered ancillary chunks in pngtest.png to be the same as what - pngtest now produces, and made some cosmetic changes to pngtest output. - Eliminated deprecated png_read_init_3() and png_write_init_3() functions. - -Version 1.4.0beta55 [April 15, 2009] - Simplified error handling in pngread.c and pngwrite.c by putting - the new png_read_cleanup() and png_write_cleanup() functions inline. - -Version 1.4.0beta56 [April 25, 2009] - 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.4.0beta57 [May 2, 2009] - Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 - but was never defined (again). - Rebuilt configure scripts with autoconf-2.63 instead of 2.62 - Removed pngprefs.h and MMX from makefiles - -Version 1.4.0beta58 [May 14, 2009] - Changed pngw32.def to pngwin.def in makefile.mingw (typo was introduced - in beta57). - Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) - -Version 1.4.0beta59 [May 15, 2009] - Reformated sources in libpng style (3-space intentation, comment format) - Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG) - Added sections about the git repository and our coding style to the - documentation - Relocated misplaced #endif in pngwrite.c, sCAL chunk handler. - -Version 1.4.0beta60 [May 19, 2009] - 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.4.0beta61 [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. - More reformatting of comments, mostly to capitalize sentences. - -Version 1.4.0beta62 [June 2, 2009] - 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 - Reformatted several remaining "else statement" into two lines. - Added a section to the libpng documentation about using png_get_io_ptr() - in configure scripts to detect the presence of libpng. - -Version 1.4.0beta63 [June 15, 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. - -Version 1.4.0beta64 [June 24, 2009] - Eliminated PNG_LEGACY_SUPPORTED code. - Moved the various unknown chunk macro definitions outside of the - PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. - -Version 1.4.0beta65 [June 26, 2009] - Added a reference to the libpng license in each file. - -Version 1.4.0beta66 [June 27, 2009] - Refer to the libpng license instead of the libpng license in each file. - -Version 1.4.0beta67 [July 6, 2009] - Relocated INVERT_ALPHA within png_read_png() and png_write_png(). - Added high-level API transform PNG_TRANSFORM_GRAY_TO_RGB. - Added an "xcode" project to the projects directory (Alam Arias). - -Version 1.4.0beta68 [July 19, 2009] - Avoid some tests in filter selection in pngwutil.c - -Version 1.4.0beta69 [July 25, 2009] - Simplified the new filter-selection test. This runs faster in the - common "PNG_ALL_FILTERS" and PNG_FILTER_NONE cases. - Removed extraneous declaration from the new call to png_read_gray_to_rgb() - (bug introduced in libpng-1.4.0beta67). - Fixed up xcode project (Alam Arias) - Added a prototype for png_64bit_product() in png.c - -Version 1.4.0beta70 [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.4.0beta71 [July 29, 2009] - Rebuilt configure scripts with autoconf-2.64. - -Version 1.4.0beta72 [August 1, 2009] - Replaced *.tar.lzma with *.tar.xz in distribution. Get the xz codec - from . - -Version 1.4.0beta73 [August 1, 2009] - Reject attempt to write iCCP chunk with negative embedded profile length - (JD Chen) (CVE-2009-5063). - -Version 1.4.0beta74 [August 8, 2009] - Changed png_ptr and info_ptr member "trans" to "trans_alpha". - -Version 1.4.0beta75 [August 21, 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.4.0beta76 [August 22, 2009] - Moved an incorrectly located test in png_read_row() in pngread.c - -Version 1.4.0beta77 [August 27, 2009] - Removed lpXYZ.tar.bz2 (with CRLF), KNOWNBUG, libpng-x.y.z-KNOWNBUG.txt, - and the "noconfig" files from the distribution. - Moved CMakeLists.txt from scripts into the main libpng directory. - Various bugfixes and improvements to CMakeLists.txt (Philip Lowman) - -Version 1.4.0beta78 [August 31, 2009] - Converted all PNG_NO_* tests to PNG_*_SUPPORTED everywhere except pngconf.h - Eliminated PNG_NO_FREE_ME and PNG_FREE_ME_SUPPORTED macros. - Use png_malloc plus a loop instead of png_calloc() to initialize - row_pointers in png_read_png(). - -Version 1.4.0beta79 [September 1, 2009] - Eliminated PNG_GLOBAL_ARRAYS and PNG_LOCAL_ARRAYS; always use local arrays. - Eliminated PNG_CALLOC_SUPPORTED macro and always provide png_calloc(). - -Version 1.4.0beta80 [September 17, 2009] - Removed scripts/libpng.icc - Changed typecast of filler from png_byte to png_uint_16 in png_set_filler(). - (Dennis Gustafsson) - Fixed typo introduced in beta78 in pngtest.c ("#if def " should be "#ifdef ") - -Version 1.4.0beta81 [September 23, 2009] - Eliminated unused PNG_FLAG_FREE_* defines from pngpriv.h - Expanded TAB characters in pngrtran.c - Removed PNG_CONST from all "PNG_CONST PNG_CHNK" declarations to avoid - compiler complaints about doubly declaring things "const". - Changed all "#if [!]defined(X)" to "if[n]def X" where possible. - Eliminated unused png_ptr->row_buf_size - -Version 1.4.0beta82 [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 - -Version 1.4.0beta83 [September 25, 2009] - Revised png_check_IHDR() to eliminate bogus complaint about filter_type. - -Version 1.4.0beta84 [September 30, 2009] - Fixed some inconsistent indentation in pngconf.h - Revised png_check_IHDR() to add a test for width variable less than 32-bit. - -Version 1.4.0beta85 [October 1, 2009] - Revised png_check_IHDR() again, to check info_ptr members instead of - the contents of the returned parameters. - -Version 1.4.0beta86 [October 9, 2009] - Updated the "xcode" project (Alam Arias). - Eliminated a shadowed declaration of "pp" in png_handle_sPLT(). - -Version 1.4.0rc01 [October 19, 2009] - Trivial cosmetic changes. - -Version 1.4.0beta87 [October 30, 2009] - Moved version 1.4.0 back into beta. - -Version 1.4.0beta88 [October 30, 2009] - Revised libpng*.txt section about differences between 1.2.x and 1.4.0 - because most of the new features have now been ported back to 1.2.41 - -Version 1.4.0beta89 [November 1, 2009] - More bugfixes and improvements to CMakeLists.txt (Philip Lowman) - Removed a harmless extra png_set_invert_alpha() from pngwrite.c - 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.4.0beta90 [November 2, 2009] - Removed all remaining WIN32_WCE #ifdefs except those involving the - time.h "tm" structure - -Version 1.4.0beta91 [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.4.0beta92 [November 4, 2009] - 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 - Revised libpng*.txt to describe differences from 1.2.40 to 1.4.0 (instead - of differences from 1.2.41 to 1.4.0) - -Version 1.4.0beta93 [November 7, 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". - They should work but still need to be updated to remove - references to pnggccrd.c or pngvcrd.c and ASM building. - Added README.txt to the beos, cbuilder5, netware, and xcode projects warning - that they need to be updated, to remove references to pnggccrd.c and - pngvcrd.c and to depend on pngpriv.h - Removed three direct references to read_info_ptr members in pngtest.c - that were detected by the new PNG_DEPSTRUCT macro. - Moved the png_debug macro definitions and the png_read_destroy(), - png_write_destroy() and png_far_to_near() prototypes from png.h - to pngpriv.h (John Bowler) - Moved the synopsis lines for png_read_destroy(), png_write_destroy() - png_debug(), png_debug1(), and png_debug2() from libpng.3 to libpngpf.3. - -Version 1.4.0beta94 [November 9, 2009] - Removed the obsolete, unused pnggccrd.c and pngvcrd.c files. - Updated CMakeLists.txt to add "-DPNG_CONFIGURE_LIBPNG" to the definitions. - Removed dependency of pngtest.o on pngpriv.h in the makefiles. - Only #define PNG_DEPSTRUCT, etc. in pngconf.h if not already defined. - -Version 1.4.0beta95 [November 10, 2009] - Changed png_check_sig() to !png_sig_cmp() in contrib programs. - Added -DPNG_CONFIGURE_LIBPNG to contrib/pngminm/*/makefile - Changed png_check_sig() to !png_sig_cmp() in contrib programs. - Corrected the png_get_IHDR() call in contrib/gregbook/readpng2.c - Changed pngminim/*/gather.sh to stop trying to remove pnggccrd.c and pngvcrd.c - Added dependency on pngpriv.h in contrib/pngminim/*/makefile - -Version 1.4.0beta96 [November 12, 2009] - Renamed scripts/makefile.wce to scripts/makefile.cegcc - Revised Makefile.am to use libpng.sys while building libpng.so - so that only PNG_EXPORT functions are exported. - Removed the deprecated png_check_sig() function/macro. - Removed recently removed function names from scripts/*.def - Revised pngtest.png to put chunks in the same order written by pngtest - (evidently the same change made in libpng-1.0beta54 was lost). - Added PNG_PRIVATE macro definition in pngconf.h for possible future use. - -Version 1.4.0beta97 [November 13, 2009] - Restored pngtest.png to the libpng-1.4.0beta7 version. - Removed projects/beos and netware.txt; no one seems to be supporting them. - Revised Makefile.in - -Version 1.4.0beta98 [November 13, 2009] - Added the "xcode" project to zip distributions, - Fixed a typo in scripts/pngwin.def introduced in beta97. - -Version 1.4.0beta99 [November 14, 2009] - Moved libpng-config.in and libpng.pc-configure.in out of the scripts - directory, to libpng-config.in and libpng-pc.in, respectively, and - modified Makefile.am and configure.ac accordingly. Now "configure" - needs nothing from the "scripts" directory. - Avoid redefining PNG_CONST in pngconf.h - -Version 1.4.0beta100 [November 14, 2009] - Removed ASM builds from projects/visualc6 and projects/visualc71 - Removed scripts/makefile.nommx and makefile.vcawin32 - Revised CMakeLists.txt to account for new location of libpng-config.in - and libpng-pc.in - Updated INSTALL to reflect removal and relocation of files. - -Version 1.4.0beta101 [November 14, 2009] - Restored the binary files (*.jpg, *.png, some project files) that were - accidentally deleted from the zip and 7z distributions when the xcode - project was added. - -Version 1.4.0beta102 [November 18, 2009] - Added libpng-config.in and libpng-pc.in to the zip and 7z distributions. - Fixed a typo in projects/visualc6/pngtest.dsp, introduced in beta100. - Moved descriptions of makefiles and other scripts out of INSTALL into - scripts/README.txt - Updated the copyright year in scripts/pngwin.rc from 2006 to 2009. - -Version 1.4.0beta103 [November 21, 2009] - Removed obsolete comments about ASM from projects/visualc71/README_zlib.txt - Align row_buf on 16-byte boundary in memory. - Restored the PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED guard around the call - to png_flush() after png_write_IEND(). See 1.4.0beta32, 1.4.0beta50 - changes above and 1.2.30, 1.2.30rc01 and rc03 in 1.2.41 CHANGES. Someone - needs this feature. - Make the 'png_jmpbuf' macro expand to a call that records the correct - longjmp function as well as returning a pointer to the setjmp - jmp_buf buffer, and marked direct access to jmpbuf 'deprecated'. - (John Bowler) - -Version 1.4.0beta104 [November 22, 2009] - Removed png_longjmp_ptr from scripts/*.def and libpng.3 - Rebuilt configure scripts with autoconf-2.65 - -Version 1.4.0beta105 [November 25, 2009] - Use fast integer PNG_DIVIDE_BY_255() or PNG_DIVIDE_BY_65535() - to accomplish alpha premultiplication when - PNG_READ_COMPOSITE_NODIV_SUPPORTED is defined. - Changed "/255" to "/255.0" in background calculations to make it clear - that the 255 is used as a double. - -Version 1.4.0beta106 [November 27, 2009] - Removed premultiplied alpha feature. - -Version 1.4.0beta107 [December 4, 2009] - Updated README - Added "#define PNG_NO_PEDANTIC_WARNINGS" in the libpng source files. - Removed "-DPNG_CONFIGURE_LIBPNG" from the makefiles and projects. - 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/libpng15 instead of in - $prefix/include/libpng/libpng15. - -Version 1.4.0beta108 [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.4.0beta109 [December 13, 2009] - Added "bit_depth" parameter to the private png_build_gamma_table() function. - Pass bit_depth=8 to png_build_gamma_table() when bit_depth is 16 but the - PNG_16_TO_8 transform has been set, to avoid unnecessary build of 16-bit - tables. - -Version 1.4.0rc02 [December 20, 2009] - Declared png_cleanup_needed "volatile" in pngread.c and pngwrite.c - -Version 1.4.0rc03 [December 22, 2009] - Renamed libpng-pc.in back to libpng.pc.in and revised CMakeLists.txt - (revising the change in 1.4.0beta99) - -Version 1.4.0rc04 [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.4.0rc05 [December 25, 2009] - Changed "libpng-pc.in" to "libpng.pc.in" in configure.ac, configure, and - Makefile.in to be consistent with changes in libpng-1.4.0rc03 - -Version 1.4.0rc06 [December 29, 2009] - Reverted the gamma_table changes from libpng-1.4.0beta109. - Fixed some indentation errors. - -Version 1.4.0rc07 [January 1, 2010] - Revised libpng*.txt and libpng.3 about 1.2.x->1.4.x differences. - Use png_calloc() instead of png_malloc(); png_memset() in pngrutil.c - Update copyright year to 2010. - -Version 1.4.0rc08 [January 2, 2010] - Avoid deprecated references to png_ptr-io_ptr and png_ptr->error_ptr - in pngtest.c - -Version 1.4.0 [January 3, 2010] - No changes. - -Version 1.4.1beta01 [January 8, 2010] - Updated CMakeLists.txt for consistent indentation and to avoid an - unclosed if-statement warning (Philip Lowman). - Revised Makefile.am and Makefile.in to remove references to Y2KINFO, - KNOWNBUG, and libpng.la (Robert Schwebel). - Revised the makefiles to install the same files and symbolic - links as configure, except for libpng.la and libpng14.la. - Make png_set|get_compression_buffer_size() available even when - PNG_WRITE_SUPPORTED is not enabled. - Revised Makefile.am and Makefile.in to simplify their maintenance. - Revised scripts/makefile.linux to install a link to libpng14.so.14.1 - -Version 1.4.1beta02 [January 9, 2010] - Revised the rest of the makefiles to install a link to libpng14.so.14.1 - -Version 1.4.1beta03 [January 10, 2010] - Removed png_set_premultiply_alpha() from scripts/*.def - -Version 1.4.1rc01 [January 16, 2010] - No changes. - -Version 1.4.1beta04 [January 23, 2010] - Revised png_decompress_chunk() to improve speed and memory usage when - decoding large chunks. - Added png_set|get_chunk_malloc_max() functions. - -Version 1.4.1beta05 [January 26, 2010] - Relocated "int k" declaration in pngtest.c to minimize its scope. - -Version 1.4.1beta06 [January 28, 2010] - Revised png_decompress_chunk() to use a two-pass method suggested by - John Bowler. - -Version 1.4.1beta07 [February 6, 2010] - Folded some long lines in the source files. - Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, - and a PNG_USER_LIMITS_SUPPORTED flag. - Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as - png_ptr->png_user_chunk_malloc_max. - Revised png_push_save_buffer() to do fewer but larger png_malloc() calls. - -Version 1.4.1beta08 [February 6, 2010] - Minor cleanup and updating of dates and copyright year. - -Version 1.5.0beta01 [February 7, 2010] - Moved declaration of png_struct into private pngstruct.h and png_info - into pnginfo.h - -Version 1.4.1beta09 and 1.5.0beta02 [February 7, 2010] - Reverted to original png_push_save_buffer() code. - -Version 1.4.1beta10 and 1.5.0beta03 [February 8, 2010] - Return allocated "old_buffer" in png_push_save_buffer() before - calling png_error(), to avoid a potential memory leak. - Updated configure script to use SO number 15. - -Version 1.5.0beta04 [February 9, 2010] - Removed malformed "incomplete struct declaration" of png_info from png.h - -Version 1.5.0beta05 [February 12, 2010] - Removed PNG_DEPSTRUCT markup in pngstruct.h and pnginfo.h, and undid the - linewrapping that it entailed. - Revised comments in pngstruct.h and pnginfo.h and added pointers to - the libpng license. - Changed PNG_INTERNAL to PNG_EXPOSE_INTERNAL_STRUCTURES - Removed the cbuilder5 project, which has not been updated to 1.4.0. - -Version 1.4.1beta12 and 1.5.0beta06 [February 14, 2010] - Fixed type declaration of png_get_chunk_malloc_max() in pngget.c (Daisuke - Nishikawa) - -Version 1.5.0beta07 [omitted] - -Version 1.5.0beta08 [February 19, 2010] - Changed #ifdef PNG_NO_STDIO_SUPPORTED to #ifdef PNG_NO_CONSOLE_IO_SUPPORTED - wherever png_snprintf() is used to construct error and warning messages. - Noted in scripts/makefile.mingw that it expects to be run under MSYS. - Removed obsolete unused MMX-querying support from contrib/gregbook - Added exported png_longjmp() function. - Removed the AIX redefinition of jmpbuf in png.h - Added -D_ALLSOURCE in configure.ac, makefile.aix, and CMakeLists.txt - when building on AIX. - -Version 1.5.0beta09 [February 19, 2010] - Removed -D_ALLSOURCE from configure.ac, makefile.aix, and CMakeLists.txt. - Changed the name of png_ptr->jmpbuf to png_ptr->png_jmpbuf in pngstruct.h - -Version 1.5.0beta10 [February 25, 2010] - Removed unused gzio.c from contrib/pngminim gather and makefile scripts - Removed replacement error handlers from contrib/gregbook. Because of - the new png_longjmp() function they are no longer needed. - -Version 1.5.0beta11 [March 6, 2010] - Removed checking for already-included setjmp.h from pngconf.h - Fixed inconsistent indentations and made numerous cosmetic changes. - Revised the "SEE ALSO" style of libpng.3, libpngpf.3, and png.5 - -Version 1.5.0beta12 [March 9, 2010] - Moved "#include png.h" inside pngpriv.h and removed "#include png.h" from - the source files, along with "#define PNG_EXPOSE_INTERNAL_STRUCTURES" - and "#define PNG_NO_PEDANTIC_WARNINGS" (John Bowler). - Created new pngdebug.h and moved debug definitions there. - -Version 1.5.0beta13 [March 10, 2010] - Protect pngstruct.h, pnginfo.h, and pngdebug.h from being included twice. - Revise the "#ifdef" blocks in png_inflate() so it will compile when neither - PNG_USER_CHUNK_MALLOC_MAX nor PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED - is defined. - Removed unused png_measure_compressed_chunk() from pngpriv.h and libpngpf.3 - Moved the 'config.h' support from pngconf.h to pngpriv.h - Removed PNGAPI from the png_longjmp_ptr typedef. - Eliminated dependence of pngtest.c on the private pngdebug.h file. - Make all png_debug macros into *unterminated* statements or - expressions (i.e. a trailing ';' must always be added) and correct - the format statements in various png_debug messages. - -Version 1.5.0beta14 [March 14, 2010] - Removed direct access to png_ptr->io_ptr from the Windows code in pngtest.c - Revised Makefile.am to account for recent additions and replacements. - Corrected CE and OS/2 DEF files (scripts/png*def) for symbols removed and - added ordinal numbers to the Windows DEF file and corrected the duplicated - ordinal numbers on CE symbols that are commented out. - Added back in export symbols that can be present in the Windows build but - are disabled by default. - PNG_EXPORT changed to include an 'ordinal' field for DEF file generation. - PNG_CALLBACK added to make callback definitions uniform. PNGAPI split - into PNGCAPI (base C form), PNGAPI (exports) and PNGCBAPI (callbacks), - and appropriate changes made to all files. Cygwin builds re-hinged to - allow procedure call standard changes and to remove the need for the DEF - file (fixes build on Cygwin). - Enabled 'attribute' warnings that are relevant to library APIs and callbacks. - Changed rules for generation of the various symbol files and added a new - rule for a DEF file (which is also added to the distribution). - Updated the symbol file generation to stop it adding spurious spaces - to EOL (coming from preprocessor macro expansion). Added a facility - to join tokens in the output and rewrite *.dfn to use this. - Eliminated scripts/*.def in favor of libpng.def; updated projects/visualc71 - and removed scripts/makefile.cygwin. - Made PNG_BUILD_DLL safe: it can be set whenever a DLL is being built. - Removed the include of sys/types.h - apparently unnecessary now on the - platforms on which it happened (all but Mac OS and RISC OS). - Moved the Mac OS test into pngpriv.h (the only place it is used.) - -Version 1.5.0beta15 [March 17, 2010] - Added symbols.chk target to Makefile.am to validate the symbols in png.h - against the new DEF file scripts/symbols.def. - Changed the default DEF file back to pngwin.def. - Removed makefile.mingw. - Eliminated PNG_NO_EXTERN and PNG_ALL_EXTERN - -Version 1.5.0beta16 [April 1, 2010] - Make png_text_struct independent of PNG_iTXt_SUPPORTED, so that - fields are initialized in all configurations. The READ/WRITE - macros (PNG_(READ|WRITE)_iTXt_SUPPORTED) still function as - before to disable code to actually read or write iTXt chunks - and iTXt_SUPPORTED can be used to detect presence of either - read or write support (but it is probably better to check for - the one actually required - read or write.) - Combined multiple png_warning() calls for a single error. - Restored the macro definition of png_check_sig(). - -Version 1.5.0beta17 [April 17, 2010] - Added some "(long)" typecasts to printf calls in png_handle_cHRM(). - Documented the fact that png_set_dither() was disabled since libpng-1.4.0. - Reenabled png_set_dither() but renamed it to png_set_quantize() to reflect - more accurately what it actually does. At the same time, renamed - the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros to - PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS. - Added some "(long)" typecasts to printf calls in png_handle_cHRM(). - Freeze build-time only configuration in the build. - In all prior versions of libpng most configuration options - controlled by compiler #defines had to be repeated by the - application code that used libpng. This patch changes this - so that compilation options that can only be changed at build - time are frozen in the build. Options that are compiler - dependent (and those that are system dependent) are evaluated - each time - pngconf.h holds these. Options that can be changed - per-file in the application are in png.h. Frozen options are - in the new installed header file pnglibconf.h (John Bowler) - Removed the xcode project because it has not been updated to work - with libpng-1.5.0. - Removed the ability to include optional pngusr.h - -Version 1.5.0beta18 [April 17, 2010] - Restored the ability to include optional pngusr.h - Moved replacements for png_error() and png_warning() from the - contrib/pngminim project to pngerror.c, for use when warnings or - errors are disabled via PNG_NO_WARN or PNG_NO_ERROR_TEXT, to avoid - storing unneeded error/warning text. - Updated contrib/pngminim project to work with the new pnglibconf.h - Added some PNG_NO_* defines to contrib/pngminim/*/pngusr.h to save space. - -Version 1.5.0beta19 [April 24, 2010] - Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the functions - to read and write ints to be disabled independently of PNG_USE_READ_MACROS, - which allows libpng to be built with the functions even though the default - is to use the macros - this allows applications to choose at app build - time whether or not to use macros (previously impossible because the - functions weren't in the default build.) - Changed Windows calling convention back to __cdecl for API functions. - For Windows/x86 platforms only: - __stdcall is no longer needed for Visual Basic, so libpng-1.5.0 uses - __cdecl throughout (both API functions and callbacks) on Windows/x86 - platforms. - Replaced visualc6 and visualc71 projects with new vstudio project - Relaxed the overly-restrictive permissions of some files. - -Version 1.5.0beta20 [April 24, 2010] - Relaxed more overly-restrictive permissions of some files. - -Version 1.5.0beta21 [April 27, 2010] - Removed some unwanted binary bytes and changed CRLF to NEWLINE in the new - vstudio project files, and some trivial editing of some files in the - scripts directory. - Set PNG_NO_READ_BGR, PNG_NO_IO_STATE, and PNG_NO_TIME_RFC1123 in - contrib/pngminim/decoder/pngusr.h to make a smaller decoder application. - -Version 1.5.0beta22 [April 28, 2010] - Fixed dependencies of GET_INT_32 - it does not require READ_INT_FUNCTIONS - because it has a macro equivalent. - Improved the options.awk script; added an "everything off" option. - Revised contrib/pngminim to use the "everything off" option in pngusr.dfa. - -Version 1.5.0beta23 [April 29, 2010] - Corrected PNG_REMOVED macro to take five arguments. - The macro was documented with two arguments (name,ordinal), however - the symbol checking .dfn files assumed five arguments. The five - argument form seems more useful so it is changed to that. - Corrected PNG_UNKNOWN_CHUNKS_SUPPORTED to PNG_HANDLE_AS_UNKNOWN_SUPPORTED - in gregbook/readpng2.c - Corrected protection of png_get_user_transform_ptr. The API declaration in - png.h is removed if both READ and WRITE USER_TRANSFORM are turned off - but was left defined in pngtrans.c - Added logunsupported=1 to cause pnglibconf.h to document disabled options. - This makes the installed pnglibconf.h more readable but causes no - other change. The intention is that users of libpng will find it - easier to understand if an API they need is missing. - Include png_reset_zstream() in png.c only when PNG_READ_SUPPORTED is defined. - Removed dummy_inflate.c from contrib/pngminim/encoder - Removed contrib/pngminim/*/gather.sh; gathering is now done in the makefile. - -Version 1.5.0beta24 [May 7, 2010] - Use bitwise "&" instead of arithmetic mod in pngrutil.c calculation of the - offset of the png_ptr->rowbuf pointer into png_ptr->big_row_buf. - Added more blank lines for readability. - -Version 1.5.0beta25 [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.5.0beta26 [June 18, 2010] - In pngpread.c: png_push_process_row() add check for too many rows. - -Version 1.5.0beta27 [June 18, 2010] - Removed the check added in beta25 as it is now redundant. - -Version 1.5.0beta28 [June 20, 2010] - Rewrote png_process_IDAT_data to consistently treat extra data as warnings - and handle end conditions more cleanly. - Removed the new (beta26) check in png_push_process_row(). - -Version 1.5.0beta29 [June 21, 2010] - Revised scripts/options.awk to work on Sunos (but still doesn't work) - Added comment to options.awk and contrib/pngminim/*/makefile to try nawk. - -Version 1.5.0beta30 [June 22, 2010] - Stop memory leak when reading a malformed sCAL chunk. - -Version 1.5.0beta31 [June 26, 2010] - Revised pngpread.c patch of beta28 to avoid an endless loop. - Removed some trailing blanks. - -Version 1.5.0beta32 [June 26, 2010] - Removed leftover scripts/options.patch and scripts/options.rej - -Version 1.5.0beta33 [July 6, 3010] - Made FIXED and FLOATING options consistent in the APIs they enable and - disable. Corrected scripts/options.awk to handle both command line - options and options specified in the .dfa files. - Changed char *msg to PNG_CONST char *msg in pngrutil.c - Make png_set_sRGB_gAMA_and_cHRM set values using either the fixed or - floating point APIs, but not both. - Reversed patch to remove error handler when the jmp_buf is stored in the - main program structure, not the png_struct. - The error handler is needed because the default handler in libpng will - always use the jmp_buf in the library control structure; this is never - set. The gregbook code is a useful example because, even though it - uses setjmp/longjmp, it shows how error handling can be implemented - using control mechanisms not directly supported by libpng. The - technique will work correctly with mechanisms such as Microsoft - Structure Exceptions or C++ exceptions (compiler willing - note that gcc - does not by default support interworking of C and C++ error handling.) - Reverted changes to call png_longjmp in contrib/gregbook where it is not - appropriate. If mainprog->jmpbuf is used by setjmp, then png_longjmp - cannot be used. - Changed "extern PNG_EXPORT" to "PNG_EXPORT" in png.h (Jan Nijtmans) - Changed "extern" to "PNG_EXTERN" in pngpriv.h (except for the 'extern "C" {') - -Version 1.5.0beta34 [July 12, 2010] - Put #ifndef PNG_EXTERN, #endif around the define PNG_EXTERN in pngpriv.h - -Version 1.5.0beta35 [July 24, 2010] - Removed some newly-added TAB characters. - Added -DNO_PNG_SNPRINTF to CFLAGS in scripts/makefile.dj2 - Moved the definition of png_snprintf() outside of the enclosing - #ifdef blocks in pngconf.h - -Version 1.5.0beta36 [July 29, 2010] - Patches by John Bowler: - Fixed point APIs are now supported throughout (no missing APIs). - Internal fixed point arithmetic support exists for all internal floating - point operations. - sCAL validates the floating point strings it is passed. - Safe, albeit rudimentary, Watcom support is provided by PNG_API_RULE==2 - Two new APIs exist to get the number of passes without turning on the - PNG_INTERLACE transform and to get the number of rows in the current - pass. - A new test program, pngvalid.c, validates the gamma code. - Errors in the 16-bit gamma correction (overflows) have been corrected. - cHRM chunk testing is done consistently (previously the floating point - API bypassed it, because the test really didn't work on FP, now the test - is performed on the actual values to be stored in the PNG file so it - works in the FP case too.) - Most floating point APIs now simply call the fixed point APIs after - converting the values to the fixed point form used in the PNG file. - The standard headers no longer include zlib.h, which is currently only - required for pngstruct.h and can therefore be internal. - Revised png_get_int_32 to undo the PNG two's complement representation of - negative numbers. - -Version 1.5.0beta37 [July 30, 2010] - Added a typecast in png_get_int_32() in png.h and pngrutil.h to avoid - a compiler warning. - Replaced oFFs 0,0 with oFFs -10,20 in pngtest.png - -Version 1.5.0beta38 [July 31, 2010] - Implemented remaining "_fixed" functions. - Corrected a number of recently introduced warnings mostly resulting from - safe but uncast assignments to shorter integers. Also added a zlib - VStudio release library project because the latest zlib Official Windows - build does not include such a thing. - Revised png_get_int_16() to be similar to png_get_int_32(). - Restored projects/visualc71. - -Version 1.5.0beta39 [August 2, 2010] - VisualC/GCC warning fixes, VisualC build fixes - The changes include support for function attributes in VC in addition to - those already present in GCC - necessary because without these some - warnings are unavoidable. Fixes include signed/unsigned fixes in - pngvalid and checks with gcc -Wall -Wextra -Wunused. - VC requires function attributes on function definitions as well as - declarations, PNG_FUNCTION has been added to enable this and the - relevant function definitions changed. - -Version 1.5.0beta40 [August 6, 2010] - Correct use of _WINDOWS_ in pngconf.h - Removed png_mem_ #defines; they are no longer used. - Added the sRGB chunk to pngtest.png - -Version 1.5.0beta41 [August 11, 2010] - Added the cHRM chunk to pngtest.png - Don't try to use version-script with cygwin/mingw. - Revised contrib/gregbook to work under cygwin/mingw. - -Version 1.5.0beta42 [August 18, 2010] - Add .dll.a to the list of extensions to be symlinked by Makefile.am (Yaakov) - Made all API functions that have const arguments and constant string - literal pointers declare them (John Bowler). - -Version 1.5.0beta43 [August 20, 2010] - Removed spurious tabs, shorten long lines (no source change) - Also added scripts/chkfmt to validate the format of all the files that can - reasonably be validated (it is suggested to run "make distclean" before - checking, because some machine generated files have long lines.) - Reformatted the CHANGES file to be more consistent throughout. - Made changes to address various issues identified by GCC, mostly - signed/unsigned and shortening problems on assignment but also a few - difficult to optimize (for GCC) loops. - Fixed non-GCC fixed point builds. In png.c a declaration was misplaced - in an earlier update. Fixed to declare the auto variables at the head. - Use cexcept.h in pngvalid.c. - -Version 1.5.0beta44 [August 24, 2010] - Updated CMakeLists.txt to use CMAKE_INSTALL_LIBDIR variable; useful for - installing libpng in /usr/lib64 (Funda Wang). - Revised CMakeLists.txt to put the man pages in share/man/man* not man/man* - Revised CMakeLists.txt to make symlinks instead of copies when installing. - Changed PNG_LIB_NAME from pngNN to libpngNN in CMakeLists.txt (Philip Lowman) - Implemented memory checks within pngvalid - Reformatted/rearranged pngvalid.c to assist use of progressive reader. - Check interlaced images in pngvalid - Clarified pngusr.h comments in pnglibconf.dfa - Simplified the pngvalid error-handling code now that cexcept.h is in place. - Implemented progressive reader in pngvalid.c for standard tests - Implemented progressive read in pngvalid.c gamma tests - Turn on progressive reader in pngvalid.c by default and tidy code. - -Version 1.5.0beta45 [August 26, 2010] - Added an explicit make step to projects/vstudio for pnglibconf.h - Also corrected zlib.vcxproj into which Visual Studio had introduced - what it calls an "authoring error". The change to make pnglibconf.h - simply copies the file; in the future it may actually generate the - file from scripts/pnglibconf.dfa as the other build systems do. - Changed pngvalid to work when floating point APIs are disabled - Renamed the prebuilt scripts/pnglibconf.h to scripts/pnglibconf.h.prebuilt - Supply default values for PNG_USER_PRIVATEBUILD and PNG_USER_DLLFNAME_POSTFIX - in pngpriv.h in case the user neglected to define them in their pngusr.h - -Version 1.5.0beta46 [August 28, 2010] - Added new private header files to libpng_sources in CMakeLists.txt - Added PNG_READ_16BIT, PNG_WRITE_16BIT, and PNG_16BIT options. - Added reference to scripts/pnglibconf.h.prebuilt in the visualc71 project. - -Version 1.5.0beta47 [September 11, 2010] - Fixed a number of problems with 64-bit compilation reported by Visual - Studio 2010 (John Bowler). - -Version 1.5.0beta48 [October 4, 2010] - Updated CMakeLists.txt (Philip Lowman). - Revised autogen.sh to recognize and use $AUTOCONF, $AUTOMAKE, $AUTOHEADER, - $AUTOPOINT, $ACLOCAL and $LIBTOOLIZE - Fixed problem with symbols creation in Makefile.am which was assuming that - all versions of ccp write to standard output by default (Martin Banky). The - bug was introduced in libpng-1.2.9beta5. - Removed unused mkinstalldirs. - -Version 1.5.0beta49 [October 8, 2010] - Undid Makefile.am revision of 1.5.0beta48. - -Version 1.5.0beta50 [October 14, 2010] - Revised Makefile.in to account for mkinstalldirs being removed. - Added some "(unsigned long)" typecasts in printf statements in pngvalid.c. - Suppressed a compiler warning in png_handle_sPLT(). - Check for out-of-range text compression mode in png_set_text(). - -Version 1.5.0beta51 [October 15, 2010] - Changed embedded dates to "(PENDING RELEASE) in beta releases (and future - rc releases) to minimize the difference between releases. - -Version 1.5.0beta52 [October 16, 2010] - Restored some of the embedded dates (in png.h, png.c, documentation, etc.) - -Version 1.5.0beta53 [October 18, 2010] - Updated INSTALL to mention using "make maintainer-clean" and to remove - obsolete statement about a custom ltmain.sh - Disabled "color-tests" by default in Makefile.am so it will work with - automake versions earlier than 1.11.1 - Use document name "libpng-manual.txt" instead of "libpng-.txt" - to simplify version differences. - Removed obsolete remarks about setjmp handling from INSTALL. - Revised and renamed the typedef in png.h and png.c that was designed - to catch library and header mismatch. - -Version 1.5.0beta54 [November 10, 2010] - Require 48 bytes, not 64 bytes, for big_row_buf in overflow checks. - Used a consistent structure for the pngget.c functions. - -Version 1.5.0beta55 [November 21, 2010] - Revised png_get_uint_32, png_get_int_32, png_get_uint_16 (Cosmin) - Moved reading of file signature into png_read_sig (Cosmin) - Fixed atomicity of chunk header serialization (Cosmin) - Added test for io_state in pngtest.c (Cosmin) - Added "#!/bin/sh" at the top of contrib/pngminim/*/gather.sh scripts. - Changes to remove gcc warnings (John Bowler) - Certain optional gcc warning flags resulted in warnings in libpng code. - With these changes only -Wconversion and -Wcast-qual cannot be turned on. - Changes are trivial rearrangements of code. -Wconversion is not possible - for pngrutil.c (because of the widespread use of += et al on variables - smaller than (int) or (unsigned int)) and -Wcast-qual is not possible - with pngwio.c and pngwutil.c because the 'write' callback and zlib - compression both fail to declare their input buffers with 'const'. - -Version 1.5.0beta56 [December 7, 2010] - Added the private PNG_UNUSED() macro definition in pngpriv.h. - Added some commentary about PNG_EXPORT in png.h and pngconf.h - Revised PNG_EXPORT() macro and added PNG_EXPORTA() macro, with the - objective of simplifying and improving the cosmetic appearance of png.h. - Fixed some incorrect "=" macro names in pnglibconf.dfa - Included documentation of changes in 1.5.0 from 1.4.x in libpng-manual.txt - -Version 1.5.0beta57 [December 9, 2010] - Documented the pngvalid gamma error summary with additional comments and - print statements. - Improved missing symbol handling in checksym.awk; symbols missing in both - the old and new files can now be optionally ignored, treated as errors - or warnings. - Removed references to pngvcrd.c and pnggccrd.c from the vstudio project. - Updated "libpng14" to "libpng15" in the visualc71 project. - Enabled the strip16 tests in pngvalid.` - Don't display test results (except PASS/FAIL) when running "make test". - Instead put them in pngtest-log.txt - Added "--with-zprefix=" to configure.ac - Updated the prebuilt configuration files to autoconf version 2.68 - -Version 1.5.0beta58 [December 19, 2010] - Fixed interlace image handling and add test cases (John Bowler) - Fixed the clean rule in Makefile.am to remove pngtest-log.txt - Made minor changes to work around warnings in gcc 3.4 - -Version 1.5.0rc01 [December 27, 2010] - No changes. - -Version 1.5.0rc02 [December 27, 2010] - Eliminated references to the scripts/*.def files in project/visualc71. - -Version 1.5.0rc03 [December 28, 2010] - Eliminated scripts/*.def and revised Makefile.am accordingly - -Version 1.5.0rc04 [December 29, 2010] - Fixed bug in background transformation handling in pngrtran.c (it was - looking for the flag in png_ptr->transformations instead of in - png_ptr->flags) (David Raymond). - -Version 1.5.0rc05 [December 31, 2010] - Fixed typo in a comment in CMakeLists.txt (libpng14 => libpng15) (Cosmin) - -Version 1.5.0rc06 [January 4, 2011] - Changed the new configure option "zprefix=string" to "zlib-prefix=string" - -Version 1.5.0rc07 [January 4, 2011] - Updated copyright year. - -Version 1.5.0 [January 6, 2011] - No changes. - -version 1.5.1beta01 [January 8, 2011] - Added description of png_set_crc_action() to the manual. - Added a note in the manual that the type of the iCCP profile was changed - from png_charpp to png_bytepp in png_get_iCCP(). This change happened - in version 1.5.0beta36 but is not noted in the CHANGES. Similarly, - it was changed from png_charpp to png_const_bytepp in png_set_iCCP(). - Ensure that png_rgb_to_gray ignores palette mapped images, if libpng - internally happens to call it with one, and fixed a failure to handle - palette mapped images correctly. This fixes CVE-2690. - -Version 1.5.1beta02 [January 14, 2011] - Fixed a bug in handling of interlaced images (bero at arklinux.org). - Updated CMakeLists.txt (Clifford Yapp) - -Version 1.5.1beta03 [January 14, 2011] - Fixed typecasting of some png_debug() statements (Cosmin) - -Version 1.5.1beta04 [January 16, 2011] - Updated documentation of png_set|get_tRNS() (Thomas Klausner). - Mentioned in the documentation that applications must #include "zlib.h" - if they need access to anything in zlib.h, and that a number of - macros such as png_memset() are no longer accessible by applications. - Corrected pngvalid gamma test "sample" function to access all of the color - samples of each pixel, instead of sampling the red channel three times. - Prefixed variable names index, div, exp, gamma with "png_" to avoid "shadow" - warnings, and (mistakenly) changed png_exp() to exp(). - -Version 1.5.1beta05 [January 16, 2011] - Changed variable names png_index, png_div, png_exp, and png_gamma to - char_index, divisor, exp_b10, and gamma_val, respectively, and - changed exp() back to png_exp(). - -Version 1.5.1beta06 [January 20, 2011] - Prevent png_push_crc_skip() from hanging while reading an unknown chunk - or an over-large compressed zTXt chunk with the progressive reader. - Eliminated more GCC "shadow" warnings. - Revised png_fixed() in png.c to avoid compiler warning about reaching the - end without returning anything. - -Version 1.5.1beta07 [January 22, 2011] - In the manual, describe the png_get_IHDR() arguments in the correct order. - Added const_png_structp and const_png_infop types, and used them in - prototypes for most png_get_*() functions. - -Version 1.5.1beta08 [January 23, 2011] - Added png_get_io_chunk_type() and deprecated png_get_io_chunk_name() - Added synopses for the IO_STATE functions and other missing synopses - to the manual. Removed the synopses from libpngpf.3 because they - were out of date and no longer useful. Better information can be - obtained by reading the prototypes and comments in pngpriv.h - Attempted to fix cpp on Solaris with S. Studio 12 cc, fix build - Added a make macro DFNCPP that is a CPP that will accept the tokens in - a .dfn file and adds configure stuff to test for such a CPP. ./configure - should fail if one is not available. - Corrected const_png_ in png.h to png_const_ to avoid polluting the namespace. - Added png_get_current_row_number and png_get_current_pass_number for the - benefit of the user transform callback. - Added png_process_data_pause and png_process_data_skip for the benefit of - progressive readers that need to stop data processing or want to optimize - skipping of unread data (e.g., if the reader marks a chunk to be skipped.) - -Version 1.5.1beta09 [January 24, 2011] - Enhanced pngvalid, corrected an error in gray_to_rgb, corrected doc error. - pngvalid contains tests of transforms, which tests are currently disabled - because they are incompletely tested. gray_to_rgb was failing to expand - the bit depth for smaller bit depth images; this seems to be a long - standing error and resulted, apparently, in invalid output - (CVE-2011-0408, CERT VU#643140). The documentation did not accurately - describe what libpng really does when converting RGB to gray. - -Version 1.5.1beta10 [January 27, 2010] - Fixed incorrect examples of callback prototypes in the manual, that were - introduced in libpng-1.0.0. - In addition the order of the png_get_uint macros with respect to the - relevant function definitions has been reversed. This helps the - preprocessing of the symbol files be more robust. Furthermore, the - symbol file preprocessing now uses -DPNG_NO_USE_READ_MACROS even when - the library may actually be built with PNG_USE_READ_MACROS; this stops - the read macros interfering with the symbol file format. - Made the manual, synopses, and function prototypes use the function - argument names file_gamma, int_file_gamma, and srgb_intent consistently. - -Version 1.5.1beta11 [January 28, 2011] - Changed PNG_UNUSED from "param=param;" to "{if(param){}}". - Corrected local variable type in new API png_process_data_skip() - The type was self-evidently incorrect but only causes problems on 64-bit - architectures. - Added transform tests to pngvalid and simplified the arguments. - -Version 1.5.1rc01 [January 29, 2011] - No changes. - -Version 1.5.1rc02 [January 31, 2011] - Added a request in the manual that applications do not use "png_" or - "PNG_" to begin any of their own symbols. - Changed PNG_UNUSED to "(void)param;" and updated the commentary in pngpriv.h - -Version 1.5.1 [February 3, 2011] - No changes. - -Version 1.5.2beta01 [February 13, 2011] - More -Wshadow fixes for older gcc compilers. Older gcc versions apparently - check formal parameters names in function declarations (as well as - definitions) to see if they match a name in the global namespace. - Revised PNG_EXPORTA macro to not use an empty parameter, to accommodate the - old VisualC++ preprocessor. - Turned on interlace handling in png_read_png(). - Fixed gcc pendantic warnings. - Handle longjmp in Cygwin. - Fixed png_get_current_row_number() in the interlaced case. - Cleaned up ALPHA flags and transformations. - Implemented expansion to 16 bits. - -Version 1.5.2beta02 [February 19, 2011] - Fixed mistake in the descriptions of user read_transform and write_transform - function prototypes in the manual. The row_info struct is png_row_infop. - Reverted png_get_current_row_number() to previous (1.5.2beta01) behavior. - Corrected png_get_current_row_number documentation - Fixed the read/write row callback documentation. - This documents the current behavior, where the callback is called after - every row with information pertaining to the next row. - -Version 1.5.2beta03 [March 3, 2011] - Fixed scripts/makefile.vcwin32 - Updated contrib/pngsuite/README to add the word "modify". - Define PNG_ALLOCATED to blank when _MSC_VER<1300. - -Version 1.5.2rc01 [March 19, 2011] - Define remaining attributes to blank when MSC_VER<1300. - ifdef out mask arrays in pngread.c when interlacing is not supported. - -Version 1.5.2rc02 [March 22, 2011] - Added a hint to try CPP=/bin/cpp if "cpp -E" fails in scripts/pnglibconf.mak - and in contrib/pngminim/*/makefile, eg., on SunOS 5.10, and removed "strip" - from the makefiles. - Fixed a bug (present since libpng-1.0.7) that makes png_handle_sPLT() fail - to compile when PNG_NO_POINTER_INDEXING is defined (Chubanov Kirill) - -Version 1.5.2rc03 [March 24, 2011] - Don't include standard header files in png.h while building the symbol table, - to avoid cpp failure on SunOS (introduced PNG_BUILDING_SYMBOL_TABLE macro). - -Version 1.5.2 [March 31, 2011] - No changes. - -Version 1.5.3beta01 [April 1, 2011] - Re-initialize the zlib compressor before compressing non-IDAT chunks. - Added API functions (png_set_text_compression_level() and four others) to - set parameters for zlib compression of non-IDAT chunks. - -Version 1.5.3beta02 [April 3, 2011] - Updated scripts/symbols.def with new API functions. - Only compile the new zlib re-initializing code when text or iCCP is - supported, using PNG_WRITE_COMPRESSED_TEXT_SUPPORTED macro. - Improved the optimization of the zlib CMF byte (see libpng-1.2.6beta03). - Optimize the zlib CMF byte in non-IDAT compressed chunks - -Version 1.5.3beta03 [April 16, 2011] - Fixed gcc -ansi -pedantic compile. A strict ANSI system does not have - snprintf, and the "__STRICT_ANSI__" detects that condition more reliably - than __STDC__ (John Bowler). - Removed the PNG_PTR_NORETURN attribute because it too dangerous. It tells - the compiler that a user supplied callback (the error handler) does not - return, yet there is no guarantee in practice that the application code - will correctly implement the error handler because the compiler only - issues a warning if there is a mistake (John Bowler). - Removed the no-longer-used PNG_DEPSTRUCT macro. - Updated the zlib version to 1.2.5 in the VStudio project. - Fixed 64-bit builds where png_uint_32 is smaller than png_size_t in - pngwutil.c (John Bowler). - Fixed bug with stripping the filler or alpha channel when writing, that - was introduced in libpng-1.5.2beta01 (bug report by Andrew Church). - -Version 1.5.3beta04 [April 27, 2011] - Updated pngtest.png with the new zlib CMF optimization. - Cleaned up conditional compilation code and of background/gamma handling - Internal changes only except a new option to avoid compiling the - png_build_grayscale_palette API (which is not used at all internally.) - The main change is to move the transform tests (READ_TRANSFORMS, - WRITE_TRANSFORMS) up one level to the caller of the APIs. This avoids - calls to spurious functions if all transforms are disabled and slightly - simplifies those functions. Pngvalid modified to handle this. - A minor change is to stop the strip_16 and expand_16 interfaces from - disabling each other; this allows the future alpha premultiplication - code to use 16-bit intermediate values while still producing 8-bit output. - png_do_background and png_do_gamma have been simplified to take a single - pointer to the png_struct rather than pointers to every item required - from the png_struct. This makes no practical difference to the internal - code. - A serious bug in the pngvalid internal routine 'standard_display_init' has - been fixed - this failed to initialize the red channel and accidentally - initialized the alpha channel twice. - Changed png_struct jmp_buf member name from png_jmpbuf to tmp_jmpbuf to - avoid a possible clash with the png_jmpbuf macro on some platforms. - -Version 1.5.3beta05 [May 6, 2011] - Added the "_POSIX_SOURCE" feature test macro to ensure libpng sees the - correct API. _POSIX_SOURCE is defined in pngpriv.h, pngtest.c and - pngvalid.c to ensure that POSIX conformant systems disable non-POSIX APIs. - Removed png_snprintf and added formatted warning messages. This change adds - internal APIs to allow png_warning messages to have parameters without - requiring the host OS to implement snprintf. As a side effect the - dependency of the tIME-supporting RFC1132 code on stdio is removed and - PNG_NO_WARNINGS does actually work now. - Pass "" instead of '\0' to png_default_error() in png_err(). This mistake - was introduced in libpng-1.2.20beta01. This fixes CVE-2011-2691. - Added PNG_WRITE_OPTIMIZE_CMF_SUPPORTED macro to make the zlib "CMF" byte - optimization configureable. - IDAT compression failed if preceded by a compressed text chunk (bug - introduced in libpng-1.5.3beta01-02). This was because the attempt to - reset the zlib stream in png_write_IDAT happened after the first IDAT - chunk had been deflated - much too late. In this change internal - functions were added to claim/release the z_stream and, hopefully, make - the code more robust. Also deflateEnd checking is added - previously - libpng would ignore an error at the end of the stream. - -Version 1.5.3beta06 [May 8, 2011] - Removed the -D_ALL_SOURCE from definitions for AIX in CMakeLists.txt - Implemented premultiplied alpha support: png_set_alpha_mode API - -Version 1.5.3beta07 [May 11, 2011] - Added expand_16 support to the high level interface. - Added named value and 'flag' gamma support to png_set_gamma. Made a minor - change from the previous (unreleased) ABI/API to hide the exact value used - for Macs - it's not a good idea to embed this in the ABI! - Moved macro definitions for PNG_HAVE_IHDR, PNG_HAVE_PLTE, and PNG_AFTER_IDAT - from pngpriv.h to png.h because they must be visible to applications - that call png_set_unknown_chunks(). - Check for up->location !PNG_AFTER_IDAT when writing unknown chunks - before IDAT. - -Version 1.5.3beta08 [May 16, 2011] - Improved "pngvalid --speed" to exclude more of pngvalid from the time. - Documented png_set_alpha_mode(), other changes in libpng.3/libpng-manual.txt - The cHRM chunk now sets the defaults for png_set_rgb_to_gray() (when negative - parameters are supplied by the caller), while in the absence of cHRM - sRGB/Rec 709 values are still used. This introduced a divide-by-zero - bug in png_handle_cHRM(). - The bKGD chunk no longer overwrites the background value set by - png_set_background(), allowing the latter to be used before the file - header is read. It never performed any useful function to override - the default anyway. - Added memory overwrite and palette image checks to pngvalid.c - Previously palette image code was poorly checked. Since the transformation - code has a special palette path in most cases this was a severe weakness. - Minor cleanup and some extra checking in pngrutil.c and pngrtran.c. When - expanding an indexed image, always expand to RGBA if transparency is - present. - -Version 1.5.3beta09 [May 17, 2011] - Reversed earlier 1.5.3 change of transformation order; move png_expand_16 - back where it was. The change doesn't work because it requires 16-bit - gamma tables when the code only generates 8-bit ones. This fails - silently; the libpng code just doesn't do any gamma correction. Moving - the tests back leaves the old, inaccurate, 8-bit gamma calculations, but - these are clearly better than none! - -Version 1.5.3beta10 [May 20, 2011] - - png_set_background() and png_expand_16() did not work together correctly. - This problem is present in 1.5.2; if png_set_background is called with - need_expand false and the matching 16 bit color libpng erroneously just - treats it as an 8-bit color because of where png_do_expand_16 is in the - transform list. This simple fix reduces the supplied colour to 8-bits, - so it gets smashed, but this is better than the current behavior. - Added tests for expand16, more fixes for palette image tests to pngvalid. - Corrects the code for palette image tests and disables attempts to - validate palette colors. - -Version 1.5.3rc01 [June 3, 2011] - No changes. - -Version 1.5.3rc02 [June 8, 2011] - Fixed uninitialized memory read in png_format_buffer() (Bug report by - Frank Busse, CVE-2011-2501, related to CVE-2004-0421). - -Version 1.5.3beta11 [June 11, 2011] - Fixed png_handle_sCAL which is broken in 1.5. This fixes CVE 2011-2692. - Added sCAL to pngtest.png - Revised documentation about png_set_user_limits() to say that it also affects - png writing. - Revised handling of png_set_user_limits() so that it can increase the - limit beyond the PNG_USER_WIDTH|HEIGHT_MAX; previously it could only - reduce it. - Make the 16-to-8 scaling accurate. Dividing by 256 with no rounding is - wrong (high by one) 25% of the time. Dividing by 257 with rounding is - wrong in 128 out of 65536 cases. Getting the right answer all the time - without division is easy. - Added "_SUPPORTED" to the PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION macro. - Added projects/owatcom, an IDE project for OpenWatcom to replace - scripts/makefile.watcom. This project works with OpenWatcom 1.9. The - IDE autogenerates appropriate makefiles (libpng.mk) for batch processing. - The project is configurable, unlike the Visual Studio project, so long - as the developer has an awk. - Changed png_set_gAMA to limit the gamma value range so that the inverse - of the stored value cannot overflow the fixed point representation, - and changed other things OpenWatcom warns about. - Revised pngvalid.c to test PNG_ALPHA_MODE_SUPPORTED correctly. This allows - pngvalid to build when ALPHA_MODE is not supported, which is required if - it is to build on libpng 1.4. - Removed string/memory macros that are no longer used and are not - necessarily fully supportable, particularly png_strncpy and png_snprintf. - Added log option to pngvalid.c and attempted to improve gamma messages. - -Version 1.5.3 [omitted] - People found the presence of a beta release following an rc release - to be confusing; therefore we bump the version to libpng-1.5.4beta01 - and there will be no libpng-1.5.3 release. - -Version 1.5.4beta01 [June 14, 2011] - Made it possible to undefine PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED - to get the same (inaccurate) output as libpng-1.5.2 and earlier. - Moved definitions of PNG_HAVE_IHDR, PNG_AFTER_IDAT, and PNG_HAVE_PLTE - outside of an unknown-chunk block in png.h because they are also - needed for other uses. - -Version 1.5.4beta02 [June 14, 2011] - Fixed and clarified LEGACY 16-to-8 scaling code. - Added png_set_chop_16() API, to match inaccurate results from previous - libpng versions. - Removed the ACCURATE and LEGACY options (they are no longer useable) - Use the old scaling method for background if png_set_chop_16() was - called. - Made png_set_chop_16() API removeable by disabling PNG_CHOP_16_TO_8_SUPPORTED - -Version 1.5.4beta03 [June 15, 2011] - Fixed a problem in png_do_expand_palette() exposed by optimization in - 1.5.3beta06 - Also removed a spurious and confusing "trans" member ("trans") from png_info. - The palette expand optimization prevented expansion to an intermediate RGBA - form if tRNS was present but alpha was marked to be stripped; this exposed - a check for tRNS in png_do_expand_palette() which is inconsistent with the - code elsewhere in libpng. - Correction to the expand_16 code; removed extra instance of - png_set_scale_16_to_8 from pngpriv.h - -Version 1.5.4beta04 [June 16, 2011] - Added a missing "#ifdef PNG_READ_BACKGROUND_SUPPORTED/#endif" in pngrtran.c - Added PNG_TRANSFORM_CHOP_16 to the high-level read transforms. - Made PNG_READ_16_TO_8_ACCURATE_SCALE configurable again. If this is - not enabled, png_set_strip_16() and png_do_scale_16_to_8() aren't built. - Revised contrib/visupng, gregbook, and pngminim to demonstrate chop_16_to_8 - -Version 1.5.4beta05 [June 16, 2011] - Renamed png_set_strip_16() to png_set_scale_16() and renamed - png_set_chop_16() to png_set_strip(16) in an attempt to minimize the - behavior changes between libpng14 and libpng15. - -Version 1.5.4beta06 [June 18, 2011] - Fixed new bug that was causing both strip_16 and scale_16 to be applied. - -Version 1.5.4beta07 [June 19, 2011] - Fixed pngvalid, simplified macros, added checking for 0 in sCAL. - The ACCURATE scale macro is no longer defined in 1.5 - call the - png_scale_16_to_8 API. Made sure that PNG_READ_16_TO_8 is still defined - if the png_strip_16_to_8 API is present. png_check_fp_number now - maintains some state so that positive, negative and zero values are - identified. sCAL uses these to be strictly spec conformant. - -Version 1.5.4beta08 [June 23, 2011] - Fixed pngvalid if ACCURATE_SCALE is defined. - Updated scripts/pnglibconf.h.prebuilt. - -Version 1.5.4rc01 [June 30, 2011] - Define PNG_ALLOCATED to "restrict" only if MSC_VER >= 1400. - -Version 1.5.4 [July 7, 2011] - No changes. - -Version 1.5.5beta01 [July 13, 2011] - Fixed some typos and made other minor changes in the manual. - Updated contrib/pngminus/makefile.std (Samuli Souminen) - -Version 1.5.5beta02 [July 14, 2011] - Revised Makefile.am and Makefile.in to look in the right directory for - pnglibconf.h.prebuilt - -Version 1.5.5beta03 [July 27, 2011] - Enabled compilation with g++ compiler. This compiler does not recognize - the file extension, so it always compiles with C++ rules. Made minor - changes to pngrutil.c to cast results where C++ expects it but C does not. - Minor editing of libpng.3 and libpng-manual.txt. - -Version 1.5.5beta04 [July 29, 2011] - Revised CMakeLists.txt (Clifford Yapp) - Updated commentary about the png_rgb_to_gray() default coefficients - in the manual and in pngrtran.c - -Version 1.5.5beta05 [August 17, 2011] - Prevent unexpected API exports from non-libpng DLLs on Windows. The "_DLL" - is removed from the test of whether a DLL is being built (this erroneously - caused the libpng APIs to be marked as DLL exports in static builds under - Microsoft Visual Studio). Almost all of the libpng building configuration - is moved from pngconf.h to pngpriv.h, but PNG_DLL_EXPORT remains in - pngconf.h, though, so that it is colocated with the import definition (it - is no longer used anywhere in the installed headers). The VStudio project - definitions have been cleaned up: "_USRDLL" has been removed from the - static library builds (this was incorrect), and PNG_USE_DLL has been added - to pngvalid to test the functionality (pngtest does not supply it, - deliberately). The spurious "_EXPORTS" has been removed from the - libpng build (all these errors were a result of copy/paste between project - configurations.) - Added new types and internal functions for CIE RGB end point handling to - pngpriv.h (functions yet to be implemented). - -Version 1.5.5beta06 [August 26, 2011] - Ensure the CMAKE_LIBRARY_OUTPUT_DIRECTORY is set in CMakeLists.txt - (Clifford Yap) - Fixes to rgb_to_gray and cHRM XYZ APIs (John Bowler): - The rgb_to_gray code had errors when combined with gamma correction. - Some pixels were treated as true grey when they weren't and such pixels - and true grey ones were not gamma corrected (the original value of the - red component was used instead). APIs to get and set cHRM using color - space end points have been added and the rgb_to_gray code that defaults - based on cHRM, and the divide-by-zero bug in png_handle_cHRM (CERT - VU#477046, CVE-2011-3328, introduced in 1.5.4) have been corrected. - A considerable number of tests has been added to pngvalid for the - rgb_to_gray transform. - Arithmetic errors in rgb_to_gray whereby the calculated gray value was - truncated to the bit depth rather than rounded have been fixed except in - the 8-bit non-gamma-corrected case (where consistency seems more important - than correctness.) The code still has considerable inaccuracies in the - 8-bit case because 8-bit linear arithmetic is used. - -Version 1.5.5beta07 [September 7, 2011] - Added "$(ARCH)" option to makefile.darwin - Added SunOS support to configure.ac and Makefile.am - Changed png_chunk_benign_error() to png_warning() in png.c, in - png_XYZ_from_xy_checked(). - -Version 1.5.5beta08 [September 10, 2011] - Fixed 64-bit compilation errors (gcc). The errors fixed relate - to conditions where types that are 32 bits in the GCC 32-bit - world (uLong and png_size_t) become 64 bits in the 64-bit - world. This produces potential truncation errors which the - compiler correctly flags. - Relocated new HAVE_SOLARIS_LD definition in configure.ac - Constant changes for 64-bit compatibility (removal of L suffixes). The - 16-bit cases still use "L" as we don't have a 16-bit test system. - -Version 1.5.5rc01 [September 15, 2011] - Removed "L" suffixes in pngpriv.h - -Version 1.5.5 [September 22, 2011] - No changes. - -Version 1.5.6beta01 [September 22, 2011] - Fixed some 64-bit type conversion warnings in pngrtran.c - Moved row_info from png_struct to a local variable. - The various interlace mask arrays have been made into arrays of - bytes and made PNG_CONST and static (previously some arrays were - marked PNG_CONST and some weren't). - Additional checks have been added to the transform code to validate the - pixel depths after the transforms on both read and write. - Removed some redundant code from pngwrite.c, in png_destroy_write_struct(). - Changed chunk reading/writing code to use png_uint_32 instead of png_byte[4]. - This removes the need to allocate temporary strings for chunk names on - the stack in the read/write code. Unknown chunk handling still uses the - string form because this is exposed in the API. - -Version 1.5.6beta02 [September 26, 2011] - Added a note in the manual the png_read_update_info() must be called only - once with a particular info_ptr. - Fixed a typo in the definition of the new PNG_STRING_FROM_CHUNK(s,c) macro. - -Version 1.5.6beta03 [September 28, 2011] - Revised test-pngtest.sh to report FAIL when pngtest fails. - Added "--strict" option to pngtest, to report FAIL when the failure is - only because the resulting valid files are different. - Revised CMakeLists.txt to work with mingw and removed some material from - CMakeLists.txt that is no longer useful in libpng-1.5. - -Version 1.5.6beta04 [October 5, 2011] - Fixed typo in Makefile.in and Makefile.am ("-M Wl" should be "-M -Wl")." - -Version 1.5.6beta05 [October 12, 2011] - Speed up png_combine_row() for interlaced images. This reduces the generality - of the code, allowing it to be optimized for Adam7 interlace. The masks - passed to png_combine_row() are now generated internally, avoiding - some code duplication and localizing the interlace handling somewhat. - Align png_struct::row_buf - previously it was always unaligned, caused by - a bug in the code that attempted to align it; the code needs to subtract - one from the pointer to take account of the filter byte prepended to - each row. - Optimized png_combine_row() when rows are aligned. This gains a small - percentage for 16-bit and 32-bit pixels in the typical case where the - output row buffers are appropriately aligned. The optimization was not - previously possible because the png_struct buffer was always misaligned. - Fixed bug in png_write_chunk_header() debug print, introduced in 1.5.6beta01. - -Version 1.5.6beta06 [October 17, 2011] - Removed two redundant tests for unitialized row. - Fixed a relatively harmless memory overwrite in compressed text writing - with a 1 byte zlib buffer. - Add ability to call png_read_update_info multiple times to pngvalid.c. - Fixes for multiple calls to png_read_update_info. These fixes attend to - most of the errors revealed in pngvalid, however doing the gamma work - twice results in inaccuracies that can't be easily fixed. There is now - a warning in the code if this is going to happen. - Turned on multiple png_read_update_info in pngvalid transform tests. - Prevent libpng from overwriting unused bits at the end of the image when - it is not byte aligned, while reading. Prior to libpng-1.5.6 libpng would - overwrite the partial byte at the end of each row if the row width was not - an exact multiple of 8 bits and the image is not interlaced. - -Version 1.5.6beta07 [October 21, 2011] - Made png_ptr->prev_row an aligned pointer into png_ptr->big_prev_row - (Mans Rullgard). - -Version 1.5.6rc01 [October 26, 2011] - Changed misleading "Missing PLTE before cHRM" warning to "Out of place cHRM" - -Version 1.5.6rc02 [October 27, 2011] - Added LSR() macro to defend against buggy compilers that evaluate non-taken - code branches and complain about out-of-range shifts. - -Version 1.5.6rc03 [October 28, 2011] - Renamed the LSR() macro to PNG_LSR() and added PNG_LSL() macro. - Fixed compiler warnings with Intel and MSYS compilers. The logical shift - fix for Microsoft Visual C is required by other compilers, so this - enables that fix for all compilers when using compile-time constants. - Under MSYS 'byte' is a name declared in a system header file, so we - changed the name of a local variable to avoid the warnings that result. - Added #define PNG_ALIGN_TYPE PNG_ALIGN_NONE to contrib/pngminim/*/pngusr.h - -Version 1.5.6 [November 3, 2011] - No changes. - -Version 1.5.7beta01 [November 4, 2011] - Added support for ARM processor (Mans Rullgard) - Fixed bug in pngvalid on early allocation failure; fixed type cast in - pngmem.c; pngvalid would attempt to call png_error() if the allocation - of a png_struct or png_info failed. This would probably have led to a - crash. The pngmem.c implementation of png_malloc() included a cast - to png_size_t which would fail on large allocations on 16-bit systems. - Fix for the preprocessor of the Intel C compiler. The preprocessor - splits adjacent @ signs with a space; this changes the concatentation - token from @-@-@ to PNG_JOIN; that should work with all compiler - preprocessors. - Paeth filter speed improvements from work by Siarhei Siamashka. This - changes the 'Paeth' reconstruction function to improve the GCC code - generation on x86. The changes are only part of the suggested ones; - just the changes that definitely improve speed and remain simple. - The changes also slightly increase the clarity of the code. - -Version 1.5.7beta02 [November 11, 2011] - Check compression_type parameter in png_get_iCCP and remove spurious - casts. The compression_type parameter is always assigned to, so must - be non-NULL. The cast of the profile length potentially truncated the - value unnecessarily on a 16-bit int system, so the cast of the (byte) - compression type to (int) is specified by ANSI-C anyway. - Fixed FP division by zero in pngvalid.c; the 'test_pixel' code left - the sBIT fields in the test pixel as 0, which resulted in a floating - point division by zero which was irrelevant but causes systems where - FP exceptions cause a crash. Added code to pngvalid to turn on FP - exceptions if the appropriate glibc support is there to ensure this is - tested in the future. - Updated scripts/pnglibconf.mak and scripts/makefile.std to handle the - new PNG_JOIN macro. - Added versioning to pnglibconf.h comments. - Simplified read/write API initial version; basic read/write tested on - a variety of images, limited documentation (in the header file.) - Installed more accurate linear to sRGB conversion tables. The slightly - modified tables reduce the number of 16-bit values that - convert to an off-by-one 8-bit value. The "makesRGB.c" code that was used - to generate the tables is now in a contrib/sRGBtables sub-directory. - -Version 1.5.7beta03 [November 17, 2011] - Removed PNG_CONST from the sRGB table declarations in pngpriv.h and png.c - Added run-time detection of NEON support. - Added contrib/libtests; includes simplified API test and timing test and - a color conversion utility for rapid checking of failed 'pngstest' results. - Multiple transform bug fixes plus a work-round for double gamma correction. - libpng does not support more than one transform that requires linear data - at once - if this is tried typically the results is double gamma - correction. Since the simplified APIs can need rgb to gray combined with - a compose operation it is necessary to do one of these outside the main - libpng transform code. This check-in also contains fixes to various bugs - in the simplified APIs themselves and to some bugs in compose and rgb to - gray (on palette) itself. - Fixes for C++ compilation using g++ When libpng source is compiled - using g++. The compiler imposes C++ rules on the C source; thus it - is desireable to make the source work with either C or C++ rules - without throwing away useful error information. This change adds - png_voidcast to allow C semantic (void*) cases or the corresponding - C++ static_cast operation, as appropriate. - Added --noexecstack to assembler file compilation. GCC does not set - this on assembler compilation, even though it does on C compilation. - This creates security issues if assembler code is enabled; the - work-around is to set it by default in the flags for $(CCAS) - Work around compilers that don't support declaration of const data. Some - compilers fault 'extern const' data declarations (because the data is - not initialized); this turns on const-ness only for compilers where - this is known to work. - -Version 1.5.7beta04 [November 17, 2011] - Since the gcc driver does not recognize the --noexecstack flag, we must - use the -Wa prefix to have it passed through to the assembler. - Also removed a duplicate setting of this flag. - Added files that were omitted from the libpng-1.5.7beta03 zip distribution. - -Version 1.5.7beta05 [November 25, 2011] - Removed "zTXt" from warning in generic chunk decompression function. - Validate time settings passed to pngset() and png_convert_to_rfc1123() - (Frank Busse). - Added MINGW support to CMakeLists.txt - Reject invalid compression flag or method when reading the iTXt chunk. - Backed out 'simplified' API changes. The API seems too complex and there - is a lack of consensus or enthusiasm for the proposals. The API also - reveals significant bugs inside libpng (double gamma correction and the - known bug of being unable to retrieve a corrected palette). It seems - better to wait until the bugs, at least, are corrected. - Moved pngvalid.c into contrib/libtests - Rebuilt Makefile.in, configure, etc., with autoconf-2.68 - -Version 1.5.7rc01 [December 1, 2011] - Replaced an "#if" with "#ifdef" in pngrtran.c - Revised #if PNG_DO_BC block in png.c (use #ifdef and add #else) - -Version 1.5.7rc02 [December 5, 2011] - Revised project files and contrib/pngvalid/pngvalid.c to account for - the relocation of pngvalid into contrib/libtests. - Revised pngconf.h to use " __declspec(restrict)" only when MSC_VER >= 1400, - as in libpng-1.5.4. - Put CRLF line endings in the owatcom project files. - -Version 1.5.7rc03 [December 7, 2011] - Updated CMakeLists.txt to account for the relocation of pngvalid.c - -Version 1.5.7 [December 15, 2011] - Minor fixes to pngvalid.c for gcc 4.6.2 compatibility to remove warnings - reported by earlier versions. - -Version 1.5.8beta01 [January 15, 2011] - Removed '#include config.h"' from contrib/libtests/pngvalid.c. It's not - needed and causes trouble for VPATH building. - Moved AC_MSG_CHECKING([if libraries can be versioned]) later to the proper - location in configure.ac (Gilles Espinasse). - Fix bug in pngerror.c: some long warnings were being improperly truncated - (CVE-2011-3464, bug introduced in libpng-1.5.3beta05). - -Version 1.5.8rc01 [January 21, 2012] - No changes. - -Version 1.5.8rc02 [January 25, 2012] - Fixed Min/GW uninstall to remove libpng.dll.a - Conditionalize the install rules for MINGW and CYGWIN in CMakeLists.txt - -Version 1.5.8 [February 1, 2012] - No changes. - -Version 1.5.9beta01 [February 3, 2012] - Rebuilt configure scripts in the tar distributions. - -Version 1.5.9beta02 [February 16, 2012] - Removed two unused definitions from scripts/pnglibconf.h.prebuilt - Removed some unused arrays (with #ifdef) from png_read_push_finish_row(). - Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h - -Version 1.5.9rc01 [February 17, 2012] - Fixed CVE-2011-3026 buffer overrun bug. Deal more correctly with the test - on iCCP chunk length. Also removed spurious casts that may hide problems - on 16-bit systems. - -Version 1.5.9 [February 18, 2012] - No changes. - -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/plugins/FreeImage/Source/LibPNG/INSTALL b/plugins/FreeImage/Source/LibPNG/INSTALL deleted file mode 100644 index c2d6c9e24a..0000000000 --- a/plugins/FreeImage/Source/LibPNG/INSTALL +++ /dev/null @@ -1,135 +0,0 @@ - -Installing libpng - -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. To be really sure that you aren't using any of the included -pre-built scripts, you can do this: - - ./configure --enable-maintainer-mode - make maintainer-clean - ./autogen.sh - ./configure [--prefix=/path] [other options] - make - make install - make check - -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-x.y.z" or "libpngNN" and "zlib-1.2.5" -or "zlib125") 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, libpng.pc.in, - libpng-config.in, aclocal.m4, config.h.in, config.sub, - depcomp, install-sh, mkinstalldirs, test-pngtest.sh - contrib - gregbook - pngminim - pngminus - pngsuite - visupng - projects - visualc71 - vstudio - scripts - makefile.* - *.def (module definition files) - etc. - 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 pnglibconf.dfa 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". - -Further information can be found in the README and libpng-manual.txt -files, in the individual makefiles, in png.h, and the manual pages -libpng.3 and png.5. diff --git a/plugins/FreeImage/Source/LibPNG/KNOWNBUG b/plugins/FreeImage/Source/LibPNG/KNOWNBUG deleted file mode 100644 index f3ddc5245f..0000000000 --- a/plugins/FreeImage/Source/LibPNG/KNOWNBUG +++ /dev/null @@ -1,29 +0,0 @@ - -Known bugs in libpng version 1.2.43 - -1. December 4, 2009: The PNG_NO_ERROR_NUMBERS macro was inadvertently - defined in libpng-1.2.41/pngconf.h, which may cause a problem with - building a binary-compatible library. - - STATUS: This will be fixed in libpng-1.2.42. In the meantime, simply - delete the definition from line : - -2. 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. - -3. 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. - -4. 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/plugins/FreeImage/Source/LibPNG/LICENSE b/plugins/FreeImage/Source/LibPNG/LICENSE deleted file mode 100644 index 0c927409ac..0000000000 --- a/plugins/FreeImage/Source/LibPNG/LICENSE +++ /dev/null @@ -1,111 +0,0 @@ - -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.5.9, February 18, 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 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 -February 18, 2012 diff --git a/plugins/FreeImage/Source/LibPNG/README b/plugins/FreeImage/Source/LibPNG/README deleted file mode 100644 index c648a5ad78..0000000000 --- a/plugins/FreeImage/Source/LibPNG/README +++ /dev/null @@ -1,202 +0,0 @@ -README for libpng version 1.5.9 - February 18, 2012 (shared library 15.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*.zip if you want DOS-style line endings. - -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_ and -png_get_ 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-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-manual.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.info-zip.org/pub/infozip/zlib - -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/documents/ - -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.sourceforge.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-implement list, however. - -Please do not send general questions about PNG. Send them to -png-mng-misc at lists.sf.net (subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-misc to -subscribe). 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 sixteen 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.3 => manual page for libpng (includes libpng-manual.txt) - libpng-manual.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 (public) - pngpriv.h => Library function and interface declarations (private) - pngconf.h => System specific library configuration (public) - pngstruct.h => png_struct declaration (private) - pnginfo.h => png_info struct declaration (private) - pngdebug.h => debugging macros (private) - 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 - 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 - cbuilder5 => Contains a Borland workspace for building - libpng and zlib - visualc6 => Contains a Microsoft Visual C++ (MSVC) - workspace for building libpng and zlib - visualc71 => Contains a Microsoft Visual C++ (MSVC) - workspace for building libpng and zlib - xcode => Contains an Apple xcode - workspace for building libpng and zlib - scripts => Directory containing scripts for building libpng: - (see scripts/README.txt for the list of scripts) - -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://www-mddsp.enel.ucalgary.ca/People/adilger/ - --Guy Eric Schalnat (original author and former maintainer, 1995-1996) - (formerly of Group 42, Inc) - Internet: gschal at infinet.com diff --git a/plugins/FreeImage/Source/LibPNG/TODO b/plugins/FreeImage/Source/LibPNG/TODO deleted file mode 100644 index b1660a413a..0000000000 --- a/plugins/FreeImage/Source/LibPNG/TODO +++ /dev/null @@ -1,27 +0,0 @@ -/* -TODO - list of things to do for libpng: - -Final bug fixes. -Better C++ wrapper/full C++ implementation? -Fix problem with C++ and EXTERN "C". -cHRM transformation. -Remove setjmp/longjmp usage 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). -Avoid building gamma tables whenever possible. -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. -Switch to the simpler zlib (zlib/libpng) license if legally possible. -Extend pngvalid.c to validate more of the libpng transformations. - -*/ diff --git a/plugins/FreeImage/Source/LibPNG/Y2KINFO b/plugins/FreeImage/Source/LibPNG/Y2KINFO deleted file mode 100644 index 7776d83732..0000000000 --- a/plugins/FreeImage/Source/LibPNG/Y2KINFO +++ /dev/null @@ -1,55 +0,0 @@ - Y2K compliance in libpng: - ========================= - - February 25, 2010 - - 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.43 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/plugins/FreeImage/Source/LibPNG/configure b/plugins/FreeImage/Source/LibPNG/configure deleted file mode 100644 index 9da0f74eca..0000000000 --- a/plugins/FreeImage/Source/LibPNG/configure +++ /dev/null @@ -1,19 +0,0 @@ - -echo " - There is no \"configure\" script in this distribution of - libpng-1.5.9. - - 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.5.9.tar.gz, libpng-1.5.9.tar.xz, or libpng-1.5.9.tar.bz2 - - If the line endings in the files look funny, which is likely to be the - case if you were trying to run \"configure\" on a Linux machine, you may - wish to get the other distribution of libpng. It is available in both - tar.gz/tar.xz (UNIX style line endings) and .7z/.zip (DOS style line - endings) formats. -" - diff --git a/plugins/FreeImage/Source/LibPNG/libpng.3 b/plugins/FreeImage/Source/LibPNG/libpng.3 deleted file mode 100644 index 1d72ab4cae..0000000000 --- a/plugins/FreeImage/Source/LibPNG/libpng.3 +++ /dev/null @@ -1,5952 +0,0 @@ -.TH LIBPNG 3 "February 18, 2012" -.SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.5.9 -.SH SYNOPSIS -\fI\fB - -\fB#include \fP - -\fI\fB - -\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP - -\fI\fB - -\fBvoid png_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP - -\fI\fB - -\fBvoid png_build_grayscale_palette (int \fP\fIbit_depth\fP\fB, png_colorp \fIpalette\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_calloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP - -\fI\fB - -\fBvoid png_chunk_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\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 - -\fBvoid png_data_freer (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIfreer\fP\fB, png_uint_32 \fImask)\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_err (png_structp \fIpng_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_bKGD (png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_cHRM (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_uint_32 png_get_cHRM_XYZ (png_structp \fIpng_ptr, - -\fBpng_const_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*red_X\fP\fB, double \fP\fI*red_Y\fP\fB, double \fI*red_Z, - -\fBdouble \fP\fI*green_X\fP\fB, double \fP\fI*green_Y\fP\fB, double \fP\fI*green_Z\fP\fB, double \fI*blue_X, - -\fBdouble \fP\fI*blue_Y\fP\fB, double \fI*blue_Z\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_cHRM_XYZ_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_fixed_point \fP\fI*int_red_X\fP\fB, png_fixed_point \fP\fI*int_red_Y\fP\fB, png_fixed_point \fP\fI*int_red_Z\fP\fB, png_fixed_point \fP\fI*int_green_X\fP\fB, png_fixed_point \fP\fI*int_green_Y\fP\fB, png_fixed_point \fP\fI*int_green_Z\fP\fB, png_fixed_point \fP\fI*int_blue_X\fP\fB, png_fixed_point \fP\fI*int_blue_Y\fP\fB, png_fixed_point \fI*int_blue_Z\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_chunk_cache_max (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_alloc_size_t png_get_chunk_malloc_max (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_byte png_get_color_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_compression_buffer_size (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_byte png_get_compression_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_byte png_get_copyright (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_current_row_number \fI(png_const_structp\fP\fB);\fP - -\fI\fB - -\fBpng_byte png_get_current_pass_number \fI(png_const_structp\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_get_error_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_byte png_get_filter_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_gAMA (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_gAMA_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_byte png_get_header_version (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_hIST (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_iCCP (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_bytepp \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_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_image_width (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_int_32 png_get_int_32 (png_bytep \fIbuf\fP\fB);\fP - -\fI\fB - -\fBpng_byte png_get_interlace_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_const_bytep png_get_io_chunk_name (png_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_io_chunk_type (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_io_state (png_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_byte png_get_libpng_ver (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_get_mem_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_oFFs (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_pHYs_dpi (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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 - -\fBpng_fixed_point png_get_pixel_aspect_ratio_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_get_progressive_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_PLTE (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fIpng_ptr) - -\fBpng_uint_32 png_get_rowbytes (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_bytepp png_get_rows (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_sBIT (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP - -\fI\fB - -\fBvoid png_get_sCAL (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, double* \fP\fIwidth\fP\fB, double* \fIheight\fP\fB);\fP - -\fI\fB - -\fBvoid png_get_sCAL_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_fixed_pointp \fP\fIwidth\fP\fB, png_fixed_pointp \fIheight\fP\fB);\fP - -\fI\fB - -\fBvoid png_get_sCAL_s (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_charpp \fP\fIwidth\fP\fB, png_charpp \fIheight\fP\fB);\fP - -\fI\fB - -\fBpng_bytep png_get_signature (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_sPLT (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_sRGB (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int \fI*file_srgb_intent\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_text (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans_alpha\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_color\fP\fB);\fP - -\fI\fB - -\fB/* This function is really an inline macro. \fI*/ - -\fBpng_uint_16 png_get_uint_16 (png_bytep \fIbuf\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_uint_31 (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIbuf\fP\fB);\fP - -\fI\fB - -\fB/* This function is really an inline macro. \fI*/ - -\fBpng_uint_32 png_get_uint_32 (png_bytep \fIbuf\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_unknown_chunks (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_get_user_chunk_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_user_height_max (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_get_user_transform_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_user_width_max (png_const_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_valid (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP - -\fI\fB - -\fBfloat png_get_x_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_fixed_point png_get_x_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_int_32 png_get_x_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_int_32 png_get_x_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_x_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_x_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBfloat png_get_y_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_fixed_point png_get_y_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_int_32 png_get_y_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_int_32 png_get_y_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_y_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_get_y_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_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_info_init_3 (png_infopp \fP\fIinfo_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP - -\fI\fB - -\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP - -\fI\fB - -\fBvoid png_longjmp (png_structp \fP\fIpng_ptr\fP\fB, int \fIval\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_malloc_default (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP - -\fI\fB - -\fBpng_voidp png_malloc_warn (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_permit_mng_features (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fImng_features_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 - -\fBpng_size_t png_process_data_pause \fP\fI(png_structp\fP\fB, int \fIsave\fP\fB);\fP - -\fI\fB - -\fBpng_uint_32 png_process_data_skip \fI(png_structp\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_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 - -\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 - -\fBint png_reset_zstream (png_structp \fIpng_ptr\fP\fB);\fP - -\fI\fB - -\fBvoid png_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 - -\fBvoid png_set_alpha_mode (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImode\fP\fB, double \fIoutput_gamma\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_alpha_mode_fixed (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImode\fP\fB, png_fixed_point \fIoutput_gamma\fP\fB);\fP - -\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_background_fixed (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, png_uint_32 \fIbackground_gamma\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_benign_errors (png_structp \fP\fIpng_ptr\fP\fB, int \fIallowed\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_cHRM_XYZ (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIred_X\fP\fB, double \fP\fIred_Y\fP\fB, double \fP\fIred_Z\fP\fB, double \fP\fIgreen_X\fP\fB, double \fIgreen_Y, - -\fBdouble \fP\fIgreen_Z\fP\fB, double \fP\fIblue_X\fP\fB, double \fP\fIblue_Y\fP\fB, double \fIblue_Z\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_cHRM_XYZ_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\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_red_Z\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_green_Z\fP\fB, png_fixed_point \fP\fIint_blue_X\fP\fB, png_fixed_point \fP\fIint_blue_Y\fP\fB, png_fixed_point \fIint_blue_Z\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_chunk_cache_max (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIuser_chunk_cache_max\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_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_16 (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_filter_heuristics_fixed (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_fixed_point_p \fP\fIfilter_weights\fP\fB, png_fixed_point_p \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_gamma_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIscreen_gamma\fP\fB, png_uint_32 \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_const_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_const_bytep \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 - -\fBjmp_buf* png_set_longjmp_fn (png_structp \fP\fIpng_ptr\fP\fB, png_longjmp_ptr \fP\fIlongjmp_fn\fP\fB, size_t \fIjmp_buf_size\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_chunk_malloc_max (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIuser_chunk_cache_max\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 - -\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_quantize (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_quantize\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_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_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_uint_32 \fP\fIred\fP\fB, png_uint_32 \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, int \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_sCAL_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_fixed_point \fP\fIwidth\fP\fB, png_fixed_point \fIheight\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_sCAL_s (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_charp \fP\fIwidth\fP\fB, png_charp \fIheight\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_scale_16 (png_structp \fIpng_ptr\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 \fIsrgb_intent\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 \fIsrgb_intent\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_strip_error_numbers (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIstrip_mode\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_text_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_text_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_text_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP - -\fI\fB - -\fBvoid png_set_text_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP - -\fI\fB - -\fBvoid \fP\fIpng_set_text_compression_method\fP\fB, (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod)\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_alpha\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_color\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_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 - -\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_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 - -\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 - -\fBvoid png_write_sig (png_structp \fIpng_ptr\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-manual.txt file that accompanies libpng. -.SH LIBPNG.TXT -libpng-manual.txt - A description on how to use and modify libpng - - libpng version 1.5.9 - February 18, 2012 - Updated and distributed by Glenn Randers-Pehrson - - Copyright (c) 1998-2011 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.5.9 - February 18, 2012 - Updated and distributed by Glenn Randers-Pehrson - Copyright (c) 1998-2011 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 -. 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 and as a -W3C Recommendation . - -Some additional chunks are described in the special-purpose public chunks -documents at . - -Other information -about PNG, and the latest version of libpng, can be found at the PNG home -page, . - -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, . -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. Both are internal structures that are no longer exposed -in the libpng interface (as of libpng 1.5.0). - -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, and direct access to the png_info fields was -deprecated.. - -The png_struct structure is the object used by the library to decode a -single image. As of 1.5.0 this structure is also not exposed. - -Almost all libpng APIs require a pointer to a png_struct as the first argument. -Many (in particular the png_set and png_get APIs) also require a pointer -to png_info as the second argument. Some application visible macros -defined in png.h designed for basic data access (reading and writing -integers in the PNG format) don't take a png_info pointer, but it's almost -always safe to assume that a (png_struct*) has to be passed to call an API -function. - -You can have more than one png_info structure associated with an image, -as illustrated in pngtest.c, one for information valid prior to the -IDAT chunks and another (called "end_info" below) for things after them. - -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 - -and also (as of libpng-1.5.0) the zlib header file, if you need it: - -#include - -.SS Types - -The png.h header file defines a number of integral types used by the -APIs. Most of these are fairly obvious; for example types corresponding -to integers of particular sizes and types for passing color values. - -One exception is how non-integral numbers are handled. For application -convenience most APIs that take such numbers have C (double) arguments, -however internally PNG, and libpng, use 32 bit signed integers and encode -the value by multiplying by 100,000. As of libpng 1.5.0 a convenience -macro PNG_FP_1 is defined in png.h along with a type (png_fixed_point) -which is simply (png_int_32). - -All APIs that take (double) arguments also have a matching API that -takes the corresponding fixed point integer arguments. The fixed point -API has the same name as the floating point one with "_fixed" appended. -The actual range of values permitted in the APIs is frequently less than -the full range of (png_fixed_point) (-21474 to +21474). When APIs require -a non-negative argument the type is recorded as png_uint_32 above. Consult -the header file and the text below for more information. - -Special care must be take with sCAL chunk handling because the chunk itself -uses non-integral values encoded as strings containing decimal floating point -numbers. See the comments in the header file. - -.SS Configuration - -The main header file function declarations are frequently protected by C -preprocessing directives of the form: - - #ifdef PNG_feature_SUPPORTED - declare-function - #endif - ... - #ifdef PNG_feature_SUPPORTED - use-function - #endif - -The library can be built without support for these APIs, although a -standard build will have all implemented APIs. Application programs -should check the feature macros before using an API for maximum -portability. From libpng 1.5.0 the feature macros set during the build -of libpng are recorded in the header file "pnglibconf.h" and this file -is always included by png.h. - -If you don't need to change the library configuration from the default, skip to -the next section ("Reading"). - -Notice that some of the makefiles in the 'scripts' directory and (in 1.5.0) all -of the build project files in the 'projects' directory simply copy -scripts/pnglibconf.h.prebuilt to pnglibconf.h. This means that these build -systems do not permit easy auto-configuration of the library - they only -support the default configuration. - -The easiest way to make minor changes to the libpng configuration when -auto-configuration is supported is to add definitions to the command line -using (typically) CPPFLAGS. For example: - -CPPFLAGS=-DPNG_NO_FLOATING_ARITHMETIC - -will change the internal libpng math implementation for gamma correction and -other arithmetic calculations to fixed point, avoiding the need for fast -floating point support. The result can be seen in the generated pnglibconf.h - -make sure it contains the changed feature macro setting. - -If you need to make more extensive configuration changes - more than one or two -feature macro settings - you can either add -DPNG_USER_CONFIG to the build -command line and put a list of feature macro settings in pngusr.h or you can set -DFA_XTRA (a makefile variable) to a file containing the same information in the -form of 'option' settings. - -A. Changing pnglibconf.h - -A variety of methods exist to build libpng. Not all of these support -reconfiguration of pnglibconf.h. To reconfigure pnglibconf.h it must either be -rebuilt from scripts/pnglibconf.dfa using awk or it must be edited by hand. - -Hand editing is achieved by copying scripts/pnglibconf.h.prebuilt to -pnglibconf.h and changing the lines defining the supported features, paying -very close attention to the 'option' information in scripts/pnglibconf.dfa -that describes those features and their requirements. This is easy to get -wrong. - -B. Configuration using DFA_XTRA - -Rebuilding from pnglibconf.dfa is easy if a functioning 'awk', or a later -variant such as 'nawk' or 'gawk', is available. The configure build will -automatically find an appropriate awk and build pnglibconf.h. -The scripts/pnglibconf.mak file contains a set of make rules for doing the -same thing if configure is not used, and many of the makefiles in the scripts -directory use this approach. - -When rebuilding simply write a new file containing changed options and set -DFA_XTRA to the name of this file. This causes the build to append the new file -to the end of scripts/pnglibconf.dfa. The pngusr.dfa file should contain lines -of the following forms: - -everything = off - -This turns all optional features off. Include it at the start of pngusr.dfa to -make it easier to build a minimal configuration. You will need to turn at least -some features on afterward to enable either reading or writing code, or both. - -option feature on -option feature off - -Enable or disable a single feature. This will automatically enable other -features required by a feature that is turned on or disable other features that -require a feature which is turned off. Conflicting settings will cause an error -message to be emitted by awk. - -setting feature default value - -Changes the default value of setting 'feature' to 'value'. There are a small -number of settings listed at the top of pnglibconf.h, they are documented in the -source code. Most of these values have performance implications for the library -but most of them have no visible effect on the API. Some can also be overridden -from the API. - -This method of building a customized pnglibconf.h is illustrated in -contrib/pngminim/*. See the "$(PNGCONF):" target in the makefile and -pngusr.dfa in these directories. - -C. Configuration using PNG_USR_CONFIG - -If -DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file -pngusr.h will automatically be included before the options in -scripts/pnglibconf.dfa are processed. Your pngusr.h file should contain only -macro definitions turning features on or off or setting settings. - -Apart from the global setting "everything = off" all the options listed above -can be set using macros in pngusr.h: - -#define PNG_feature_SUPPORTED - -is equivalent to: - -option feature on - -#define PNG_NO_feature - -is equivalent to: - -option feature off - -#define PNG_feature value - -is equivalent to: - -setting feature default value - -Notice that in both cases, pngusr.dfa and pngusr.h, the contents of the -pngusr file you supply override the contents of scripts/pnglibconf.dfa - -If confusing or incomprehensible behavior results it is possible to -examine the intermediate file pnglibconf.dfn to find the full set of -dependency information for each setting and option. Simply locate the -feature in the file and read the C comments that precede it. - -This method is also illustrated in the contrib/pngminim/* makefiles and -pngusr.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); - } - -If you want to use your own memory allocation routines, -use a libpng that was built with PNG_USER_MEM_SUPPORTED defined, 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 longjmp buffer 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); - } - -Pass (png_infopp)NULL instead of &end_info if you didn't create -an end_info structure. - -If you would rather avoid the complexity of setjmp/longjmp issues, -you can compile libpng with PNG_NO_SETJMP, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -You can #define PNG_ABORT() to a function that does something -more useful than abort(), as long as your function does not -return. - -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); - -You can change the zlib compression buffer size to be used while -reading compressed data with - - png_set_compression_buffer_size(png_ptr, buffer_size); - -where the default size is 8192 bytes. Note that the buffer size -is changed immediately and the buffer is reallocated immediately, -instead of setting a flag to be acted upon later. - -If you want CRC errors to be handled in a different manner than -the default, use - - png_set_crc_action(png_ptr, crit_action, ancil_action); - -The values for png_set_crc_action() say how libpng is 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. - -Choices for (int) crit_action are - PNG_CRC_DEFAULT 0 error/quit - PNG_CRC_ERROR_QUIT 1 error/quit - PNG_CRC_WARN_USE 3 warn/use data - PNG_CRC_QUIET_USE 4 quiet/use data - PNG_CRC_NO_CHANGE 5 use the current value - -Choices for (int) ancil_action are - PNG_CRC_DEFAULT 0 error/quit - PNG_CRC_ERROR_QUIT 1 error/quit - PNG_CRC_WARN_DISCARD 2 warn/discard data - PNG_CRC_WARN_USE 3 warn/use data - PNG_CRC_QUIET_USE 4 quiet/use data - PNG_CRC_NO_CHANGE 5 use the current value - -.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_structp png_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_structp png_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); - -When this function is called the row has already been completely processed and -the 'row' and 'pass' refer to the next row to be handled. For the -non-interlaced case the row that was just handled is simply one less than the -passed in row number, and pass will always be 0. For the interlaced case the -same applies unless the row value is 0, in which case the row just handled was -the last one from one of the preceding passes. Because interlacing may skip a -pass you cannot be sure that the preceding pass is just 'pass-1', if you really -need to know what the last pass is record (row,pass) from the callback and use -the last recorded value each time. - -As with the user transform you can find the output row using the -PNG_ROW_FROM_PASS_ROW macro. - -.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. -If you know that your application will never make use of some particular -chunks, use PNG_HANDLE_CHUNK_NEVER (or 1) as demonstrated below. - -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 change 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(). - -When writing a PNG datastream, put this statement before calling -png_write_info() or png_write_png(). - -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. - -You can also set a limit on the amount of memory that a compressed chunk -other than IDAT can occupy, with - - png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); - -and you can retrieve the limit with - - chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); - -Any chunks that would cause either of these limits to be exceeded will -be ignored. - -.SS Information about your system - -If you intend to display the PNG or to incorporate it in other image data you -need to tell libpng information about your display or drawing surface so that -libpng can convert the values in the image to match the display. - -From libpng-1.5.4 this information can be set before reading the PNG file -header. In earlier versions png_set_gamma() existed but behaved incorrectly if -called before the PNG file header had been read and png_set_alpha_mode() did not -exist. - -If you need to support versions prior to libpng-1.5.4 test the version number -as illustrated below using "PNG_LIBPNG_VER >= 10504" and follow the procedures -described in the appropriate manual page. - -You give libpng the encoding expected by your system expressed as a 'gamma' -value. You can also specify a default encoding for the PNG file in -case the required information is missing from the file. By default libpng -assumes that the PNG data matches your system, to keep this default call: - - png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/); - -or you can use the fixed point equivalent: - - png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma, PNG_FP_1/screen_gamma); - -If you don't know the gamma for your system it is probably 2.2 - a good -approximation to the IEC standard for display systems (sRGB). If images are -too contrasty or washed out you got the value wrong - check your system -documentation! - -Many systems permit the system gamma to be changed via a lookup table in the -display driver, a few systems, including older Macs, change the response by -default. As of 1.5.4 three special values are available to handle common -situations: - - PNG_DEFAULT_sRGB: Indicates that the system conforms to the IEC 61966-2-1 - standard. This matches almost all systems. - PNG_GAMMA_MAC_18: Indicates that the system is an older (pre Mac OS 10.6) - Apple Macintosh system with the default settings. - PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates that the - system expects data with no gamma encoding. - -You would use the linear (unencoded) value if you need to process the pixel -values further because this avoids the need to decode and reencode each -component value whenever arithmetic is performed. A lot of graphics software -uses linear values for this reason, often with higher precision component values -to preserve overall accuracy. - -The second thing you may need to tell libpng about is how your system handles -alpha channel information. Some, but not all, PNG files contain an alpha -channel. To display these files correctly you need to compose the data onto a -suitable background, as described in the PNG specification. - -Libpng only supports composing onto a single color (using png_set_background; -see below). Otherwise you must do the composition yourself and, in this case, -you may need to call png_set_alpha_mode: - -#if PNG_LIBPNG_VER >= 10504 - png_set_alpha_mode(png_ptr, mode, screen_gamma); -#else - png_set_gamma(png_ptr, screen_gamma, 1.0/screen_gamma); -#endif - -The screen_gamma value is the same as the argument to png_set_gamma; however, -how it affects the output depends on the mode. png_set_alpha_mode() sets the -file gamma default to 1/screen_gamma, so normally you don't need to call -png_set_gamma. If you need different defaults call png_set_gamma() before -png_set_alpha_mode() - if you call it after it will override the settings made -by png_set_alpha_mode(). - -The mode is as follows: - - PNG_ALPHA_PNG: The data is encoded according to the PNG specification. Red, -green and blue, or gray, components are gamma encoded color -values and are not premultiplied by the alpha value. The -alpha value is a linear measure of the contribution of the -pixel to the corresponding final output pixel. - -You should normally use this format if you intend to perform -color correction on the color values; most, maybe all, color -correction software has no handling for the alpha channel and, -anyway, the math to handle pre-multiplied component values is -unnecessarily complex. - -Before you do any arithmetic on the component values you need -to remove the gamma encoding and multiply out the alpha -channel. See the PNG specification for more detail. It is -important to note that when an image with an alpha channel is -scaled, linear encoded, pre-multiplied component values must -be used! - -The remaining modes assume you don't need to do any further color correction or -that if you do, your color correction software knows all about alpha (it -probably doesn't!) - - PNG_ALPHA_STANDARD: The data libpng produces -is encoded in the standard way -assumed by most correctly written graphics software. -The gamma encoding will be removed by libpng and the -linear component values will be pre-multiplied by the -alpha channel. - -With this format the final image must be re-encoded to -match the display gamma before the image is displayed. -If your system doesn't do that, yet still seems to -perform arithmetic on the pixels without decoding them, -it is broken - check out the modes below. - -With PNG_ALPHA_STANDARD libpng always produces linear -component values, whatever screen_gamma you supply. The -screen_gamma value is, however, used as a default for -the file gamma if the PNG file has no gamma information. - -If you call png_set_gamma() after png_set_alpha_mode() you -will override the linear encoding. Instead the -pre-multiplied pixel values will be gamma encoded but -the alpha channel will still be linear. This may -actually match the requirements of some broken software, -but it is unlikely. - -While linear 8-bit data is often used it has -insufficient precision for any image with a reasonable -dynamic range. To avoid problems, and if your software -supports it, use png_set_expand_16() to force all -components to 16 bits. - - PNG_ALPHA_OPTIMIZED: This mode is the same -as PNG_ALPHA_STANDARD except that -completely opaque pixels are gamma encoded according to -the screen_gamma value. Pixels with alpha less than 1.0 -will still have linear components. - -Use this format if you have control over your -compositing software and do don't do other arithmetic -(such as scaling) on the data you get from libpng. Your -compositing software can simply copy opaque pixels to -the output but still has linear values for the -non-opaque pixels. - -In normal compositing, where the alpha channel encodes -partial pixel coverage (as opposed to broad area -translucency), the inaccuracies of the 8-bit -representation of non-opaque pixels are irrelevant. - -You can also try this format if your software is broken; -it might look better. - - PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD; -however, all component values, -including the alpha channel are gamma encoded. This is -an appropriate format to try if your software, or more -likely hardware, is totally broken, i.e., if it performs -linear arithmetic directly on gamma encoded values. - -In most cases of broken software or hardware the bug in the final display -manifests as a subtle halo around composited parts of the image. You may not -even perceive this as a halo; the composited part of the image may simply appear -separate from the background, as though it had been cut out of paper and pasted -on afterward. - -If you don't have to deal with bugs in software or hardware, or if you can fix -them, there are three recommended ways of using png_set_alpha_mode(): - - png_set_alpha_mode(png_ptr, PNG_ALPHA_PNG, - screen_gamma); - -You can do color correction on the result (libpng does not currently -support color correction internally). When you handle the alpha channel -you need to undo the gamma encoding and multiply out the alpha. - - png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, - screen_gamma); - png_set_expand_16(png_ptr); - -If you are using the high level interface, don't call png_set_expand_16(); -instead pass PNG_TRANSFORM_EXPAND_16 to the interface. - -With this mode you can't do color correction, but you can do arithmetic, -including composition and scaling, on the data without further processing. - - png_set_alpha_mode(png_ptr, PNG_ALPHA_OPTIMIZED, - screen_gamma); - -You can avoid the expansion to 16-bit components with this mode, but you -lose the ability to scale the image or perform other linear arithmetic. -All you can do is compose the result onto a matching output. Since this -mode is libpng-specific you also need to write your own composition -software. - -If you don't need, or can't handle, the alpha channel you can call -png_set_background() to remove it by compositing against a fixed color. Don't -call png_set_strip_alpha() to do this - it will leave spurious pixel values in -transparent parts of this image. - - png_set_background(png_ptr, &background_color, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1); - -The background_color is an RGB or grayscale value according to the data format -libpng will produce for you. Because you don't yet know the format of the PNG -file, if you call png_set_background at this point you must arrange for the -format produced by libpng to always have 8-bit or 16-bit components and then -store the color as an 8-bit or 16-bit color as appropriate. The color contains -separate gray and RGB component values, so you can let libpng produce gray or -RGB output according to the input format, but low bit depth grayscale images -must always be converted to at least 8-bit format. (Even though low bit depth -grayscale images can't have an alpha channel they can have a transparent -color!) - -You set the transforms you need later, either as flags to the high level -interface or libpng API calls for the low level interface. For reference the -settings and API calls required are: - -8-bit values: - PNG_TRANSFORM_SCALE_16 | PNG_EXPAND - png_set_expand(png_ptr); png_set_scale_16(png_ptr); - - If you must get exactly the same inaccurate results - produced by default in versions prior to libpng-1.5.4, - use PNG_TRANSFORM_STRIP_16 and png_set_strip_16(png_ptr) - instead. - -16-bit values: - PNG_TRANSFORM_EXPAND_16 - png_set_expand_16(png_ptr); - -In either case palette image data will be expanded to RGB. If you just want -color data you can add PNG_TRANSFORM_GRAY_TO_RGB or png_set_gray_to_rgb(png_ptr) -to the list. - -Calling png_set_background before the PNG file header is read will not work -prior to libpng-1.5.4. Because the failure may result in unexpected warnings or -errors it is therefore much safer to call png_set_background after the head has -been read. Unfortunately this means that prior to libpng-1.5.4 it cannot be -used with the high level interface. - -.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_SCALE_16 Strip 16-bit samples to - 8-bit accurately - PNG_TRANSFORM_STRIP_16 Chop 16-bit samples to - 8-bit less accurately - 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) - PNG_TRANSFORM_EXPAND_16 Expand samples to 16 bits - -(This excludes setting a background color, doing gamma transformation, -quantizing, 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) and -png_get_(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_ 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, &file_gamma); - png_get_gAMA_fixed(png_ptr, info_ptr, &int_file_gamma); - - file_gamma - the gamma at which the file is - written (PNG_INFO_gAMA) - - int_file_gamma - 100,000 times the gamma at which the - file is written - - png_get_cHRM(png_ptr, info_ptr, &white_x, &white_y, &red_x, &red_y, - &green_x, &green_y, &blue_x, &blue_y) - png_get_cHRM_XYZ(png_ptr, info_ptr, &red_X, &red_Y, &red_Z, &green_X, - &green_Y, &green_Z, &blue_X, &blue_Y, &blue_Z) - png_get_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) - png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, &int_red_X, &int_red_Y, - &int_red_Z, &int_green_X, &int_green_Y, &int_green_Z, - &int_blue_X, &int_blue_Y, &int_blue_Z) - - {white,red,green,blue}_{x,y} - A color space encoding specified using the chromaticities - of the end points and the white point. (PNG_INFO_cHRM) - - {red,green,blue}_{X,Y,Z} - A color space encoding specified using the encoding end - points - the CIE tristimulus specification of the intended - color of the red, green and blue channels in the PNG RGB - data. The white point is simply the sum of the three end - points. (PNG_INFO_cHRM) - - png_get_sRGB(png_ptr, info_ptr, &srgb_intent); - - file_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_type - 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_alpha, - &num_trans, &trans_color); - - trans_alpha - array of alpha (transparency) - entries for palette (PNG_INFO_tRNS) - - num_trans - number of transparent entries - (PNG_INFO_tRNS) - - trans_color - graylevel or color sample values of - the single transparent color for - non-paletted images (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 (of type - png_color_16p) (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. Prior to - libpng-1.4.0 the library was built by default without - iTXt support. Also note that when iTXt is supported, - they contain NULL pointers when the "compression" - field contains PNG_TEXT_COMPRESSION_NONE or - PNG_TEXT_COMPRESSION_zTXt. - - 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); - - num_spalettes - number of sPLT chunks read. - - palette_ptr - array of palette structures holding - contents of one or more 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 (can be negative) - - offset_y - positive offset from the top edge - of the screen (can be negative) - - 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 - (expressed as a string) - - 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 value of "location" is a bitwise "or" of - - PNG_HAVE_IHDR (0x01) - PNG_HAVE_PLTE (0x02) - PNG_AFTER_IDAT (0x08) - -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 - - Note that because of the way the resolutions are - stored internally, the inch conversions won't - come out to exactly even number. For example, - 72 dpi is stored as 0.28346 pixels/meter, and - when this is retrieved it is 71.9988 dpi, so - be sure to round the returned value appropriately - if you want to display a reasonable-looking result. - -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. The - remark about inexact inch conversions applies here - as well, because a value in inches can't always be - converted to microns and back without some loss - of precision. - -For more information, see 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. - -Transformations you request are ignored if they don't have any meaning for a -particular input data format. However some transformations can have an effect -as a result of a previous transformation. If you specify a contradictory set of -transformations, for example both adding and removing the alpha channel, you -cannot predict the final result. - -The color used for the transparency values should be supplied in the same -format/depth as the current image data. It is stored in the same format/depth -as the image data in a tRNS chunk, so this is what libpng expects for this data. - -The color used for the background value depends on the need_expand argument as -described 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_scale_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(), png_set_strip_16(), -or png_set_scale_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 (png_get_valid(png_ptr, info_ptr, - PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); - - if (color_type == PNG_COLOR_TYPE_GRAY && - bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); - -The first two 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.5.2, png_set_expand_16() was added. It behaves as -png_set_expand(); however, the resultant channels have 16 bits rather than 8. -Use this when the output color or gray channels are made linear to avoid fairly -severe accuracy loss. - - if (bit_depth < 16) - png_set_expand_16(png_ptr); - -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) -#if PNG_LIBPNG_VER >= 10504 - png_set_scale_16(png_ptr); -#else - png_set_strip_16(png_ptr); -#endif - -(The more accurate "png_set_scale_16()" API became available in libpng version -1.5.4). - -If you need to process the alpha channel on the image separately from the image -data (for example if you convert it to a bitmap mask) it is possible to have -libpng strip the channel leaving just RGB or gray data: - - if (color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png_ptr); - -If you strip the alpha channel you need to find some other way of dealing with -the information. If, instead, you want to convert the image to an opaque -version with no alpha channel use png_set_background; see below. - -As of libpng version 1.5.2, almost all useful expansions are supported, the -major ommissions are conversion of grayscale to indexed images (which can be -done trivially in the application) and conversion of indexed to grayscale (which -can be done by a trivial manipulation of the palette.) - -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 - [G] - - - - - - - - - - - - - - 31 [Q] Q [Q] [Q] [Q] Q Q Q Q Q Q [Q] [Q] Q Q - 0 1 G + . . G G G G G G B B GB GB - 0T lt Gt t + . Gt G G Gt G G Bt Bt GBt GBt - 0O lt Gt t . + Gt Gt G Gt Gt G Bt Bt GBt GBt - 2 C P C C C + . . C - - CB CB B B - 2T Ct - Ct C C t + t - - - CBt CBt Bt Bt - 2O Ct - Ct C C t t + - - - CBt CBt Bt Bt - 3 [Q] p [Q] [Q] [Q] Q Q Q + . . [Q] [Q] Q Q - 3T [Qt] p [Qt][Q] [Q] Qt Qt Qt t + t [Qt][Qt] Qt Qt - 3O [Qt] p [Qt][Q] [Q] Qt Qt Qt t t + [Qt][Qt] Qt Qt - 4A lA G A T T GA GT GT GA GT GT + BA G GBA - 4O lA GBA A T T GA GT GT GA GT GT BA + GBA G - 6A CA PA CA C C A T tT PA P P C CBA + BA - 6O CA PBA CA C C A tT T PA P P CBA C BA + - -Within the matrix, - "+" identifies entries where 'from' and 'to' are the same. - "-" means the transformation is not supported. - "." means nothing is necessary (a tRNS chunk can just be ignored). - "t" means the transformation is obtained by png_set_tRNS. - "A" means the transformation is obtained by png_set_add_alpha(). - "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() (and by png_set_expand() if there - is no transparency in the original or the final format). - "C" means the transformation is obtained by png_set_gray_to_rgb(). - "G" means the transformation is obtained by png_set_rgb_to_gray(). - "P" means the transformation is obtained by - png_set_expand_palette_to_rgb(). - "p" means the transformation is obtained by png_set_packing(). - "Q" means the transformation is obtained by png_set_quantize(). - "T" means the transformation is obtained by png_set_tRNS_to_alpha(). - "B" means the transformation is obtained by png_set_background(), or - png_strip_alpha(). - -When an entry has multiple transforms listed all are required to cause the -right overall transformation. When two transforms are separated by a comma -either will do the job. When transforms are enclosed in [] the transform should -do the job but this is currently unimplemented - a different format will result -if the suggested transformations are used. - -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(png_ptr, error_action, double red_weight, - double 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 - - green_weight: weight of green component - If either weight is negative, default - weights are used. - -In the corresponding fixed point API the red_weight and green_weight values are -simply scaled by 100,000: - - png_set_rgb_to_gray(png_ptr, error_action, png_fixed_point red_weight, - png_fixed_point green_weight); - -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. Background and sBIT data -will be silently converted to grayscale, using the green channel -data for sBIT, regardless of the error_action setting. - -The default values come from the PNG file cHRM chunk if present; otherwise, the -defaults correspond to the ITU-R recommendation 709, and also the sRGB color -space, as recommended in the Charles Poynton's Colour FAQ, -, in section 9: - - - - Y = 0.2126 * R + 0.7152 * G + 0.0722 * B - -Previous versions of this document, 1998 through 2002, recommended a slightly -different formula: - - Y = 0.212671 * R + 0.715160 * G + 0.072169 * B - -Libpng uses an integer approximation: - - Y = (6968 * R + 23434 * G + 2366 * B)/32768 - -The calculation is done in a linear colorspace, if the image gamma -can be determined. - -The png_set_background() function has been described already; it tells libpng to -composite images with alpha or simple transparency against the supplied -background color. For compatibility with versions of libpng earlier than -libpng-1.5.4 it is recommended that you call the function after reading the file -header, even if you don't want to use the color in a bKGD chunk, if one exists. - -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 how the color is represented, both the format of the -component values in the color (the number of bits) and the gamma encoding of the -color. The function takes two arguments, background_gamma_mode and need_expand -to convey this information, however only two combinations are likely to be -useful: - - 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/*needs to be expanded*/, 1); - else - png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0/*do not expand*/, 1); - -The second call was described above - my_background is in the format of the -final, display, output produced by libpng. Because you now know the format of -the PNG it is possible to avoid the need to choose either 8-bit or 16-bit -output and to retain palette images (the palette colors will be modified -appropriately and the tRNS chunk removed.) However, if you are doing this, -take great care not to ask for transformations without checking first that -they apply! - -In the first call the background color has the original bit depth and color type -of the PNG file. So, for palette images the color is supplied as a palette -index and for low bit greyscale images the color is a reduced bit value in -image_background->gray. - -If you didn't call png_set_gamma() before reading the file header, for example -if you need your code to remain compatible with older versions of libpng prior -to libpng-1.5.4, this is the place to call it. - -Do not call it if you called png_set_alpha_mode(); doing so will damage the -settings put in place by png_set_alpha_mode(). (If png_set_alpha_mode() is -supported then you can certainly do png_set_gamma() before reading the PNG -header.) - -This API unconditionally sets the screen and file gamma values, so it will -override the value in the PNG file unless it is called before the PNG file -reading starts. For this reason you must always call it with the PNG file -value when you call it in this position: - - if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) - png_set_gamma(png_ptr, screen_gamma, file_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_quantize() -will do that. Note that this is a simple match quantization that merely -finds the closest color available. This should work fairly well with -optimized palettes, but fairly badly with linear color cubes. If you -pass a palette that is larger than 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, libpng 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_quantize(png_ptr, palette, num_palette, - max_screen_colors, histogram, 1); - } - - else - { - png_color std_color_cube[MAX_SCREEN_COLORS] = - { ... colors ... }; - - png_set_quantize(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_structp png_ptr, png_row_infop - 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. Take care with -interlaced images if you do the interlace yourself - the width of the row is the -width in 'row_info', not the overall image width. - -If supported, libpng provides two information routines that you can use to find -where you are in processing the image: - - png_get_current_pass_number(png_structp png_ptr); - png_get_current_row_number(png_structp png_ptr); - -Don't try using these outside a transform callback - firstly they are only -supported if user transforms are supported, secondly they may well return -unexpected results unless the row is actually being processed at the moment they -are called. - -With interlaced -images the value returned is the row in the input sub-image image. Use -PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to -find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). - -The discussion of interlace handling above contains more information on how to -use these values. - -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. - - png_read_update_info(png_ptr, info_ptr); - -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. You may -only call png_read_update_info() once with a particular 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. - -Remember: Before you call png_read_update_info(), the png_get_*() -functions return the values corresponding to the original PNG image. -After you call png_read_update_info the values refer to the image -that libpng will output. Consequently you must call all the png_set_ -functions before you call png_read_update_info(). This is particularly -important for png_set_interlace_handling() - if you are going to call -png_read_update_info() you must call png_set_interlace_handling() before -it unless you want to receive interlaced output. - -.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() (unless you call -png_read_update_info()) 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); -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. This number is defined (from libpng 1.5) as -PNG_INTERLACE_ADAM7_PASSES in png.h - -libpng can fill out those images or it can give them to you "as is". -It is almost always better to have libpng handle the interlacing for you. -If you want the images 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, as is likely, 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. -You then need to read the whole image 'number_of_passes' times. Each time -will distribute the pixels from the current pass to the correct place in -the output image, so you need to supply the same rows to png_read_rows in -each 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); - -If you don't want libpng to handle the interlacing details, just call -png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images. -Each of the images is a valid image by itself, however you will almost -certainly need to distribute the pixels from each sub-image to the -correct place. This is where everything gets very tricky. - -If you want to retrieve the separate images you must pass the correct -number of rows to each successive call of png_read_rows(). The calculation -gets pretty complicated for small images, where some sub-images may -not even exist because either their width or height ends up zero. -libpng provides two macros to help you in 1.5 and later versions: - - png_uint_32 width = PNG_PASS_COLS(image_width, pass_number); - png_uint_32 height = PNG_PASS_ROWS(image_height, pass_number); - -Respectively these tell you the width and height of the sub-image -corresponding to the numbered pass. 'pass' is in in the range 0 to 6 - -this can be confusing because the specification refers to the same passes -as 1 to 7! Be careful, you must check both the width and height before -calling png_read_rows() and not call it for that pass if either is zero. - -You can, of course, read each sub-image row by row. If you want to -produce optimal code to make a pixel-by-pixel transformation of an -interlaced image this is the best approach; read each row of each pass, -transform it, and write it out to a new interlaced image. - -If you want to de-interlace the image yourself libpng provides further -macros to help that tell you where to place the pixels in the output image. -Because the interlacing scheme is rectangular - sub-image pixels are always -arranged on a rectangular grid - all you need to know for each pass is the -starting column and row in the output image of the first pixel plus the -spacing between each pixel. As of libpng 1.5 there are four macros to -retrieve this information: - - png_uint_32 x = PNG_PASS_START_COL(pass); - png_uint_32 y = PNG_PASS_START_ROW(pass); - png_uint_32 xStep = 1U << PNG_PASS_COL_SHIFT(pass); - png_uint_32 yStep = 1U << PNG_PASS_ROW_SHIFT(pass); - -These allow you to write the obvious loop: - - png_uint_32 input_y = 0; - png_uint_32 output_y = PNG_PASS_START_ROW(pass); - - while (output_y < output_image_height) - { - png_uint_32 input_x = 0; - png_uint_32 output_x = PNG_PASS_START_COL(pass); - - while (output_x < output_image_width) - { - image[output_y][output_x] = - subimage[pass][input_y][input_x++]; - - output_x += xStep; - } - - ++input_y; - output_y += yStep; - } - -Notice that the steps between successive output rows and columns are -returned as shifts. This is possible because the pixels in the subimages -are always a power of 2 apart - 1, 2, 4 or 8 pixels - in the original -image. In practice you may need to directly calculate the output coordinate -given an input coordinate. libpng provides two further macros for this -purpose: - - png_uint_32 output_x = PNG_COL_FROM_PASS_COL(input_x, pass); - png_uint_32 output_y = PNG_ROW_FROM_PASS_ROW(input_y, pass); - -Finally a pair of macros are provided to tell you if a particular image -row or column appears in a given pass: - - int col_in_pass = PNG_COL_IN_INTERLACE_PASS(output_x, pass); - int row_in_pass = PNG_ROW_IN_INTERLACE_PASS(output_y, pass); - -Bear in mind that you will probably also need to check the width and height -of the pass in addition to the above to be sure the pass even exists! - -With any luck you are convinced by now that you don't want to do your own -interlace handling. In reality normally the only good reason for doing this -is if you are processing PNG files on a pixel-by-pixel basis and don't want -to load the whole file into memory when it is interlaced. - -libpng includes a test program, pngvalid, that illustrates reading and -writing of interlaced images. If you can't get interlacing to work in your -code and don't want to leave it to libpng (the recommended approach), see -how pngvalid.c does it. - -.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. - - 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); - } - - png_read_end(png_ptr, end_info); - -If you are not interested, you should still call png_read_end() -but you can pass NULL, avoiding the need to create an end_info structure. - - png_read_end(png_ptr, (png_infop)NULL); - -If you don't call png_read_end(), then your file pointer will be -left pointing to the first chunk after the last IDAT, which is probably -not what you want if you expect to read something beyond the end of -the PNG datastream. - -When you are done, you can free all memory allocated by libpng like this: - - png_destroy_read_struct(&png_ptr, &info_ptr, - &end_info); - -or, if you didn't create an end_info structure, - - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - -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) - - freer - one of - PNG_DESTROY_WILL_FREE_DATA - PNG_SET_WILL_FREE_DATA - PNG_USER_WILL_FREE_DATA - - mask - which data elements are affected - same choices as in png_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); - - /* At this point you can call png_process_data_skip if - you want to handle data the library will skip yourself; - it simply returns the number of bytes to skip (and stops - libpng skipping that number of bytes on the next - png_process_data call). - 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 is where you turn on interlace handling, - assuming you don't want to do it yourself. - - If you need to you can stop the processing of - your original input data at this point by calling - png_process_data_pause. This returns the number - of unprocessed bytes from the last png_process_data - call - it is up to you to ensure that the next call - sees these bytes again. If you don't want to bother - with this you can get libpng to cache the unread - bytes by setting the 'save' parameter (see png.h) but - then libpng will have to copy the data internally. - */ - } - - /* 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. - - If you did not turn on interlace handling then - the callback is called for each row of each - sub-image when the image is interlaced. In this - case 'row_num' is the row in the sub-image, not - the row in the output image as it is in all other - cases. - - For the non-NULL rows of interlaced images when - you have switched on libpng interlace handling, - 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 if you switch on interlace handling; - */ - - 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. - - You can also call png_process_data_pause in this - callback - see above. - */ - } - - 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_NO_SETJMP, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -You can #define PNG_ABORT() to a function that does something -more useful than abort(), as long as your function does not -return. - -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_structp 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); - -When this function is called the row has already been completely processed and -it has also been written out. The 'row' and 'pass' refer to the next row to be -handled. For the -non-interlaced case the row that was just handled is simply one less than the -passed in row number, and pass will always be 0. For the interlaced case the -same applies unless the row value is 0, in which case the row just handled was -the last one from one of the preceding passes. Because interlacing may skip a -pass you cannot be sure that the preceding pass is just 'pass-1', if you really -need to know what the last pass is record (row,pass) from the callback and use -the last recorded value each time. - -As with the user transform you can find the output row using the -PNG_ROW_FROM_PASS_ROW macro. - -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. - - #include zlib.h - - /* Set the zlib compression level */ - png_set_compression_level(png_ptr, - Z_BEST_COMPRESSION); - - /* Set other zlib parameters for compressing IDAT */ - 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) - - /* Set zlib parameters for text compression - * If you don't call these, the parameters - * fall back on those defined for IDAT chunks - */ - png_set_text_compression_mem_level(png_ptr, 8); - png_set_text_compression_strategy(png_ptr, - Z_DEFAULT_STRATEGY); - png_set_text_compression_window_bits(png_ptr, 15); - png_set_text_compression_method(png_ptr, 8); - -.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, file_gamma); - png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); - - file_gamma - the gamma at which the image was - created (PNG_INFO_gAMA) - - int_file_gamma - 100,000 times the gamma at which - the image was created - - png_set_cHRM(png_ptr, info_ptr, white_x, white_y, red_x, red_y, - green_x, green_y, blue_x, blue_y) - png_set_cHRM_XYZ(png_ptr, info_ptr, red_X, red_Y, red_Z, green_X, - green_Y, green_Z, blue_X, blue_Y, blue_Z) - 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) - png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, int_red_X, int_red_Y, - int_red_Z, int_green_X, int_green_Y, int_green_Z, - int_blue_X, int_blue_Y, int_blue_Z) - - {white,red,green,blue}_{x,y} - A color space encoding specified using the chromaticities - of the end points and the white point. - - {red,green,blue}_{X,Y,Z} - A color space encoding specified using the encoding end - points - the CIE tristimulus specification of the intended - color of the red, green and blue channels in the PNG RGB - data. The white point is simply the sum of the three end - points. - - 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_type - 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_alpha, - num_trans, trans_color); - - trans_alpha - array of alpha (transparency) - entries for palette (PNG_INFO_tRNS) - - num_trans - number of transparent entries - (PNG_INFO_tRNS) - - trans_color - graylevel or color sample values - (in order red, green, blue) of the - single transparent color for - non-paletted images (PNG_INFO_tRNS) - - png_set_hIST(png_ptr, info_ptr, hist); - - hist - histogram of palette (array of - png_uint_16) (PNG_INFO_hIST) - - 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 (of type - png_color_16p) (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. Prior to - libpng-1.4.0 the library was built by default without - iTXt support. Also note that when iTXt is supported, - they contain NULL pointers when the "compression" - field contains PNG_TEXT_COMPRESSION_NONE or - PNG_TEXT_COMPRESSION_zTXt. - - 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 - expressed as a string - - 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 a few hundred 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_structp png_ptr, png_row_infop - 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. If supported -libpng also supplies an information routine that may be called from -your callback: - - png_get_current_row_number(png_ptr); - png_get_current_pass_number(png_ptr); - -This returns the current row passed to the transform. With interlaced -images the value returned is the row in the input sub-image image. Use -PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to -find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). - -The discussion of interlace handling above contains more information on how to -use these values. - -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 the sub-images -(png_set_interlace_handling() returns the number of 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); - -Think carefully before you write an interlaced image. Typically code that -reads such images reads all the image data into memory, uncompressed, before -doing any processing. Only code that can display an image on the fly can -take advantage of the interlacing and even then the image has to be exactly -the correct size for the output device, because scaling an image requires -adjacent pixels and these are not available until all the passes have been -read. - -If you do write an interlaced image you will hardly ever need to handle -the interlacing yourself. Call png_set_interlace_handling() and use the -approach described above. - -The only time it is conceivable that you will really need to write an -interlaced image pass-by-pass is when you have read one pass by pass and -made some pixel-by-pixel transformation to it, as described in the read -code above. In this case use the PNG_PASS_ROWS and PNG_PASS_COLS macros -to determine the size of each sub-image in turn and simply write the rows -you obtained from the read code. - -.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) - - freer - one of - PNG_DESTROY_WILL_FREE_DATA - PNG_SET_WILL_FREE_DATA - PNG_USER_WILL_FREE_DATA - - mask - which data elements are affected - same choices as in png_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 clears the newly -allocated memory to zero. There is limited support for certain systems -with segmented memory architectures and the types of pointers declared by -png.h match this; you will have to use appropriate pointers in your -application. 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_alloc_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_NO_SETJMP, in which case it is handled via PNG_ABORT()), -but you could change this to do things like exit() if you should wish, -as long as your function does not return. - -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), -which is illustrated in pngvalid.c and in contrib/visupng. - -.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 private or unknown chunks in a generic method, -via callback functions, instead of by modifying libpng functions. This -is illustrated in pngtest.c, which uses a callback function to handle a -private "vpAg" chunk and the new "sTER" chunk, which are both unknown to -libpng. - -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 placed in pngpriv.h, -which is only used by the routines inside libpng itself. -The files in libpng proper only include pngpriv.h and png.h, which -%14%in turn includes pngconf.h. -in turn includes pngconf.h and, as of libpng-1.5.0, pnglibconf.h. -As of libpng-1.5.0, pngpriv.h also includes three other private header -files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material -that previously appeared in the public headers. - -.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: - - #include zlib.h - 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. - - #include zlib.h - 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. - - #include zlib.h - 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); - -As of libpng version 1.5.4, additional APIs became -available to set these separately for non-IDAT -compressed chunks such as zTXt, iTXt, and iCCP: - - #include zlib.h - #if PNG_LIBPNG_VER <= 10504 - png_set_text_compression_level(png_ptr, level); - - png_set_text_compression_mem_level(png_ptr, level); - - png_set_text_compression_strategy(png_ptr, - strategy); - - png_set_text_compression_window_bits(png_ptr, - window_bits); - - png_set_text_compression_method(png_ptr, method); - #endif - -.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_. - -In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead. - -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 1.4.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). - -Note that this function does not take a png_ptr, so you can call it -before you've created one. - -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. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x - -Private libpng prototypes and macro definitions were moved from -png.h and pngconf.h into a new pngpriv.h header file. - -Functions png_set_benign_errors(), png_benign_error(), and -png_chunk_benign_error() were added. - -Support for setting the maximum amount of memory that the application -will allocate for reading chunks was added, as a security measure. -The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() -were added to the library. - -We implemented support for I/O states by adding png_ptr member io_state -and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c - -We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level -input transforms. - -Checking for and reporting of errors in the IHDR chunk is more thorough. - -Support for global arrays was removed, to improve thread safety. - -Some obsolete/deprecated macros and functions have been removed. - -Typecasted NULL definitions such as - #define png_voidp_NULL (png_voidp)NULL -were eliminated. If you used these in your application, just use -NULL instead. - -The png_struct and info_struct members "trans" and "trans_values" were -changed to "trans_alpha" and "trans_color", respectively. - -The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles -were removed. - -The PNG_1_0_X and PNG_1_2_X macros were eliminated. - -The PNG_LEGACY_SUPPORTED macro was eliminated. - -Many WIN32_WCE #ifdefs were removed. - -The functions png_read_init(info_ptr), png_write_init(info_ptr), -png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() -have been removed. They have been deprecated since libpng-0.95. - -The png_permit_empty_plte() was removed. It has been deprecated -since libpng-1.0.9. Use png_permit_mng_features() instead. - -We removed the obsolete stub functions 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(), and png_mmx_supported() - -We removed the obsolete png_check_sig(), png_memcpy_check(), and -png_memset_check() functions. Instead use !png_sig_cmp(), memcpy(), -and memset(), respectively. - -The function png_set_gray_1_2_4_to_8() was removed. It has been -deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with -png_set_expand_gray_1_2_4_to_8() because the former function also -expanded any tRNS chunk to an alpha channel. - -Macros for png_get_uint_16, png_get_uint_32, and png_get_int_32 -were added and are used by default instead of the corresponding -functions. Unfortunately, -from libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the -function) incorrectly returned a value of type png_uint_32. - -We changed the prototype for png_malloc() from - png_malloc(png_structp png_ptr, png_uint_32 size) -to - png_malloc(png_structp png_ptr, png_alloc_size_t size) - -This also applies to the prototype for the user replacement malloc_fn(). - -The png_calloc() function was added and is used in place of -of "png_malloc(); memset();" except in the case in png_read_png() -where the array consists of pointers; in this case a "for" loop is used -after the png_malloc() to set the pointers to NULL, to give robust. -behavior in case the application runs out of memory part-way through -the process. - -We changed the prototypes of png_get_compression_buffer_size() and -png_set_compression_buffer_size() to work with png_size_t instead of -png_uint_32. - -Support for numbered error messages was removed by default, since we -never got around to actually numbering the error messages. The function -png_set_strip_error_numbers() was removed from the library by default. - -The png_zalloc() and png_zfree() functions are no longer exported. -The png_zalloc() function no longer zeroes out the memory that it -allocates. - -Support for dithering was disabled by default in libpng-1.4.0, because -it has not been well tested and doesn't actually "dither". -The code was not -removed, however, and could be enabled by building libpng with -PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support -was reenabled, but the function was renamed png_set_quantize() to -reflect more accurately what it actually does. At the same time, -the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to -PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS, and PNG_READ_DITHER_SUPPORTED -was renamed to PNG_READ_QUANTIZE_SUPPORTED. - -We removed the trailing '.' from the warning and error messages. - -.SH X. Changes to Libpng from version 1.4.x to 1.5.x - -From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the -function) incorrectly returned a value of type png_uint_32. - -A. Changes that affect users of libpng - -There are no substantial API changes between the non-deprecated parts of -the 1.4.5 API and the 1.5.0 API, however the ability to directly access -the main libpng control structures, png_struct and png_info, deprecated -in earlier versions of libpng, has been completely removed from -libpng 1.5. - -We no longer include zlib.h in png.h. Applications that need access -to information in zlib.h will need to add the '#include "zlib.h"' -directive. It does not matter whether it is placed prior to or after -the '"#include png.h"' directive. - -We moved the png_strcpy(), png_strncpy(), png_strlen(), png_memcpy(), -png_memcmp(), png_sprintf, and png_memcpy() macros into a private -header file (pngpriv.h) that is not accessible to applications. - -In png_get_iCCP, the type of "profile" was changed from png_charpp -to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep. - -There are changes of form in png.h, including new and changed macros to -declare parts of the API. Some API functions with arguments that are -pointers to data not modified within the function have been corrected to -declare these arguments with PNG_CONST. - -Much of the internal use of C macros to control the library build has also -changed and some of this is visible in the exported header files, in -particular the use of macros to control data and API elements visible -during application compilation may require significant revision to -application code. (It is extremely rare for an application to do this.) - -Any program that compiled against libpng 1.4 and did not use deprecated -features or access internal library structures should compile and work -against libpng 1.5, except for the change in the prototype for -png_get_iCCP() and png_set_iCCP() API functions mentioned above. - -libpng 1.5.0 adds PNG_ PASS macros to help in the reading and writing of -interlaced images. The macros return the number of rows and columns in -each pass and information that can be used to de-interlace and (if -absolutely necessary) interlace an image. - -libpng 1.5.0 adds an API png_longjmp(png_ptr, value). This API calls -the application-provided png_longjmp_ptr on the internal, but application -initialized, longjmp buffer. It is provided as a convenience to avoid -the need to use the png_jmpbuf macro, which had the unnecessary side -effect of resetting the internal png_longjmp_ptr value. - -libpng 1.5.0 includes a complete fixed point API. By default this is -present along with the corresponding floating point API. In general the -fixed point API is faster and smaller than the floating point one because -the PNG file format used fixed point, not floating point. This applies -even if the library uses floating point in internal calculations. A new -macro, PNG_FLOATING_ARITHMETIC_SUPPORTED, reveals whether the library -uses floating point arithmetic (the default) or fixed point arithmetic -internally for performance critical calculations such as gamma correction. -In some cases, the gamma calculations may produce slightly different -results. This has changed the results in png_rgb_to_gray and in alpha -composition (png_set_background for example). This applies even if the -original image was already linear (gamma == 1.0) and, therefore, it is -not necessary to linearize the image. This is because libpng has *not* -been changed to optimize that case correctly, yet. - -Fixed point support for the sCAL chunk comes with an important caveat; -the sCAL specification uses a decimal encoding of floating point values -and the accuracy of PNG fixed point values is insufficient for -representation of these values. Consequently a "string" API -(png_get_sCAL_s and png_set_sCAL_s) is the only reliable way of reading -arbitrary sCAL chunks in the absence of either the floating point API or -internal floating point calculations. - -Applications no longer need to include the optional distribution header -file pngusr.h or define the corresponding macros during application -build in order to see the correct variant of the libpng API. From 1.5.0 -application code can check for the corresponding _SUPPORTED macro: - -#ifdef PNG_INCH_CONVERSIONS_SUPPORTED - /* code that uses the inch conversion APIs. */ -#endif - -This macro will only be defined if the inch conversion functions have been -compiled into libpng. The full set of macros, and whether or not support -has been compiled in, are available in the header file pnglibconf.h. -This header file is specific to the libpng build. Notice that prior to -1.5.0 the _SUPPORTED macros would always have the default definition unless -reset by pngusr.h or by explicit settings on the compiler command line. -These settings may produce compiler warnings or errors in 1.5.0 because -of macro redefinition. - -From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the -function) incorrectly returned a value of type png_uint_32. libpng 1.5.0 -is consistent with the implementation in 1.4.5 and 1.2.x (where the macro -did not exist.) - -Applications can now choose whether to use these macros or to call the -corresponding function by defining PNG_USE_READ_MACROS or -PNG_NO_USE_READ_MACROS before including png.h. Notice that this is -only supported from 1.5.0 -defining PNG_NO_USE_READ_MACROS prior to 1.5.0 -will lead to a link failure. - -Prior to libpng-1.5.4, the zlib compressor used the same set of parameters -when compressing the IDAT data and textual data such as zTXt and iCCP. -In libpng-1.5.4 we reinitialized the zlib stream for each type of data. -We added five png_set_text_*() functions for setting the parameters to -use with textual data. - -Prior to libpng-1.5.4, the PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -option was off by default, and slightly inaccurate scaling occurred. -This option can no longer be turned off, and the choice of accurate -or inaccurate 16-to-8 scaling is by using the new png_set_scale_16_to_8() -API for accurate scaling or the old png_set_strip_16_to_8() API for simple -chopping. - -Prior to libpng-1.5.4, the png_set_user_limits() function could only be -used to reduce the width and height limits from the value of -PNG_USER_WIDTH_MAX and PNG_USER_HEIGHT_MAX, although this document said -that it could be used to override them. Now this function will reduce or -increase the limits. - -B. Changes to the build and configuration of libpng - -Details of internal changes to the library code can be found in the CHANGES -file and in the GIT repository logs. These will be of no concern to the vast -majority of library users or builders, however the few who configure libpng -to a non-default feature set may need to change how this is done. - -There should be no need for library builders to alter build scripts if -these use the distributed build support - configure or the makefiles - -however users of the makefiles may care to update their build scripts -to build pnglibconf.h where the corresponding makefile does not do so. - -Building libpng with a non-default configuration has changed completely. -The old method using pngusr.h should still work correctly even though the -way pngusr.h is used in the build has been changed; however, library -builders will probably want to examine the changes to take advantage of -new capabilities and to simplify their build system. - -B.1 Specific changes to library configuration capabilities - -The library now supports a complete fixed point implementation and can -thus be used on systems that have no floating point support or very -limited or slow support. Previously gamma correction, an essential part -of complete PNG support, required reasonably fast floating point. - -As part of this the choice of internal implementation has been made -independent of the choice of fixed versus floating point APIs and all the -missing fixed point APIs have been implemented. - -The exact mechanism used to control attributes of API functions has -changed. A single set of operating system independent macro definitions -is used and operating system specific directives are defined in -pnglibconf.h - -As part of this the mechanism used to choose procedure call standards on -those systems that allow a choice has been changed. At present this only -affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems -running on Intel processors. As before, PNGAPI is defined where required -to control the exported API functions; however, two new macros, PNGCBAPI -and PNGCAPI, are used instead for callback functions (PNGCBAPI) and -(PNGCAPI) for functions that must match a C library prototype (currently -only png_longjmp_ptr, which must match the C longjmp function.) The new -approach is documented in pngconf.h - -Despite these changes, libpng 1.5.0 only supports the native C function -calling standard on those platforms tested so far (__cdecl on Microsoft -Windows). This is because the support requirements for alternative -calling conventions seem to no longer exist. Developers who find it -necessary to set PNG_API_RULE to 1 should advise the mailing list -(png-mng-implement) of this and library builders who use Openwatcom and -therefore set PNG_API_RULE to 2 should also contact the mailing list. - -A new test program, pngvalid, is provided in addition to pngtest. -pngvalid validates the arithmetic accuracy of the gamma correction -calculations and includes a number of validations of the file format. -A subset of the full range of tests is run when "make check" is done -(in the 'configure' build.) pngvalid also allows total allocated memory -usage to be evaluated and performs additional memory overwrite validation. - -Many changes to individual feature macros have been made. The following -are the changes most likely to be noticed by library builders who -configure libpng: - -1) All feature macros now have consistent naming: - -#define PNG_NO_feature turns the feature off -#define PNG_feature_SUPPORTED turns the feature on - -pnglibconf.h contains one line for each feature macro which is either: - -#define PNG_feature_SUPPORTED - -if the feature is supported or: - -/*#undef PNG_feature_SUPPORTED*/ - -if it is not. Library code consistently checks for the 'SUPPORTED' macro. -It does not, and libpng applications should not, check for the 'NO' macro -which will not normally be defined even if the feature is not supported. -The 'NO' macros are only used internally for setting or not setting the -corresponding 'SUPPORTED' macros. - -Compatibility with the old names is provided as follows: - -PNG_INCH_CONVERSIONS turns on PNG_INCH_CONVERSIONS_SUPPORTED - -And the following definitions disable the corresponding feature: - -PNG_SETJMP_NOT_SUPPORTED disables SETJMP -PNG_READ_TRANSFORMS_NOT_SUPPORTED disables READ_TRANSFORMS -PNG_NO_READ_COMPOSITED_NODIV disables READ_COMPOSITE_NODIV -PNG_WRITE_TRANSFORMS_NOT_SUPPORTED disables WRITE_TRANSFORMS -PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED disables READ_ANCILLARY_CHUNKS -PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED disables WRITE_ANCILLARY_CHUNKS - -Library builders should remove use of the above, inconsistent, names. - -2) Warning and error message formatting was previously conditional on -the STDIO feature. The library has been changed to use the -CONSOLE_IO feature instead. This means that if CONSOLE_IO is disabled -the library no longer uses the printf(3) functions, even though the -default read/write implementations use (FILE) style stdio.h functions. - -3) Three feature macros now control the fixed/floating point decisions: - -PNG_FLOATING_POINT_SUPPORTED enables the floating point APIs - -PNG_FIXED_POINT_SUPPORTED enables the fixed point APIs; however, in -practice these are normally required internally anyway (because the PNG -file format is fixed point), therefore in most cases PNG_NO_FIXED_POINT -merely stops the function from being exported. - -PNG_FLOATING_ARITHMETIC_SUPPORTED chooses between the internal floating -point implementation or the fixed point one. Typically the fixed point -implementation is larger and slower than the floating point implementation -on a system that supports floating point, however it may be faster on a -system which lacks floating point hardware and therefore uses a software -emulation. - -4) Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the -functions to read and write ints to be disabled independently of -PNG_USE_READ_MACROS, which allows libpng to be built with the functions -even though the default is to use the macros - this allows applications -to choose at app buildtime whether or not to use macros (previously -impossible because the functions weren't in the default build.) - -B.2 Changes to the configuration mechanism - -Prior to libpng-1.5.0 library builders who needed to configure libpng -had either to modify the exported pngconf.h header file to add system -specific configuration or had to write feature selection macros into -pngusr.h and cause this to be included into pngconf.h by defining -PNG_USER_CONFIG. The latter mechanism had the disadvantage that an -application built without PNG_USER_CONFIG defined would see the -unmodified, default, libpng API and thus would probably fail to link. - -These mechanisms still work in the configure build and in any makefile -build that builds pnglibconf.h, although the feature selection macros -have changed somewhat as described above. In 1.5.0, however, pngusr.h is -processed only once, when the exported header file pnglibconf.h is built. -pngconf.h no longer includes pngusr.h, therefore pngusr.h is ignored after the -build of pnglibconf.h and it is never included in an application build. - -The rarely used alternative of adding a list of feature macros to the -CFLAGS setting in the build also still works, however the macros will be -copied to pnglibconf.h and this may produce macro redefinition warnings -when the individual C files are compiled. - -All configuration now only works if pnglibconf.h is built from -scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan -(the original author of awk) maintains C source code of that awk and this -and all known later implementations (often called by subtly different -names - nawk and gawk for example) are adequate to build pnglibconf.h. -The Sun Microsystems (now Oracle) program 'awk' is an earlier version -and does not work; this may also apply to other systems that have a -functioning awk called 'nawk'. - -Configuration options are now documented in scripts/pnglibconf.dfa. This -file also includes dependency information that ensures a configuration is -consistent; that is, if a feature is switched off dependent features are -also removed. As a recommended alternative to using feature macros in -pngusr.h a system builder may also define equivalent options in pngusr.dfa -(or, indeed, any file) and add that to the configuration by setting -DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate -how to do this, and a case where pngusr.h is still required. - -.SH XI. 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 XII. 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 - -We also accept patches built from the tar or zip distributions, and -simple verbal discriptions of bug fixes, reported either to the -SourceForge bug tracker, to the png-mng-implement at lists.sf.net -mailing list, or directly to glennrp. - -.SH XIII. 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; - - /* This is a multiple-line - * comment. - */ - statement; - -Very short comments can be placed after 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 programmers. 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 -pngpriv.h -above the comment that says - - /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ - -To avoid polluting the global namespace, the names of all exported -functions and variables begin with "png_", and all publicly visible C -preprocessor macros begin with "PNG_". We request that applications that -use libpng *not* begin any of their own symbols with either of these strings. - -We put a space after each comma and after each semicolon -in "for" statements, and we put spaces before and after each -C binary operator and after "for" or "while", and before -"?". 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 prefer to express integers that are used as bit masks in hex format, -with an even number of lower-case hex digits (e.g., 0x00, 0xff, 0x0100). - -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 XIV. Y2K Compliance in libpng - -February 18, 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.5.9 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 12.so.0.1.0.17rc1 - 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - 1.0.17 10 10017 12.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 12.so.0.1.0.18rc1-5 - 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - 1.0.18 10 10018 12.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-7 13 10210 12.so.0.10[.0] - 1.2.10rc1-2 13 10210 12.so.0.10[.0] - 1.2.10 13 10210 12.so.0.10[.0] - 1.4.0beta1-6 14 10400 14.so.0.0[.0] - 1.2.11beta1-4 13 10210 12.so.0.11[.0] - 1.4.0beta7-8 14 10400 14.so.0.0[.0] - 1.2.11 13 10211 12.so.0.11[.0] - 1.2.12 13 10212 12.so.0.12[.0] - 1.4.0beta9-14 14 10400 14.so.0.0[.0] - 1.2.13 13 10213 12.so.0.13[.0] - 1.4.0beta15-36 14 10400 14.so.0.0[.0] - 1.4.0beta37-87 14 10400 14.so.14.0[.0] - 1.4.0rc01 14 10400 14.so.14.0[.0] - 1.4.0beta88-109 14 10400 14.so.14.0[.0] - 1.4.0rc02-08 14 10400 14.so.14.0[.0] - 1.4.0 14 10400 14.so.14.0[.0] - 1.4.1beta01-03 14 10401 14.so.14.1[.0] - 1.4.1rc01 14 10401 14.so.14.1[.0] - 1.4.1beta04-12 14 10401 14.so.14.1[.0] - 1.4.1 14 10401 14.so.14.1[.0] - 1.4.2 14 10402 14.so.14.2[.0] - 1.4.3 14 10403 14.so.14.3[.0] - 1.4.4 14 10404 14.so.14.4[.0] - 1.5.0beta01-58 15 10500 15.so.15.0[.0] - 1.5.0rc01-07 15 10500 15.so.15.0[.0] - 1.5.0 15 10500 15.so.15.0[.0] - 1.5.1beta01-11 15 10501 15.so.15.1[.0] - 1.5.1rc01-02 15 10501 15.so.15.1[.0] - 1.5.1 15 10501 15.so.15.1[.0] - 1.5.2beta01-03 15 10502 15.so.15.2[.0] - 1.5.2rc01-03 15 10502 15.so.15.2[.0] - 1.5.2 15 10502 15.so.15.2[.0] - 1.5.3beta01-10 15 10503 15.so.15.3[.0] - 1.5.3rc01-02 15 10503 15.so.15.3[.0] - 1.5.3beta11 15 10503 15.so.15.3[.0] - 1.5.3 [omitted] - 1.5.4beta01-08 15 10504 15.so.15.4[.0] - 1.5.4rc01 15 10504 15.so.15.4[.0] - 1.5.4 15 10504 15.so.15.4[.0] - 1.5.5beta01-08 15 10505 15.so.15.5[.0] - 1.5.5rc01 15 10505 15.so.15.5[.0] - 1.5.5 15 10505 15.so.15.5[.0] - 1.5.6beta01-07 15 10506 15.so.15.6[.0] - 1.5.6rc01-03 15 10506 15.so.15.6[.0] - 1.5.6 15 10506 15.so.15.6[.0] - 1.5.7beta01-05 15 10507 15.so.15.7[.0] - 1.5.7rc01-03 15 10507 15.so.15.7[.0] - 1.5.7 15 10507 15.so.15.7[.0] - 1.5.8beta01 15 10508 15.so.15.8[.0] - 1.5.8rc01 15 10508 15.so.15.8[.0] - 1.5.8 15 10508 15.so.15.8[.0] - 1.5.9beta01-02 15 10509 15.so.15.9[.0] - 1.5.9rc01 15 10509 15.so.15.9[.0] - 1.5.9 15 10509 15.so.15.9[.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 "rcN". - -.SH "SEE ALSO" -.BR "png"(5), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(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://ds.internic.net/rfc/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 - - -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.5.9 - February 18, 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.5.9, February 18, 2012, are -Copyright (c) 2004,2006-2007 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 -February 18, 2012 - -.\" end of man page - diff --git a/plugins/FreeImage/Source/LibPNG/libpng.txt b/plugins/FreeImage/Source/LibPNG/libpng.txt deleted file mode 100644 index f1eefbbb37..0000000000 --- a/plugins/FreeImage/Source/LibPNG/libpng.txt +++ /dev/null @@ -1,3352 +0,0 @@ -libpng.txt - A description on how to use and modify libpng - - libpng version 1.4.3 - June 26, 2010 - Updated and distributed by Glenn Randers-Pehrson - - 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.4.3 - June 26, 2010 - 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 -. 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 and as a -W3C Recommendation . - -Some additional chunks are described in the special-purpose public chunks -documents at . - -Other information -about PNG, and the latest version of libpng, can be found at the PNG home -page, . - -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, . -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 - -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_NO_SETJMP, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -You can #define PNG_ABORT() to a function that does something -more useful than abort(), as long as your function does not -return. - -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); - -You can change the zlib compression buffer size to be used while -reading compressed data with - - png_set_compression_buffer_size(png_ptr, buffer_size); - -where the default size is 8192 bytes. Note that the buffer size -is changed immediately and the buffer is reallocated immediately, -instead of setting a flag to be acted upon later. - -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. - -You can also set a limit on the amount of memory that a compressed chunk -other than IDAT can occupy, with - - png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); - -and you can retrieve the limit with - - chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); - -Any chunks that would cause either of these limits to be exceeded will -be ignored. - -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, -quantizing, 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) and -png_get_(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_ 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_alpha, - &num_trans, &trans_color); - trans_alpha - array of alpha (transparency) - entries for palette (PNG_INFO_tRNS) - trans_color - 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.4.3, 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); - -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, -Copyright (c) 1998-01-04 Charles Poynton - - 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_quantize() -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_quantize(png_ptr, palette, num_palette, - max_screen_colors, histogram, 1); - } - else - { - png_color std_color_cube[MAX_SCREEN_COLORS] = - { ... colors ... }; - - png_set_quantize(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_NO_SETJMP, in which case -errors will result in a call to PNG_ABORT() which defaults to abort(). - -You can #define PNG_ABORT() to a function that does something -more useful than abort(), as long as your function does not -return. - -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_alpha, - num_trans, trans_color); - trans_alpha - array of alpha (transparency) - entries for palette (PNG_INFO_tRNS) - trans_color - 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_alloc_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_NO_SETJMP, in which case it is handled via PNG_ABORT()), -but you could change this to do things like exit() if you should wish, -as long as your function does not return. - -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 placed in pngpriv.h, -which is only used by the routines inside libpng itself. -The files in libpng proper only include pngpriv.h and png.h, which -in turn 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. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x - -Private libpng prototypes and macro definitions were moved from -png.h and pngconf.h into a new pngpriv.h header file. - -Functions png_set_benign_errors(), png_benign_error(), and -png_chunk_benign_error() were added. - -Support for setting the maximum amount of memory that the application -will allocate for reading chunks was added, as a security measure. -The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() -were added to the library. - -We implemented support for I/O states by adding png_ptr member io_state -and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c - -We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level -input transforms. - -Checking for and reporting of errors in the IHDR chunk is more thorough. - -Support for global arrays was removed, to improve thread safety. - -Some obsolete/deprecated macros and functions have been removed. - -Typecasted NULL definitions such as - #define png_voidp_NULL (png_voidp)NULL -were eliminated. If you used these in your application, just use -NULL instead. - -The png_struct and info_struct members "trans" and "trans_values" were -changed to "trans_alpha" and "trans_color", respectively. - -The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles -were removed. - -The PNG_1_0_X and PNG_1_2_X macros were eliminated. - -The PNG_LEGACY_SUPPORTED macro was eliminated. - -Many WIN32_WCE #ifdefs were removed. - -The functions png_read_init(info_ptr), png_write_init(info_ptr), -png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() -have been removed. They have been deprecated since libpng-0.95. - -The png_permit_empty_plte() was removed. It has been deprecated -since libpng-1.0.9. Use png_permit_mng_features() instead. - -We removed the obsolete stub functions 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(), and png_mmx_supported() - -We removed the obsolete png_check_sig(), png_memcpy_check(), and -png_memset_check() functions. Instead use !png_sig_cmp(), png_memcpy(), -and png_memset(), respectively. - -The function png_set_gray_1_2_4_to_8() was removed. It has been -deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with -png_set_expand_gray_1_2_4_to_8() because the former function also -expanded palette images. - -We changed the prototype for png_malloc() from - png_malloc(png_structp png_ptr, png_uint_32 size) -to - png_malloc(png_structp png_ptr, png_alloc_size_t size) - -This also applies to the prototype for the user replacement malloc_fn(). - -The png_calloc() function was added and is used in place of -of "png_malloc(); png_memset();" except in the case in png_read_png() -where the array consists of pointers; in this case a "for" loop is used -after the png_malloc() to set the pointers to NULL, to give robust. -behavior in case the application runs out of memory part-way through -the process. - -We changed the prototypes of png_get_compression_buffer_size() and -png_set_compression_buffer_size() to work with png_size_t instead of -png_uint_32. - -Support for numbered error messages was removed by default, since we -never got around to actually numbering the error messages. The function -png_set_strip_error_numbers() was removed from the library by default. - -The png_zalloc() and png_zfree() functions are no longer exported. -The png_zalloc() function no longer zeroes out the memory that it -allocates. - -Support for dithering was disabled by default in libpng-1.4.0, because -been well tested and doesn't actually "dither". The code was not -removed, however, and could be enabled by building libpng with -PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support -was reenabled, but the function was renamed png_set_quantize() to -reflect more accurately what it actually does. At the same time, -the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to -PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS. - -We removed the trailing '.' from the warning and error messages. - -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; - - /* This is a multiple-line - * comment. - */ - statement; - -Very short comments can be placed after 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 -pngpriv.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", and before -"?". 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 - -June 26, 2010 - -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.4.3 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/plugins/FreeImage/Source/LibPNG/libpngpf.3 b/plugins/FreeImage/Source/LibPNG/libpngpf.3 deleted file mode 100644 index ef54f7b5b0..0000000000 --- a/plugins/FreeImage/Source/LibPNG/libpngpf.3 +++ /dev/null @@ -1,28 +0,0 @@ -.TH LIBPNGPF 3 "February 18, 2012" -.SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.5.9 -(private functions) -.SH SYNOPSIS -\fB#include \fI"pngpriv.h" - -\fI\fB - -\fBAs of libpng version \fP\fI1.5.1\fP\fB, this section is no longer \fP\fImaintained\fP\fB, now \fIthat - -\fBthe private function prototypes are hidden in pngpriv.h and not \fIaccessible - -\fBto applications. Look in pngpriv.h for the prototypes and a short \fIdescription - -\fBof each \fIfunction. - -\fI\fB - -.SH DESCRIPTION -The functions previously listed here are used privately by libpng -and are not recommended for use by applications. They are -not "exported" to applications using shared libraries. - -.SH SEE ALSO -.BR "png"(5), " libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) -.SH AUTHOR -Glenn Randers-Pehrson diff --git a/plugins/FreeImage/Source/LibPNG/png.5 b/plugins/FreeImage/Source/LibPNG/png.5 deleted file mode 100644 index 6df917d4ae..0000000000 --- a/plugins/FreeImage/Source/LibPNG/png.5 +++ /dev/null @@ -1,74 +0,0 @@ -.TH PNG 5 "February 18, 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" -.BR "libpng"(3), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) -.LP -PNG specification (second edition), November 2003: -.IP -.br - 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 behavior as strcmp, memcmp, etc). - */ -int PNGAPI -png_sig_cmp(png_const_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))); -} - -#endif /* PNG_READ_SUPPORTED */ - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -/* Function to allocate memory for zlib */ -PNG_FUNCTION(voidpf /* PRIVATE */, -png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) -{ - png_voidp ptr; - png_structp p=(png_structp)png_ptr; - png_uint_32 save_flags=p->flags; - png_alloc_size_t 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_alloc_size_t)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; - - return ((voidpf)ptr); -} - -/* Function to free memory for zlib */ -void /* PRIVATE */ -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) -{ - /* The cast is safe because the crc is a 32 bit value. */ - png_ptr->crc = (png_uint_32)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_const_bytep ptr, png_size_t length) -{ - int need_crc = 1; - - if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name)) - { - 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; - } - - /* 'uLong' is defined as unsigned long, this means that on some systems it is - * a 64 bit value. crc32, however, returns 32 bits so the following cast is - * safe. 'uInt' may be no more than 16 bits, so it is necessary to perform a - * loop here. - */ - if (need_crc && length > 0) - { - uLong crc = png_ptr->crc; /* Should never issue a warning */ - - do - { - uInt safeLength = (uInt)length; - if (safeLength == 0) - safeLength = (uInt)-1; /* evil, but safe */ - - crc = crc32(crc, ptr, safeLength); - - /* The following should never issue compiler warnings, if they do the - * target system has characteristics that will probably violate other - * assumptions within the libpng code. - */ - ptr += safeLength; - length -= safeLength; - } - while (length > 0); - - /* And the following is always safe because the crc is only 32 bits. */ - png_ptr->crc = (png_uint_32)crc; - } -} - -/* Check a user supplied version number, called from both read and write - * functions that create a png_struct - */ -int -png_user_version_check(png_structp png_ptr, png_const_charp user_png_ver) -{ - if (user_png_ver) - { - int 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')) - { -#ifdef PNG_WARNINGS_SUPPORTED - size_t pos = 0; - char m[128]; - - pos = png_safecat(m, sizeof m, pos, "Application built with libpng-"); - pos = png_safecat(m, sizeof m, pos, user_png_ver); - pos = png_safecat(m, sizeof m, pos, " but running with "); - pos = png_safecat(m, sizeof m, pos, png_libpng_ver); - - png_warning(png_ptr, m); -#endif - -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags = 0; -#endif - - return 0; - } - } - - /* Success return. */ - return 1; -} - -/* 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_FUNCTION(png_infop,PNGAPI -png_create_info_struct,(png_structp png_ptr),PNG_ALLOCATED) -{ - 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. - */ - -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)); -} - -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"); -} - -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 */ - if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) - { - 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 */ - if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) - { - png_free(png_ptr, info_ptr->trans_alpha); - info_ptr->trans_alpha = NULL; - info_ptr->valid &= ~PNG_INFO_tRNS; - } -#endif - -#ifdef PNG_sCAL_SUPPORTED - /* Free any sCAL entry */ - if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) - { - 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; - info_ptr->valid &= ~PNG_INFO_sCAL; - } -#endif - -#ifdef PNG_pCAL_SUPPORTED - /* Free any pCAL entry */ - if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) - { - 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 */ - if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) - { - 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 */ - if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) - { - 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; - } - - if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) - { - 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 < 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 */ - if ((mask & PNG_FREE_HIST) & info_ptr->free_me) - { - png_free(png_ptr, info_ptr->hist); - info_ptr->hist = NULL; - info_ptr->valid &= ~PNG_INFO_hIST; - } -#endif - - /* Free any PLTE entry that was internally allocated */ - if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) - { - png_zfree(png_ptr, info_ptr->palette); - info_ptr->palette = NULL; - info_ptr->valid &= ~PNG_INFO_PLTE; - info_ptr->num_palette = 0; - } - -#ifdef PNG_INFO_IMAGE_SUPPORTED - /* Free any image bits attached to the info structure */ - if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) - { - 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 - - if (num != -1) - mask &= ~PNG_FREE_MUL; - - info_ptr->free_me &= ~mask; -} - -/* 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 or otherwise disabled PNG_STDIO_SUPPORTED, 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_const_charp PNGAPI -png_convert_to_rfc1123(png_structp png_ptr, png_const_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 (ptime->year > 9999 /* RFC1123 limitation */ || - ptime->month == 0 || ptime->month > 12 || - ptime->day == 0 || ptime->day > 31 || - ptime->hour > 23 || ptime->minute > 59 || - ptime->second > 60) - { - png_warning(png_ptr, "Ignoring invalid time value"); - return (NULL); - } - - { - size_t pos = 0; - char number_buf[5]; /* enough for a four-digit year */ - -# define APPEND_STRING(string)\ - pos = png_safecat(png_ptr->time_buffer, sizeof png_ptr->time_buffer,\ - pos, (string)) -# define APPEND_NUMBER(format, value)\ - APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value))) -# define APPEND(ch)\ - if (pos < (sizeof png_ptr->time_buffer)-1)\ - png_ptr->time_buffer[pos++] = (ch) - - APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day); - APPEND(' '); - APPEND_STRING(short_months[(ptime->month - 1)]); - APPEND(' '); - APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year); - APPEND(' '); - APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour); - APPEND(':'); - APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute); - APPEND(':'); - APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second); - APPEND_STRING(" +0000"); /* This reliably terminates the buffer */ - -# undef APPEND -# undef APPEND_NUMBER -# undef APPEND_STRING - } - - return png_ptr->time_buffer; -} -# endif /* PNG_TIME_RFC1123_SUPPORTED */ - -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ - -png_const_charp PNGAPI -png_get_copyright(png_const_structp png_ptr) -{ - PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ -#ifdef PNG_STRING_COPYRIGHT - return PNG_STRING_COPYRIGHT -#else -# ifdef __STDC__ - return PNG_STRING_NEWLINE \ - "libpng version 1.5.9 - February 18, 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 "libpng version 1.5.9 - February 18, 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_const_charp PNGAPI -png_get_libpng_ver(png_const_structp png_ptr) -{ - /* Version of *.c files used when building libpng */ - return png_get_header_ver(png_ptr); -} - -png_const_charp PNGAPI -png_get_header_ver(png_const_structp png_ptr) -{ - /* Version of *.h files used when building libpng */ - PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ - return PNG_LIBPNG_VER_STRING; -} - -png_const_charp PNGAPI -png_get_header_version(png_const_structp png_ptr) -{ - /* Returns longer string containing both version and date */ - PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ -#ifdef __STDC__ - return PNG_HEADER_VERSION_STRING -# ifndef PNG_READ_SUPPORTED - " (NO READ SUPPORT)" -# endif - PNG_STRING_NEWLINE; -#else - return PNG_HEADER_VERSION_STRING; -#endif -} - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -int PNGAPI -png_handle_as_unknown(png_structp png_ptr, png_const_bytep chunk_name) -{ - /* Check chunk_name and return "keep" value if it's on the list, else 0 */ - png_const_bytep p, p_end; - - if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list <= 0) - return PNG_HANDLE_CHUNK_AS_DEFAULT; - - p_end = png_ptr->chunk_list; - p = p_end + png_ptr->num_chunk_list*5; /* beyond end */ - - /* The code is the fifth byte after each four byte string. Historically this - * code was always searched from the end of the list, so it should continue - * to do so in case there are duplicated entries. - */ - do /* num_chunk_list > 0, so at least one */ - { - p -= 5; - if (!png_memcmp(chunk_name, p, 4)) - return p[4]; - } - while (p > p_end); - - return PNG_HANDLE_CHUNK_AS_DEFAULT; -} - -int /* PRIVATE */ -png_chunk_unknown_handling(png_structp png_ptr, png_uint_32 chunk_name) -{ - png_byte chunk_string[5]; - - PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name); - return png_handle_as_unknown(png_ptr, chunk_string); -} -#endif - -#ifdef PNG_READ_SUPPORTED -/* 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 /* PNG_READ_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_WRITE_SUPPORTED) -/* png_convert_size: a PNGAPI but no longer in png.h, so deleted - * at libpng 1.5.5! - */ - -/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ -# ifdef PNG_CHECK_cHRM_SUPPORTED - -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; - - /* (x,y,z) values are first limited to 0..100000 (PNG_FP_1), the white - * y must also be greater than 0. To test for the upper limit calculate - * (PNG_FP_1-y) - x must be <= to this for z to be >= 0 (and the expression - * cannot overflow.) At this point we know x and y are >= 0 and (x+y) is - * <= PNG_FP_1. The previous test on PNG_MAX_UINT_31 is removed because it - * pointless (and it produces compiler warnings!) - */ - 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; - } - /* And (x+y) must be <= PNG_FP_1 (so z is >= 0) */ - if (white_x > PNG_FP_1 - white_y) - { - png_warning(png_ptr, "Invalid cHRM white point"); - ret = 0; - } - - if (red_x > PNG_FP_1 - red_y) - { - png_warning(png_ptr, "Invalid cHRM red point"); - ret = 0; - } - - if (green_x > PNG_FP_1 - green_y) - { - png_warning(png_ptr, "Invalid cHRM green point"); - ret = 0; - } - - if (blue_x > PNG_FP_1 - 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 */ - -#ifdef PNG_cHRM_SUPPORTED -/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for - * cHRM, as opposed to using chromaticities. These internal APIs return - * non-zero on a parameter error. The X, Y and Z values are required to be - * positive and less than 1.0. - */ -int png_xy_from_XYZ(png_xy *xy, png_XYZ XYZ) -{ - png_int_32 d, dwhite, whiteX, whiteY; - - d = XYZ.redX + XYZ.redY + XYZ.redZ; - if (!png_muldiv(&xy->redx, XYZ.redX, PNG_FP_1, d)) return 1; - if (!png_muldiv(&xy->redy, XYZ.redY, PNG_FP_1, d)) return 1; - dwhite = d; - whiteX = XYZ.redX; - whiteY = XYZ.redY; - - d = XYZ.greenX + XYZ.greenY + XYZ.greenZ; - if (!png_muldiv(&xy->greenx, XYZ.greenX, PNG_FP_1, d)) return 1; - if (!png_muldiv(&xy->greeny, XYZ.greenY, PNG_FP_1, d)) return 1; - dwhite += d; - whiteX += XYZ.greenX; - whiteY += XYZ.greenY; - - d = XYZ.blueX + XYZ.blueY + XYZ.blueZ; - if (!png_muldiv(&xy->bluex, XYZ.blueX, PNG_FP_1, d)) return 1; - if (!png_muldiv(&xy->bluey, XYZ.blueY, PNG_FP_1, d)) return 1; - dwhite += d; - whiteX += XYZ.blueX; - whiteY += XYZ.blueY; - - /* The reference white is simply the same of the end-point (X,Y,Z) vectors, - * thus: - */ - if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1; - if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1; - - return 0; -} - -int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy) -{ - png_fixed_point red_inverse, green_inverse, blue_scale; - png_fixed_point left, right, denominator; - - /* Check xy and, implicitly, z. Note that wide gamut color spaces typically - * have end points with 0 tristimulus values (these are impossible end - * points, but they are used to cover the possible colors.) - */ - if (xy.redx < 0 || xy.redx > PNG_FP_1) return 1; - if (xy.redy < 0 || xy.redy > PNG_FP_1-xy.redx) return 1; - if (xy.greenx < 0 || xy.greenx > PNG_FP_1) return 1; - if (xy.greeny < 0 || xy.greeny > PNG_FP_1-xy.greenx) return 1; - if (xy.bluex < 0 || xy.bluex > PNG_FP_1) return 1; - if (xy.bluey < 0 || xy.bluey > PNG_FP_1-xy.bluex) return 1; - if (xy.whitex < 0 || xy.whitex > PNG_FP_1) return 1; - if (xy.whitey < 0 || xy.whitey > PNG_FP_1-xy.whitex) return 1; - - /* The reverse calculation is more difficult because the original tristimulus - * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 - * derived values were recorded in the cHRM chunk; - * (red,green,blue,white)x(x,y). This loses one degree of freedom and - * therefore an arbitrary ninth value has to be introduced to undo the - * original transformations. - * - * Think of the original end-points as points in (X,Y,Z) space. The - * chromaticity values (c) have the property: - * - * C - * c = --------- - * X + Y + Z - * - * For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the - * three chromaticity values (x,y,z) for each end-point obey the - * relationship: - * - * x + y + z = 1 - * - * This describes the plane in (X,Y,Z) space that intersects each axis at the - * value 1.0; call this the chromaticity plane. Thus the chromaticity - * calculation has scaled each end-point so that it is on the x+y+z=1 plane - * and chromaticity is the intersection of the vector from the origin to the - * (X,Y,Z) value with the chromaticity plane. - * - * To fully invert the chromaticity calculation we would need the three - * end-point scale factors, (red-scale, green-scale, blue-scale), but these - * were not recorded. Instead we calculated the reference white (X,Y,Z) and - * recorded the chromaticity of this. The reference white (X,Y,Z) would have - * given all three of the scale factors since: - * - * color-C = color-c * color-scale - * white-C = red-C + green-C + blue-C - * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale - * - * But cHRM records only white-x and white-y, so we have lost the white scale - * factor: - * - * white-C = white-c*white-scale - * - * To handle this the inverse transformation makes an arbitrary assumption - * about white-scale: - * - * Assume: white-Y = 1.0 - * Hence: white-scale = 1/white-y - * Or: red-Y + green-Y + blue-Y = 1.0 - * - * Notice the last statement of the assumption gives an equation in three of - * the nine values we want to calculate. 8 more equations come from the - * above routine as summarised at the top above (the chromaticity - * calculation): - * - * Given: color-x = color-X / (color-X + color-Y + color-Z) - * Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0 - * - * This is 9 simultaneous equations in the 9 variables "color-C" and can be - * solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix - * determinants, however this is not as bad as it seems because only 28 of - * the total of 90 terms in the various matrices are non-zero. Nevertheless - * Cramer's rule is notoriously numerically unstable because the determinant - * calculation involves the difference of large, but similar, numbers. It is - * difficult to be sure that the calculation is stable for real world values - * and it is certain that it becomes unstable where the end points are close - * together. - * - * So this code uses the perhaps slighly less optimal but more understandable - * and totally obvious approach of calculating color-scale. - * - * This algorithm depends on the precision in white-scale and that is - * (1/white-y), so we can immediately see that as white-y approaches 0 the - * accuracy inherent in the cHRM chunk drops off substantially. - * - * libpng arithmetic: a simple invertion of the above equations - * ------------------------------------------------------------ - * - * white_scale = 1/white-y - * white-X = white-x * white-scale - * white-Y = 1.0 - * white-Z = (1 - white-x - white-y) * white_scale - * - * white-C = red-C + green-C + blue-C - * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale - * - * This gives us three equations in (red-scale,green-scale,blue-scale) where - * all the coefficients are now known: - * - * red-x*red-scale + green-x*green-scale + blue-x*blue-scale - * = white-x/white-y - * red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1 - * red-z*red-scale + green-z*green-scale + blue-z*blue-scale - * = (1 - white-x - white-y)/white-y - * - * In the last equation color-z is (1 - color-x - color-y) so we can add all - * three equations together to get an alternative third: - * - * red-scale + green-scale + blue-scale = 1/white-y = white-scale - * - * So now we have a Cramer's rule solution where the determinants are just - * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve - * multiplication of three coefficients so we can't guarantee to avoid - * overflow in the libpng fixed point representation. Using Cramer's rule in - * floating point is probably a good choice here, but it's not an option for - * fixed point. Instead proceed to simplify the first two equations by - * eliminating what is likely to be the largest value, blue-scale: - * - * blue-scale = white-scale - red-scale - green-scale - * - * Hence: - * - * (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale = - * (white-x - blue-x)*white-scale - * - * (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale = - * 1 - blue-y*white-scale - * - * And now we can trivially solve for (red-scale,green-scale): - * - * green-scale = - * (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale - * ----------------------------------------------------------- - * green-x - blue-x - * - * red-scale = - * 1 - blue-y*white-scale - (green-y - blue-y) * green-scale - * --------------------------------------------------------- - * red-y - blue-y - * - * Hence: - * - * red-scale = - * ( (green-x - blue-x) * (white-y - blue-y) - - * (green-y - blue-y) * (white-x - blue-x)) / white-y - * ------------------------------------------------------------------------- - * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) - * - * green-scale = - * ( (red-y - blue-y) * (white-x - blue-x) - - * (red-x - blue-x) * (white-y - blue-y)) / white-y - * ------------------------------------------------------------------------- - * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) - * - * Accuracy: - * The input values have 5 decimal digits of accuracy. The values are all in - * the range 0 < value < 1, so simple products are in the same range but may - * need up to 10 decimal digits to preserve the original precision and avoid - * underflow. Because we are using a 32-bit signed representation we cannot - * match this; the best is a little over 9 decimal digits, less than 10. - * - * The approach used here is to preserve the maximum precision within the - * signed representation. Because the red-scale calculation above uses the - * difference between two products of values that must be in the range -1..+1 - * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The - * factor is irrelevant in the calculation because it is applied to both - * numerator and denominator. - * - * Note that the values of the differences of the products of the - * chromaticities in the above equations tend to be small, for example for - * the sRGB chromaticities they are: - * - * red numerator: -0.04751 - * green numerator: -0.08788 - * denominator: -0.2241 (without white-y multiplication) - * - * The resultant Y coefficients from the chromaticities of some widely used - * color space definitions are (to 15 decimal places): - * - * sRGB - * 0.212639005871510 0.715168678767756 0.072192315360734 - * Kodak ProPhoto - * 0.288071128229293 0.711843217810102 0.000085653960605 - * Adobe RGB - * 0.297344975250536 0.627363566255466 0.075291458493998 - * Adobe Wide Gamut RGB - * 0.258728243040113 0.724682314948566 0.016589442011321 - */ - /* By the argument, above overflow should be impossible here. The return - * value of 2 indicates an internal error to the caller. - */ - if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.redy - xy.bluey, 7)) return 2; - if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.redx - xy.bluex, 7)) return 2; - denominator = left - right; - - /* Now find the red numerator. */ - if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2; - if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.whitex-xy.bluex, 7)) return 2; - - /* Overflow is possible here and it indicates an extreme set of PNG cHRM - * chunk values. This calculation actually returns the reciprocal of the - * scale value because this allows us to delay the multiplication of white-y - * into the denominator, which tends to produce a small number. - */ - if (!png_muldiv(&red_inverse, xy.whitey, denominator, left-right) || - red_inverse <= xy.whitey /* r+g+b scales = white scale */) - return 1; - - /* Similarly for green_inverse: */ - if (!png_muldiv(&left, xy.redy-xy.bluey, xy.whitex-xy.bluex, 7)) return 2; - if (!png_muldiv(&right, xy.redx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2; - if (!png_muldiv(&green_inverse, xy.whitey, denominator, left-right) || - green_inverse <= xy.whitey) - return 1; - - /* And the blue scale, the checks above guarantee this can't overflow but it - * can still produce 0 for extreme cHRM values. - */ - blue_scale = png_reciprocal(xy.whitey) - png_reciprocal(red_inverse) - - png_reciprocal(green_inverse); - if (blue_scale <= 0) return 1; - - - /* And fill in the png_XYZ: */ - if (!png_muldiv(&XYZ->redX, xy.redx, PNG_FP_1, red_inverse)) return 1; - if (!png_muldiv(&XYZ->redY, xy.redy, PNG_FP_1, red_inverse)) return 1; - if (!png_muldiv(&XYZ->redZ, PNG_FP_1 - xy.redx - xy.redy, PNG_FP_1, - red_inverse)) - return 1; - - if (!png_muldiv(&XYZ->greenX, xy.greenx, PNG_FP_1, green_inverse)) return 1; - if (!png_muldiv(&XYZ->greenY, xy.greeny, PNG_FP_1, green_inverse)) return 1; - if (!png_muldiv(&XYZ->greenZ, PNG_FP_1 - xy.greenx - xy.greeny, PNG_FP_1, - green_inverse)) - return 1; - - if (!png_muldiv(&XYZ->blueX, xy.bluex, blue_scale, PNG_FP_1)) return 1; - if (!png_muldiv(&XYZ->blueY, xy.bluey, blue_scale, PNG_FP_1)) return 1; - if (!png_muldiv(&XYZ->blueZ, PNG_FP_1 - xy.bluex - xy.bluey, blue_scale, - PNG_FP_1)) - return 1; - - return 0; /*success*/ -} - -int png_XYZ_from_xy_checked(png_structp png_ptr, png_XYZ *XYZ, png_xy xy) -{ - switch (png_XYZ_from_xy(XYZ, xy)) - { - case 0: /* success */ - return 1; - - case 1: - /* The chunk may be technically valid, but we got png_fixed_point - * overflow while trying to get XYZ values out of it. This is - * entirely benign - the cHRM chunk is pretty extreme. - */ - png_warning(png_ptr, - "extreme cHRM chunk cannot be converted to tristimulus values"); - break; - - default: - /* libpng is broken; this should be a warning but if it happens we - * want error reports so for the moment it is an error. - */ - png_error(png_ptr, "internal error in png_XYZ_from_xy"); - break; - } - - /* ERROR RETURN */ - return 0; -} -#endif - -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) - -# 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) -# 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 */ - - 48 /* 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"); -} - -#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) -/* ASCII to fp functions */ -/* Check an ASCII formated floating point value, see the more detailed - * comments in pngpriv.h - */ -/* The following is used internally to preserve the sticky flags */ -#define png_fp_add(state, flags) ((state) |= (flags)) -#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) - -int /* PRIVATE */ -png_check_fp_number(png_const_charp string, png_size_t size, int *statep, - png_size_tp whereami) -{ - int state = *statep; - png_size_t i = *whereami; - - while (i < size) - { - int type; - /* First find the type of the next character */ - switch (string[i]) - { - case 43: type = PNG_FP_SAW_SIGN; break; - case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break; - case 46: type = PNG_FP_SAW_DOT; break; - case 48: type = PNG_FP_SAW_DIGIT; break; - case 49: case 50: case 51: case 52: - case 53: case 54: case 55: case 56: - case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break; - case 69: - case 101: type = PNG_FP_SAW_E; break; - default: goto PNG_FP_End; - } - - /* Now deal with this type according to the current - * state, the type is arranged to not overlap the - * bits of the PNG_FP_STATE. - */ - switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY)) - { - case PNG_FP_INTEGER + PNG_FP_SAW_SIGN: - if (state & PNG_FP_SAW_ANY) - goto PNG_FP_End; /* not a part of the number */ - - png_fp_add(state, type); - break; - - case PNG_FP_INTEGER + PNG_FP_SAW_DOT: - /* Ok as trailer, ok as lead of fraction. */ - if (state & PNG_FP_SAW_DOT) /* two dots */ - goto PNG_FP_End; - - else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */ - png_fp_add(state, type); - - else - png_fp_set(state, PNG_FP_FRACTION | type); - - break; - - case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT: - if (state & PNG_FP_SAW_DOT) /* delayed fraction */ - png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); - - png_fp_add(state, type | PNG_FP_WAS_VALID); - - break; - - case PNG_FP_INTEGER + PNG_FP_SAW_E: - if ((state & PNG_FP_SAW_DIGIT) == 0) - goto PNG_FP_End; - - png_fp_set(state, PNG_FP_EXPONENT); - - break; - - /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: - goto PNG_FP_End; ** no sign in fraction */ - - /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: - goto PNG_FP_End; ** Because SAW_DOT is always set */ - - case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT: - png_fp_add(state, type | PNG_FP_WAS_VALID); - break; - - case PNG_FP_FRACTION + PNG_FP_SAW_E: - /* This is correct because the trailing '.' on an - * integer is handled above - so we can only get here - * with the sequence ".E" (with no preceding digits). - */ - if ((state & PNG_FP_SAW_DIGIT) == 0) - goto PNG_FP_End; - - png_fp_set(state, PNG_FP_EXPONENT); - - break; - - case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN: - if (state & PNG_FP_SAW_ANY) - goto PNG_FP_End; /* not a part of the number */ - - png_fp_add(state, PNG_FP_SAW_SIGN); - - break; - - /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: - goto PNG_FP_End; */ - - case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT: - png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID); - - break; - - /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: - goto PNG_FP_End; */ - - default: goto PNG_FP_End; /* I.e. break 2 */ - } - - /* The character seems ok, continue. */ - ++i; - } - -PNG_FP_End: - /* Here at the end, update the state and return the correct - * return code. - */ - *statep = state; - *whereami = i; - - return (state & PNG_FP_SAW_DIGIT) != 0; -} - - -/* The same but for a complete string. */ -int -png_check_fp_string(png_const_charp string, png_size_t size) -{ - int state=0; - png_size_t char_index=0; - - if (png_check_fp_number(string, size, &state, &char_index) && - (char_index == size || string[char_index] == 0)) - return state /* must be non-zero - see above */; - - return 0; /* i.e. fail */ -} -#endif /* pCAL or sCAL */ - -#ifdef PNG_READ_sCAL_SUPPORTED -# ifdef PNG_FLOATING_POINT_SUPPORTED -/* Utility used below - a simple accurate power of ten from an integral - * exponent. - */ -static double -png_pow10(int power) -{ - int recip = 0; - double d = 1; - - /* Handle negative exponent with a reciprocal at the end because - * 10 is exact whereas .1 is inexact in base 2 - */ - if (power < 0) - { - if (power < DBL_MIN_10_EXP) return 0; - recip = 1, power = -power; - } - - if (power > 0) - { - /* Decompose power bitwise. */ - double mult = 10; - do - { - if (power & 1) d *= mult; - mult *= mult; - power >>= 1; - } - while (power > 0); - - if (recip) d = 1/d; - } - /* else power is 0 and d is 1 */ - - return d; -} - -/* Function to format a floating point value in ASCII with a given - * precision. - */ -void /* PRIVATE */ -png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size, - double fp, unsigned int precision) -{ - /* We use standard functions from math.h, but not printf because - * that would require stdio. The caller must supply a buffer of - * sufficient size or we will png_error. The tests on size and - * the space in ascii[] consumed are indicated below. - */ - if (precision < 1) - precision = DBL_DIG; - - /* Enforce the limit of the implementation precision too. */ - if (precision > DBL_DIG+1) - precision = DBL_DIG+1; - - /* Basic sanity checks */ - if (size >= precision+5) /* See the requirements below. */ - { - if (fp < 0) - { - fp = -fp; - *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */ - --size; - } - - if (fp >= DBL_MIN && fp <= DBL_MAX) - { - int exp_b10; /* A base 10 exponent */ - double base; /* 10^exp_b10 */ - - /* First extract a base 10 exponent of the number, - * the calculation below rounds down when converting - * from base 2 to base 10 (multiply by log10(2) - - * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to - * be increased. Note that the arithmetic shift - * performs a floor() unlike C arithmetic - using a - * C multiply would break the following for negative - * exponents. - */ - (void)frexp(fp, &exp_b10); /* exponent to base 2 */ - - exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ - - /* Avoid underflow here. */ - base = png_pow10(exp_b10); /* May underflow */ - - while (base < DBL_MIN || base < fp) - { - /* And this may overflow. */ - double test = png_pow10(exp_b10+1); - - if (test <= DBL_MAX) - ++exp_b10, base = test; - - else - break; - } - - /* Normalize fp and correct exp_b10, after this fp is in the - * range [.1,1) and exp_b10 is both the exponent and the digit - * *before* which the decimal point should be inserted - * (starting with 0 for the first digit). Note that this - * works even if 10^exp_b10 is out of range because of the - * test on DBL_MAX above. - */ - fp /= base; - while (fp >= 1) fp /= 10, ++exp_b10; - - /* Because of the code above fp may, at this point, be - * less than .1, this is ok because the code below can - * handle the leading zeros this generates, so no attempt - * is made to correct that here. - */ - - { - int czero, clead, cdigits; - char exponent[10]; - - /* Allow up to two leading zeros - this will not lengthen - * the number compared to using E-n. - */ - if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ - { - czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ - exp_b10 = 0; /* Dot added below before first output. */ - } - else - czero = 0; /* No zeros to add */ - - /* Generate the digit list, stripping trailing zeros and - * inserting a '.' before a digit if the exponent is 0. - */ - clead = czero; /* Count of leading zeros */ - cdigits = 0; /* Count of digits in list. */ - - do - { - double d; - - fp *= 10; - /* Use modf here, not floor and subtract, so that - * the separation is done in one step. At the end - * of the loop don't break the number into parts so - * that the final digit is rounded. - */ - if (cdigits+czero-clead+1 < (int)precision) - fp = modf(fp, &d); - - else - { - d = floor(fp + .5); - - if (d > 9) - { - /* Rounding up to 10, handle that here. */ - if (czero > 0) - { - --czero, d = 1; - if (cdigits == 0) --clead; - } - else - { - while (cdigits > 0 && d > 9) - { - int ch = *--ascii; - - if (exp_b10 != (-1)) - ++exp_b10; - - else if (ch == 46) - { - ch = *--ascii, ++size; - /* Advance exp_b10 to '1', so that the - * decimal point happens after the - * previous digit. - */ - exp_b10 = 1; - } - - --cdigits; - d = ch - 47; /* I.e. 1+(ch-48) */ - } - - /* Did we reach the beginning? If so adjust the - * exponent but take into account the leading - * decimal point. - */ - if (d > 9) /* cdigits == 0 */ - { - if (exp_b10 == (-1)) - { - /* Leading decimal point (plus zeros?), if - * we lose the decimal point here it must - * be reentered below. - */ - int ch = *--ascii; - - if (ch == 46) - ++size, exp_b10 = 1; - - /* Else lost a leading zero, so 'exp_b10' is - * still ok at (-1) - */ - } - else - ++exp_b10; - - /* In all cases we output a '1' */ - d = 1; - } - } - } - fp = 0; /* Guarantees termination below. */ - } - - if (d == 0) - { - ++czero; - if (cdigits == 0) ++clead; - } - else - { - /* Included embedded zeros in the digit count. */ - cdigits += czero - clead; - clead = 0; - - while (czero > 0) - { - /* exp_b10 == (-1) means we just output the decimal - * place - after the DP don't adjust 'exp_b10' any - * more! - */ - if (exp_b10 != (-1)) - { - if (exp_b10 == 0) *ascii++ = 46, --size; - /* PLUS 1: TOTAL 4 */ - --exp_b10; - } - *ascii++ = 48, --czero; - } - - if (exp_b10 != (-1)) - { - if (exp_b10 == 0) *ascii++ = 46, --size; /* counted - above */ - --exp_b10; - } - *ascii++ = (char)(48 + (int)d), ++cdigits; - } - } - while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); - - /* The total output count (max) is now 4+precision */ - - /* Check for an exponent, if we don't need one we are - * done and just need to terminate the string. At - * this point exp_b10==(-1) is effectively if flag - it got - * to '-1' because of the decrement after outputing - * the decimal point above (the exponent required is - * *not* -1!) - */ - if (exp_b10 >= (-1) && exp_b10 <= 2) - { - /* The following only happens if we didn't output the - * leading zeros above for negative exponent, so this - * doest add to the digit requirement. Note that the - * two zeros here can only be output if the two leading - * zeros were *not* output, so this doesn't increase - * the output count. - */ - while (--exp_b10 >= 0) *ascii++ = 48; - - *ascii = 0; - - /* Total buffer requirement (including the '\0') is - * 5+precision - see check at the start. - */ - return; - } - - /* Here if an exponent is required, adjust size for - * the digits we output but did not count. The total - * digit output here so far is at most 1+precision - no - * decimal point and no leading or trailing zeros have - * been output. - */ - size -= cdigits; - - *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ - - /* The following use of an unsigned temporary avoids ambiguities in - * the signed arithmetic on exp_b10 and permits GCC at least to do - * better optimization. - */ - { - unsigned int uexp_b10; - - if (exp_b10 < 0) - { - *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ - uexp_b10 = -exp_b10; - } - - else - uexp_b10 = exp_b10; - - cdigits = 0; - - while (uexp_b10 > 0) - { - exponent[cdigits++] = (char)(48 + uexp_b10 % 10); - uexp_b10 /= 10; - } - } - - /* Need another size check here for the exponent digits, so - * this need not be considered above. - */ - if ((int)size > cdigits) - { - while (cdigits > 0) *ascii++ = exponent[--cdigits]; - - *ascii = 0; - - return; - } - } - } - else if (!(fp >= DBL_MIN)) - { - *ascii++ = 48; /* '0' */ - *ascii = 0; - return; - } - else - { - *ascii++ = 105; /* 'i' */ - *ascii++ = 110; /* 'n' */ - *ascii++ = 102; /* 'f' */ - *ascii = 0; - return; - } - } - - /* Here on buffer too small. */ - png_error(png_ptr, "ASCII conversion buffer too small"); -} - -# endif /* FLOATING_POINT */ - -# ifdef PNG_FIXED_POINT_SUPPORTED -/* Function to format a fixed point value in ASCII. - */ -void /* PRIVATE */ -png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size, - png_fixed_point fp) -{ - /* Require space for 10 decimal digits, a decimal point, a minus sign and a - * trailing \0, 13 characters: - */ - if (size > 12) - { - png_uint_32 num; - - /* Avoid overflow here on the minimum integer. */ - if (fp < 0) - *ascii++ = 45, --size, num = -fp; - else - num = fp; - - if (num <= 0x80000000) /* else overflowed */ - { - unsigned int ndigits = 0, first = 16 /* flag value */; - char digits[10]; - - while (num) - { - /* Split the low digit off num: */ - unsigned int tmp = num/10; - num -= tmp*10; - digits[ndigits++] = (char)(48 + num); - /* Record the first non-zero digit, note that this is a number - * starting at 1, it's not actually the array index. - */ - if (first == 16 && num > 0) - first = ndigits; - num = tmp; - } - - if (ndigits > 0) - { - while (ndigits > 5) *ascii++ = digits[--ndigits]; - /* The remaining digits are fractional digits, ndigits is '5' or - * smaller at this point. It is certainly not zero. Check for a - * non-zero fractional digit: - */ - if (first <= 5) - { - unsigned int i; - *ascii++ = 46; /* decimal point */ - /* ndigits may be <5 for small numbers, output leading zeros - * then ndigits digits to first: - */ - i = 5; - while (ndigits < i) *ascii++ = 48, --i; - while (ndigits >= first) *ascii++ = digits[--ndigits]; - /* Don't output the trailing zeros! */ - } - } - else - *ascii++ = 48; - - /* And null terminate the string: */ - *ascii = 0; - return; - } - } - - /* Here on buffer too small. */ - png_error(png_ptr, "ASCII conversion buffer too small"); -} -# endif /* FIXED_POINT */ -#endif /* READ_SCAL */ - -#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ - !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) -png_fixed_point -png_fixed(png_structp png_ptr, double fp, png_const_charp text) -{ - double r = floor(100000 * fp + .5); - - if (r > 2147483647. || r < -2147483648.) - png_fixed_error(png_ptr, text); - - return (png_fixed_point)r; -} -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || \ - defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED) -/* muldiv functions */ -/* This API takes signed arguments and rounds the result to the nearest - * integer (or, for a fixed point number - the standard argument - to - * the nearest .00001). Overflow and divide by zero are signalled in - * the result, a boolean - true on success, false on overflow. - */ -int -png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, - png_int_32 divisor) -{ - /* Return a * times / divisor, rounded. */ - if (divisor != 0) - { - if (a == 0 || times == 0) - { - *res = 0; - return 1; - } - else - { -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = a; - r *= times; - r /= divisor; - r = floor(r+.5); - - /* A png_fixed_point is a 32-bit integer. */ - if (r <= 2147483647. && r >= -2147483648.) - { - *res = (png_fixed_point)r; - return 1; - } -#else - int negative = 0; - png_uint_32 A, T, D; - png_uint_32 s16, s32, s00; - - if (a < 0) - negative = 1, A = -a; - else - A = a; - - if (times < 0) - negative = !negative, T = -times; - else - T = times; - - if (divisor < 0) - negative = !negative, D = -divisor; - else - D = divisor; - - /* Following can't overflow because the arguments only - * have 31 bits each, however the result may be 32 bits. - */ - s16 = (A >> 16) * (T & 0xffff) + - (A & 0xffff) * (T >> 16); - /* Can't overflow because the a*times bit is only 30 - * bits at most. - */ - s32 = (A >> 16) * (T >> 16) + (s16 >> 16); - s00 = (A & 0xffff) * (T & 0xffff); - - s16 = (s16 & 0xffff) << 16; - s00 += s16; - - if (s00 < s16) - ++s32; /* carry */ - - if (s32 < D) /* else overflow */ - { - /* s32.s00 is now the 64-bit product, do a standard - * division, we know that s32 < D, so the maximum - * required shift is 31. - */ - int bitshift = 32; - png_fixed_point result = 0; /* NOTE: signed */ - - while (--bitshift >= 0) - { - png_uint_32 d32, d00; - - if (bitshift > 0) - d32 = D >> (32-bitshift), d00 = D << bitshift; - - else - d32 = 0, d00 = D; - - if (s32 > d32) - { - if (s00 < d00) --s32; /* carry */ - s32 -= d32, s00 -= d00, result += 1<= d00) - s32 = 0, s00 -= d00, result += 1<= (D >> 1)) - ++result; - - if (negative) - result = -result; - - /* Check for overflow. */ - if ((negative && result <= 0) || (!negative && result >= 0)) - { - *res = result; - return 1; - } - } -#endif - } - } - - return 0; -} -#endif /* READ_GAMMA || INCH_CONVERSIONS */ - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) -/* The following is for when the caller doesn't much care about the - * result. - */ -png_fixed_point -png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times, - png_int_32 divisor) -{ - png_fixed_point result; - - if (png_muldiv(&result, a, times, divisor)) - return result; - - png_warning(png_ptr, "fixed point overflow ignored"); - return 0; -} -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */ -/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ -png_fixed_point -png_reciprocal(png_fixed_point a) -{ -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = floor(1E10/a+.5); - - if (r <= 2147483647. && r >= -2147483648.) - return (png_fixed_point)r; -#else - png_fixed_point res; - - if (png_muldiv(&res, 100000, 100000, a)) - return res; -#endif - - return 0; /* error/overflow */ -} - -/* A local convenience routine. */ -static png_fixed_point -png_product2(png_fixed_point a, png_fixed_point b) -{ - /* The required result is 1/a * 1/b; the following preserves accuracy. */ -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = a * 1E-5; - r *= b; - r = floor(r+.5); - - if (r <= 2147483647. && r >= -2147483648.) - return (png_fixed_point)r; -#else - png_fixed_point res; - - if (png_muldiv(&res, a, b, 100000)) - return res; -#endif - - return 0; /* overflow */ -} - -/* The inverse of the above. */ -png_fixed_point -png_reciprocal2(png_fixed_point a, png_fixed_point b) -{ - /* The required result is 1/a * 1/b; the following preserves accuracy. */ -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = 1E15/a; - r /= b; - r = floor(r+.5); - - if (r <= 2147483647. && r >= -2147483648.) - return (png_fixed_point)r; -#else - /* This may overflow because the range of png_fixed_point isn't symmetric, - * but this API is only used for the product of file and screen gamma so it - * doesn't matter that the smallest number it can produce is 1/21474, not - * 1/100000 - */ - png_fixed_point res = png_product2(a, b); - - if (res != 0) - return png_reciprocal(res); -#endif - - return 0; /* overflow */ -} -#endif /* READ_GAMMA */ - -#ifdef PNG_CHECK_cHRM_SUPPORTED -/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2, - * 2010: moved from pngset.c) */ -/* - * 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; -} -#endif /* CHECK_cHRM */ - -#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */ -#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED -/* Fixed point gamma. - * - * To calculate gamma this code implements fast log() and exp() calls using only - * fixed point arithmetic. This code has sufficient precision for either 8-bit - * or 16-bit sample values. - * - * The tables used here were calculated using simple 'bc' programs, but C double - * precision floating point arithmetic would work fine. The programs are given - * at the head of each table. - * - * 8-bit log table - * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to - * 255, so it's the base 2 logarithm of a normalized 8-bit floating point - * mantissa. The numbers are 32-bit fractions. - */ -static png_uint_32 -png_8bit_l2[128] = -{ -# ifdef PNG_DO_BC - for (i=128;i<256;++i) { .5 - l(i/255)/l(2)*65536*65536; } -# else - 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U, - 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U, - 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U, - 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U, - 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U, - 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U, - 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U, - 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U, - 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U, - 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U, - 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U, - 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U, - 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U, - 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U, - 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U, - 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U, - 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U, - 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U, - 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U, - 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U, - 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U, - 24347096U, 0U -# endif - -#if 0 - /* The following are the values for 16-bit tables - these work fine for the - * 8-bit conversions but produce very slightly larger errors in the 16-bit - * log (about 1.2 as opposed to 0.7 absolute error in the final value). To - * use these all the shifts below must be adjusted appropriately. - */ - 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, - 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, - 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068, - 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782, - 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887, - 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339, - 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098, - 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132, - 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415, - 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523, - 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495, - 1119, 744, 372 -#endif -}; - -PNG_STATIC png_int_32 -png_log8bit(unsigned int x) -{ - unsigned int lg2 = 0; - /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log, - * because the log is actually negate that means adding 1. The final - * returned value thus has the range 0 (for 255 input) to 7.994 (for 1 - * input), return 7.99998 for the overflow (log 0) case - so the result is - * always at most 19 bits. - */ - if ((x &= 0xff) == 0) - return 0xffffffff; - - if ((x & 0xf0) == 0) - lg2 = 4, x <<= 4; - - if ((x & 0xc0) == 0) - lg2 += 2, x <<= 2; - - if ((x & 0x80) == 0) - lg2 += 1, x <<= 1; - - /* result is at most 19 bits, so this cast is safe: */ - return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16)); -} - -/* The above gives exact (to 16 binary places) log2 values for 8-bit images, - * for 16-bit images we use the most significant 8 bits of the 16-bit value to - * get an approximation then multiply the approximation by a correction factor - * determined by the remaining up to 8 bits. This requires an additional step - * in the 16-bit case. - * - * We want log2(value/65535), we have log2(v'/255), where: - * - * value = v' * 256 + v'' - * = v' * f - * - * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128 - * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less - * than 258. The final factor also needs to correct for the fact that our 8-bit - * value is scaled by 255, whereas the 16-bit values must be scaled by 65535. - * - * This gives a final formula using a calculated value 'x' which is value/v' and - * scaling by 65536 to match the above table: - * - * log2(x/257) * 65536 - * - * Since these numbers are so close to '1' we can use simple linear - * interpolation between the two end values 256/257 (result -368.61) and 258/257 - * (result 367.179). The values used below are scaled by a further 64 to give - * 16-bit precision in the interpolation: - * - * Start (256): -23591 - * Zero (257): 0 - * End (258): 23499 - */ -PNG_STATIC png_int_32 -png_log16bit(png_uint_32 x) -{ - unsigned int lg2 = 0; - - /* As above, but now the input has 16 bits. */ - if ((x &= 0xffff) == 0) - return 0xffffffff; - - if ((x & 0xff00) == 0) - lg2 = 8, x <<= 8; - - if ((x & 0xf000) == 0) - lg2 += 4, x <<= 4; - - if ((x & 0xc000) == 0) - lg2 += 2, x <<= 2; - - if ((x & 0x8000) == 0) - lg2 += 1, x <<= 1; - - /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional - * value. - */ - lg2 <<= 28; - lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4; - - /* Now we need to interpolate the factor, this requires a division by the top - * 8 bits. Do this with maximum precision. - */ - x = ((x << 16) + (x >> 9)) / (x >> 8); - - /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24, - * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly - * 16 bits to interpolate to get the low bits of the result. Round the - * answer. Note that the end point values are scaled by 64 to retain overall - * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust - * the overall scaling by 6-12. Round at every step. - */ - x -= 1U << 24; - - if (x <= 65536U) /* <= '257' */ - lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12); - - else - lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12); - - /* Safe, because the result can't have more than 20 bits: */ - return (png_int_32)((lg2 + 2048) >> 12); -} - -/* The 'exp()' case must invert the above, taking a 20-bit fixed point - * logarithmic value and returning a 16 or 8-bit number as appropriate. In - * each case only the low 16 bits are relevant - the fraction - since the - * integer bits (the top 4) simply determine a shift. - * - * The worst case is the 16-bit distinction between 65535 and 65534, this - * requires perhaps spurious accuracy in the decoding of the logarithm to - * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance - * of getting this accuracy in practice. - * - * To deal with this the following exp() function works out the exponent of the - * frational part of the logarithm by using an accurate 32-bit value from the - * top four fractional bits then multiplying in the remaining bits. - */ -static png_uint_32 -png_32bit_exp[16] = -{ -# ifdef PNG_DO_BC - for (i=0;i<16;++i) { .5 + e(-i/16*l(2))*2^32; } -# else - /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */ - 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, - 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, - 2553802834U, 2445529972U, 2341847524U, 2242560872U -# endif -}; - -/* Adjustment table; provided to explain the numbers in the code below. */ -#ifdef PNG_DO_BC -for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} - 11 44937.64284865548751208448 - 10 45180.98734845585101160448 - 9 45303.31936980687359311872 - 8 45364.65110595323018870784 - 7 45395.35850361789624614912 - 6 45410.72259715102037508096 - 5 45418.40724413220722311168 - 4 45422.25021786898173001728 - 3 45424.17186732298419044352 - 2 45425.13273269940811464704 - 1 45425.61317555035558641664 - 0 45425.85339951654943850496 -#endif - -PNG_STATIC png_uint_32 -png_exp(png_fixed_point x) -{ - if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ - { - /* Obtain a 4-bit approximation */ - png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; - - /* Incorporate the low 12 bits - these decrease the returned value by - * multiplying by a number less than 1 if the bit is set. The multiplier - * is determined by the above table and the shift. Notice that the values - * converge on 45426 and this is used to allow linear interpolation of the - * low bits. - */ - if (x & 0x800) - e -= (((e >> 16) * 44938U) + 16U) >> 5; - - if (x & 0x400) - e -= (((e >> 16) * 45181U) + 32U) >> 6; - - if (x & 0x200) - e -= (((e >> 16) * 45303U) + 64U) >> 7; - - if (x & 0x100) - e -= (((e >> 16) * 45365U) + 128U) >> 8; - - if (x & 0x080) - e -= (((e >> 16) * 45395U) + 256U) >> 9; - - if (x & 0x040) - e -= (((e >> 16) * 45410U) + 512U) >> 10; - - /* And handle the low 6 bits in a single block. */ - e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9; - - /* Handle the upper bits of x. */ - e >>= x >> 16; - return e; - } - - /* Check for overflow */ - if (x <= 0) - return png_32bit_exp[0]; - - /* Else underflow */ - return 0; -} - -PNG_STATIC png_byte -png_exp8bit(png_fixed_point lg2) -{ - /* Get a 32-bit value: */ - png_uint_32 x = png_exp(lg2); - - /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the - * second, rounding, step can't overflow because of the first, subtraction, - * step. - */ - x -= x >> 8; - return (png_byte)((x + 0x7fffffU) >> 24); -} - -PNG_STATIC png_uint_16 -png_exp16bit(png_fixed_point lg2) -{ - /* Get a 32-bit value: */ - png_uint_32 x = png_exp(lg2); - - /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */ - x -= x >> 16; - return (png_uint_16)((x + 32767U) >> 16); -} -#endif /* FLOATING_ARITHMETIC */ - -png_byte -png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) -{ - if (value > 0 && value < 255) - { -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = floor(255*pow(value/255.,gamma_val*.00001)+.5); - return (png_byte)r; -# else - png_int_32 lg2 = png_log8bit(value); - png_fixed_point res; - - if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) - return png_exp8bit(res); - - /* Overflow. */ - value = 0; -# endif - } - - return (png_byte)value; -} - -png_uint_16 -png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) -{ - if (value > 0 && value < 65535) - { -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5); - return (png_uint_16)r; -# else - png_int_32 lg2 = png_log16bit(value); - png_fixed_point res; - - if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) - return png_exp16bit(res); - - /* Overflow. */ - value = 0; -# endif - } - - return (png_uint_16)value; -} - -/* This does the right thing based on the bit_depth field of the - * png_struct, interpreting values as 8-bit or 16-bit. While the result - * is nominally a 16-bit value if bit depth is 8 then the result is - * 8-bit (as are the arguments.) - */ -png_uint_16 /* PRIVATE */ -png_gamma_correct(png_structp png_ptr, unsigned int value, - png_fixed_point gamma_val) -{ - if (png_ptr->bit_depth == 8) - return png_gamma_8bit_correct(value, gamma_val); - - else - return png_gamma_16bit_correct(value, gamma_val); -} - -/* This is the shared test on whether a gamma value is 'significant' - whether - * it is worth doing gamma correction. - */ -int /* PRIVATE */ -png_gamma_significant(png_fixed_point gamma_val) -{ - return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || - gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; -} - -/* Internal function to build a single 16-bit table - the table consists of - * 'num' 256-entry subtables, where 'num' is determined by 'shift' - the amount - * to shift the input values right (or 16-number_of_signifiant_bits). - * - * The caller is responsible for ensuring that the table gets cleaned up on - * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument - * should be somewhere that will be cleaned. - */ -static void -png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) -{ - /* Various values derived from 'shift': */ - PNG_CONST unsigned int num = 1U << (8U - shift); - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; - PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); - unsigned int i; - - png_uint_16pp table = *ptable = - (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); - - for (i = 0; i < num; i++) - { - png_uint_16p sub_table = table[i] = - (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16)); - - /* The 'threshold' test is repeated here because it can arise for one of - * the 16-bit tables even if the others don't hit it. - */ - if (png_gamma_significant(gamma_val)) - { - /* The old code would overflow at the end and this would cause the - * 'pow' function to return a result >1, resulting in an - * arithmetic error. This code follows the spec exactly; ig is - * the recovered input sample, it always has 8-16 bits. - * - * We want input * 65535/max, rounded, the arithmetic fits in 32 - * bits (unsigned) so long as max <= 32767. - */ - unsigned int j; - for (j = 0; j < 256; j++) - { - png_uint_32 ig = (j << (8-shift)) + i; -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED - /* Inline the 'max' scaling operation: */ - double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5); - sub_table[j] = (png_uint_16)d; -# else - if (shift) - ig = (ig * 65535U + max_by_2)/max; - - sub_table[j] = png_gamma_16bit_correct(ig, gamma_val); -# endif - } - } - else - { - /* We must still build a table, but do it the fast way. */ - unsigned int j; - - for (j = 0; j < 256; j++) - { - png_uint_32 ig = (j << (8-shift)) + i; - - if (shift) - ig = (ig * 65535U + max_by_2)/max; - - sub_table[j] = (png_uint_16)ig; - } - } - } -} - -/* NOTE: this function expects the *inverse* of the overall gamma transformation - * required. - */ -static void -png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) -{ - PNG_CONST unsigned int num = 1U << (8U - shift); - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; - unsigned int i; - png_uint_32 last; - - png_uint_16pp table = *ptable = - (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); - - /* 'num' is the number of tables and also the number of low bits of the - * input 16-bit value used to select a table. Each table is itself indexed - * by the high 8 bits of the value. - */ - for (i = 0; i < num; i++) - table[i] = (png_uint_16p)png_malloc(png_ptr, - 256 * png_sizeof(png_uint_16)); - - /* 'gamma_val' is set to the reciprocal of the value calculated above, so - * pow(out,g) is an *input* value. 'last' is the last input value set. - * - * In the loop 'i' is used to find output values. Since the output is - * 8-bit there are only 256 possible values. The tables are set up to - * select the closest possible output value for each input by finding - * the input value at the boundary between each pair of output values - * and filling the table up to that boundary with the lower output - * value. - * - * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit - * values the code below uses a 16-bit value in i; the values start at - * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last - * entries are filled with 255). Start i at 128 and fill all 'last' - * table entries <= 'max' - */ - last = 0; - for (i = 0; i < 255; ++i) /* 8-bit output value */ - { - /* Find the corresponding maximum input value */ - png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */ - - /* Find the boundary value in 16 bits: */ - png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val); - - /* Adjust (round) to (16-shift) bits: */ - bound = (bound * max + 32768U)/65535U + 1U; - - while (last < bound) - { - table[last & (0xffU >> shift)][last >> (8U - shift)] = out; - last++; - } - } - - /* And fill in the final entries. */ - while (last < (num << 8)) - { - table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U; - last++; - } -} - -/* Build a single 8-bit table: same as the 16-bit case but much simpler (and - * typically much faster). Note that libpng currently does no sBIT processing - * (apparently contrary to the spec) so a 256-entry table is always generated. - */ -static void -png_build_8bit_table(png_structp png_ptr, png_bytepp ptable, - PNG_CONST png_fixed_point gamma_val) -{ - unsigned int i; - png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); - - if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++) - table[i] = png_gamma_8bit_correct(i, gamma_val); - - else for (i=0; i<256; ++i) - table[i] = (png_byte)i; -} - -/* Used from png_read_destroy and below to release the memory used by the gamma - * tables. - */ -void /* PRIVATE */ -png_destroy_gamma_table(png_structp png_ptr) -{ - png_free(png_ptr, png_ptr->gamma_table); - png_ptr->gamma_table = NULL; - - 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); - png_ptr->gamma_16_table = NULL; - } - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_free(png_ptr, png_ptr->gamma_from_1); - png_ptr->gamma_from_1 = NULL; - png_free(png_ptr, png_ptr->gamma_to_1); - png_ptr->gamma_to_1 = NULL; - - 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); - png_ptr->gamma_16_from_1 = NULL; - } - 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); - png_ptr->gamma_16_to_1 = NULL; - } -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ -} - -/* 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. - */ -void /* PRIVATE */ -png_build_gamma_table(png_structp png_ptr, int bit_depth) -{ - png_debug(1, "in png_build_gamma_table"); - - /* Remove any existing table; this copes with multiple calls to - * png_read_update_info. The warning is because building the gamma tables - * multiple times is a performance hit - it's harmless but the ability to call - * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible - * to warn if the app introduces such a hit. - */ - if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) - { - png_warning(png_ptr, "gamma table being rebuilt"); - png_destroy_gamma_table(png_ptr); - } - - if (bit_depth <= 8) - { - png_build_8bit_table(png_ptr, &png_ptr->gamma_table, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, - png_ptr->screen_gamma) : PNG_FP_1); - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) - { - png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, - png_reciprocal(png_ptr->gamma)); - - png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->gamma/* Probably doing rgb_to_gray */); - } -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ - } - else - { - png_byte shift, sig_bit; - - if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) - { - sig_bit = png_ptr->sig_bit.red; - - if (png_ptr->sig_bit.green > sig_bit) - sig_bit = png_ptr->sig_bit.green; - - if (png_ptr->sig_bit.blue > sig_bit) - sig_bit = png_ptr->sig_bit.blue; - } - else - sig_bit = png_ptr->sig_bit.gray; - - /* 16-bit gamma code uses this equation: - * - * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] - * - * Where 'iv' is the input color value and 'ov' is the output value - - * pow(iv, gamma). - * - * Thus the gamma table consists of up to 256 256-entry tables. The table - * is selected by the (8-gamma_shift) most significant of the low 8 bits of - * the color value then indexed by the upper 8 bits: - * - * table[low bits][high 8 bits] - * - * So the table 'n' corresponds to all those 'iv' of: - * - * ..<(n+1 << gamma_shift)-1> - * - */ - if (sig_bit > 0 && sig_bit < 16U) - shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */ - - else - shift = 0; /* keep all 16 bits */ - - if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) - { - /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively - * the significant bits in the *input* when the output will - * eventually be 8 bits. By default it is 11. - */ - if (shift < (16U - PNG_MAX_GAMMA_8)) - shift = (16U - PNG_MAX_GAMMA_8); - } - - if (shift > 8U) - shift = 8U; /* Guarantees at least one table! */ - - png_ptr->gamma_shift = shift; - -#ifdef PNG_16BIT_SUPPORTED - /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now - * PNG_COMPOSE). This effectively smashed the background calculation for - * 16-bit output because the 8-bit table assumes the result will be reduced - * to 8 bits. - */ - if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) -#endif - png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma, - png_ptr->screen_gamma) : PNG_FP_1); - -#ifdef PNG_16BIT_SUPPORTED - else - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, - png_ptr->screen_gamma) : PNG_FP_1); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) - { - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, - png_reciprocal(png_ptr->gamma)); - - /* Notice that the '16 from 1' table should be full precision, however - * the lookup on this table still uses gamma_shift, so it can't be. - * TODO: fix this. - */ - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->gamma/* Probably doing rgb_to_gray */); - } -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ - } -} -#endif /* READ_GAMMA */ -#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/plugins/FreeImage/Source/LibPNG/png.h b/plugins/FreeImage/Source/LibPNG/png.h deleted file mode 100644 index 81267675a5..0000000000 --- a/plugins/FreeImage/Source/LibPNG/png.h +++ /dev/null @@ -1,2658 +0,0 @@ - -/* png.h - header file for PNG reference library - * - * libpng version 1.5.9 - February 18, 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.5.9 - February 18, 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 12.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 12.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 12.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 12.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-7 13 10210 12.so.0.10[.0] - * 1.2.10rc1-2 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.4.0beta1-5 14 10400 14.so.0.0[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.4.0beta7-8 14 10400 14.so.0.0[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.4.0beta9-14 14 10400 14.so.0.0[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.4.0beta15-36 14 10400 14.so.0.0[.0] - * 1.4.0beta37-87 14 10400 14.so.14.0[.0] - * 1.4.0rc01 14 10400 14.so.14.0[.0] - * 1.4.0beta88-109 14 10400 14.so.14.0[.0] - * 1.4.0rc02-08 14 10400 14.so.14.0[.0] - * 1.4.0 14 10400 14.so.14.0[.0] - * 1.4.1beta01-03 14 10401 14.so.14.1[.0] - * 1.4.1rc01 14 10401 14.so.14.1[.0] - * 1.4.1beta04-12 14 10401 14.so.14.1[.0] - * 1.4.1 14 10401 14.so.14.1[.0] - * 1.4.2 14 10402 14.so.14.2[.0] - * 1.4.3 14 10403 14.so.14.3[.0] - * 1.4.4 14 10404 14.so.14.4[.0] - * 1.5.0beta01-58 15 10500 15.so.15.0[.0] - * 1.5.0rc01-07 15 10500 15.so.15.0[.0] - * 1.5.0 15 10500 15.so.15.0[.0] - * 1.5.1beta01-11 15 10501 15.so.15.1[.0] - * 1.5.1rc01-02 15 10501 15.so.15.1[.0] - * 1.5.1 15 10501 15.so.15.1[.0] - * 1.5.2beta01-03 15 10502 15.so.15.2[.0] - * 1.5.2rc01-03 15 10502 15.so.15.2[.0] - * 1.5.2 15 10502 15.so.15.2[.0] - * 1.5.3beta01-10 15 10503 15.so.15.3[.0] - * 1.5.3rc01-02 15 10503 15.so.15.3[.0] - * 1.5.3beta11 15 10503 15.so.15.3[.0] - * 1.5.3 [omitted] - * 1.5.4beta01-08 15 10504 15.so.15.4[.0] - * 1.5.4rc01 15 10504 15.so.15.4[.0] - * 1.5.4 15 10504 15.so.15.4[.0] - * 1.5.5beta01-08 15 10505 15.so.15.5[.0] - * 1.5.5rc01 15 10505 15.so.15.5[.0] - * 1.5.5 15 10505 15.so.15.5[.0] - * 1.5.6beta01-07 15 10506 15.so.15.6[.0] - * 1.5.6rc01-03 15 10506 15.so.15.6[.0] - * 1.5.6 15 10506 15.so.15.6[.0] - * 1.5.7beta01-05 15 10507 15.so.15.7[.0] - * 1.5.7rc01-03 15 10507 15.so.15.7[.0] - * 1.5.7 15 10507 15.so.15.7[.0] - * 1.5.8beta01 15 10508 15.so.15.8[.0] - * 1.5.8rc01 15 10508 15.so.15.8[.0] - * 1.5.8 15 10508 15.so.15.8[.0] - * 1.5.9beta01-02 15 10509 15.so.15.9[.0] - * 1.5.9rc01 15 10509 15.so.15.9[.0] - * 1.5.9 15 10509 15.so.15.9[.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 "rcN". - * - * 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-manual.txt or libpng.3 for more information. The PNG - * specification is available as a W3C Recommendation and as an ISO - * Specification, -# endif - - /* Need the time information for converting tIME chunks, it - * defines struct tm: - */ -# ifdef PNG_CONVERT_tIME_SUPPORTED - /* "time.h" functions are not supported on all operating systems */ -# include -# endif -# endif - -/* Machine specific configuration. */ -# include "pngconf.h" -#endif - -/* - * 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 /* From pnglibconf.h */ -# 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 */ - -/* Version information for C files, stored in png.c. This had better match - * the version above. - */ -#define png_libpng_ver png_get_header_ver(NULL) - -/* This file is arranged in several sections: - * - * 1. Any configuration options that can be specified by for the application - * code when it is built. (Build time configuration is in pnglibconf.h) - * 2. Type definitions (base types are defined in pngconf.h), structure - * definitions. - * 3. Exported library functions. - * - * The library source code has additional files (principally pngpriv.h) that - * allow configuration of the library. - */ -/* Section 1: run time configuration - * See pnglibconf.h for build time configuration - * - * Run time configuration allows the application to choose between - * implementations of certain arithmetic APIs. The default is set - * at build time and recorded in pnglibconf.h, but it is safe to - * override these (and only these) settings. Note that this won't - * change what the library does, only application code, and the - * settings can (and probably should) be made on a per-file basis - * by setting the #defines before including png.h - * - * Use macros to read integers from PNG data or use the exported - * functions? - * PNG_USE_READ_MACROS: use the macros (see below) Note that - * the macros evaluate their argument multiple times. - * PNG_NO_USE_READ_MACROS: call the relevant library function. - * - * Use the alternative algorithm for compositing alpha samples that - * does not use division? - * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' - * algorithm. - * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. - * - * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is - * false? - * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error - * APIs to png_warning. - * Otherwise the calls are mapped to png_error. - */ - -/* Section 2: type definitions, including structures and compile time - * constants. - * See pngconf.h for base types that vary by machine/system - */ - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef char* png_libpng_version_1_5_9; - -/* 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_CONST png_color FAR * png_const_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_CONST png_color_16 FAR * png_const_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_CONST png_color_8 FAR * png_const_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_CONST png_sPLT_entry FAR * png_const_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_CONST png_sPLT_t FAR * png_const_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" fields can be a - * regular C string, an empty string, or a NULL pointer. - * However, the structure returned by png_get_text() will always contain - * the "text" field as a regular zero-terminated C string (possibly - * empty), never a NULL pointer, so it can be safely used in printf() and - * other string-handling functions. Note that the "itxt_length", "lang", and - * "lang_key" members of the structure only exist when the library is built - * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by - * default without iTXt support. Also note that when iTXt *is* supported, - * the "lang" and "lang_key" fields contain NULL pointers when the - * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or - * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the - * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" - * which is always 0 or 1, or its "compression method" which is always 0. - */ -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 */ - 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 */ -} png_text; -typedef png_text FAR * png_textp; -typedef PNG_CONST png_text FAR * png_const_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_CONST png_time FAR * png_const_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. - */ -typedef struct png_unknown_chunk_t -{ - png_byte name[5]; - 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_CONST png_unknown_chunk FAR * png_const_unknown_chunkp; -typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; -#endif - -/* Values for the unknown chunk location byte */ - -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_AFTER_IDAT 0x08 - -/* The complete definition of png_info has, as of libpng-1.5.0, - * been moved into a separate header file that is not accessible to - * applications. Read libpng-manual.txt or libpng.3 for more info. - */ -typedef struct png_info_def png_info; -typedef png_info FAR * png_infop; -typedef PNG_CONST png_info FAR * png_const_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)) - -/* These are constants for fixed point values encoded in the - * PNG specification manner (x100000) - */ -#define PNG_FP_1 100000 -#define PNG_FP_HALF 50000 -#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) -#define PNG_FP_MIN (-PNG_FP_MAX) - -/* 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_ 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 0x8000 /* 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_size_t 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; - -/* The complete definition of png_struct has, as of libpng-1.5.0, - * been moved into a separate header file that is not accessible to - * applications. Read libpng-manual.txt or libpng.3 for more info. - */ -typedef struct png_struct_def png_struct; -typedef PNG_CONST png_struct FAR * png_const_structp; -typedef png_struct FAR * png_structp; - -/* 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. Note that the 'write' function must not - * modify the buffer it is passed. The 'read' function, on the other hand, is - * expected to return the read data in the buffer. - */ -typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); -typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); -typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, - int)); -typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); -typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); - -/* The following callback receives png_uint_32 row_number, int pass for the - * png_bytep data of the row. When transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, - png_bytep)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, - png_unknown_chunkp)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This must match the function definition in , and the application - * must include this before png.h to obtain the definition of jmp_buf. The - * function is required to be PNG_NORETURN, but this is not checked. If the - * function does return the application will crash via an abort() or similar - * system level call. - * - * If you get a warning here while building the library you may need to make - * changes to ensure that pnglibconf.h records the calling convention used by - * your compiler. This may be very difficult - try using a different compiler - * to build the library! - */ -PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); -#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 */ -/* Added to libpng-1.2.34 */ -#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER -#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ -/* Added to libpng-1.4.0 */ -#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ -/* Added to libpng-1.5.4 */ -#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ -#define PNG_TRANSFORM_SCALE_16 0x8000 /* 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 - -/* NOTE: prior to 1.5 these functions had no 'API' style declaration, - * this allowed the zlib default functions to be used on Windows - * platforms. In 1.5 the zlib default malloc (which just calls malloc and - * ignores the first argument) should be completely compatible with the - * following. - */ -typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, - png_alloc_size_t)); -typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); - -typedef png_struct FAR * FAR * png_structpp; - -/* Section 3: exported functions - * Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng-manual.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. - * - * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in - * pngconf.h and in the *.dfn files in the scripts directory. - * - * PNG_EXPORT(ordinal, type, name, (args)); - * - * ordinal: ordinal that is used while building - * *.def files. The ordinal value is only - * relevant when preprocessing png.h with - * the *.dfn files for building symbol table - * entries, and are removed by pngconf.h. - * type: return type of the function - * name: function name - * args: function arguments, with types - * - * When we wish to append attributes to a function prototype we use - * the PNG_EXPORTA() macro instead. - * - * PNG_EXPORTA(ordinal, type, name, (args), attributes); - * - * ordinal, type, name, and args: same as in PNG_EXPORT(). - * attributes: function attributes - */ - -/* Returns the version number of the library */ -PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -PNG_EXPORT(2, void, png_set_sig_bytes, (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). - */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_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). - */ -#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -PNG_EXPORTA(4, png_structp, png_create_read_struct, - (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 */ -PNG_EXPORTA(5, png_structp, png_create_write_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn), - PNG_ALLOCATED); - -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, - (png_const_structp png_ptr)); - -PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, - png_size_t size)); - -/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp - * match up. - */ -#ifdef PNG_SETJMP_SUPPORTED -/* This function returns the jmp_buf built in to *png_ptr. It must be - * supplied with an appropriate 'longjmp' function to use on that jmp_buf - * unless the default error function is overridden in which case NULL is - * acceptable. The size of the jmp_buf is checked against the actual size - * allocated by the library - the call will return NULL on a mismatch - * indicating an ABI mismatch. - */ -PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr, - png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); -# define png_jmpbuf(png_ptr) \ - (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) -#endif -/* This function should be used by libpng applications in place of - * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it - * will use it; otherwise it will call PNG_ABORT(). This function was - * added in libpng-1.5.0. - */ -PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val), - PNG_NORETURN); - -#ifdef PNG_READ_SUPPORTED -/* Reset the compression stream */ -PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); -#endif - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(11, png_structp, 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), - PNG_ALLOCATED); -PNG_EXPORTA(12, png_structp, 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), - PNG_ALLOCATED); -#endif - -/* Write the PNG file signature. */ -PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr)); - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, - png_const_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, - png_const_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); - -/* Allocate and initialize the info structure */ -PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), - PNG_ALLOCATED); - -PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size)); - -/* Writes all the PNG information before the image. */ -PNG_EXPORT(20, void, png_write_info_before_PLTE, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(21, void, png_write_info, - (png_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. */ -PNG_EXPORT(22, void, png_read_info, - (png_structp png_ptr, png_infop info_ptr)); -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED -PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, - (png_structp png_ptr, - png_const_timep ptime)); -#endif - -#ifdef PNG_CONVERT_tIME_SUPPORTED -/* Convert from a struct tm to png_time */ -PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, - PNG_CONST struct tm FAR * ttime)); - -/* Convert from time_t to png_time. Uses gmtime() */ -PNG_EXPORT(25, void, png_convert_from_time_t, - (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. */ -PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr)); -PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr)); -PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr)); -PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED -/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion - * of a tRNS chunk if present. - */ -PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -/* Expand the grayscale to 24-bit RGB if necessary. */ -PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -/* Reduce RGB to grayscale. */ -#define PNG_ERROR_ACTION_NONE 1 -#define PNG_ERROR_ACTION_WARN 2 -#define PNG_ERROR_ACTION_ERROR 3 -#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ - -PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, - int error_action, double red, double green)); -PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green)); - -PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp - png_ptr)); -#endif - -#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, - png_colorp palette)); -#endif - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED -/* How the alpha channel is interpreted - this affects how the color channels of - * a PNG file are returned when an alpha channel, or tRNS chunk in a palette - * file, is present. - * - * This has no effect on the way pixels are written into a PNG output - * datastream. The color samples in a PNG datastream are never premultiplied - * with the alpha samples. - * - * The default is to return data according to the PNG specification: the alpha - * channel is a linear measure of the contribution of the pixel to the - * corresponding composited pixel. The gamma encoded color channels must be - * scaled according to the contribution and to do this it is necessary to undo - * the encoding, scale the color values, perform the composition and reencode - * the values. This is the 'PNG' mode. - * - * The alternative is to 'associate' the alpha with the color information by - * storing color channel values that have been scaled by the alpha. The - * advantage is that the color channels can be resampled (the image can be - * scaled) in this form. The disadvantage is that normal practice is to store - * linear, not (gamma) encoded, values and this requires 16-bit channels for - * still images rather than the 8-bit channels that are just about sufficient if - * gamma encoding is used. In addition all non-transparent pixel values, - * including completely opaque ones, must be gamma encoded to produce the final - * image. This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the - * latter being the two common names for associated alpha color channels.) - * - * Since it is not necessary to perform arithmetic on opaque color values so - * long as they are not to be resampled and are in the final color space it is - * possible to optimize the handling of alpha by storing the opaque pixels in - * the PNG format (adjusted for the output color space) while storing partially - * opaque pixels in the standard, linear, format. The accuracy required for - * standard alpha composition is relatively low, because the pixels are - * isolated, therefore typically the accuracy loss in storing 8-bit linear - * values is acceptable. (This is not true if the alpha channel is used to - * simulate transparency over large areas - use 16 bits or the PNG mode in - * this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is - * treated as opaque only if the alpha value is equal to the maximum value. - * - * The final choice is to gamma encode the alpha channel as well. This is - * broken because, in practice, no implementation that uses this choice - * correctly undoes the encoding before handling alpha composition. Use this - * choice only if other serious errors in the software or hardware you use - * mandate it; the typical serious error is for dark halos to appear around - * opaque areas of the composited PNG image because of arithmetic overflow. - * - * The API function png_set_alpha_mode specifies which of these choices to use - * with an enumerated 'mode' value and the gamma of the required output: - */ -#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ -#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ -#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ -#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ -#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ -#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ - -PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode, - double output_gamma)); -PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr, - int mode, png_fixed_point output_gamma)); -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) -/* The output_gamma value is a screen gamma in libpng terminology: it expresses - * how to decode the output values, not how they are encoded. The values used - * correspond to the normal numbers used to describe the overall gamma of a - * computer display system; for example 2.2 for an sRGB conformant system. The - * values are scaled by 100000 in the _fixed version of the API (so 220000 for - * sRGB.) - * - * The inverse of the value is always used to provide a default for the PNG file - * encoding if it has no gAMA chunk and if png_set_gamma() has not been called - * to override the PNG gamma information. - * - * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode - * opaque pixels however pixels with lower alpha values are not encoded, - * regardless of the output gamma setting. - * - * When the standard Porter Duff handling is requested with mode 1 the output - * encoding is set to be linear and the output_gamma value is only relevant - * as a default for input data that has no gamma information. The linear output - * encoding will be overridden if png_set_gamma() is called - the results may be - * highly unexpected! - * - * The following numbers are derived from the sRGB standard and the research - * behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of - * 0.45455 (1/2.2) for PNG. The value implicitly includes any viewing - * correction required to take account of any differences in the color - * environment of the original scene and the intended display environment; the - * value expresses how to *decode* the image for display, not how the original - * data was *encoded*. - * - * sRGB provides a peg for the PNG standard by defining a viewing environment. - * sRGB itself, and earlier TV standards, actually use a more complex transform - * (a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is - * limited to simple power laws.) By saying that an image for direct display on - * an sRGB conformant system should be stored with a gAMA chunk value of 45455 - * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification - * makes it possible to derive values for other display systems and - * environments. - * - * The Mac value is deduced from the sRGB based on an assumption that the actual - * extra viewing correction used in early Mac display systems was implemented as - * a power 1.45 lookup table. - * - * Any system where a programmable lookup table is used or where the behavior of - * the final display device characteristics can be changed requires system - * specific code to obtain the current characteristic. However this can be - * difficult and most PNG gamma correction only requires an approximate value. - * - * By default, if png_set_alpha_mode() is not called, libpng assumes that all - * values are unencoded, linear, values and that the output device also has a - * linear characteristic. This is only very rarely correct - it is invariably - * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the - * default if you don't know what the right answer is! - * - * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS - * 10.6) which used a correction table to implement a somewhat lower gamma on an - * otherwise sRGB system. - * - * Both these values are reserved (not simple gamma values) in order to allow - * more precise correction internally in the future. - * - * NOTE: the following values can be passed to either the fixed or floating - * point APIs, but the floating point API will also accept floating point - * values. - */ -#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ -#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ -#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ -#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ -#endif - -/* The following are examples of calls to png_set_alpha_mode to achieve the - * required overall gamma correction and, where necessary, alpha - * premultiplication. - * - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); - * This is the default libpng handling of the alpha channel - it is not - * pre-multiplied into the color components. In addition the call states - * that the output is for a sRGB system and causes all PNG files without gAMA - * chunks to be assumed to be encoded using sRGB. - * - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); - * In this case the output is assumed to be something like an sRGB conformant - * display preceeded by a power-law lookup table of power 1.45. This is how - * early Mac systems behaved. - * - * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); - * This is the classic Jim Blinn approach and will work in academic - * environments where everything is done by the book. It has the shortcoming - * of assuming that input PNG data with no gamma information is linear - this - * is unlikely to be correct unless the PNG files where generated locally. - * Most of the time the output precision will be so low as to show - * significant banding in dark areas of the image. - * - * png_set_expand_16(pp); - * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); - * This is a somewhat more realistic Jim Blinn inspired approach. PNG files - * are assumed to have the sRGB encoding if not marked with a gamma value and - * the output is always 16 bits per component. This permits accurate scaling - * and processing of the data. If you know that your input PNG files were - * generated locally you might need to replace PNG_DEFAULT_sRGB with the - * correct value for your system. - * - * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); - * If you just need to composite the PNG image onto an existing background - * and if you control the code that does this you can use the optimization - * setting. In this case you just copy completely opaque pixels to the - * output. For pixels that are not completely transparent (you just skip - * those) you do the composition math using png_composite or png_composite_16 - * below then encode the resultant 8-bit or 16-bit values to match the output - * encoding. - * - * Other cases - * If neither the PNG nor the standard linear encoding work for you because - * of the software or hardware you use then you have a big problem. The PNG - * case will probably result in halos around the image. The linear encoding - * will probably result in a washed out, too bright, image (it's actually too - * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably - * substantially reduce the halos. Alternatively try: - * - * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); - * This option will also reduce the halos, but there will be slight dark - * halos round the opaque parts of the image where the background is light. - * In the OPTIMIZED mode the halos will be light halos where the background - * is dark. Take your pick - the halos are unavoidable unless you can get - * your hardware/software fixed! (The OPTIMIZED approach is slightly - * faster.) - * - * When the default gamma of PNG files doesn't match the output gamma. - * If you have PNG files with no gamma information png_set_alpha_mode allows - * you to provide a default gamma, but it also sets the ouput gamma to the - * matching value. If you know your PNG files have a gamma that doesn't - * match the output you can take advantage of the fact that - * png_set_alpha_mode always sets the output gamma but only sets the PNG - * default if it is not already set: - * - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); - * The first call sets both the default and the output gamma values, the - * second call overrides the output gamma without changing the default. This - * is easier than achieving the same effect with png_set_gamma. You must use - * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will - * fire if more than one call to png_set_alpha_mode and png_set_background is - * made in the same read operation, however multiple calls with PNG_ALPHA_PNG - * are ignored. - */ - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXPORT(38, void, png_set_invert_alpha, (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. */ -PNG_EXPORT(39, void, png_set_filler, (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. */ -PNG_EXPORT(40, void, png_set_add_alpha, - (png_structp png_ptr, png_uint_32 filler, - int flags)); -#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. */ -PNG_EXPORT(41, void, png_set_swap, (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. */ -PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ - defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_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. - * MUST be called before png_read_update_info or png_start_read_image, - * otherwise it will not have the desired effect. Note that it is still - * necessary to call png_read_row or png_read_rows png_get_image_height - * times for each pass. -*/ -PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS by replacing with a background color. Prior to - * libpng-1.5.4 this API must not be called before the PNG file header has been - * read. Doing so will result in unexpected behavior and possible warnings or - * errors if the PNG file contains a bKGD chunk. - */ -PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)); -PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, png_fixed_point background_gamma)); -#endif -#ifdef PNG_READ_BACKGROUND_SUPPORTED -# 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_SCALE_16_TO_8_SUPPORTED -/* Scale a 16-bit depth file down to 8-bit, accurately. */ -PNG_EXPORT(229, void, png_set_scale_16, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED -#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ -/* Strip the second byte of information from a 16-bit depth file. */ -PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* Turn on quantizing, and reduce the palette to the number of colors - * available. - */ -PNG_EXPORT(49, void, png_set_quantize, - (png_structp png_ptr, png_colorp palette, - int num_palette, int maximum_colors, png_const_uint_16p histogram, - int full_quantize)); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* The threshold on gamma processing is configurable but hard-wired into the - * library. The following is the floating point variant. - */ -#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) - -/* Handle gamma correction. Screen_gamma=(display_exponent). - * NOTE: this API simply sets the screen and file gamma values. It will - * therefore override the value for gamma in a PNG file if it is called after - * the file header has been read - use with care - call before reading the PNG - * file for best results! - * - * These routines accept the same gamma values as png_set_alpha_mode (described - * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either - * API (floating point or fixed.) Notice, however, that the 'file_gamma' value - * is the inverse of a 'screen gamma' value. - */ -PNG_FP_EXPORT(50, void, png_set_gamma, - (png_structp png_ptr, double screen_gamma, - double override_file_gamma)); -PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, - png_fixed_point screen_gamma, png_fixed_point override_file_gamma)); -#endif - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -/* Set how many lines between output flushes - 0 for no flushing */ -PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr)); -#endif - -/* Optional update palette with requested transformations */ -PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr)); - -/* Optional call to update the users info structure */ -PNG_EXPORT(54, void, png_read_update_info, - (png_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. */ -PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read a row of data. */ -PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, - png_bytep display_row)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the whole image into memory at once. */ -PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image)); -#endif - -/* Write a row of image data */ -PNG_EXPORT(58, void, png_write_row, - (png_structp png_ptr, png_const_bytep row)); - -/* Write a few rows of image data: (*row) is not written; however, the type - * is declared as writeable to maintain compatibility with previous versions - * of libpng and to allow the 'display_row' array from read_rows to be passed - * unchanged to write_rows. - */ -PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, - png_uint_32 num_rows)); - -/* Write the image data */ -PNG_EXPORT(60, void, png_write_image, - (png_structp png_ptr, png_bytepp image)); - -/* Write the end of the PNG file. */ -PNG_EXPORT(61, void, png_write_end, - (png_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. */ -PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr)); -#endif - -/* Free any memory associated with the png_info_struct */ -PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, - png_infopp info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr)); - -/* Set the libpng method of handling chunk CRC errors */ -PNG_EXPORT(66, void, png_set_crc_action, - (png_structp png_ptr, int crit_action, int ancil_action)); - -/* Values for png_set_crc_action() 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. - */ -PNG_EXPORT(67, void, png_set_filter, - (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 - -#ifdef 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. - */ -PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, - int heuristic_method, int num_weights, png_const_doublep filter_weights, - png_const_doublep filter_costs)); -PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, - (png_structp png_ptr, - int heuristic_method, int num_weights, png_const_fixed_point_p - filter_weights, png_const_fixed_point_p filter_costs)); -#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 */ - -#ifdef PNG_WRITE_SUPPORTED -/* 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. - */ -PNG_EXPORT(69, void, png_set_compression_level, - (png_structp png_ptr, int level)); - -PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, - int mem_level)); - -PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, - int strategy)); - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, - int window_bits)); - -PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, - int method)); -#endif - -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -/* Also set zlib parameters for compressing non-IDAT chunks */ -PNG_EXPORT(222, void, png_set_text_compression_level, - (png_structp png_ptr, int level)); - -PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structp png_ptr, - int mem_level)); - -PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structp png_ptr, - int strategy)); - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -PNG_EXPORT(225, void, png_set_text_compression_window_bits, (png_structp - png_ptr, int window_bits)); - -PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr, - int method)); -#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ - -/* 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-manual.txt for - * more information. - */ - -#ifdef PNG_STDIO_SUPPORTED -/* Initialize the input/output for the PNG file to the default functions. */ -PNG_EXPORT(74, void, png_init_io, (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. - */ - -PNG_EXPORT(75, void, png_set_error_fn, - (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 */ -PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_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. - */ -PNG_EXPORT(77, void, png_set_write_fn, (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. */ -PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); - -PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, - png_read_status_ptr read_row_fn)); - -PNG_EXPORT(81, void, png_set_write_status_fn, (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). */ -PNG_EXPORT(82, void, png_set_mem_fn, (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 */ -PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); -#endif - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, - png_user_transform_ptr read_user_transform_fn)); -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, - png_user_transform_ptr write_user_transform_fn)); -#endif - -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -PNG_EXPORT(86, void, png_set_user_transform_info, (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 */ -PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, - (png_const_structp png_ptr)); -#endif - -#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED -/* Return information about the row currently being processed. Note that these - * APIs do not fail but will return unexpected results if called outside a user - * transform callback. Also note that when transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp)); -PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_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. - */ -PNG_EXPORT(90, void, 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)); - -/* Returns the user pointer associated with the push read functions */ -PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); - -/* Function to be called when data becomes available */ -PNG_EXPORT(92, void, png_process_data, - (png_structp png_ptr, png_infop info_ptr, - png_bytep buffer, png_size_t buffer_size)); - -/* A function which may be called *only* within png_process_data to stop the - * processing of any more data. The function returns the number of bytes - * remaining, excluding any that libpng has cached internally. A subsequent - * call to png_process_data must supply these bytes again. If the argument - * 'save' is set to true the routine will first save all the pending data and - * will always return 0. - */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save)); - -/* A function which may be called *only* outside (after) a call to - * png_process_data. It returns the number of bytes of data to skip in the - * input. Normally it will return 0, but if it returns a non-zero value the - * application must skip than number of bytes of input data and pass the - * following data to the next call to png_process_data. - */ -PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); - -#ifdef PNG_READ_INTERLACING_SUPPORTED -/* Function that combines rows. 'new_row' is a flag that should come from - * the callback and be non-NULL if anything needs to be done; the library - * stores its own version of the new data internally and ignores the passed - * in value. - */ -PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, - png_bytep old_row, png_const_bytep new_row)); -#endif /* PNG_READ_INTERLACING_SUPPORTED */ -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -PNG_EXPORTA(94, png_voidp, png_malloc, - (png_structp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED); -/* Added at libpng version 1.4.0 */ -PNG_EXPORTA(95, png_voidp, png_calloc, - (png_structp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED); - -/* Added at libpng version 1.2.4 */ -PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); - -/* Frees a pointer allocated by png_malloc() */ -PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr)); - -/* Free data that was allocated internally */ -PNG_EXPORT(98, void, png_free_data, - (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num)); - -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application */ -PNG_EXPORT(99, void, png_data_freer, - (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask)); - -/* 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 -PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); -PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); -#endif - -#ifdef PNG_ERROR_TEXT_SUPPORTED -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(102, void, png_error, - (png_structp png_ptr, png_const_charp error_message), - PNG_NORETURN); - -/* The same, but the chunk name is prepended to the error string. */ -PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, - png_const_charp error_message), PNG_NORETURN); - -#else -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); -#endif - -#ifdef PNG_WARNINGS_SUPPORTED -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, - png_const_charp warning_message)); - -/* Non-fatal error in libpng, chunk name is prepended to message. */ -PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, - png_const_charp warning_message)); -#endif - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -/* Benign error in libpng. Can continue, but may have a problem. - * User can choose whether to handle as a fatal error or as a warning. */ -# undef png_benign_error -PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, - png_const_charp warning_message)); - -/* Same, chunk name is prepended to message. */ -# undef png_chunk_benign_error -PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, - png_const_charp warning_message)); - -PNG_EXPORT(109, void, png_set_benign_errors, - (png_structp png_ptr, int allowed)); -#else -# ifdef PNG_ALLOW_BENIGN_ERRORS -# define png_benign_error png_warning -# define png_chunk_benign_error png_chunk_warning -# else -# define png_benign_error png_error -# define png_chunk_benign_error png_chunk_error -# endif -#endif - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ 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_ 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. */ -PNG_EXPORT(110, png_uint_32, png_get_valid, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, - png_const_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(). - */ -PNG_EXPORT(112, png_bytepp, png_get_rows, - (png_const_structp png_ptr, png_const_infop info_ptr)); -/* Set row_pointers, which is an array of pointers to scanlines for use - * by png_write_png(). - */ -PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -PNG_EXPORT(114, png_byte, png_get_channels, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image height in pixels. */ -PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image bit_depth. */ -PNG_EXPORT(117, png_byte, png_get_bit_depth, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -/* Returns image color_type. */ -PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image filter_type. */ -PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image interlace_type. */ -PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image compression_type. */ -PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -/* Returns pointer to signature string read from PNG header */ -PNG_EXPORT(130, png_const_bytep, png_get_signature, - (png_const_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(131, png_uint_32, png_get_bKGD, - (png_const_structp png_ptr, png_infop info_ptr, - png_color_16p *background)); -#endif - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, - png_const_color_16p background)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, - png_const_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_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_structp png_ptr, - png_const_infop info_ptr, double *red_X, double *red_Y, double *red_Z, - double *green_X, double *green_Y, double *green_Z, double *blue_X, - double *blue_Y, double *blue_Z)); -#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */ -PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, - (png_const_structp png_ptr, - png_const_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 -PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, - (png_structp png_ptr, png_const_infop info_ptr, - png_fixed_point *int_red_X, png_fixed_point *int_red_Y, - png_fixed_point *int_red_Z, png_fixed_point *int_green_X, - png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, - png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, - png_fixed_point *int_blue_Z)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(135, void, 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_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_structp png_ptr, - png_infop info_ptr, double red_X, double red_Y, double red_Z, - double green_X, double green_Y, double green_Z, double blue_X, - double blue_Y, double blue_Z)); -PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (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)); -PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, - png_fixed_point int_red_Z, png_fixed_point int_green_X, - png_fixed_point int_green_Y, png_fixed_point int_green_Z, - png_fixed_point int_blue_X, png_fixed_point int_blue_Y, - png_fixed_point int_blue_Z)); -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, - (png_const_structp png_ptr, png_const_infop info_ptr, - double *file_gamma)); -PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_fixed_point *int_file_gamma)); -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr, - png_infop info_ptr, double file_gamma)); -PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_file_gamma)); -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(141, png_uint_32, png_get_hIST, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_16p *hist)); -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, - png_infop info_ptr, png_const_uint_16p hist)); -#endif - -PNG_EXPORT(143, png_uint_32, 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_method, int *compression_method, int *filter_method)); - -PNG_EXPORT(144, void, 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_method, int compression_method, int filter_method)); - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(145, png_uint_32, png_get_oFFs, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); -#endif - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(146, void, png_set_oFFs, - (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 -PNG_EXPORT(147, png_uint_32, png_get_pCAL, - (png_const_structp png_ptr, png_const_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 -PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr, - png_infop info_ptr, - png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, - int nparams, png_const_charp units, png_charpp params)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(149, png_uint_32, png_get_pHYs, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(150, void, png_set_pHYs, - (png_structp png_ptr, png_infop info_ptr, - png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -PNG_EXPORT(151, png_uint_32, png_get_PLTE, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_colorp *palette, int *num_palette)); - -PNG_EXPORT(152, void, png_set_PLTE, - (png_structp png_ptr, png_infop info_ptr, - png_const_colorp palette, int num_palette)); - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(153, png_uint_32, png_get_sBIT, - (png_const_structp png_ptr, png_infop info_ptr, - png_color_8p *sig_bit)); -#endif - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(154, void, png_set_sBIT, - (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, - png_const_infop info_ptr, int *file_srgb_intent)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(156, void, png_set_sRGB, - (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); -PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, - png_infop info_ptr, int srgb_intent)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(158, png_uint_32, png_get_iCCP, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_charpp name, int *compression_type, png_bytepp profile, - png_uint_32 *proflen)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(159, void, png_set_iCCP, - (png_structp png_ptr, png_infop info_ptr, - png_const_charp name, int compression_type, png_const_bytep profile, - png_uint_32 proflen)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(160, png_uint_32, png_get_sPLT, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_sPLT_tpp entries)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(161, void, png_set_sPLT, - (png_structp png_ptr, png_infop info_ptr, - png_const_sPLT_tp entries, int nentries)); -#endif - -#ifdef PNG_TEXT_SUPPORTED -/* png_get_text also returns the number of text chunks in *num_text */ -PNG_EXPORT(162, png_uint_32, png_get_text, - (png_const_structp png_ptr, png_const_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 -PNG_EXPORT(163, void, png_set_text, - (png_structp png_ptr, png_infop info_ptr, - png_const_textp text_ptr, int num_text)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(164, png_uint_32, png_get_tIME, - (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(165, void, png_set_tIME, - (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(166, png_uint_32, png_get_tRNS, - (png_const_structp png_ptr, png_infop info_ptr, - png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(167, void, png_set_tRNS, - (png_structp png_ptr, png_infop info_ptr, - png_const_bytep trans_alpha, int num_trans, - png_const_color_16p trans_color)); -#endif - -#ifdef PNG_sCAL_SUPPORTED -PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, - (png_const_structp png_ptr, png_const_infop info_ptr, - int *unit, double *width, double *height)); -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED -/* NOTE: this API is currently implemented using floating point arithmetic, - * consequently it can only be used on systems with floating point support. - * In any case the range of values supported by png_fixed_point is small and it - * is highly recommended that png_get_sCAL_s be used instead. - */ -PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, - (png_structp png_ptr, png_const_infop info_ptr, int *unit, - png_fixed_point *width, - png_fixed_point *height)); -#endif -PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, - (png_const_structp png_ptr, png_const_infop info_ptr, - int *unit, png_charpp swidth, png_charpp sheight)); - -PNG_FP_EXPORT(170, void, png_set_sCAL, - (png_structp png_ptr, png_infop info_ptr, - int unit, double width, double height)); -PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, - png_infop info_ptr, int unit, png_fixed_point width, - png_fixed_point height)); -PNG_EXPORT(171, void, png_set_sCAL_s, - (png_structp png_ptr, png_infop info_ptr, - int unit, png_const_charp swidth, png_const_charp sheight)); -#endif /* PNG_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. Because this turns off the default handling for chunks - that would otherwise be recognized the behavior of libpng transformations may - well become incorrect! - keep = 0: PNG_HANDLE_CHUNK_AS_DEFAULT: follow default behavior - = 1: PNG_HANDLE_CHUNK_NEVER: do not keep - = 2: PNG_HANDLE_CHUNK_IF_SAFE: keep only if safe-to-copy - = 3: PNG_HANDLE_CHUNK_ALWAYS: keep even if unsafe-to-copy -*/ -PNG_EXPORT(172, void, png_set_keep_unknown_chunks, - (png_structp png_ptr, int keep, - png_const_bytep chunk_list, int num_chunks)); - -/* The handling code is returned; the result is therefore true (non-zero) if - * special handling is required, false for the default handling. - */ -PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, - png_const_bytep chunk_name)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, - png_infop info_ptr, png_const_unknown_chunkp unknowns, - int num_unknowns)); -PNG_EXPORT(175, void, png_set_unknown_chunk_location, - (png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, - png_const_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); - */ -PNG_EXPORT(177, void, png_set_invalid, - (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. */ -PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, - int transforms, png_voidp params)); -PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, - int transforms, png_voidp params)); -#endif - -PNG_EXPORT(180, png_const_charp, png_get_copyright, - (png_const_structp png_ptr)); -PNG_EXPORT(181, png_const_charp, png_get_header_ver, - (png_const_structp png_ptr)); -PNG_EXPORT(182, png_const_charp, png_get_header_version, - (png_const_structp png_ptr)); -PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, - (png_const_structp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (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 - -/* 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 -PNG_EXPORT(185, void, png_set_strip_error_numbers, - (png_structp png_ptr, - png_uint_32 strip_mode)); -#endif - -/* Added in libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, - png_uint_32 user_width_max, png_uint_32 user_height_max)); -PNG_EXPORT(187, png_uint_32, png_get_user_width_max, - (png_const_structp png_ptr)); -PNG_EXPORT(188, png_uint_32, png_get_user_height_max, - (png_const_structp png_ptr)); -/* Added in libpng-1.4.0 */ -PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, - png_uint_32 user_chunk_cache_max)); -PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, - (png_const_structp png_ptr)); -/* Added in libpng-1.4.1 */ -PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, - png_alloc_size_t user_chunk_cache_max)); -PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, - (png_const_structp png_ptr)); -#endif - -#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) -PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -PNG_FP_EXPORT(196, float, png_get_x_offset_inches, - (png_const_structp png_ptr, png_const_infop info_ptr)); -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, - (png_structp png_ptr, png_const_infop info_ptr)); -#endif - -PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, - png_const_infop info_ptr)); -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, - (png_structp png_ptr, png_const_infop info_ptr)); -#endif - -# ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, - png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, - int *unit_type)); -# endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ - -/* Added in libpng-1.4.0 */ -#ifdef PNG_IO_STATE_SUPPORTED -PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr)); - -PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name, - (png_structp png_ptr), PNG_DEPRECATED); -PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, - (png_const_structp png_ptr)); - -/* The flags returned by png_get_io_state() are the following: */ -# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ -# define PNG_IO_READING 0x0001 /* currently reading */ -# define PNG_IO_WRITING 0x0002 /* currently writing */ -# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ -# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ -# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ -# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ -# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ -# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ -#endif /* ?PNG_IO_STATE_SUPPORTED */ - -/* Interlace support. The following macros are always defined so that if - * libpng interlace handling is turned off the macros may be used to handle - * interlaced images within the application. - */ -#define PNG_INTERLACE_ADAM7_PASSES 7 - -/* Two macros to return the first row and first column of the original, - * full, image which appears in a given pass. 'pass' is in the range 0 - * to 6 and the result is in the range 0 to 7. - */ -#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) -#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) - -/* A macro to return the offset between pixels in the output row for a pair of - * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that - * follows. Note that ROW_OFFSET is the offset from one row to the next whereas - * COL_OFFSET is from one column to the next, within a row. - */ -#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) -#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) - -/* Two macros to help evaluate the number of rows or columns in each - * pass. This is expressed as a shift - effectively log2 of the number or - * rows or columns in each 8x8 tile of the original image. - */ -#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) -#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) - -/* Hence two macros to determine the number of rows or columns in a given - * pass of an image given its height or width. In fact these macros may - * return non-zero even though the sub-image is empty, because the other - * dimension may be empty for a small image. - */ -#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) -#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) - -/* For the reader row callbacks (both progressive and sequential) it is - * necessary to find the row in the output image given a row in an interlaced - * image, so two more macros: - */ -#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ - (((yIn)<>(((7-(off))-(pass))<<2)) & 0xF) | \ - ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) - -#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ - ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) -#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ - ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) - -#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)) + 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)*(65535 \ - - (png_uint_32)(alpha)) + 32768); \ - (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)) + \ - 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)(65535 - (png_uint_32)(alpha)) + \ - 32767) / 65535) -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ - -#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); -PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); -PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); -#endif - -PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, - png_const_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). */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); -#endif -#ifdef PNG_SAVE_INT_32_SUPPORTED -PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); -#endif - -/* 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. - */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ -#endif - -#ifdef PNG_USE_READ_MACROS -/* Inline macros to do direct reads of bytes from the input buffer. - * The png_get_int_32() routine assumes we are using two's complement - * format for negative values, which is almost certainly true. - */ -# define png_get_uint_32(buf) \ - (((png_uint_32)(*(buf)) << 24) + \ - ((png_uint_32)(*((buf) + 1)) << 16) + \ - ((png_uint_32)(*((buf) + 2)) << 8) + \ - ((png_uint_32)(*((buf) + 3)))) - - /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the - * function) incorrectly returned a value of type png_uint_32. - */ -# define png_get_uint_16(buf) \ - ((png_uint_16) \ - (((unsigned int)(*(buf)) << 8) + \ - ((unsigned int)(*((buf) + 1))))) - -# define png_get_int_32(buf) \ - ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ - : (png_int_32)png_get_uint_32(buf))) -#endif - -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project - * defs - */ - -/* The last ordinal number (this is the *last* one already used; the next - * one to use is one more than this.) Maintainer, remember to add an entry to - * scripts/symbols.def as well. - */ -#ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(233); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* Do not put anything past this line */ -#endif /* PNG_H */ diff --git a/plugins/FreeImage/Source/LibPNG/pngconf.h b/plugins/FreeImage/Source/LibPNG/pngconf.h deleted file mode 100644 index 121d204ccd..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngconf.h +++ /dev/null @@ -1,596 +0,0 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.5.9 - February 18, 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 - -#ifndef PNG_BUILDING_SYMBOL_TABLE -/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C - * definition file for machine specific limits, this may impact the - * correctness of the definitons below (see uses of INT_MAX). - */ -# ifndef PNG_NO_LIMITS_H -# include -# endif - -/* For the memory copy APIs (i.e. the standard definitions of these), - * because this file defines png_memcpy and so on the base APIs must - * be defined here. - */ -# ifdef BSD -# include -# else -# include -# endif - -/* For png_FILE_p - this provides the standard definition of a - * FILE - */ -# ifdef PNG_STDIO_SUPPORTED -# include -# endif -#endif - -/* This controls optimization of the reading of 16 and 32 bit values - * from PNG files. It can be set on a per-app-file basis - it - * just changes whether a macro is used to the function is called. - * The library builder sets the default, if read functions are not - * built into the library the macro implementation is forced on. - */ -#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED -# define PNG_USE_READ_MACROS -#endif -#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) -# if PNG_DEFAULT_READ_MACROS -# define PNG_USE_READ_MACROS -# endif -#endif - -/* COMPILER SPECIFIC OPTIONS. - * - * These options are provided so that a variety of difficult compilers - * can be used. Some are fixed at build time (e.g. PNG_API_RULE - * below) but still have compiler specific implementations, others - * may be changed on a per-file basis when compiling against libpng. - */ - -/* The PNGARG 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) () -# else -# define PNGARG(arglist) arglist -# endif /* _NO_PROTO */ - -# endif /* OF */ - -#endif /* PNGARG */ - -/* Function calling conventions. - * ============================= - * Normally it is not necessary to specify to the compiler how to call - * a function - it just does it - however on x86 systems derived from - * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems - * and some others) there are multiple ways to call a function and the - * default can be changed on the compiler command line. For this reason - * libpng specifies the calling convention of every exported function and - * every function called via a user supplied function pointer. This is - * done in this file by defining the following macros: - * - * PNGAPI Calling convention for exported functions. - * PNGCBAPI Calling convention for user provided (callback) functions. - * PNGCAPI Calling convention used by the ANSI-C library (required - * for longjmp callbacks and sometimes used internally to - * specify the calling convention for zlib). - * - * These macros should never be overridden. If it is necessary to - * change calling convention in a private build this can be done - * by setting PNG_API_RULE (which defaults to 0) to one of the values - * below to select the correct 'API' variants. - * - * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. - * This is correct in every known environment. - * PNG_API_RULE=1 Use the operating system convention for PNGAPI and - * the 'C' calling convention (from PNGCAPI) for - * callbacks (PNGCBAPI). This is no longer required - * in any known environment - if it has to be used - * please post an explanation of the problem to the - * libpng mailing list. - * - * These cases only differ if the operating system does not use the C - * calling convention, at present this just means the above cases - * (x86 DOS/Windows sytems) and, even then, this does not apply to - * Cygwin running on those systems. - * - * Note that the value must be defined in pnglibconf.h so that what - * the application uses to call the library matches the conventions - * set when building the library. - */ - -/* Symbol export - * ============= - * When building a shared library it is almost always necessary to tell - * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' - * is used to mark the symbols. On some systems these symbols can be - * extracted at link time and need no special processing by the compiler, - * on other systems the symbols are flagged by the compiler and just - * the declaration requires a special tag applied (unfortunately) in a - * compiler dependent way. Some systems can do either. - * - * A small number of older systems also require a symbol from a DLL to - * be flagged to the program that calls it. This is a problem because - * we do not know in the header file included by application code that - * the symbol will come from a shared library, as opposed to a statically - * linked one. For this reason the application must tell us by setting - * the magic flag PNG_USE_DLL to turn on the special processing before - * it includes png.h. - * - * Four additional macros are used to make this happen: - * - * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from - * the build or imported if PNG_USE_DLL is set - compiler - * and system specific. - * - * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to - * 'type', compiler specific. - * - * PNG_DLL_EXPORT Set to the magic to use during a libpng build to - * make a symbol exported from the DLL. Not used in the - * public header files; see pngpriv.h for how it is used - * in the libpng build. - * - * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come - * from a DLL - used to define PNG_IMPEXP when - * PNG_USE_DLL is set. - */ - -/* System specific discovery. - * ========================== - * This code is used at build time to find PNG_IMPEXP, the API settings - * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL - * import processing is possible. On Windows/x86 systems it also sets - * compiler-specific macros to the values required to change the calling - * conventions of the various functions. - */ -#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ - defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)) &&\ - ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\ - defined(_M_X64) || defined(_M_IA64)) - /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes - * builds under Cygwin or MinGW. Also includes Watcom builds but these need - * special treatment because they are not compatible with GCC or Visual C - * because of different calling conventions. - */ -# if PNG_API_RULE == 2 - /* If this line results in an error, either because __watcall is not - * understood or because of a redefine just below you cannot use *this* - * build of the library with the compiler you are using. *This* build was - * build using Watcom and applications must also be built using Watcom! - */ -# define PNGCAPI __watcall -# endif - -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGCAPI __cdecl -# if PNG_API_RULE == 1 -# define PNGAPI __stdcall -# endif -# else - /* An older compiler, or one not detected (erroneously) above, - * if necessary override on the command line to get the correct - * variants for the compiler. - */ -# ifndef PNGCAPI -# define PNGCAPI _cdecl -# endif -# if PNG_API_RULE == 1 && !defined(PNGAPI) -# define PNGAPI _stdcall -# endif -# endif /* compiler/api */ - /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ - -# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) - ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed -# endif - -# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ - (defined(__BORLANDC__) && __BORLANDC__ < 0x500) - /* older Borland and MSC - * compilers used '__export' and required this to be after - * the type. - */ -# ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP -# endif -# define PNG_DLL_EXPORT __export -# else /* newer compiler */ -# define PNG_DLL_EXPORT __declspec(dllexport) -# ifndef PNG_DLL_IMPORT -# define PNG_DLL_IMPORT __declspec(dllimport) -# endif -# endif /* compiler */ - -#else /* !Windows/x86 */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# define PNGAPI _System -# else /* !Windows/x86 && !OS/2 */ - /* Use the defaults, or define PNG*API on the command line (but - * this will have to be done for every compile!) - */ -# endif /* other system, !OS/2 */ -#endif /* !Windows/x86 */ - -/* Now do all the defaulting . */ -#ifndef PNGCAPI -# define PNGCAPI -#endif -#ifndef PNGCBAPI -# define PNGCBAPI PNGCAPI -#endif -#ifndef PNGAPI -# define PNGAPI PNGCAPI -#endif - -/* PNG_IMPEXP may be set on the compilation system command line or (if not set) - * then in an internal header file when building the library, otherwise (when - * using the library) it is set here. - */ -#ifndef PNG_IMPEXP -# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) - /* This forces use of a DLL, disallowing static linking */ -# define PNG_IMPEXP PNG_DLL_IMPORT -# endif - -# ifndef PNG_IMPEXP -# define PNG_IMPEXP -# endif -#endif - -/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat - * 'attributes' as a storage class - the attributes go at the start of the - * function definition, and attributes are always appended regardless of the - * compiler. This considerably simplifies these macros but may cause problems - * if any compilers both need function attributes and fail to handle them as - * a storage class (this is unlikely.) - */ -#ifndef PNG_FUNCTION -# define PNG_FUNCTION(type, name, args, attributes) attributes type name args -#endif - -#ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type -#endif - - /* The ordinal value is only relevant when preprocessing png.h for symbol - * table entries, so we discard it here. See the .dfn files in the - * scripts directory. - */ -#ifndef PNG_EXPORTA - -# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ - PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ - extern attributes) -#endif - -/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, - * so make something non-empty to satisfy the requirement: - */ -#define PNG_EMPTY /*empty list*/ - -#define PNG_EXPORT(ordinal, type, name, args)\ - PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) - -/* Use PNG_REMOVED to comment out a removed interface. */ -#ifndef PNG_REMOVED -# define PNG_REMOVED(ordinal, type, name, args, attributes) -#endif - -#ifndef PNG_CALLBACK -# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) -#endif - -/* 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-1.2.41. - */ - -#ifndef PNG_NO_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. - */ -# if defined(__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 -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __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 -# endif /* __GNUC__ */ - -# if defined(_MSC_VER) && (_MSC_VER >= 1300) -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* not supported */ -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __declspec(noreturn) -# endif -# ifndef PNG_ALLOCATED -# if (_MSC_VER >= 1400) -# define PNG_ALLOCATED __declspec(restrict) -# endif -# endif -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __declspec(deprecated) -# endif -# ifndef PNG_PRIVATE -# define PNG_PRIVATE __declspec(deprecated) -# endif -# endif /* _MSC_VER */ -#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_PRIVATE -# define PNG_PRIVATE /* This is a private libpng function */ -#endif -#ifndef PNG_FP_EXPORT /* A floating point API. */ -# ifdef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FP_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args) -# else /* No floating point APIs */ -# define PNG_FP_EXPORT(ordinal, type, name, args) -# endif -#endif -#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ -# ifdef PNG_FIXED_POINT_SUPPORTED -# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args) -# else /* No fixed point APIs */ -# define PNG_FIXED_EXPORT(ordinal, type, name, args) -# endif -#endif - -/* 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. - * - * This should not change how the APIs are called, so it can be done - * on a per-file basis in the application. - */ -#ifndef PNG_CONST -# ifndef PNG_NO_CONST -# define PNG_CONST const -# else -# define PNG_CONST -# endif -#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. - */ - -#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) -typedef unsigned int png_uint_32; -typedef int png_int_32; -#else -typedef unsigned long png_uint_32; -typedef long png_int_32; -#endif -typedef unsigned short png_uint_16; -typedef short png_int_16; -typedef unsigned char png_byte; - -#ifdef PNG_NO_SIZE_T -typedef unsigned int png_size_t; -#else -typedef size_t png_size_t; -#endif -#define png_sizeof(x) (sizeof (x)) - -/* The following is needed for medium model support. It cannot be in the - * pngpriv.h header. 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 /* only used in build */ -# 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 -# 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., gamma - */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef PNG_CONST void FAR * png_const_voidp; -typedef png_byte FAR * png_bytep; -typedef PNG_CONST png_byte FAR * png_const_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef PNG_CONST png_int_32 FAR * png_const_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p; -typedef png_int_16 FAR * png_int_16p; -typedef PNG_CONST png_int_16 FAR * png_const_int_16p; -typedef char FAR * png_charp; -typedef PNG_CONST char FAR * png_const_charp; -typedef png_fixed_point FAR * png_fixed_point_p; -typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p; -typedef png_size_t FAR * png_size_tp; -typedef PNG_CONST png_size_t FAR * png_const_size_tp; - -#ifdef PNG_STDIO_SUPPORTED -typedef FILE * png_FILE_p; -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; -typedef PNG_CONST double FAR * png_const_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; - -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, - * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 - * to png_alloc_size_t are not necessary; in fact, it is recommended - * not to use them at all so that the compiler can complain when something - * turns out to be problematic. - * Casts in the other direction (from png_alloc_size_t to png_size_t or - * png_uint_32) should be explicitly applied; however, we do not expect - * to encounter practical situations that require such conversions. - */ -#if defined(__TURBOC__) && !defined(__FLAT__) - typedef unsigned long png_alloc_size_t; -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - typedef unsigned long png_alloc_size_t; -# else - /* This is an attempt to detect an old Windows system where (int) is - * actually 16 bits, in that case png_malloc must have an argument with a - * bigger size to accomodate the requirements of the library. - */ -# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ - (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) - typedef DWORD png_alloc_size_t; -# else - typedef png_size_t png_alloc_size_t; -# endif -# endif -#endif - -#endif /* PNGCONF_H */ diff --git a/plugins/FreeImage/Source/LibPNG/pngdebug.h b/plugins/FreeImage/Source/LibPNG/pngdebug.h deleted file mode 100644 index 96c1ea42b3..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngdebug.h +++ /dev/null @@ -1,157 +0,0 @@ - -/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c - * - * 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.) - * - * Last changed in libpng 1.5.0 [January 6, 2011] - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -/* 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. - * - * png_debug[1-2]?(level, message ,arg{0-2}) - * Expands to a statement (either a simple expression or a compound - * do..while(0) statement) that outputs a message with parameter - * substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG - * is undefined, 0 or 1 every png_debug expands to a simple expression - * (actually ((void)0)). - * - * level: level of detail of message, starting at 0. A level 'n' - * message is preceded by 'n' tab characters (not implemented - * on Microsoft compilers unless PNG_DEBUG_FILE is also - * defined, to allow debug DLL compilation with no standard IO). - * message: a printf(3) style text string. A trailing '\n' is added - * to the message. - * arg: 0 to 2 arguments for printf(3) style substitution in message. - */ -#ifndef PNGDEBUG_H -#define PNGDEBUG_H -/* These settings control the formatting of messages in png.c and pngerror.c */ -/* Moved to pngdebug.h at 1.5.0 */ -# 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 -# ifndef PNG_STRING_NEWLINE -# define PNG_STRING_NEWLINE "\n" -# endif - -#ifdef PNG_DEBUG -# if (PNG_DEBUG > 0) -# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) -# include -# 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_STDIO_SUPPORTED -# include /* not included yet */ -# endif -# 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) \ - do { \ - 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":"")))); \ - } while (0) -# endif -# ifndef png_debug1 -# define png_debug1(l,m,p1) \ - do { \ - 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); \ - } while (0) -# endif -# ifndef png_debug2 -# define png_debug2(l,m,p1,p2) \ - do { \ - 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); \ - } while (0) -# endif -# else /* __STDC __ */ -# ifndef png_debug -# define png_debug(l,m) \ - do { \ - 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); \ - } while (0) -# endif -# ifndef png_debug1 -# define png_debug1(l,m,p1) \ - do { \ - 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); \ - } while (0) -# endif -# ifndef png_debug2 -# define png_debug2(l,m,p1,p2) \ - do { \ - 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); \ - } while (0) -# 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) ((void)0) -#endif -#ifndef png_debug1 -# define png_debug1(l, m, p1) ((void)0) -#endif -#ifndef png_debug2 -# define png_debug2(l, m, p1, p2) ((void)0) -#endif -#endif /* PNGDEBUG_H */ diff --git a/plugins/FreeImage/Source/LibPNG/pngerror.c b/plugins/FreeImage/Source/LibPNG/pngerror.c deleted file mode 100644 index 9df97f583c..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngerror.c +++ /dev/null @@ -1,685 +0,0 @@ - -/* pngerror.c - stub functions for i/o and memory allocation - * - * Last changed in libpng 1.5.8 [February 1, 2011] - * 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 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. - */ - -#include "pngpriv.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -static PNG_FUNCTION(void, 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 -PNG_FUNCTION(void,PNGAPI -png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) -{ -#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 -PNG_FUNCTION(void,PNGAPI -png_err,(png_structp png_ptr),PNG_NORETURN) -{ - /* Prior to 1.5.2 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 */ - -/* Utility to safely appends strings to a buffer. This never errors out so - * error checking is not required in the caller. - */ -size_t -png_safecat(png_charp buffer, size_t bufsize, size_t pos, - png_const_charp string) -{ - if (buffer != NULL && pos < bufsize) - { - if (string != NULL) - while (*string != '\0' && pos < bufsize-1) - buffer[pos++] = *string++; - - buffer[pos] = '\0'; - } - - return pos; -} - -#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) -/* Utility to dump an unsigned value into a buffer, given a start pointer and - * and end pointer (which should point just *beyond* the end of the buffer!) - * Returns the pointer to the start of the formatted string. - */ -png_charp -png_format_number(png_const_charp start, png_charp end, int format, - png_alloc_size_t number) -{ - int count = 0; /* number of digits output */ - int mincount = 1; /* minimum number required */ - int output = 0; /* digit output (for the fixed point format) */ - - *--end = '\0'; - - /* This is written so that the loop always runs at least once, even with - * number zero. - */ - while (end > start && (number != 0 || count < mincount)) - { - - static const char digits[] = "0123456789ABCDEF"; - - switch (format) - { - case PNG_NUMBER_FORMAT_fixed: - /* Needs five digits (the fraction) */ - mincount = 5; - if (output || number % 10 != 0) - { - *--end = digits[number % 10]; - output = 1; - } - number /= 10; - break; - - case PNG_NUMBER_FORMAT_02u: - /* Expects at least 2 digits. */ - mincount = 2; - /* fall through */ - - case PNG_NUMBER_FORMAT_u: - *--end = digits[number % 10]; - number /= 10; - break; - - case PNG_NUMBER_FORMAT_02x: - /* This format expects at least two digits */ - mincount = 2; - /* fall through */ - - case PNG_NUMBER_FORMAT_x: - *--end = digits[number & 0xf]; - number >>= 4; - break; - - default: /* an error */ - number = 0; - break; - } - - /* Keep track of the number of digits added */ - ++count; - - /* Float a fixed number here: */ - if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start) - { - /* End of the fraction, but maybe nothing was output? In that case - * drop the decimal point. If the number is a true zero handle that - * here. - */ - if (output) - *--end = '.'; - else if (number == 0) /* and !output */ - *--end = '0'; - } - } - - return end; -} -#endif - -#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); -} - -/* These functions support 'formatted' warning messages with up to - * PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter - * is introduced by @, where 'number' starts at 1. This follows the - * standard established by X/Open for internationalizable error messages. - */ -void -png_warning_parameter(png_warning_parameters p, int number, - png_const_charp string) -{ - if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) - (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); -} - -void -png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, - png_alloc_size_t value) -{ - char buffer[PNG_NUMBER_BUFFER_SIZE]; - png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); -} - -void -png_warning_parameter_signed(png_warning_parameters p, int number, int format, - png_int_32 value) -{ - png_alloc_size_t u; - png_charp str; - char buffer[PNG_NUMBER_BUFFER_SIZE]; - - /* Avoid overflow by doing the negate in a png_alloc_size_t: */ - u = (png_alloc_size_t)value; - if (value < 0) - u = ~u + 1; - - str = PNG_FORMAT_NUMBER(buffer, format, u); - - if (value < 0 && str > buffer) - *--str = '-'; - - png_warning_parameter(p, number, str); -} - -void -png_formatted_warning(png_structp png_ptr, png_warning_parameters p, - png_const_charp message) -{ - /* The internal buffer is just 192 bytes - enough for all our messages, - * overflow doesn't happen because this code checks! If someone figures - * out how to send us a message longer than 192 bytes, all that will - * happen is that the message will be truncated appropriately. - */ - size_t i = 0; /* Index in the msg[] buffer: */ - char msg[192]; - - /* Each iteration through the following loop writes at most one character - * to msg[i++] then returns here to validate that there is still space for - * the trailing '\0'. It may (in the case of a parameter) read more than - * one character from message[]; it must check for '\0' and continue to the - * test if it finds the end of string. - */ - while (i<(sizeof msg)-1 && *message != '\0') - { - /* '@' at end of string is now just printed (previously it was skipped); - * it is an error in the calling code to terminate the string with @. - */ - if (p != NULL && *message == '@' && message[1] != '\0') - { - int parameter_char = *++message; /* Consume the '@' */ - static const char valid_parameters[] = "123456789"; - int parameter = 0; - - /* Search for the parameter digit, the index in the string is the - * parameter to use. - */ - while (valid_parameters[parameter] != parameter_char && - valid_parameters[parameter] != '\0') - ++parameter; - - /* If the parameter digit is out of range it will just get printed. */ - if (parameter < PNG_WARNING_PARAMETER_COUNT) - { - /* Append this parameter */ - png_const_charp parm = p[parameter]; - png_const_charp pend = p[parameter] + (sizeof p[parameter]); - - /* No need to copy the trailing '\0' here, but there is no guarantee - * that parm[] has been initialized, so there is no guarantee of a - * trailing '\0': - */ - while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend) - msg[i++] = *parm++; - - /* Consume the parameter digit too: */ - ++message; - continue; - } - - /* else not a parameter and there is a character after the @ sign; just - * copy that. This is known not to be '\0' because of the test above. - */ - } - - /* At this point *message can't be '\0', even in the bad parameter case - * above where there is a lone '@' at the end of the message string. - */ - msg[i++] = *message++; - } - - /* i is always less than (sizeof msg), so: */ - msg[i] = '\0'; - - /* And this is the formatted message, it may be larger than - * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these are - * not (currently) formatted. - */ - png_warning(png_ptr, msg); -} -#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) -{ - png_uint_32 chunk_name = png_ptr->chunk_name; - int iout = 0, ishift = 24; - - while (ishift >= 0) - { - int c = (int)(chunk_name >> ishift) & 0xff; - - ishift -= 8; - 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++] = (char)c; - } - } - - if (error_message == NULL) - buffer[iout] = '\0'; - - else - { - int iin = 0; - - buffer[iout++] = ':'; - buffer[iout++] = ' '; - - 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'; - } -} -#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ - -#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) -PNG_FUNCTION(void,PNGAPI -png_chunk_error,(png_structp png_ptr, png_const_charp error_message), - PNG_NORETURN) -{ - 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 && 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 */ - -#ifdef PNG_ERROR_TEXT_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_FUNCTION(void, -png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN) -{ -# define fixed_message "fixed point overflow in " -# define fixed_message_ln ((sizeof fixed_message)-1) - int iin; - char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; - png_memcpy(msg, fixed_message, fixed_message_ln); - iin = 0; - if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) - { - msg[fixed_message_ln + iin] = name[iin]; - ++iin; - } - msg[fixed_message_ln + iin] = 0; - png_error(png_ptr, msg); -} -#endif -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This API only exists if ANSI-C style error handling is used, - * otherwise it is necessary for png_default_error to be overridden. - */ -jmp_buf* PNGAPI -png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn, - size_t jmp_buf_size) -{ - if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf)) - return NULL; - - png_ptr->longjmp_fn = longjmp_fn; - return &png_ptr->longjmp_buffer; -} -#endif - -/* 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 PNG_FUNCTION(void /* PRIVATE */, -png_default_error,(png_structp png_ptr, png_const_charp error_message), - PNG_NORETURN) -{ -#ifdef PNG_CONSOLE_IO_SUPPORTED -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - /* Check on NULL only added in 1.5.4 */ - if (error_message != NULL && *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 ? error_message : - "undefined"); - fprintf(stderr, PNG_STRING_NEWLINE); - } -#else - PNG_UNUSED(error_message) /* Make compiler happy */ -#endif - png_longjmp(png_ptr, 1); -} - -PNG_FUNCTION(void,PNGAPI -png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN) -{ -#ifdef PNG_SETJMP_SUPPORTED - if (png_ptr && png_ptr->longjmp_fn) - { -# ifdef USE_FAR_KEYWORD - { - jmp_buf tmp_jmpbuf; - png_memcpy(tmp_jmpbuf, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); - png_ptr->longjmp_fn(tmp_jmpbuf, val); - } - -# else - png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val); -# endif - } -#endif - /* Here if not setjmp support or if png_ptr is null. */ - PNG_ABORT(); -} - -#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 - PNG_UNUSED(warning_message) /* Make compiler happy */ -#endif - PNG_UNUSED(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->longjmp_buffer, 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; -#ifdef PNG_WARNINGS_SUPPORTED - png_ptr->warning_fn = warning_fn; -#else - PNG_UNUSED(warning_fn) -#endif -} - - -/* 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_const_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/plugins/FreeImage/Source/LibPNG/pngget.c b/plugins/FreeImage/Source/LibPNG/pngget.c deleted file mode 100644 index 1889e9903e..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngget.c +++ /dev/null @@ -1,1124 +0,0 @@ - -/* pngget.c - retrieval of values from info struct - * - * Last changed in libpng 1.5.7 [December 15, 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 - * - */ - -#include "pngpriv.h" - -#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) - -png_uint_32 PNGAPI -png_get_valid(png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_32 flag) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->valid & flag); - - return(0); -} - -png_size_t PNGAPI -png_get_rowbytes(png_const_structp png_ptr, png_const_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->rowbytes); - - return(0); -} - -#ifdef PNG_INFO_IMAGE_SUPPORTED -png_bytepp PNGAPI -png_get_rows(png_const_structp png_ptr, png_const_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->row_pointers); - - 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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return info_ptr->height; - - return (0); -} - -png_byte PNGAPI -png_get_bit_depth(png_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_infop info_ptr) -{ -#ifdef PNG_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->x_pixels_per_unit); - } -#endif - - return (0); -} - -png_uint_32 PNGAPI -png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) -{ -#ifdef PNG_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->y_pixels_per_unit); - } -#endif - - return (0); -} - -png_uint_32 PNGAPI -png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) -{ -#ifdef PNG_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->x_pixels_per_unit); - } -#endif - - return (0); -} - -#ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr) -{ -#ifdef PNG_READ_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (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)((float)info_ptr->y_pixels_per_unit - /(float)info_ptr->x_pixels_per_unit)); - } -#endif - - return ((float)0.0); -} -#endif - -#ifdef PNG_FIXED_POINT_SUPPORTED -png_fixed_point PNGAPI -png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr, - png_const_infop info_ptr) -{ -#ifdef PNG_READ_pHYs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) - && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 - && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX - && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX) - { - png_fixed_point res; - - png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); - - /* The following casts work because a PNG 4 byte integer only has a valid - * range of 0..2^31-1; otherwise the cast might overflow. - */ - if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1, - (png_int_32)info_ptr->x_pixels_per_unit)) - return res; - } -#endif - - return 0; -} -#endif - -png_int_32 PNGAPI -png_get_x_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) -{ -#ifdef PNG_oFFs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->x_offset); - } -#endif - - return (0); -} - -png_int_32 PNGAPI -png_get_y_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) -{ -#ifdef PNG_oFFs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->y_offset); - } -#endif - - return (0); -} - -png_int_32 PNGAPI -png_get_x_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) -{ -#ifdef PNG_oFFs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) - { - png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); - - if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) - return (info_ptr->x_offset); - } -#endif - - return (0); -} - -png_int_32 PNGAPI -png_get_y_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) -{ -#ifdef PNG_oFFs_SUPPORTED - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) - { - png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); - - if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) - return (info_ptr->y_offset); - } -#endif - - return (0); -} - -#ifdef PNG_INCH_CONVERSIONS_SUPPORTED -static png_uint_32 -ppi_from_ppm(png_uint_32 ppm) -{ -#if 0 - /* The conversion is *(2.54/100), in binary (32 digits): - * .00000110100000001001110101001001 - */ - png_uint_32 t1001, t1101; - ppm >>= 1; /* .1 */ - t1001 = ppm + (ppm >> 3); /* .1001 */ - t1101 = t1001 + (ppm >> 1); /* .1101 */ - ppm >>= 20; /* .000000000000000000001 */ - t1101 += t1101 >> 15; /* .1101000000000001101 */ - t1001 >>= 11; /* .000000000001001 */ - t1001 += t1001 >> 12; /* .000000000001001000000001001 */ - ppm += t1001; /* .000000000001001000001001001 */ - ppm += t1101; /* .110100000001001110101001001 */ - return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */ -#else - /* The argument is a PNG unsigned integer, so it is not permitted - * to be bigger than 2^31. - */ - png_fixed_point result; - if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, - 5000)) - return result; - - /* Overflow. */ - return 0; -#endif -} - -png_uint_32 PNGAPI -png_get_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) -{ - return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr)); -} - -png_uint_32 PNGAPI -png_get_x_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) -{ - return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr)); -} - -png_uint_32 PNGAPI -png_get_y_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) -{ - return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr)); -} - -#ifdef PNG_FIXED_POINT_SUPPORTED -static png_fixed_point -png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns) -{ - /* Convert from metres * 1,000,000 to inches * 100,000, meters to - * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. - * Notice that this can overflow - a warning is output and 0 is - * returned. - */ - return png_muldiv_warn(png_ptr, microns, 500, 127); -} - -png_fixed_point PNGAPI -png_get_x_offset_inches_fixed(png_structp png_ptr, - png_const_infop info_ptr) -{ - return png_fixed_inches_from_microns(png_ptr, - png_get_x_offset_microns(png_ptr, info_ptr)); -} -#endif - -#ifdef PNG_FIXED_POINT_SUPPORTED -png_fixed_point PNGAPI -png_get_y_offset_inches_fixed(png_structp png_ptr, - png_const_infop info_ptr) -{ - return png_fixed_inches_from_microns(png_ptr, - png_get_y_offset_microns(png_ptr, info_ptr)); -} -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_x_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) -{ - /* To avoid the overflow do the conversion directly in floating - * point. - */ - return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937); -} -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_y_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) -{ - /* To avoid the overflow do the conversion directly in floating - * point. - */ - return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937); -} -#endif - -#ifdef PNG_pHYs_SUPPORTED -png_uint_32 PNGAPI -png_get_pHYs_dpi(png_const_structp png_ptr, png_const_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_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_const_structp png_ptr, png_const_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->channels); - - return (0); -} - -png_const_bytep PNGAPI -png_get_signature(png_const_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->signature); - - return (NULL); -} - -#ifdef PNG_bKGD_SUPPORTED -png_uint_32 PNGAPI -png_get_bKGD(png_const_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 -/* The XYZ APIs were added in 1.5.5 to take advantage of the code added at the - * same time to correct the rgb grayscale coefficient defaults obtained from the - * cHRM chunk in 1.5.4 - */ -png_uint_32 PNGFAPI -png_get_cHRM_XYZ_fixed(png_structp png_ptr, png_const_infop info_ptr, - png_fixed_point *int_red_X, png_fixed_point *int_red_Y, - png_fixed_point *int_red_Z, png_fixed_point *int_green_X, - png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, - png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, - png_fixed_point *int_blue_Z) -{ - if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - { - png_xy xy; - png_XYZ XYZ; - - png_debug1(1, "in %s retrieval function", "cHRM_XYZ"); - - xy.whitex = info_ptr->x_white; - xy.whitey = info_ptr->y_white; - xy.redx = info_ptr->x_red; - xy.redy = info_ptr->y_red; - xy.greenx = info_ptr->x_green; - xy.greeny = info_ptr->y_green; - xy.bluex = info_ptr->x_blue; - xy.bluey = info_ptr->y_blue; - - /* The *_checked function handles error reporting, so just return 0 if - * there is a failure here. - */ - if (png_XYZ_from_xy_checked(png_ptr, &XYZ, xy)) - { - if (int_red_X != NULL) - *int_red_X = XYZ.redX; - if (int_red_Y != NULL) - *int_red_Y = XYZ.redY; - if (int_red_Z != NULL) - *int_red_Z = XYZ.redZ; - if (int_green_X != NULL) - *int_green_X = XYZ.greenX; - if (int_green_Y != NULL) - *int_green_Y = XYZ.greenY; - if (int_green_Z != NULL) - *int_green_Z = XYZ.greenZ; - if (int_blue_X != NULL) - *int_blue_X = XYZ.blueX; - if (int_blue_Y != NULL) - *int_blue_Y = XYZ.blueY; - if (int_blue_Z != NULL) - *int_blue_Z = XYZ.blueZ; - - return (PNG_INFO_cHRM); - } - } - - return (0); -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM(png_const_structp png_ptr, png_const_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 = png_float(png_ptr, info_ptr->x_white, "cHRM white X"); - if (white_y != NULL) - *white_y = png_float(png_ptr, info_ptr->y_white, "cHRM white Y"); - if (red_x != NULL) - *red_x = png_float(png_ptr, info_ptr->x_red, "cHRM red X"); - if (red_y != NULL) - *red_y = png_float(png_ptr, info_ptr->y_red, "cHRM red Y"); - if (green_x != NULL) - *green_x = png_float(png_ptr, info_ptr->x_green, "cHRM green X"); - if (green_y != NULL) - *green_y = png_float(png_ptr, info_ptr->y_green, "cHRM green Y"); - if (blue_x != NULL) - *blue_x = png_float(png_ptr, info_ptr->x_blue, "cHRM blue X"); - if (blue_y != NULL) - *blue_y = png_float(png_ptr, info_ptr->y_blue, "cHRM blue Y"); - return (PNG_INFO_cHRM); - } - - return (0); -} - -png_uint_32 PNGAPI -png_get_cHRM_XYZ(png_structp png_ptr, png_const_infop info_ptr, - double *red_X, double *red_Y, double *red_Z, double *green_X, - double *green_Y, double *green_Z, double *blue_X, double *blue_Y, - double *blue_Z) -{ - png_XYZ XYZ; - - if (png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, - &XYZ.redX, &XYZ.redY, &XYZ.redZ, &XYZ.greenX, &XYZ.greenY, &XYZ.greenZ, - &XYZ.blueX, &XYZ.blueY, &XYZ.blueZ) & PNG_INFO_cHRM) - { - if (red_X != NULL) - *red_X = png_float(png_ptr, XYZ.redX, "cHRM red X"); - if (red_Y != NULL) - *red_Y = png_float(png_ptr, XYZ.redY, "cHRM red Y"); - if (red_Z != NULL) - *red_Z = png_float(png_ptr, XYZ.redZ, "cHRM red Z"); - if (green_X != NULL) - *green_X = png_float(png_ptr, XYZ.greenX, "cHRM green X"); - if (green_Y != NULL) - *green_Y = png_float(png_ptr, XYZ.greenY, "cHRM green Y"); - if (green_Z != NULL) - *green_Z = png_float(png_ptr, XYZ.greenZ, "cHRM green Z"); - if (blue_X != NULL) - *blue_X = png_float(png_ptr, XYZ.blueX, "cHRM blue X"); - if (blue_Y != NULL) - *blue_Y = png_float(png_ptr, XYZ.blueY, "cHRM blue Y"); - if (blue_Z != NULL) - *blue_Z = png_float(png_ptr, XYZ.blueZ, "cHRM blue Z"); - return (PNG_INFO_cHRM); - } - - return (0); -} -# endif - -# ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM_fixed(png_const_structp png_ptr, png_const_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->x_white; - if (white_y != NULL) - *white_y = info_ptr->y_white; - if (red_x != NULL) - *red_x = info_ptr->x_red; - if (red_y != NULL) - *red_y = info_ptr->y_red; - if (green_x != NULL) - *green_x = info_ptr->x_green; - if (green_y != NULL) - *green_y = info_ptr->y_green; - if (blue_x != NULL) - *blue_x = info_ptr->x_blue; - if (blue_y != NULL) - *blue_y = info_ptr->y_blue; - return (PNG_INFO_cHRM); - } - - return (0); -} -# endif -#endif - -#ifdef PNG_gAMA_SUPPORTED -png_uint_32 PNGFAPI -png_get_gAMA_fixed(png_const_structp png_ptr, png_const_infop info_ptr, - png_fixed_point *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 = info_ptr->gamma; - return (PNG_INFO_gAMA); - } - - return (0); -} -# ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_gAMA(png_const_structp png_ptr, png_const_infop info_ptr, - double *file_gamma) -{ - png_fixed_point igamma; - png_uint_32 ok = png_get_gAMA_fixed(png_ptr, info_ptr, &igamma); - - if (ok) - *file_gamma = png_float(png_ptr, igamma, "png_get_gAMA"); - - return ok; -} - -# endif -#endif - -#ifdef PNG_sRGB_SUPPORTED -png_uint_32 PNGAPI -png_get_sRGB(png_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_infop info_ptr, - png_charpp name, int *compression_type, - png_bytepp 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 && compression_type != 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 = info_ptr->iccp_proflen; - *compression_type = info_ptr->iccp_compression; - return (PNG_INFO_iCCP); - } - - return (0); -} -#endif - -#ifdef PNG_sPLT_SUPPORTED -png_uint_32 PNGAPI -png_get_sPLT(png_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_FIXED_POINT_SUPPORTED -# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED -png_uint_32 PNGAPI -png_get_sCAL_fixed(png_structp png_ptr, png_const_infop info_ptr, - int *unit, png_fixed_point *width, png_fixed_point *height) -{ - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sCAL)) - { - *unit = info_ptr->scal_unit; - /*TODO: make this work without FP support */ - *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); - *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), - "sCAL height"); - return (PNG_INFO_sCAL); - } - - return(0); -} -# endif /* FLOATING_ARITHMETIC */ -# endif /* FIXED_POINT */ -# ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_sCAL(png_const_structp png_ptr, png_const_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 = atof(info_ptr->scal_s_width); - *height = atof(info_ptr->scal_s_height); - return (PNG_INFO_sCAL); - } - - return(0); -} -# endif /* FLOATING POINT */ -png_uint_32 PNGAPI -png_get_sCAL_s(png_const_structp png_ptr, png_const_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 /* sCAL */ - -#ifdef PNG_pHYs_SUPPORTED -png_uint_32 PNGAPI -png_get_pHYs(png_const_structp png_ptr, png_const_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 /* pHYs */ - -png_uint_32 PNGAPI -png_get_PLTE(png_const_structp png_ptr, png_const_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_const_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_const_structp png_ptr, png_const_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 0x%lx retrieval function", - (unsigned long)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_const_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_const_structp png_ptr, png_infop info_ptr, - png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) -{ - 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_alpha != NULL) - { - *trans_alpha = info_ptr->trans_alpha; - retval |= PNG_INFO_tRNS; - } - - if (trans_color != NULL) - *trans_color = &(info_ptr->trans_color); - } - - else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ - { - if (trans_color != NULL) - { - *trans_color = &(info_ptr->trans_color); - retval |= PNG_INFO_tRNS; - } - - if (trans_alpha != NULL) - *trans_alpha = NULL; - } - - if (num_trans != NULL) - { - *num_trans = info_ptr->num_trans; - retval |= PNG_INFO_tRNS; - } - } - - return (retval); -} -#endif - -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -int PNGAPI -png_get_unknown_chunks(png_const_structp png_ptr, png_const_infop info_ptr, - png_unknown_chunkpp unknowns) -{ - if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) - { - *unknowns = info_ptr->unknown_chunks; - return 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_const_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_const_structp png_ptr) -{ - return (png_ptr ? png_ptr->user_chunk_ptr : NULL); -} -#endif - -png_size_t PNGAPI -png_get_compression_buffer_size(png_const_structp png_ptr) -{ - return (png_ptr ? png_ptr->zbuf_size : 0); -} - -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -/* These functions were added to libpng 1.2.6 and were enabled - * by default in libpng-1.4.0 */ -png_uint_32 PNGAPI -png_get_user_width_max (png_const_structp png_ptr) -{ - return (png_ptr ? png_ptr->user_width_max : 0); -} - -png_uint_32 PNGAPI -png_get_user_height_max (png_const_structp png_ptr) -{ - return (png_ptr ? png_ptr->user_height_max : 0); -} - -/* This function was added to libpng 1.4.0 */ -png_uint_32 PNGAPI -png_get_chunk_cache_max (png_const_structp png_ptr) -{ - return (png_ptr ? png_ptr->user_chunk_cache_max : 0); -} - -/* This function was added to libpng 1.4.1 */ -png_alloc_size_t PNGAPI -png_get_chunk_malloc_max (png_const_structp png_ptr) -{ - return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); -} -#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ - -/* These functions were added to libpng 1.4.0 */ -#ifdef PNG_IO_STATE_SUPPORTED -png_uint_32 PNGAPI -png_get_io_state (png_structp png_ptr) -{ - return png_ptr->io_state; -} - -png_uint_32 PNGAPI -png_get_io_chunk_type (png_const_structp png_ptr) -{ - return png_ptr->chunk_name; -} - -png_const_bytep PNGAPI -png_get_io_chunk_name (png_structp png_ptr) -{ - PNG_CSTRING_FROM_CHUNK(png_ptr->io_chunk_string, png_ptr->chunk_name); - return png_ptr->io_chunk_string; -} -#endif /* ?PNG_IO_STATE_SUPPORTED */ - -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibPNG/pnginfo.h b/plugins/FreeImage/Source/LibPNG/pnginfo.h deleted file mode 100644 index bbfb105aaf..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pnginfo.h +++ /dev/null @@ -1,269 +0,0 @@ - -/* pnginfo.h - header file for PNG reference library - * - * 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.) - * - * Last changed in libpng 1.5.0 [January 6, 2011] - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - - /* 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, using png_set_*() functions, 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 libpng-1.5.0 this was moved into a separate private - * file that is not visible to applications. - * - * 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. - */ -#ifndef PNGINFO_H -#define PNGINFO_H - -struct png_info_def -{ - /* the following are necessary for every PNG file */ - png_uint_32 width; /* width of image in pixels (from IHDR) */ - png_uint_32 height; /* height of image in pixels (from IHDR) */ - png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ - png_size_t rowbytes; /* bytes needed to hold an untransformed row */ - png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ - png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ - png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ - png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ - png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ - /* The following three should have been named *_method not *_type */ - png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ - png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ - png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - - /* The following is informational only on read, and not used on writes. */ - png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte spare_byte; /* to align the data, and for future use */ - png_byte signature[8]; /* 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) - /* 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. - */ - png_fixed_point gamma; -#endif - -#ifdef PNG_sRGB_SUPPORTED - /* GR-P, 0.96a */ - /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ - png_byte srgb_intent; /* 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; /* number of comments read or comments to write */ - int max_text; /* current size of text array */ - png_textp text; /* array of comments read or comments 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; -#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; /* 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_alpha; /* alpha values for paletted image */ - png_color_16 trans_color; /* 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; -#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; /* x offset on page */ - png_int_32 y_offset; /* y offset on page */ - png_byte offset_unit_type; /* 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; /* horizontal pixel density */ - png_uint_32 y_pixels_per_unit; /* vertical pixel density */ - png_byte phys_unit_type; /* 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; -#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. - */ - png_fixed_point x_white; - png_fixed_point y_white; - png_fixed_point x_red; - png_fixed_point y_red; - png_fixed_point x_green; - png_fixed_point y_green; - png_fixed_point x_blue; - png_fixed_point y_blue; -#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; /* pCAL chunk description string */ - png_int_32 pcal_X0; /* minimum value */ - png_int_32 pcal_X1; /* maximum value */ - png_charp pcal_units; /* Latin-1 string giving physical units */ - png_charpp pcal_params; /* ASCII strings containing parameter values */ - png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ - png_byte pcal_nparams; /* number of parameters given in pcal_params */ -#endif - -/* New members added in libpng-1.0.6 */ - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ - -#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; - int unknown_chunks_num; -#endif - -#ifdef PNG_iCCP_SUPPORTED - /* iCCP chunk data. */ - png_charp iccp_name; /* profile name */ - png_bytep iccp_profile; /* International Color Consortium profile data */ - png_uint_32 iccp_proflen; /* ICC profile data length */ - png_byte iccp_compression; /* Always zero */ -#endif - -#ifdef PNG_sPLT_SUPPORTED - /* Data on sPLT chunks (there may be more than one). */ - png_sPLT_tp splt_palettes; - png_uint_32 splt_palettes_num; -#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. Data values are valid if (valid & PNG_INFO_sCAL) is - * non-zero. - */ - png_byte scal_unit; /* unit of physical scale */ - png_charp scal_s_width; /* string containing height */ - png_charp scal_s_height; /* string containing width */ -#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; /* the image bits */ -#endif - -}; -#endif /* PNGINFO_H */ diff --git a/plugins/FreeImage/Source/LibPNG/pnglibconf.h b/plugins/FreeImage/Source/LibPNG/pnglibconf.h deleted file mode 100644 index 8022a5a881..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pnglibconf.h +++ /dev/null @@ -1,187 +0,0 @@ - -/* libpng STANDARD API DEFINITION */ - -/* pnglibconf.h - library build configuration */ - -/* libpng version 1.5.4 - last changed on June 22, 2011 */ - -/* Copyright (c) 1998-2011 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 */ - -/* pnglibconf.h */ -/* Derived from: scripts/pnglibconf.dfa */ -/* If you edit this file by hand you must obey the rules expressed in */ -/* pnglibconf.dfa with respect to the dependencies between the following */ -/* symbols. It is much better to generate a new file using */ -/* scripts/libpngconf.mak */ - -#ifndef PNGLCONF_H -#define PNGLCONF_H -/* settings */ -#define PNG_API_RULE 0 -#define PNG_CALLOC_SUPPORTED -#define PNG_COST_SHIFT 3 -#define PNG_DEFAULT_READ_MACROS 1 -#define PNG_GAMMA_THRESHOLD_FIXED 5000 -#define PNG_MAX_GAMMA_8 11 -#define PNG_QUANTIZE_BLUE_BITS 5 -#define PNG_QUANTIZE_GREEN_BITS 5 -#define PNG_QUANTIZE_RED_BITS 5 -#define PNG_sCAL_PRECISION 5 -#define PNG_USER_CHUNK_CACHE_MAX 0 -#define PNG_USER_CHUNK_MALLOC_MAX 0 -#define PNG_USER_HEIGHT_MAX 1000000 -#define PNG_USER_WIDTH_MAX 1000000 -#define PNG_WEIGHT_SHIFT 8 -#define PNG_ZBUF_SIZE 8192 -/* end of settings */ -/* options */ -#define PNG_16BIT_SUPPORTED -#define PNG_ALIGN_MEMORY_SUPPORTED -#define PNG_BENIGN_ERRORS_SUPPORTED -#define PNG_bKGD_SUPPORTED -#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -#define PNG_CHECK_cHRM_SUPPORTED -#define PNG_cHRM_SUPPORTED -#define PNG_CONSOLE_IO_SUPPORTED -#define PNG_CONVERT_tIME_SUPPORTED -#define PNG_EASY_ACCESS_SUPPORTED -/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ -#define PNG_ERROR_TEXT_SUPPORTED -#define PNG_FIXED_POINT_SUPPORTED -#define PNG_FLOATING_ARITHMETIC_SUPPORTED -#define PNG_FLOATING_POINT_SUPPORTED -#define PNG_gAMA_SUPPORTED -#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -#define PNG_hIST_SUPPORTED -#define PNG_iCCP_SUPPORTED -#define PNG_INCH_CONVERSIONS_SUPPORTED -#define PNG_INFO_IMAGE_SUPPORTED -#define PNG_IO_STATE_SUPPORTED -#define PNG_iTXt_SUPPORTED -#define PNG_MNG_FEATURES_SUPPORTED -#define PNG_oFFs_SUPPORTED -#define PNG_pCAL_SUPPORTED -#define PNG_pHYs_SUPPORTED -#define PNG_POINTER_INDEXING_SUPPORTED -#define PNG_PROGRESSIVE_READ_SUPPORTED -#define PNG_READ_16BIT_SUPPORTED -#define PNG_READ_ALPHA_MODE_SUPPORTED -#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_READ_BACKGROUND_SUPPORTED -#define PNG_READ_BGR_SUPPORTED -#define PNG_READ_bKGD_SUPPORTED -#define PNG_READ_cHRM_SUPPORTED -#define PNG_READ_COMPOSITE_NODIV_SUPPORTED -#define PNG_READ_COMPRESSED_TEXT_SUPPORTED -#define PNG_READ_EXPAND_16_SUPPORTED -#define PNG_READ_EXPAND_SUPPORTED -#define PNG_READ_FILLER_SUPPORTED -#define PNG_READ_gAMA_SUPPORTED -#define PNG_READ_GAMMA_SUPPORTED -#define PNG_READ_GRAY_TO_RGB_SUPPORTED -#define PNG_READ_hIST_SUPPORTED -#define PNG_READ_iCCP_SUPPORTED -#define PNG_READ_INTERLACING_SUPPORTED -#define PNG_READ_INT_FUNCTIONS_SUPPORTED -#define PNG_READ_INVERT_ALPHA_SUPPORTED -#define PNG_READ_INVERT_SUPPORTED -#define PNG_READ_iTXt_SUPPORTED -#define PNG_READ_oFFs_SUPPORTED -#define PNG_READ_OPT_PLTE_SUPPORTED -#define PNG_READ_PACK_SUPPORTED -#define PNG_READ_PACKSWAP_SUPPORTED -#define PNG_READ_pCAL_SUPPORTED -#define PNG_READ_pHYs_SUPPORTED -#define PNG_READ_QUANTIZE_SUPPORTED -#define PNG_READ_RGB_TO_GRAY_SUPPORTED -#define PNG_READ_sBIT_SUPPORTED -#define PNG_READ_SCALE_16_TO_8_SUPPORTED -#define PNG_READ_sCAL_SUPPORTED -#define PNG_READ_SHIFT_SUPPORTED -#define PNG_READ_sPLT_SUPPORTED -#define PNG_READ_sRGB_SUPPORTED -#define PNG_READ_STRIP_16_TO_8_SUPPORTED -#define PNG_READ_STRIP_ALPHA_SUPPORTED -#define PNG_READ_SUPPORTED -#define PNG_READ_SWAP_ALPHA_SUPPORTED -#define PNG_READ_SWAP_SUPPORTED -#define PNG_READ_tEXt_SUPPORTED -#define PNG_READ_TEXT_SUPPORTED -#define PNG_READ_tIME_SUPPORTED -#define PNG_READ_TRANSFORMS_SUPPORTED -#define PNG_READ_tRNS_SUPPORTED -#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_READ_USER_CHUNKS_SUPPORTED -#define PNG_READ_USER_TRANSFORM_SUPPORTED -#define PNG_READ_zTXt_SUPPORTED -#define PNG_SAVE_INT_32_SUPPORTED -#define PNG_sBIT_SUPPORTED -#define PNG_sCAL_SUPPORTED -#define PNG_SEQUENTIAL_READ_SUPPORTED -#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -#define PNG_SETJMP_SUPPORTED -#define PNG_SET_USER_LIMITS_SUPPORTED -#define PNG_sPLT_SUPPORTED -#define PNG_sRGB_SUPPORTED -#define PNG_STDIO_SUPPORTED -#define PNG_tEXt_SUPPORTED -#define PNG_TEXT_SUPPORTED -#define PNG_TIME_RFC1123_SUPPORTED -#define PNG_tIME_SUPPORTED -#define PNG_tRNS_SUPPORTED -#define PNG_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_USER_CHUNKS_SUPPORTED -#define PNG_USER_LIMITS_SUPPORTED -#define PNG_USER_MEM_SUPPORTED -#define PNG_USER_TRANSFORM_INFO_SUPPORTED -#define PNG_USER_TRANSFORM_PTR_SUPPORTED -#define PNG_WARNINGS_SUPPORTED -#define PNG_WRITE_16BIT_SUPPORTED -#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_WRITE_BGR_SUPPORTED -#define PNG_WRITE_bKGD_SUPPORTED -#define PNG_WRITE_cHRM_SUPPORTED -#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED -#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -#define PNG_WRITE_FILLER_SUPPORTED -#define PNG_WRITE_FILTER_SUPPORTED -#define PNG_WRITE_FLUSH_SUPPORTED -#define PNG_WRITE_gAMA_SUPPORTED -#define PNG_WRITE_hIST_SUPPORTED -#define PNG_WRITE_iCCP_SUPPORTED -#define PNG_WRITE_INTERLACING_SUPPORTED -#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED -#define PNG_WRITE_INVERT_ALPHA_SUPPORTED -#define PNG_WRITE_INVERT_SUPPORTED -#define PNG_WRITE_iTXt_SUPPORTED -#define PNG_WRITE_oFFs_SUPPORTED -#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED -#define PNG_WRITE_PACK_SUPPORTED -#define PNG_WRITE_PACKSWAP_SUPPORTED -#define PNG_WRITE_pCAL_SUPPORTED -#define PNG_WRITE_pHYs_SUPPORTED -#define PNG_WRITE_sBIT_SUPPORTED -#define PNG_WRITE_sCAL_SUPPORTED -#define PNG_WRITE_SHIFT_SUPPORTED -#define PNG_WRITE_sPLT_SUPPORTED -#define PNG_WRITE_sRGB_SUPPORTED -#define PNG_WRITE_SUPPORTED -#define PNG_WRITE_SWAP_ALPHA_SUPPORTED -#define PNG_WRITE_SWAP_SUPPORTED -#define PNG_WRITE_tEXt_SUPPORTED -#define PNG_WRITE_TEXT_SUPPORTED -#define PNG_WRITE_tIME_SUPPORTED -#define PNG_WRITE_TRANSFORMS_SUPPORTED -#define PNG_WRITE_tRNS_SUPPORTED -#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_WRITE_USER_TRANSFORM_SUPPORTED -#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#define PNG_WRITE_zTXt_SUPPORTED -#define PNG_zTXt_SUPPORTED -/* end of options */ -#endif /* PNGLCONF_H */ diff --git a/plugins/FreeImage/Source/LibPNG/pngmem.c b/plugins/FreeImage/Source/LibPNG/pngmem.c deleted file mode 100644 index 25b5c73546..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngmem.c +++ /dev/null @@ -1,667 +0,0 @@ - -/* pngmem.c - stub functions for memory allocation - * - * Last changed in libpng 1.5.7 [December 15, 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 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. - */ - -#include "pngpriv.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_FUNCTION(png_voidp /* PRIVATE */, -png_create_struct,(int type),PNG_ALLOCATED) -{ -# ifdef PNG_USER_MEM_SUPPORTED - return (png_create_struct_2(type, NULL, NULL)); -} - -/* Alternate version of png_create_struct, for use with user-defined malloc. */ -PNG_FUNCTION(png_voidp /* PRIVATE */, -png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), - PNG_ALLOCATED) -{ -# 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; - memset(&dummy_struct, 0, sizeof dummy_struct); - dummy_struct.mem_ptr=mem_ptr; - struct_ptr = (*(malloc_fn))(&dummy_struct, (png_alloc_size_t)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, NULL, 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; - memset(&dummy_struct, 0, sizeof dummy_struct); - dummy_struct.mem_ptr=mem_ptr; - (*(free_fn))(&dummy_struct, 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_FUNCTION(png_voidp,PNGAPI -png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) -{ - png_voidp ret; - - ret = (png_malloc(png_ptr, size)); - - if (ret != NULL) - png_memset(ret,0,(png_size_t)size); - - return (ret); -} - -PNG_FUNCTION(png_voidp,PNGAPI -png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) -{ - 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, 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_FUNCTION(png_voidp,PNGAPI -png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) -{ - 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, mem_level, window_bits; - png_byte huge * hptr; - int window_bits - - if (ret != NULL) - { - farfree(ret); - ret = NULL; - } - - window_bits = - png_ptr->zlib_window_bits >= png_ptr->zlib_text_window_bits ? - png_ptr->zlib_window_bits : png_ptr->zlib_text_window_bits; - - if (window_bits > 14) - num_blocks = (int)(1 << (window_bits - 14)); - - else - num_blocks = 1; - - mem_level = - png_ptr->zlib_mem_level >= png_ptr->zlib_text_mem_level ? - png_ptr->zlib_mem_level : png_ptr->zlib_text_mem_level; - - if (mem_level >= 7) - num_blocks += (int)(1 << (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_FUNCTION(png_voidp /* PRIVATE */, -png_create_struct,(int type),PNG_ALLOCATED) -{ -# ifdef PNG_USER_MEM_SUPPORTED - return (png_create_struct_2(type, NULL, 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_FUNCTION(png_voidp /* PRIVATE */, -png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), - PNG_ALLOCATED) -{ -# 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, NULL, 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_FUNCTION(png_voidp,PNGAPI -png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) -{ - png_voidp ret; - - ret = (png_malloc(png_ptr, size)); - - if (ret != NULL) - png_memset(ret,0,(png_size_t)size); - - return (ret); -} - -PNG_FUNCTION(png_voidp,PNGAPI -png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) -{ - 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_FUNCTION(png_voidp,PNGAPI -png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) -{ - 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 */ - -/* 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_FUNCTION(png_voidp,PNGAPI -png_malloc_warn,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) -{ - 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); -} - - -#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_const_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/plugins/FreeImage/Source/LibPNG/pngpread.c b/plugins/FreeImage/Source/LibPNG/pngpread.c deleted file mode 100644 index eda5a6c80f..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngpread.c +++ /dev/null @@ -1,1843 +0,0 @@ - -/* pngpread.c - read a png file in push mode - * - * Last changed in libpng 1.5.9 [February 18, 2012] - * 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 - */ - -#include "pngpriv.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); - } -} - -png_size_t PNGAPI -png_process_data_pause(png_structp png_ptr, int save) -{ - if (png_ptr != NULL) - { - /* It's easiest for the caller if we do the save, then the caller doesn't - * have to supply the same data again: - */ - if (save) - png_push_save_buffer(png_ptr); - else - { - /* This includes any pending saved bytes: */ - png_size_t remaining = png_ptr->buffer_size; - png_ptr->buffer_size = 0; - - /* So subtract the saved buffer size, unless all the data - * is actually 'saved', in which case we just return 0 - */ - if (png_ptr->save_buffer_size < remaining) - return remaining - png_ptr->save_buffer_size; - } - } - - return 0; -} - -png_uint_32 PNGAPI -png_process_data_skip(png_structp png_ptr) -{ - png_uint_32 remaining = 0; - - if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE && - png_ptr->skip_length > 0) - { - /* At the end of png_process_data the buffer size must be 0 (see the loop - * above) so we can detect a broken call here: - */ - if (png_ptr->buffer_size != 0) - png_error(png_ptr, - "png_process_data_skip called inside png_process_data"); - - /* If is impossible for there to be a saved buffer at this point - - * otherwise we could not be in SKIP mode. This will also happen if - * png_process_skip is called inside png_process_data (but only very - * rarely.) - */ - if (png_ptr->save_buffer_size != 0) - png_error(png_ptr, "png_process_data_skip called with saved data"); - - remaining = png_ptr->skip_length; - png_ptr->skip_length = 0; - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } - - return remaining; -} - -/* 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; - } - -#ifdef PNG_READ_tEXt_SUPPORTED - case PNG_READ_tEXt_MODE: - { - png_push_read_tEXt(png_ptr, info_ptr); - break; - } - -#endif -#ifdef PNG_READ_zTXt_SUPPORTED - case PNG_READ_zTXt_MODE: - { - png_push_read_zTXt(png_ptr, info_ptr); - break; - } - -#endif -#ifdef PNG_READ_iTXt_SUPPORTED - case PNG_READ_iTXt_MODE: - { - png_push_read_iTXt(png_ptr, info_ptr); - break; - } - -#endif - 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) -{ - png_uint_32 chunk_name; - - /* 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]; - png_byte chunk_tag[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, chunk_tag, 4); - png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); - png_check_chunk_name(png_ptr, png_ptr->chunk_name); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - } - - chunk_name = png_ptr->chunk_name; - - if (chunk_name == png_IDAT) - { - /* This is here above the if/else case statement below because if the - * unknown handling marks 'IDAT' as unknown then the IDAT handling case is - * completely skipped. - * - * TODO: there must be a better way of doing this. - */ - if (png_ptr->mode & PNG_AFTER_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; - } - - if (chunk_name == png_IHDR) - { - 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 (chunk_name == png_IEND) - { - 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_chunk_unknown_handling(png_ptr, chunk_name)) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - if (chunk_name == png_IDAT) - png_ptr->mode |= PNG_HAVE_IDAT; - - png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); - - if (chunk_name == png_PLTE) - png_ptr->mode |= PNG_HAVE_PLTE; - - else if (chunk_name == png_IDAT) - { - 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 (chunk_name == png_PLTE) - { - 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 (chunk_name == png_IDAT) - { - /* 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_benign_error(png_ptr, "Too many IDATs 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_ptr->chunk_name == png_gAMA) - { - 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_ptr->chunk_name == png_sBIT) - { - 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_ptr->chunk_name == png_cHRM) - { - 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 (chunk_name == png_sRGB) - { - 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_ptr->chunk_name == png_iCCP) - { - 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 (chunk_name == png_sPLT) - { - 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 (chunk_name == png_tRNS) - { - 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 (chunk_name == png_bKGD) - { - 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 (chunk_name == png_hIST) - { - 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 (chunk_name == png_pHYs) - { - 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 (chunk_name == png_oFFs) - { - 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 (chunk_name == png_pCAL) - { - 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 (chunk_name == png_sCAL) - { - 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 (chunk_name == png_tIME) - { - 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 (chunk_name == png_tEXt) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_zTXt_SUPPORTED - else if (chunk_name == png_zTXt) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_iTXt_SUPPORTED - else if (chunk_name == png_iTXt) - { - if (png_ptr->push_length + 4 > png_ptr->buffer_size) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_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_push_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 = png_ptr->save_buffer_size; - png_uint_32 skip_length = png_ptr->skip_length; - - /* We want the smaller of 'skip_length' and 'save_buffer_size', but - * they are of different types and we don't know which variable has the - * fewest bits. Carefully select the smaller and cast it to the type of - * the larger - this cannot overflow. Do not cast in the following test - * - it will break on either 16 or 64 bit platforms. - */ - if (skip_length < save_size) - save_size = (png_size_t)skip_length; - - else - skip_length = (png_uint_32)save_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - - png_ptr->skip_length -= skip_length; - 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 = png_ptr->current_buffer_size; - png_uint_32 skip_length = png_ptr->skip_length; - - /* We want the smaller of 'skip_length' and 'current_buffer_size', here, - * the same problem exists as above and the same solution. - */ - if (skip_length < save_size) - save_size = (png_size_t)skip_length; - - else - skip_length = (png_uint_32)save_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->skip_length -= skip_length; - 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 PNGCBAPI -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, 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) -{ - if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) - { - png_byte chunk_length[4]; - png_byte chunk_tag[4]; - - /* TODO: this code can be commoned up with the same code in push_read */ - 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, chunk_tag, 4); - png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); - png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; - - if (png_ptr->chunk_name != png_IDAT) - { - 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 = png_ptr->save_buffer_size; - png_uint_32 idat_size = png_ptr->idat_size; - - /* We want the smaller of 'idat_size' and 'current_buffer_size', but they - * are of different types and we don't know which variable has the fewest - * bits. Carefully select the smaller and cast it to the type of the - * larger - this cannot overflow. Do not cast in the following test - it - * will break on either 16 or 64 bit platforms. - */ - if (idat_size < save_size) - save_size = (png_size_t)idat_size; - - else - idat_size = (png_uint_32)save_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 -= idat_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 = png_ptr->current_buffer_size; - png_uint_32 idat_size = png_ptr->idat_size; - - /* We want the smaller of 'idat_size' and 'current_buffer_size', but they - * are of different types and we don't know which variable has the fewest - * bits. Carefully select the smaller and cast it to the type of the - * larger - this cannot overflow. - */ - if (idat_size < save_size) - save_size = (png_size_t)idat_size; - - else - idat_size = (png_uint_32)save_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 -= idat_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 someplace 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 (a stream with a missing end code) can still - * be handled, 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 in IDAT"); -} - -void /* PRIVATE */ -png_push_process_row(png_structp png_ptr) -{ - /* 1.5.6: row_info moved out of png_struct to a local here. */ - png_row_info row_info; - - row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ - row_info.color_type = png_ptr->color_type; - row_info.bit_depth = png_ptr->bit_depth; - row_info.channels = png_ptr->channels; - row_info.pixel_depth = png_ptr->pixel_depth; - row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); - - if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) - { - if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) - png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, - png_ptr->prev_row + 1, png_ptr->row_buf[0]); - else - png_error(png_ptr, "bad adaptive filter value"); - } - - /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before - * 1.5.6, while the buffer really is this big in current versions of libpng - * it may not be in the future, so this was changed just to copy the - * interlaced row count: - */ - png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED - if (png_ptr->transformations) - png_do_read_transformations(png_ptr, &row_info); -#endif - - /* The transformed pixel depth should match the depth now in row_info. */ - if (png_ptr->transformed_pixel_depth == 0) - { - png_ptr->transformed_pixel_depth = row_info.pixel_depth; - if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) - png_error(png_ptr, "progressive row overflow"); - } - - else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) - png_error(png_ptr, "internal progressive row size calculation error"); - - -#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) - png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, - png_ptr->transformations); - - 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, 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, NULL); - png_read_push_finish_row(png_ptr); - } - } - - if (png_ptr->pass == 6 && png_ptr->height <= 4) - { - png_push_have_row(png_ptr, 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, 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, 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, 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, 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, NULL); - png_read_push_finish_row(png_ptr); - } - - if (png_ptr->pass == 6) /* Pass 5 might be empty */ - { - png_push_have_row(png_ptr, 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, NULL); - png_read_push_finish_row(png_ptr); - } - - break; - } - - default: - 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, 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_READ_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte 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 - static PNG_CONST png_byte 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(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 */ -} - -#ifdef PNG_READ_tEXt_SUPPORTED -void /* PRIVATE */ -png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ - png_error(png_ptr, "Out of place tEXt"); - /* NOT REACHED */ - } - -#ifdef PNG_MAX_MALLOC_64K - png_ptr->skip_length = 0; /* This may not be necessary */ - - if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ - { - png_warning(png_ptr, "tEXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_tEXt_MODE; -} - -void /* PRIVATE */ -png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - - else - text_size = png_ptr->current_text_left; - - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - -#ifdef PNG_MAX_MALLOC_64K - if (png_ptr->skip_length) - return; -#endif - - key = png_ptr->current_text; - - for (text = key; *text; text++) - /* Empty loop */ ; - - if (text < key + png_ptr->current_text_size) - text++; - - text_ptr = (png_textp)png_malloc(png_ptr, png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr->key = key; - text_ptr->itxt_length = 0; - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; - text_ptr->text = text; - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - png_ptr->current_text = NULL; - - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk"); - } -} -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED -void /* PRIVATE */ -png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ - png_error(png_ptr, "Out of place zTXt"); - /* NOT REACHED */ - } - -#ifdef PNG_MAX_MALLOC_64K - /* We can't handle zTXt chunks > 64K, since we don't have enough space - * to be able to store the uncompressed data. Actually, the threshold - * is probably around 32K, but it isn't as definite as 64K is. - */ - if (length > (png_uint_32)65535L) - { - png_warning(png_ptr, "zTXt chunk too large to fit in memory"); - png_push_crc_skip(png_ptr, length); - return; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_zTXt_MODE; -} - -void /* PRIVATE */ -png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) -{ - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - - else - text_size = png_ptr->current_text_left; - - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp text; - png_charp key; - int ret; - png_size_t text_size, key_size; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - - key = png_ptr->current_text; - - for (text = key; *text; text++) - /* Empty loop */ ; - - /* zTXt can't have zero text */ - if (text >= key + png_ptr->current_text_size) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } - - text++; - - if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */ - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - return; - } - - text++; - - png_ptr->zstream.next_in = (png_bytep)text; - png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - - (text - key)); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - key_size = text - key; - text_size = 0; - text = NULL; - ret = Z_STREAM_END; - - while (png_ptr->zstream.avail_in) - { - ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } - - if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) - { - if (text == NULL) - { - text = (png_charp)png_malloc(png_ptr, - (png_ptr->zbuf_size - - png_ptr->zstream.avail_out + key_size + 1)); - - png_memcpy(text + key_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - - png_memcpy(text, key, key_size); - - text_size = key_size + png_ptr->zbuf_size - - png_ptr->zstream.avail_out; - - *(text + text_size) = '\0'; - } - - else - { - png_charp tmp; - - tmp = text; - text = (png_charp)png_malloc(png_ptr, text_size + - (png_ptr->zbuf_size - - png_ptr->zstream.avail_out + 1)); - - png_memcpy(text, tmp, text_size); - png_free(png_ptr, tmp); - - png_memcpy(text + text_size, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - - text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; - *(text + text_size) = '\0'; - } - - if (ret != Z_STREAM_END) - { - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - } - } - else - { - break; - } - - if (ret == Z_STREAM_END) - break; - } - - inflateReset(&png_ptr->zstream); - png_ptr->zstream.avail_in = 0; - - if (ret != Z_STREAM_END) - { - png_ptr->current_text = NULL; - png_free(png_ptr, key); - png_free(png_ptr, text); - return; - } - - png_ptr->current_text = NULL; - png_free(png_ptr, key); - key = text; - text += key_size; - - text_ptr = (png_textp)png_malloc(png_ptr, - png_sizeof(png_text)); - text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; - text_ptr->key = key; - text_ptr->itxt_length = 0; - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; - text_ptr->text = text; - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_free(png_ptr, key); - png_free(png_ptr, text_ptr); - - if (ret) - png_warning(png_ptr, "Insufficient memory to store text chunk"); - } -} -#endif - -#ifdef PNG_READ_iTXt_SUPPORTED -void /* PRIVATE */ -png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) - { - PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ - png_error(png_ptr, "Out of place iTXt"); - /* NOT REACHED */ - } - -#ifdef PNG_MAX_MALLOC_64K - png_ptr->skip_length = 0; /* This may not be necessary */ - - if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ - { - png_warning(png_ptr, "iTXt chunk too large to fit in memory"); - png_ptr->skip_length = length - (png_uint_32)65535L; - length = (png_uint_32)65535L; - } -#endif - - png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1); - png_ptr->current_text[length] = '\0'; - png_ptr->current_text_ptr = png_ptr->current_text; - png_ptr->current_text_size = (png_size_t)length; - png_ptr->current_text_left = (png_size_t)length; - png_ptr->process_mode = PNG_READ_iTXt_MODE; -} - -void /* PRIVATE */ -png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) -{ - - if (png_ptr->buffer_size && png_ptr->current_text_left) - { - png_size_t text_size; - - if (png_ptr->buffer_size < png_ptr->current_text_left) - text_size = png_ptr->buffer_size; - - else - text_size = png_ptr->current_text_left; - - png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); - png_ptr->current_text_left -= text_size; - png_ptr->current_text_ptr += text_size; - } - - if (!(png_ptr->current_text_left)) - { - png_textp text_ptr; - png_charp key; - int comp_flag; - png_charp lang; - png_charp lang_key; - png_charp text; - int ret; - - if (png_ptr->buffer_size < 4) - { - png_push_save_buffer(png_ptr); - return; - } - - png_push_crc_finish(png_ptr); - -#ifdef PNG_MAX_MALLOC_64K - if (png_ptr->skip_length) - return; -#endif - - key = png_ptr->current_text; - - for (lang = key; *lang; lang++) - /* Empty loop */ ; - - if (lang < key + png_ptr->current_text_size - 3) - lang++; - - comp_flag = *lang++; - lang++; /* Skip comp_type, always zero */ - - for (lang_key = lang; *lang_key; lang_key++) - /* Empty loop */ ; - - lang_key++; /* Skip NUL separator */ - - text=lang_key; - - if (lang_key < key + png_ptr->current_text_size - 1) - { - for (; *text; text++) - /* Empty loop */ ; - } - - if (text < key + png_ptr->current_text_size) - text++; - - text_ptr = (png_textp)png_malloc(png_ptr, - png_sizeof(png_text)); - - text_ptr->compression = comp_flag + 2; - text_ptr->key = key; - text_ptr->lang = lang; - text_ptr->lang_key = lang_key; - text_ptr->text = text; - text_ptr->text_length = 0; - text_ptr->itxt_length = png_strlen(text); - - ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); - - png_ptr->current_text = NULL; - - png_free(png_ptr, text_ptr); - if (ret) - png_warning(png_ptr, "Insufficient memory to store iTXt chunk"); - } -} -#endif - -/* This function is called when we haven't found a handler for this - * chunk. If there isn't a problem with the chunk itself (ie a bad chunk - * name or a critical chunk), the chunk is (currently) silently ignored. - */ -void /* PRIVATE */ -png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 - length) -{ - png_uint_32 skip = 0; - png_uint_32 chunk_name = png_ptr->chunk_name; - - if (PNG_CHUNK_CRITICAL(chunk_name)) - { -#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED - if (png_chunk_unknown_handling(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"); - - PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ - } - -#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED - /* TODO: the code below is apparently just using the - * png_struct::unknown_chunk member as a temporarily variable, it should be - * possible to eliminate both it and the temporary buffer. - */ - if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) - { -#ifdef PNG_MAX_MALLOC_64K - if (length > 65535) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - 65535; - length = 65535; - } -#endif - /* This is just a record for the user; libpng doesn't use the character - * form of the name. - */ - PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); - - png_ptr->unknown_chunk.size = length; - - if (length == 0) - png_ptr->unknown_chunk.data = NULL; - - else - { - png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, - png_ptr->unknown_chunk.size); - png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, - png_ptr->unknown_chunk.size); - } - -#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_CHUNK_CRITICAL(png_ptr->chunk_name)) - if (png_chunk_unknown_handling(png_ptr, chunk_name) != - PNG_HANDLE_CHUNK_ALWAYS) - 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_push_crc_skip(png_ptr, skip); -} - -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); -} - -#ifdef PNG_READ_INTERLACING_SUPPORTED -void PNGAPI -png_progressive_combine_row (png_structp png_ptr, png_bytep old_row, - png_const_bytep new_row) -{ - if (png_ptr == NULL) - return; - - /* new_row is a flag here - if it is NULL then the app callback was called - * from an empty row (see the calls to png_struct::row_fn below), otherwise - * it must be png_ptr->row_buf+1 - */ - if (new_row != NULL) - png_combine_row(png_ptr, old_row, 1/*display*/); -} -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - -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_const_structp png_ptr) -{ - if (png_ptr == NULL) - return (NULL); - - return png_ptr->io_ptr; -} -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibPNG/pngpriv.h b/plugins/FreeImage/Source/LibPNG/pngpriv.h deleted file mode 100644 index 02cc5d8c53..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngpriv.h +++ /dev/null @@ -1,1629 +0,0 @@ - -/* pngpriv.h - private declarations for use inside libpng - * - * For conditions of distribution and use, see copyright notice in png.h - * 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.) - * - * Last changed in libpng 1.5.7 [December 15, 2011] - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -/* The symbols declared in this file (including the functions declared - * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public - * interface, and are not recommended for use by regular applications. - * Some of them may become public in the future; others may stay private, - * change in an incompatible way, or even disappear. - * Although the libpng users are not forbidden to include this header, - * they should be well aware of the issues that may arise from doing so. - */ - -#ifndef PNGPRIV_H -#define PNGPRIV_H - -/* Feature Test Macros. The following are defined here to ensure that correctly - * implemented libraries reveal the APIs libpng needs to build and hide those - * that are not needed and potentially damaging to the compilation. - * - * Feature Test Macros must be defined before any system header is included (see - * POSIX 1003.1 2.8.2 "POSIX Symbols." - * - * These macros only have an effect if the operating system supports either - * POSIX 1003.1 or C99, or both. On other operating systems (particularly - * Windows/Visual Studio) there is no effect; the OS specific tests below are - * still required (as of 2011-05-02.) - */ -#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ - -/* This is required for the definition of abort(), used as a last ditch - * error handler when all else fails. - */ -#include - -/* This is used to find 'offsetof', used below for alignment tests. */ -#include - -#define PNGLIB_BUILD /*libpng is being built, not used*/ - -#ifdef PNG_USER_CONFIG -# include "pngusr.h" - /* These should have been defined in pngusr.h */ -# ifndef PNG_USER_PRIVATEBUILD -# define PNG_USER_PRIVATEBUILD "Custom libpng build" -# endif -# ifndef PNG_USER_DLLFNAME_POSTFIX -# define PNG_USER_DLLFNAME_POSTFIX "Cb" -# endif -#endif - -/* Is this a build of a DLL where compilation of the object modules requires - * different preprocessor settings to those required for a simple library? If - * so PNG_BUILD_DLL must be set. - * - * If libpng is used inside a DLL but that DLL does not export the libpng APIs - * PNG_BUILD_DLL must not be set. To avoid the code below kicking in build a - * static library of libpng then link the DLL against that. - */ -#ifndef PNG_BUILD_DLL -# ifdef DLL_EXPORT - /* This is set by libtool when files are compiled for a DLL; libtool - * always compiles twice, even on systems where it isn't necessary. Set - * PNG_BUILD_DLL in case it is necessary: - */ -# define PNG_BUILD_DLL -# else -# ifdef _WINDLL - /* This is set by the Microsoft Visual Studio IDE in projects that - * build a DLL. It can't easily be removed from those projects (it - * isn't visible in the Visual Studio UI) so it is a fairly reliable - * indication that PNG_IMPEXP needs to be set to the DLL export - * attributes. - */ -# define PNG_BUILD_DLL -# else -# ifdef __DLL__ - /* This is set by the Borland C system when compiling for a DLL - * (as above.) - */ -# define PNG_BUILD_DLL -# else - /* Add additional compiler cases here. */ -# endif -# endif -# endif -#endif /* Setting PNG_BUILD_DLL if required */ - -/* See pngconf.h for more details: the builder of the library may set this on - * the command line to the right thing for the specific compilation system or it - * may be automagically set above (at present we know of no system where it does - * need to be set on the command line.) - * - * PNG_IMPEXP must be set here when building the library to prevent pngconf.h - * setting it to the "import" setting for a DLL build. - */ -#ifndef PNG_IMPEXP -# ifdef PNG_BUILD_DLL -# define PNG_IMPEXP PNG_DLL_EXPORT -# else - /* Not building a DLL, or the DLL doesn't require specific export - * definitions. - */ -# define PNG_IMPEXP -# endif -#endif - -/* No warnings for private or deprecated functions in the build: */ -#ifndef PNG_DEPRECATED -# define PNG_DEPRECATED -#endif -#ifndef PNG_PRIVATE -# define PNG_PRIVATE -#endif - -#include "png.h" -#include "pnginfo.h" -#include "pngstruct.h" - -/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */ -#ifndef PNG_DLL_EXPORT -# define PNG_DLL_EXPORT -#endif - -/* This is used for 16 bit gamma tables - only the top level pointers are const, - * this could be changed: - */ -typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; - -/* Added at libpng-1.2.9 */ -/* Moved to pngpriv.h at libpng-1.5.0 */ - -/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" - * script. We may need it here to get the correct configuration on things - * like limits. - */ -#ifdef PNG_CONFIGURE_LIBPNG -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif -#endif - -/* Moved to pngpriv.h at libpng-1.5.0 */ -/* NOTE: some of these may have been used in external applications as - * these definitions were exposed in pngconf.h prior to 1.5. - */ - -/* 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. - * - * zlib provides 'MAXSEG_64K' which, if defined, indicates the - * same limit and pngconf.h (already included) sets the limit - * if certain operating systems are detected. - */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) -# define PNG_MAX_MALLOC_64K -#endif - -#ifndef PNG_UNUSED -/* Unused formal parameter warnings are silenced using the following macro - * which is expected to have no bad effects on performance (optimizing - * compilers will probably remove it entirely). Note that if you replace - * it with something other than whitespace, you must include the terminating - * semicolon. - */ -# define PNG_UNUSED(param) (void)param; -#endif - -/* 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 - -/* PNG_STATIC is used to mark internal file scope functions if they need to be - * accessed for implementation tests (see the code in tests/?*). - */ -#ifndef PNG_STATIC -# define PNG_STATIC static -#endif - -/* C99 restrict is used where possible, to do this 'restrict' is defined as - * empty if we can't be sure it is supported. configure builds have already - * done this work. - */ -#ifdef PNG_CONFIGURE_LIBPNG -# define PNG_RESTRICT restrict -#else - /* Modern compilers support restrict, but assume not for anything not - * recognized here: - */ -# if defined __GNUC__ || defined _MSC_VER || defined __WATCOMC__ -# define PNG_RESTRICT restrict -# else -# define PNG_RESTRICT -# endif -#endif - -/* If warnings or errors are turned off the code is disabled or redirected here. - * From 1.5.4 functions have been added to allow very limited formatting of - * error and warning messages - this code will also be disabled here. - */ -#ifdef PNG_WARNINGS_SUPPORTED -# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p; -#else -# define png_warning(s1,s2) ((void)(s1)) -# define png_chunk_warning(s1,s2) ((void)(s1)) -# define png_warning_parameter(p,number,string) ((void)0) -# define png_warning_parameter_unsigned(p,number,format,value) ((void)0) -# define png_warning_parameter_signed(p,number,format,value) ((void)0) -# define png_formatted_warning(pp,p,message) ((void)(pp)) -# define PNG_WARNING_PARAMETERS(p) -#endif -#ifndef PNG_ERROR_TEXT_SUPPORTED -# define png_error(s1,s2) png_err(s1) -# define png_chunk_error(s1,s2) png_err(s1) -# define png_fixed_error(s1,s2) png_err(s1) -#endif - -/* C allows up-casts from (void*) to any pointer and (const void*) to any - * pointer to a const object. C++ regards this as a type error and requires an - * explicit, static, cast and provides the static_cast<> rune to ensure that - * const is not cast away. - */ -#ifdef __cplusplus -# define png_voidcast(type, value) static_cast(value) -#else -# define png_voidcast(type, value) (value) -#endif /* __cplusplus */ - -#ifndef PNG_EXTERN -/* The functions exported by PNG_EXTERN are 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 might be made available again. - * - * 1.5.7: turned the use of 'extern' back on, since it is localized to pngpriv.h - * it should be safe now (it is unclear why it was turned off.) - */ -# define PNG_EXTERN extern -#endif - -/* Some fixed point APIs are still required even if not exported because - * they get used by the corresponding floating point APIs. This magic - * deals with this: - */ -#ifdef PNG_FIXED_POINT_SUPPORTED -# define PNGFAPI PNGAPI -#else -# define PNGFAPI /* PRIVATE */ -#endif - -/* Other defines specific to compilers can go here. Try to keep - * them inside an appropriate ifdef/endif pair for portability. - */ -#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ - defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) - /* png.c requires the following ANSI-C constants if the conversion of - * floating point to ASCII is implemented therein: - * - * DBL_DIG Maximum number of decimal digits (can be set to any constant) - * DBL_MIN Smallest normalized fp number (can be set to an arbitrary value) - * DBL_MAX Maximum floating point number (can be set to an arbitrary value) - */ -# include - -# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) - /* We need to check that hasn't already been included earlier - * as it seems it doesn't agree with , yet we should really use - * if possible. - */ -# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) -# include -# endif -# else -# include -# endif -# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) - /* Amiga SAS/C: We must include builtin FPU functions when compiling using - * MATH=68881 - */ -# include -# endif -#endif - -/* This provides the non-ANSI (far) memory allocation routines. */ -#if defined(__TURBOC__) && defined(__MSDOS__) -# include -# include -#endif - -#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ - defined(_WIN32) || defined(__WIN32__) -# include /* defines _WINDOWS_ macro */ -#endif - -/* Moved here around 1.5.0beta36 from pngconf.h */ -/* Users may want to use these so they are not private. Any library - * functions that are passed far data must be model-independent. - */ - -/* Memory model/platform independent fns */ -#ifndef PNG_ABORT -# ifdef _WINDOWS_ -# define PNG_ABORT() ExitProcess(0) -# else -# define PNG_ABORT() abort() -# endif -#endif - -#ifdef USE_FAR_KEYWORD -/* 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_strlen _fstrlen -# define png_memcmp _fmemcmp /* SJT: added */ -# define png_memcpy _fmemcpy -# define png_memset _fmemset -#else -# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ -# define CVT_PTR(ptr) (ptr) -# define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strlen lstrlenA -# define png_memcmp memcmp -# define png_memcpy CopyMemory -# define png_memset memset -# else -# define CVT_PTR(ptr) (ptr) -# define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strlen strlen -# define png_memcmp memcmp /* SJT: added */ -# define png_memcpy memcpy -# define png_memset memset -# endif -#endif - -/* These macros may need to be architecture dependent. */ -#define PNG_ALIGN_NONE 0 /* do not use data alignment */ -#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */ -#ifdef offsetof -# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */ -#else -# define PNG_ALIGN_OFFSET -1 /* prevent the use of this */ -#endif -#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */ - -#ifndef PNG_ALIGN_TYPE - /* Default to using aligned access optimizations and requiring alignment to a - * multiple of the data type size. Override in a compiler specific fashion - * if necessary by inserting tests here: - */ -# define PNG_ALIGN_TYPE PNG_ALIGN_SIZE -#endif - -#if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE - /* This is used because in some compiler implementations non-aligned - * structure members are supported, so the offsetof approach below fails. - * Set PNG_ALIGN_TO_SIZE=0 for compiler combinations where unaligned access - * is good for performance. Do not do this unless you have tested the result - * and understand it. - */ -# define png_alignof(type) (sizeof (type)) -#else -# if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET -# define png_alignof(type) offsetof(struct{char c; type t;}, t) -# else -# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS -# define png_alignof(type) (1) -# endif - /* Else leave png_alignof undefined to prevent use thereof */ -# endif -#endif - -/* This implicitly assumes alignment is always to a power of 2. */ -#ifdef png_alignof -# define png_isaligned(ptr, type)\ - ((((const char*)ptr-(const char*)0) & (png_alignof(type)-1)) == 0) -#else -# define png_isaligned(ptr, type) 0 -#endif - -/* End of memory model/platform independent support */ -/* End of 1.5.0beta36 move from pngconf.h */ - -/* CONSTANTS and UTILITY MACROS - * These are used internally by libpng and not exposed in the API - */ - -/* Various modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. Three of these - * are defined in png.h because they need to be visible to applications - * that call png_set_unknown_chunk(). - */ -/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ -/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ -#define PNG_HAVE_IDAT 0x04 -/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ -#define PNG_HAVE_IEND 0x10 -#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_QUANTIZE 0x0040 -#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ -#define PNG_BACKGROUND_EXPAND 0x0100 -#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ -#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ -#define PNG_RGBA 0x0800 -#define PNG_EXPAND 0x1000 -#define PNG_GAMMA 0x2000 -#define PNG_GRAY_TO_RGB 0x4000 -#define PNG_FILLER 0x8000 -#define PNG_PACKSWAP 0x10000 -#define PNG_SWAP_ALPHA 0x20000 -#define PNG_STRIP_ALPHA 0x40000 -#define PNG_INVERT_ALPHA 0x80000 -#define PNG_USER_TRANSFORM 0x100000 -#define PNG_RGB_TO_GRAY_ERR 0x200000 -#define PNG_RGB_TO_GRAY_WARN 0x400000 -#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */ -#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */ -#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */ -#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */ -#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */ - /* 0x8000000 unused */ - /* 0x10000000 unused */ - /* 0x20000000 unused */ - /* 0x40000000 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_FACTOR (1<<(PNG_WEIGHT_SHIFT)) -#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_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ -#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 -#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 -#define PNG_FLAG_LIBRARY_MISMATCH 0x20000 -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000 -#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 -#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000 - /* 0x200000 unused */ - /* 0x400000 unused */ -#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000 /* Added to libpng-1.4.0 */ -#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000 /* 5 lines added */ -#define PNG_FLAG_ZTXT_CUSTOM_LEVEL 0x2000000 /* to libpng-1.5.4 */ -#define PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL 0x4000000 -#define PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS 0x8000000 -#define PNG_FLAG_ZTXT_CUSTOM_METHOD 0x10000000 - /* 0x20000000 unused */ - /* 0x40000000 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) - -/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib - * can handle at once. This type need be no larger than 16 bits (so maximum of - * 65535), this define allows us to discover how big it is, but limited by the - * maximuum for png_size_t. The value can be overriden in a library build - * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably - * lower value (e.g. 255 works). A lower value may help memory usage (slightly) - * and may even improve performance on some systems (and degrade it on others.) - */ -#ifndef ZLIB_IO_MAX -# define ZLIB_IO_MAX ((uInt)-1) -#endif - -/* 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 ? \ - ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ - (( ((png_size_t)(width) * ((png_size_t)(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)) - -/* Conversions between fixed and floating point, only defined if - * required (to make sure the code doesn't accidentally use float - * when it is supposedly disabled.) - */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -/* The floating point conversion can't overflow, though it can and - * does lose accuracy relative to the original fixed point value. - * In practice this doesn't matter because png_fixed_point only - * stores numbers with very low precision. The png_ptr and s - * arguments are unused by default but are there in case error - * checking becomes a requirement. - */ -#define png_float(png_ptr, fixed, s) (.00001 * (fixed)) - -/* The fixed point conversion performs range checking and evaluates - * its argument multiple times, so must be used with care. The - * range checking uses the PNG specification values for a signed - * 32 bit fixed point value except that the values are deliberately - * rounded-to-zero to an integral value - 21474 (21474.83 is roughly - * (2^31-1) * 100000). 's' is a string that describes the value being - * converted. - * - * NOTE: this macro will raise a png_error if the range check fails, - * therefore it is normally only appropriate to use this on values - * that come from API calls or other sources where an out of range - * error indicates a programming error, not a data error! - * - * NOTE: by default this is off - the macro is not used - because the - * function call saves a lot of code. - */ -#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED -#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\ - ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0)) -#else -PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp, - png_const_charp text)); -#endif -#endif - -/* Constants for known chunk types. If you need to add a chunk, define the name - * here. For historical reasons these constants have the form png_; i.e. - * the prefix is lower case. Please use decimal values as the parameters to - * match the ISO PNG specification and to avoid relying on the C locale - * interpretation of character values. - * - * Prior to 1.5.6 these constants were strings, as of 1.5.6 png_uint_32 values - * are computed and a new macro (PNG_STRING_FROM_CHUNK) added to allow a string - * to be generated if required. - * - * PNG_32b correctly produces a value shifted by up to 24 bits, even on - * architectures where (int) is only 16 bits. - */ -#define PNG_32b(b,s) ((png_uint_32)(b) << (s)) -#define PNG_CHUNK(b1,b2,b3,b4) \ - (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0)) - -#define png_IHDR PNG_CHUNK( 73, 72, 68, 82) -#define png_IDAT PNG_CHUNK( 73, 68, 65, 84) -#define png_IEND PNG_CHUNK( 73, 69, 78, 68) -#define png_PLTE PNG_CHUNK( 80, 76, 84, 69) -#define png_bKGD PNG_CHUNK( 98, 75, 71, 68) -#define png_cHRM PNG_CHUNK( 99, 72, 82, 77) -#define png_gAMA PNG_CHUNK(103, 65, 77, 65) -#define png_hIST PNG_CHUNK(104, 73, 83, 84) -#define png_iCCP PNG_CHUNK(105, 67, 67, 80) -#define png_iTXt PNG_CHUNK(105, 84, 88, 116) -#define png_oFFs PNG_CHUNK(111, 70, 70, 115) -#define png_pCAL PNG_CHUNK(112, 67, 65, 76) -#define png_sCAL PNG_CHUNK(115, 67, 65, 76) -#define png_pHYs PNG_CHUNK(112, 72, 89, 115) -#define png_sBIT PNG_CHUNK(115, 66, 73, 84) -#define png_sPLT PNG_CHUNK(115, 80, 76, 84) -#define png_sRGB PNG_CHUNK(115, 82, 71, 66) -#define png_sTER PNG_CHUNK(115, 84, 69, 82) -#define png_tEXt PNG_CHUNK(116, 69, 88, 116) -#define png_tIME PNG_CHUNK(116, 73, 77, 69) -#define png_tRNS PNG_CHUNK(116, 82, 78, 83) -#define png_zTXt PNG_CHUNK(122, 84, 88, 116) - -/* The following will work on (signed char*) strings, whereas the get_uint_32 - * macro will fail on top-bit-set values because of the sign extension. - */ -#define PNG_CHUNK_FROM_STRING(s)\ - PNG_CHUNK(0xff&(s)[0], 0xff&(s)[1], 0xff&(s)[2], 0xff&(s)[3]) - -/* This uses (char), not (png_byte) to avoid warnings on systems where (char) is - * signed and the argument is a (char[]) This macro will fail miserably on - * systems where (char) is more than 8 bits. - */ -#define PNG_STRING_FROM_CHUNK(s,c)\ - (void)(((char*)(s))[0]=(char)((c)>>24), ((char*)(s))[1]=(char)((c)>>16),\ - ((char*)(s))[2]=(char)((c)>>8), ((char*)(s))[3]=(char)((c))) - -/* Do the same but terminate with a null character. */ -#define PNG_CSTRING_FROM_CHUNK(s,c)\ - (void)(PNG_STRING_FROM_CHUNK(s,c), ((char*)(s))[4] = 0) - -/* Test on flag values as defined in the spec (section 5.4): */ -#define PNG_CHUNK_ANCILLIARY(c) (1 & ((c) >> 29)) -#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLIARY(c)) -#define PNG_CHUNK_PRIVATE(c) (1 & ((c) >> 21)) -#define PNG_CHUNK_RESERVED(c) (1 & ((c) >> 13)) -#define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >> 5)) - -/* Gamma values (new at libpng-1.5.4): */ -#define PNG_GAMMA_MAC_OLD 151724 /* Assume '1.8' is really 2.2/1.45! */ -#define PNG_GAMMA_MAC_INVERSE 65909 -#define PNG_GAMMA_sRGB_INVERSE 45455 - - -/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* These 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. - */ - -/* Check the user version string for compatibility, returns false if the version - * numbers aren't compatible. - */ -PNG_EXTERN int png_user_version_check(png_structp png_ptr, - png_const_charp user_png_ver); - -/* Allocate memory for an internal libpng struct */ -PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct,PNGARG((int type)), - PNG_ALLOCATED); - -/* Free memory from internal libpng struct */ -PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); - -PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct_2, - PNGARG((int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)), - PNG_ALLOCATED); -PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, - png_free_ptr free_fn, png_voidp mem_ptr)); - -/* 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)); - -/* Function to allocate memory for zlib. PNGAPI is disallowed. */ -PNG_EXTERN PNG_FUNCTION(voidpf,png_zalloc,PNGARG((voidpf png_ptr, uInt items, - uInt size)),PNG_ALLOCATED); - -/* Function to free memory for zlib. PNGAPI is disallowed. */ -PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); - -/* Next four functions are used internally as callbacks. PNGCBAPI is required - * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to - * PNGCBAPI at 1.5.0 - */ - -PNG_EXTERN void PNGCBAPI png_default_read_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void PNGCBAPI png_push_fill_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t length)); -#endif - -PNG_EXTERN void PNGCBAPI png_default_write_data PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -# ifdef PNG_STDIO_SUPPORTED -PNG_EXTERN void PNGCBAPI png_default_flush PNGARG((png_structp png_ptr)); -# endif -#endif - -/* Reset the CRC variable */ -PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); - -/* Write the "data" buffer to whatever output you are using */ -PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, - png_const_bytep data, png_size_t length)); - -/* Read and check the PNG file signature */ -PNG_EXTERN void png_read_sig PNGARG((png_structp png_ptr, png_infop info_ptr)); - -/* Read the chunk header (length + type name) */ -PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr)); - -/* 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)); - -/* 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)); - -/* Decompress data in a chunk that uses compression */ -#if defined(PNG_READ_COMPRESSED_TEXT_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)); -#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)); - -/* 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)); - -/* 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_const_bytep ptr, png_size_t length)); - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); -#endif - -/* 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_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, - png_const_colorp palette, png_uint_32 num_pal)); - -PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, - png_size_t length)); - -PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); - -#ifdef PNG_WRITE_gAMA_SUPPORTED -# ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); -# endif -# ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, - png_fixed_point file_gamma)); -# endif -#endif - -#ifdef PNG_WRITE_sBIT_SUPPORTED -PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, - png_const_color_8p sbit, int color_type)); -#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)); -# endif -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)); -#endif - -#ifdef PNG_WRITE_sRGB_SUPPORTED -PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, - int intent)); -#endif - -#ifdef PNG_WRITE_iCCP_SUPPORTED -PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, - png_const_charp name, int compression_type, - png_const_charp profile, int proflen)); - /* 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_const_sPLT_tp palette)); -#endif - -#ifdef PNG_WRITE_tRNS_SUPPORTED -PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, - png_const_bytep trans, png_const_color_16p values, int number, - int color_type)); -#endif - -#ifdef PNG_WRITE_bKGD_SUPPORTED -PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, - png_const_color_16p values, int color_type)); -#endif - -#ifdef PNG_WRITE_hIST_SUPPORTED -PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, - png_const_uint_16p hist, int num_hist)); -#endif - -/* Chunks that have keywords */ -#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_const_charp key, png_charpp new_key)); -#endif - -#ifdef PNG_WRITE_tEXt_SUPPORTED -PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_const_charp key, - png_const_charp text, png_size_t text_len)); -#endif - -#ifdef PNG_WRITE_zTXt_SUPPORTED -PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_const_charp key, - png_const_charp text, png_size_t text_len, int compression)); -#endif - -#ifdef PNG_WRITE_iTXt_SUPPORTED -PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, - int compression, png_const_charp key, png_const_charp lang, - png_const_charp lang_key, png_const_charp text)); -#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_const_textp text_ptr, int num_text)); -#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)); -#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_const_charp units, png_charpp params)); -#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)); -#endif - -#ifdef PNG_WRITE_tIME_SUPPORTED -PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, - png_const_timep mod_time)); -#endif - -#ifdef PNG_WRITE_sCAL_SUPPORTED -PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, - int unit, png_const_charp width, png_const_charp height)); -#endif - -/* Called when finished processing a row of data */ -PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); - -/* Internal use only. Called before first row of data */ -PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); - -/* Combine a row of data, dealing with alpha, etc. if requested. 'row' is an - * array of png_ptr->width pixels. If the image is not interlaced or this - * is the final pass this just does a png_memcpy, otherwise the "display" flag - * is used to determine whether to copy pixels that are not in the current pass. - * - * Because 'png_do_read_interlace' (below) replicates pixels this allows this - * function to achieve the documented 'blocky' appearance during interlaced read - * if display is 1 and the 'sparkle' appearance, where existing pixels in 'row' - * are not changed if they are not in the current pass, when display is 0. - * - * 'display' must be 0 or 1, otherwise the memcpy will be done regardless. - * - * The API always reads from the png_struct row buffer and always assumes that - * it is full width (png_do_read_interlace has already been called.) - * - * This function is only ever used to write to row buffers provided by the - * caller of the relevant libpng API and the row must have already been - * transformed by the read transformations. - * - * The PNG_USE_COMPILE_TIME_MASKS option causes generation of pre-computed - * bitmasks for use within the code, otherwise runtime generated masks are used. - * The default is compile time masks. - */ -#ifndef PNG_USE_COMPILE_TIME_MASKS -# define PNG_USE_COMPILE_TIME_MASKS 1 -#endif -PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, - int display)); - -#ifdef PNG_READ_INTERLACING_SUPPORTED -/* Expand an interlaced row: the 'row_info' describes the pass data that has - * been read in and must correspond to the pixels in 'row', the pixels are - * expanded (moved apart) in 'row' to match the final layout, when doing this - * the pixels are *replicated* to the intervening space. This is essential for - * the correct operation of png_combine_row, above. - */ -PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, - png_bytep row, int pass, png_uint_32 transformations)); -#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)); -#endif - -/* Unfilter a row: check the filter value before calling this, there is no point - * calling it for PNG_FILTER_VALUE_NONE. - */ -PNG_EXTERN void png_read_filter_row PNGARG((png_structp pp, png_row_infop row_info, - png_bytep row, png_const_bytep prev_row, int filter)); - -PNG_EXTERN void png_read_filter_row_up_neon PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep prev_row)); -PNG_EXTERN void png_read_filter_row_sub3_neon PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep prev_row)); -PNG_EXTERN void png_read_filter_row_sub4_neon PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep prev_row)); -PNG_EXTERN void png_read_filter_row_avg3_neon PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep prev_row)); -PNG_EXTERN void png_read_filter_row_avg4_neon PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep prev_row)); -PNG_EXTERN void png_read_filter_row_paeth3_neon PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep prev_row)); -PNG_EXTERN void png_read_filter_row_paeth4_neon PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep prev_row)); - -/* 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)); - -/* 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)); - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -/* Optional call to update the users info structure */ -PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -/* 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)); -#endif - -#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED -PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED -PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED -PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED -PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ - defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_strip_channel PNGARG((png_row_infop row_info, - png_bytep row, int at_start)); -#endif - -#ifdef PNG_16BIT_SUPPORTED -#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)); -#endif -#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)); -#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)); -#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)); -#endif - -#ifdef PNG_READ_PACK_SUPPORTED -PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_READ_SHIFT_SUPPORTED -PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, - png_bytep row, png_const_color_8p sig_bits)); -#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)); -#endif - -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED -PNG_EXTERN void png_do_scale_16_to_8 PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED -PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep palette_lookup, - png_const_bytep quantize_lookup)); - -# ifdef PNG_CORRECT_PALETTE_SUPPORTED -PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette)); -# 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)); -#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)); -#endif - -#ifdef PNG_WRITE_SHIFT_SUPPORTED -PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, - png_bytep row, png_const_color_8p bit_depth)); -#endif - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) -PNG_EXTERN void png_do_compose PNGARG((png_row_infop row_info, - png_bytep row, png_structp png_ptr)); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, - png_bytep row, png_structp png_ptr)); -#endif - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED -PNG_EXTERN void png_do_encode_alpha PNGARG((png_row_infop row_info, - png_bytep row, png_structp png_ptr)); -#endif - -#ifdef PNG_READ_EXPAND_SUPPORTED -PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, - png_bytep row, png_const_colorp palette, png_const_bytep trans, - int num_trans)); -PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, - png_bytep row, png_const_color_16p trans_color)); -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED -PNG_EXTERN void png_do_expand_16 PNGARG((png_row_infop row_info, - png_bytep row)); -#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_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)); -#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)); -#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)); -#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)); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED -PNG_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)); -#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)); -#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)); -#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)); -#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)); -#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)); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED -PNG_EXTERN void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, - png_uint_32 length)); -#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)); -#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)); -#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)); -#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)); -#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)); -#endif - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -#endif - -PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, - png_uint_32 chunk_name)); - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -/* Exactly as png_handle_as_unknown() except that the argument is a 32-bit chunk - * name, not a string. - */ -PNG_EXTERN int png_chunk_unknown_handling PNGARG((png_structp png_ptr, - png_uint_32 chunk_name)); -#endif - -/* Handle the transformations for reading and writing */ -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr, - png_row_infop row_info)); -#endif -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr, - png_row_infop row_info)); -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, - png_uint_32 length)); -PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, - png_bytep buffer, png_size_t buffer_length)); -PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); -PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 length)); -PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); -PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); -# 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_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -# 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_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -# 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_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, - png_infop info_ptr)); -# 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_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, - png_bytep row)); -#endif - -/* Added at libpng version 1.4.0 */ -#ifdef PNG_CHECK_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)); -#endif - -#ifdef PNG_CHECK_cHRM_SUPPORTED -/* Added at libpng version 1.2.34 and 1.4.0 */ -/* Currently only used by png_check_cHRM_fixed */ -PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2, - unsigned long *hi_product, unsigned long *lo_product)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -/* Added at libpng version 1.5.5 */ -typedef struct png_xy -{ - png_fixed_point redx, redy; - png_fixed_point greenx, greeny; - png_fixed_point bluex, bluey; - png_fixed_point whitex, whitey; -} png_xy; - -typedef struct png_XYZ -{ - png_fixed_point redX, redY, redZ; - png_fixed_point greenX, greenY, greenZ; - png_fixed_point blueX, blueY, blueZ; -} png_XYZ; - -/* The conversion APIs return 0 on success, non-zero on a parameter error. They - * allow conversion between the above representations of a color encoding. When - * converting from XYZ end points to chromaticities the absolute magnitude of - * the end points is lost, when converting back the sum of the Y values of the - * three end points will be 1.0 - */ -PNG_EXTERN int png_xy_from_XYZ PNGARG((png_xy *xy, png_XYZ XYZ)); -PNG_EXTERN int png_XYZ_from_xy PNGARG((png_XYZ *XYZ, png_xy xy)); -PNG_EXTERN int png_XYZ_from_xy_checked PNGARG((png_structp png_ptr, - png_XYZ *XYZ, png_xy xy)); -#endif - -/* Added at libpng version 1.4.0 */ -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)); - -/* Free all memory used by the read (old method - NOT DLL EXPORTED) */ -PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr, - png_infop info_ptr, png_infop end_info_ptr)); - -/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ -PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr)); - -#ifdef USE_FAR_KEYWORD /* memory model conversion function */ -PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr, png_voidp ptr, - int check)); -#endif /* USE_FAR_KEYWORD */ - -#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) -PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr, - png_const_charp name),PNG_NORETURN); -#endif - -/* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite - * the end. Always leaves the buffer nul terminated. Never errors out (and - * there is no error code.) - */ -PNG_EXTERN size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos, - png_const_charp string); - -/* Various internal functions to handle formatted warning messages, currently - * only implemented for warnings. - */ -#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) -/* Utility to dump an unsigned value into a buffer, given a start pointer and - * and end pointer (which should point just *beyond* the end of the buffer!) - * Returns the pointer to the start of the formatted string. This utility only - * does unsigned values. - */ -PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end, - int format, png_alloc_size_t number); - -/* Convenience macro that takes an array: */ -#define PNG_FORMAT_NUMBER(buffer,format,number) \ - png_format_number(buffer, buffer + (sizeof buffer), format, number) - -/* Suggested size for a number buffer (enough for 64 bits and a sign!) */ -#define PNG_NUMBER_BUFFER_SIZE 24 - -/* These are the integer formats currently supported, the name is formed from - * the standard printf(3) format string. - */ -#define PNG_NUMBER_FORMAT_u 1 /* chose unsigned API! */ -#define PNG_NUMBER_FORMAT_02u 2 -#define PNG_NUMBER_FORMAT_d 1 /* chose signed API! */ -#define PNG_NUMBER_FORMAT_02d 2 -#define PNG_NUMBER_FORMAT_x 3 -#define PNG_NUMBER_FORMAT_02x 4 -#define PNG_NUMBER_FORMAT_fixed 5 /* choose the signed API */ -#endif - -#ifdef PNG_WARNINGS_SUPPORTED -/* New defines and members adding in libpng-1.5.4 */ -# define PNG_WARNING_PARAMETER_SIZE 32 -# define PNG_WARNING_PARAMETER_COUNT 8 - -/* An l-value of this type has to be passed to the APIs below to cache the - * values of the parameters to a formatted warning message. - */ -typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][ - PNG_WARNING_PARAMETER_SIZE]; - -PNG_EXTERN void png_warning_parameter(png_warning_parameters p, int number, - png_const_charp string); - /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters, - * including the trailing '\0'. - */ -PNG_EXTERN void png_warning_parameter_unsigned(png_warning_parameters p, - int number, int format, png_alloc_size_t value); - /* Use png_alloc_size_t because it is an unsigned type as big as any we - * need to output. Use the following for a signed value. - */ -PNG_EXTERN void png_warning_parameter_signed(png_warning_parameters p, - int number, int format, png_int_32 value); - -PNG_EXTERN void png_formatted_warning(png_structp png_ptr, - png_warning_parameters p, png_const_charp message); - /* 'message' follows the X/Open approach of using @1, @2 to insert - * parameters previously supplied using the above functions. Errors in - * specifying the paramters will simple result in garbage substitutions. - */ -#endif - -/* ASCII to FP interfaces, currently only implemented if sCAL - * support is required. - */ -#if defined(PNG_READ_sCAL_SUPPORTED) -/* MAX_DIGITS is actually the maximum number of characters in an sCAL - * width or height, derived from the precision (number of significant - * digits - a build time settable option) and assumpitions about the - * maximum ridiculous exponent. - */ -#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) - -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXTERN void png_ascii_from_fp PNGARG((png_structp png_ptr, png_charp ascii, - png_size_t size, double fp, unsigned int precision)); -#endif /* FLOATING_POINT */ - -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr, - png_charp ascii, png_size_t size, png_fixed_point fp)); -#endif /* FIXED_POINT */ -#endif /* READ_sCAL */ - -#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) -/* An internal API to validate the format of a floating point number. - * The result is the index of the next character. If the number is - * not valid it will be the index of a character in the supposed number. - * - * The format of a number is defined in the PNG extensions specification - * and this API is strictly conformant to that spec, not anyone elses! - * - * The format as a regular expression is: - * - * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)? - * - * or: - * - * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)? - * - * The complexity is that either integer or fraction must be present and the - * fraction is permitted to have no digits only if the integer is present. - * - * NOTE: The dangling E problem. - * There is a PNG valid floating point number in the following: - * - * PNG floating point numb1.ers are not greedy. - * - * Working this out requires *TWO* character lookahead (because of the - * sign), the parser does not do this - it will fail at the 'r' - this - * doesn't matter for PNG sCAL chunk values, but it requires more care - * if the value were ever to be embedded in something more complex. Use - * ANSI-C strtod if you need the lookahead. - */ -/* State table for the parser. */ -#define PNG_FP_INTEGER 0 /* before or in integer */ -#define PNG_FP_FRACTION 1 /* before or in fraction */ -#define PNG_FP_EXPONENT 2 /* before or in exponent */ -#define PNG_FP_STATE 3 /* mask for the above */ -#define PNG_FP_SAW_SIGN 4 /* Saw +/- in current state */ -#define PNG_FP_SAW_DIGIT 8 /* Saw a digit in current state */ -#define PNG_FP_SAW_DOT 16 /* Saw a dot in current state */ -#define PNG_FP_SAW_E 32 /* Saw an E (or e) in current state */ -#define PNG_FP_SAW_ANY 60 /* Saw any of the above 4 */ - -/* These three values don't affect the parser. They are set but not used. - */ -#define PNG_FP_WAS_VALID 64 /* Preceding substring is a valid fp number */ -#define PNG_FP_NEGATIVE 128 /* A negative number, including "-0" */ -#define PNG_FP_NONZERO 256 /* A non-zero value */ -#define PNG_FP_STICKY 448 /* The above three flags */ - -/* This is available for the caller to store in 'state' if required. Do not - * call the parser after setting it (the parser sometimes clears it.) - */ -#define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ - -/* Result codes for the parser (boolean - true meants ok, false means - * not ok yet.) - */ -#define PNG_FP_MAYBE 0 /* The number may be valid in the future */ -#define PNG_FP_OK 1 /* The number is valid */ - -/* Tests on the sticky non-zero and negative flags. To pass these checks - * the state must also indicate that the whole number is valid - this is - * achieved by testing PNG_FP_SAW_DIGIT (see the implementation for why this - * is equivalent to PNG_FP_OK above.) - */ -#define PNG_FP_NZ_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NEGATIVE | PNG_FP_NONZERO) - /* NZ_MASK: the string is valid and a non-zero negative value */ -#define PNG_FP_Z_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NONZERO) - /* Z MASK: the string is valid and a non-zero value. */ - /* PNG_FP_SAW_DIGIT: the string is valid. */ -#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT) -#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK) -#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK) - -/* The actual parser. This can be called repeatedly, it updates - * the index into the string and the state variable (which must - * be initialzed to 0). It returns a result code, as above. There - * is no point calling the parser any more if it fails to advance to - * the end of the string - it is stuck on an invalid character (or - * terminated by '\0'). - * - * Note that the pointer will consume an E or even an E+ then leave - * a 'maybe' state even though a preceding integer.fraction is valid. - * The PNG_FP_WAS_VALID flag indicates that a preceding substring was - * a valid number. It's possible to recover from this by calling - * the parser again (from the start, with state 0) but with a string - * that omits the last character (i.e. set the size to the index of - * the problem character.) This has not been tested within libpng. - */ -PNG_EXTERN int png_check_fp_number PNGARG((png_const_charp string, - png_size_t size, int *statep, png_size_tp whereami)); - -/* This is the same but it checks a complete string and returns true - * only if it just contains a floating point number. As of 1.5.4 this - * function also returns the state at the end of parsing the number if - * it was valid (otherwise it returns 0.) This can be used for testing - * for negative or zero values using the sticky flag. - */ -PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string, - png_size_t size)); -#endif /* pCAL || sCAL */ - -#if defined(PNG_READ_GAMMA_SUPPORTED) ||\ - defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) -/* Added at libpng version 1.5.0 */ -/* This is a utility to provide a*times/div (rounded) and indicate - * if there is an overflow. The result is a boolean - false (0) - * for overflow, true (1) if no overflow, in which case *res - * holds the result. - */ -PNG_EXTERN int png_muldiv PNGARG((png_fixed_point_p res, png_fixed_point a, - png_int_32 multiplied_by, png_int_32 divided_by)); -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) -/* Same deal, but issue a warning on overflow and return 0. */ -PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr, - png_fixed_point a, png_int_32 multiplied_by, png_int_32 divided_by)); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* Calculate a reciprocal - used for gamma values. This returns - * 0 if the argument is 0 in order to maintain an undefined value, - * there are no warnings. - */ -PNG_EXTERN png_fixed_point png_reciprocal PNGARG((png_fixed_point a)); - -/* The same but gives a reciprocal of the product of two fixed point - * values. Accuracy is suitable for gamma calculations but this is - * not exact - use png_muldiv for that. - */ -PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a, - png_fixed_point b)); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* Internal fixed point gamma correction. These APIs are called as - * required to convert single values - they don't need to be fast, - * they are not used when processing image pixel values. - * - * While the input is an 'unsigned' value it must actually be the - * correct bit value - 0..255 or 0..65535 as required. - */ -PNG_EXTERN png_uint_16 png_gamma_correct PNGARG((png_structp png_ptr, - unsigned int value, png_fixed_point gamma_value)); -PNG_EXTERN int png_gamma_significant PNGARG((png_fixed_point gamma_value)); -PNG_EXTERN png_uint_16 png_gamma_16bit_correct PNGARG((unsigned int value, - png_fixed_point gamma_value)); -PNG_EXTERN png_byte png_gamma_8bit_correct PNGARG((unsigned int value, - png_fixed_point gamma_value)); -PNG_EXTERN void png_destroy_gamma_table(png_structp png_ptr); -PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, - int bit_depth)); -#endif - -/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ - -#include "pngdebug.h" - -#ifdef __cplusplus -} -#endif - -#endif /* PNGPRIV_H */ diff --git a/plugins/FreeImage/Source/LibPNG/pngread.c b/plugins/FreeImage/Source/LibPNG/pngread.c deleted file mode 100644 index e2641d540f..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngread.c +++ /dev/null @@ -1,1308 +0,0 @@ - -/* pngread.c - read a PNG file - * - * Last changed in libpng 1.5.7 [December 15, 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 routines that an application calls directly to - * read a PNG file or stream. - */ - -#include "pngpriv.h" - -#ifdef PNG_READ_SUPPORTED - -/* Create a PNG structure for reading, and allocate any memory needed. */ -PNG_FUNCTION(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),PNG_ALLOCATED) -{ - -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, NULL, NULL, NULL)); -} - -/* Alternate create PNG structure for reading, and allocate any memory - * needed. - */ -PNG_FUNCTION(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),PNG_ALLOCATED) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - -#ifdef PNG_SETJMP_SUPPORTED - volatile -#endif - png_structp png_ptr; - volatile int png_cleanup_needed = 0; - -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf tmp_jmpbuf; -#endif -#endif - - png_debug(1, "in png_create_read_struct"); - -#ifdef PNG_USER_MEM_SUPPORTED - png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, - malloc_fn, 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; - -# ifdef PNG_USER_CHUNK_CACHE_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_SET_USER_CHUNK_MALLOC_MAX - /* Added at libpng-1.2.43 and 1.4.1 */ - png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; -# endif -#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(tmp_jmpbuf)) -#else - if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ -#endif - PNG_ABORT(); -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(png_ptr), tmp_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); - - /* Call the general version checker (shared with read and write code): */ - if (!png_user_version_check(png_ptr, user_png_ver)) - png_cleanup_needed = 1; - - if (!png_cleanup_needed) - { - /* Initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size); - - if (png_ptr->zbuf == NULL) - png_cleanup_needed = 1; - } - - png_ptr->zstream.zalloc = png_zalloc; - png_ptr->zstream.zfree = png_zfree; - png_ptr->zstream.opaque = (voidpf)png_ptr; - - if (!png_cleanup_needed) - { - switch (inflateInit(&png_ptr->zstream)) - { - case Z_OK: - break; /* Do nothing */ - - case Z_MEM_ERROR: - png_warning(png_ptr, "zlib memory error"); - png_cleanup_needed = 1; - break; - - case Z_STREAM_ERROR: - png_warning(png_ptr, "zlib stream error"); - png_cleanup_needed = 1; - break; - - case Z_VERSION_ERROR: - png_warning(png_ptr, "zlib version error"); - png_cleanup_needed = 1; - break; - - default: png_warning(png_ptr, "Unknown zlib error"); - png_cleanup_needed = 1; - } - } - - if (png_cleanup_needed) - { - /* Clean up PNG structure and deallocate any memory. */ - 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); - } - - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - - png_set_read_fn(png_ptr, NULL, NULL); - - - return (png_ptr); -} - - -#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; - - /* Read and check the PNG file signature. */ - png_read_sig(png_ptr, info_ptr); - - for (;;) - { - png_uint_32 length = png_read_chunk_header(png_ptr); - png_uint_32 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 (chunk_name == png_IDAT) - if (png_ptr->mode & PNG_AFTER_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; - - if (chunk_name == png_IHDR) - png_handle_IHDR(png_ptr, info_ptr, length); - - else if (chunk_name == png_IEND) - png_handle_IEND(png_ptr, info_ptr, length); - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_chunk_unknown_handling(png_ptr, chunk_name) != - PNG_HANDLE_CHUNK_AS_DEFAULT) - { - if (chunk_name == png_IDAT) - png_ptr->mode |= PNG_HAVE_IDAT; - - png_handle_unknown(png_ptr, info_ptr, length); - - if (chunk_name == png_PLTE) - png_ptr->mode |= PNG_HAVE_PLTE; - - else if (chunk_name == png_IDAT) - { - 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 (chunk_name == png_PLTE) - png_handle_PLTE(png_ptr, info_ptr, length); - - else if (chunk_name == png_IDAT) - { - 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 (chunk_name == png_bKGD) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED - else if (chunk_name == png_cHRM) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_gAMA_SUPPORTED - else if (chunk_name == png_gAMA) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_hIST_SUPPORTED - else if (chunk_name == png_hIST) - png_handle_hIST(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED - else if (chunk_name == png_oFFs) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED - else if (chunk_name == png_pCAL) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED - else if (chunk_name == png_sCAL) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED - else if (chunk_name == png_pHYs) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED - else if (chunk_name == png_sBIT) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sRGB_SUPPORTED - else if (chunk_name == png_sRGB) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED - else if (chunk_name == png_iCCP) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED - else if (chunk_name == png_sPLT) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED - else if (chunk_name == png_tEXt) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tIME_SUPPORTED - else if (chunk_name == png_tIME) - png_handle_tIME(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tRNS_SUPPORTED - else if (chunk_name == png_tRNS) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED - else if (chunk_name == png_zTXt) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iTXt_SUPPORTED - else if (chunk_name == png_iTXt) - 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; - - png_read_start_row(png_ptr); - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED - png_read_transform_info(png_ptr, info_ptr); -#else - PNG_UNUSED(info_ptr) -#endif -} - -#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) - 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) -{ - int ret; - - png_row_info row_info; - - if (png_ptr == NULL) - return; - - png_debug2(1, "in png_read_row (row %lu, pass %d)", - (unsigned long)png_ptr->row_number, png_ptr->pass); - - /* png_read_start_row sets the information (in particular iwidth) for this - * interlace pass. - */ - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - png_read_start_row(png_ptr); - - /* 1.5.6: row_info moved out of png_struct to a local here. */ - row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ - row_info.color_type = png_ptr->color_type; - row_info.bit_depth = png_ptr->bit_depth; - row_info.channels = png_ptr->channels; - row_info.pixel_depth = png_ptr->pixel_depth; - row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); - - 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. - * Notice that the pixels we have from previous rows have been transformed - * already; we can only combine like with like (transformed or - * untransformed) and, because of the libpng API for interlaced images, this - * means we must transform before de-interlacing. - */ - 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, 1/*display*/); - 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, 1/*display*/); - - 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, 1/*display*/); - - 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, 1/*display*/); - - 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, 1/*display*/); - - 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, 1/*display*/); - - png_read_finish_row(png_ptr); - return; - } - break; - - default: - 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_ptr->chunk_name != png_IDAT) - 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_benign_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); - - if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) - { - if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) - png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, - png_ptr->prev_row + 1, png_ptr->row_buf[0]); - else - png_error(png_ptr, "bad adaptive filter value"); - } - - /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before - * 1.5.6, while the buffer really is this big in current versions of libpng - * it may not be in the future, so this was changed just to copy the - * interlaced count: - */ - png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.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(&row_info, png_ptr->row_buf + 1); - } -#endif - - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED - if (png_ptr->transformations) - png_do_read_transformations(png_ptr, &row_info); -#endif - - /* The transformed pixel depth should match the depth now in row_info. */ - if (png_ptr->transformed_pixel_depth == 0) - { - png_ptr->transformed_pixel_depth = row_info.pixel_depth; - if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) - png_error(png_ptr, "sequential row overflow"); - } - - else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) - png_error(png_ptr, "internal sequential row size calculation error"); - -#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) - png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, - png_ptr->transformations); - - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, 1/*display*/); - - if (row != NULL) - png_combine_row(png_ptr, row, 0/*row*/); - } - - else -#endif - { - if (row != NULL) - png_combine_row(png_ptr, row, -1/*ignored*/); - - if (dsp_row != NULL) - png_combine_row(png_ptr, dsp_row, -1/*ignored*/); - } - 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, NULL); - rp++; - } - - else if (dp != NULL) - for (i = 0; i < num_rows; i++) - { - png_bytep dptr = *dp; - png_read_row(png_ptr, 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 - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - { - pass = png_set_interlace_handling(png_ptr); - /* And make sure transforms are initialized. */ - png_start_read_image(png_ptr); - } - else - { - if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) - { - /* Caller called png_start_read_image or png_read_update_info without - * first turning on the PNG_INTERLACE transform. We can fix this here, - * but the caller should do it! - */ - png_warning(png_ptr, "Interlace handling should be turned on when " - "using png_read_image"); - /* Make sure this is set correctly */ - png_ptr->num_rows = png_ptr->height; - } - - /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in - * the above error case. - */ - 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; - - for (j = 0; j < pass; j++) - { - rp = image; - for (i = 0; i < image_height; i++) - { - png_read_row(png_ptr, *rp, 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 - { - png_uint_32 length = png_read_chunk_header(png_ptr); - png_uint_32 chunk_name = png_ptr->chunk_name; - - if (chunk_name == png_IHDR) - png_handle_IHDR(png_ptr, info_ptr, length); - - else if (chunk_name == png_IEND) - png_handle_IEND(png_ptr, info_ptr, length); - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - else if (png_chunk_unknown_handling(png_ptr, chunk_name) != - PNG_HANDLE_CHUNK_AS_DEFAULT) - { - if (chunk_name == png_IDAT) - { - if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) - png_benign_error(png_ptr, "Too many IDATs found"); - } - png_handle_unknown(png_ptr, info_ptr, length); - if (chunk_name == png_PLTE) - png_ptr->mode |= PNG_HAVE_PLTE; - } -#endif - - else if (chunk_name == png_IDAT) - { - /* 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_benign_error(png_ptr, "Too many IDATs found"); - - png_crc_finish(png_ptr, length); - } - else if (chunk_name == png_PLTE) - png_handle_PLTE(png_ptr, info_ptr, length); - -#ifdef PNG_READ_bKGD_SUPPORTED - else if (chunk_name == png_bKGD) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED - else if (chunk_name == png_cHRM) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_gAMA_SUPPORTED - else if (chunk_name == png_gAMA) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_hIST_SUPPORTED - else if (chunk_name == png_hIST) - png_handle_hIST(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED - else if (chunk_name == png_oFFs) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED - else if (chunk_name == png_pCAL) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED - else if (chunk_name == png_sCAL) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED - else if (chunk_name == png_pHYs) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED - else if (chunk_name == png_sBIT) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sRGB_SUPPORTED - else if (chunk_name == png_sRGB) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED - else if (chunk_name == png_iCCP) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED - else if (chunk_name == png_sPLT) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED - else if (chunk_name == png_tEXt) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tIME_SUPPORTED - else if (chunk_name == png_tIME) - png_handle_tIME(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tRNS_SUPPORTED - else if (chunk_name == png_tRNS) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED - else if (chunk_name == png_zTXt) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iTXt_SUPPORTED - else if (chunk_name == png_iTXt) - 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; -#ifdef PNG_WARNINGS_SUPPORTED - png_error_ptr warning_fn; -#endif - 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); - -#ifdef PNG_READ_GAMMA_SUPPORTED - png_destroy_gamma_table(png_ptr); -#endif - - png_free(png_ptr, png_ptr->zbuf); - png_free(png_ptr, png_ptr->big_row_buf); - png_free(png_ptr, png_ptr->big_prev_row); - png_free(png_ptr, png_ptr->chunkdata); - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - png_free(png_ptr, png_ptr->palette_lookup); - png_free(png_ptr, png_ptr->quantize_index); -#endif - - if (png_ptr->free_me & PNG_FREE_PLTE) - png_zfree(png_ptr, png_ptr->palette); - png_ptr->free_me &= ~PNG_FREE_PLTE; - -#if defined(PNG_tRNS_SUPPORTED) || \ - defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr->free_me & PNG_FREE_TRNS) - png_free(png_ptr, png_ptr->trans_alpha); - png_ptr->free_me &= ~PNG_FREE_TRNS; -#endif - -#ifdef PNG_READ_hIST_SUPPORTED - if (png_ptr->free_me & PNG_FREE_HIST) - png_free(png_ptr, png_ptr->hist); - png_ptr->free_me &= ~PNG_FREE_HIST; -#endif - - inflateEnd(&png_ptr->zstream); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_free(png_ptr, png_ptr->save_buffer); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -#ifdef PNG_TEXT_SUPPORTED - png_free(png_ptr, png_ptr->current_text); -#endif /* PNG_TEXT_SUPPORTED */ -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - - /* 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->longjmp_buffer, png_sizeof(jmp_buf)); -#endif - - error_fn = png_ptr->error_fn; -#ifdef PNG_WARNINGS_SUPPORTED - warning_fn = png_ptr->warning_fn; -#endif - 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; -#ifdef PNG_WARNINGS_SUPPORTED - png_ptr->warning_fn = warning_fn; -#endif - 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->longjmp_buffer, 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 || info_ptr == NULL) - return; - - /* 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_SCALE_16_TO_8_SUPPORTED - /* Tell libpng to strip 16-bit/color files down to 8 bits per color. - */ - if (transforms & PNG_TRANSFORM_SCALE_16) - { - /* Added at libpng-1.5.4. "strip_16" produces the same result that it - * did in earlier versions, while "scale_16" is now more accurate. - */ - png_set_scale_16(png_ptr); - } -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED - /* If both SCALE and STRIP are required pngrtran will effectively cancel the - * latter by doing SCALE first. This is ok and allows apps not to check for - * which is supported to get the right answer. - */ - 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 quantizing. - */ - -#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 - -/* Added at libpng-1.5.4 */ -#ifdef PNG_READ_EXPAND_16_SUPPORTED - if (transforms & PNG_TRANSFORM_EXPAND_16) - png_set_expand_16(png_ptr); -#endif - - /* We don't handle adding filler bytes */ - - /* We use png_read_image and rely on that for interlace handling, but we also - * call png_read_update_info therefore must turn on interlace handling now: - */ - (void)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 (i.e., you selected such a transform above). - */ - png_read_update_info(png_ptr, info_ptr); - - /* -------------- image transformations end here ------------------- */ - - png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); - if (info_ptr->row_pointers == NULL) - { - png_uint_32 iptr; - - info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, - info_ptr->height * png_sizeof(png_bytep)); - for (iptr=0; iptrheight; iptr++) - info_ptr->row_pointers[iptr] = NULL; - - info_ptr->free_me |= PNG_FREE_ROWS; - - 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); - - PNG_UNUSED(transforms) /* Quiet compiler warnings */ - PNG_UNUSED(params) - -} -#endif /* PNG_INFO_IMAGE_SUPPORTED */ -#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibPNG/pngrio.c b/plugins/FreeImage/Source/LibPNG/pngrio.c deleted file mode 100644 index d0d9d8a737..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngrio.c +++ /dev/null @@ -1,176 +0,0 @@ - -/* pngrio.c - functions for data input - * - * Last changed in libpng 1.5.0 [January 6, 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 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(...). - */ - -#include "pngpriv.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 PNGCBAPI -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. - */ - check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr); - - 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 PNGCBAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t 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) - { - check = fread(n_data, 1, length, io_ptr); - } - - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t read, remaining, err; - check = 0; - remaining = length; - - do - { - read = MIN(NEAR_BUF_SIZE, remaining); - err = fread(buf, 1, read, io_ptr); - 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, - "Can't set both read_data_fn and write_data_fn in the" - " same structure"); - } - -#ifdef PNG_WRITE_FLUSH_SUPPORTED - png_ptr->output_flush_fn = NULL; -#endif -} -#endif /* PNG_READ_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibPNG/pngrtran.c b/plugins/FreeImage/Source/LibPNG/pngrtran.c deleted file mode 100644 index bbee10ce56..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngrtran.c +++ /dev/null @@ -1,5023 +0,0 @@ - -/* pngrtran.c - transforms the data in a row for PNG readers - * - * Last changed in libpng 1.5.7 [December 15, 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. - */ - -#include "pngpriv.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; - } -} - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS via a background color */ -void PNGFAPI -png_set_background_fixed(png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, png_fixed_point background_gamma) -{ - png_debug(1, "in png_set_background_fixed"); - - 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_COMPOSE | PNG_STRIP_ALPHA; - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - - png_memcpy(&(png_ptr->background), background_color, - png_sizeof(png_color_16)); - png_ptr->background_gamma = background_gamma; - png_ptr->background_gamma_type = (png_byte)(background_gamma_code); - if (need_expand) - png_ptr->transformations |= PNG_BACKGROUND_EXPAND; - else - png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_background(png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma) -{ - png_set_background_fixed(png_ptr, background_color, background_gamma_code, - need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); -} -# endif /* FLOATING_POINT */ -#endif /* READ_BACKGROUND */ - -/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the - * one that pngrtran does first (scale) happens. This is necessary to allow the - * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. - */ -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED -void PNGAPI -png_set_scale_16(png_structp png_ptr) -{ - png_debug(1, "in png_set_scale_16"); - - if (png_ptr == NULL) - return; - - png_ptr->transformations |= PNG_SCALE_16_TO_8; -} -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED -/* Chop 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->transformations |= PNG_STRIP_ALPHA; -} -#endif - -#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) -static png_fixed_point -translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma, - int is_screen) -{ - /* Check for flag values. The main reason for having the old Mac value as a - * flag is that it is pretty near impossible to work out what the correct - * value is from Apple documentation - a working Mac system is needed to - * discover the value! - */ - if (output_gamma == PNG_DEFAULT_sRGB || - output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) - { - /* If there is no sRGB support this just sets the gamma to the standard - * sRGB value. (This is a side effect of using this function!) - */ -# ifdef PNG_READ_sRGB_SUPPORTED - png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; -# endif - if (is_screen) - output_gamma = PNG_GAMMA_sRGB; - else - output_gamma = PNG_GAMMA_sRGB_INVERSE; - } - - else if (output_gamma == PNG_GAMMA_MAC_18 || - output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) - { - if (is_screen) - output_gamma = PNG_GAMMA_MAC_OLD; - else - output_gamma = PNG_GAMMA_MAC_INVERSE; - } - - return output_gamma; -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -static png_fixed_point -convert_gamma_value(png_structp png_ptr, double output_gamma) -{ - /* The following silently ignores cases where fixed point (times 100,000) - * gamma values are passed to the floating point API. This is safe and it - * means the fixed point constants work just fine with the floating point - * API. The alternative would just lead to undetected errors and spurious - * bug reports. Negative values fail inside the _fixed API unless they - * correspond to the flag values. - */ - if (output_gamma > 0 && output_gamma < 128) - output_gamma *= PNG_FP_1; - - /* This preserves -1 and -2 exactly: */ - output_gamma = floor(output_gamma + .5); - - if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) - png_fixed_error(png_ptr, "gamma value"); - - return (png_fixed_point)output_gamma; -} -# endif -#endif /* READ_ALPHA_MODE || READ_GAMMA */ - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED -void PNGFAPI -png_set_alpha_mode_fixed(png_structp png_ptr, int mode, - png_fixed_point output_gamma) -{ - int compose = 0; - png_fixed_point file_gamma; - - png_debug(1, "in png_set_alpha_mode"); - - if (png_ptr == NULL) - return; - - output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); - - /* Validate the value to ensure it is in a reasonable range. The value - * is expected to be 1 or greater, but this range test allows for some - * viewing correction values. The intent is to weed out users of this API - * who use the inverse of the gamma value accidentally! Since some of these - * values are reasonable this may have to be changed. - */ - if (output_gamma < 70000 || output_gamma > 300000) - png_error(png_ptr, "output gamma out of expected range"); - - /* The default file gamma is the inverse of the output gamma; the output - * gamma may be changed below so get the file value first: - */ - file_gamma = png_reciprocal(output_gamma); - - /* There are really 8 possibilities here, composed of any combination - * of: - * - * premultiply the color channels - * do not encode non-opaque pixels - * encode the alpha as well as the color channels - * - * The differences disappear if the input/output ('screen') gamma is 1.0, - * because then the encoding is a no-op and there is only the choice of - * premultiplying the color channels or not. - * - * png_set_alpha_mode and png_set_background interact because both use - * png_compose to do the work. Calling both is only useful when - * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along - * with a default gamma value. Otherwise PNG_COMPOSE must not be set. - */ - switch (mode) - { - case PNG_ALPHA_PNG: /* default: png standard */ - /* No compose, but it may be set by png_set_background! */ - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - break; - - case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ - compose = 1; - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - /* The output is linear: */ - output_gamma = PNG_FP_1; - break; - - case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ - compose = 1; - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; - /* output_gamma records the encoding of opaque pixels! */ - break; - - case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ - compose = 1; - png_ptr->transformations |= PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - break; - - default: - png_error(png_ptr, "invalid alpha mode"); - } - - /* Only set the default gamma if the file gamma has not been set (this has - * the side effect that the gamma in a second call to png_set_alpha_mode will - * be ignored.) - */ - if (png_ptr->gamma == 0) - png_ptr->gamma = file_gamma; - - /* But always set the output gamma: */ - png_ptr->screen_gamma = output_gamma; - - /* Finally, if pre-multiplying, set the background fields to achieve the - * desired result. - */ - if (compose) - { - /* And obtain alpha pre-multiplication by composing on black: */ - png_memset(&png_ptr->background, 0, sizeof png_ptr->background); - png_ptr->background_gamma = png_ptr->gamma; /* just in case */ - png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; - png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; - - if (png_ptr->transformations & PNG_COMPOSE) - png_error(png_ptr, - "conflicting calls to set alpha mode and background"); - - png_ptr->transformations |= PNG_COMPOSE; - } - - /* New API, make sure apps call the correct initializers: */ - png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma) -{ - png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, - output_gamma)); -} -# endif -#endif - -#ifdef PNG_READ_QUANTIZE_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_quantize" indicates - * whether we need a quantizing 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_quantize(png_structp png_ptr, png_colorp palette, - int num_palette, int maximum_colors, png_const_uint_16p histogram, - int full_quantize) -{ - png_debug(1, "in png_set_quantize"); - - if (png_ptr == NULL) - return; - - png_ptr->transformations |= PNG_QUANTIZE; - - if (!full_quantize) - { - int i; - - png_ptr->quantize_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->quantize_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->quantize_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)(num_palette * png_sizeof(png_byte))); - - /* Initialize the quantize_sort array */ - for (i = 0; i < num_palette; i++) - png_ptr->quantize_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->quantize_sort[j]] - < histogram[png_ptr->quantize_sort[j + 1]]) - { - png_byte t; - - t = png_ptr->quantize_sort[j]; - png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; - png_ptr->quantize_sort[j + 1] = t; - done = 0; - } - } - - if (done) - break; - } - - /* Swap the palette around, and set up a table, if necessary */ - if (full_quantize) - { - 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->quantize_sort[i] >= maximum_colors) - { - do - j--; - while ((int)png_ptr->quantize_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->quantize_sort[i] >= maximum_colors) - { - png_color tmp_color; - - do - j--; - while ((int)png_ptr->quantize_sort[j] >= maximum_colors); - - tmp_color = palette[j]; - palette[j] = palette[i]; - palette[i] = tmp_color; - /* Indicate where the color went */ - png_ptr->quantize_index[j] = (png_byte)i; - png_ptr->quantize_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->quantize_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->quantize_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->quantize_index[i] = (png_byte)min_k; - } - } - } - png_free(png_ptr, png_ptr->quantize_sort); - png_ptr->quantize_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_quantize) - { - int k; - - for (k = 0; k < num_palette; k++) - { - if (png_ptr->quantize_index[k] == - png_ptr->index_to_palette[j]) - png_ptr->quantize_index[k] = - png_ptr->index_to_palette[next_j]; - - if ((int)png_ptr->quantize_index[k] == - num_new_palette) - png_ptr->quantize_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_quantize) - { - int i; - png_bytep distance; - int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + - PNG_QUANTIZE_BLUE_BITS; - int num_red = (1 << PNG_QUANTIZE_RED_BITS); - int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); - int num_blue = (1 << PNG_QUANTIZE_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_QUANTIZE_RED_BITS)); - int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); - int b = (palette[i].blue >> (8 - PNG_QUANTIZE_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_QUANTIZE_BLUE_BITS + - PNG_QUANTIZE_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_QUANTIZE_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 /* PNG_READ_QUANTIZE_SUPPORTED */ - -#ifdef PNG_READ_GAMMA_SUPPORTED -void PNGFAPI -png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, - png_fixed_point file_gamma) -{ - png_debug(1, "in png_set_gamma_fixed"); - - if (png_ptr == NULL) - return; - - /* New in libpng-1.5.4 - reserve particular negative values as flags. */ - scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); - file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); - -#if PNG_LIBPNG_VER >= 10600 - /* Checking the gamma values for being >0 was added in 1.5.4 along with the - * premultiplied alpha support; this actually hides an undocumented feature - * of the previous implementation which allowed gamma processing to be - * disabled in background handling. There is no evidence (so far) that this - * was being used; however, png_set_background itself accepted and must still - * accept '0' for the gamma value it takes, because it isn't always used. - * - * Since this is an API change (albeit a very minor one that removes an - * undocumented API feature) it will not be made until libpng-1.6.0. - */ - if (file_gamma <= 0) - png_error(png_ptr, "invalid file gamma in png_set_gamma"); - - if (scrn_gamma <= 0) - png_error(png_ptr, "invalid screen gamma in png_set_gamma"); -#endif - - /* Set the gamma values unconditionally - this overrides the value in the PNG - * file if a gAMA chunk was present. png_set_alpha_mode provides a - * different, easier, way to default the file gamma. - */ - png_ptr->gamma = file_gamma; - png_ptr->screen_gamma = scrn_gamma; -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) -{ - png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), - convert_gamma_value(png_ptr, file_gamma)); -} -# endif /* FLOATING_POINT_SUPPORTED */ -#endif /* READ_GAMMA */ - -#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; -} - -/* 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; -} - - - -/* 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_EXPAND_16_SUPPORTED -/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise - * it may not work correctly.) - */ -void PNGAPI -png_set_expand_16(png_structp png_ptr) -{ - png_debug(1, "in png_set_expand_16"); - - if (png_ptr == NULL) - return; - - png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; - - /* New API, make sure apps call the correct initializers: */ - png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; -} -#endif - -#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"); - - if (png_ptr != NULL) - { - /* Because rgb must be 8 bits or more: */ - png_set_expand_gray_1_2_4_to_8(png_ptr); - png_ptr->transformations |= PNG_GRAY_TO_RGB; - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; - } -} -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -void PNGFAPI -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 PNG_ERROR_ACTION_NONE: - png_ptr->transformations |= PNG_RGB_TO_GRAY; - break; - - case PNG_ERROR_ACTION_WARN: - png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; - break; - - case PNG_ERROR_ACTION_ERROR: - png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; - break; - - default: - png_error(png_ptr, "invalid error action to rgb_to_gray"); - break; - } - 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 - { - if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) - { - png_uint_16 red_int, green_int; - - /* NOTE: this calculation does not round, but this behavior is retained - * for consistency, the inaccuracy is very small. The code here always - * overwrites the coefficients, regardless of whether they have been - * defaulted or set already. - */ - red_int = (png_uint_16)(((png_uint_32)red*32768)/100000); - green_int = (png_uint_16)(((png_uint_32)green*32768)/100000); - - png_ptr->rgb_to_gray_red_coeff = red_int; - png_ptr->rgb_to_gray_green_coeff = green_int; - png_ptr->rgb_to_gray_coefficients_set = 1; - } - - else - { - if (red >= 0 && green >= 0) - png_warning(png_ptr, - "ignoring out of range rgb_to_gray coefficients"); - - /* Use the defaults, from the cHRM chunk if set, else the historical - * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See - * png_do_rgb_to_gray for more discussion of the values. In this case - * the coefficients are not marked as 'set' and are not overwritten if - * something has already provided a default. - */ - if (png_ptr->rgb_to_gray_red_coeff == 0 && - png_ptr->rgb_to_gray_green_coeff == 0) - { - png_ptr->rgb_to_gray_red_coeff = 6968; - png_ptr->rgb_to_gray_green_coeff = 23434; - /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ - } - } - } -} - -#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) -{ - if (png_ptr == NULL) - return; - - png_set_rgb_to_gray_fixed(png_ptr, error_action, - png_fixed(png_ptr, red, "rgb to gray red coefficient"), - png_fixed(png_ptr, green, "rgb to gray green coefficient")); -} -#endif /* FLOATING POINT */ - -#endif - -#if defined(PNG_READ_USER_TRANSFORM_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 -} -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -#ifdef PNG_READ_GAMMA_SUPPORTED -/* In the case of gamma transformations 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. - */ -static int /* PRIVATE */ -png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) -{ - /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma - * correction as a difference of the overall transform from 1.0 - * - * We want to compare the threshold with s*f - 1, if we get - * overflow here it is because of wacky gamma values so we - * turn on processing anyway. - */ - png_fixed_point gtest; - return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || - png_gamma_significant(gtest); -} -#endif - -/* Initialize everything needed for the read. This includes modifying - * the palette. - */ - -/*For the moment 'png_init_palette_transformations' and - * 'png_init_rgb_transformations' only do some flag canceling optimizations. - * The intent is that these two routines should have palette or rgb operations - * extracted from 'png_init_read_transformations'. - */ -static void /* PRIVATE */ -png_init_palette_transformations(png_structp png_ptr) -{ - /* Called to handle the (input) palette case. In png_do_read_transformations - * the first step is to expand the palette if requested, so this code must - * take care to only make changes that are invariant with respect to the - * palette expansion, or only do them if there is no expansion. - * - * STRIP_ALPHA has already been handled in the caller (by setting num_trans - * to 0.) - */ - int input_has_alpha = 0; - int input_has_transparency = 0; - - if (png_ptr->num_trans > 0) - { - int i; - - /* Ignore if all the entries are opaque (unlikely!) */ - for (i=0; inum_trans; ++i) - if (png_ptr->trans_alpha[i] == 255) - continue; - else if (png_ptr->trans_alpha[i] == 0) - input_has_transparency = 1; - else - input_has_alpha = 1; - } - - /* If no alpha we can optimize. */ - if (!input_has_alpha) - { - /* Any alpha means background and associative alpha processing is - * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA - * and ENCODE_ALPHA are irrelevant. - */ - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - - if (!input_has_transparency) - png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); - } - -#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) - /* png_set_background handling - deals with the complexity of whether the - * background color is in the file format or the screen format in the case - * where an 'expand' will happen. - */ - - /* The following code cannot be entered in the alpha pre-multiplication case - * because PNG_BACKGROUND_EXPAND is cancelled below. - */ - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND)) - { - { - 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) - { - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - /* Invert the alpha channel (in tRNS) unless the pixels are - * going to be expanded, in which case leave it for later - */ - int i, istop = png_ptr->num_trans; - - for (i=0; itrans_alpha[i] = (png_byte)(255 - - png_ptr->trans_alpha[i]); - } - } -#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ - } - } /* background expand and (therefore) no alpha association. */ -#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ -} - -static void /* PRIVATE */ -png_init_rgb_transformations(png_structp png_ptr) -{ - /* Added to libpng-1.5.4: check the color type to determine whether there - * is any alpha or transparency in the image and simply cancel the - * background and alpha mode stuff if there isn't. - */ - int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; - int input_has_transparency = png_ptr->num_trans > 0; - - /* If no alpha we can optimize. */ - if (!input_has_alpha) - { - /* Any alpha means background and associative alpha processing is - * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA - * and ENCODE_ALPHA are irrelevant. - */ -# ifdef PNG_READ_ALPHA_MODE_SUPPORTED - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; -# endif - - if (!input_has_transparency) - png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); - } - -#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) - /* png_set_background handling - deals with the complexity of whether the - * background color is in the file format or the screen format in the case - * where an 'expand' will happen. - */ - - /* The following code cannot be entered in the alpha pre-multiplication case - * because PNG_BACKGROUND_EXPAND is cancelled below. - */ - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND) && - !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) - /* i.e., GRAY or GRAY_ALPHA */ - { - { - /* Expand background and tRNS chunks */ - int gray = png_ptr->background.gray; - int trans_gray = png_ptr->trans_color.gray; - - switch (png_ptr->bit_depth) - { - case 1: - gray *= 0xff; - trans_gray *= 0xff; - break; - - case 2: - gray *= 0x55; - trans_gray *= 0x55; - break; - - case 4: - gray *= 0x11; - trans_gray *= 0x11; - break; - - default: - - case 8: - /* Already 8 bits, fall through */ - - case 16: - /* Already a full 16 bits */ - break; - } - - png_ptr->background.red = png_ptr->background.green = - png_ptr->background.blue = (png_uint_16)gray; - - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_color.red = png_ptr->trans_color.green = - png_ptr->trans_color.blue = (png_uint_16)trans_gray; - } - } - } /* background expand and (therefore) no alpha association. */ -#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ -} - -void /* PRIVATE */ -png_init_read_transformations(png_structp png_ptr) -{ - png_debug(1, "in png_init_read_transformations"); - - /* This internal function is called from png_read_start_row in pngrutil.c - * and it is called before the 'rowbytes' calculation is done, so the code - * in here can change or update the transformations flags. - * - * First do updates that do not depend on the details of the PNG image data - * being processed. - */ - -#ifdef PNG_READ_GAMMA_SUPPORTED - /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds - * png_set_alpha_mode and this is another source for a default file gamma so - * the test needs to be performed later - here. In addition prior to 1.5.4 - * the tests were repeated for the PALETTE color type here - this is no - * longer necessary (and doesn't seem to have been necessary before.) - */ - { - /* The following temporary indicates if overall gamma correction is - * required. - */ - int gamma_correction = 0; - - if (png_ptr->gamma != 0) /* has been set */ - { - if (png_ptr->screen_gamma != 0) /* screen set too */ - gamma_correction = png_gamma_threshold(png_ptr->gamma, - png_ptr->screen_gamma); - - else - /* Assume the output matches the input; a long time default behavior - * of libpng, although the standard has nothing to say about this. - */ - png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma); - } - - else if (png_ptr->screen_gamma != 0) - /* The converse - assume the file matches the screen, note that this - * perhaps undesireable default can (from 1.5.4) be changed by calling - * png_set_alpha_mode (even if the alpha handling mode isn't required - * or isn't changed from the default.) - */ - png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma); - - else /* neither are set */ - /* Just in case the following prevents any processing - file and screen - * are both assumed to be linear and there is no way to introduce a - * third gamma value other than png_set_background with 'UNIQUE', and, - * prior to 1.5.4 - */ - png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1; - - /* Now turn the gamma transformation on or off as appropriate. Notice - * that PNG_GAMMA just refers to the file->screen correction. Alpha - * composition may independently cause gamma correction because it needs - * linear data (e.g. if the file has a gAMA chunk but the screen gamma - * hasn't been specified.) In any case this flag may get turned off in - * the code immediately below if the transform can be handled outside the - * row loop. - */ - if (gamma_correction) - png_ptr->transformations |= PNG_GAMMA; - - else - png_ptr->transformations &= ~PNG_GAMMA; - } -#endif - - /* Certain transformations have the effect of preventing other - * transformations that happen afterward in png_do_read_transformations, - * resolve the interdependencies here. From the code of - * png_do_read_transformations the order is: - * - * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) - * 2) PNG_STRIP_ALPHA (if no compose) - * 3) PNG_RGB_TO_GRAY - * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY - * 5) PNG_COMPOSE - * 6) PNG_GAMMA - * 7) PNG_STRIP_ALPHA (if compose) - * 8) PNG_ENCODE_ALPHA - * 9) PNG_SCALE_16_TO_8 - * 10) PNG_16_TO_8 - * 11) PNG_QUANTIZE (converts to palette) - * 12) PNG_EXPAND_16 - * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY - * 14) PNG_INVERT_MONO - * 15) PNG_SHIFT - * 16) PNG_PACK - * 17) PNG_BGR - * 18) PNG_PACKSWAP - * 19) PNG_FILLER (includes PNG_ADD_ALPHA) - * 20) PNG_INVERT_ALPHA - * 21) PNG_SWAP_ALPHA - * 22) PNG_SWAP_BYTES - * 23) PNG_USER_TRANSFORM [must be last] - */ -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if ((png_ptr->transformations & PNG_STRIP_ALPHA) && - !(png_ptr->transformations & PNG_COMPOSE)) - { - /* Stripping the alpha channel happens immediately after the 'expand' - * transformations, before all other transformation, so it cancels out - * the alpha handling. It has the side effect negating the effect of - * PNG_EXPAND_tRNS too: - */ - png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | - PNG_EXPAND_tRNS); - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - - /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen - * so transparency information would remain just so long as it wasn't - * expanded. This produces unexpected API changes if the set of things - * that do PNG_EXPAND_tRNS changes (perfectly possible given the - * documentation - which says ask for what you want, accept what you - * get.) This makes the behavior consistent from 1.5.4: - */ - png_ptr->num_trans = 0; - } -#endif /* STRIP_ALPHA supported, no COMPOSE */ - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED - /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA - * settings will have no effect. - */ - if (!png_gamma_significant(png_ptr->screen_gamma)) - { - png_ptr->transformations &= ~PNG_ENCODE_ALPHA; - png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; - } -#endif - -#if defined(PNG_READ_EXPAND_SUPPORTED) && \ - defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(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. - * - * TODO: this code needs to be revised to avoid the complexity and - * interdependencies. The color type of the background should be recorded in - * png_set_background, along with the bit depth, then the code has a record - * of exactly what color space the background is currently in. - */ - if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) - { - /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if - * the file was grayscale the background value is gray. - */ - if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - } - - else if (png_ptr->transformations & PNG_COMPOSE) - { - /* PNG_COMPOSE: png_set_background was called with need_expand false, - * so the color is in the color space of the output or png_set_alpha_mode - * was called and the color is black. Ignore RGB_TO_GRAY because that - * happens before GRAY_TO_RGB. - */ - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - { - if (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 /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */ - - /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations - * can be performed directly on the palette, and some (such as rgb to gray) - * can be optimized inside the palette. This is particularly true of the - * composite (background and alpha) stuff, which can be pretty much all done - * in the palette even if the result is expanded to RGB or gray afterward. - * - * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and - * earlier and the palette stuff is actually handled on the first row. This - * leads to the reported bug that the palette returned by png_get_PLTE is not - * updated. - */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_init_palette_transformations(png_ptr); - - else - png_init_rgb_transformations(png_ptr); - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(PNG_READ_EXPAND_16_SUPPORTED) - if ((png_ptr->transformations & PNG_EXPAND_16) && - (png_ptr->transformations & PNG_COMPOSE) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - png_ptr->bit_depth != 16) - { - /* TODO: fix this. Because the expand_16 operation is after the compose - * handling the background color must be 8, not 16, bits deep, but the - * application will supply a 16-bit value so reduce it here. - * - * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at - * present, so that case is ok (until do_expand_16 is moved.) - * - * NOTE: this discards the low 16 bits of the user supplied background - * color, but until expand_16 works properly there is no choice! - */ -# define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16)) - CHOP(png_ptr->background.red); - CHOP(png_ptr->background.green); - CHOP(png_ptr->background.blue); - CHOP(png_ptr->background.gray); -# undef CHOP - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ - defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) - if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) && - (png_ptr->transformations & PNG_COMPOSE) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - png_ptr->bit_depth == 16) - { - /* On the other hand, if a 16-bit file is to be reduced to 8-bits per - * component this will also happen after PNG_COMPOSE and so the background - * color must be pre-expanded here. - * - * TODO: fix this too. - */ - png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257); - png_ptr->background.green = - (png_uint_16)(png_ptr->background.green * 257); - png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257); - png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257); - } -#endif - - /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the - * background support (see the comments in scripts/pnglibconf.dfa), this - * allows pre-multiplication of the alpha channel to be implemented as - * compositing on black. This is probably sub-optimal and has been done in - * 1.5.4 betas simply to enable external critique and testing (i.e. to - * implement the new API quickly, without lots of internal changes.) - */ - -#ifdef PNG_READ_GAMMA_SUPPORTED -# ifdef PNG_READ_BACKGROUND_SUPPORTED - /* Includes ALPHA_MODE */ - png_ptr->background_1 = png_ptr->background; -# endif - - /* This needs to change - in the palette image case a whole set of tables are - * built when it would be quicker to just calculate the correct value for - * each palette entry directly. Also, the test is too tricky - why check - * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that - * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the - * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction - * the gamma tables will not be built even if composition is required on a - * gamma encoded value. - * - * In 1.5.4 this is addressed below by an additional check on the individual - * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the - * tables. - */ - if ((png_ptr->transformations & PNG_GAMMA) - || ((png_ptr->transformations & PNG_RGB_TO_GRAY) - && (png_gamma_significant(png_ptr->gamma) || - png_gamma_significant(png_ptr->screen_gamma))) - || ((png_ptr->transformations & PNG_COMPOSE) - && (png_gamma_significant(png_ptr->gamma) - || png_gamma_significant(png_ptr->screen_gamma) -# ifdef PNG_READ_BACKGROUND_SUPPORTED - || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE - && png_gamma_significant(png_ptr->background_gamma)) -# endif - )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) - && png_gamma_significant(png_ptr->screen_gamma)) - ) - { - png_build_gamma_table(png_ptr, png_ptr->bit_depth); - -#ifdef PNG_READ_BACKGROUND_SUPPORTED - if (png_ptr->transformations & PNG_COMPOSE) - { - /* Issue a warning about this combination: because RGB_TO_GRAY is - * optimized to do the gamma transform if present yet do_background has - * to do the same thing if both options are set a - * double-gamma-correction happens. This is true in all versions of - * libpng to date. - */ - if (png_ptr->transformations & PNG_RGB_TO_GRAY) - png_warning(png_ptr, - "libpng does not support gamma+background+rgb_to_gray"); - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - /* We don't get to here unless there is a tRNS chunk with non-opaque - * entries - see the checking code at the start of this function. - */ - 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 - { - png_fixed_point g, gs; - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = (png_ptr->screen_gamma); - gs = PNG_FP_1; - break; - - case PNG_BACKGROUND_GAMMA_FILE: - g = png_reciprocal(png_ptr->gamma); - gs = png_reciprocal2(png_ptr->gamma, - png_ptr->screen_gamma); - break; - - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = png_reciprocal(png_ptr->background_gamma); - gs = png_reciprocal2(png_ptr->background_gamma, - png_ptr->screen_gamma); - break; - default: - g = PNG_FP_1; /* back_1 */ - gs = PNG_FP_1; /* back */ - break; - } - - if (png_gamma_significant(gs)) - { - back.red = png_gamma_8bit_correct(png_ptr->background.red, - gs); - back.green = png_gamma_8bit_correct(png_ptr->background.green, - gs); - back.blue = png_gamma_8bit_correct(png_ptr->background.blue, - gs); - } - - else - { - back.red = (png_byte)png_ptr->background.red; - back.green = (png_byte)png_ptr->background.green; - back.blue = (png_byte)png_ptr->background.blue; - } - - if (png_gamma_significant(g)) - { - back_1.red = png_gamma_8bit_correct(png_ptr->background.red, - g); - back_1.green = png_gamma_8bit_correct( - png_ptr->background.green, g); - back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, - g); - } - - else - { - back_1.red = (png_byte)png_ptr->background.red; - back_1.green = (png_byte)png_ptr->background.green; - back_1.blue = (png_byte)png_ptr->background.blue; - } - } - - for (i = 0; i < num_palette; i++) - { - if (i < (int)png_ptr->num_trans && - png_ptr->trans_alpha[i] != 0xff) - { - if (png_ptr->trans_alpha[i] == 0) - { - palette[i] = back; - } - else /* if (png_ptr->trans_alpha[i] != 0xff) */ - { - png_byte v, w; - - v = png_ptr->gamma_to_1[palette[i].red]; - png_composite(w, v, png_ptr->trans_alpha[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_alpha[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_alpha[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. - * - * NOTE: this is highly dubious; it removes the transformations in - * place. This seems inconsistent with the general treatment of the - * transformations elsewhere. - */ - png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); - } /* color_type == PNG_COLOR_TYPE_PALETTE */ - - /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ - else /* color_type != PNG_COLOR_TYPE_PALETTE */ - { - int gs_sig, g_sig; - png_fixed_point g = PNG_FP_1; /* Correction to linear */ - png_fixed_point gs = PNG_FP_1; /* Correction to screen */ - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = png_ptr->screen_gamma; - /* gs = PNG_FP_1; */ - break; - - case PNG_BACKGROUND_GAMMA_FILE: - g = png_reciprocal(png_ptr->gamma); - gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma); - break; - - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = png_reciprocal(png_ptr->background_gamma); - gs = png_reciprocal2(png_ptr->background_gamma, - png_ptr->screen_gamma); - break; - - default: - png_error(png_ptr, "invalid background gamma type"); - } - - g_sig = png_gamma_significant(g); - gs_sig = png_gamma_significant(gs); - - if (g_sig) - png_ptr->background_1.gray = png_gamma_correct(png_ptr, - png_ptr->background.gray, g); - - if (gs_sig) - png_ptr->background.gray = png_gamma_correct(png_ptr, - png_ptr->background.gray, gs); - - 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 */ - if (g_sig) - { - png_ptr->background_1.red = png_gamma_correct(png_ptr, - png_ptr->background.red, g); - - png_ptr->background_1.green = png_gamma_correct(png_ptr, - png_ptr->background.green, g); - - png_ptr->background_1.blue = png_gamma_correct(png_ptr, - png_ptr->background.blue, g); - } - - if (gs_sig) - { - png_ptr->background.red = png_gamma_correct(png_ptr, - png_ptr->background.red, gs); - - png_ptr->background.green = png_gamma_correct(png_ptr, - png_ptr->background.green, gs); - - png_ptr->background.blue = png_gamma_correct(png_ptr, - png_ptr->background.blue, gs); - } - } - - 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; - } - - /* The background is now in screen gamma: */ - png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN; - } /* color_type != PNG_COLOR_TYPE_PALETTE */ - }/* png_ptr->transformations & PNG_BACKGROUND */ - - else - /* Transformation does not include PNG_BACKGROUND */ -#endif /* PNG_READ_BACKGROUND_SUPPORTED */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - /* RGB_TO_GRAY needs to have non-gamma-corrected values! */ - && ((png_ptr->transformations & PNG_EXPAND) == 0 || - (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) -#endif - ) - { - png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; - - /*NOTE: there are other transformations that should probably be in here - * too. - */ - 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; - } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ - } -#ifdef PNG_READ_BACKGROUND_SUPPORTED - else -#endif -#endif /* PNG_READ_GAMMA_SUPPORTED */ - -#ifdef PNG_READ_BACKGROUND_SUPPORTED - /* No GAMMA transformation (see the hanging else 4 lines above) */ - if ((png_ptr->transformations & PNG_COMPOSE) && - (png_ptr->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_alpha[i] == 0) - { - palette[i] = back; - } - - else if (png_ptr->trans_alpha[i] != 0xff) - { - /* The png_composite() macro is defined in png.h */ - png_composite(palette[i].red, palette[i].red, - png_ptr->trans_alpha[i], back.red); - - png_composite(palette[i].green, palette[i].green, - png_ptr->trans_alpha[i], back.green); - - png_composite(palette[i].blue, palette[i].blue, - png_ptr->trans_alpha[i], back.blue); - } - } - - png_ptr->transformations &= ~PNG_COMPOSE; - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED */ - -#ifdef PNG_READ_SHIFT_SUPPORTED - if ((png_ptr->transformations & PNG_SHIFT) && - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) - { - int i; - int istop = png_ptr->num_palette; - int shift = 8 - png_ptr->sig_bit.red; - - /* significant bits can be in the range 1 to 7 for a meaninful result, if - * the number of significant bits is 0 then no shift is done (this is an - * error condition which is silently ignored.) - */ - if (shift > 0 && shift < 8) for (i=0; ipalette[i].red; - - component >>= shift; - png_ptr->palette[i].red = (png_byte)component; - } - - shift = 8 - png_ptr->sig_bit.green; - if (shift > 0 && shift < 8) for (i=0; ipalette[i].green; - - component >>= shift; - png_ptr->palette[i].green = (png_byte)component; - } - - shift = 8 - png_ptr->sig_bit.blue; - if (shift > 0 && shift < 8) for (i=0; ipalette[i].blue; - - component >>= shift; - png_ptr->palette[i].blue = (png_byte)component; - } - } -#endif /* PNG_READ_SHIFT_SUPPORTED */ -} - -/* 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) - { - /* This check must match what actually happens in - * png_do_expand_palette; if it ever checks the tRNS chunk to see if - * it is all opaque we must do the same (at present it does not.) - */ - if (png_ptr->num_trans > 0) - 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 - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) - /* The following is almost certainly wrong unless the background value is in - * the screen space! - */ - if (png_ptr->transformations & PNG_COMPOSE) - info_ptr->background = png_ptr->background; -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED - /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), - * however it seems that the code in png_init_read_transformations, which has - * been called before this from png_read_update_info->png_read_start_row - * sometimes does the gamma transform and cancels the flag. - */ - info_ptr->gamma = png_ptr->gamma; -#endif - - if (info_ptr->bit_depth == 16) - { -# ifdef PNG_READ_16BIT_SUPPORTED -# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED - if (png_ptr->transformations & PNG_SCALE_16_TO_8) - info_ptr->bit_depth = 8; -# endif - -# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED - if (png_ptr->transformations & PNG_16_TO_8) - info_ptr->bit_depth = 8; -# endif - -# else - /* No 16 bit support: force chopping 16-bit input down to 8, in this case - * the app program can chose if both APIs are available by setting the - * correct scaling to use. - */ -# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED - /* For compatibility with previous versions use the strip method by - * default. This code works because if PNG_SCALE_16_TO_8 is already - * set the code below will do that in preference to the chop. - */ - png_ptr->transformations |= PNG_16_TO_8; - info_ptr->bit_depth = 8; -# else - -# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED - png_ptr->transformations |= PNG_SCALE_16_TO_8; - info_ptr->bit_depth = 8; -# else - - CONFIGURATION ERROR: you must enable at least one 16 to 8 method -# endif -# endif -#endif /* !READ_16BIT_SUPPORTED */ - } - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - info_ptr->color_type = (png_byte)(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_byte)(info_ptr->color_type & - ~PNG_COLOR_MASK_COLOR); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - if (png_ptr->transformations & PNG_QUANTIZE) - { - 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_EXPAND_16_SUPPORTED - if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 && - info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - { - info_ptr->bit_depth = 16; - } -#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->transformations & PNG_STRIP_ALPHA) - { - info_ptr->color_type = (png_byte)(info_ptr->color_type & - ~PNG_COLOR_MASK_ALPHA); - info_ptr->num_trans = 0; - } -#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 */ - if (png_ptr->transformations & PNG_ADD_ALPHA) - info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; - } -#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); - - /* Adding in 1.5.4: cache the above value in png_struct so that we can later - * check in png_rowbytes that the user buffer won't get overwritten. Note - * that the field is not always set - if png_read_update_info isn't called - * the application has to either not do any transforms or get the calculation - * right itself. - */ - png_ptr->info_rowbytes = info_ptr->rowbytes; - -#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_row_infop row_info) -{ - png_debug(1, "in png_do_read_transformations"); - - if (png_ptr->row_buf == NULL) - { - /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this - * error is incredibly rare and incredibly easy to debug without this - * information. - */ - png_error(png_ptr, "NULL row buffer"); - } - - /* The following is debugging; prior to 1.5.4 the code was never compiled in; - * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro - * PNG_WARN_UNINITIALIZED_ROW removed. In 1.5 the new flag is set only for - * selected new APIs to ensure that there is no API change. - */ - if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && - !(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 (but not enabled until 1.5.4). - */ - png_error(png_ptr, "Uninitialized row"); - } - -#ifdef PNG_READ_EXPAND_SUPPORTED - if (png_ptr->transformations & PNG_EXPAND) - { - if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) - { - png_do_expand_palette(row_info, png_ptr->row_buf + 1, - png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); - } - - else - { - if (png_ptr->num_trans && - (png_ptr->transformations & PNG_EXPAND_tRNS)) - png_do_expand(row_info, png_ptr->row_buf + 1, - &(png_ptr->trans_color)); - - else - png_do_expand(row_info, png_ptr->row_buf + 1, - NULL); - } - } -#endif - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if ((png_ptr->transformations & PNG_STRIP_ALPHA) && - !(png_ptr->transformations & PNG_COMPOSE) && - (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || - row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) - png_do_strip_channel(row_info, png_ptr->row_buf + 1, - 0 /* at_start == false, because SWAP_ALPHA happens later */); -#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, 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(row_info, png_ptr->row_buf + 1); -#endif - -#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ - (defined PNG_READ_ALPHA_MODE_SUPPORTED) - if (png_ptr->transformations & PNG_COMPOSE) - png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED - if ((png_ptr->transformations & PNG_GAMMA) && -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - /* Because RGB_TO_GRAY does the gamma transform. */ - !(png_ptr->transformations & PNG_RGB_TO_GRAY) && -#endif -#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ - (defined PNG_READ_ALPHA_MODE_SUPPORTED) - /* Because PNG_COMPOSE does the gamma transform if there is something to - * do (if there is an alpha channel or transparency.) - */ - !((png_ptr->transformations & PNG_COMPOSE) && - ((png_ptr->num_trans != 0) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && -#endif - /* Because png_init_read_transformations transforms the palette, unless - * RGB_TO_GRAY will do the transform. - */ - (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) - png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr); -#endif - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if ((png_ptr->transformations & PNG_STRIP_ALPHA) && - (png_ptr->transformations & PNG_COMPOSE) && - (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || - row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) - png_do_strip_channel(row_info, png_ptr->row_buf + 1, - 0 /* at_start == false, because SWAP_ALPHA happens later */); -#endif - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED - if ((png_ptr->transformations & PNG_ENCODE_ALPHA) && - (row_info->color_type & PNG_COLOR_MASK_ALPHA)) - png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr); -#endif - -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED - if (png_ptr->transformations & PNG_SCALE_16_TO_8) - png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED - /* There is no harm in doing both of these because only one has any effect, - * by putting the 'scale' option first if the app asks for scale (either by - * calling the API or in a TRANSFORM flag) this is what happens. - */ - if (png_ptr->transformations & PNG_16_TO_8) - png_do_chop(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - if (png_ptr->transformations & PNG_QUANTIZE) - { - png_do_quantize(row_info, png_ptr->row_buf + 1, - png_ptr->palette_lookup, png_ptr->quantize_index); - - if (row_info->rowbytes == 0) - png_error(png_ptr, "png_do_quantize returned rowbytes=0"); - } -#endif /* PNG_READ_QUANTIZE_SUPPORTED */ - -#ifdef PNG_READ_EXPAND_16_SUPPORTED - /* Do the expansion now, after all the arithmetic has been done. Notice - * that previous transformations can handle the PNG_EXPAND_16 flag if this - * is efficient (particularly true in the case of gamma correction, where - * better accuracy results faster!) - */ - if (png_ptr->transformations & PNG_EXPAND_16) - png_do_expand_16(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED - /*NOTE: moved here in 1.5.4 (from much later in this list.) */ - if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_INVERT_SUPPORTED - if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_SHIFT_SUPPORTED - if (png_ptr->transformations & PNG_SHIFT) - png_do_unshift(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(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_BGR_SUPPORTED - if (png_ptr->transformations & PNG_BGR) - png_do_bgr(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_PACKSWAP_SUPPORTED - if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_FILLER_SUPPORTED - if (png_ptr->transformations & PNG_FILLER) - png_do_read_filler(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(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(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_READ_16BIT_SUPPORTED -#ifdef PNG_READ_SWAP_SUPPORTED - if (png_ptr->transformations & PNG_SWAP_BYTES) - png_do_swap(row_info, png_ptr->row_buf + 1); -#endif -#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 */ - row_info, /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_size_t 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) - row_info->bit_depth = png_ptr->user_transform_depth; - - if (png_ptr->user_transform_channels) - row_info->channels = png_ptr->user_transform_channels; -#endif - row_info->pixel_depth = (png_byte)(row_info->bit_depth * - row_info->channels); - - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 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"); - - if (row_info->bit_depth < 8) - { - 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; - } - - default: - 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_const_color_8p sig_bits) -{ - int color_type; - - png_debug(1, "in png_do_unshift"); - - /* The palette case has already been handled in the _init routine. */ - color_type = row_info->color_type; - - if (color_type != PNG_COLOR_TYPE_PALETTE) - { - int shift[4]; - int channels = 0; - int bit_depth = row_info->bit_depth; - - if (color_type & PNG_COLOR_MASK_COLOR) - { - shift[channels++] = bit_depth - sig_bits->red; - shift[channels++] = bit_depth - sig_bits->green; - shift[channels++] = bit_depth - sig_bits->blue; - } - - else - { - shift[channels++] = bit_depth - sig_bits->gray; - } - - if (color_type & PNG_COLOR_MASK_ALPHA) - { - shift[channels++] = bit_depth - sig_bits->alpha; - } - - { - int c, have_shift; - - for (c = have_shift = 0; c < channels; ++c) - { - /* A shift of more than the bit depth is an error condition but it - * gets ignored here. - */ - if (shift[c] <= 0 || shift[c] >= bit_depth) - shift[c] = 0; - - else - have_shift = 1; - } - - if (!have_shift) - return; - } - - switch (bit_depth) - { - default: - /* Must be 1bpp gray: should not be here! */ - /* NOTREACHED */ - break; - - case 2: - /* Must be 2bpp gray */ - /* assert(channels == 1 && shift[0] == 1) */ - { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; - - while (bp < bp_end) - { - int b = (*bp >> 1) & 0x55; - *bp++ = (png_byte)b; - } - break; - } - - case 4: - /* Must be 4bpp gray */ - /* assert(channels == 1) */ - { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; - int gray_shift = shift[0]; - int mask = 0xf >> gray_shift; - - mask |= mask << 4; - - while (bp < bp_end) - { - int b = (*bp >> gray_shift) & mask; - *bp++ = (png_byte)b; - } - break; - } - - case 8: - /* Single byte components, G, GA, RGB, RGBA */ - { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; - int channel = 0; - - while (bp < bp_end) - { - int b = *bp >> shift[channel]; - if (++channel >= channels) - channel = 0; - *bp++ = (png_byte)b; - } - break; - } - -#ifdef PNG_READ_16BIT_SUPPORTED - case 16: - /* Double byte components, G, GA, RGB, RGBA */ - { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; - int channel = 0; - - while (bp < bp_end) - { - int value = (bp[0] << 8) + bp[1]; - - value >>= shift[channel]; - if (++channel >= channels) - channel = 0; - *bp++ = (png_byte)(value >> 8); - *bp++ = (png_byte)(value & 0xff); - } - break; - } -#endif - } - } -} -#endif - -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED -/* Scale rows of bit depth 16 down to 8 accurately */ -void /* PRIVATE */ -png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_scale_16_to_8"); - - if (row_info->bit_depth == 16) - { - png_bytep sp = row; /* source */ - png_bytep dp = row; /* destination */ - png_bytep ep = sp + row_info->rowbytes; /* end+1 */ - - while (sp < ep) - { - /* The input is an array of 16 bit components, these must be scaled to - * 8 bits each. For a 16 bit value V the required value (from the PNG - * specification) is: - * - * (V * 255) / 65535 - * - * This reduces to round(V / 257), or floor((V + 128.5)/257) - * - * Represent V as the two byte value vhi.vlo. Make a guess that the - * result is the top byte of V, vhi, then the correction to this value - * is: - * - * error = floor(((V-vhi.vhi) + 128.5) / 257) - * = floor(((vlo-vhi) + 128.5) / 257) - * - * This can be approximated using integer arithmetic (and a signed - * shift): - * - * error = (vlo-vhi+128) >> 8; - * - * The approximate differs from the exact answer only when (vlo-vhi) is - * 128; it then gives a correction of +1 when the exact correction is - * 0. This gives 128 errors. The exact answer (correct for all 16 bit - * input values) is: - * - * error = (vlo-vhi+128)*65535 >> 24; - * - * An alternative arithmetic calculation which also gives no errors is: - * - * (V * 255 + 32895) >> 16 - */ - - png_int_32 tmp = *sp++; /* must be signed! */ - tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; - *dp++ = (png_byte)tmp; - } - - 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_STRIP_16_TO_8_SUPPORTED -void /* PRIVATE */ -/* Simply discard the low byte. This was the default behavior prior - * to libpng-1.5.4. - */ -png_do_chop(png_row_infop row_info, png_bytep row) -{ - png_debug(1, "in png_do_chop"); - - if (row_info->bit_depth == 16) - { - png_bytep sp = row; /* source */ - png_bytep dp = row; /* destination */ - png_bytep ep = sp + row_info->rowbytes; /* end+1 */ - - while (sp < ep) - { - *dp++ = *sp; - sp += 2; /* skip low byte */ - } - - 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"); - - { - 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; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - /* 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]; - } - } -#endif - } - - 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; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - /* 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 - } - } -} -#endif - -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED -void /* PRIVATE */ -png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) -{ - png_uint_32 row_width; - png_debug(1, "in png_do_read_invert_alpha"); - - row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This inverts the alpha channel in RGBA */ - 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; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - /* 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; - } - } -#endif - } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This inverts the alpha channel in GA */ - 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); - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - else - { - /* This inverts the alpha channel in GGAA */ - 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 - } -} -#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; - -#ifdef PNG_READ_16BIT_SUPPORTED - png_byte hi_filler = (png_byte)((filler>>8) & 0xff); -#endif - png_byte lo_filler = (png_byte)(filler & 0xff); - - png_debug(1, "in png_do_read_filler"); - - if ( - row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - if (row_info->bit_depth == 8) - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This changes the data from G to GX */ - 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; - } - - else - { - /* This changes the data from G to XG */ - 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; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - else if (row_info->bit_depth == 16) - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This changes the data from GG to GGXX */ - 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; - } - - else - { - /* This changes the data from GG to XXGG */ - 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; - } - } -#endif - } /* COLOR_TYPE == GRAY */ - else if (row_info->color_type == PNG_COLOR_TYPE_RGB) - { - if (row_info->bit_depth == 8) - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This changes the data from RGB to RGBX */ - 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; - } - - else - { - /* This changes the data from RGB to XRGB */ - 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; - } - } - -#ifdef PNG_READ_16BIT_SUPPORTED - else if (row_info->bit_depth == 16) - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This changes the data from RRGGBB to RRGGBBXX */ - 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; - } - - else - { - /* This changes the data from RRGGBB to XXRRGGBB */ - 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; - } - } -#endif - } /* 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 && - !(row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - if (row_info->bit_depth == 8) - { - /* This changes G to RGB */ - 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 - { - /* This changes GG to RRGGBB */ - 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) - { - /* This changes GA to RGBA */ - 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 - { - /* This changes GGAA to RRGGBBAA */ - 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)(row_info->channels + 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 of 1998-01-04 at - * (THIS LINK IS DEAD June 2008 but - * versions dated 1998 through November 2002 have been archived at - * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ - * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) - * Charles Poynton poynton at poynton.com - * - * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B - * - * which can be expressed with integers as - * - * Y = (6969 * R + 23434 * G + 2365 * B)/32768 - * - * Poynton's current link (as of January 2003 through July 2011): - * - * has changed the numbers slightly: - * - * Y = 0.2126*R + 0.7152*G + 0.0722*B - * - * which can be expressed with integers as - * - * Y = (6966 * R + 23436 * G + 2366 * B)/32768 - * - * Historically, however, libpng uses numbers derived from the ITU-R Rec 709 - * end point chromaticities and the D65 white point. Depending on the - * precision used for the D65 white point this produces a variety of different - * numbers, however if the four decimal place value used in ITU-R Rec 709 is - * used (0.3127,0.3290) the Y calculation would be: - * - * Y = (6968 * R + 23435 * G + 2366 * B)/32768 - * - * While this is correct the rounding results in an overflow for white, because - * the sum of the rounded coefficients is 32769, not 32768. Consequently - * libpng uses, instead, the closest non-overflowing approximation: - * - * Y = (6968 * R + 23434 * G + 2366 * B)/32768 - * - * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk - * (including an sRGB chunk) then the chromaticities are used to calculate the - * coefficients. See the chunk handling in pngrutil.c for more information. - * - * In all cases the calculation is to be done in a linear colorspace. If no - * gamma information is available to correct the encoding of the original RGB - * values this results in an implicit assumption that the original PNG RGB - * values were linear. - * - * Other integer coefficents can be used via png_set_rgb_to_gray(). Because - * the API takes just red and green coefficients the blue coefficient is - * calculated to make the sum 32768. This will result in different rounding - * to that used above. - */ -int /* PRIVATE */ -png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) - -{ - int rgb_error = 0; - - png_debug(1, "in png_do_rgb_to_gray"); - - if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && - (row_info->color_type & PNG_COLOR_MASK_COLOR)) - { - PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; - PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; - PNG_CONST png_uint_32 bc = 32768 - rc - gc; - PNG_CONST png_uint_32 row_width = row_info->width; - PNG_CONST int have_alpha = - (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; - - if (row_info->bit_depth == 8) - { -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - /* Notice that gamma to/from 1 are not necessarily inverses (if - * there is an overall gamma correction). Prior to 1.5.5 this code - * checked the linearized values for equality; this doesn't match - * the documentation, the original values must be checked. - */ - if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) - { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - - for (i = 0; i < row_width; i++) - { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); - - if (red != green || red != blue) - { - red = png_ptr->gamma_to_1[red]; - green = png_ptr->gamma_to_1[green]; - blue = png_ptr->gamma_to_1[blue]; - - rgb_error |= 1; - *(dp++) = png_ptr->gamma_from_1[ - (rc*red + gc*green + bc*blue + 16384)>>15]; - } - - else - { - /* If there is no overall correction the table will not be - * set. - */ - if (png_ptr->gamma_table != NULL) - red = png_ptr->gamma_table[red]; - - *(dp++) = red; - } - - if (have_alpha) - *(dp++) = *(sp++); - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - - 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; - /*NOTE: this is the historical approach which simply - * truncates the results. - */ - *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); - } - - else - *(dp++) = red; - - if (have_alpha) - *(dp++) = *(sp++); - } - } - } - - 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; - png_uint_32 i; - - 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) - { - if (png_ptr->gamma_16_table != NULL) - w = png_ptr->gamma_16_table[(red&0xff) - >> png_ptr->gamma_shift][red>>8]; - - else - 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 + 16384)>>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); - - if (have_alpha) - { - *(dp++) = *(sp++); - *(dp++) = *(sp++); - } - } - } - else -#endif - { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - - 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; - - /* From 1.5.5 in the 16 bit case do the accurate conversion even - * in the 'fast' case - this is because this is where the code - * ends up when handling linear 16 bit data. - */ - gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> - 15); - *(dp++) = (png_byte)((gray16>>8) & 0xff); - *(dp++) = (png_byte)(gray16 & 0xff); - - if (have_alpha) - { - *(dp++) = *(sp++); - *(dp++) = *(sp++); - } - } - } - } - - row_info->channels = (png_byte)(row_info->channels - 2); - row_info->color_type = (png_byte)(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 -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -/* 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. This API is not used internally. - */ -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; - } -} -#endif - - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ - (defined PNG_READ_ALPHA_MODE_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_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr) -{ -#ifdef PNG_READ_GAMMA_SUPPORTED - png_const_bytep gamma_table = png_ptr->gamma_table; - png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; - png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; - png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; - png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; - png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; - int gamma_shift = png_ptr->gamma_shift; -#endif - - png_bytep sp; - png_uint_32 i; - png_uint_32 row_width = row_info->width; - int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; - int shift; - - png_debug(1, "in png_do_compose"); - - { - 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) - == png_ptr->trans_color.gray) - { - *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *sp |= (png_byte)(png_ptr->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) - == png_ptr->trans_color.gray) - { - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(png_ptr->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) - == png_ptr->trans_color.gray) - { - *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(png_ptr->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) - == png_ptr->trans_color.gray) - { - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(png_ptr->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) - == png_ptr->trans_color.gray) - { - *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(png_ptr->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 == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - - else - *sp = gamma_table[*sp]; - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->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 == png_ptr->trans_color.gray) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->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 == png_ptr->trans_color.gray) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } - } - } - break; - } - - default: - 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 == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->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 == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->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 == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(png_ptr->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 == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(png_ptr->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; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 a = *(sp + 1); - - if (a == 0xff) - *sp = gamma_table[*sp]; - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.gray; - } - - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.gray); - if (!optimize) - w = gamma_from_1[w]; - *sp = w; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_byte a = *(sp + 1); - - if (a == 0) - *sp = (png_byte)png_ptr->background.gray; - - else if (a < 0xff) - png_composite(*sp, *sp, a, png_ptr->background_1.gray); - } - } - } - 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; - for (i = 0; i < row_width; i++, sp += 4) - { - 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]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } - - else - { - png_uint_16 g, v, w; - - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, png_ptr->background_1.gray); - if (optimize) - w = v; - else - w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } - - else if (a < 0xffff) - { - png_uint_16 g, v; - - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, png_ptr->background_1.gray); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } - } - } - } - 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; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); - - if (a == 0xff) - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } - - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else - { - png_byte v, w; - - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.red); - if (!optimize) w = gamma_from_1[w]; - *sp = w; - - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, png_ptr->background_1.green); - if (!optimize) w = gamma_from_1[w]; - *(sp + 1) = w; - - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, png_ptr->background_1.blue); - if (!optimize) w = gamma_from_1[w]; - *(sp + 2) = w; - } - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); - - if (a == 0) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } - - else if (a < 0xff) - { - png_composite(*sp, *sp, a, png_ptr->background.red); - - png_composite(*(sp + 1), *(sp + 1), a, - png_ptr->background.green); - - png_composite(*(sp + 2), *(sp + 2), a, - png_ptr->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; - for (i = 0; i < row_width; i++, sp += 8) - { - 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]; - *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 if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else - { - png_uint_16 v, w; - - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, png_ptr->background_1.red); - if (!optimize) - w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, png_ptr->background_1.green); - if (!optimize) - w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - - *(sp + 2) = (png_byte)((w >> 8) & 0xff); - *(sp + 3) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, png_ptr->background_1.blue); - if (!optimize) - w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - - *(sp + 4) = (png_byte)((w >> 8) & 0xff); - *(sp + 5) = (png_byte)(w & 0xff); - } - } - } - - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); - - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } - - else if (a < 0xffff) - { - 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, png_ptr->background.red); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - - png_composite_16(v, g, a, png_ptr->background.green); - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - png_composite_16(v, b, a, png_ptr->background.blue); - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } - } - } - } - break; - } - - default: - break; - } - } -} -#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */ - -#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_structp png_ptr) -{ - png_const_bytep gamma_table = png_ptr->gamma_table; - png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; - int gamma_shift = png_ptr->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 (((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; - } - - default: - break; - } - } -} -#endif - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED -/* Encode the alpha channel to the output gamma (the input channel is always - * linear.) Called only with color types that have an alpha channel. Needs the - * from_1 tables. - */ -void /* PRIVATE */ -png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr) -{ - png_uint_32 row_width = row_info->width; - - png_debug(1, "in png_do_encode_alpha"); - - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - if (row_info->bit_depth == 8) - { - PNG_CONST png_bytep table = png_ptr->gamma_from_1; - - if (table != NULL) - { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; - - /* The alpha channel is the last component: */ - row += step - 1; - - for (; row_width > 0; --row_width, row += step) - *row = table[*row]; - - return; - } - } - - else if (row_info->bit_depth == 16) - { - PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; - PNG_CONST int gamma_shift = png_ptr->gamma_shift; - - if (table != NULL) - { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; - - /* The alpha channel is the last component: */ - row += step - 2; - - for (; row_width > 0; --row_width, row += step) - { - png_uint_16 v; - - v = table[*(row + 1) >> gamma_shift][*row]; - *row = (png_byte)((v >> 8) & 0xff); - *(row + 1) = (png_byte)(v & 0xff); - } - - return; - } - } - } - - /* Only get to here if called with a weird row_info; no harm has been done, - * so just issue a warning. - */ - png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); -} -#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_const_colorp palette, png_const_bytep trans_alpha, 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 (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; - } - - default: - break; - } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (row_info->bit_depth == 8) - { - { - if (num_trans > 0) - { - 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_alpha[*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; - } - } - } - } -} - -/* 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_const_color_16p trans_color) -{ - 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"); - - { - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->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; - } - - default: - break; - } - - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (trans_color != 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 = (png_byte)((gray >> 8) & 0xff); - png_byte gray_low = (png_byte)(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_color) - { - if (row_info->bit_depth == 8) - { - png_byte red = (png_byte)(trans_color->red & 0xff); - png_byte green = (png_byte)(trans_color->green & 0xff); - png_byte blue = (png_byte)(trans_color->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 = (png_byte)((trans_color->red >> 8) & 0xff); - png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); - png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); - png_byte red_low = (png_byte)(trans_color->red & 0xff); - png_byte green_low = (png_byte)(trans_color->green & 0xff); - png_byte blue_low = (png_byte)(trans_color->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_EXPAND_16_SUPPORTED -/* If the bit depth is 8 and the color type is not a palette type expand the - * whole row to 16 bits. Has no effect otherwise. - */ -void /* PRIVATE */ -png_do_expand_16(png_row_infop row_info, png_bytep row) -{ - if (row_info->bit_depth == 8 && - row_info->color_type != PNG_COLOR_TYPE_PALETTE) - { - /* The row have a sequence of bytes containing [0..255] and we need - * to turn it into another row containing [0..65535], to do this we - * calculate: - * - * (input / 255) * 65535 - * - * Which happens to be exactly input * 257 and this can be achieved - * simply by byte replication in place (copying backwards). - */ - png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ - png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ - while (dp > sp) - dp[-2] = dp[-1] = *--sp, dp -= 2; - - row_info->rowbytes *= 2; - row_info->bit_depth = 16; - row_info->pixel_depth = (png_byte)(row_info->channels * 16); - } -} -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -void /* PRIVATE */ -png_do_quantize(png_row_infop row_info, png_bytep row, - png_const_bytep palette_lookup, png_const_bytep quantize_lookup) -{ - png_bytep sp, dp; - png_uint_32 i; - png_uint_32 row_width=row_info->width; - - png_debug(1, "in png_do_quantize"); - - if (row_info->bit_depth == 8) - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) - { - 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_QUANTIZE_RED_BITS)) & - ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << - (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | - (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & - ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << - (PNG_QUANTIZE_BLUE_BITS)) | - ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & - ((1 << PNG_QUANTIZE_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) - { - 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_QUANTIZE_RED_BITS)) & - ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << - (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | - (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & - ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << - (PNG_QUANTIZE_BLUE_BITS)) | - ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & - ((1 << PNG_QUANTIZE_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 && - quantize_lookup) - { - sp = row; - - for (i = 0; i < row_width; i++, sp++) - { - *sp = quantize_lookup[*sp]; - } - } - } -} -#endif /* PNG_READ_QUANTIZE_SUPPORTED */ -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -#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 ( - (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 = (s0 + s1 + 65536) & 0xffff; - png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; - *(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/plugins/FreeImage/Source/LibPNG/pngrutil.c b/plugins/FreeImage/Source/LibPNG/pngrutil.c deleted file mode 100644 index 995896dbc5..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngrutil.c +++ /dev/null @@ -1,4158 +0,0 @@ - -/* pngrutil.c - utilities to read a PNG file - * - * Last changed in libpng 1.5.9 [February 18, 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. - */ - -#include "pngpriv.h" - -#ifdef PNG_READ_SUPPORTED - -#define png_strtod(p,a,b) strtod(a,b) - -png_uint_32 PNGAPI -png_get_uint_31(png_structp png_ptr, png_const_bytep buf) -{ - png_uint_32 uval = png_get_uint_32(buf); - - if (uval > PNG_UINT_31_MAX) - png_error(png_ptr, "PNG unsigned integer out of range"); - - return (uval); -} - -#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) -/* The following is a variation on the above for use with the fixed - * point values used for gAMA and cHRM. Instead of png_error it - * issues a warning and returns (-1) - an invalid value because both - * gAMA and cHRM use *unsigned* integers for fixed point values. - */ -#define PNG_FIXED_ERROR (-1) - -static png_fixed_point /* PRIVATE */ -png_get_fixed_point(png_structp png_ptr, png_const_bytep buf) -{ - png_uint_32 uval = png_get_uint_32(buf); - - if (uval <= PNG_UINT_31_MAX) - return (png_fixed_point)uval; /* known to be in range */ - - /* The caller can turn off the warning by passing NULL. */ - if (png_ptr != NULL) - png_warning(png_ptr, "PNG fixed point integer out of range"); - - return PNG_FIXED_ERROR; -} -#endif - -#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED -/* NOTE: the read macros will obscure these definitions, so that if - * PNG_USE_READ_MACROS is set the library will not use them internally, - * but the APIs will still be available externally. - * - * The parentheses around "PNGAPI function_name" in the following three - * functions are necessary because they allow the macros to co-exist with - * these (unused but exported) functions. - */ - -/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ -png_uint_32 (PNGAPI -png_get_uint_32)(png_const_bytep buf) -{ - png_uint_32 uval = - ((png_uint_32)(*(buf )) << 24) + - ((png_uint_32)(*(buf + 1)) << 16) + - ((png_uint_32)(*(buf + 2)) << 8) + - ((png_uint_32)(*(buf + 3)) ) ; - - return uval; -} - -/* 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 there - * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore - * the following code does a two's complement to native conversion. - */ -png_int_32 (PNGAPI -png_get_int_32)(png_const_bytep buf) -{ - png_uint_32 uval = png_get_uint_32(buf); - if ((uval & 0x80000000) == 0) /* non-negative */ - return uval; - - uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ - return -(png_int_32)uval; -} - -/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ -png_uint_16 (PNGAPI -png_get_uint_16)(png_const_bytep buf) -{ - /* ANSI-C requires an int value to accomodate at least 16 bits so this - * works and allows the compiler not to worry about possible narrowing - * on 32 bit systems. (Pre-ANSI systems did not make integers smaller - * than 16 bits either.) - */ - unsigned int val = - ((unsigned int)(*buf) << 8) + - ((unsigned int)(*(buf + 1))); - - return (png_uint_16)val; -} - -#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */ - -/* Read and check the PNG file signature */ -void /* PRIVATE */ -png_read_sig(png_structp png_ptr, png_infop info_ptr) -{ - png_size_t num_checked, num_to_check; - - /* Exit if the user application does not expect a signature. */ - if (png_ptr->sig_bytes >= 8) - return; - - num_checked = png_ptr->sig_bytes; - num_to_check = 8 - num_checked; - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; -#endif - - /* The signature must be serialized in a single I/O call. */ - 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; -} - -/* 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; - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; -#endif - - /* Read the length and the chunk name. - * This must be performed in a single I/O call. - */ - 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_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4); - - png_debug2(0, "Reading %lx chunk, length = %lu", - (unsigned long)png_ptr->chunk_name, (unsigned long)length); - - /* Reset the crc and run it over the chunk name. */ - png_reset_crc(png_ptr); - png_calculate_crc(png_ptr, buf + 4, 4); - - /* Check to see if chunk name is valid. */ - png_check_chunk_name(png_ptr, png_ptr->chunk_name); - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; -#endif - - 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_CHUNK_ANCILLIARY(png_ptr->chunk_name) ? - !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) : - (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)) - { - png_chunk_warning(png_ptr, "CRC error"); - } - - else - { - png_chunk_benign_error(png_ptr, "CRC error"); - return (0); - } - - 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_CHUNK_ANCILLIARY(png_ptr->chunk_name)) - { - 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; - } - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; -#endif - - /* The chunk CRC must be serialized in a single I/O call. */ - 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); -} - -#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED -static png_size_t -png_inflate(png_structp png_ptr, png_bytep data, png_size_t size, - png_bytep output, png_size_t output_size) -{ - png_size_t count = 0; - - /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't - * even necessarily handle 65536 bytes) because the type uInt is "16 bits or - * more". Consequently it is necessary to chunk the input to zlib. This - * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value - * that can be stored in a uInt.) It is possible to set ZLIB_IO_MAX to a - * lower value in pngpriv.h and this may sometimes have a performance - * advantage, because it forces access of the input data to be separated from - * at least some of the use by some period of time. - */ - png_ptr->zstream.next_in = data; - /* avail_in is set below from 'size' */ - png_ptr->zstream.avail_in = 0; - - while (1) - { - int ret, avail; - - /* The setting of 'avail_in' used to be outside the loop; by setting it - * inside it is possible to chunk the input to zlib and simply rely on - * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o - * data to be passed through zlib at the unavoidable cost of requiring a - * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX - * input bytes. - */ - if (png_ptr->zstream.avail_in == 0 && size > 0) - { - if (size <= ZLIB_IO_MAX) - { - /* The value is less than ZLIB_IO_MAX so the cast is safe: */ - png_ptr->zstream.avail_in = (uInt)size; - size = 0; - } - - else - { - png_ptr->zstream.avail_in = ZLIB_IO_MAX; - size -= ZLIB_IO_MAX; - } - } - - /* 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) - { - png_size_t space = avail; /* > 0, see above */ - - if (output != 0 && output_size > count) - { - png_size_t copy = output_size - count; - - if (space < copy) - copy = space; - - png_memcpy(output + count, png_ptr->zbuf, copy); - } - count += space; - } - - 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. - */ -# ifdef PNG_WARNINGS_SUPPORTED - { - png_const_charp msg; - - if (png_ptr->zstream.msg != 0) - msg = png_ptr->zstream.msg; - - else switch (ret) - { - case Z_BUF_ERROR: - msg = "Buffer error in compressed datastream"; - break; - - case Z_DATA_ERROR: - msg = "Data error in compressed datastream"; - break; - - default: - msg = "Incomplete compressed datastream"; - break; - } - - png_chunk_warning(png_ptr, msg); - } -# endif - - /* 0 means an error - notice that this code simply 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_SET_CHUNK_MALLOC_LIMIT_SUPPORTED - || (png_ptr->user_chunk_malloc_max && - (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1)) -#else -# ifdef PNG_USER_CHUNK_MALLOC_MAX - || ((PNG_USER_CHUNK_MALLOC_MAX > 0) && - prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) -# endif -#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_charp)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) */ - { - PNG_WARNING_PARAMETERS(p) - png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, comp_type); - png_formatted_warning(png_ptr, p, "Unknown compression type @1"); - - /* 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_charp)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 /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */ - -/* 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) - { - default: /* invalid, png_set_IHDR calls png_error */ - 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", (unsigned long)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_benign_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); - - PNG_UNUSED(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; - 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_get_fixed_point(NULL, buf); - - /* Check for zero gamma or an error. */ - if (igamma <= 0) - { - png_warning(png_ptr, - "Ignoring gAMA chunk with out of range gamma"); - - return; - } - -# ifdef PNG_READ_sRGB_SUPPORTED - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) - { - if (PNG_OUT_OF_RANGE(igamma, 45500, 500)) - { - PNG_WARNING_PARAMETERS(p) - png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, igamma); - png_formatted_warning(png_ptr, p, - "Ignoring incorrect gAMA value @1 when sRGB is also present"); - return; - } - } -# endif /* PNG_READ_sRGB_SUPPORTED */ - -# ifdef PNG_READ_GAMMA_SUPPORTED - /* Gamma correction on read is supported. */ - png_ptr->gamma = igamma; -# endif - /* And set the 'info' structure members. */ - png_set_gAMA_fixed(png_ptr, info_ptr, igamma); -} -#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]; - png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue, - y_blue; - - 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, "Out of place cHRM chunk"); - - 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; - - x_white = png_get_fixed_point(NULL, buf); - y_white = png_get_fixed_point(NULL, buf + 4); - x_red = png_get_fixed_point(NULL, buf + 8); - y_red = png_get_fixed_point(NULL, buf + 12); - x_green = png_get_fixed_point(NULL, buf + 16); - y_green = png_get_fixed_point(NULL, buf + 20); - x_blue = png_get_fixed_point(NULL, buf + 24); - y_blue = png_get_fixed_point(NULL, buf + 28); - - if (x_white == PNG_FIXED_ERROR || - y_white == PNG_FIXED_ERROR || - x_red == PNG_FIXED_ERROR || - y_red == PNG_FIXED_ERROR || - x_green == PNG_FIXED_ERROR || - y_green == PNG_FIXED_ERROR || - x_blue == PNG_FIXED_ERROR || - y_blue == PNG_FIXED_ERROR) - { - png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities"); - return; - } - -#ifdef PNG_READ_sRGB_SUPPORTED - if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) - { - if (PNG_OUT_OF_RANGE(x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(x_red, 64000, 1000) || - PNG_OUT_OF_RANGE(y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(y_green, 60000, 1000) || - PNG_OUT_OF_RANGE(x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(y_blue, 6000, 1000)) - { - PNG_WARNING_PARAMETERS(p) - - png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, x_white); - png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_fixed, y_white); - png_warning_parameter_signed(p, 3, PNG_NUMBER_FORMAT_fixed, x_red); - png_warning_parameter_signed(p, 4, PNG_NUMBER_FORMAT_fixed, y_red); - png_warning_parameter_signed(p, 5, PNG_NUMBER_FORMAT_fixed, x_green); - png_warning_parameter_signed(p, 6, PNG_NUMBER_FORMAT_fixed, y_green); - png_warning_parameter_signed(p, 7, PNG_NUMBER_FORMAT_fixed, x_blue); - png_warning_parameter_signed(p, 8, PNG_NUMBER_FORMAT_fixed, y_blue); - - png_formatted_warning(png_ptr, p, - "Ignoring incorrect cHRM white(@1,@2) r(@3,@4)g(@5,@6)b(@7,@8) " - "when sRGB is also present"); - } - return; - } -#endif /* PNG_READ_sRGB_SUPPORTED */ - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - /* Store the _white values as default coefficients for the rgb to gray - * operation if it is supported. Check if the transform is already set to - * avoid destroying the transform values. - */ - if (!png_ptr->rgb_to_gray_coefficients_set) - { - /* png_set_background has not been called and we haven't seen an sRGB - * chunk yet. Find the XYZ of the three end points. - */ - png_XYZ XYZ; - png_xy xy; - - xy.redx = x_red; - xy.redy = y_red; - xy.greenx = x_green; - xy.greeny = y_green; - xy.bluex = x_blue; - xy.bluey = y_blue; - xy.whitex = x_white; - xy.whitey = y_white; - - if (png_XYZ_from_xy_checked(png_ptr, &XYZ, xy)) - { - /* The success case, because XYZ_from_xy normalises to a reference - * white Y of 1.0 we just need to scale the numbers. This should - * always work just fine. It is an internal error if this overflows. - */ - { - png_fixed_point r, g, b; - if (png_muldiv(&r, XYZ.redY, 32768, PNG_FP_1) && - r >= 0 && r <= 32768 && - png_muldiv(&g, XYZ.greenY, 32768, PNG_FP_1) && - g >= 0 && g <= 32768 && - png_muldiv(&b, XYZ.blueY, 32768, PNG_FP_1) && - b >= 0 && b <= 32768 && - r+g+b <= 32769) - { - /* We allow 0 coefficients here. r+g+b may be 32769 if two or - * all of the coefficients were rounded up. Handle this by - * reducing the *largest* coefficient by 1; this matches the - * approach used for the default coefficients in pngrtran.c - */ - int add = 0; - - if (r+g+b > 32768) - add = -1; - else if (r+g+b < 32768) - add = 1; - - if (add != 0) - { - if (g >= r && g >= b) - g += add; - else if (r >= g && r >= b) - r += add; - else - b += add; - } - - /* Check for an internal error. */ - if (r+g+b != 32768) - png_error(png_ptr, - "internal error handling cHRM coefficients"); - - png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r; - png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g; - } - - /* This is a png_error at present even though it could be ignored - - * it should never happen, but it is important that if it does, the - * bug is fixed. - */ - else - png_error(png_ptr, "internal error handling cHRM->XYZ"); - } - } - } -#endif - - png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red, - x_green, y_green, x_blue, y_blue); -} -#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)) - { - if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500, 500)) - { - PNG_WARNING_PARAMETERS(p) - - png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, - info_ptr->gamma); - - png_formatted_warning(png_ptr, p, - "Ignoring incorrect gAMA value @1 when sRGB is also present"); - } - } -#endif /* PNG_READ_gAMA_SUPPORTED */ - -#ifdef PNG_READ_cHRM_SUPPORTED - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) - if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) || - PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) || - PNG_OUT_OF_RANGE(info_ptr->x_red, 64000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->y_green, 60000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) || - PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000)) - { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); - } -#endif /* PNG_READ_cHRM_SUPPORTED */ - - /* This is recorded for use when handling the cHRM chunk above. An sRGB - * chunk unconditionally overwrites the coefficients for grayscale conversion - * too. - */ - png_ptr->is_sRGB = 1; - -# ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - /* Don't overwrite user supplied values: */ - if (!png_ptr->rgb_to_gray_coefficients_set) - { - /* These numbers come from the sRGB specification (or, since one has to - * pay much money to get a copy, the wikipedia sRGB page) the - * chromaticity values quoted have been inverted to get the reverse - * transformation from RGB to XYZ and the 'Y' coefficients scaled by - * 32768 (then rounded). - * - * sRGB and ITU Rec-709 both truncate the values for the D65 white - * point to four digits and, even though it actually stores five - * digits, the PNG spec gives the truncated value. - * - * This means that when the chromaticities are converted back to XYZ - * end points we end up with (6968,23435,2366), which, as described in - * pngrtran.c, would overflow. If the five digit precision and up is - * used we get, instead: - * - * 6968*R + 23435*G + 2365*B - * - * (Notice that this rounds the blue coefficient down, rather than the - * choice used in pngrtran.c which is to round the green one down.) - */ - png_ptr->rgb_to_gray_red_coeff = 6968; /* 0.212639005871510 */ - png_ptr->rgb_to_gray_green_coeff = 23434; /* 0.715168678767756 */ - /* png_ptr->rgb_to_gray_blue_coeff = 2366; 0.072192315360734 */ - - /* The following keeps the cHRM chunk from destroying the - * coefficients again in the event that it follows the sRGB chunk. - */ - png_ptr->rgb_to_gray_coefficients_set = 1; - } -# endif - - 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; - png_alloc_size_t 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 = 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)) ); - - /* NOTE: the following guarantees that 'profile_length' fits into 32 bits, - * because profile_size is a 32 bit value. - */ - if (profile_size < profile_length) - profile_length = profile_size; - - /* And the following guarantees that profile_size == profile_length. */ - if (profile_size > profile_length) - { - PNG_WARNING_PARAMETERS(p) - - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; - - png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_u, profile_size); - png_warning_parameter_unsigned(p, 2, PNG_NUMBER_FORMAT_u, profile_length); - png_formatted_warning(png_ptr, p, - "Ignoring iCCP chunk with declared size = @1 and actual length = @2"); - return; - } - - png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, - compression_type, (png_bytep)png_ptr->chunkdata + prefix_length, - profile_size); - 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; - png_sPLT_entryp pp; - png_uint_32 data_length; - int entry_size, i; - png_uint_32 skip = 0; - png_size_t slength; - png_uint_32 dl; - png_size_t max_dl; - - 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); - - /* WARNING: this may break if size_t is less than 32 bits; it is assumed - * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a - * potential breakage point if the types in pngconf.h aren't exactly right. - */ - slength = 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); - /* This must fit in a png_uint_32 because it is derived from the original - * chunk data length (and use 'length', not 'slength' here for clarity - - * they are guaranteed to be the same, see the tests above.) - */ - data_length = length - (png_uint_32)(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; - } - - dl = (png_int_32)(data_length / entry_size); - max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry); - - if (dl > max_dl) - { - png_warning(png_ptr, "sPLT chunk too long"); - return; - } - - new_palette.nentries = (png_int_32)(data_length / entry_size); - - 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[i].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_color.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_color.red = png_get_uint_16(buf); - png_ptr->trans_color.green = png_get_uint_16(buf + 2); - png_ptr->trans_color.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_color)); -} -#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_color_16 background; - - 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) - { - 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; - } - - background.red = (png_uint_16)png_ptr->palette[buf[0]].red; - background.green = (png_uint_16)png_ptr->palette[buf[0]].green; - background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue; - } - - else - background.red = background.green = background.blue = 0; - - background.gray = 0; - } - - else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ - { - background.index = 0; - background.red = - background.green = - background.blue = - background.gray = png_get_uint_16(buf); - } - - else - { - background.index = 0; - background.red = png_get_uint_16(buf); - background.green = png_get_uint_16(buf + 2); - background.blue = png_get_uint_16(buf + 4); - background.gray = 0; - } - - png_set_bKGD(png_ptr, info_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; - } - - num = length / 2 ; - - if (num != (unsigned int)png_ptr->num_palette || num > - (unsigned int)PNG_MAX_PALETTE_LENGTH) - { - png_warning(png_ptr, "Incorrect hIST chunk length"); - png_crc_finish(png_ptr, length); - return; - } - - 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 (%u 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 = 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_size_t)(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_size_t slength, i; - int state; - - 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 (%u 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 = length; - png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); - png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ - - if (png_crc_finish(png_ptr, 0)) - { - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; - return; - } - - /* Validate the unit. */ - if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2) - { - png_warning(png_ptr, "Invalid sCAL ignored: invalid unit"); - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; - return; - } - - /* Validate the ASCII numbers, need two ASCII numbers separated by - * a '\0' and they need to fit exactly in the chunk data. - */ - i = 1; - state = 0; - - if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || - i >= slength || png_ptr->chunkdata[i++] != 0) - png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format"); - - else if (!PNG_FP_IS_POSITIVE(state)) - png_warning(png_ptr, "Invalid sCAL chunk ignored: non-positive width"); - - else - { - png_size_t heighti = i; - - state = 0; - if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || - i != slength) - png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format"); - - else if (!PNG_FP_IS_POSITIVE(state)) - png_warning(png_ptr, - "Invalid sCAL chunk ignored: non-positive height"); - - else - /* This is the (only) success case. */ - png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], - png_ptr->chunkdata+1, png_ptr->chunkdata+heighti); - } - - /* Clean up - just free the temporarily allocated buffer. */ - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; -} -#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 = 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_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; - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; - text_ptr->itxt_length = 0; - 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 = 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_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; - text_ptr->lang = NULL; - text_ptr->lang_key = NULL; - text_ptr->itxt_length = 0; - 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 = 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++; - } - - if (comp_type || (comp_flag && comp_flag != PNG_TEXT_COMPRESSION_zTXt)) - { - png_warning(png_ptr, "Unknown iTXt compression type or method"); - png_free(png_ptr, png_ptr->chunkdata); - png_ptr->chunkdata = NULL; - return; - } - - 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_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) - { - if (png_ptr->chunk_name != png_IDAT) - png_ptr->mode |= PNG_AFTER_IDAT; - } - - if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name)) - { -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - if (png_chunk_unknown_handling(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 > 65535) - { - png_warning(png_ptr, "unknown chunk too large to fit in memory"); - skip = length - 65535; - length = 65535; - } -#endif - - /* TODO: this code is very close to the unknown handling in pngpread.c, - * maybe it can be put into a common utility routine? - * png_struct::unknown_chunk is just used as a temporary variable, along - * with the data into which the chunk is read. These can be eliminated. - */ - PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); - 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_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_CHUNK_CRITICAL(png_ptr->chunk_name)) - { -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - if (png_chunk_unknown_handling(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 - PNG_UNUSED(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. - */ - -/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is: - * - * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) - */ - -void /* PRIVATE */ -png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name) -{ - int i; - - png_debug(1, "in png_check_chunk_name"); - - for (i=1; i<=4; ++i) - { - int c = chunk_name & 0xff; - - if (c < 65 || c > 122 || (c > 90 && c < 97)) - png_chunk_error(png_ptr, "invalid chunk type"); - - chunk_name >>= 8; - } -} - -/* 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 'display' value; if 'display' is true then the whole row - * (dp) is filled from the start by replicating the available pixels. If - * 'display' is false only those pixels present in the pass are filled in. - */ -void /* PRIVATE */ -png_combine_row(png_structp png_ptr, png_bytep dp, int display) -{ - unsigned int pixel_depth = png_ptr->transformed_pixel_depth; - png_const_bytep sp = png_ptr->row_buf + 1; - png_uint_32 row_width = png_ptr->width; - unsigned int pass = png_ptr->pass; - png_bytep end_ptr = 0; - png_byte end_byte = 0; - unsigned int end_mask; - - png_debug(1, "in png_combine_row"); - - /* Added in 1.5.6: it should not be possible to enter this routine until at - * least one row has been read from the PNG data and transformed. - */ - if (pixel_depth == 0) - png_error(png_ptr, "internal row logic error"); - - /* Added in 1.5.4: the pixel depth should match the information returned by - * any call to png_read_update_info at this point. Do not continue if we got - * this wrong. - */ - if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes != - PNG_ROWBYTES(pixel_depth, row_width)) - png_error(png_ptr, "internal row size calculation error"); - - /* Don't expect this to ever happen: */ - if (row_width == 0) - png_error(png_ptr, "internal row width error"); - - /* Preserve the last byte in cases where only part of it will be overwritten, - * the multiply below may overflow, we don't care because ANSI-C guarantees - * we get the low bits. - */ - end_mask = (pixel_depth * row_width) & 7; - if (end_mask != 0) - { - /* end_ptr == NULL is a flag to say do nothing */ - end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1; - end_byte = *end_ptr; -# ifdef PNG_READ_PACKSWAP_SUPPORTED - if (png_ptr->transformations & PNG_PACKSWAP) /* little-endian byte */ - end_mask = 0xff << end_mask; - - else /* big-endian byte */ -# endif - end_mask = 0xff >> end_mask; - /* end_mask is now the bits to *keep* from the destination row */ - } - - /* For non-interlaced images this reduces to a png_memcpy(). A png_memcpy() - * will also happen if interlacing isn't supported or if the application - * does not call png_set_interlace_handling(). In the latter cases the - * caller just gets a sequence of the unexpanded rows from each interlace - * pass. - */ -#ifdef PNG_READ_INTERLACING_SUPPORTED - if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) && - pass < 6 && (display == 0 || - /* The following copies everything for 'display' on passes 0, 2 and 4. */ - (display == 1 && (pass & 1) != 0))) - { - /* Narrow images may have no bits in a pass; the caller should handle - * this, but this test is cheap: - */ - if (row_width <= PNG_PASS_START_COL(pass)) - return; - - if (pixel_depth < 8) - { - /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit - * into 32 bits, then a single loop over the bytes using the four byte - * values in the 32-bit mask can be used. For the 'display' option the - * expanded mask may also not require any masking within a byte. To - * make this work the PACKSWAP option must be taken into account - it - * simply requires the pixels to be reversed in each byte. - * - * The 'regular' case requires a mask for each of the first 6 passes, - * the 'display' case does a copy for the even passes in the range - * 0..6. This has already been handled in the test above. - * - * The masks are arranged as four bytes with the first byte to use in - * the lowest bits (little-endian) regardless of the order (PACKSWAP or - * not) of the pixels in each byte. - * - * NOTE: the whole of this logic depends on the caller of this function - * only calling it on rows appropriate to the pass. This function only - * understands the 'x' logic; the 'y' logic is handled by the caller. - * - * The following defines allow generation of compile time constant bit - * masks for each pixel depth and each possibility of swapped or not - * swapped bytes. Pass 'p' is in the range 0..6; 'x', a pixel index, - * is in the range 0..7; and the result is 1 if the pixel is to be - * copied in the pass, 0 if not. 'S' is for the sparkle method, 'B' - * for the block method. - * - * With some compilers a compile time expression of the general form: - * - * (shift >= 32) ? (a >> (shift-32)) : (b >> shift) - * - * Produces warnings with values of 'shift' in the range 33 to 63 - * because the right hand side of the ?: expression is evaluated by - * the compiler even though it isn't used. Microsoft Visual C (various - * versions) and the Intel C compiler are known to do this. To avoid - * this the following macros are used in 1.5.6. This is a temporary - * solution to avoid destabilizing the code during the release process. - */ -# if PNG_USE_COMPILE_TIME_MASKS -# define PNG_LSR(x,s) ((x)>>((s) & 0x1f)) -# define PNG_LSL(x,s) ((x)<<((s) & 0x1f)) -# else -# define PNG_LSR(x,s) ((x)>>(s)) -# define PNG_LSL(x,s) ((x)<<(s)) -# endif -# define S_COPY(p,x) (((p)<4 ? PNG_LSR(0x80088822,(3-(p))*8+(7-(x))) :\ - PNG_LSR(0xaa55ff00,(7-(p))*8+(7-(x)))) & 1) -# define B_COPY(p,x) (((p)<4 ? PNG_LSR(0xff0fff33,(3-(p))*8+(7-(x))) :\ - PNG_LSR(0xff55ff00,(7-(p))*8+(7-(x)))) & 1) - - /* Return a mask for pass 'p' pixel 'x' at depth 'd'. The mask is - * little endian - the first pixel is at bit 0 - however the extra - * parameter 's' can be set to cause the mask position to be swapped - * within each byte, to match the PNG format. This is done by XOR of - * the shift with 7, 6 or 4 for bit depths 1, 2 and 4. - */ -# define PIXEL_MASK(p,x,d,s) \ - (PNG_LSL(((PNG_LSL(1U,(d)))-1),(((x)*(d))^((s)?8-(d):0)))) - - /* Hence generate the appropriate 'block' or 'sparkle' pixel copy mask. - */ -# define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) -# define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) - - /* Combine 8 of these to get the full mask. For the 1-bpp and 2-bpp - * cases the result needs replicating, for the 4-bpp case the above - * generates a full 32 bits. - */ -# define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1))) - -# define S_MASK(p,d,s) MASK_EXPAND(S_MASKx(p,0,d,s) + S_MASKx(p,1,d,s) +\ - S_MASKx(p,2,d,s) + S_MASKx(p,3,d,s) + S_MASKx(p,4,d,s) +\ - S_MASKx(p,5,d,s) + S_MASKx(p,6,d,s) + S_MASKx(p,7,d,s), d) - -# define B_MASK(p,d,s) MASK_EXPAND(B_MASKx(p,0,d,s) + B_MASKx(p,1,d,s) +\ - B_MASKx(p,2,d,s) + B_MASKx(p,3,d,s) + B_MASKx(p,4,d,s) +\ - B_MASKx(p,5,d,s) + B_MASKx(p,6,d,s) + B_MASKx(p,7,d,s), d) - -#if PNG_USE_COMPILE_TIME_MASKS - /* Utility macros to construct all the masks for a depth/swap - * combination. The 's' parameter says whether the format is PNG - * (big endian bytes) or not. Only the three odd-numbered passes are - * required for the display/block algorithm. - */ -# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\ - S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) } - -# define B_MASKS(d,s) { B_MASK(1,d,s), S_MASK(3,d,s), S_MASK(5,d,s) } - -# define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2)) - - /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and - * then pass: - */ - static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = - { - /* Little-endian byte masks for PACKSWAP */ - { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, - /* Normal (big-endian byte) masks - PNG format */ - { S_MASKS(1,1), S_MASKS(2,1), S_MASKS(4,1) } - }; - - /* display_mask has only three entries for the odd passes, so index by - * pass>>1. - */ - static PNG_CONST png_uint_32 display_mask[2][3][3] = - { - /* Little-endian byte masks for PACKSWAP */ - { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, - /* Normal (big-endian byte) masks - PNG format */ - { B_MASKS(1,1), B_MASKS(2,1), B_MASKS(4,1) } - }; - -# define MASK(pass,depth,display,png)\ - ((display)?display_mask[png][DEPTH_INDEX(depth)][pass>>1]:\ - row_mask[png][DEPTH_INDEX(depth)][pass]) - -#else /* !PNG_USE_COMPILE_TIME_MASKS */ - /* This is the runtime alternative: it seems unlikely that this will - * ever be either smaller or faster than the compile time approach. - */ -# define MASK(pass,depth,display,png)\ - ((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png)) -#endif /* !PNG_USE_COMPILE_TIME_MASKS */ - - /* Use the appropriate mask to copy the required bits. In some cases - * the byte mask will be 0 or 0xff, optimize these cases. row_width is - * the number of pixels, but the code copies bytes, so it is necessary - * to special case the end. - */ - png_uint_32 pixels_per_byte = 8 / pixel_depth; - png_uint_32 mask; - -# ifdef PNG_READ_PACKSWAP_SUPPORTED - if (png_ptr->transformations & PNG_PACKSWAP) - mask = MASK(pass, pixel_depth, display, 0); - - else -# endif - mask = MASK(pass, pixel_depth, display, 1); - - for (;;) - { - png_uint_32 m; - - /* It doesn't matter in the following if png_uint_32 has more than - * 32 bits because the high bits always match those in m<<24; it is, - * however, essential to use OR here, not +, because of this. - */ - m = mask; - mask = (m >> 8) | (m << 24); /* rotate right to good compilers */ - m &= 0xff; - - if (m != 0) /* something to copy */ - { - if (m != 0xff) - *dp = (png_byte)((*dp & ~m) | (*sp & m)); - else - *dp = *sp; - } - - /* NOTE: this may overwrite the last byte with garbage if the image - * is not an exact number of bytes wide; libpng has always done - * this. - */ - if (row_width <= pixels_per_byte) - break; /* May need to restore part of the last byte */ - - row_width -= pixels_per_byte; - ++dp; - ++sp; - } - } - - else /* pixel_depth >= 8 */ - { - unsigned int bytes_to_copy, bytes_to_jump; - - /* Validate the depth - it must be a multiple of 8 */ - if (pixel_depth & 7) - png_error(png_ptr, "invalid user transform pixel depth"); - - pixel_depth >>= 3; /* now in bytes */ - row_width *= pixel_depth; - - /* Regardless of pass number the Adam 7 interlace always results in a - * fixed number of pixels to copy then to skip. There may be a - * different number of pixels to skip at the start though. - */ - { - unsigned int offset = PNG_PASS_START_COL(pass) * pixel_depth; - - row_width -= offset; - dp += offset; - sp += offset; - } - - /* Work out the bytes to copy. */ - if (display) - { - /* When doing the 'block' algorithm the pixel in the pass gets - * replicated to adjacent pixels. This is why the even (0,2,4,6) - * passes are skipped above - the entire expanded row is copied. - */ - bytes_to_copy = (1<<((6-pass)>>1)) * pixel_depth; - - /* But don't allow this number to exceed the actual row width. */ - if (bytes_to_copy > row_width) - bytes_to_copy = row_width; - } - - else /* normal row; Adam7 only ever gives us one pixel to copy. */ - bytes_to_copy = pixel_depth; - - /* In Adam7 there is a constant offset between where the pixels go. */ - bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth; - - /* And simply copy these bytes. Some optimization is possible here, - * depending on the value of 'bytes_to_copy'. Special case the low - * byte counts, which we know to be frequent. - * - * Notice that these cases all 'return' rather than 'break' - this - * avoids an unnecessary test on whether to restore the last byte - * below. - */ - switch (bytes_to_copy) - { - case 1: - for (;;) - { - *dp = *sp; - - if (row_width <= bytes_to_jump) - return; - - dp += bytes_to_jump; - sp += bytes_to_jump; - row_width -= bytes_to_jump; - } - - case 2: - /* There is a possibility of a partial copy at the end here; this - * slows the code down somewhat. - */ - do - { - dp[0] = sp[0], dp[1] = sp[1]; - - if (row_width <= bytes_to_jump) - return; - - sp += bytes_to_jump; - dp += bytes_to_jump; - row_width -= bytes_to_jump; - } - while (row_width > 1); - - /* And there can only be one byte left at this point: */ - *dp = *sp; - return; - - case 3: - /* This can only be the RGB case, so each copy is exactly one - * pixel and it is not necessary to check for a partial copy. - */ - for (;;) - { - dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2]; - - if (row_width <= bytes_to_jump) - return; - - sp += bytes_to_jump; - dp += bytes_to_jump; - row_width -= bytes_to_jump; - } - - default: -#if PNG_ALIGN_TYPE != PNG_ALIGN_NONE - /* Check for double byte alignment and, if possible, use a - * 16-bit copy. Don't attempt this for narrow images - ones that - * are less than an interlace panel wide. Don't attempt it for - * wide bytes_to_copy either - use the png_memcpy there. - */ - if (bytes_to_copy < 16 /*else use png_memcpy*/ && - png_isaligned(dp, png_uint_16) && - png_isaligned(sp, png_uint_16) && - bytes_to_copy % sizeof (png_uint_16) == 0 && - bytes_to_jump % sizeof (png_uint_16) == 0) - { - /* Everything is aligned for png_uint_16 copies, but try for - * png_uint_32 first. - */ - if (png_isaligned(dp, png_uint_32) && - png_isaligned(sp, png_uint_32) && - bytes_to_copy % sizeof (png_uint_32) == 0 && - bytes_to_jump % sizeof (png_uint_32) == 0) - { - png_uint_32p dp32 = (png_uint_32p)dp; - png_const_uint_32p sp32 = (png_const_uint_32p)sp; - unsigned int skip = (bytes_to_jump-bytes_to_copy) / - sizeof (png_uint_32); - - do - { - size_t c = bytes_to_copy; - do - { - *dp32++ = *sp32++; - c -= sizeof (png_uint_32); - } - while (c > 0); - - if (row_width <= bytes_to_jump) - return; - - dp32 += skip; - sp32 += skip; - row_width -= bytes_to_jump; - } - while (bytes_to_copy <= row_width); - - /* Get to here when the row_width truncates the final copy. - * There will be 1-3 bytes left to copy, so don't try the - * 16-bit loop below. - */ - dp = (png_bytep)dp32; - sp = (png_const_bytep)sp32; - do - *dp++ = *sp++; - while (--row_width > 0); - return; - } - - /* Else do it in 16-bit quantities, but only if the size is - * not too large. - */ - else - { - png_uint_16p dp16 = (png_uint_16p)dp; - png_const_uint_16p sp16 = (png_const_uint_16p)sp; - unsigned int skip = (bytes_to_jump-bytes_to_copy) / - sizeof (png_uint_16); - - do - { - size_t c = bytes_to_copy; - do - { - *dp16++ = *sp16++; - c -= sizeof (png_uint_16); - } - while (c > 0); - - if (row_width <= bytes_to_jump) - return; - - dp16 += skip; - sp16 += skip; - row_width -= bytes_to_jump; - } - while (bytes_to_copy <= row_width); - - /* End of row - 1 byte left, bytes_to_copy > row_width: */ - dp = (png_bytep)dp16; - sp = (png_const_bytep)sp16; - do - *dp++ = *sp++; - while (--row_width > 0); - return; - } - } -#endif /* PNG_ALIGN_ code */ - - /* The true default - use a png_memcpy: */ - for (;;) - { - png_memcpy(dp, sp, bytes_to_copy); - - if (row_width <= bytes_to_jump) - return; - - sp += bytes_to_jump; - dp += bytes_to_jump; - row_width -= bytes_to_jump; - if (bytes_to_copy > row_width) - bytes_to_copy = row_width; - } - } - - /* NOT REACHED*/ - } /* pixel_depth >= 8 */ - - /* Here if pixel_depth < 8 to check 'end_ptr' below. */ - } - else -#endif - - /* If here then the switch above wasn't used so just png_memcpy the whole row - * from the temporary row buffer (notice that this overwrites the end of the - * destination row if it is a partial byte.) - */ - png_memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width)); - - /* Restore the overwritten bits from the last byte if necessary. */ - if (end_ptr != NULL) - *end_ptr = (png_byte)((end_byte & end_mask) | (*end_ptr & ~end_mask)); -} - -#ifdef PNG_READ_INTERLACING_SUPPORTED -void /* PRIVATE */ -png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, - png_uint_32 transformations /* Because these may affect the byte layout */) -{ - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* Offset to next interlace block */ - static 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) & 0x0f); - 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 - PNG_UNUSED(transformations) /* Silence compiler warning */ -#endif -} -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - -static void -png_read_filter_row_sub(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - png_size_t i; - png_size_t istop = row_info->rowbytes; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp = row + bpp; - - PNG_UNUSED(prev_row) - - for (i = bpp; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); - rp++; - } -} - -static void -png_read_filter_row_up(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - png_size_t i; - png_size_t istop = row_info->rowbytes; - png_bytep rp = row; - png_const_bytep pp = prev_row; - - for (i = 0; i < istop; i++) - { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; - } -} - -static void -png_read_filter_row_avg(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - png_size_t i; - png_bytep rp = row; - png_const_bytep pp = prev_row; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t 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++ + *(rp-bpp)) / 2 ) & 0xff); - - rp++; - } -} - -static void -png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - png_bytep rp_end = row + row_info->rowbytes; - int a, c; - - /* First pixel/byte */ - c = *prev_row++; - a = *row + c; - *row++ = (png_byte)a; - - /* Remainder */ - while (row < rp_end) - { - int b, pa, pb, pc, p; - - a &= 0xff; /* From previous iteration or start */ - b = *prev_row++; - - 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 - - /* Find the best predictor, the least of pa, pb, pc favoring the earlier - * ones in the case of a tie. - */ - if (pb < pa) pa = pb, a = b; - if (pc < pa) a = c; - - /* Calculate the current pixel in a, and move the previous row pixel to c - * for the next time round the loop - */ - c = b; - a += *row; - *row++ = (png_byte)a; - } -} - -static void -png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) -{ - int bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp_end = row + bpp; - - /* Process the first pixel in the row completely (this is the same as 'up' - * because there is only one candidate predictor for the first row). - */ - while (row < rp_end) - { - int a = *row + *prev_row++; - *row++ = (png_byte)a; - } - - /* Remainder */ - rp_end += row_info->rowbytes - bpp; - - while (row < rp_end) - { - int a, b, c, pa, pb, pc, p; - - c = *(prev_row - bpp); - a = *(row - bpp); - b = *prev_row++; - - 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 (pb < pa) pa = pb, a = b; - if (pc < pa) a = c; - - c = b; - a += *row; - *row++ = (png_byte)a; - } -} - -#ifdef PNG_ARM_NEON - -#ifdef __linux__ -#include -#include -#include - -static int png_have_hwcap(unsigned cap) -{ - FILE *f = fopen("/proc/self/auxv", "r"); - Elf32_auxv_t aux; - int have_cap = 0; - - if (!f) - return 0; - - while (fread(&aux, sizeof(aux), 1, f) > 0) - { - if (aux.a_type == AT_HWCAP && - aux.a_un.a_val & cap) - { - have_cap = 1; - break; - } - } - - fclose(f); - - return have_cap; -} -#endif /* __linux__ */ - -static void -png_init_filter_functions_neon(png_structp pp, unsigned int bpp) -{ -#ifdef __linux__ - if (!png_have_hwcap(HWCAP_NEON)) - return; -#endif - - pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon; - - if (bpp == 3) - { - pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon; - pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon; - pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = - png_read_filter_row_paeth3_neon; - } - - else if (bpp == 4) - { - pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon; - pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon; - pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = - png_read_filter_row_paeth4_neon; - } -} -#endif /* PNG_ARM_NEON */ - -static void -png_init_filter_functions(png_structp pp) -{ - unsigned int bpp = (pp->pixel_depth + 7) >> 3; - - pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub; - pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up; - pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg; - if (bpp == 1) - pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = - png_read_filter_row_paeth_1byte_pixel; - else - pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = - png_read_filter_row_paeth_multibyte_pixel; - -#ifdef PNG_ARM_NEON - png_init_filter_functions_neon(pp, bpp); -#endif -} - -void /* PRIVATE */ -png_read_filter_row(png_structp pp, png_row_infop row_info, png_bytep row, - png_const_bytep prev_row, int filter) -{ - if (pp->read_filter[0] == NULL) - png_init_filter_functions(pp); - if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST) - pp->read_filter[filter-1](row_info, row, prev_row); -} - -#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 */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte 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; - - /* TO DO: don't do this if prev_row isn't needed (requires - * read-ahead of the next row's filter byte. - */ - png_memset(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]; - } - - else /* if (png_ptr->transformations & PNG_INTERLACE) */ - break; /* libpng deinterlacing sees every row */ - - } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0); - - if (png_ptr->pass < 7) - return; - } -#endif /* PNG_READ_INTERLACING_SUPPORTED */ - - if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) - { - 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_crc_finish(png_ptr, 0); - png_ptr->idat_size = png_read_chunk_header(png_ptr); - if (png_ptr->chunk_name != png_IDAT) - 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 */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte 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; -#ifdef PNG_READ_TRANSFORMS_SUPPORTED - png_init_read_transformations(png_ptr); -#endif -#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; - - /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of - * calculations to calculate the final pixel depth, then - * png_do_read_transforms actually does the transforms. This means that the - * code which effectively calculates this value is actually repeated in three - * separate places. They must all match. Innocent changes to the order of - * transformations can and will break libpng in a way that causes memory - * overwrites. - * - * TODO: fix this. - */ -#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_EXPAND_16_SUPPORTED - if (png_ptr->transformations & PNG_EXPAND_16) - { -# ifdef PNG_READ_EXPAND_SUPPORTED - /* In fact it is an error if it isn't supported, but checking is - * the safe way. - */ - if (png_ptr->transformations & PNG_EXPAND) - { - if (png_ptr->bit_depth < 16) - max_pixel_depth *= 2; - } - else -# endif - png_ptr->transformations &= ~PNG_EXPAND_16; - } -#endif - -#ifdef PNG_READ_FILLER_SUPPORTED - if (png_ptr->transformations & (PNG_FILLER)) - { - 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 || - png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - 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 - - /* This value is stored in png_struct and double checked in the row read - * code. - */ - png_ptr->maximum_pixel_depth = (png_byte)max_pixel_depth; - png_ptr->transformed_pixel_depth = 0; /* calculated on demand */ - - /* 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 + 48 > png_ptr->old_big_row_buf_size) - { - png_free(png_ptr, png_ptr->big_row_buf); - png_free(png_ptr, png_ptr->big_prev_row); - - if (png_ptr->interlaced) - png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, - row_bytes + 48); - - else - png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); - - png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); - -#ifdef PNG_ALIGNED_MEMORY_SUPPORTED - /* Use 16-byte aligned memory for row_buf with at least 16 bytes - * of padding before and after row_buf; treat prev_row similarly. - * NOTE: the alignment is to the start of the pixels, one beyond the start - * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this - * was incorrect; the filter byte was aligned, which had the exact - * opposite effect of that intended. - */ - { - png_bytep temp = png_ptr->big_row_buf + 32; - int extra = (int)((temp - (png_bytep)0) & 0x0f); - png_ptr->row_buf = temp - extra - 1/*filter byte*/; - - temp = png_ptr->big_prev_row + 32; - extra = (int)((temp - (png_bytep)0) & 0x0f); - png_ptr->prev_row = temp - extra - 1/*filter byte*/; - } - -#else - /* Use 31 bytes of padding before and 17 bytes after row_buf. */ - png_ptr->row_buf = png_ptr->big_row_buf + 31; - png_ptr->prev_row = png_ptr->big_prev_row + 31; -#endif - png_ptr->old_big_row_buf_size = row_bytes + 48; - } - -#ifdef PNG_MAX_MALLOC_64K - if (png_ptr->rowbytes > 65535) - png_error(png_ptr, "This image requires a row greater than 64KB"); - -#endif - if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1)) - png_error(png_ptr, "Row has too many bytes to allocate in memory"); - - png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); - - png_debug1(3, "width = %u,", png_ptr->width); - png_debug1(3, "height = %u,", png_ptr->height); - png_debug1(3, "iwidth = %u,", png_ptr->iwidth); - png_debug1(3, "num_rows = %u,", png_ptr->num_rows); - png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes); - png_debug1(3, "irowbytes = %lu", - (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); - - png_ptr->flags |= PNG_FLAG_ROW_INIT; -} -#endif /* PNG_READ_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibPNG/pngset.c b/plugins/FreeImage/Source/LibPNG/pngset.c deleted file mode 100644 index e753ca8867..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngset.c +++ /dev/null @@ -1,1284 +0,0 @@ - -/* pngset.c - storage of image information into info struct - * - * Last changed in libpng 1.5.7 [December 15, 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 - * - * 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. - */ - -#include "pngpriv.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_const_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 -void PNGFAPI -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->x_white = white_x; - info_ptr->y_white = white_y; - info_ptr->x_red = red_x; - info_ptr->y_red = red_y; - info_ptr->x_green = green_x; - info_ptr->y_green = green_y; - info_ptr->x_blue = blue_x; - info_ptr->y_blue = blue_y; - info_ptr->valid |= PNG_INFO_cHRM; - } -} - -void PNGFAPI -png_set_cHRM_XYZ_fixed(png_structp png_ptr, png_infop info_ptr, - png_fixed_point int_red_X, png_fixed_point int_red_Y, - png_fixed_point int_red_Z, png_fixed_point int_green_X, - png_fixed_point int_green_Y, png_fixed_point int_green_Z, - png_fixed_point int_blue_X, png_fixed_point int_blue_Y, - png_fixed_point int_blue_Z) -{ - png_XYZ XYZ; - png_xy xy; - - png_debug1(1, "in %s storage function", "cHRM XYZ fixed"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - XYZ.redX = int_red_X; - XYZ.redY = int_red_Y; - XYZ.redZ = int_red_Z; - XYZ.greenX = int_green_X; - XYZ.greenY = int_green_Y; - XYZ.greenZ = int_green_Z; - XYZ.blueX = int_blue_X; - XYZ.blueY = int_blue_Y; - XYZ.blueZ = int_blue_Z; - - if (png_xy_from_XYZ(&xy, XYZ)) - png_error(png_ptr, "XYZ values out of representable range"); - - png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy, - xy.greenx, xy.greeny, xy.bluex, xy.bluey); -} - -# 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_set_cHRM_fixed(png_ptr, info_ptr, - png_fixed(png_ptr, white_x, "cHRM White X"), - png_fixed(png_ptr, white_y, "cHRM White Y"), - png_fixed(png_ptr, red_x, "cHRM Red X"), - png_fixed(png_ptr, red_y, "cHRM Red Y"), - png_fixed(png_ptr, green_x, "cHRM Green X"), - png_fixed(png_ptr, green_y, "cHRM Green Y"), - png_fixed(png_ptr, blue_x, "cHRM Blue X"), - png_fixed(png_ptr, blue_y, "cHRM Blue Y")); -} - -void PNGAPI -png_set_cHRM_XYZ(png_structp png_ptr, png_infop info_ptr, double red_X, - double red_Y, double red_Z, double green_X, double green_Y, double green_Z, - double blue_X, double blue_Y, double blue_Z) -{ - png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, - png_fixed(png_ptr, red_X, "cHRM Red X"), - png_fixed(png_ptr, red_Y, "cHRM Red Y"), - png_fixed(png_ptr, red_Z, "cHRM Red Z"), - png_fixed(png_ptr, green_X, "cHRM Red X"), - png_fixed(png_ptr, green_Y, "cHRM Red Y"), - png_fixed(png_ptr, green_Z, "cHRM Red Z"), - png_fixed(png_ptr, blue_X, "cHRM Red X"), - png_fixed(png_ptr, blue_Y, "cHRM Red Y"), - png_fixed(png_ptr, blue_Z, "cHRM Red Z")); -} -# endif /* PNG_FLOATING_POINT_SUPPORTED */ - -#endif /* PNG_cHRM_SUPPORTED */ - -#ifdef PNG_gAMA_SUPPORTED -void PNGFAPI -png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point - file_gamma) -{ - png_debug1(1, "in %s storage function", "gAMA"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't - * occur. Since the fixed point representation is assymetrical it is - * possible for 1/gamma to overflow the limit of 21474 and this means the - * gamma value must be at least 5/100000 and hence at most 20000.0. For - * safety the limits here are a little narrower. The values are 0.00016 to - * 6250.0, which are truly ridiculous gammma values (and will produce - * displays that are all black or all white.) - */ - if (file_gamma < 16 || file_gamma > 625000000) - png_warning(png_ptr, "Out of range gamma value ignored"); - - else - { - info_ptr->gamma = file_gamma; - info_ptr->valid |= PNG_INFO_gAMA; - } -} - -# ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) -{ - png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, - "png_set_gAMA")); -} -# endif -#endif - -#ifdef PNG_hIST_SUPPORTED -void PNGAPI -png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_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; - } - - png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); - - /* 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_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; - info_ptr->free_me |= PNG_FREE_HIST; -} -#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 RRGGBBAA pixels */ - - 48 /* bigrowbuf hack */ - - 1 /* filter byte */ - - 7*8 /* rounding of width to multiple of 8 pixels */ - - 8) /* extra max_pixel_depth pad */ - info_ptr->rowbytes = 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_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, - int nparams, png_const_charp units, png_charpp params) -{ - png_size_t 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); - - /* TODO: validate format of calibration name and unit name */ - - /* Check that the type matches the specification. */ - if (type < 0 || type > 3) - png_error(png_ptr, "Invalid pCAL equation type"); - - /* Validate params[nparams] */ - for (i=0; ipcal_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, 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, length); - - info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, - (png_size_t)((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], length); - } - - info_ptr->valid |= PNG_INFO_pCAL; - info_ptr->free_me |= PNG_FREE_PCAL; -} -#endif - -#ifdef PNG_sCAL_SUPPORTED -void PNGAPI -png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, - int unit, png_const_charp swidth, png_const_charp sheight) -{ - png_size_t lengthw = 0, lengthh = 0; - - png_debug1(1, "in %s storage function", "sCAL"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - /* Double check the unit (should never get here with an invalid - * unit unless this is an API call.) - */ - if (unit != 1 && unit != 2) - png_error(png_ptr, "Invalid sCAL unit"); - - if (swidth == NULL || (lengthw = png_strlen(swidth)) == 0 || - swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw)) - png_error(png_ptr, "Invalid sCAL width"); - - if (sheight == NULL || (lengthh = png_strlen(sheight)) == 0 || - sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh)) - png_error(png_ptr, "Invalid sCAL height"); - - info_ptr->scal_unit = (png_byte)unit; - - ++lengthw; - - png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); - - info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw); - - 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, lengthw); - - ++lengthh; - - png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); - - info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh); - - 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, lengthh); - - info_ptr->valid |= PNG_INFO_sCAL; - info_ptr->free_me |= PNG_FREE_SCAL; -} - -# 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"); - - /* Check the arguments. */ - if (width <= 0) - png_warning(png_ptr, "Invalid sCAL width ignored"); - - else if (height <= 0) - png_warning(png_ptr, "Invalid sCAL height ignored"); - - else - { - /* Convert 'width' and 'height' to ASCII. */ - char swidth[PNG_sCAL_MAX_DIGITS+1]; - char sheight[PNG_sCAL_MAX_DIGITS+1]; - - png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width, - PNG_sCAL_PRECISION); - png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height, - PNG_sCAL_PRECISION); - - png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); - } -} -# endif - -# ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit, - png_fixed_point width, png_fixed_point height) -{ - png_debug1(1, "in %s storage function", "sCAL"); - - /* Check the arguments. */ - if (width <= 0) - png_warning(png_ptr, "Invalid sCAL width ignored"); - - else if (height <= 0) - png_warning(png_ptr, "Invalid sCAL height ignored"); - - else - { - /* Convert 'width' and 'height' to ASCII. */ - char swidth[PNG_sCAL_MAX_DIGITS+1]; - char sheight[PNG_sCAL_MAX_DIGITS+1]; - - png_ascii_from_fixed(png_ptr, swidth, sizeof swidth, width); - png_ascii_from_fixed(png_ptr, sheight, sizeof sheight, height); - - png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); - } -} -# 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_const_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. - */ - png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); - - /* 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; - - info_ptr->free_me |= PNG_FREE_PLTE; - - info_ptr->valid |= PNG_INFO_PLTE; -} - -#ifdef PNG_sBIT_SUPPORTED -void PNGAPI -png_set_sBIT(png_structp png_ptr, png_infop info_ptr, - png_const_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 srgb_intent) -{ - png_debug1(1, "in %s storage function", "sRGB"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - info_ptr->srgb_intent = (png_byte)srgb_intent; - info_ptr->valid |= PNG_INFO_sRGB; -} - -void PNGAPI -png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, - int srgb_intent) -{ - 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, srgb_intent); - -# ifdef PNG_gAMA_SUPPORTED - png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); -# endif - -# ifdef PNG_cHRM_SUPPORTED - png_set_cHRM_fixed(png_ptr, info_ptr, - /* color x y */ - /* white */ 31270, 32900, - /* red */ 64000, 33000, - /* green */ 30000, 60000, - /* blue */ 15000, 6000 - ); -# endif /* cHRM */ -} -#endif /* sRGB */ - - -#ifdef PNG_iCCP_SUPPORTED -void PNGAPI -png_set_iCCP(png_structp png_ptr, png_infop info_ptr, - png_const_charp name, int compression_type, - png_const_bytep profile, png_uint_32 proflen) -{ - png_charp new_iccp_name; - png_bytep new_iccp_profile; - png_size_t 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_bytep)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; - info_ptr->free_me |= PNG_FREE_ICCP; - 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_const_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_const_textp text_ptr, int num_text) -{ - int i; - - png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" : - (unsigned long)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) - { - if (info_ptr->text != NULL) - { - png_textp old_text; - int old_max; - - old_max = info_ptr->max_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_size_t)(info_ptr->max_text * png_sizeof(png_text))); - - if (info_ptr->text == NULL) - { - png_free(png_ptr, old_text); - return(1); - } - - png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * - 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_size_t)(info_ptr->max_text * png_sizeof(png_text))); - if (info_ptr->text == NULL) - return(1); - info_ptr->free_me |= PNG_FREE_TEXT; - } - - 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; - - if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || - text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) - { - png_warning(png_ptr, "text compression mode is out of range"); - 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_size_t) - (key_len + text_length + lang_len + lang_key_len + 4)); - - if (textp->key == NULL) - return(1); - - png_debug2(2, "Allocated %lu bytes at %p in png_set_text", - (unsigned long)(png_uint_32) - (key_len + lang_len + lang_key_len + text_length + 4), - textp->key); - - png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); - *(textp->key + key_len) = '\0'; - - 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 - { - textp->lang=NULL; - textp->lang_key=NULL; - 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; - textp->itxt_length = 0; - } - - 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_const_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; - - if (mod_time->month == 0 || mod_time->month > 12 || - mod_time->day == 0 || mod_time->day > 31 || - mod_time->hour > 23 || mod_time->minute > 59 || - mod_time->second > 60) - { - png_warning(png_ptr, "Ignoring invalid time value"); - 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_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) -{ - png_debug1(1, "in %s storage function", "tRNS"); - - if (png_ptr == NULL || info_ptr == NULL) - return; - - if (trans_alpha != NULL) - { - /* It may not actually be necessary to set png_ptr->trans_alpha here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - */ - - png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); - - /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ - png_ptr->trans_alpha = info_ptr->trans_alpha = - (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH); - - if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) - png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); - } - - if (trans_color != NULL) - { - int sample_max = (1 << info_ptr->bit_depth); - - if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && - (int)trans_color->gray > sample_max) || - (info_ptr->color_type == PNG_COLOR_TYPE_RGB && - ((int)trans_color->red > sample_max || - (int)trans_color->green > sample_max || - (int)trans_color->blue > sample_max))) - png_warning(png_ptr, - "tRNS chunk has out-of-range samples for bit_depth"); - - png_memcpy(&(info_ptr->trans_color), trans_color, - 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; - info_ptr->free_me |= PNG_FREE_TRNS; - } -} -#endif - -#ifdef PNG_sPLT_SUPPORTED -void PNGAPI -png_set_sPLT(png_structp png_ptr, - png_infop info_ptr, png_const_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_size_t)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_const_sPLT_tp from = entries + i; - png_size_t 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, - 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; - info_ptr->free_me |= PNG_FREE_SPLT; -} -#endif /* PNG_sPLT_SUPPORTED */ - -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -void PNGAPI -png_set_unknown_chunks(png_structp png_ptr, - png_infop info_ptr, png_const_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_size_t)(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, - (png_size_t)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_const_unknown_chunkp from = unknowns + i; - - png_memcpy(to->name, 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_size_t)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; - info_ptr->free_me |= PNG_FREE_UNKN; -} - -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 < - info_ptr->unknown_chunks_num) - info_ptr->unknown_chunks[chunk].location = (png_byte)location; -} -#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_const_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_size_t)(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; inum_chunk_list = old_num_chunks + num_chunks; - png_ptr->chunk_list = new_list; - png_ptr->free_me |= PNG_FREE_LIST; -} -#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_size_t size) -{ - if (png_ptr == NULL) - return; - - png_free(png_ptr, png_ptr->zbuf); - - if (size > ZLIB_IO_MAX) - { - png_warning(png_ptr, "Attempt to set buffer size beyond max ignored"); - png_ptr->zbuf_size = ZLIB_IO_MAX; - size = ZLIB_IO_MAX; /* must fit */ - } - - else - png_ptr->zbuf_size = (uInt)size; - - png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); - - /* The following ensures a relatively safe failure if this gets called while - * the buffer is actually in use. - */ - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = 0; - png_ptr->zstream.avail_in = 0; -} - -void PNGAPI -png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) -{ - if (png_ptr && info_ptr) - info_ptr->valid &= ~mask; -} - - - -#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; -} - -/* This function was added to libpng 1.4.0 */ -void PNGAPI -png_set_chunk_cache_max (png_structp png_ptr, - png_uint_32 user_chunk_cache_max) -{ - if (png_ptr) - png_ptr->user_chunk_cache_max = user_chunk_cache_max; -} - -/* This function was added to libpng 1.4.1 */ -void PNGAPI -png_set_chunk_malloc_max (png_structp png_ptr, - png_alloc_size_t user_chunk_malloc_max) -{ - if (png_ptr) - png_ptr->user_chunk_malloc_max = user_chunk_malloc_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_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibPNG/pngstruct.h b/plugins/FreeImage/Source/LibPNG/pngstruct.h deleted file mode 100644 index 1824c49114..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngstruct.h +++ /dev/null @@ -1,358 +0,0 @@ - -/* pngstruct.h - header file for PNG reference library - * - * 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.) - * - * Last changed in libpng 1.5.9 [February 18, 2012] - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - */ - -/* 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. - */ - -#ifndef PNGSTRUCT_H -#define PNGSTRUCT_H -/* zlib.h defines the structure z_stream, an instance of which is included - * in this structure and is required for decompressing the LZ compressed - * data in PNG files. - */ -#include "zlib.h" - -struct png_struct_def -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf longjmp_buffer; /* used in png_error */ - png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */ -#endif - png_error_ptr error_fn; /* function for printing errors and aborting */ -#ifdef PNG_WARNINGS_SUPPORTED - png_error_ptr warning_fn; /* function for printing warnings */ -#endif - png_voidp error_ptr; /* user supplied struct for error functions */ - png_rw_ptr write_data_fn; /* function for writing output data */ - png_rw_ptr read_data_fn; /* function for reading input data */ - png_voidp io_ptr; /* ptr to application struct for I/O functions */ - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr read_user_transform_fn; /* user read transform */ -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr write_user_transform_fn; /* 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; /* user supplied struct for user transform */ - png_byte user_transform_depth; /* bit depth of user transformed pixels */ - png_byte user_transform_channels; /* channels in user transformed pixels */ -#endif -#endif - - png_uint_32 mode; /* tells us where we are in the PNG file */ - png_uint_32 flags; /* flags indicating various things to libpng */ - png_uint_32 transformations; /* which transformations to perform */ - - z_stream zstream; /* pointer to decompression structure (below) */ - png_bytep zbuf; /* buffer for zlib */ - uInt zbuf_size; /* size of zbuf (typically 65536) */ -#ifdef PNG_WRITE_SUPPORTED - -/* Added in 1.5.4: state to keep track of whether the zstream has been - * initialized and if so whether it is for IDAT or some other chunk. - */ -#define PNG_ZLIB_UNINITIALIZED 0 -#define PNG_ZLIB_FOR_IDAT 1 -#define PNG_ZLIB_FOR_TEXT 2 /* anything other than IDAT */ -#define PNG_ZLIB_USE_MASK 3 /* bottom two bits */ -#define PNG_ZLIB_IN_USE 4 /* a flag value */ - - png_uint_32 zlib_state; /* State of zlib initialization */ -/* End of material added at libpng 1.5.4 */ - - int zlib_level; /* holds zlib compression level */ - int zlib_method; /* holds zlib compression method */ - int zlib_window_bits; /* holds zlib compression window bits */ - int zlib_mem_level; /* holds zlib compression memory level */ - int zlib_strategy; /* holds zlib compression strategy */ -#endif -/* Added at libpng 1.5.4 */ -#if defined(PNG_WRITE_COMPRESSED_TEXT_SUPPORTED) || \ - defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED) - int zlib_text_level; /* holds zlib compression level */ - int zlib_text_method; /* holds zlib compression method */ - int zlib_text_window_bits; /* holds zlib compression window bits */ - int zlib_text_mem_level; /* holds zlib compression memory level */ - int zlib_text_strategy; /* holds zlib compression strategy */ -#endif -/* End of material added at libpng 1.5.4 */ - - png_uint_32 width; /* width of image in pixels */ - png_uint_32 height; /* height of image in pixels */ - png_uint_32 num_rows; /* number of rows in current pass */ - png_uint_32 usr_width; /* width of row at start of write */ - png_size_t rowbytes; /* size of row in bytes */ - png_uint_32 iwidth; /* width of current interlaced row in pixels */ - png_uint_32 row_number; /* current row in interlace pass */ - png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ - png_bytep prev_row; /* buffer to save previous (unfiltered) row. - * This is a pointer into big_prev_row - */ - png_bytep row_buf; /* buffer to save current (unfiltered) row. - * This is a pointer into big_row_buf - */ - png_bytep sub_row; /* buffer to save "sub" row when filtering */ - png_bytep up_row; /* buffer to save "up" row when filtering */ - png_bytep avg_row; /* buffer to save "avg" row when filtering */ - png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ - png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ - - png_uint_32 idat_size; /* current IDAT size for read */ - png_uint_32 crc; /* current chunk CRC value */ - png_colorp palette; /* palette from the input file */ - png_uint_16 num_palette; /* number of color entries in palette */ - png_uint_16 num_trans; /* number of transparency values */ - png_byte compression; /* file compression type (always 0) */ - png_byte filter; /* file filter type (always 0) */ - png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ - png_byte pass; /* current interlace pass (0 - 6) */ - png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ - png_byte color_type; /* color type of file */ - png_byte bit_depth; /* bit depth of file */ - png_byte usr_bit_depth; /* bit depth of users row: write only */ - png_byte pixel_depth; /* number of bits per pixel */ - png_byte channels; /* number of channels in file */ - png_byte usr_channels; /* channels at start of write: write only */ - png_byte sig_bytes; /* magic bytes read/written from start of file */ - png_byte maximum_pixel_depth; - /* pixel depth used for the row buffers */ - png_byte transformed_pixel_depth; - /* pixel depth after read/write transforms */ - png_byte io_chunk_string[5]; - /* string name of chunk */ - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) - png_uint_16 filler; /* filler bytes for pixel expansion */ -#endif - -#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) - png_byte background_gamma_type; - png_fixed_point background_gamma; - png_color_16 background; /* background color in screen gamma space */ -#ifdef PNG_READ_GAMMA_SUPPORTED - png_color_16 background_1; /* background normalized to gamma 1.0 */ -#endif -#endif /* PNG_bKGD_SUPPORTED */ - -#ifdef PNG_WRITE_FLUSH_SUPPORTED - png_flush_ptr output_flush_fn; /* Function for flushing output */ - png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ - png_uint_32 flush_rows; /* number of rows written since last flush */ -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED - int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ - png_fixed_point gamma; /* file gamma value */ - png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ - - png_bytep gamma_table; /* gamma table for 8-bit depth files */ - png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_bytep gamma_from_1; /* converts from 1.0 to screen */ - png_bytep gamma_to_1; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ - png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit; /* significant bits in each available channel */ -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* 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_alpha; /* alpha values for paletted files */ - png_color_16 trans_color; /* transparent color for non-paletted files */ -#endif - - png_read_status_ptr read_row_fn; /* called after each row is decoded */ - png_write_status_ptr write_row_fn; /* called after each row is encoded */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_progressive_info_ptr info_fn; /* called after header data fully read */ - png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ - png_progressive_end_ptr end_fn; /* called after image is complete */ - png_bytep save_buffer_ptr; /* current location in save_buffer */ - png_bytep save_buffer; /* buffer for previously read data */ - png_bytep current_buffer_ptr; /* current location in current_buffer */ - png_bytep current_buffer; /* buffer for recently used data */ - png_uint_32 push_length; /* size of current input chunk */ - png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ - int process_mode; /* what push library is currently doing */ - int cur_palette; /* current push library palette index */ - -# ifdef PNG_TEXT_SUPPORTED - png_size_t current_text_size; /* current size of text input data */ - png_size_t current_text_left; /* how much text left to read in input */ - png_charp current_text; /* current text chunk buffer */ - png_charp current_text_ptr; /* current location in current_text */ -# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && 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_bytep offset_table; - png_uint_16 offset_table_number; - png_uint_16 offset_table_count; - png_uint_16 offset_table_count_free; -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - png_bytep palette_lookup; /* lookup table for quantizing */ - png_bytep quantize_index; /* index translation for palette files */ -#endif - -#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) - png_uint_16p hist; /* histogram */ -#endif - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - png_byte heuristic_method; /* heuristic for row filter selection */ - png_byte num_prev_filters; /* number of weights for previous rows */ - png_bytep prev_filters; /* filter type(s) of previous row(s) */ - png_uint_16p filter_weights; /* weight(s) for previous line(s) */ - png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ - png_uint_16p filter_costs; /* relative filter calculation cost */ - png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED - char time_buffer[29]; /* String to hold RFC 1123 time text */ -#endif - -/* New members added in libpng-1.0.6 */ - - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ - -#ifdef PNG_USER_CHUNKS_SUPPORTED - png_voidp user_chunk_ptr; - png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ -#endif - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - int num_chunk_list; - png_bytep chunk_list; -#endif - -#ifdef PNG_READ_sRGB_SUPPORTED - /* Added in 1.5.5 to record an sRGB chunk in the png. */ - png_byte is_sRGB; -#endif - -/* New members added in libpng-1.0.3 */ -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - png_byte rgb_to_gray_status; - /* Added in libpng 1.5.5 to record setting of coefficients: */ - png_byte rgb_to_gray_coefficients_set; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff; - png_uint_16 rgb_to_gray_green_coeff; - /* deleted in 1.5.5: rgb_to_gray_blue_coeff; */ -#endif - -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) -/* Changed from png_byte to png_uint_32 at version 1.2.0 */ - png_uint_32 mng_features_permitted; -#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; -#endif - -/* New members added in libpng-1.2.0 */ - -/* 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; /* user supplied struct for mem functions */ - png_malloc_ptr malloc_fn; /* function for allocating memory */ - png_free_ptr free_fn; /* function for freeing memory */ -#endif - -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep quantize_sort; /* working sort array */ - png_bytep index_to_palette; /* where the original index currently is - in the palette */ - png_bytep palette_to_index; /* 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; - -#ifdef PNG_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max; - png_uint_32 user_height_max; - - /* 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; - - /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk - * can occupy when decompressed. 0 means unlimited. - */ - png_alloc_size_t user_chunk_malloc_max; -#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; -#endif - -/* New member added in libpng-1.2.26 */ - png_size_t old_big_row_buf_size; - -/* New member added in libpng-1.2.30 */ - png_charp chunkdata; /* buffer for reading chunk data */ - -#ifdef PNG_IO_STATE_SUPPORTED -/* New member added in libpng-1.4.0 */ - png_uint_32 io_state; -#endif - -/* New member added in libpng-1.5.6 */ - png_bytep big_prev_row; - - void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, - png_bytep row, png_const_bytep prev_row); -}; -#endif /* PNGSTRUCT_H */ diff --git a/plugins/FreeImage/Source/LibPNG/pngtest.c b/plugins/FreeImage/Source/LibPNG/pngtest.c deleted file mode 100644 index 840517400b..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngtest.c +++ /dev/null @@ -1,1820 +0,0 @@ - -/* pngtest.c - a simple test program to test libpng - * - * Last changed in libpng 1.5.6 [November 3, 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 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 _POSIX_SOURCE 1 - -#include "zlib.h" -#include "png.h" -/* Copied from pngpriv.h but only used in error messages below. */ -#ifndef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 8192 -#endif -# include -# include -# include -# define FCLOSE(file) fclose(file) - -#ifndef PNG_STDIO_SUPPORTED -typedef FILE * png_FILE_p; -#endif - -/* Makes pngtest verbose so we can find problems. */ -#ifndef PNG_DEBUG -# define PNG_DEBUG 0 -#endif - -#if PNG_DEBUG > 1 -# define pngtest_debug(m) ((void)fprintf(stderr, m "\n")) -# define pngtest_debug1(m,p1) ((void)fprintf(stderr, m "\n", p1)) -# define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2)) -#else -# define pngtest_debug(m) ((void)0) -# define pngtest_debug1(m,p1) ((void)0) -# define pngtest_debug2(m,p1,p2) ((void)0) -#endif - -#if !PNG_DEBUG -# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ -#endif - -/* The code uses memcmp and memcpy on large objects (typically row pointers) so - * it is necessary to do soemthing special on certain architectures, note that - * the actual support for this was effectively removed in 1.4, so only the - * memory remains in this program: - */ -#define CVT_PTR(ptr) (ptr) -#define CVT_PTR_NOCHECK(ptr) (ptr) -#define png_memcmp memcmp -#define png_memcpy memcpy -#define png_memset memset - -/* 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 -#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; -static int strict = 0; - -int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); - -#ifdef __TURBOC__ -#include -#endif - -/* Defined so I can write to a file on gui/windowing platforms */ -/* #define STDERR stderr */ -#define STDERR stdout /* For DOS */ - -/* 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 PNGCBAPI -read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); -void PNGCBAPI -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 PNGCBAPI -write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); -void PNGCBAPI -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 PNGCBAPI -count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); -void PNGCBAPI -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 PNGCBAPI -count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); -void PNGCBAPI -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; nbit_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; nbit_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. - */ - -#ifdef PNG_IO_STATE_SUPPORTED -void -pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, - png_uint_32 io_op); -void -pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, - png_uint_32 io_op) -{ - png_uint_32 io_state = png_get_io_state(png_ptr); - int err = 0; - - /* Check if the current operation (reading / writing) is as expected. */ - if ((io_state & PNG_IO_MASK_OP) != io_op) - png_error(png_ptr, "Incorrect operation in I/O state"); - - /* Check if the buffer size specific to the current location - * (file signature / header / data / crc) is as expected. - */ - switch (io_state & PNG_IO_MASK_LOC) - { - case PNG_IO_SIGNATURE: - if (data_length > 8) - err = 1; - break; - case PNG_IO_CHUNK_HDR: - if (data_length != 8) - err = 1; - break; - case PNG_IO_CHUNK_DATA: - break; /* no restrictions here */ - case PNG_IO_CHUNK_CRC: - if (data_length != 4) - err = 1; - break; - default: - err = 1; /* uninitialized */ - } - if (err) - png_error(png_ptr, "Bad I/O state or buffer size"); -} -#endif - -#ifndef USE_FAR_KEYWORD -static void PNGCBAPI -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) - { - check = fread(data, 1, length, (png_FILE_p)io_ptr); - } - - if (check != length) - { - png_error(png_ptr, "Read Error"); - } - -#ifdef PNG_IO_STATE_SUPPORTED - pngtest_check_io_state(png_ptr, length, PNG_IO_READING); -#endif -} -#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 PNGCBAPI -pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t 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_get_io_ptr(png_ptr)); - if ((png_bytep)n_data == data) - { - check = fread(n_data, 1, length, io_ptr); - } - else - { - png_byte buf[NEAR_BUF_SIZE]; - png_size_t read, remaining, err; - check = 0; - remaining = length; - - do - { - read = MIN(NEAR_BUF_SIZE, remaining); - err = fread(buf, 1, 1, io_ptr); - 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"); - -#ifdef PNG_IO_STATE_SUPPORTED - pngtest_check_io_state(png_ptr, length, PNG_IO_READING); -#endif -} -#endif /* USE_FAR_KEYWORD */ - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -static void PNGCBAPI -pngtest_flush(png_structp png_ptr) -{ - /* Do nothing; fflush() is said to be just a waste of energy. */ - PNG_UNUSED(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 PNGCBAPI -pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); - - if (check != length) - { - png_error(png_ptr, "Write Error"); - } - -#ifdef PNG_IO_STATE_SUPPORTED - pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); -#endif -} -#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 PNGCBAPI -pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t 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_get_io_ptr(png_ptr)); - - if ((png_bytep)near_data == data) - { - check = fwrite(near_data, 1, length, io_ptr); - } - - 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 */ - err = fwrite(buf, 1, written, io_ptr); - if (err != written) - break; - else - check += err; - data += written; - remaining -= written; - } - while (remaining != 0); - } - - if (check != length) - { - png_error(png_ptr, "Write Error"); - } - -#ifdef PNG_IO_STATE_SUPPORTED - pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); -#endif -} -#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 PNGCBAPI -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 PNGCBAPI -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_alloc_size_t 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 PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr, - png_alloc_size_t size)); -void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); - -png_voidp -PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t 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_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_malloc(png_ptr, size); - /* Restore malloc_fn and free_fn */ - - png_set_mem_fn(png_ptr, - NULL, png_debug_malloc, 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 %p\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 PNGCBAPI -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 %p\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 PNGCBAPI 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 tmp_jmpbuf; -#endif -#endif - - char inbuf[256], outbuf[256]; - - row_buf = NULL; - - if ((fpin = fopen(inname, "rb")) == NULL) - { - fprintf(STDERR, "Could not find input file %s\n", inname); - return (1); - } - - if ((fpout = fopen(outname, "wb")) == NULL) - { - fprintf(STDERR, "Could not open output file %s\n", outname); - FCLOSE(fpin); - return (1); - } - - pngtest_debug("Allocating read and write structures"); -#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG - read_ptr = - png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, - NULL, NULL, NULL, png_debug_malloc, png_debug_free); -#else - read_ptr = - png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, 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, NULL, - NULL, NULL, NULL, png_debug_malloc, png_debug_free); -#else - write_ptr = - png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); -#endif -#ifndef PNG_STDIO_SUPPORTED - png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, - pngtest_warning); -#endif -#endif - pngtest_debug("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 - pngtest_debug("Setting jmpbuf for read struct"); -#ifdef USE_FAR_KEYWORD - if (setjmp(tmp_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), tmp_jmpbuf, png_sizeof(jmp_buf)); -#endif - -#ifdef PNG_WRITE_SUPPORTED - pngtest_debug("Setting jmpbuf for write struct"); -#ifdef USE_FAR_KEYWORD - - if (setjmp(tmp_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), tmp_jmpbuf, png_sizeof(jmp_buf)); -#endif -#endif -#endif - - pngtest_debug("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 - -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED - /* Normally one would use Z_DEFAULT_STRATEGY for text compression. - * This is here just to make pngtest replicate the results from libpng - * versions prior to 1.5.4, and to test this new API. - */ - png_set_text_compression_strategy(write_ptr, Z_FILTERED); -#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, NULL); -#endif - png_set_read_status_fn(read_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, - 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, - NULL, 0); -#endif - - pngtest_debug("Reading info struct"); - png_read_info(read_ptr, read_info_ptr); - - pngtest_debug("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_bytep 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, ¶ms)) - { - 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) - { - pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); - - if (verbose) - printf("\n Text compression=%d\n", text_ptr->compression); - - 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_alpha; - int num_trans; - png_color_16p trans_color; - - if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans, - &trans_color)) - { - 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_color->gray > sample_max) || - (color_type == PNG_COLOR_TYPE_RGB && - ((int)trans_color->red > sample_max || - (int)trans_color->green > sample_max || - (int)trans_color->blue > sample_max)))) - png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, - trans_color); - } - } -#endif -#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - { - png_unknown_chunkp unknowns; - int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr, - &unknowns); - - if (num_unknowns) - { - int 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 < num_unknowns; i++) - png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, - unknowns[i].location); - } - } -#endif - -#ifdef PNG_WRITE_SUPPORTED - pngtest_debug("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 - pngtest_debug("Allocating row buffer..."); - row_buf = (png_bytep)png_malloc(read_ptr, - png_get_rowbytes(read_ptr, read_info_ptr)); - - pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); -#endif /* SINGLE_ROWBUF_ALLOC */ - pngtest_debug("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++) - { - pngtest_debug1("Writing row data for pass %d", pass); - for (y = 0; y < height; y++) - { -#ifndef SINGLE_ROWBUF_ALLOC - pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); - row_buf = (png_bytep)png_malloc(read_ptr, - png_get_rowbytes(read_ptr, read_info_ptr)); - - pngtest_debug2("\t0x%08lx (%u 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, 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 - pngtest_debug2("Freeing row buffer (pass %d, y = %u)", 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 - - pngtest_debug("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) - { - pngtest_debug1("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 = png_get_unknown_chunks(read_ptr, end_info_ptr, - &unknowns); - - if (num_unknowns) - { - int 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 < 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 - - pngtest_debug("Destroying data structs"); -#ifdef SINGLE_ROWBUF_ALLOC - pngtest_debug("destroying row_buf for read_ptr"); - png_free(read_ptr, row_buf); - row_buf = NULL; -#endif /* SINGLE_ROWBUF_ALLOC */ - pngtest_debug("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 - pngtest_debug("destroying write_end_info_ptr"); - png_destroy_info_struct(write_ptr, &write_end_info_ptr); - pngtest_debug("destroying write_ptr, write_info_ptr"); - png_destroy_write_struct(&write_ptr, &write_info_ptr); -#endif - pngtest_debug("Destruction complete."); - - FCLOSE(fpin); - FCLOSE(fpout); - - pngtest_debug("Opening files for comparison"); - if ((fpin = fopen(inname, "rb")) == NULL) - { - fprintf(STDERR, "Could not find file %s\n", inname); - return (1); - } - - if ((fpout = fopen(outname, "rb")) == NULL) - { - fprintf(STDERR, "Could not find file %s\n", outname); - FCLOSE(fpin); - return (1); - } - - for (;;) - { - png_size_t num_in, num_out; - - num_in = fread(inbuf, 1, 1, fpin); - num_out = fread(outbuf, 1, 1, fpout); - - 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); - - if (strict != 0) - return (1); - - else - 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); - - if (strict != 0) - return (1); - - else - 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); - - /* 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 if (strcmp(argv[1], "--strict") == 0) - { - status_dots_requested = 0; - verbose = 1; - inname = argv[2]; - strict++; - } - - 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; isize, - (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 png_libpng_version_1_5_9 Your_png_h_is_not_version_1_5_9; diff --git a/plugins/FreeImage/Source/LibPNG/pngtrans.c b/plugins/FreeImage/Source/LibPNG/pngtrans.c deleted file mode 100644 index 53d9a25b95..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngtrans.c +++ /dev/null @@ -1,678 +0,0 @@ - -/* pngtrans.c - transforms the data in a row (used by both readers and writers) - * - * Last changed in libpng 1.5.4 [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 - */ - -#include "pngpriv.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_const_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; - png_ptr->filler = (png_uint_16)filler; - - 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; - } -} - -/* 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 - -#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 && - */ - if (row_info->color_type == PNG_COLOR_TYPE_GRAY) - { - png_bytep rp = row; - png_size_t i; - png_size_t 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_size_t i; - png_size_t istop = row_info->rowbytes; - - for (i = 0; i < istop; i += 2) - { - *rp = (png_byte)(~(*rp)); - rp += 2; - } - } - -#ifdef PNG_16BIT_SUPPORTED - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - row_info->bit_depth == 16) - { - png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; - - for (i = 0; i < istop; i += 4) - { - *rp = (png_byte)(~(*rp)); - *(rp + 1) = (png_byte)(~(*(rp + 1))); - rp += 4; - } - } -#endif -} -#endif - -#ifdef PNG_16BIT_SUPPORTED -#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 (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 -#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 (row_info->bit_depth < 8) - { - png_bytep rp; - png_const_bytep end, table; - - end = row + row_info->rowbytes; - - if (row_info->bit_depth == 1) - table = onebppswaptable; - - else if (row_info->bit_depth == 2) - table = twobppswaptable; - - else if (row_info->bit_depth == 4) - table = 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 a channel - this used to be 'png_do_strip_filler' but it used a - * somewhat weird combination of flags to determine what to do. All the calls - * to png_do_strip_filler are changed in 1.5.2 to call this instead with the - * correct arguments. - * - * The routine isn't general - the channel must be the channel at the start or - * end (not in the middle) of each pixel. - */ -void /* PRIVATE */ -png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) -{ - png_bytep sp = row; /* source pointer */ - png_bytep dp = row; /* destination pointer */ - png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */ - - /* At the start sp will point to the first byte to copy and dp to where - * it is copied to. ep always points just beyond the end of the row, so - * the loop simply copies (channels-1) channels until sp reaches ep. - * - * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc. - * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc. - */ - - /* GA, GX, XG cases */ - if (row_info->channels == 2) - { - if (row_info->bit_depth == 8) - { - if (at_start) /* Skip initial filler */ - ++sp; - else /* Skip initial channel and, for sp, the filler */ - sp += 2, ++dp; - - /* For a 1 pixel wide image there is nothing to do */ - while (sp < ep) - *dp++ = *sp, sp += 2; - - row_info->pixel_depth = 8; - } - - else if (row_info->bit_depth == 16) - { - if (at_start) /* Skip initial filler */ - sp += 2; - else /* Skip initial channel and, for sp, the filler */ - sp += 4, dp += 2; - - while (sp < ep) - *dp++ = *sp++, *dp++ = *sp, sp += 3; - - row_info->pixel_depth = 16; - } - - else - return; /* bad bit depth */ - - row_info->channels = 1; - - /* Finally fix the color type if it records an alpha channel */ - if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - row_info->color_type = PNG_COLOR_TYPE_GRAY; - } - - /* RGBA, RGBX, XRGB cases */ - else if (row_info->channels == 4) - { - if (row_info->bit_depth == 8) - { - if (at_start) /* Skip initial filler */ - ++sp; - else /* Skip initial channels and, for sp, the filler */ - sp += 4, dp += 3; - - /* Note that the loop adds 3 to dp and 4 to sp each time. */ - while (sp < ep) - *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; - - row_info->pixel_depth = 24; - } - - else if (row_info->bit_depth == 16) - { - if (at_start) /* Skip initial filler */ - sp += 2; - else /* Skip initial channels and, for sp, the filler */ - sp += 8, dp += 6; - - while (sp < ep) - { - /* Copy 6 bytes, skip 2 */ - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp, sp += 3; - } - - row_info->pixel_depth = 48; - } - - else - return; /* bad bit depth */ - - row_info->channels = 3; - - /* Finally fix the color type if it records an alpha channel */ - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - row_info->color_type = PNG_COLOR_TYPE_RGB; - } - - else - return; /* The filler channel has gone already */ - - /* Fix the rowbytes value. */ - row_info->rowbytes = dp-row; -} -#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 ((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; - } - } - } - -#ifdef PNG_16BIT_SUPPORTED - 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 - } -} -#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -#ifdef PNG_USER_TRANSFORM_PTR_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; - 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; -} -#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. - */ -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -png_voidp PNGAPI -png_get_user_transform_ptr(png_const_structp png_ptr) -{ - if (png_ptr == NULL) - return (NULL); - - return ((png_voidp)png_ptr->user_transform_ptr); -} -#endif - -#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED -png_uint_32 PNGAPI -png_get_current_row_number(png_const_structp png_ptr) -{ - /* See the comments in png.h - this is the sub-image row when reading and - * interlaced image. - */ - if (png_ptr != NULL) - return png_ptr->row_number; - - return PNG_UINT_32_MAX; /* help the app not to fail silently */ -} - -png_byte PNGAPI -png_get_current_pass_number(png_const_structp png_ptr) -{ - if (png_ptr != NULL) - return png_ptr->pass; - return 8; /* invalid */ -} -#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */ -#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED || - PNG_WRITE_USER_TRANSFORM_SUPPORTED */ -#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibPNG/pngwio.c b/plugins/FreeImage/Source/LibPNG/pngwio.c deleted file mode 100644 index 8eacf9f6d4..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngwio.c +++ /dev/null @@ -1,254 +0,0 @@ - -/* pngwio.c - functions for data output - * - * Last changed in libpng 1.5.0 [January 6, 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 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(...). - */ - -#include "pngpriv.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_const_bytep data, png_size_t length) -{ - /* NOTE: write_data_fn must not change the buffer! */ - if (png_ptr->write_data_fn != NULL ) - (*(png_ptr->write_data_fn))(png_ptr, (png_bytep)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 PNGCBAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - if (png_ptr == NULL) - return; - - check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); - - 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 PNGCBAPI -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) - { - check = fwrite(near_data, 1, length, io_ptr); - } - - 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 */ - err = fwrite(buf, 1, written, io_ptr); - - 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 PNGCBAPI -png_default_flush(png_structp png_ptr) -{ - png_FILE_p io_ptr; - - if (png_ptr == NULL) - return; - - io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); - fflush(io_ptr); -} -# 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, - "Can't set both read_data_fn and write_data_fn in the" - " same structure"); - } -} - -#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/plugins/FreeImage/Source/LibPNG/pngwrite.c b/plugins/FreeImage/Source/LibPNG/pngwrite.c deleted file mode 100644 index dc12a20481..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngwrite.c +++ /dev/null @@ -1,1655 +0,0 @@ - -/* pngwrite.c - general routines to write a PNG file - * - * Last changed in libpng 1.5.7 [December 15, 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 - */ - -#include "pngpriv.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) - png_write_gAMA_fixed(png_ptr, info_ptr->gamma); -#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, - (png_charp)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) - png_write_cHRM_fixed(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); -#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->location & PNG_AFTER_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_alpha[j] = - (png_byte)(255 - info_ptr->trans_alpha[j]); - } -#endif - png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), - 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_WRITE_sCAL_SUPPORTED - if (info_ptr->valid & PNG_INFO_sCAL) - png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, - info_ptr->scal_s_width, info_ptr->scal_s_height); -#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, PNG_CONST 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_FUNCTION(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),PNG_ALLOCATED) -{ -#ifdef PNG_USER_MEM_SUPPORTED - return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, - warn_fn, NULL, NULL, NULL)); -} - -/* Alternate initialize png_ptr structure, and allocate any memory needed */ -static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */ - -PNG_FUNCTION(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),PNG_ALLOCATED) -{ -#endif /* PNG_USER_MEM_SUPPORTED */ - volatile int png_cleanup_needed = 0; -#ifdef PNG_SETJMP_SUPPORTED - volatile -#endif - png_structp png_ptr; -#ifdef PNG_SETJMP_SUPPORTED -#ifdef USE_FAR_KEYWORD - jmp_buf tmp_jmpbuf; -#endif -#endif - - 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 -/* 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(tmp_jmpbuf)) -#else - if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */ -#endif -#ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); -#endif - PNG_ABORT(); -#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 (!png_user_version_check(png_ptr, user_png_ver)) - png_cleanup_needed = 1; - - /* Initialize zbuf - compression buffer */ - png_ptr->zbuf_size = PNG_ZBUF_SIZE; - - if (!png_cleanup_needed) - { - png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, - png_ptr->zbuf_size); - if (png_ptr->zbuf == NULL) - png_cleanup_needed = 1; - } - - if (png_cleanup_needed) - { - /* Clean up PNG structure and deallocate any memory. */ - 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); - } - - png_set_write_fn(png_ptr, NULL, NULL, NULL); - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - png_reset_filter_heuristics(png_ptr); -#endif - - return (png_ptr); -} - - -/* 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_const_bytep row) -{ - /* 1.5.6: moved from png_struct to be a local structure: */ - png_row_info row_info; - - if (png_ptr == NULL) - return; - - png_debug2(1, "in png_write_row (row %u, 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; - - default: /* error: ignore it */ - break; - } - } -#endif - - /* Set up row info for transformations */ - row_info.color_type = png_ptr->color_type; - row_info.width = png_ptr->usr_width; - row_info.channels = png_ptr->usr_channels; - row_info.bit_depth = png_ptr->usr_bit_depth; - row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels); - row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); - - png_debug1(3, "row_info->color_type = %d", row_info.color_type); - png_debug1(3, "row_info->width = %u", row_info.width); - png_debug1(3, "row_info->channels = %d", row_info.channels); - png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth); - png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth); - png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes); - - /* Copy user's row into buffer, leaving room for filter byte. */ - png_memcpy(png_ptr->row_buf + 1, row, 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(&row_info, png_ptr->row_buf + 1, png_ptr->pass); - /* This should always get caught above, but still ... */ - if (!(row_info.width)) - { - png_write_finish_row(png_ptr); - return; - } - } -#endif - -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED - /* Handle other transformations */ - if (png_ptr->transformations) - png_do_write_transformations(png_ptr, &row_info); -#endif - - /* At this point the row_info pixel depth must match the 'transformed' depth, - * which is also the output depth. - */ - if (row_info.pixel_depth != png_ptr->pixel_depth || - row_info.pixel_depth != png_ptr->transformed_pixel_depth) - png_error(png_ptr, "internal write transform logic error"); - -#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(&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, &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); - 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->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 - 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->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; -#ifdef PNG_WARNINGS_SUPPORTED - png_error_ptr warning_fn; -#endif - 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 */ - if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED) - 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_WRITE_WEIGHTED_FILTER_SUPPORTED - /* Use this to save a little code space, it doesn't free the filter_costs */ - png_reset_filter_heuristics(png_ptr); - 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->longjmp_buffer, png_sizeof(jmp_buf)); -#endif - - error_fn = png_ptr->error_fn; -#ifdef PNG_WARNINGS_SUPPORTED - warning_fn = png_ptr->warning_fn; -#endif - 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; -#ifdef PNG_WARNINGS_SUPPORTED - png_ptr->warning_fn = warning_fn; -#endif - 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->longjmp_buffer, 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_byte)(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_byte)(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 */ -/* Convenience reset API. */ -static void -png_reset_filter_heuristics(png_structp png_ptr) -{ - /* Clear out any old values in the 'weights' - this must be done because if - * the app calls set_filter_heuristics multiple times with different - * 'num_weights' values we would otherwise potentially have wrong sized - * arrays. - */ - png_ptr->num_prev_filters = 0; - png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; - if (png_ptr->prev_filters != NULL) - { - png_bytep old = png_ptr->prev_filters; - png_ptr->prev_filters = NULL; - png_free(png_ptr, old); - } - if (png_ptr->filter_weights != NULL) - { - png_uint_16p old = png_ptr->filter_weights; - png_ptr->filter_weights = NULL; - png_free(png_ptr, old); - } - - if (png_ptr->inv_filter_weights != NULL) - { - png_uint_16p old = png_ptr->inv_filter_weights; - png_ptr->inv_filter_weights = NULL; - png_free(png_ptr, old); - } - - /* Leave the filter_costs - this array is fixed size. */ -} - -static int -png_init_filter_heuristics(png_structp png_ptr, int heuristic_method, - int num_weights) -{ - if (png_ptr == NULL) - return 0; - - /* Clear out the arrays */ - png_reset_filter_heuristics(png_ptr); - - /* Check arguments; the 'reset' function makes the correct settings for the - * unweighted case, but we must handle the weight case by initializing the - * arrays for the caller. - */ - if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int i; - - if (num_weights > 0) - { - 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; - } - - 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; - } - - /* Safe to set this now */ - png_ptr->num_prev_filters = (png_byte)num_weights; - } - - /* 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; - } - - /* All the arrays are inited, safe to set this: */ - png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED; - - /* Return the 'ok' code. */ - return 1; - } - else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT || - heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) - { - return 1; - } - else - { - png_warning(png_ptr, "Unknown filter heuristic method"); - return 0; - } -} - -/* Provide floating and fixed point APIs */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, - int num_weights, png_const_doublep filter_weights, - png_const_doublep filter_costs) -{ - png_debug(1, "in png_set_filter_heuristics"); - - /* The internal API allocates all the arrays and ensures that the elements of - * those arrays are set to the default value. - */ - if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) - return; - - /* If using the weighted method copy in the weights. */ - if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int i; - 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)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5); - - png_ptr->filter_weights[i] = - (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5); - } - } - - /* 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[i] >= 1.0) - { - png_ptr->inv_filter_costs[i] = - (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5); - - png_ptr->filter_costs[i] = - (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5); - } - } -} -#endif /* FLOATING_POINT */ - -#ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method, - int num_weights, png_const_fixed_point_p filter_weights, - png_const_fixed_point_p filter_costs) -{ - png_debug(1, "in png_set_filter_heuristics_fixed"); - - /* The internal API allocates all the arrays and ensures that the elements of - * those arrays are set to the default value. - */ - if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) - return; - - /* If using the weighted method copy in the weights. */ - if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int i; - for (i = 0; i < num_weights; i++) - { - if (filter_weights[i] <= 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) - ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1); - - png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR* - PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]); - } - } - - /* 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[i] >= PNG_FP_1) - { - png_uint_32 tmp; - - /* Use a 32 bit unsigned temporary here because otherwise the - * intermediate value will be a 32 bit *signed* integer (ANSI rules) - * and this will get the wrong answer on division. - */ - tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2); - tmp /= filter_costs[i]; - - png_ptr->inv_filter_costs[i] = (png_uint_16)tmp; - - tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF; - tmp /= PNG_FP_1; - - png_ptr->filter_costs[i] = (png_uint_16)tmp; - } - } -} -#endif /* FIXED_POINT */ -#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; -} - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -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; -} - -/* The following were added to libpng-1.5.4 */ -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -void PNGAPI -png_set_text_compression_level(png_structp png_ptr, int level) -{ - png_debug(1, "in png_set_text_compression_level"); - - if (png_ptr == NULL) - return; - - png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_LEVEL; - png_ptr->zlib_text_level = level; -} - -void PNGAPI -png_set_text_compression_mem_level(png_structp png_ptr, int mem_level) -{ - png_debug(1, "in png_set_text_compression_mem_level"); - - if (png_ptr == NULL) - return; - - png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL; - png_ptr->zlib_text_mem_level = mem_level; -} - -void PNGAPI -png_set_text_compression_strategy(png_structp png_ptr, int strategy) -{ - png_debug(1, "in png_set_text_compression_strategy"); - - if (png_ptr == NULL) - return; - - png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_STRATEGY; - png_ptr->zlib_text_strategy = strategy; -} - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -void PNGAPI -png_set_text_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, "Text compression window is being reset to 512"); - window_bits = 9; - } - -#endif - png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS; - png_ptr->zlib_text_window_bits = window_bits; -} - -void PNGAPI -png_set_text_compression_method(png_structp png_ptr, int method) -{ - png_debug(1, "in png_set_text_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_ZTXT_CUSTOM_METHOD; - png_ptr->zlib_text_method = method; -} -#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ -/* end of API added to libpng-1.5.4 */ - -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); - - PNG_UNUSED(transforms) /* Quiet compiler warnings */ - PNG_UNUSED(params) -} -#endif -#endif /* PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibPNG/pngwtran.c b/plugins/FreeImage/Source/LibPNG/pngwtran.c deleted file mode 100644 index b598149a96..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngwtran.c +++ /dev/null @@ -1,633 +0,0 @@ - -/* pngwtran.c - transforms the data in a row for PNG writers - * - * Last changed in libpng 1.5.6 [November 3, 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 - */ - -#include "pngpriv.h" - -#ifdef PNG_WRITE_SUPPORTED - -#ifdef PNG_WRITE_TRANSFORMS_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_row_infop row_info) -{ - 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 */ - row_info, /* row_info: */ - /* png_uint_32 width; width of row */ - /* png_size_t 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_channel(row_info, png_ptr->row_buf + 1, - !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); -#endif - -#ifdef PNG_WRITE_PACKSWAP_SUPPORTED - if (png_ptr->transformations & PNG_PACKSWAP) - png_do_packswap(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_WRITE_PACK_SUPPORTED - if (png_ptr->transformations & PNG_PACK) - png_do_pack(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(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_WRITE_SHIFT_SUPPORTED - if (png_ptr->transformations & PNG_SHIFT) - png_do_shift(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(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(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_WRITE_BGR_SUPPORTED - if (png_ptr->transformations & PNG_BGR) - png_do_bgr(row_info, png_ptr->row_buf + 1); -#endif - -#ifdef PNG_WRITE_INVERT_SUPPORTED - if (png_ptr->transformations & PNG_INVERT_MONO) - png_do_invert(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 && - 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; - } - - default: - 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_const_color_8p bit_depth) -{ - png_debug(1, "in png_do_shift"); - - if (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_size_t i; - png_byte mask; - png_size_t 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"); - - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This converts from ARGB to RGBA */ - 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; - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - else - { - /* This converts from AARRGGBB to RRGGBBAA */ - 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]; - } - } -#endif /* PNG_WRITE_16BIT_SUPPORTED */ - } - - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This converts from AG to GA */ - 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; - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - else - { - /* This converts from AAGG to GGAA */ - 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 /* PNG_WRITE_16BIT_SUPPORTED */ - } - } -} -#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"); - - { - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This inverts the alpha channel in RGBA */ - 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++)); - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - else - { - /* This inverts the alpha channel in RRGGBBAA */ - 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++)); - } - } -#endif /* PNG_WRITE_16BIT_SUPPORTED */ - } - - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - if (row_info->bit_depth == 8) - { - /* This inverts the alpha channel in GA */ - 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++)); - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - else - { - /* This inverts the alpha channel in GGAA */ - 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 /* PNG_WRITE_16BIT_SUPPORTED */ - } - } -} -#endif -#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ - -#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 ((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); - } - } - -#ifdef PNG_WRITE_16BIT_SUPPORTED - 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_WRITE_16BIT_SUPPORTED */ - } -} -#endif /* PNG_MNG_FEATURES_SUPPORTED */ -#endif /* PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/Source/LibPNG/pngwutil.c b/plugins/FreeImage/Source/LibPNG/pngwutil.c deleted file mode 100644 index 64888f7c6c..0000000000 --- a/plugins/FreeImage/Source/LibPNG/pngwutil.c +++ /dev/null @@ -1,3180 +0,0 @@ - -/* pngwutil.c - utilities to write a PNG file - * - * Last changed in libpng 1.5.6 [November 3, 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 - */ - -#include "pngpriv.h" - -#ifdef PNG_WRITE_SUPPORTED - -#ifdef PNG_WRITE_INT_FUNCTIONS_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); -} - -#ifdef PNG_SAVE_INT_32_SUPPORTED -/* 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. Note that, - * the following works correctly even if png_int_32 has more than 32 bits - * (compare the more complex code required on read for sign extention.) - */ -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); -} -#endif - -/* 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); -} -#endif - -/* 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 PNGAPI -png_write_sig(png_structp png_ptr) -{ - png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - -#ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that the signature is being written */ - png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; -#endif - - /* 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 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(). - */ -static void -png_write_chunk_header(png_structp png_ptr, png_uint_32 chunk_name, - png_uint_32 length) -{ - png_byte buf[8]; - -#if defined(PNG_DEBUG) && (PNG_DEBUG > 0) - PNG_CSTRING_FROM_CHUNK(buf, chunk_name); - png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length); -#endif - - if (png_ptr == NULL) - return; - -#ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that the chunk header is being written. - * PNG_IO_CHUNK_HDR requires a single I/O call. - */ - png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; -#endif - - /* Write the length and the chunk name */ - png_save_uint_32(buf, length); - png_save_uint_32(buf + 4, chunk_name); - png_write_data(png_ptr, buf, 8); - - /* Put the chunk name into png_ptr->chunk_name */ - png_ptr->chunk_name = chunk_name; - - /* Reset the crc and run it over the chunk name */ - png_reset_crc(png_ptr); - - png_calculate_crc(png_ptr, buf + 4, 4); - -#ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that chunk data will (possibly) be written. - * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. - */ - png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; -#endif -} - -void PNGAPI -png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_string, - png_uint_32 length) -{ - png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); -} - -/* Write the data of a PNG chunk started with png_write_chunk_header(). - * 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_header(). - */ -void PNGAPI -png_write_chunk_data(png_structp png_ptr, png_const_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_header(). */ -void PNGAPI -png_write_chunk_end(png_structp png_ptr) -{ - png_byte buf[4]; - - if (png_ptr == NULL) return; - -#ifdef PNG_IO_STATE_SUPPORTED - /* Inform the I/O callback that the chunk CRC is being written. - * PNG_IO_CHUNK_CRC requires a single I/O function call. - */ - png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; -#endif - - /* 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); -} - -/* 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. - */ -static void -png_write_complete_chunk(png_structp png_ptr, png_uint_32 chunk_name, - png_const_bytep data, png_size_t length) -{ - if (png_ptr == NULL) - return; - - /* On 64 bit architectures 'length' may not fit in a png_uint_32. */ - if (length > PNG_UINT_32_MAX) - png_error(png_ptr, "length exceeds PNG maxima"); - - png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length); - png_write_chunk_data(png_ptr, data, length); - png_write_chunk_end(png_ptr); -} - -/* This is the API that calls the internal function above. */ -void PNGAPI -png_write_chunk(png_structp png_ptr, png_const_bytep chunk_string, - png_const_bytep data, png_size_t length) -{ - png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, - length); -} - -/* Initialize the compressor for the appropriate type of compression. */ -static void -png_zlib_claim(png_structp png_ptr, png_uint_32 state) -{ - if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE)) - { - /* If already initialized for 'state' do not re-init. */ - if (png_ptr->zlib_state != state) - { - int ret = Z_OK; - png_const_charp who = "-"; - - /* If actually initialized for another state do a deflateEnd. */ - if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED) - { - ret = deflateEnd(&png_ptr->zstream); - who = "end"; - png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED; - } - - /* zlib itself detects an incomplete state on deflateEnd */ - if (ret == Z_OK) switch (state) - { -# ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED - case PNG_ZLIB_FOR_TEXT: - ret = deflateInit2(&png_ptr->zstream, - png_ptr->zlib_text_level, png_ptr->zlib_text_method, - png_ptr->zlib_text_window_bits, - png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy); - who = "text"; - break; -# endif - - case PNG_ZLIB_FOR_IDAT: - 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); - who = "IDAT"; - break; - - default: - png_error(png_ptr, "invalid zlib state"); - } - - if (ret == Z_OK) - png_ptr->zlib_state = state; - - else /* an error in deflateEnd or deflateInit2 */ - { - size_t pos = 0; - char msg[64]; - - pos = png_safecat(msg, sizeof msg, pos, - "zlib failed to initialize compressor ("); - pos = png_safecat(msg, sizeof msg, pos, who); - - switch (ret) - { - case Z_VERSION_ERROR: - pos = png_safecat(msg, sizeof msg, pos, ") version error"); - break; - - case Z_STREAM_ERROR: - pos = png_safecat(msg, sizeof msg, pos, ") stream error"); - break; - - case Z_MEM_ERROR: - pos = png_safecat(msg, sizeof msg, pos, ") memory error"); - break; - - default: - pos = png_safecat(msg, sizeof msg, pos, ") unknown error"); - break; - } - - png_error(png_ptr, msg); - } - } - - /* Here on success, claim the zstream: */ - png_ptr->zlib_state |= PNG_ZLIB_IN_USE; - } - - else - png_error(png_ptr, "zstream already in use (internal error)"); -} - -/* The opposite: release the stream. It is also reset, this API will warn on - * error but will not fail. - */ -static void -png_zlib_release(png_structp png_ptr) -{ - if (png_ptr->zlib_state & PNG_ZLIB_IN_USE) - { - int ret = deflateReset(&png_ptr->zstream); - - png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE; - - if (ret != Z_OK) - { - png_const_charp err; - PNG_WARNING_PARAMETERS(p) - - switch (ret) - { - case Z_VERSION_ERROR: - err = "version"; - break; - - case Z_STREAM_ERROR: - err = "stream"; - break; - - case Z_MEM_ERROR: - err = "memory"; - break; - - default: - err = "unknown"; - break; - } - - png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret); - png_warning_parameter(p, 2, err); - - if (png_ptr->zstream.msg) - err = png_ptr->zstream.msg; - else - err = "[no zlib message]"; - - png_warning_parameter(p, 3, err); - - png_formatted_warning(png_ptr, p, - "zlib failed to reset compressor: @1(@2): @3"); - } - } - - else - png_warning(png_ptr, "zstream not in use (internal error)"); -} - -#ifdef PNG_WRITE_COMPRESSED_TEXT_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 -{ - png_const_bytep input; /* The uncompressed input data */ - png_size_t input_len; /* Its length */ - int num_output_ptr; /* Number of output pointers used */ - int max_output_ptr; /* Size of output_ptr */ - png_bytep *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_const_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 = text_len; - - /* We may just want to pass the text right through */ - if (compression == PNG_TEXT_COMPRESSION_NONE) - { - comp->input = (png_const_bytep)text; - return((int)text_len); - } - - if (compression >= PNG_TEXT_COMPRESSION_LAST) - { - PNG_WARNING_PARAMETERS(p) - - png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, - compression); - png_formatted_warning(png_ptr, p, "Unknown compression type @1"); - } - - /* 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). - */ - png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT); - - /* Set up the compression buffers */ - /* TODO: the following cast hides a potential overflow problem. */ - png_ptr->zstream.avail_in = (uInt)text_len; - - /* NOTE: assume zlib doesn't overwrite the input */ - png_ptr->zstream.next_in = (Bytef *)text; - png_ptr->zstream.avail_out = png_ptr->zbuf_size; - png_ptr->zstream.next_out = 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_bytepp old_ptr; - - old_ptr = comp->output_ptr; - - comp->output_ptr = (png_bytepp)png_malloc(png_ptr, - (png_alloc_size_t) - (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_bytepp)png_malloc(png_ptr, - (png_alloc_size_t) - (comp->max_output_ptr * png_sizeof(png_charp))); - } - - /* Save the data */ - comp->output_ptr[comp->num_output_ptr] = - (png_bytep)png_malloc(png_ptr, - (png_alloc_size_t)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_bytepp old_ptr; - - old_ptr = comp->output_ptr; - - /* This could be optimized to realloc() */ - comp->output_ptr = (png_bytepp)png_malloc(png_ptr, - (png_alloc_size_t)(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_bytepp)png_malloc(png_ptr, - (png_alloc_size_t)(comp->max_output_ptr * - png_sizeof(png_charp))); - } - - /* Save the data */ - comp->output_ptr[comp->num_output_ptr] = - (png_bytep)png_malloc(png_ptr, - (png_alloc_size_t)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, comp->input, comp->input_len); - - return; - } - -#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED - /* The zbuf_size test is because the code below doesn't work if zbuf_size is - * '1'; simply skip it to avoid memory overwrite. - */ - if (comp->input_len >= 2 && comp->input_len < 16384 && png_ptr->zbuf_size > 1) - { - unsigned int z_cmf; /* zlib compression method and flags */ - - /* Optimize the CMF field in the zlib stream. This hack of the zlib - * stream is compliant to the stream specification. - */ - - if (comp->num_output_ptr) - z_cmf = comp->output_ptr[0][0]; - else - z_cmf = png_ptr->zbuf[0]; - - if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) - { - unsigned int z_cinfo; - unsigned int half_z_window_size; - png_size_t uncompressed_text_size = comp->input_len; - - z_cinfo = z_cmf >> 4; - half_z_window_size = 1 << (z_cinfo + 7); - - while (uncompressed_text_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 (comp->num_output_ptr) - { - - if (comp->output_ptr[0][0] != z_cmf) - { - int tmp; - - comp->output_ptr[0][0] = (png_byte)z_cmf; - tmp = comp->output_ptr[0][1] & 0xe0; - tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; - comp->output_ptr[0][1] = (png_byte)tmp; - } - } - else - { - int tmp; - - png_ptr->zbuf[0] = (png_byte)z_cmf; - tmp = png_ptr->zbuf[1] & 0xe0; - tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; - png_ptr->zbuf[1] = (png_byte)tmp; - } - } - - else - png_error(png_ptr, - "Invalid zlib compression method or flags in non-IDAT chunk"); - } -#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ - - /* Write saved output buffers, if any */ - for (i = 0; i < comp->num_output_ptr; i++) - { - png_write_chunk_data(png_ptr, comp->output_ptr[i], - (png_size_t)png_ptr->zbuf_size); - - png_free(png_ptr, comp->output_ptr[i]); - } - - if (comp->max_output_ptr != 0) - png_free(png_ptr, comp->output_ptr); - - /* 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 */ - png_zlib_release(png_ptr); -} -#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ - -/* 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) -{ - 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: -#ifdef PNG_WRITE_16BIT_SUPPORTED - case 16: -#endif - png_ptr->channels = 1; break; - - default: - png_error(png_ptr, - "Invalid bit depth for grayscale image"); - } - break; - - case PNG_COLOR_TYPE_RGB: -#ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) -#endif - 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: -#ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) -#endif - 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_complete_chunk(png_ptr, 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; - -#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED - if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY)) - png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; - - if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL)) - png_ptr->zlib_text_level = png_ptr->zlib_level; - - if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL)) - png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level; - - if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS)) - png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits; - - if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD)) - png_ptr->zlib_text_method = png_ptr->zlib_method; -#else - png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; - png_ptr->zlib_text_level = png_ptr->zlib_level; - png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level; - png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits; - png_ptr->zlib_text_method = png_ptr->zlib_method; -#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ -#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ - - /* Record that the compressor has not yet been initialized. */ - png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED; - - png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ -} - -/* 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_const_colorp palette, - png_uint_32 num_pal) -{ - png_uint_32 i; - png_const_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_header(png_ptr, 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) -{ - png_debug(1, "in png_write_IDAT"); - -#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED - if (!(png_ptr->mode & PNG_HAVE_IDAT) && - png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) - { - /* Optimize the CMF field in the zlib stream. This hack of the zlib - * stream is compliant to the stream specification. - */ - 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) - { - /* Compute the maximum possible length of the datastream */ - - /* Number of pixels, plus for each row a filter byte - * and possibly a padding byte, so increase the maximum - * size to account for these. - */ - unsigned int z_cinfo; - unsigned int half_z_window_size; - png_uint_32 uncompressed_idat_size = png_ptr->height * - ((png_ptr->width * - png_ptr->channels * png_ptr->bit_depth + 15) >> 3); - - /* If it's interlaced, each block of 8 rows is sent as up to - * 14 rows, i.e., 6 additional rows, each with a filter byte - * and possibly a padding byte - */ - if (png_ptr->interlaced) - uncompressed_idat_size += ((png_ptr->height + 7)/8) * - (png_ptr->bit_depth < 8 ? 12 : 6); - - z_cinfo = z_cmf >> 4; - 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] != z_cmf) - { - int tmp; - data[0] = (png_byte)z_cmf; - tmp = data[1] & 0xe0; - tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; - data[1] = (png_byte)tmp; - } - } - } - - else - png_error(png_ptr, - "Invalid zlib compression method or flags in IDAT"); - } -#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ - - png_write_complete_chunk(png_ptr, png_IDAT, data, length); - png_ptr->mode |= PNG_HAVE_IDAT; - - /* Prior to 1.5.4 this code was replicated in every caller (except at the - * end, where it isn't technically necessary). Since this function has - * flushed the data we can safely reset the zlib output buffer here. - */ - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; -} - -/* Write an IEND chunk */ -void /* PRIVATE */ -png_write_IEND(png_structp png_ptr) -{ - png_debug(1, "in png_write_IEND"); - - png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); - png_ptr->mode |= PNG_HAVE_IEND; -} - -#ifdef PNG_WRITE_gAMA_SUPPORTED -/* Write a gAMA chunk */ -void /* PRIVATE */ -png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) -{ - 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_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); -} -#endif - -#ifdef PNG_WRITE_sRGB_SUPPORTED -/* Write a sRGB chunk */ -void /* PRIVATE */ -png_write_sRGB(png_structp png_ptr, int srgb_intent) -{ - 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_complete_chunk(png_ptr, 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_const_charp name, int compression_type, - png_const_charp profile, int profile_len) -{ - 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_const_bytep)profile ))<<24) | - ((*( (png_const_bytep)profile + 1))<<16) | - ((*( (png_const_bytep)profile + 2))<< 8) | - ((*( (png_const_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_header(png_ptr, 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) - { - comp.input_len = 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_const_sPLT_tp spalette) -{ - png_size_t name_len; - png_charp new_name; - png_byte entrybuf[10]; - png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); - png_size_t 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_header(png_ptr, 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, &spalette->depth, (png_size_t)1); - - /* Loop through each palette entry, writing appropriately */ -#ifdef PNG_POINTER_INDEXING_SUPPORTED - for (ep = spalette->entries; epentries + 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_const_color_8p sbit, int color_type) -{ - 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_complete_chunk(png_ptr, png_sBIT, buf, size); -} -#endif - -#ifdef PNG_WRITE_cHRM_SUPPORTED -/* Write the cHRM chunk */ -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) -{ - 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_complete_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); - } -} -#endif - -#ifdef PNG_WRITE_tRNS_SUPPORTED -/* Write the tRNS chunk */ -void /* PRIVATE */ -png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha, - png_const_color_16p tran, int num_trans, int color_type) -{ - 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_complete_chunk(png_ptr, png_tRNS, trans_alpha, (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_complete_chunk(png_ptr, 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); -#ifdef PNG_WRITE_16BIT_SUPPORTED - if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) -#else - if (buf[0] | buf[2] | buf[4]) -#endif - { - png_warning(png_ptr, - "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); - return; - } - - png_write_complete_chunk(png_ptr, 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_const_color_16p back, int color_type) -{ - 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_complete_chunk(png_ptr, 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); -#ifdef PNG_WRITE_16BIT_SUPPORTED - if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) -#else - if (buf[0] | buf[2] | buf[4]) -#endif - { - png_warning(png_ptr, - "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); - - return; - } - - png_write_complete_chunk(png_ptr, 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_complete_chunk(png_ptr, 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_const_uint_16p hist, int num_hist) -{ - 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_header(png_ptr, 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_const_charp key, png_charpp new_key) -{ - png_size_t key_len; - png_const_charp ikp; - 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 (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++) - { - if ((png_byte)*ikp < 0x20 || - ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1)) - { - PNG_WARNING_PARAMETERS(p) - - png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x, - (png_byte)*ikp); - png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1"); - *dp = ' '; - } - - else - { - *dp = *ikp; - } - } - *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); - 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_const_charp key, png_const_charp text, - png_size_t text_len) -{ - 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_header(png_ptr, 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_const_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_const_charp key, png_const_charp text, - png_size_t text_len, int compression) -{ - png_size_t key_len; - png_byte buf; - 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_header(png_ptr, 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 = (png_byte)compression; - - /* Write compression */ - png_write_chunk_data(png_ptr, &buf, (png_size_t)1); - - /* Write the compressed data */ - comp.input_len = text_len; - 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_const_charp key, - png_const_charp lang, png_const_charp lang_key, png_const_charp text) -{ - 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_header(png_ptr, 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_const_bytep)new_lang : cbuf), - (png_size_t)(lang_len + 1)); - - png_write_chunk_data(png_ptr, (lang_key ? (png_const_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) -{ - 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_complete_chunk(png_ptr, 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_const_charp units, - png_charpp params) -{ - png_size_t purpose_len, units_len, total_len; - png_size_tp 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_size_tp)png_malloc(png_ptr, - (png_alloc_size_t)(nparams * png_sizeof(png_size_t))); - - /* 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 += params_len[i]; - } - - png_debug1(3, "pCAL total length = %d", (int)total_len); - png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len); - png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, 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_const_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_const_bytep)params[i], 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 */ -void /* PRIVATE */ -png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width, - png_const_charp height) -{ - 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_complete_chunk(png_ptr, png_sCAL, buf, total_len); -} -#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) -{ - 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_complete_chunk(png_ptr, 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_const_timep mod_time) -{ - 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_complete_chunk(png_ptr, 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 */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; -#endif - - png_alloc_size_t buf_size; - int usr_pixel_depth; - - png_debug(1, "in png_write_start_row"); - - usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; - buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; - - /* 1.5.6: added to allow checking in the row write code. */ - png_ptr->transformed_pixel_depth = png_ptr->pixel_depth; - png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; - - /* Set up row buffer */ - png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, 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_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, buf_size); - - if (png_ptr->do_filter & PNG_FILTER_UP) - { - 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 = (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 = (png_bytep)png_malloc(png_ptr, - 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_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT); - 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 */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte 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); - } - - png_zlib_release(png_ptr); - 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 */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte 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) */ - if (pass < 6) - { - /* 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. - */ -static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row, - png_size_t row_bytes); - -#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_size_t row_bytes = row_info->rowbytes; -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - int num_p_filters = 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_size_t 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_size_t 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_size_t 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_size_t 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_size_t 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_size_t 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_size_t 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_size_t 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, row_info->rowbytes+1); - -#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. */ -static void -png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row, - png_size_t avail/*includes filter byte*/) -{ - 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 = 0; - /* Repeat until we have compressed all the data */ - do - { - int ret; /* Return of zlib */ - - /* Record the number of bytes available - zlib supports at least 65535 - * bytes at one step, depending on the size of the zlib type 'uInt', the - * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h). - * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e. - * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a - * uInt. ZLIB_IO_MAX can be safely reduced to cause zlib to be called - * with smaller chunks of data. - */ - if (png_ptr->zstream.avail_in == 0) - { - if (avail > ZLIB_IO_MAX) - { - png_ptr->zstream.avail_in = ZLIB_IO_MAX; - avail -= ZLIB_IO_MAX; - } - - else - { - /* So this will fit in the available uInt space: */ - png_ptr->zstream.avail_in = (uInt)avail; - avail = 0; - } - } - - /* 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); - } - /* Repeat until all data has been compressed */ - } while (avail > 0 || png_ptr->zstream.avail_in > 0); - - /* 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/plugins/FreeImage/Source/LibTIFF/ChangeLog b/plugins/FreeImage/Source/LibTIFF/ChangeLog deleted file mode 100644 index f3dfe26b0b..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/ChangeLog +++ /dev/null @@ -1,4849 +0,0 @@ -2011-04-09 Bob Friesenhahn - - * libtiff 3.9.5 released. - -2011-04-09 Bob Friesenhahn - - * configure.ac: Should use AC_CANONICAL_HOST since host specifies - the run-time target whereas target is used to specify the final - output target if the package is a build tool (like a compiler), - which libtiff is not. Resolves libtiff bug 2307 "Use - AC_CANONICAL_HOST macro". - -2011-04-02 Bob Friesenhahn - - * tools/fax2ps.c (main): Use tmpfile() rather than mkstemp() since - it is much more portable. Tmpfile is included in ISO/IEC - 9899:1990 and the WIN32 CRT. - -2011-03-21 Frank Warmerdam - - * libtiff/tiffiop.h: avoid declaring int64/uint64 on AIX with XLC - where they are already available. (#2301) - - * libtiff/tif_thunder.c: Correct potential buffer overflow with - thunder encoded files with wrong bitspersample set. The libtiff - development team would like to thank Marin Barbella and TippingPoint's - Zero Day Initiative for reporting this vulnerability (ZDI-CAN-1004, - CVE-2011-1167). - http://bugzilla.maptools.org/show_bug.cgi?id=2300 - -2011-03-10 Frank Warmerdam - - * libtiff/tif_fax3.h: Fix to last change allowing zero length - runs at the start of a scanline - needed for legal cases. - -2011-03-02 Frank Warmerdam - - * libtiff/tif_fax3.h: Protect against a fax VL(n) codeword commanding - a move left. Without this, a malicious input file can generate an - indefinitely large series of runs without a0 ever reaching the right - margin, thus overrunning our buffer of run lengths. Per CVE-2011-0192. - This is a modified version of a patch proposed by Drew Yao of Apple - Product Security. It adds an unexpected() report, and disallows the - equality case, since emitting a run without increasing a0 still allows - buffer overrun. - -2011-02-25 Andrey Kiselev - - * libtiff/tif_dirwrite.c: Avoid undefined behaviour when casting from - float to unsigned integer in TIFFWriteRationalArray() as reported by - Kareem Shehata. - -2011-01-03 Lee Howard - - * libtiff/tif_jpeg.c: Fix regressions with 2 and 3 band images - caused by commit on 2010-12-14. Submitted by e-mail from - Even Rouault - -2010-12-31 Olivier Paquet - - * libtiff/tif_dirread.c: Allow reading directories where - TIFFTAG_SMINSAMPLEVALUE and TIFFTAG_SMAXSAMPLEVALUE values differ for each - channel. The min/max of all channels is used as appropriate. - -2010-12-14 Lee Howard - - * libtiff/tif_dirread.c: tolerate some cases where - FIELD_COLORMAP is missing - http://bugzilla.maptools.org/show_bug.cgi?id=2189 - -2010-12-14 Lee Howard - - * libtiff/tif_strip.c: use TIFFGetFieldDefaulted instead - of TIFFGetField when we assume that it will succeed - http://bugzilla.maptools.org/show_bug.cgi?id=2215 - -2010-12-14 Lee Howard - - * tools/gif2tiff.c: fix buffer overrun - http://bugzilla.maptools.org/show_bug.cgi?id=2270 - -2010-12-14 Lee Howard - - * libtiff/tif_jpeg.c: reduce usage of JCS_UNKNOWN in order - to improve compatibility with various viewers - submitted by e-mail from Dwight Kelly - -2010-12-13 Lee Howard - - * tools/fax2ps.c: be consistent with page-numbering - http://bugzilla.maptools.org/show_bug.cgi?id=2225 - -2010-12-13 Lee Howard - - * libtiff/tif_dirread.c: fix needless tag ordering warning - http://bugzilla.maptools.org/show_bug.cgi?id=2210 - -2010-12-13 Lee Howard - - * libtiff/tif_color.c: prevent crash in handling bad TIFFs - resolves CVE-2010-2595 - http://bugzilla.maptools.org/show_bug.cgi?id=2208 - -2010-12-13 Lee Howard - - * tools/tiffcrop.c: new release by Richard Nolde - http://bugzilla.maptools.org/show_bug.cgi?id=2004 - -2010-12-12 Lee Howard - - * tools/tiff2pdf.c: fix colors for images with RGBA - interleaved data - http://bugzilla.maptools.org/show_bug.cgi?id=2250 - -2010-12-11 Lee Howard - - * tools/tiff2pdf.c: remove invalid duplication for Lab - http://bugzilla.maptools.org/show_bug.cgi?id=2162 - -2010-12-11 Lee Howard - - * libtiff/tif_jpeg.c: fix use of clumplines calculation - http://bugzilla.maptools.org/show_bug.cgi?id=2149 - -2010-12-11 Lee Howard - - * tools/fax2ps.c: replace unsafe tmpfile() with mkstemp() - http://bugzilla.maptools.org/show_bug.cgi?id=2118 - -2010-12-11 Lee Howard - - * tools/tiff2pdf.c: add fill-page option - http://bugzilla.maptools.org/show_bug.cgi?id=2051 - -2010-12-11 Lee Howard - - * libtiff/tif_dirread.c: modify warnings - http://bugzilla.maptools.org/show_bug.cgi?id=2016 - -2010-12-11 Lee Howard - - * libtiff/tif_ojpeg.c: fix buffer overflow on problem data - http://bugzilla.maptools.org/show_bug.cgi?id=1999 - -2010-12-11 Lee Howard - - * libtiff/tif_ojpeg.c: fix crash when reading a TIFF with a zero - or missing byte-count tag - * tools/tiffsplit.c: abort when reading a TIFF without a byte-count - per http://bugzilla.maptools.org/show_bug.cgi?id=1996 - -2010-12-08 Lee Howard - - * libtiff/tif_dirread.c: fix crash when reading a badly-constructed - TIFF per http://bugzilla.maptools.org/show_bug.cgi?id=1994 - -2010-12-07 Lee Howard - - * libtiff/tif_jpeg.c, libtiff/tif_strip.c: apply patch for - CVE-2010-3087 per bug - http://bugzilla.maptools.org/show_bug.cgi?id=2140 - -2010-12-06 Lee Howard - - * libtiff/tif_open.c: Fix mode check before opening a file. - http://bugzilla.maptools.org/show_bug.cgi?id=1906 - -2010-09-25 Lee Howard - - * tools/tiff2ps.c: improvements and enhancements from Richard Nolde - with additional command line options for Document Title, - Document Creator, and Page Orientation - -2010-07-13 Bob Friesenhahn - - * tools/tiffcrop.c: Patch from Richard Nolde to avoid a - potentially unterminated buffer due to using an exceptionally long - file name. - -2010-07-08 Andrey Kiselev - - * tools/tiff2pdf.c: Fixed ID buffer filling in - t2p_write_pdf_trailer(), thanks to Dmitry V. Levin. - -2010-07-07 Andrey Kiselev - - * libtiff/tif_dirread.c: Really reset the tag count in CheckDirCount() - to expected value as the warning message suggests. As per bug - http://bugzilla.maptools.org/show_bug.cgi?id=1963 - - * tools/tiffdump.c: Avoid integer overflows computing the buffer size - for large directories. As per bug - http://bugzilla.maptools.org/show_bug.cgi?id=2218 - -2010-07-06 Andrey Kiselev - - * tools/tiffset.c: Properly handle TIFFTAG_PAGENUMBER, - TIFFTAG_HALFTONEHINTS, TIFFTAG_YCBCRSUBSAMPLING, TIFFTAG_DOTRANGE - which should be set by value. - - * libtiff/tif_dirinfo.c: Don't use assertions in _TIFFFieldWithTag() - and _TIFFFieldWithName() if the tag is not found in the tag table. - This should be normal situation and returned NULL value should be - properly handled by the caller. - - * libtiff/{tif_dirwrite.c, tif_print.c}: Properly handle "DotRange" - tag as it can be either byte or short size and should be set and read - by value, not as an array. As per bug - http://bugzilla.maptools.org/show_bug.cgi?id=2116 - -2010-07-02 Andrey Kiselev - - * libtiff/tif_getimage.c: Avoid wrong math du to the signed/unsigned - integer type conversions. As per bug - http://bugzilla.maptools.org/show_bug.cgi?id=2207 - - * tools/{tiff2bw.c, thumbnail.c, pal2rgb.c}: Fix the count for - WhitePoint tag as per bug - http://bugzilla.maptools.org/show_bug.cgi?id=2042 - - * tools/tiffdump.c: Use PrintData() function instead of - PrintByte/Short/Long(). Should fix an issue reported at - http://bugzilla.maptools.org/show_bug.cgi?id=2116 - - * libtiff/tif_getimage.c: Check the number of samples per pixel when - working with YCbCr image in PickContigCase(). As per bug - http://bugzilla.maptools.org/show_bug.cgi?id=2216 - - * libtiff/tif_dir.c: Set the bogus post-decoding hook when processing - TIFFTAG_BITSPERSAMPLE in _TIFFVSetField() for the case of 8 bit when - we don't need any post-processing. That helps to reset the hook if we - previously set this field to some other value and the hook was - initialized accordingly. As per bug - http://bugzilla.maptools.org/show_bug.cgi?id=2035 - -2010-06-30 Andrey Kiselev - - * tools/tiff2pdf.c: Better generation of ID field in - t2p_write_pdf_trailer(). Get rid of GCC aliasing warnings. - - * tools/tiff2pdf.c: Fixed computation of the tile buffer size when - converting JPEG encoded tiles. - - * tools/tiff2pdf.c: Better handling of string fields, use static - string buffers instead of dynamically allocated, use strncpy() instead - of strcpy(), control the string lengths. - -2010-06-25 Andrey Kiselev - - * tools/tiffcp.c: Initialize buffer arrays with zero to avoid - referencing to uninitialized memory in some cases (e.g. when tile size - set bigger than the image size). - -2010-06-15 Bob Friesenhahn - - * tools/tiffcrop.c: Patch from Richard Nolde. Reject YCbCr - subsampled data since tiffcrop currently doesn't support it. Fix - JPEG support. - -2010-06-15 Bob Friesenhahn - - * libtiff 3.9.4 released. - -2010-06-13 Frank Warmerdam - - * libtiff/tif_jpeg.c: avoid re-preparing jpeg tables unnecessarily - (gdal #3633, libtiff #2135). - - * libtiff/tif_dirread.c: Fixed bad handling of out of order tags - definated late by a codec (#2210) - - * libtiff/tif_dirread.c: Fixed inadequate validation of the - SubjectDistance field (#2212). - - * tiff2pdf.c: Fix assorted bugs in tiff2pdf: missing "return" - in t2p_read_tiff_size() causes t2p->tiff_datasize to be set entirely - wrong for COMPRESSION_JPEG case, resulting in memory stomp if actual - size is larger. Also, there are a bunch of places that try to - memset() a malloc'd buffer before checking for malloc failure, which - would result in core dump if there actually were a failure. (#2211) - -2010-06-11 Bob Friesenhahn - - * tools/tiff2rgba.c: Applied portion of patch (from Tom Lane) - which was left out in order to fully resolve "CVE-2009-2347 - libtiff: integer overflows in various inter-color space conversion - tools". http://bugzilla.maptools.org/show_bug.cgi?id=2079 - - * libtiff/tiffiop.h (TIFFSafeMultiply): Need more castings to - avoid compiler warnings if parameter types are not sign - consistent. - - * tools/tiffcrop.c: Applied patch from Richard Nolde: Corrected - European page size dimensions. Added an option to allow the user - to specify a custom page size on the command line. Fix the case - where a page size specified with a fractional part was being - coerced to an integer by retyping the variables that define the - paper size. - - * libtiff 3.9.3 released. - - * tools/tiffcp.c (tiffcp): Applied Tom Lane's patch to reject - YCbCr subsampled data since tiffcp currently doesn't support it. - http://bugzilla.maptools.org/show_bug.cgi?id=2097 - - * Update libtool to version 2.2.10. - -2010-06-10 Bob Friesenhahn - - * libtiff/tiffiop.h (TIFFSafeMultiply): Work properly if - multiplier is zero. - -2010-06-09 Bob Friesenhahn - - * libtiff/tif_dir.h: Restore ReferenceBlackWhite as a non-custom - field. This avoids a multi-thread reentrancy problem as well as - fixing output of wrong tag value due to redundant definitions for - the same tag in the tiffFieldInfo[] array. Resolves - http://bugzilla.maptools.org/show_bug.cgi?id=2185 - - * libtiff/tif_fax3.c (Fax3SetupState): Yesterday's fix for - CVE-2010-1411 was not complete. - - * libtiff/tiffiop.h (TIFFSafeMultiply): New macro to safely - multiply two integers. Returns zero if there is an integer - overflow. - - * tools/tiffcp.c (main): Fix more TIFF handle leaks. - - * libtiff/tif_read.c (TIFFReadBufferSetup): Skip allocating - tif_rawdata if tif_rawdatasize becomes zero. - -2010-06-08 Bob Friesenhahn - - * tools/tiffcrop.c: Removed duplicated macros such as - TIFFhowmany(). - - * Update libtool to version 2.2.8. - - * libtiff/tif_fax3.c (Fax3SetupState): Avoid under-allocation of - buffer due to integer overflow in TIFFroundup() and several other - potential overflows. In conjunction with the fix to TIFFhowmany(), - fixes CVE-2010-1411. - - * libtiff/tiffiop.h (TIFFhowmany): Return zero if parameters would - result in an integer overflow. This causes TIFFroundup() to also - return zero if there would be an integer overflow. - - * libtiff/tif_read.c (TIFFReadBufferSetup): Return an error if - tif_rawdatasize becomes zero due to an initial raw size of zero or - an overflow reported by TIFFroundup(). - - * libtiff/tif_ojpeg.c (OJPEGReadBufferFill): Report an error and - avoid a crash if the input file is so broken that the strip - offsets are not defined. - - * tools/tiffcp.c (main): tiffcp should not leak memory if an error - is reported when reading the input file. - - * libtiff/tif_aux.c (_TIFFCheckRealloc): Produce a fully detailed - error message string. - - * Add an emacs formatting mode footer to all source files so that - emacs can be effectively used. - -2010-06-03 Oliver Chen Feng - - * libtiff/tools/tiffcp.c: add a new option -x to force merged tiff - file PAGENUMBER value in sequence for users who care the page - sequence, this will also prevent tiff2pdf from creating pdf file from - the merged tiff file with wrong page sequence. - -2010-05-07 Frank Warmerdam - - * libtiff/tif_jpeg.c: Ensure that quality is always set in - JPEGPreEncode(), not just when we want to output local tables. - Otherwise the quality used during compression may not be right and - might not match the tables in the tables tag. This bug only occurs - when seeking between directories in the midst of writing blocks. - http://trac.osgeo.org/gdal/ticket/3539 - -2010-05-05 Olivier Paquet - - * libtiff/tif_print.c: Have TIFFTAG_REFERENCEBLACKWHITE always print 6 - floats instead of 2*SamplesPerPixel. - http://bugzilla.maptools.org/show_bug.cgi?id=2186 - * man/TIFFGetField.3tiff, man/TIFFSetField.3tiff: Fixed doc to reflect the - fact that libtiff considers TIFFTAG_REFERENCEBLACKWHITE to be 6 floats. - -2010-04-10 Bob Friesenhahn - - * tools/ppm2tiff.c (main): While case for parsing comment line - requires extra parenthesis to work as expected. Reported by - Thomas Sinclair. - -2010-02-22 Lee Howard - - * libtiff/tif_jpeg.c: Do not generate a JPEGTables tag when creating - the JPEG TIFF as is is not required in order to prevent it from - being unused and filled with invalid data. (Leave it to be - generated by later activity.) - http://bugzilla.maptools.org/show_bug.cgi?id=2135 - * tools/tiff2pdf.c: Write the JPEG SOI headers into the TIFF strip - data rather than skipping them. This fixes the ability to view in - Acrobat Reader, Evince, and Ghostscript. - http://bugzilla.maptools.org/show_bug.cgi?id=2135 - * libtiff/tif_fax3.c: Don't return error on badly-terminated MMR - strips. - http://bugzilla.maptools.org/show_bug.cgi?id=2029 - -2010-01-06 Frank Warmerdam - - * libtiff/tif_dir.c: Ensure tile and scanline sizes are reset - when moving to new directories. - http://bugzilla.maptools.org/show_bug.cgi?id=1936 - -2009-12-03 Frank Warmerdam - - * libtiff/tif_jpeg.c: Fix a couple of issues that trigger failures in - some cases when using TIFFReadScanline() with JPEG compressed - subsampled ycbcr images. - http://bugzilla.maptools.org/show_bug.cgi?id=1936 - -2009-11-04 Bob Friesenhahn - - * libtiff 3.9.2 released. - -2009-11-03 Bob Friesenhahn - - * tools/tiffcrop.c: Updated tiffcrop from Richard Nolde. This - version has undergone substantial testing with arbitrary sample - bit depths. Also eliminates GCC compilation warnings. - -2009-11-02 Bob Friesenhahn - - * port/libport.h: Added header file for porting prototypes and - extern declarations. - -2009-10-31 Bob Friesenhahn - - * libtiff/tif_dirwrite.c (TIFFWriteAnyArray): Add missing break - statement so writing an array of TIFF_DOUBLE works. - -2009-10-29 Bob Friesenhahn - - * libtiff/tif_dirread.c: Eliminate GCC "dereferencing type-punned - pointer" warnings. - -2009-10-28 Bob Friesenhahn - - * html/tools.html: Add manual page links, and a summary - description of tiffcrop. - -2009-10-07 Bob Friesenhahn - - * configure.ac: x86_64 should use the same fill order as i386. - -2009-09-24 Bob Friesenhahn - - * tools/tiffcrop.c, man/tiffcrop.1: New tiffcrop from Richard - Nolde. Major updates to add significant functionality for reading - and writing tile based images with bit depths not a multiple of 8 - which cannot be handled by tiffcp. - -2009-09-03 Bob Friesenhahn - - * libtiff/tif_ojpeg.c (OJPEGWriteHeaderInfo): IJG JPEG 7 needs - do_fancy_upsampling=FALSE in order to read raw data. Resolves - "Bug 2090 - OJPEG crash with libjpeg v7". - http://bugzilla.maptools.org/show_bug.cgi?id=2090 - -2009-08-30 Bob Friesenhahn - - * contrib/iptcutil/iptcutil.c, - libtiff/tif_getimage.c,libtiff/tif_jpeg.c,libtiff/tif_ojpeg.c,tools/tiffcrop.c,tools/tiffgt.c: - Applied patch from Oden Eriksson to allow building with GCC using - the "-Wformat -Werror=format-security" flags. - -2009-08-28 Bob Friesenhahn - - * libtiff 3.9.1 released. - -2009-08-28 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff/tif_lzw.c: Fix buffer underflow bug. - http://bugzilla.maptools.org/show_bug.cgi?id=2065 - -2009-06-03 Frank Warmerdam - - * 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 - - * libtiff/tif_luv.c: Fix handling of tiled logluv images. - http://bugzilla.maptools.org/show_bug.cgi?id=2005 - -2009-01-23 Frank Warmerdam - - * 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 - - * tools/tiffsplit.c: fix sampleformat to be shortv instead of longv. - -2009-01-12 Bob Friesenhahn - - * tools/tiff2ps.c: Remove spurious message printed to stderr. - -2009-01-11 Bob Friesenhahn - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/tiffcrop.c, man/tiffcrop.1: A major update from Richard - Nolde. - -2008-12-21 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * libtiff/tif_jbig.c: Support the JBIG-KIT 2.0 (compatibility with - the older versions retained). - -2008-09-05 Andrey Kiselev - - * tools/tiffsplit.c: Use dynamically allocated array instead of static - when constructing output file names. - -2008-09-03 Andrey Kiselev - - * 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 - - * 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 - - * tif_fax3.c: Make find0span() and find1span() non-inline to - make MSVC 6.0 compiler happy. - -2007-11-26 Frank Warmerdam - - * tif_fax3.c: fix leak of FAXCS state (per bug 1603). - -2007-11-23 Andrey Kiselev - - * configure.com, libtiff/tif_vms.c: Better OpenVMS support. Patches - from Alexey Chupahin. - -2007-11-22 Frank Warmerdam - - * 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 - - * tools/tiff2pdf.c: Fixed setting of alpha value per report on list. - -2007-09-13 Frank Warmerdam - - * 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 - - * 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 - - * libtiff 3.9.0beta released. - -2007-07-12 Andrey Kiselev - - * tools/tiff2pdf.c: Added missed extern optind as per bug - - http://bugzilla.remotesensing.org/show_bug.cgi?id=1567 - -2007-07-03 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * contrib/addtiffo/tif_overview.c: Fix problems with odd sized output - blocks in TIFF_DownSample_Subsampled() (bug 1542). - -2007-04-06 Frank Warmerdam - - * 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 - - * 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 - - * libtiff/tif_fax3.c: "inline static" -> "static inline" for IRIC CC. - -2007-03-07 Joris Van Damme - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tif_msdos.c: Avoid handle leak for failed opens. c/o Thierry Pierron - -2006-07-19 Frank Warmerdam - - * 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 - - * 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 - - * {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 - - * 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 - - * tools/tiff2pdf.c: Fix handling of -q values. - http://bugzilla.remotesensing.org/show_bug.cgi?id=587 - -2006-06-17 Frank Warmerdam - - * 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 - - * 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 - - * {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 - - * libtiff/{tif_dirinfo.c, tif_print.c} : Fix crash in - TIFFPrintDirectory(). Joris Van Damme authored the fix. - -2006-04-21 Andrey Kiselev - - * 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 - - * 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 - - * nmake.opt: use /EHsc for VS2005 compatibility. Also define - _CRT_SECURE_NO_DEPRECATE to avoid noise on VS2005. - -2006-04-12 Joris Van Damme - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * contrib/addtiffo/tif_ovrcache.c: bugfix to correctly pass size - of last truncated strip data to TIFFWriteEncodedStrip - -2006-03-25 Joris Van Damme - - * libtiff/{tif_jpeg.c, tif_strip.c}: bugfix of tif_jpeg decode raw - -2006-03-25 Joris Van Damme - - * 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 - - * libtiff 3.8.2 released. - - * tools/Makefile.am: Use runtime paths linker flags when rpath - option enabled. - -2006-03-21 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff 3.8.1 released. - -2006-03-07 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/tiff2pdf.c: Fixed support for non-YCbCr encoded JPEG - compressed TIFF files, per submission from Dan Cobra. - -2006-02-07 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * libtool related stuff updated from the 2.1a branch. - -2006-01-11 Frank Warmerdam - - * 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 - - * configure.ac: Fix with_default_strip_size comparison as reported - by Norihiko Murase. - -2006-01-08 Bob Friesenhahn - - * 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 - - * 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 - - * 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 - - * libtiff 3.8.0 released. - -2005-12-28 Bob Friesenhahn - - * 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 - - * html/{index.html, support.hml, libtiff.html}: Cleaned up HTML - -2005-12-27 Andrey Kiselev - - * libtiff/tiffio.h: Added VC_EXTRALEAN definition before including - windows.h, to reduce the compile time. - -2005-12-26 Bob Friesenhahn - - * libtiff/tif_jpeg.c: Improve compilation under MinGW. - -2005-12-26 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff/{tif_dir.c, tif_dir.h, tif_print.c}: Make RichTIFFIPTC, - Photoshop and ICCProfile tags custom. - -2005-12-21 Joris Van Damme - - * 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 - - * 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 - - * contrib/addtiffo/*: Major upgrade by Joris to support subsampled - YCbCr images in jpeg compressed TIFF files. - -2005-12-14 Andrey Kiselev - - * tools/tiffcp.c: Return non-zero status when reading fails (again). - -2005-12-13 Andrey Kiselev - - * tools/tiffcp.c: Return non-zero status when reading fails. - -2005-12-12 Andrey Kiselev - - * libtiff/{tif_dir.h, tiff.h}: Added more EXIF tags. - -2005-12-09 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff/libtiff.def, tiffiop.h, tiffio.h: Made TIFFFreeDirectory - public. - -2005-10-31 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * tif_write.c: fixed setting of planarconfig as per bug report - on the mailing list from Joris. - -2005-10-07 Andrey Kiselev - - * 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 - - * html/support.html: Fixed link to documentation on Greg Ward's - LogLuv TIFF format. - -2005-09-28 Andrey Kiselev - - * tools/tiffdump.c: Fixed crash when reading malformed tags. - -2005-09-20 Andrey Kiselev - - * tools/tiff2pdf.c: Added missed 'break' statement as per bug - http://bugzilla.remotesensing.org/show_bug.cgi?id=932 - -2005-09-12 Andrey Kiselev - - * 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 - - * libtiff/tif_open.c: reintroduce seek to avoid problem on solaris. - -2005-09-05 Frank Warmerdam - - * 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 - - * libtiff/tif_print.c: avoid signed/unsigned warning. - - * libtiff/tif_dirread.c: removed unused variable. - -2005-07-30 Frank Warmerdam - - * 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 - - * 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 - - * libtiff/tif_dir.c: More improvements in the "pass by value" part of - the custom tags handling code. - -2005-07-26 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff 3.7.3 released. - - * configure, configure.ac: Do not use empty -R option when linking - with --enable-rpath. - -2005-07-01 Andrey Kiselev - - * 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 - - * 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 - - * libtiff/tif_dirinfo.c: Added support for ClipPath, XClipPathUnits - and YClipPathUnits tags. - -2005-06-07 Andrey Kiselev - - * contrib/addtiffo/tif_ovrcache.c: Properly extract tile/strip size; - use pixel sized shift in contigous case. - -2005-06-06 Andrey Kiselev - - * contrib/addtiffo/{tif_overview.c, tif_ovrcache.c, tif_ovrcache.h}: - Make overviews working for contiguos images. - -2005-06-03 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/tiffsplit.c: Check for JPEGTables tag presence before copying. - -2005-05-06 Frank Warmerdam - - * 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 - * 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 - - * 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 - - * tools/tiffdither.c: Copy the PhotometricInterpretation tag from the - input file. - -2005-04-15 Andrey Kiselev - - * libtiff/tif_predict.c: Added ability to encode floating point - predictor, as per TIFF Technical Note 3. - -2005-04-14 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * configure.ac, libtiff/Makefile.am: Use libtool machinery to pass - rpath option. - -2005-03-21 Andrey Kiselev - - * libtiff/{tif_dir.c, tif_print.c}: Handle all data types in custom - tags. - -2005-03-18 Andrey Kiselev - - * 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 - - * 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 - - * libtiff 3.7.2 released. - -2005-03-09 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff/tiff.h (TIFFTAG_TILEWIDTH): Corrected description. - (TIFFTAG_TILELENGTH): Corrected description. - -2005-01-30 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff/tif_getimage.c: #define A1 bracketing for clean build on - SunPro compiler. - -2004-12-11 Bob Friesenhahn - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff/tif_unix.c: Make UNIX module compilable (and usable) - on Windows. - - * nmake.opt: Add missed DLLNAME variable. - -2004-11-26 Frank Warmerdam - - * libtiff/makefile.vc: make it easier to rename the libtiff DLL. - -2004-11-24 Andrey Kiselev - - * 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 - - * libtiff/tif_error.c: fixed TIFFerror call to be TIFFError. - -2004-11-21 Frank Warmerdam - - * html/document.html: Updated Adobe web links as per email from Joris. - -2004-11-21 Andrey Kiselev - - * 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 . - -2004-11-13 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * libtiff/tif_color.c: Division by zero fixed (Hans Petter Selasky). - -2004-11-07 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff/tif_next.c: avoid use of u_long and u_char types. Bug 653. - -2004-11-02 Frank Warmerdam - - * tools/tiff2rgba.c: removed extra newlines in usage message. - -2004-10-30 Andrey Kiselev - - * 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 - - * libtiff/tiffiop.h: added fallback definition of assert() if we - don't have assert.h. - -2004-10-29 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * configure, configure.ac: Added --enable-rpath option to embed linker - paths into library binary. - -2004-10-26 Andrey Kiselev - - * 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 - - * libtiff 3.7.0 released. - -2004-10-15 Bob Friesenhahn - - * 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 - - * man/bmp2tiff.1: Added manual page for bmp2tiff utility. - -2004-10-13 Bob Friesenhahn - - * 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 - - * 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 - - * 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 - - * libtiff/tif_dirinfo.c: Type of the TIFFTAG_SUBIFD field changed - to TIFF_IFD. - -2004-10-10 Andrey Kiselev - - * tools/bmp2tif.c: Check the space allocation results. - -2004-10-09 Andrey Kiselev - - * 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 - - * 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 - - * contrib/iptcutil/README: Added the missing README which goes - along with iptcutil. - -2004-10-03 Andrey Kiselev - - * libtiff/tif_compress.c: Improved error reporting in - TIFFGetConfiguredCODECs() (Dmitry V. Levin). - -2004-10-02 Andrey Kiselev - - * 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 - - * libtiff/tif_open.c: added a more informative message if a BigTIFF - file is opened. - -2004-09-30 Frank Warmerdam - - * 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 - - * 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 - - * libtiff/tif_getimage.c: Check for allocated buffers before clearing - (Dmitry V. Levin). - -2004-09-26 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * libtiff/tif_dirread.c: Applied patch from Dmitry V. Levin to fix - possible integer overflow in CheckMalloc() function. - -2004-09-22 Andrey Kiselev - - * libtiff/{tiffiop.h, tif_strip.c}: Use TIFFhowmany8() macro instead - of plain TIFFhowmany() where appropriate. - -2004-09-21 Andrey Kiselev - - * libtiff/tif_getimage.c: Initialize arrays after space allocation. - -2004-09-19 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * configure.ac, acinclude.m4, aclocal.m4: New macros to detect GLUT - libraries. - -2004-09-11 Bob Friesenhahn - - * 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 - - * html/internals.html: Split off a discussion of adding new tags - into addingtags.html. - -2004-09-10 Andrey Kiselev - - * 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 - - * 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 - - * libtiff/tif_dirread.c: Use memcpy() function instead of pointer - assigning magic in TIFFFetchFloat(). - -2004-09-01 Andrey Kiselev - - * 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 - - * 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 - - * tools/tiff2pdf.c: More fixes for bug - - http://bugzilla.remotesensing.org/show_bug.cgi?id=590 - - from Ross Finlayson. - -2004-08-23 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff/tiffio.h: Revert thandle_t back to void* type. - -2004-07-11 Andrey Kiselev - - * libtiff/{tif_read.c, tif_tile.c, tif_strip.c}: Fixes in error - messages, as suggested by Bernd Herd. - -2004-07-03 Andrey Kiselev - - * 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 - - * tools/bmp2tiff.c: Add missed RawsPerStrip setting. - -2004-06-08 Andrey Kiselev - - * tools/bmp2tiff.c: Added new utility to convert Windows BMP files - into TIFFs. - -2004-06-07 Andrey Kiselev - - * libtiff 3.7.0alpha released. - -2004-06-06 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * tools/tiffsplit.c: Don't forget to copy Photometric - Interpretation tag. - -2004-05-20 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * libtiff/tif_strip.c: Never return 0 from the - TIFFNumberOfStrips(). - -2004-04-29 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * libtiff/tif_open.c: close clientdata if TIFFClientOpen() fails - via bad2. - -2004-03-26 Andrey Kiselev - - * 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 - - * {many}: The first attempt to switch to autotools. - -2004-03-03 Andrey Kiselev - - * 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 - - * tools/ycbcr.c: fixed main() declaration as per: - http://bugzilla.remotesensing.org/show_bug.cgi?id=513 - -2004-02-26 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * libtiff/libtiff.def: Added TIFFCurrentDirOffset, TIFFWriteCheck, - TIFFRGBAImageOK, and TIFFNumberOfDirectories as suggested by - Scott Reynolds. - -2004-01-29 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/tiffcp.c: Fixed problem with wrong Photometric setting for - non-RGB images. - -2003-12-31 Andrey Kiselev - - * 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 - - * libtiff 3.6.1 released. - -2003-12-24 Andrey Kiselev - - * config.guess, config.sub: Updated from the recent upstream. - -2003-12-22 Andrey Kiselev - - * 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 - - * 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 - - * libtiff/{tif_getimage.c, tiffio.h}: Avoid warnings. - - * libtiff/makefile.vc, tools/makefile.vc: Support for IJG JPEG - library. - -2003-12-06 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/tiff2pdf.c: Some bugs fixed. - -2003-11-27 Andrey Kiselev - - * 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 - - * /man/tiff2pdf.1: File added to repository. - -2003-11-26 Andrey Kiselev - - * Makefile.in, /tools/{Makefile.in, makefile.vc}: - Added support fpr tiff2pdf utility. - -2003-11-25 Ross Finlayson - - * /tools/tiff2pdf.c: File added to repository. - -2003-11-22 Andrey Kiselev - - * /tools/raw2tiff.c: sqrtf() replaced with sqrt(). - -2003-11-21 Andrey Kiselev - - * /tools/raw2tiff.c: #include 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 - - * 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 - - * tif_dirread.c: do not mark all anonymously defined tags to be - IGNOREd. - -2003-11-17 Andrey Kiselev - - * contrib/pds/{tif_pdsdirread.c, tif_pdsdirwrite.c}: Use - TIFFDataWidth() function insted of tiffDataWidth array. - -2003-11-16 Andrey Kiselev - - * libtiff/{tiff.h, tif_dirinfo.c}: Added support for IFD (13) - datatype, intruduced in "Adobe PageMaker TIFF Tech. Notes". - -2003-11-15 Frank Warmerdam - - * Makefile.in: fixed missing backslash for tif_color.c in list. - -2003-11-13 Andrey Kiselev - - * 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 - - * 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 - - * tools/raw2tiff.c: Implemented image size guessing using - correlation coefficient calculation between two neighbour lines. - -2003-11-09 Frank Warmerdam - - * 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 - - * libtiff/tiffiop.h: New macros: TIFFmax, TIFFmin and TIFFrint. - -2003-11-07 Andrey Kiselev - - * libtiff/{tiffio.h, tif_strip.c}, man/{TIFFstrip.3t, libtiff.3t}: - Added TIFFRawStripSize() function as suggested by Chris Hanson. - -2003-11-03 Andrey Kiselev - - * 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 - - * libtiff/libtiff.def: Added TIFFReadRGBAImageOriented. - - * html/build.html: Added note about GNU make requirement. - -2003-10-25 Andrey Kiselev - - * 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 - - * /tools/tiff2ps.c: #include replaced with the - #include . - -2003-10-16 Andrey Kiselev - - * Makefile.in: Add an absolute path to the test_pics.sh call. - -2003-10-12 Andrey Kiselev - - * libtiff/tiffcomp.h: #define _BSDTYPES_DEFINED when defining BSD - typedefs. - -2003-10-09 Andrey Kiselev - - * 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 - - * Makefile.in: Added missed v3.6.0.html. - - * libtiff/tiffio.h: Typo fixed: ORIENTATION_BOTTOMLEFT replaced with - ORIENTATION_BOTLEFT. - -2003-10-04 Andrey Kiselev - - * 3.6.0 final release. - -2003-10-03 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * libtiff/tif_dirread.c: More fixes for EstimateStripByteCounts(). See - - http://bugzilla.remotesensing.org/show_bug.cgi?id=358 - -2003-08-21 Andrey Kiselev - - * 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 - - * libtiff/Makefile.in: Fixed problem with building in different - directory. - - * tools/tiff2ps.c: Added missing #include . - - * libtiff/tif_dirwrite.c: More fixes for custom tags code - from Ashley Dreier. - -2003-08-07 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/thumbnail.c: Memory leak fixed as reported by Robert S. Kissel. - -2003-06-30 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/fax2tiff.c: Page numbering fixed, as per bug - - http://bugzilla.remotesensing.org/show_bug.cgi?id=341 - -2003-05-20 Andrey Kiselev - - * 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 - - * libtiff/mkversion.c: Fixed problem with wrong string size when - reading RELEASE-DATE file. - -2003-05-07 Andrey Kiselev - - * tools/tiff2ps.c: Fixed bug in Ascii85EncodeBlock() function: array - index was out of range. - -2003-05-06 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * port/install.sh.in: Fixed problems with install producing paths - like ///usr/local/lib on cygwin. - -2003-02-27 Andrey Kiselev - - * 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 - - * 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 - - * tools/ppm2tiff.c: Fixed problem with too many arguments. - -2003-02-04 Andrey Kiselev - - * tools/raw2tiff.c: Memory leak fixed. - -2003-02-03 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * config.guess, config.sub: Updated to recent upstream versions. - -2003-01-15 Frank Warmerdam - - * cut 3.6.0 Beta release. - -2002-12-20 Andrey Kiselev - - * 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 - - * libtiff/tif_dirread.c: Allow wrong sized arrays in - TIFFFetchStripThing(). - - http://bugzilla.remotesensing.org/show_bug.cgi?id=49 - -2002-12-02 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - * 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 - - * 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 - - * libtiff/tiff.h: added COMPRESSION_JP2000. - -2002-10-02 Andrey Kiselev - - * 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 - - * configure, libtiff/Makefile.in: Added SCO OpenServer 5.0.6 support - from John H. DuBois III. - -2002-09-15 Andrey Kiselev - - * Makefile.in, /man/{raw2tiff.1, Makefile.in, libtiff.3}: Added - manual page for raw2tiff(1) tool. - -2002-09-12 Andrey Kiselev - - * /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 - - * 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 - - * /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 - - * /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 - - * /libtiff/{Makefile.vc, libtiff.def}: - Missed declarations added. - -2002-08-15 Frank Warmerdam - - * 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 - - * /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 - - * 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 - - * /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 - - * 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 . - -2002-06-11 Frank Warmerdam - - * 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 - - * 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 - - * libtiff/libtiff.def: Added missed declaration. - -2002-04-22 Andrey Kiselev - - * 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 - - * libtiff/tif_open.c: Pointers to custom procedures - in TIFFClientOpen() are checked to be not NULL-pointers. - -2002-04-18 Andrey Kiselev - - * libtiff/libtiff.def: Added missed declarations. - - * libtiff/tif_pixarlog.c: Updated for using tif_tagmethods structure. - -2002-04-16 Andrey Kiselev - - * 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 - - * tools/tiff2ps: Division by zero fixed. - Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=88 - -2002-04-09 Andrey Kiselev - - * 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 - - * 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 - - * 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 - - * 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 - - * tools/: tifcp.c: Added support for 'Orientation' tag in tiffcp - utility (at cpStripToTile routine). - -2002-03-27 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * man/TIFFGetField: fixed type of TIFFTAG_COPYRIGHT. - - * man/libtiff.3t: added copyright tag info. - -2002-02-11 Frank Warmerdam - - * 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 - - * config.site/configure: added support for OJPEG=yes option to enable - OJPEG support from config.site. - -2002-01-27 Frank Warmerdam - - * html/document.html: fixed links for TIFf 6 docs. - -2002-01-18 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * html/Makefile.in: added missing images per bug 92. - - * port/Makefile.in: fixed clean target per bug 92. - -2001-11-28 Frank Warmerdam - - * 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 - - * added html/v3.5.7.html, updated html/index.html. - - * Makefile.in: added contrib/addtiffo/tif_ovrcache.{c,h}. - -2001-11-15 Frank Warmerdam - - * configure: fixed test for -lm. - -2001-11-02 Frank Warmerdam - - * Added PHOTOMETRIC_ITULAB as per bug 90. - - http://bugzilla.remotesensing.org/show_bug.cgi?id=90 - -2001-10-10 Frank Warmerdam - - * 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 - - * libtiff/tif_dirwrite.c: added TIFFRewriteDirectory() function. - Updated TIFFWriteDirectory man page to include TIFFRewriteDirectory. - -2001-09-24 Frank Warmerdam - - * 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 - - * libtiff/tif_ojpeg.c: new update from Scott. - -2001-09-09 Frank Warmerdam - - * 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 - - * libtiff/tif_packbits.c: fixed memory overrun error. - - http://bugzilla.remotesensing.org/show_bug.cgi?id=77 - -2001-08-31 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * 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 - - * man/Makefile.in: add TIFFClientOpen link as per debian submitted - bug 66. - -2001-07-20 Frank Warmerdam - - * libtiff/tif_jpeg.c: Define HAVE_BOOLEAN on windows if RPCNDR.H - has been included. - -2001-07-19 Frank Warmerdam - - * libtiff/tif_open.c: Seek back to zero after failed read, - before writing header. - -2001-07-18 Frank Warmerdam - - * 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 - - * */Makefile.in: added DESTDIR support. - - http://bugzilla.remotesensing.org/show_bug.cgi?id=60 - -2001-07-16 Frank Warmerdam - - * configure, libtiff/Makefile.in: applied OpenBSD patches - as per: - - http://bugzilla.remotesensing.org/show_bug.cgi?id=61 - -2001-06-28 Frank Warmerdam - - * 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 - - * configure: Changes for DSO generation on AIX provided by - John Marquart . - - * 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 - - * tools/tiff2rgba.c: added -n flag to avoid emitting alpha component. - - * man/tiff2rgba.1: new - -2001-05-22 Frank Warmerdam - - * Added tiffset and tif_ojpeg to the dist lists in Makefile.in. - -2001-05-13 Frank Warmerdam - - * libtiff/tools/thumbnail.c: changed default output compression - to packbits from LZW since LZW isn't generally available. - -2001-05-12 Frank Warmerdam - - * libtiff/tif_ojpeg.c: New. - libtiff/tif_jpeg.c, tiffconf.h, tif_getimage.c: changes related - to OJPEG support. - - Scott Marovich supplied OJPEG support. - -2001-05-11 Frank Warmerdam - - * tiff.h: removed, it duplicates libtiff/tiff.h. - -2001-05-08 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * configure, Makefile.in, etc: added support for OPTIMIZER being - set from config.site. - -2001-03-28 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * tif_getimage.c: Added support for 16bit minisblack/miniswhite - images in RGBA interface. - -2001-03-02 Frank Warmerdam - - * Added TIFFTAG_COPYRIGHT support. - -2001-02-19 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * Makefile.in: Now cleaning up after itself after creating the .tar.gz and .zip - -2001-01-07 Frank Warmerdam - - * html/libtiff.html: Fixed arguments in example for TIFFRGBAImageGet() - as per bug report by Patrick Connor. - -2000-12-28 Frank Warmerdam - - * Added RELEASE-DATE file to release file list. - - * Fixed libtiff/makefile.vc to make tiffvers.h not version.h. - -2000-12-22 Mike Welles - * 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 - - * 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 - - * libtiff/tif_apple.c: Applied "Carbon" support patches supplied by - Leonard Rosenthol . May interfere - with correct building on older systems. If so, please let me know. - -2000-12-19 Mike Welles - - * 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 - - * Added patches for EOFB support in tif_fax3.c and tif_fax3.h. - Patches supplied by Frank Cringle - Example file at: ftp://ftp.remotesensing.org/pub/libtiff/eofb_396.tif - -2000-11-24 Frank Warmerdam - - * 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 - - * I have applied a patch from Steffen Moeller to - the configure script so that it now accepts the --prefix, and - --exec-prefix directives. - -2000-11-13 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - -2000-09-30 Frank Warmerdam - - * 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 - - * Added GNULDdso target an`d switched linux and freebsd to use it. - -2000-09-26 Frank Warmerdam - - * Applied patch for 0x0000 sequences in tif_fax3.h's definition - of EXPAND1D() as per bug 11 (from Roman). - -2000-09-25 Frank Warmerdam - * 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 for reporting the - bug and proving the patch. - -2000-09-18 Frank Warmerdam - - * Fixed tif_jpeg.c so avoid destroying the decompressor before - we are done access data thanks to bug report from: - Michael Eckstein . - - * Reverted tif_flush change. - -2000-09-14 Frank Warmerdam - - * 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 - - * 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 - - * Tentatively added support for SAMPLEFORMAT_COMPLEXIEEEFP, and - SAMPLEFORMAT_COMPLEXINT. - -2000-07-13 Mike Welles - - * index.html, bugs.html: added bugzilla info. - -2000-07-12 Frank Warmerdam - - * 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 - -2000-06-15 Frank Warmerdam - - * Modified tiffio.h logic with regard to including windows.h. It - won't include it when building with __CYGWIN__. - -2000-05-11 Frank Warmerdam - - * 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 . - -2000-04-21 Frank Warmerdam - - * 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 - - * contrib/addtiffo: Added "averaging" resampling option. - - * tools/tiffsplit.c: Copy TIFFTAG_SAMPLEFORMAT. - -Tue Apr 18 16:18:08 2000 Frank Warmerdam - - * tools/Makefile.in: Modified to install properly on SGI. - -2000-04-12 Mike Welles - * configure: Fixed stupid mistake in libc6 test on Linux - -2000-04-04 Mike Welles - * tif_win32.c: Applied patch to fix overreads and ovverwrites - caught by BoundsChecker. From Arvan Pritchard - (untested). - - * tif_getimage.c: Applied patch to silence VC6 warnings. From - Arvan Pritchard - - * tif_lzw.c: Applied patch to silence VC6 warnings. From - Arvan Pritchard - -2000-03-28 Frank Warmerdam - - * Added contrib/stream (stream io) code submitted by Avi Bleiweiss. - -2000-03-28 Frank Warmerdam *** 3.5.5 release *** - - * fax2ps: Fixed mixup of width and height in bounding box statement - as per submission by Nalin Dahyabhai . - -2000-03-27 Mike Welles - - * fax2ps: Modified printruns to take uint32 instead of uint16. - Patch courtesy of Bernt Herd - -2000-03-20 Mike Welles - - * configure: added test for libc6 for linux targets. Bug reported by - Stanislav Brabec - - * Added 3.5 docs to html/Makefile.in. - Thanks to Stanislav Brabec - - * configure: fixed bugs in sed scripts - (applied sed script s:/@:s;@:;s:/s;;:;: to configure). - fix submitted to Stanislav Brabec - - * tools/iptcutil was not in files list, and wasn't being - added to tar archive. Updated Makefile.in. - -2000-03-17 Frank Warmerdam - - * tif_fax3.c: Fixed serious bug introduced during the uint16->uint32 - conversion for the run arrays. - -2000-03-03 Frank Warmerdam - - * Set td_sampleformat default to SAMPLEFORMAT_UINT instead of - SAMPLEFORMAT_VOID in TIFFDefaultDirectory() in tif_dir.c. - -2000-03-02 Frank Warmerdam - - * 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 - - * Fixed tools/tiffcmp so that stopondiff testing works. - Patch care of Joseph Orost . - -2000-01-28 - - * 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 - - * 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 - - * Added TIFFmemory(3t) functions to libtiff.def. - -Tue Jan 4 13:39:00 2000 Frank Warmerdam - - * Added libtiff/libtiff.def to TIFFILES distribution list. - -Mon Dec 27 12:13:39 EST 1999 Mike Welles - - * 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 - - * Added fax3sm_winnt.c to distribution list in Makefile.in. - -Tue Dec 21 11:04:45 EST 1999 Mike Welles *** 3.5.4 release *** - - * Aadded Pixar tag support. Contributed by Phil Beffery - - * 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 - - * 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 - - * Added patch from Ivo Penzar , - supporting Adobe ZIP deflate. Untested. - -Sat Dec 4 15:47:11 1999 Frank Warmerdam - - * Made Packbits the default compression in tools/tiff2rgba.c instead - of LZW. - -Tue Nov 30 14:41:43 1999 Frank Warmerdam *** 3.5.3. release *** - - * Added tif_luv to contrib/djgpp/Makefile.lib. - -Tue Nov 30 14:15:32 EST 1999 Mike Welles - - * Added zip creation to relase makefile target - - * Added html for TIFFWriteTile.3t man page. - -Tue Nov 30 09:20:16 1999 Frank Warmerdam - - * 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 - - * Added TIFFWriteTile.3t man page. - -Sun Nov 28 20:36:18 1999 Frank Warmerdam - - * Added notes on use of makefile.vc in build.html, and fixed - email subscription address. - -199-11-28 Mike Welles - - * 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 -- modifications of - changes made by Frank (sun cc still complained on cast). - - * Added tiffconf.h to install target per request from Bill - Radcliffe : "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 - - * fixed various VC++ warnings as suggested by Gilles Vollant - . - -Wed Nov 24 12:08:16 1999 Frank Warmerdam - - * Modified TIFFquery.3t man pages info on TIFFIsByteSwapped() to - not imply applications are responsible for image data swapping. - -1999-11-22 Mike Welles - * HTML-ized the man pages, added to html/man - - * Removed LZW Compression to comply with Unisys patent extortion. - -1999-09-29 Mike Welles - * Corrected one remaining 16 -> 32 bit value in tif_fax3.c, - From Ivo Penzar - -1999-09-26 Mike Welles *** 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 - - * 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 - - * Applied Francois Dagand's patch to handle fax decompression bug. - (sizes >= 65536 were failing) - -Tue Sep 14 21:31:43 1999 Frank Warmerdam - - * Applied "a" mode fix to tif_win32.c/TIFFOpen() as suggested - by Christopher Lawton - -Wed Sep 8 08:19:18 1999 Frank Warmerdam - - * Added IRIX/gcc, and OSF/1 4.x support on behalf of - Albert Chin-A-Young - - * Added TIFFReassignTagToIgnore() API on behalf of - Bruce Cameron . Man page still pending. - -Wed Aug 25 11:39:07 1999 Frank Warmerdam - - * 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 - - * 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 - - * 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 - - * Updated html/index.html with anon CVS instructions. - -Mon Aug 16 13:18:41 1999 Frank Warmerdam - - * 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/plugins/FreeImage/Source/LibTIFF/LibTIFF.dsp b/plugins/FreeImage/Source/LibTIFF/LibTIFF.dsp deleted file mode 100644 index 9dd04050be..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/LibTIFF.dsp +++ /dev/null @@ -1,293 +0,0 @@ -# Microsoft Developer Studio Project File - Name="LibTIFF" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** NICHT BEARBEITEN ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=LibTIFF - Win32 Debug -!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE -!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl -!MESSAGE -!MESSAGE NMAKE /f "LibTIFF.mak". -!MESSAGE -!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben -!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: -!MESSAGE -!MESSAGE NMAKE /f "LibTIFF.mak" CFG="LibTIFF - Win32 Debug" -!MESSAGE -!MESSAGE Für die Konfiguration stehen zur Auswahl: -!MESSAGE -!MESSAGE "LibTIFF - Win32 Release" (basierend auf "Win32 (x86) Static Library") -!MESSAGE "LibTIFF - Win32 Debug" (basierend auf "Win32 (x86) Static Library") -!MESSAGE "LibTIFF - Win32 Release Unicode" (basierend auf "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "LibTIFF - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ELSEIF "$(CFG)" == "LibTIFF - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ELSEIF "$(CFG)" == "LibTIFF - Win32 Release Unicode" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "LibTIFF___Win32_Release_Unicode" -# PROP BASE Intermediate_Dir "LibTIFF___Win32_Release_Unicode" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "LibTIFF___Win32_Release_Unicode" -# PROP Intermediate_Dir "LibTIFF___Win32_Release_Unicode" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo - -!ENDIF - -# Begin Target - -# Name "LibTIFF - Win32 Release" -# Name "LibTIFF - Win32 Debug" -# Name "LibTIFF - Win32 Release Unicode" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\tif_aux.c -# End Source File -# Begin Source File - -SOURCE=.\tif_close.c -# End Source File -# Begin Source File - -SOURCE=.\tif_codec.c -# End Source File -# Begin Source File - -SOURCE=.\tif_color.c -# End Source File -# Begin Source File - -SOURCE=.\tif_compress.c -# End Source File -# Begin Source File - -SOURCE=.\tif_dir.c -# End Source File -# Begin Source File - -SOURCE=.\tif_dirinfo.c -# End Source File -# Begin Source File - -SOURCE=.\tif_dirread.c -# End Source File -# Begin Source File - -SOURCE=.\tif_dirwrite.c -# End Source File -# Begin Source File - -SOURCE=.\tif_dumpmode.c -# End Source File -# Begin Source File - -SOURCE=.\tif_error.c -# End Source File -# Begin Source File - -SOURCE=.\tif_extension.c -# End Source File -# Begin Source File - -SOURCE=.\tif_fax3.c -# End Source File -# Begin Source File - -SOURCE=.\tif_fax3sm.c -# End Source File -# Begin Source File - -SOURCE=.\tif_flush.c -# End Source File -# Begin Source File - -SOURCE=.\tif_getimage.c -# End Source File -# Begin Source File - -SOURCE=.\tif_jpeg.c -# End Source File -# Begin Source File - -SOURCE=.\tif_luv.c -# End Source File -# Begin Source File - -SOURCE=.\tif_lzw.c -# End Source File -# Begin Source File - -SOURCE=.\tif_next.c -# End Source File -# Begin Source File - -SOURCE=.\tif_open.c -# End Source File -# Begin Source File - -SOURCE=.\tif_packbits.c -# End Source File -# Begin Source File - -SOURCE=.\tif_pixarlog.c -# End Source File -# Begin Source File - -SOURCE=.\tif_predict.c -# End Source File -# Begin Source File - -SOURCE=.\tif_print.c -# End Source File -# Begin Source File - -SOURCE=.\tif_read.c -# End Source File -# Begin Source File - -SOURCE=.\tif_strip.c -# End Source File -# Begin Source File - -SOURCE=.\tif_swab.c -# End Source File -# Begin Source File - -SOURCE=.\tif_thunder.c -# End Source File -# Begin Source File - -SOURCE=.\tif_tile.c -# End Source File -# Begin Source File - -SOURCE=.\tif_version.c -# End Source File -# Begin Source File - -SOURCE=.\tif_warning.c -# End Source File -# Begin Source File - -SOURCE=.\tif_write.c -# End Source File -# Begin Source File - -SOURCE=.\tif_zip.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\t4.h -# End Source File -# Begin Source File - -SOURCE=.\tif_config.h -# End Source File -# Begin Source File - -SOURCE=.\tif_dir.h -# End Source File -# Begin Source File - -SOURCE=.\tif_fax3.h -# End Source File -# Begin Source File - -SOURCE=.\tif_predict.h -# End Source File -# Begin Source File - -SOURCE=.\tiff.h -# End Source File -# Begin Source File - -SOURCE=.\tiffio.h -# End Source File -# Begin Source File - -SOURCE=.\tiffiop.h -# End Source File -# Begin Source File - -SOURCE=.\tiffvers.h -# End Source File -# Begin Source File - -SOURCE=.\uvcode.h -# End Source File -# End Group -# End Target -# End Project diff --git a/plugins/FreeImage/Source/LibTIFF/SConstruct b/plugins/FreeImage/Source/LibTIFF/SConstruct deleted file mode 100644 index d1a2620cf5..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/SConstruct +++ /dev/null @@ -1,73 +0,0 @@ -# $Id: SConstruct,v 1.29 2011/04/10 17:14:09 drolon Exp $ - -# Tag Image File Format (TIFF) Software -# -# Copyright (C) 2005, Andrey Kiselev -# -# 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/plugins/FreeImage/Source/LibTIFF/mkg3states.c b/plugins/FreeImage/Source/LibTIFF/mkg3states.c deleted file mode 100644 index 46fac37a9c..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/mkg3states.c +++ /dev/null @@ -1,451 +0,0 @@ -/* "$Id: mkg3states.c,v 1.37 2011/04/10 17:14:09 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 -#include -#include - -#ifdef HAVE_UNISTD_H -# include -#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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/t4.h b/plugins/FreeImage/Source/LibTIFF/t4.h deleted file mode 100644 index 1457ebfabe..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/t4.h +++ /dev/null @@ -1,292 +0,0 @@ -/* $Id: t4.h,v 1.37 2011/04/10 17:14:09 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_ */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_acorn.c b/plugins/FreeImage/Source/LibTIFF/tif_acorn.c deleted file mode 100644 index d2de42de53..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_acorn.c +++ /dev/null @@ -1,526 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_acorn.c,v 1.37 2011/04/10 17:14:09 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 -#include - -/* -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; -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_apple.c b/plugins/FreeImage/Source/LibTIFF/tif_apple.c deleted file mode 100644 index 0cd2948cb7..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_apple.c +++ /dev/null @@ -1,281 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_apple.c,v 1.37 2011/04/10 17:14:09 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 -#include -#include -#include - -#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; -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_atari.c b/plugins/FreeImage/Source/LibTIFF/tif_atari.c deleted file mode 100644 index 62453a1d93..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_atari.c +++ /dev/null @@ -1,250 +0,0 @@ -/* "$Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_atari.c,v 1.37 2011/04/10 17:14:09 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 -#include -#else -#include -#include -#endif - -#ifndef O_ACCMODE -#define O_ACCMODE 3 -#endif - -#include - -#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 - -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; -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_aux.c b/plugins/FreeImage/Source/LibTIFF/tif_aux.c deleted file mode 100644 index 92df69bd1a..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_aux.c +++ /dev/null @@ -1,290 +0,0 @@ -/* $Id: tif_aux.c,v 1.37 2011/04/10 17:14:09 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 - -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, - "Failed to allocate memory for %s " - "(%ld elements of %ld bytes each)", - what,(long) nmemb, (long) elem_size); - - 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_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; -} - -static int -TIFFDefaultRefBlackWhite(TIFFDirectory* td) -{ - int i; - - if (!(td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float)))) - return 0; - if (td->td_photometric == PHOTOMETRIC_YCBCR) { - /* - * YCbCr (Class Y) images must have the ReferenceBlackWhite - * tag set. Fix the broken images, which lacks that tag. - */ - td->td_refblackwhite[0] = 0.0F; - td->td_refblackwhite[1] = td->td_refblackwhite[3] = - td->td_refblackwhite[5] = 255.0F; - td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F; - } else { - /* - * Assume RGB (Class R) - */ - for (i = 0; i < 3; i++) { - td->td_refblackwhite[2*i+0] = 0; - td->td_refblackwhite[2*i+1] = - (float)((1L<td_bitspersample)-1L); - } - } - return 1; -} - -/* - * 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_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: - if (!td->td_refblackwhite && !TIFFDefaultRefBlackWhite(td)) - return (0); - *va_arg(ap, float **) = td->td_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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_close.c b/plugins/FreeImage/Source/LibTIFF/tif_close.c deleted file mode 100644 index 03a8847e84..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_close.c +++ /dev/null @@ -1,126 +0,0 @@ -/* $Id: tif_close.c,v 1.37 2011/04/10 17:14:09 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); -} - -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_codec.c b/plugins/FreeImage/Source/LibTIFF/tif_codec.c deleted file mode 100644 index 7876a5fc63..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_codec.c +++ /dev/null @@ -1,160 +0,0 @@ -/* $Id: tif_codec.c,v 1.37 2011/04/10 17:14:09 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; -} - -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_color.c b/plugins/FreeImage/Source/LibTIFF/tif_color.c deleted file mode 100644 index f0302e4bf2..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_color.c +++ /dev/null @@ -1,287 +0,0 @@ -/* $Id: tif_color.c,v 1.37 2011/04/10 17:14:09 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 - -/* - * 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<(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) -{ - int32 i; - - /* XXX: Only 8-bit YCbCr input supported for now */ - Y = HICLAMP(Y, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255); - - i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]; - *r = CLAMP(i, 0, 255); - i = ycbcr->Y_tab[Y] - + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT); - *g = CLAMP(i, 0, 255); - i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]; - *b = CLAMP(i, 0, 255); -} - -/* - * 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_compress.c b/plugins/FreeImage/Source/LibTIFF/tif_compress.c deleted file mode 100644 index ac471b1e10..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_compress.c +++ /dev/null @@ -1,295 +0,0 @@ -/* $Id: tif_compress.c,v 1.37 2011/04/10 17:14:09 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 = ®isteredCODECS; (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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_config.h b/plugins/FreeImage/Source/LibTIFF/tif_config.h deleted file mode 100644 index 3e08176627..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_config.h +++ /dev/null @@ -1,266 +0,0 @@ -/* 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 compression (read-only) */ -#define OJPEG_SUPPORT 1 - -/* 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 header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the 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 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 header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the 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 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 header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the 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 header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the 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 header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the 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. */ -#include -#if (LONG_MAX == +9223372036854775807L) -#define SIZEOF_LONG 8 -#elif (LONG_MAX == +2147483647) -#define SIZEOF_LONG 4 -#else -#error "Cannot detect SIZEOF_LONG" -#endif - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to 1 if your 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 */ - -/* 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 header file. */ -#define HAVE_SEARCH_H 1 -#endif // _MSC_VER - - -/* Define to `long' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned' if does not define. */ -/* #undef size_t */ - -#endif /* _TIFFCONF_ */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_config.h-vms b/plugins/FreeImage/Source/LibTIFF/tif_config.h-vms deleted file mode 100644 index c2cae5752e..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_config.h-vms +++ /dev/null @@ -1,46 +0,0 @@ -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the 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 header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -//#define HAVE_IO_H 1 - -/* Define to 1 if you have the 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/plugins/FreeImage/Source/LibTIFF/tif_config.h.in b/plugins/FreeImage/Source/LibTIFF/tif_config.h.in deleted file mode 100644 index 86c07e6a99..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_config.h.in +++ /dev/null @@ -1,309 +0,0 @@ -/* 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 header file. */ -#undef HAVE_ASSERT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_DLFCN_H - -/* Define to 1 if you have the 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 header file. */ -#undef HAVE_INTTYPES_H - -/* Define to 1 if you have the 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 header file. */ -#undef HAVE_LIMITS_H - -/* Define to 1 if you have the 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 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 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 header file. */ -#undef HAVE_STDINT_H - -/* Define to 1 if you have the 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 header file. */ -#undef HAVE_STRINGS_H - -/* Define to 1 if you have the 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 header file. */ -#undef HAVE_SYS_STAT_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TIME_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_SYS_TYPES_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_UNISTD_H - -/* Define to 1 if you have the 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 and . */ -#undef TIME_WITH_SYS_TIME - -/* Define to 1 if your 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 does not define. */ -#undef off_t - -/* Define to `unsigned int' if does not define. */ -#undef size_t diff --git a/plugins/FreeImage/Source/LibTIFF/tif_config.vc.h b/plugins/FreeImage/Source/LibTIFF/tif_config.vc.h deleted file mode 100644 index 2bb16d3322..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_config.vc.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Define to 1 if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define to 1 if you have the 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 header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_IO_H 1 - -/* Define to 1 if you have the 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 -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_dir.c b/plugins/FreeImage/Source/LibTIFF/tif_dir.c deleted file mode 100644 index 081bb43c06..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_dir.c +++ /dev/null @@ -1,1391 +0,0 @@ -/* $Id: tif_dir.c,v 1.38 2011/04/10 17:14:09 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 == 8) - tif->tif_postdecode = _TIFFNoPostDecode; - else 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_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_bitspersample); - break; - case TIFFTAG_REFERENCEBLACKWHITE: - /* XXX should check for null range */ - _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6); - 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_REFERENCEBLACKWHITE: - *va_arg(ap, float**) = td->td_refblackwhite; - 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_refblackwhite); - 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; - /* - * Clear other directory-specific fields. - */ - tif->tif_tilesize = -1; - tif->tif_scanlinesize = -1; - - 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 - * - * 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_dir.h b/plugins/FreeImage/Source/LibTIFF/tif_dir.h deleted file mode 100644 index f642834c44..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_dir.h +++ /dev/null @@ -1,211 +0,0 @@ -/* $Id: tif_dir.h,v 1.37 2011/04/10 17:14:09 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 */ - float* td_refblackwhite; - 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_REFBLACKWHITE 41 -#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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_dirinfo.c b/plugins/FreeImage/Source/LibTIFF/tif_dirinfo.c deleted file mode 100644 index 7b7507a8cb..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_dirinfo.c +++ /dev/null @@ -1,884 +0,0 @@ -/* $Id: tif_dirinfo.c,v 1.38 2011/04/10 17:14:09 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 -#include - -/* - * 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_REFBLACKWHITE, - 1, 0, "ReferenceBlackWhite" }, -/* XXX temporarily accept LONG for backwards compatibility */ - { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_LONG, FIELD_REFBLACKWHITE, - 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); - } - 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); - } - 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_dirread.c b/plugins/FreeImage/Source/LibTIFF/tif_dirread.c deleted file mode 100644 index 3567b2ae51..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_dirread.c +++ /dev/null @@ -1,2117 +0,0 @@ -/* $Id: tif_dirread.c,v 1.38 2011/04/10 17:14:09 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*, 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; - uint16 previous_tag = 0; - int diroutoforderwarning = 0, compressionknown = 0; - int haveunknowntags = 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; - } - { - TIFFDirEntry* ma; - uint16 mb; - for (ma=dir, mb=0; mbtdir_tag==na->tdir_tag) - na->tdir_tag=IGNORE; - } - } - } - 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 (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 < previous_tag) { - if (!diroutoforderwarning) { - TIFFWarningExt(tif->tif_clientdata, module, - "%s: invalid TIFF directory; tags are not sorted in ascending order", - tif->tif_name); - diroutoforderwarning = 1; - } - } - previous_tag = dp->tdir_tag; - if (fix >= tif->tif_nfields || - dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) - 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) { - /* Unknown tag ... we'll deal with it below */ - haveunknowntags = 1; - continue; - } - /* - * 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; - } - } - - /* - * If we saw any unknown tags, make an extra pass over the directory - * to deal with them. This must be done separately because the tags - * could have become known when we registered a codec after finding - * the Compression tag. In a correctly-sorted directory there's - * no problem because Compression will come before any codec-private - * tags, but if the sorting is wrong that might not hold. - */ - if (haveunknowntags) { - fix = 0; - for (dp = dir, n = dircount; n > 0; n--, dp++) { - if (dp->tdir_tag == IGNORE) - continue; - if (fix >= tif->tif_nfields || - dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) - 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); - dp->tdir_tag = IGNORE; - continue; - } - fix = 0; - while (fix < tif->tif_nfields && - tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) - fix++; - } - /* - * 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); - 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: - { - double minv = 0.0, maxv = 0.0; - if (!TIFFFetchPerSampleAnys(tif, dp, &minv, &maxv) || - !TIFFSetField(tif, dp->tdir_tag, minv)) - goto bad; - } - break; - case TIFFTAG_SMAXSAMPLEVALUE: - { - double minv = 0.0, maxv = 0.0; - if (!TIFFFetchPerSampleAnys(tif, dp, &minv, &maxv) || - !TIFFSetField(tif, dp->tdir_tag, maxv)) - 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_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) - { - TIFFWarningExt(tif->tif_clientdata, - "TIFFReadDirectory", - "SamplesPerPixel tag is missing, " - "assuming correct SamplesPerPixel value is 3"); - if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) - goto bad; - } - if (td->td_photometric==PHOTOMETRIC_YCBCR) - { - TIFFWarningExt(tif->tif_clientdata, - "TIFFReadDirectory", - "SamplesPerPixel tag is missing, " - "applying correct SamplesPerPixel value of 3"); - if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) - goto bad; - } - else if ((td->td_photometric==PHOTOMETRIC_MINISWHITE) - || (td->td_photometric==PHOTOMETRIC_MINISBLACK)) - { - /* - * SamplesPerPixel tag is missing, but is not required - * by spec. Assume correct SamplesPerPixel value of 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)) { - if ( tif->tif_dir.td_bitspersample>=8 && tif->tif_dir.td_samplesperpixel==3) - tif->tif_dir.td_photometric = PHOTOMETRIC_RGB; - else if (tif->tif_dir.td_bitspersample>=8) - tif->tif_dir.td_photometric = PHOTOMETRIC_MINISBLACK; - else { - 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_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; ntdir_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); - 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) { - union - { - float f; - uint32 i; - } float_union; - - float_union.i=dir->tdir_offset; - v[0]=float_union.f; - 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 returns their min - * and max. - */ -static int -TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* minv, double* maxv) -{ - 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; - - *minv = *maxv = v[0]; - for (i = 1; i < check_count; i++) - { - if (v[i] < *minv) - *minv = v[i]; - if (v[i] > *maxv) - *maxv = v[i]; - } - status = 1; - } - 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 ( dir->tdir_count != 1 || dir->tdir_type != TIFF_RATIONAL ) - { - TIFFWarningExt(tif->tif_clientdata, tif->tif_name, - "incorrect count or type for SubjectDistance, tag ignored" ); - return (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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_dirwrite.c b/plugins/FreeImage/Source/LibTIFF/tif_dirwrite.c deleted file mode 100644 index 962937298e..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_dirwrite.c +++ /dev/null @@ -1,1436 +0,0 @@ -/* $Id: tif_dirwrite.c,v 1.37 2011/04/10 17:14:09 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 TIFFSetupBytePair(TIFF*, ttag_t, TIFFDirEntry*); -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_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 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. See comments - * related to these tags in tif_dir.c. - */ - if (fip->field_tag == TIFFTAG_PAGENUMBER - || fip->field_tag == TIFFTAG_HALFTONEHINTS - || fip->field_tag == TIFFTAG_YCBCRSUBSAMPLING - || fip->field_tag == TIFFTAG_DOTRANGE) { - if (fip->field_type == TIFF_BYTE) { - if (!TIFFSetupBytePair(tif, fip->field_tag, dir)) - goto bad; - } else if (fip->field_type == TIFF_SHORT) { - 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 bytes that are returned by - * value, rather than as a reference to an array. - */ -static int -TIFFSetupBytePair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) -{ - char v[2]; - - TIFFGetField(tif, tag, &v[0], &v[1]); - - dir->tdir_tag = (uint16) tag; - dir->tdir_type = (uint16) TIFF_BYTE; - dir->tdir_count = 2; - return (TIFFWriteByteArray(tif, dir, v)); -} - -/* - * 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_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 * (int32)(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; - } - break; - 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_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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_dumpmode.c b/plugins/FreeImage/Source/LibTIFF/tif_dumpmode.c deleted file mode 100644 index 273614728d..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_dumpmode.c +++ /dev/null @@ -1,126 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_dumpmode.c,v 1.37 2011/04/10 17:14:09 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); -} -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_error.c b/plugins/FreeImage/Source/LibTIFF/tif_error.c deleted file mode 100644 index 23f90648de..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_error.c +++ /dev/null @@ -1,80 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_error.c,v 1.37 2011/04/10 17:14:09 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); -} - -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_extension.c b/plugins/FreeImage/Source/LibTIFF/tif_extension.c deleted file mode 100644 index e8fb4a2cac..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_extension.c +++ /dev/null @@ -1,118 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_extension.c,v 1.37 2011/04/10 17:14:09 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; -} -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_fax3.c b/plugins/FreeImage/Source/LibTIFF/tif_fax3.c deleted file mode 100644 index 2e74a37c69..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_fax3.c +++ /dev/null @@ -1,1626 +0,0 @@ -/* $Id: tif_fax3.c,v 1.37 2011/04/10 17:14:09 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 - -/* - * 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 - ); - - /* - Assure that allocation computations do not overflow. - - TIFFroundup and TIFFSafeMultiply return zero on integer overflow - */ - dsp->runs=(uint32*) NULL; - nruns = TIFFroundup(rowpixels,32); - if (needsRefLine) { - nruns = TIFFSafeMultiply(uint32,nruns,2); - } - if ((nruns == 0) || (TIFFSafeMultiply(uint32,nruns,2) == 0)) { - TIFFErrorExt(tif->tif_clientdata, tif->tif_name, - "Row pixels integer overflow (rowpixels %u)", - rowpixels); - return (0); - } - dsp->runs = (uint32*) _TIFFCheckMalloc(tif, - TIFFSafeMultiply(uint32,nruns,2), - 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<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 EOFB\n", stderr ); -#endif - ClrBits( 13 ); - (*sp->fill)(buf, thisrun, pa, lastx); - UNCACHE_STATE(tif, sp); - return ( sp->line ? 1 : -1); /* don't error on badly-terminated strips */ - } - 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_fax3.h b/plugins/FreeImage/Source/LibTIFF/tif_fax3.h deleted file mode 100644 index ec2811f660..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_fax3.h +++ /dev/null @@ -1,538 +0,0 @@ -/* $Id: tif_fax3.h,v 1.37 2011/04/10 17:14:09 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++])<>= (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; \ - if (b1 <= (int) (a0 + TabEnt->Param)) { \ - if (b1 < (int) (a0 + TabEnt->Param) || pa != thisrun) { \ - unexpected("VL", a0); \ - goto eol2d; \ - } \ - } \ - 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_ */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_fax3sm.c b/plugins/FreeImage/Source/LibTIFF/tif_fax3sm.c deleted file mode 100644 index 1e2fe42316..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_fax3sm.c +++ /dev/null @@ -1,1260 +0,0 @@ -/* 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} -}; -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_flush.c b/plugins/FreeImage/Source/LibTIFF/tif_flush.c deleted file mode 100644 index af7fdd9b2a..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_flush.c +++ /dev/null @@ -1,74 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_flush.c,v 1.37 2011/04/10 17:14:09 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)); -} - -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_getimage.c b/plugins/FreeImage/Source/LibTIFF/tif_getimage.c deleted file mode 100644 index 041e540cba..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_getimage.c +++ /dev/null @@ -1,2678 +0,0 @@ -/* $Id: tif_getimage.c,v 1.39 2011/04/10 17:14:09 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 - -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), "%s", 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; - int32 incr = 2*toskew+w; - (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 += incr; - cp2 += incr; - 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; - int32 incr = 2*toskew+w; - (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 += incr; - cp2 += incr; - 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<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<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<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) && (img->samplesperpixel==3)) - { - 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), "%s", 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), "%s", 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_jbig.c b/plugins/FreeImage/Source/LibTIFF/tif_jbig.c deleted file mode 100644 index c779c9b0f6..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_jbig.c +++ /dev/null @@ -1,385 +0,0 @@ -/* $Id: tif_jbig.c,v 1.23 2011/04/10 17:14:09 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 - * - */ - -#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: */ - -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_jpeg.c b/plugins/FreeImage/Source/LibTIFF/tif_jpeg.c deleted file mode 100644 index ee7d886fa8..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_jpeg.c +++ /dev/null @@ -1,2078 +0,0 @@ -/* $Id: tif_jpeg.c,v 1.37 2011/04/10 17:14:09 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 . - */ -#include - -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", "%s", 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", "%s", 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; - - 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) { - /* 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; icinfo.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; - } 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 ( sp->jpegtables == NULL - || memcmp(sp->jpegtables,"\0\0\0\0\0\0\0\0\0",8) == 0 ) - { - if (!prepare_JPEGTables(tif)) - return (0); - /* Mark the field present */ - /* Can't use TIFFSetField since BEENWRITING is already set! */ - tif->tif_flags |= TIFF_DIRTYDIRECT; - TIFFSetFieldBit(tif, FIELD_JPEGTABLES); - } - } 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 { - if ((td->td_photometric == PHOTOMETRIC_MINISWHITE || td->td_photometric == PHOTOMETRIC_MINISBLACK) && td->td_samplesperpixel == 1) - sp->cinfo.c.in_color_space = JCS_GRAYSCALE; - else if (td->td_photometric == PHOTOMETRIC_RGB) - sp->cinfo.c.in_color_space = JCS_RGB; - else if (td->td_photometric == PHOTOMETRIC_SEPARATED && td->td_samplesperpixel == 4) - sp->cinfo.c.in_color_space = JCS_CMYK; - else - sp->cinfo.c.in_color_space = JCS_UNKNOWN; - if (!TIFFjpeg_set_colorspace(sp, sp->cinfo.c.in_color_space)) - 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 (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) - return (0); - if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) { - 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 += bytesperclumpline; - 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? - */ - if ( tif->tif_tilesize > 0 ) - tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; - - if(tif->tif_scanlinesize > 0 ) - tif->tif_scanlinesize = TIFFScanlineSize(tif); -} - -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 ); - - /* - ** We want to clear the loaded strip so the application has time - ** to set JPEGCOLORMODE or other behavior modifiers. This essentially - ** undoes the JPEGPreDecode triggers by TIFFFileStrip(). (#1936) - */ - tif->tif_curstrip = -1; - -#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 -/* -The following line assumes incorrectly that all JPEG-in-TIFF files will have -a JPEGTABLES tag generated and causes null-filled JPEGTABLES tags to be written -when the JPEG data is placed with TIFFWriteRawStrip. The field bit should be -set, anyway, later when actual JPEGTABLES header is generated, so removing it -here hopefully is harmless. - 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: */ - -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_luv.c b/plugins/FreeImage/Source/LibTIFF/tif_luv.c deleted file mode 100644 index 5e72ca63ba..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_luv.c +++ /dev/null @@ -1,1629 +0,0 @@ -/* $Id: tif_luv.c,v 1.37 2011/04/10 17:14:09 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 -#include -#include - -/* - * 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_lzw.c b/plugins/FreeImage/Source/LibTIFF/tif_lzw.c deleted file mode 100644 index 16fcd7f9a7..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_lzw.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* $Id: tif_lzw.c,v 1.38 2011/04/10 17:14:09 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 - -/* - * 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_msdos.c b/plugins/FreeImage/Source/LibTIFF/tif_msdos.c deleted file mode 100644 index 884981fa49..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_msdos.c +++ /dev/null @@ -1,193 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_msdos.c,v 1.35 2011/04/10 17:14:09 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 /* for open, close, etc. function prototypes */ -#include -#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 - -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 -#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; -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_next.c b/plugins/FreeImage/Source/LibTIFF/tif_next.c deleted file mode 100644 index 3fa6406e68..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_next.c +++ /dev/null @@ -1,154 +0,0 @@ -/* $Id: tif_next.c,v 1.37 2011/04/10 17:14:09 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 - * 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_ojpeg.c b/plugins/FreeImage/Source/LibTIFF/tif_ojpeg.c deleted file mode 100644 index ad339afc1b..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_ojpeg.c +++ /dev/null @@ -1,2448 +0,0 @@ -/* $Id: tif_ojpeg.c,v 1.36 2011/04/10 17:14:09 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 . - - 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 - and from AWare Systems' TIFF section - . 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 - Copyright (c) AWare Systems - - 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 . -*/ - -/* 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 -#endif - -#include "../LibJPEG/jpeglib.h" -#include "../LibJPEG/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; nqtable_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; ndctable_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; nactable_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; mqtable_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; mdctable_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; mactable_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_curstrilelibjpeg_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; mlines_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; qsubsampling_convert_clinelenout; q++) - { - r=oy; - for (sy=0; sysubsampling_ver; sy++) - { - for (sx=0; sxsubsampling_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_horsubsampling_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_lengthimage_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_offsetplane_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; -#if JPEG_LIB_VERSION >= 70 - sp->libjpeg_jpeg_decompress_struct.do_fancy_upsampling=FALSE; -#endif - 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; nsubsampling_convert_ylines; n++) - *m++=sp->subsampling_convert_ybuf+n*sp->subsampling_convert_ylinelen; - for (n=0; nsubsampling_convert_clines; n++) - *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen; - for (n=0; nsubsampling_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; osamples_per_pixel; o++) - sp->sof_c[o]=o; - sp->sof_hv[0]=((sp->subsampling_hor<<4)|sp->subsampling_ver); - for (o=1; osamples_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; osamples_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 (3tif_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 (3tif_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 (3tif_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 - { - /* Y: Number of lines */ - if (OJPEGReadWord(sp,&p)==0) - return(0); - if ((pimage_length) && (pstrile_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 ((pimage_width) && (pstrile_width)) - { - TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected width"); - return(0); - } - if ((uint32)p>sp->strile_width) - { - TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data image width exceeds expected image 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; qsubsamplingcorrect==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; osamples_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; msamples_per_pixel; m++) - { - if ((sp->qtable_offset[m]!=0) && ((m==0) || (sp->qtable_offset[m]!=sp->qtable_offset[m-1]))) - { - for (n=0; nqtable_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; msamples_per_pixel; m++) - { - if ((sp->dctable_offset[m]!=0) && ((m==0) || (sp->dctable_offset[m]!=sp->dctable_offset[m-1]))) - { - for (n=0; ndctable_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; msamples_per_pixel; m++) - { - if ((sp->actable_offset[m]!=0) && ((m==0) || (sp->actable_offset[m]!=sp->actable_offset[m-1]))) - { - for (n=0; nactable_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 - { - if (sp->tif->tif_dir.td_stripoffset == 0) { - TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip offsets are missing"); - return(0); - } - 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 if (sp->tif->tif_dir.td_stripbytecount==NULL) - sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; - else - { - if (sp->tif->tif_dir.td_stripbytecount == 0) { - TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing"); - return(0); - } - 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; msamples_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; msamples_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_strilein_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", "%s", 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", "%s", 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 - - -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_open.c b/plugins/FreeImage/Source/LibTIFF/tif_open.c deleted file mode 100644 index c2a0412e90..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_open.c +++ /dev/null @@ -1,695 +0,0 @@ -/* $Id: tif_open.c,v 1.37 2011/04/10 17:14:09 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 ((m & 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_packbits.c b/plugins/FreeImage/Source/LibTIFF/tif_packbits.c deleted file mode 100644 index 1fc96d13a2..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_packbits.c +++ /dev/null @@ -1,300 +0,0 @@ -/* $Id: tif_packbits.c,v 1.37 2011/04/10 17:14:09 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 - -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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_pixarlog.c b/plugins/FreeImage/Source/LibTIFF/tif_pixarlog.c deleted file mode 100644 index ef4faa4e45..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_pixarlog.c +++ /dev/null @@ -1,1371 +0,0 @@ -/* $Id: tif_pixarlog.c,v 1.37 2011/04/10 17:14:09 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/zlib.h" - -#include -#include -#include - -/* 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_predict.c b/plugins/FreeImage/Source/LibTIFF/tif_predict.c deleted file mode 100644 index 7f7dc636be..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_predict.c +++ /dev/null @@ -1,736 +0,0 @@ -/* $Id: tif_predict.c,v 1.37 2011/04/10 17:14:09 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_predict.h b/plugins/FreeImage/Source/LibTIFF/tif_predict.h deleted file mode 100644 index 6675d9b2a7..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_predict.h +++ /dev/null @@ -1,77 +0,0 @@ -/* $Id: tif_predict.h,v 1.37 2011/04/10 17:14:09 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_print.c b/plugins/FreeImage/Source/LibTIFF/tif_print.c deleted file mode 100644 index 50663396df..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_print.c +++ /dev/null @@ -1,642 +0,0 @@ -/* $Id: tif_print.c,v 1.37 2011/04/10 17:14:09 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 -#include -#include - -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, ""); - 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_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 < 3; 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: , %lu bytes\n", - (unsigned long) value_count * 4); - return 1; - case TIFFTAG_PHOTOSHOP: - fprintf(fd, " Photoshop Data: , %lu bytes\n", - (unsigned long) value_count); - return 1; - case TIFFTAG_ICCPROFILE: - fprintf(fd, " ICC Profile: , %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_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_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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_read.c b/plugins/FreeImage/Source/LibTIFF/tif_read.c deleted file mode 100644 index 351a1b058d..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_read.c +++ /dev/null @@ -1,750 +0,0 @@ -/* $Id: tif_read.c,v 1.37 2011/04/10 17:14:09 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 - - 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); - if (tif->tif_rawdatasize > 0) - tif->tif_rawdata = (tidata_t) _TIFFmalloc(tif->tif_rawdatasize); - tif->tif_flags |= TIFF_MYBUFFER; - } - if ((tif->tif_rawdata == NULL) || (tif->tif_rawdatasize == 0)) { - 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_stream.cxx b/plugins/FreeImage/Source/LibTIFF/tif_stream.cxx deleted file mode 100644 index a3aaea19d7..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_stream.cxx +++ /dev/null @@ -1,295 +0,0 @@ -/* $Id: tif_stream.cxx,v 1.32 2011/04/10 17:14:09 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 - -#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/plugins/FreeImage/Source/LibTIFF/tif_strip.c b/plugins/FreeImage/Source/LibTIFF/tif_strip.c deleted file mode 100644 index 8abf726a00..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_strip.c +++ /dev/null @@ -1,366 +0,0 @@ -/* $Id: tif_strip.c,v 1.37 2011/04/10 17:14:09 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; - - TIFFGetFieldDefaulted(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]; - - TIFFGetFieldDefaulted(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; - } - - /* number of sample clumps per line */ - scanline = TIFFhowmany(td->td_imagewidth, - ycbcrsubsampling[0]); - /* number of samples per line */ - scanline = multiply(tif, scanline, - ycbcrsubsampling[0]*ycbcrsubsampling[1] + 2, - "TIFFScanlineSize"); - } 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]; - - TIFFGetFieldDefaulted(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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_swab.c b/plugins/FreeImage/Source/LibTIFF/tif_swab.c deleted file mode 100644 index 5a42713d5c..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_swab.c +++ /dev/null @@ -1,242 +0,0 @@ -/* $Id: tif_swab.c,v 1.37 2011/04/10 17:14:09 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[] gives - * the bit reversed value of . 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_thunder.c b/plugins/FreeImage/Source/LibTIFF/tif_thunder.c deleted file mode 100644 index b8c6cc93cc..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_thunder.c +++ /dev/null @@ -1,189 +0,0 @@ -/* $Id: tif_thunder.c,v 1.37 2011/04/10 17:14:09 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" -#include -#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 < maxpixels ) \ - { \ - if (npixels++ & 1) \ - *op++ |= lastpixel; \ - else \ - op[0] = (tidataval_t) (lastpixel << 4); \ - } \ -} - -static int -ThunderSetupDecode(TIFF* tif) -{ - static const char module[] = "ThunderSetupDecode"; - - if ( tif->tif_dir.td_bitspersample != 4 ) - { - TIFFErrorExt(tif->tif_clientdata, module, - "Wrong bitspersample value (%d), Thunder decoder only supports 4bits per sample.", - (int) tif->tif_dir.td_bitspersample ); - return 0; - } - - - return (1); -} - -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; - tif->tif_setupdecode = ThunderSetupDecode; - return (1); -} -#endif /* THUNDER_SUPPORT */ - -/* vim: set ts=8 sts=8 sw=8 noet: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ - diff --git a/plugins/FreeImage/Source/LibTIFF/tif_tile.c b/plugins/FreeImage/Source/LibTIFF/tif_tile.c deleted file mode 100644 index 4659825aab..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_tile.c +++ /dev/null @@ -1,280 +0,0 @@ -/* $Id: tif_tile.c,v 1.37 2011/04/10 17:14:09 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_unix.c b/plugins/FreeImage/Source/LibTIFF/tif_unix.c deleted file mode 100644 index 7e294cb78b..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_unix.c +++ /dev/null @@ -1,300 +0,0 @@ -/* $Id: tif_unix.c,v 1.35 2011/04/10 17:14:09 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 -#endif - -#include -#include -#include - -#ifdef HAVE_UNISTD_H -# include -#endif - -#ifdef HAVE_FCNTL_H -# include -#endif - -#ifdef HAVE_IO_H -# include -#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 - -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 -/* - * 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 : "", - 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; -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_version.c b/plugins/FreeImage/Source/LibTIFF/tif_version.c deleted file mode 100644 index 6badfcdb5f..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_version.c +++ /dev/null @@ -1,40 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_version.c,v 1.37 2011/04/10 17:14:09 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); -} -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_vms.c b/plugins/FreeImage/Source/LibTIFF/tif_vms.c deleted file mode 100644 index 553f5072e3..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_vms.c +++ /dev/null @@ -1,595 +0,0 @@ -/* $Id: tif_vms.c,v 1.21 2011/04/10 17:14:09 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 -#include -#include "tiffiop.h" -#if !HAVE_IEEEFP -#include -#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 - -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 -#include -#include - -/* - * 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 -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_warning.c b/plugins/FreeImage/Source/LibTIFF/tif_warning.c deleted file mode 100644 index a2dbbe7e2f..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_warning.c +++ /dev/null @@ -1,81 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_warning.c,v 1.37 2011/04/10 17:14:09 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); -} - - -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_win3.c b/plugins/FreeImage/Source/LibTIFF/tif_win3.c deleted file mode 100644 index aa21e3aef8..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_win3.c +++ /dev/null @@ -1,232 +0,0 @@ -/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_win3.c,v 1.35 2011/04/10 17:14:09 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 /* for open, close, etc. function prototypes */ -#endif - -#include -#include -#include - -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 - -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; -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_win32.c b/plugins/FreeImage/Source/LibTIFF/tif_win32.c deleted file mode 100644 index 5b3875901d..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_win32.c +++ /dev/null @@ -1,408 +0,0 @@ -/* $Id: tif_win32.c,v 1.35 2011/04/10 17:14:09 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 - -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" : - * - * 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 : "", 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_write.c b/plugins/FreeImage/Source/LibTIFF/tif_write.c deleted file mode 100644 index 043e645b87..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_write.c +++ /dev/null @@ -1,718 +0,0 @@ -/* $Id: tif_write.c,v 1.37 2011/04/10 17:14:09 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 - -#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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tif_zip.c b/plugins/FreeImage/Source/LibTIFF/tif_zip.c deleted file mode 100644 index 74ee9c4b5a..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tif_zip.c +++ /dev/null @@ -1,419 +0,0 @@ -/* $Id: tif_zip.c,v 1.37 2011/04/10 17:14:09 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/zlib.h" - -#include - -/* - * 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tiff.h b/plugins/FreeImage/Source/LibTIFF/tiff.h deleted file mode 100644 index b8912efb9d..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tiff.h +++ /dev/null @@ -1,654 +0,0 @@ -/* $Id: tiff.h,v 1.38 2011/04/10 17:14:09 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 */ -#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 */ -#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 */ -#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 */ -#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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tiffconf.h-vms b/plugins/FreeImage/Source/LibTIFF/tiffconf.h-vms deleted file mode 100644 index de717ecb97..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tiffconf.h-vms +++ /dev/null @@ -1,99 +0,0 @@ -/* - 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/plugins/FreeImage/Source/LibTIFF/tiffconf.vc.h b/plugins/FreeImage/Source/LibTIFF/tiffconf.vc.h deleted file mode 100644 index 5d73852c41..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tiffconf.vc.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - 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_ */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tiffio.h b/plugins/FreeImage/Source/LibTIFF/tiffio.h deleted file mode 100644 index 2b94407acd..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tiffio.h +++ /dev/null @@ -1,526 +0,0 @@ -/* $Id: tiffio.h,v 1.37 2011/04/10 17:14:09 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 -# 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 -#include - -/* 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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tiffio.hxx b/plugins/FreeImage/Source/LibTIFF/tiffio.hxx deleted file mode 100644 index fc20d725d2..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tiffio.hxx +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: tiffio.hxx,v 1.32 2011/04/10 17:14:09 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 -#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: */ -/* - * Local Variables: - * mode: c++ - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tiffiop.h b/plugins/FreeImage/Source/LibTIFF/tiffiop.h deleted file mode 100644 index 1a64862810..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tiffiop.h +++ /dev/null @@ -1,353 +0,0 @@ -/* $Id: tiffiop.h,v 1.37 2011/04/10 17:14:09 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 -#endif - -#ifdef HAVE_SYS_TYPES_H -# include -#endif - -#ifdef HAVE_STRING_H -# include -#endif - -#ifdef HAVE_ASSERT_H -# include -#else -# define assert(x) -#endif - -#ifdef HAVE_SEARCH_H -# include -#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. -*/ - -#if !defined(__xlC__) && !defined(__xlc__) // Already defined there (#2301) -#define TIFF_INT64_T signed long long -#define TIFF_UINT64_T unsigned long long -#endif - -#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 < (0xffffffff - (uint32)(y-1))) ? \ - ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \ - 0U) -#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3) -#define TIFFroundup(x, y) (TIFFhowmany(x,y)*(y)) - -/* Safe multiply which returns zero if there is an integer overflow */ -#define TIFFSafeMultiply(t,v,m) ((((t)m != (t)0) && (((t)((v*m)/m)) == (t)v)) ? (t)(v*m) : (t)0) - -#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: */ -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/LibTIFF/tiffvers.h b/plugins/FreeImage/Source/LibTIFF/tiffvers.h deleted file mode 100644 index 594702b566..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/tiffvers.h +++ /dev/null @@ -1,9 +0,0 @@ -#define TIFFLIB_VERSION_STR "LIBTIFF, Version 3.9.5\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 20110409 diff --git a/plugins/FreeImage/Source/LibTIFF/uvcode.h b/plugins/FreeImage/Source/LibTIFF/uvcode.h deleted file mode 100644 index 8f22325703..0000000000 --- a/plugins/FreeImage/Source/LibTIFF/uvcode.h +++ /dev/null @@ -1,180 +0,0 @@ -/* 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 }, -}; -/* - * Local Variables: - * mode: c - * c-basic-offset: 8 - * fill-column: 78 - * End: - */ diff --git a/plugins/FreeImage/Source/Metadata/Exif.cpp b/plugins/FreeImage/Source/Metadata/Exif.cpp deleted file mode 100644 index 7d0955c5db..0000000000 --- a/plugins/FreeImage/Source/Metadata/Exif.cpp +++ /dev/null @@ -1,859 +0,0 @@ -// ========================================================== -// Metadata functions implementation -// Exif metadata model -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// 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_MAKER_NOTE 0x927C // Maker note - -// CANON cameras have some funny bespoke fields that need further processing... -#define TAG_CANON_CAMERA_STATE_0x01 0x0001 // tags under tag 0x001 (CameraSettings) -#define TAG_CANON_CAMERA_STATE_0x02 0x0002 // tags under tag 0x002 (FocalLength) -#define TAG_CANON_CAMERA_STATE_0x04 0x0004 // tags under tag 0x004 (ShotInfo) -#define TAG_CANON_CAMERA_STATE_0x12 0x0012 // tags under tag 0x012 (AFInfo) -#define TAG_CANON_CAMERA_STATE_0xA0 0x00A0 // tags under tag 0x0A0 (ProcessingInfo) -#define TAG_CANON_CAMERA_STATE_0xE0 0x00E0 // tags under tag 0x0E0 (SensorInfo) - - -// ===================================================================== -// Reimplementation of strnicmp (it is not supported on some systems) -// ===================================================================== - -/** -Compare characters of two strings without regard to case. -@param s1 Null-terminated string to compare. -@param s2 Null-terminated string to compare. -@param len Number of characters to compare -@return Returns 0 if s1 substring identical to s2 substring -*/ -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, const 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, const 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, const 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 DWORD -ReadUint32(BOOL msb_order, const void *buffer) { - return ((DWORD) 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 ((memcmp("OLYMP\x00\x01", pval, 7) == 0) || (memcmp("OLYMP\x00\x02", pval, 7) == 0) || (memcmp("EPSON", pval, 5) == 0) || (memcmp("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(memcmp("OLYMPUS\x00\x49\x49\x03\x00", pval, 12) == 0) { - // Olympus Type 2 Makernote - // !!! NOT YET SUPPORTED !!! - *subdirOffset = 0; - *md_model = TagLib::UNKNOWN; - } - else if(memcmp("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 - *subdirOffset = 0; - *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(memcmp("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 ((memcmp("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\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\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("LEICA", Maker, 5) == 0)) { - // Leica maker note - if(memcmp("LEICA\x00\x00\x00", pval, 8) == 0) { - // not yet supported makernote data ignored - *subdirOffset = 0; - *md_model = TagLib::UNKNOWN; - } - } - else if(Maker && ((FreeImage_strnicmp("Pentax", Maker, 6) == 0) || (FreeImage_strnicmp("Asahi", Maker, 5) == 0))) { - // Pentax maker note - if(memcmp("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 ((memcmp("SONY CAM\x20\x00\x00\x00", pval, 12) == 0) || (memcmp("SONY DSC\x20\x00\x00\x00", pval, 12) == 0)) { - *md_model = TagLib::EXIF_MAKERNOTE_SONY; - *subdirOffset = 12; - } - else if ((memcmp("SIGMA\x00\x00\x00", pval, 8) == 0) || (memcmp("FOVEON\x00\x00", pval, 8) == 0)) { - FITAG *tagModel = NULL; - FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "Model", &tagModel); - const char *Model = (char*)FreeImage_GetTagValue(tagModel); - if(Model && (memcmp("SIGMA SD1\x00", Model, 10) == 0)) { - // Sigma SD1 maker note - *subdirOffset = 10; - *md_model = TagLib::EXIF_MAKERNOTE_SIGMA_SD1; - } else { - // Sigma / Foveon makernote - *subdirOffset = 10; - *md_model = TagLib::EXIF_MAKERNOTE_SIGMA_FOVEON; - } - } -} - -/** -Process a Canon maker note tag. -A single Canon tag may contain many other tags within. -*/ -static BOOL -processCanonMakerNoteTag(FIBITMAP *dib, FITAG *tag) { - char defaultKey[16]; - DWORD startIndex = 0; - TagLib& s = TagLib::instance(); - - WORD tag_id = FreeImage_GetTagID(tag); - - int subTagTypeBase = 0; - - switch(tag_id) { - case TAG_CANON_CAMERA_STATE_0x01: - subTagTypeBase = 0xC100; - startIndex = 1; - break; - case TAG_CANON_CAMERA_STATE_0x02: - subTagTypeBase = 0xC200; - startIndex = 0; - break; - case TAG_CANON_CAMERA_STATE_0x04: - subTagTypeBase = 0xC400; - startIndex = 1; - break; - case TAG_CANON_CAMERA_STATE_0x12: - subTagTypeBase = 0x1200; - startIndex = 0; - break; - case TAG_CANON_CAMERA_STATE_0xA0: - subTagTypeBase = 0xCA00; - startIndex = 1; - break; - case TAG_CANON_CAMERA_STATE_0xE0: - subTagTypeBase = 0xCE00; - startIndex = 1; - break; - - default: - { - // 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); - } - - return TRUE; - } - break; - - } - - WORD *pvalue = (WORD*)FreeImage_GetTagValue(tag); - - // create a tag - FITAG *canonTag = FreeImage_CreateTag(); - if (!canonTag) return FALSE; - - // we intentionally skip the first array member (if needed) - for (DWORD i = startIndex; i < FreeImage_GetTagCount(tag); i++) { - - 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); - - return TRUE; -} - -/** -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)); - if(NULL == exif_value) { - // out of memory ... - return; - } - 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 destack; // directory entries stack - std::stack ifdstack; // IFD stack - std::stack 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 visitedIFD; - - /* - "An Image File Directory (IFD) consists of a 2-byte count of the number of directory - entries (i.e. the number of fields), followed by a sequence of 12-byte field - entries, followed by a 4-byte offset of the next IFD (or 0 if none)." - The "next IFD" (1st IFD) is the thumbnail. - */ - #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 (0th IFD) and follow it were it leads. - - const BYTE *ifd0th = (BYTE*)tiffp + offset; - - const BYTE *ifdp = ifd0th; - - 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 and entry 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 type - 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)); - // check that tag length (size of the tag value in bytes) will fit in a DWORD - unsigned tag_data_width = FreeImage_TagDataWidth(FreeImage_GetTagType(tag)); - if (tag_data_width != 0 && FreeImage_GetTagCount(tag) > ~(DWORD)0 / tag_data_width) { - FreeImage_DeleteTag(tag); - // jump to next entry - continue; - } - FreeImage_SetTagLength(tag, FreeImage_GetTagCount(tag) * tag_data_width); - - 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 that length does not exceed the buffer size - if(FreeImage_GetTagLength(tag) > length - offset_value){ - // 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; - const 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 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()); - - // - // --- handle thumbnail data --- - // - - const WORD entriesCount0th = ReadUint16(msb_order, ifd0th); - - DWORD next_offset = ReadUint32(msb_order, DIR_ENTRY_ADDR(ifd0th, entriesCount0th)); - if ((next_offset == 0) || (next_offset >= length)) { - return TRUE; //< no thumbnail - } - - const BYTE* const ifd1st = (BYTE*)tiffp + next_offset; - const WORD entriesCount1st = ReadUint16(msb_order, ifd1st); - - unsigned thCompression = 0; - unsigned thOffset = 0; - unsigned thSize = 0; - - for(int e = 0; e < entriesCount1st; e++) { - - // point to the directory entry - const BYTE* base = DIR_ENTRY_ADDR(ifd1st, e); - - // check for buffer overflow - const size_t remaining = (size_t)base + 12 - (size_t)tiffp; - if(remaining >= length) { - // bad IFD1 directory, ignore it - return FALSE; - } - - // get the tag ID - WORD tag = ReadUint16(msb_order, base); - // get the tag type - WORD type = ReadUint16(msb_order, base + sizeof(WORD)); - // get number of components - DWORD count = ReadUint32(msb_order, base + sizeof(WORD) + sizeof(WORD)); - // get the tag value - DWORD offset = ReadUint32(msb_order, base + sizeof(WORD) + sizeof(WORD) + sizeof(DWORD)); - - switch(tag) { - case TAG_COMPRESSION: - // Tiff Compression Tag (should be COMPRESSION_OJPEG (6), but is not always respected) - thCompression = offset; - break; - case TAG_JPEG_INTERCHANGE_FORMAT: - // Tiff JPEGInterchangeFormat Tag - thOffset = offset; - break; - case TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: - // Tiff JPEGInterchangeFormatLength Tag - thSize = offset; - break; - // ### X and Y Resolution ignored, orientation ignored - case TAG_X_RESOLUTION: // XResolution - case TAG_Y_RESOLUTION: // YResolution - case TAG_RESOLUTION_UNIT: // ResolutionUnit - case TAG_ORIENTATION: // Orientation - break; - default: - break; - } - } - - if (/*thCompression != 6 ||*/ thOffset == 0 || thSize == 0) { - return TRUE; - } - - if(thOffset + thSize > length) { - return TRUE; - } - - // load the thumbnail - - const BYTE *thLocation = tiffp + thOffset; - - FIMEMORY* hmem = FreeImage_OpenMemory(const_cast(thLocation), thSize); - FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem); - FreeImage_CloseMemory(hmem); - - // store the thumbnail - FreeImage_SetThumbnail(dib, thumbnail); - // then delete it - FreeImage_Unload(thumbnail); - - return TRUE; -} - -/** - Read and decode 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 - TIFF header with 2 IFDs. 0th - the image attributes, 1st - may be used for thumbnail - - profile += sizeof(exif_signature); - length -= sizeof(exif_signature); - - // read the TIFF header (8 bytes) - - // 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 (Image File Directory) - unsigned long first_offset = ReadUint32(bMotorolaOrder, profile + 4); - if (first_offset > length) { - // bad Exif data - return FALSE; - } - - /* - Note: as FreeImage 3.14.0, this test is no longer needed for images with similar suspicious offset - => tested with Pentax Optio 230, FujiFilm SP-2500 and Canon EOS 300D - 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/plugins/FreeImage/Source/Metadata/FIRational.cpp b/plugins/FreeImage/Source/Metadata/FIRational.cpp deleted file mode 100644 index d383c8d38f..0000000000 --- a/plugins/FreeImage/Source/Metadata/FIRational.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// ========================================================== -// Helper class for rational numbers -// -// 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 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/plugins/FreeImage/Source/Metadata/FIRational.h b/plugins/FreeImage/Source/Metadata/FIRational.h deleted file mode 100644 index bd3ee13e07..0000000000 --- a/plugins/FreeImage/Source/Metadata/FIRational.h +++ /dev/null @@ -1,108 +0,0 @@ -// ========================================================== -// Helper class for rational numbers -// -// 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 your own risk! -// ========================================================== - -#ifndef FIRATIONAL_H -#define FIRATIONAL_H - -/** -Helper class to deal with rational numbers. -NB: LONG data type is assumed to be a signed 32-bit number. -*/ -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/plugins/FreeImage/Source/Metadata/FreeImageTag.cpp b/plugins/FreeImage/Source/Metadata/FreeImageTag.cpp deleted file mode 100644 index 84e15d0822..0000000000 --- a/plugins/FreeImage/Source/Metadata/FreeImageTag.cpp +++ /dev/null @@ -1,318 +0,0 @@ -// ========================================================== -// Tag manipulation functions -// -// 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 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; - - try { - // 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)); - if (!dst_tag->key) { - throw FI_MSG_ERROR_MEMORY; - } - 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)); - if (!dst_tag->description) { - throw FI_MSG_ERROR_MEMORY; - } - 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 - dst_tag->value = (BYTE*)malloc(src_tag->length * sizeof(BYTE)); - if (!dst_tag->value) { - throw FI_MSG_ERROR_MEMORY; - } - memcpy(dst_tag->value, src_tag->value, src_tag->length); - - return clone; - - } catch(const char *message) { - FreeImage_DeleteTag(clone); - FreeImage_OutputMessageProc(FIF_UNKNOWN, message); - return NULL; - } -} - -// -------------------------------------------------------------------------- -// 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 && value) { - FITAGHEADER *tag_header = (FITAGHEADER *)tag->data; - // first, check the tag - if(tag_header->count * FreeImage_TagDataWidth((FREE_IMAGE_MDTYPE)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: - { - tag_header->value = (char*)malloc((tag_header->length + 1) * sizeof(char)); - if (!tag_header->value) { - return FALSE; - } - char *src_data = (char*)value; - char *dst_data = (char*)tag_header->value; - for(DWORD i = 0; i < tag_header->length; i++) { - dst_data[i] = src_data[i]; - } - dst_data[tag_header->length] = '\0'; - } - break; - - default: - tag_header->value = malloc(tag_header->length * sizeof(BYTE)); - if (!tag_header->value) { - return FALSE; - } - memcpy(tag_header->value, value, tag_header->length); - break; - } - return TRUE; - } - return FALSE; -} - - -// -------------------------------------------------------------------------- -// FITAG internal helper functions -// -------------------------------------------------------------------------- - -/** -Given a FREE_IMAGE_MDTYPE, calculate the size of this type in bytes unit -@param type Input data type -@return Returns the size of the data type, in bytes unit -*/ -unsigned -FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE type) { - static const unsigned format_bytes[] = { - 0, // FIDT_NOTYPE = 0, // placeholder - 1, // FIDT_BYTE = 1, // 8-bit unsigned integer - 1, // FIDT_ASCII = 2, // 8-bit bytes w/ last byte null - 2, // FIDT_SHORT = 3, // 16-bit unsigned integer - 4, // FIDT_LONG = 4, // 32-bit unsigned integer - 8, // FIDT_RATIONAL = 5, // 64-bit unsigned fraction - 1, // FIDT_SBYTE = 6, // 8-bit signed integer - 1, // FIDT_UNDEFINED= 7, // 8-bit untyped data - 2, // FIDT_SSHORT = 8, // 16-bit signed integer - 4, // FIDT_SLONG = 9, // 32-bit signed integer - 8, // FIDT_SRATIONAL= 10, // 64-bit signed fraction - 4, // FIDT_FLOAT = 11, // 32-bit IEEE floating point - 8, // FIDT_DOUBLE = 12, // 64-bit IEEE floating point - 4, // FIDT_IFD = 13, // 32-bit unsigned integer (offset) - 4, // FIDT_PALETTE = 14 // 32-bit RGBQUAD - 0, // placeholder (15) - 8, // FIDT_LONG8 = 16, // 64-bit unsigned integer - 8, // FIDT_SLONG8 = 17, // 64-bit signed integer - 8 // FIDT_IFD8 = 18 // 64-bit unsigned integer (offset) - }; - - return (type < (sizeof(format_bytes)/sizeof(format_bytes[0]))) ? - format_bytes[type] : 0; -} - diff --git a/plugins/FreeImage/Source/Metadata/FreeImageTag.h b/plugins/FreeImage/Source/Metadata/FreeImageTag.h deleted file mode 100644 index f412603e8d..0000000000 --- a/plugins/FreeImage/Source/Metadata/FreeImageTag.h +++ /dev/null @@ -1,474 +0,0 @@ -// ========================================================== -// Tag manipulation functions -// -// 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 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 - -// LibTIF compression modes - -#define TAG_COMPRESSION_NONE 1 /* dump mode */ -#define TAG_COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */ -#define TAG_COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */ -#define TAG_COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */ -#define TAG_COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */ -#define TAG_COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */ -#define TAG_COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */ -#define TAG_COMPRESSION_OJPEG 6 /* !6.0 JPEG */ -#define TAG_COMPRESSION_JPEG 7 /* %JPEG DCT compression */ -#define TAG_COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */ -#define TAG_COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */ -#define TAG_COMPRESSION_PACKBITS 32773 /* Macintosh RLE */ -#define TAG_COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */ -/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT */ -#define TAG_COMPRESSION_DCS 32947 /* Kodak DCS encoding */ -#define TAG_COMPRESSION_JBIG 34661 /* ISO JBIG */ -#define TAG_COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */ -#define TAG_COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */ -#define TAG_COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */ -#define TAG_COMPRESSION_LZMA 34925 /* LZMA2 */ - -// 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 -*/ -unsigned FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE 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).
- - Sample usage :
- - TagLib& s = TagLib::instance(); - TagInfo *tag_info = s.getTagInfo(EXIF_MAIN, 0x0100); - - -*/ - -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, - EXIF_MAKERNOTE_SIGMA_SD1, - EXIF_MAKERNOTE_SIGMA_FOVEON, - IPTC, - GEOTIFF, - ANIMATION - }; - -private: - - typedef std::map TAGINFO; - typedef std::map TABLEMAP; - - /// store hash tables for all known tag info tables - TABLEMAP _table_map; - -private: - /** - Constructor (private)
- 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 const char *g_TagLib_XMPFieldName = "XMLPacket"; - -/// Name of the Exif raw field -static const char *g_TagLib_ExifRawFieldName = "ExifRaw"; - -// -------------------------------------------------------------------------- -// 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/plugins/FreeImage/Source/Metadata/IPTC.cpp b/plugins/FreeImage/Source/Metadata/IPTC.cpp deleted file mode 100644 index 817beddf98..0000000000 --- a/plugins/FreeImage/Source/Metadata/IPTC.cpp +++ /dev/null @@ -1,325 +0,0 @@ -// ========================================================== -// 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; - - if (!dataptr || (datalen == 0)) { - return FALSE; - } - - // 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 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/plugins/FreeImage/Source/Metadata/TagConversion.cpp b/plugins/FreeImage/Source/Metadata/TagConversion.cpp deleted file mode 100644 index 7b91598014..0000000000 --- a/plugins/FreeImage/Source/Metadata/TagConversion.cpp +++ /dev/null @@ -1,1094 +0,0 @@ -// ========================================================== -// Tag to string conversion functions -// -// 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 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 - { - DWORD *pvalue = (DWORD *)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) - { - DWORD *pvalue = (DWORD *)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_LONG8: // N x 64-bit unsigned integer - { - FIUINT64 *pvalue = (FIUINT64 *)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_IFD8: // N x 64-bit unsigned integer (offset) - { - FIUINT64 *pvalue = (FIUINT64 *)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_SLONG8: // N x 64-bit signed integer - { - FIINT64 *pvalue = (FIINT64 *)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_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: - { - const 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; - - case TAG_COMPRESSION: - { - WORD compression = *((WORD*)FreeImage_GetTagValue(tag)); - switch(compression) { - case TAG_COMPRESSION_NONE: - sprintf(format, "dump mode (%d)", compression); - break; - case TAG_COMPRESSION_CCITTRLE: - sprintf(format, "CCITT modified Huffman RLE (%d)", compression); - break; - case TAG_COMPRESSION_CCITTFAX3: - sprintf(format, "CCITT Group 3 fax encoding (%d)", compression); - break; - /* - case TAG_COMPRESSION_CCITT_T4: - sprintf(format, "CCITT T.4 (TIFF 6 name) (%d)", compression); - break; - */ - case TAG_COMPRESSION_CCITTFAX4: - sprintf(format, "CCITT Group 4 fax encoding (%d)", compression); - break; - /* - case TAG_COMPRESSION_CCITT_T6: - sprintf(format, "CCITT T.6 (TIFF 6 name) (%d)", compression); - break; - */ - case TAG_COMPRESSION_LZW: - sprintf(format, "LZW (%d)", compression); - break; - case TAG_COMPRESSION_OJPEG: - sprintf(format, "!6.0 JPEG (%d)", compression); - break; - case TAG_COMPRESSION_JPEG: - sprintf(format, "JPEG (%d)", compression); - break; - case TAG_COMPRESSION_NEXT: - sprintf(format, "NeXT 2-bit RLE (%d)", compression); - break; - case TAG_COMPRESSION_CCITTRLEW: - sprintf(format, "CCITTRLEW (%d)", compression); - break; - case TAG_COMPRESSION_PACKBITS: - sprintf(format, "PackBits Macintosh RLE (%d)", compression); - break; - case TAG_COMPRESSION_THUNDERSCAN: - sprintf(format, "ThunderScan RLE (%d)", compression); - break; - case TAG_COMPRESSION_PIXARFILM: - sprintf(format, "Pixar companded 10bit LZW (%d)", compression); - break; - case TAG_COMPRESSION_PIXARLOG: - sprintf(format, "Pixar companded 11bit ZIP (%d)", compression); - break; - case TAG_COMPRESSION_DEFLATE: - sprintf(format, "Deflate compression (%d)", compression); - break; - case TAG_COMPRESSION_ADOBE_DEFLATE: - sprintf(format, "Adobe Deflate compression (%d)", compression); - break; - case TAG_COMPRESSION_DCS: - sprintf(format, "Kodak DCS encoding (%d)", compression); - break; - case TAG_COMPRESSION_JBIG: - sprintf(format, "ISO JBIG (%d)", compression); - break; - case TAG_COMPRESSION_SGILOG: - sprintf(format, "SGI Log Luminance RLE (%d)", compression); - break; - case TAG_COMPRESSION_SGILOG24: - sprintf(format, "SGI Log 24-bit packed (%d)", compression); - break; - case TAG_COMPRESSION_JP2000: - sprintf(format, "Leadtools JPEG2000 (%d)", compression); - break; - case TAG_COMPRESSION_LZMA: - sprintf(format, "LZMA2 (%d)", compression); - break; - default: - sprintf(format, "Unknown type (%d)", compression); - break; - } - - buffer += format; - 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/plugins/FreeImage/Source/Metadata/TagLib.cpp b/plugins/FreeImage/Source/Metadata/TagLib.cpp deleted file mode 100644 index eff291beab..0000000000 --- a/plugins/FreeImage/Source/Metadata/TagLib.cpp +++ /dev/null @@ -1,1617 +0,0 @@ -// ========================================================== -// Tag library -// -// 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 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 TagInfo 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"}, - { 0x011D, (char *) "PageName", (char *) "Name of the page"}, - { 0x011E, (char *) "XPosition", (char *) "X position of the image"}, - { 0x011F, (char *) "YPosition", (char *) "Y position of the image"}, - { 0x0128, (char *) "ResolutionUnit", (char *) "Unit of X and Y resolution"}, - { 0x0129, (char *) "PageNumber", (char *) "Page number"}, - { 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"}, - { 0x013C, (char *) "HostComputer", (char *) "Host computer used to generate 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"}, - { 0xA430, (char *) "CameraOwnerName", (char *) "Camera owner name"}, - { 0xA431, (char *) "BodySerialNumber", (char *) "Body serial number"}, - { 0xA432, (char *) "LensSpecification", (char *) "Lens specification"}, - { 0xA433, (char *) "LensMake", (char *) "Lens make"}, - { 0xA434, (char *) "LensModel", (char *) "Lens model"}, - { 0xA435, (char *) "LensSerialNumber", (char *) "Lens serial number"}, - - // These tags are not part of the Exiv v2.3 specifications but are often loaded by applications as Exif data - { 0x4746, (char *) "Rating", (char *) "Rating tag used by Windows"}, - { 0x4749, (char *) "RatingPercent", (char *) "Rating tag used by Windows, value in percent"}, - { 0x9C9B, (char *) "XPTitle", (char *) "Title tag used by Windows, encoded in UCS2"}, - { 0x9C9C, (char *) "XPComment", (char *) "Comment tag used by Windows, encoded in UCS2"}, - { 0x9C9D, (char *) "XPAuthor", (char *) "Author tag used by Windows, encoded in UCS2"}, - { 0x9C9E, (char *) "XPKeywords", (char *) "Keywords tag used by Windows, encoded in UCS2"}, - { 0x9C9F, (char *) "XPSubject", (char *) "Subject tag used by Windows, encoded in UCS2"}, - { 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 *) "UnknownD30", (char *) "Canon UnknownD30 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 *) "CanonAFInfo", (char *) "Canon AFInfo Tags"}, - { 0x0013, (char *) "ThumbnailImageValidArea", (char *) NULL}, - { 0x0015, (char *) "SerialNumberFormat", (char *) NULL}, - { 0x001A, (char *) "SuperMacro", (char *) NULL}, - { 0x001C, (char *) "DateStampMode", (char *) NULL}, - { 0x001D, (char *) "MyColors", (char *) NULL}, - { 0x001E, (char *) "FirmwareRevision", (char *) NULL}, - { 0x0023, (char *) "Categories", (char *) NULL}, - { 0x0024, (char *) "FaceDetect1", (char *) NULL}, - { 0x0025, (char *) "FaceDetect2", (char *) NULL}, - { 0x0026, (char *) "CanonAFInfo2", (char *) "Canon AFInfo2 Tags"}, - { 0x0028, (char *) "ImageUniqueID", (char *) NULL}, - { 0x0081, (char *) "RawDataOffset", (char *) NULL}, - { 0x0083, (char *) "OriginalDecisionDataOffset", (char *) NULL}, - { 0x0090, (char *) "CustomFunctions1D", (char *) "CanonCustom Functions1D Tags"}, - { 0x0091, (char *) "PersonalFunctions", (char *) "CanonCustom PersonalFuncs Tags"}, - { 0x0092, (char *) "PersonalFunctionValues", (char *) "CanonCustom PersonalFuncValues Tags"}, - { 0x0093, (char *) "CanonFileInfo", (char *) "Canon FileInfo Tags"}, - { 0x0094, (char *) "AFPointsInFocus1D", (char *) NULL}, - { 0x0095, (char *) "LensModel", (char *) NULL}, - { 0x0096, (char *) "SerialInfo", (char *) NULL}, - { 0x0097, (char *) "DustRemovalData", (char *) NULL}, - { 0x0098, (char *) "CropInfo", (char *) NULL}, - { 0x0099, (char *) "CustomFunctions2", (char *) NULL}, - { 0x009A, (char *) "AspectInfo", (char *) NULL}, - { 0x00A0, (char *) "ProcessingInfo", (char *) NULL}, - { 0x00A1, (char *) "ToneCurveTable", (char *) NULL}, - { 0x00A2, (char *) "SharpnessTable", (char *) NULL}, - { 0x00A3, (char *) "SharpnessFreqTable", (char *) NULL}, - { 0x00A4, (char *) "WhiteBalanceTable", (char *) NULL}, - { 0x00A9, (char *) "ColorBalance", (char *) NULL}, - { 0x00AA, (char *) "MeasuredColor", (char *) NULL}, - { 0x00AE, (char *) "ColorTemperature", (char *) NULL}, - { 0x00B0, (char *) "CanonFlags", (char *) NULL}, - { 0x00B1, (char *) "ModifiedInfo", (char *) NULL}, - { 0x00B2, (char *) "ToneCurveMatching", (char *) NULL}, - { 0x00B3, (char *) "WhiteBalanceMatching", (char *) NULL}, - { 0x00B4, (char *) "ColorSpace", (char *) NULL}, - { 0x00B6, (char *) "PreviewImageInfo", (char *) NULL}, - { 0x00D0, (char *) "VRDOffset", (char *) "Offset of VRD 'recipe data' if it exists"}, - { 0x00E0, (char *) "SensorInfo", (char *) NULL}, - { 0x4001, (char *) "ColorData", (char *) "Canon ColorData Tags"}, - { 0x4002, (char *) "CRWParam?", (char *) NULL}, - { 0x4003, (char *) "ColorInfo", (char *) NULL}, - { 0x4005, (char *) "Flavor?", (char *) NULL}, - { 0x4008, (char *) "BlackLevel?", (char *) NULL}, - { 0x4010, (char *) "CustomPictureStyleFileName", (char *) NULL}, - { 0x4013, (char *) "AFMicroAdj", (char *) NULL}, - { 0x4015, (char *) "VignettingCorr", (char *) NULL}, - { 0x4016, (char *) "VignettingCorr2", (char *) NULL}, - { 0x4018, (char *) "LightingOpt", (char *) NULL}, - { 0x4019, (char *) "LensInfo", (char *) NULL}, - { 0x4020, (char *) "AmbienceInfo", (char *) NULL}, - { 0x4024, (char *) "FilterInfo", (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) - { 0xC100 + 1, (char *) "CameraSettings:MacroMode", (char *) NULL}, - { 0xC100 + 2, (char *) "CameraSettings:SelfTimer", (char *) NULL}, - { 0xC100 + 3, (char *) "CameraSettings:Quality", (char *) NULL}, - { 0xC100 + 4, (char *) "CameraSettings:CanonFlashMode", (char *) NULL}, - { 0xC100 + 5, (char *) "CameraSettings:ContinuousDrive", (char *) NULL}, - { 0xC100 + 6, (char *) "CameraSettings:0x0006", (char *) NULL}, - { 0xC100 + 7, (char *) "CameraSettings:FocusMode", (char *) NULL}, - { 0xC100 + 8, (char *) "CameraSettings:0x0008", (char *) NULL}, - { 0xC100 + 9, (char *) "CameraSettings:RecordMode", (char *) NULL}, - { 0xC100 + 10, (char *) "CameraSettings:CanonImageSize", (char *) NULL}, - { 0xC100 + 11, (char *) "CameraSettings:EasyMode", (char *) NULL}, - { 0xC100 + 12, (char *) "CameraSettings:DigitalZoom", (char *) NULL}, - { 0xC100 + 13, (char *) "CameraSettings:Contrast", (char *) NULL}, - { 0xC100 + 14, (char *) "CameraSettings:Saturation", (char *) NULL}, - { 0xC100 + 15, (char *) "CameraSettings:Sharpness", (char *) NULL}, - { 0xC100 + 16, (char *) "CameraSettings:CameraISO", (char *) NULL}, - { 0xC100 + 17, (char *) "CameraSettings:MeteringMode", (char *) NULL}, - { 0xC100 + 18, (char *) "CameraSettings:FocusRange", (char *) NULL}, - { 0xC100 + 19, (char *) "CameraSettings:AFPoint", (char *) NULL}, - { 0xC100 + 20, (char *) "CameraSettings:CanonExposureMode", (char *) NULL}, - { 0xC100 + 21, (char *) "CameraSettings:0x0015", (char *) NULL}, - { 0xC100 + 22, (char *) "CameraSettings:LensType", (char *) NULL}, - { 0xC100 + 23, (char *) "CameraSettings:LongFocal", (char *) NULL}, - { 0xC100 + 24, (char *) "CameraSettings:ShortFocal", (char *) NULL}, - { 0xC100 + 25, (char *) "CameraSettings:FocalUnits", (char *) "Focal Units per mm"}, - { 0xC100 + 26, (char *) "CameraSettings:MaxAperture", (char *) NULL}, - { 0xC100 + 27, (char *) "CameraSettings:MinAperture", (char *) NULL}, - { 0xC100 + 28, (char *) "CameraSettings:FlashActivity", (char *) NULL}, - { 0xC100 + 29, (char *) "CameraSettings:FlashBits", (char *) NULL}, - { 0xC100 + 30, (char *) "CameraSettings:0x001E", (char *) NULL}, - { 0xC100 + 31, (char *) "CameraSettings:0x001F", (char *) NULL}, - { 0xC100 + 32, (char *) "CameraSettings:FocusContinuous", (char *) NULL}, - { 0xC100 + 33, (char *) "CameraSettings:AESetting", (char *) NULL}, - { 0xC100 + 34, (char *) "CameraSettings:ImageStabilization", (char *) NULL}, - { 0xC100 + 35, (char *) "CameraSettings:DisplayAperture", (char *) NULL}, - { 0xC100 + 36, (char *) "CameraSettings:ZoomSourceWidth", (char *) NULL}, - { 0xC100 + 37, (char *) "CameraSettings:ZoomTargetWidth", (char *) NULL}, - { 0xC100 + 38, (char *) "CameraSettings:0x0026", (char *) NULL}, - { 0xC100 + 39, (char *) "CameraSettings:SpotMeteringMode", (char *) NULL}, - { 0xC100 + 40, (char *) "CameraSettings:PhotoEffect", (char *) NULL}, - { 0xC100 + 41, (char *) "CameraSettings:ManualFlashOutput", (char *) NULL}, - { 0xC100 + 42, (char *) "CameraSettings:ColorTone", (char *) NULL}, - { 0xC100 + 43, (char *) "CameraSettings:0x002B", (char *) NULL}, - { 0xC100 + 44, (char *) "CameraSettings:0x002C", (char *) NULL}, - { 0xC100 + 45, (char *) "CameraSettings:0x002D", (char *) NULL}, - { 0xC100 + 46, (char *) "CameraSettings:SRAWQuality", (char *) NULL}, - { 0xC100 + 47, (char *) "CameraSettings:0x002F", (char *) NULL}, - { 0xC100 + 48, (char *) "CameraSettings:0x0030", (char *) NULL}, - - // Fields under tag 0x0002 (we add 0xC200 to make unique tag id) - { 0xC200 + 0, (char *) "FocalLength:FocalType", (char *) NULL}, - { 0xC200 + 1, (char *) "FocalLength:FocalLength", (char *) NULL}, - { 0xC200 + 2, (char *) "FocalLength:FocalPlaneXSize", (char *) NULL}, - { 0xC200 + 3, (char *) "FocalLength:FocalPlaneYSize", (char *) NULL}, - - // Fields under tag 0x0004 (we add 0xC400 to make unique tag id) - { 0xC400 + 1, (char *) "ShotInfo:AutoISO", (char *) NULL}, - { 0xC400 + 2, (char *) "ShotInfo:BaseISO", (char *) NULL}, - { 0xC400 + 3, (char *) "ShotInfo:MeasuredEV", (char *) NULL}, - { 0xC400 + 4, (char *) "ShotInfo:TargetAperture", (char *) NULL}, - { 0xC400 + 5, (char *) "ShotInfo:TargetExposureTime", (char *) NULL}, - { 0xC400 + 6, (char *) "ShotInfo:ExposureCompensation", (char *) NULL}, - { 0xC400 + 7, (char *) "ShotInfo:WhiteBalance", (char *) NULL}, - { 0xC400 + 8, (char *) "ShotInfo:SlowShutter", (char *) NULL}, - { 0xC400 + 9, (char *) "ShotInfo:SequenceNumber", (char *) NULL}, - { 0xC400 + 10, (char *) "ShotInfo:OpticalZoomCode", (char *) NULL}, - { 0xC400 + 11, (char *) "ShotInfo:0x000B", (char *) NULL}, - { 0xC400 + 12, (char *) "ShotInfo:CameraTemperature", (char *) NULL}, - { 0xC400 + 13, (char *) "ShotInfo:FlashGuideNumber", (char *) NULL}, - { 0xC400 + 14, (char *) "ShotInfo:AFPointsInFocus", (char *) NULL}, - { 0xC400 + 15, (char *) "ShotInfo:FlashExposureComp", (char *) NULL}, - { 0xC400 + 16, (char *) "ShotInfo:AutoExposureBracketing", (char *) NULL}, - { 0xC400 + 17, (char *) "ShotInfo:AEBBracketValue", (char *) NULL}, - { 0xC400 + 18, (char *) "ShotInfo:ControlMode", (char *) NULL}, - { 0xC400 + 19, (char *) "ShotInfo:FocusDistanceUpper", (char *) NULL}, - { 0xC400 + 20, (char *) "ShotInfo:FocusDistanceLower", (char *) NULL}, - { 0xC400 + 21, (char *) "ShotInfo:FNumber", (char *) NULL}, - { 0xC400 + 22, (char *) "ShotInfo:ExposureTime", (char *) NULL}, - { 0xC400 + 23, (char *) "ShotInfo:MeasuredEV2", (char *) NULL}, - { 0xC400 + 24, (char *) "ShotInfo:BulbDuration", (char *) NULL}, - { 0xC400 + 25, (char *) "ShotInfo:0x0019", (char *) NULL}, - { 0xC400 + 26, (char *) "ShotInfo:CameraType", (char *) NULL}, - { 0xC400 + 27, (char *) "ShotInfo:AutoRotate", (char *) NULL}, - { 0xC400 + 28, (char *) "ShotInfo:NDFilter", (char *) NULL}, - { 0xC400 + 29, (char *) "ShotInfo:SelfTimer2", (char *) NULL}, - { 0xC400 + 30, (char *) "ShotInfo:0x001E", (char *) NULL}, - { 0xC400 + 31, (char *) "ShotInfo:0x001F", (char *) NULL}, - { 0xC400 + 32, (char *) "ShotInfo:0x0020", (char *) NULL}, - { 0xC400 + 33, (char *) "ShotInfo:FlashOutput", (char *) NULL}, - - // Fields under tag 0x0012 (we add 0x1200 to make unique tag id) - { 0x1200 + 0, (char *) "AFInfo:NumAFPoints", (char *) NULL}, - { 0x1200 + 1, (char *) "AFInfo:ValidAFPoints", (char *) NULL}, - { 0x1200 + 2, (char *) "AFInfo:CanonImageWidth", (char *) NULL}, - { 0x1200 + 3, (char *) "AFInfo:CanonImageHeight", (char *) NULL}, - { 0x1200 + 4, (char *) "AFInfo:AFImageWidth", (char *) NULL}, - { 0x1200 + 5, (char *) "AFInfo:AFImageHeight", (char *) NULL}, - { 0x1200 + 6, (char *) "AFInfo:AFAreaWidth", (char *) NULL}, - { 0x1200 + 7, (char *) "AFInfo:AFAreaHeight", (char *) NULL}, - { 0x1200 + 8, (char *) "AFInfo:AFAreaXPositions", (char *) NULL}, - { 0x1200 + 9, (char *) "AFInfo:AFAreaYPositions", (char *) NULL}, - { 0x1200 + 10, (char *) "AFInfo:AFPointsInFocus", (char *) NULL}, - { 0x1200 + 11, (char *) "AFInfo:PrimaryAFPoint?", (char *) NULL}, - { 0x1200 + 12, (char *) "AFInfo:PrimaryAFPoint", (char *) NULL}, - { 0x1200 + 13, (char *) "AFInfo:0x000D", (char *) NULL}, - { 0x1200 + 14, (char *) "AFInfo:0x000E", (char *) NULL}, - { 0x1200 + 15, (char *) "AFInfo:0x000F", (char *) NULL}, - { 0x1200 + 16, (char *) "AFInfo:0x0010", (char *) NULL}, - { 0x1200 + 17, (char *) "AFInfo:0x0011", (char *) NULL}, - { 0x1200 + 18, (char *) "AFInfo:0x0012", (char *) NULL}, - { 0x1200 + 19, (char *) "AFInfo:0x0013", (char *) NULL}, - { 0x1200 + 20, (char *) "AFInfo:0x0014", (char *) NULL}, - { 0x1200 + 21, (char *) "AFInfo:0x0015", (char *) NULL}, - { 0x1200 + 22, (char *) "AFInfo:0x0016", (char *) NULL}, - { 0x1200 + 23, (char *) "AFInfo:0x0017", (char *) NULL}, - { 0x1200 + 24, (char *) "AFInfo:0x0018", (char *) NULL}, - { 0x1200 + 25, (char *) "AFInfo:0x0019", (char *) NULL}, - { 0x1200 + 26, (char *) "AFInfo:0x001A", (char *) NULL}, - { 0x1200 + 27, (char *) "AFInfo:0x001B", (char *) NULL}, - - // Fields under tag 0x00A0 (we add 0xCA00 to make unique tag id) - { 0xCA00 + 1, (char *) "ProcessingInfo:ToneCurve", (char *) NULL}, - { 0xCA00 + 2, (char *) "ProcessingInfo:Sharpness", (char *) NULL}, - { 0xCA00 + 3, (char *) "ProcessingInfo:SharpnessFrequency", (char *) NULL}, - { 0xCA00 + 4, (char *) "ProcessingInfo:SensorRedLevel", (char *) NULL}, - { 0xCA00 + 5, (char *) "ProcessingInfo:SensorBlueLevel", (char *) NULL}, - { 0xCA00 + 6, (char *) "ProcessingInfo:WhiteBalanceRed", (char *) NULL}, - { 0xCA00 + 7, (char *) "ProcessingInfo:WhiteBalanceBlue", (char *) NULL}, - { 0xCA00 + 8, (char *) "ProcessingInfo:WhiteBalance", (char *) NULL}, - { 0xCA00 + 9, (char *) "ProcessingInfo:ColorTemperature", (char *) NULL}, - { 0xCA00 + 10, (char *) "ProcessingInfo:PictureStyle", (char *) NULL}, - { 0xCA00 + 11, (char *) "ProcessingInfo:DigitalGain", (char *) NULL}, - { 0xCA00 + 12, (char *) "ProcessingInfo:WBShiftAB", (char *) NULL}, - { 0xCA00 + 13, (char *) "ProcessingInfo:WBShiftGM", (char *) NULL}, - - // Fields under tag 0x00E0 (we add 0xCE00 to make unique tag id) - { 0xCE00 + 1, (char *) "SensorInfo:SensorWidth", (char *) NULL}, - { 0xCE00 + 2, (char *) "SensorInfo:SensorHeight", (char *) NULL}, - { 0xCE00 + 3, (char *) "SensorInfo:0x0003", (char *) NULL}, - { 0xCE00 + 4, (char *) "SensorInfo:0x0004", (char *) NULL}, - { 0xCE00 + 5, (char *) "SensorInfo:SensorLeftBorder", (char *) NULL}, - { 0xCE00 + 6, (char *) "SensorInfo:SensorTopBorder", (char *) NULL}, - { 0xCE00 + 7, (char *) "SensorInfo:SensorRightBorder", (char *) NULL}, - { 0xCE00 + 8, (char *) "SensorInfo:SensorBottomBorder", (char *) NULL}, - { 0xCE00 + 9, (char *) "SensorInfo:BlackMaskLeftBorder", (char *) NULL}, - { 0xCE00 + 10, (char *) "SensorInfo:BlackMaskTopBorder", (char *) NULL}, - { 0xCE00 + 11, (char *) "SensorInfo:BlackMaskRightBorder", (char *) NULL}, - { 0xCE00 + 12, (char *) "SensorInfo:BlackMaskBottomBorder", (char *) NULL}, - { 0xCE00 + 13, (char *) "SensorInfo:0x000D", (char *) NULL}, - { 0xCE00 + 14, (char *) "SensorInfo:0x000E", (char *) NULL}, - { 0xCE00 + 15, (char *) "SensorInfo:0x000F", (char *) NULL}, - { 0xCE00 + 16, (char *) "SensorInfo:0x0010", (char *) NULL}, - - { 0x0000, (char *) NULL, (char *) NULL} - }; - -/** -Casio type 1 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 *) "ISO", (char *) NULL}, - { 0x0015, (char *) "FirmwareDate", (char *) NULL}, - { 0x0016, (char *) "Enhancement", (char *) NULL}, - { 0x0017, (char *) "ColorFilter", (char *) NULL}, - { 0x0018, (char *) "AFPoint", (char *) NULL}, - { 0x0019, (char *) "FlashIntensity", (char *) NULL}, - { 0x0E00, (char *) "PrintIM", (char *) NULL}, - { 0x0000, (char *) NULL, (char *) NULL} - }; - -/** -Casio type 2 maker note -*/ -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}, - { 0x2001, (char *) "FirmwareDate", (char *) NULL}, - { 0x2011, (char *) "WhiteBalanceBias", (char *) NULL}, - { 0x2012, (char *) "WhiteBalance", (char *) NULL}, - { 0x2021, (char *) "AFPointPosition", (char *) NULL}, - { 0x2022, (char *) "ObjectDistance", (char *) NULL}, - { 0x2034, (char *) "FlashDistance", (char *) NULL}, - { 0x2076, (char *) "SpecialEffectMode", (char *) NULL}, - { 0x3000, (char *) "RecordMode", (char *) NULL}, - { 0x3001, (char *) "ReleaseMode", (char *) NULL}, - { 0x3002, (char *) "Quality", (char *) NULL}, - { 0x3003, (char *) "FocusMode", (char *) NULL}, - { 0x3006, (char *) "HometownCity", (char *) NULL}, - { 0x3007, (char *) "BestShotMode", (char *) NULL}, - { 0x3008, (char *) "AutoISO", (char *) NULL}, - { 0x3009, (char *) "AFMode", (char *) NULL}, - { 0x3011, (char *) "Sharpness", (char *) NULL}, - { 0x3012, (char *) "Contrast", (char *) NULL}, - { 0x3013, (char *) "Saturation", (char *) NULL}, - { 0x3014, (char *) "ISO", (char *) NULL}, - { 0x3015, (char *) "ColorMode", (char *) NULL}, - { 0x3016, (char *) "Enhancement", (char *) NULL}, - { 0x3017, (char *) "ColorFilter", (char *) NULL}, - { 0x301C, (char *) "SequenceNumber", (char *) NULL}, - { 0x301D, (char *) "BracketSequence", (char *) NULL}, - { 0x3020, (char *) "ImageStabilization", (char *) NULL}, - { 0x302A, (char *) "LightingMode", (char *) NULL}, - { 0x302B, (char *) "PortraitRefiner", (char *) NULL}, - { 0x3030, (char *) "SpecialEffectLevel", (char *) NULL}, - { 0x3031, (char *) "SpecialEffectSetting", (char *) NULL}, - { 0x3103, (char *) "DriveMode", (char *) NULL}, - { 0x4001, (char *) "CaptureFrameRate", (char *) NULL}, - { 0x4003, (char *) "VideoQuality", (char *) NULL}, - { 0x0000, (char *) NULL, (char *) NULL} - }; - -/** -FujiFilm maker note -*/ -static TagInfo - exif_fujifilm_tag_table[] = - { - { 0x0000, (char *) "Version", (char *) NULL}, - { 0x0010, (char *) "InternalSerialNumber", (char *) NULL}, - { 0x1000, (char *) "Quality", (char *) NULL}, - { 0x1001, (char *) "Sharpness", (char *) NULL}, - { 0x1002, (char *) "WhiteBalance", (char *) NULL}, - { 0x1003, (char *) "Saturation", (char *) NULL}, - { 0x1004, (char *) "Contrast", (char *) NULL}, - { 0x1005, (char *) "ColorTemperature", (char *) NULL}, - { 0x100A, (char *) "WhiteBalanceFineTune", (char *) NULL}, - { 0x100B, (char *) "NoiseReduction", (char *) NULL}, - { 0x1010, (char *) "FujiFlashMode", (char *) NULL}, - { 0x1011, (char *) "FlashExposureComp", (char *) NULL}, - { 0x1020, (char *) "Macro", (char *) NULL}, - { 0x1021, (char *) "FocusMode", (char *) NULL}, - { 0x1023, (char *) "FocusPixel", (char *) NULL}, - { 0x1030, (char *) "SlowSync", (char *) NULL}, - { 0x1031, (char *) "PictureMode", (char *) NULL}, - { 0x1033, (char *) "EXRAuto", (char *) NULL}, - { 0x1034, (char *) "EXRMode", (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}, - { 0x1401, (char *) "FilmMode", (char *) NULL}, - { 0x1402, (char *) "DynamicRangeSetting", (char *) NULL}, - { 0x1403, (char *) "DevelopmentDynamicRange", (char *) NULL}, - { 0x1404, (char *) "MinFocalLength", (char *) NULL}, - { 0x1405, (char *) "MaxFocalLength", (char *) NULL}, - { 0x1406, (char *) "MaxApertureAtMinFocal", (char *) NULL}, - { 0x1407, (char *) "MaxApertureAtMaxFocal", (char *) NULL}, - { 0x4100, (char *) "FacesDetected", (char *) NULL}, - { 0x4103, (char *) "FacePositions", (char *) NULL}, - { 0x8000, (char *) "FileSource", (char *) NULL}, - { 0x8002, (char *) "OrderNumber", (char *) NULL}, - { 0x8003, (char *) "FrameNumber", (char *) NULL}, - { 0xB211, (char *) "Parallax", (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}, - { 0x0104, (char *) "BodyFirmwareVersion", (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}, - { 0x020B, (char *) "EpsonImageWidth", (char *) NULL}, - { 0x020C, (char *) "EpsonImageHeight", (char *) NULL}, - { 0x020D, (char *) "EpsonSoftware", (char *) NULL}, - { 0x0280, (char *) "PreviewImage", (char *) NULL}, - { 0x0300, (char *) "PreCaptureFrames", (char *) NULL}, - { 0x0301, (char *) "WhiteBoard", (char *) NULL}, - { 0x0302, (char *) "OneTouchWB", (char *) NULL}, - { 0x0303, (char *) "WhiteBalanceBracket", (char *) NULL}, - { 0x0304, (char *) "WhiteBalanceBias", (char *) NULL}, - { 0x0403, (char *) "SceneMode", (char *) NULL}, - { 0x0404, (char *) "SerialNumber", (char *) NULL}, - { 0x0405, (char *) "Firmware", (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}, - { 0x1009, (char *) "LightCondition", (char *) NULL}, - { 0x100A, (char *) "FocusRange", (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}, - { 0x1019, (char *) "ColorMatrixNumber", (char *) NULL}, - { 0x101A, (char *) "SerialNumber", (char *) NULL}, - { 0x1023, (char *) "FlashExposureComp", (char *) NULL}, - { 0x1024, (char *) "InternalFlashTable", (char *) NULL}, - { 0x1025, (char *) "ExternalFlashGValue", (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}, - { 0x1030, (char *) "SceneDetect", (char *) NULL}, - { 0x1031, (char *) "SceneArea?", (char *) NULL}, - { 0x1033, (char *) "SceneDetectData?", (char *) NULL}, - { 0x1034, (char *) "CompressionRatio", (char *) NULL}, - { 0x1035, (char *) "PreviewImageValid", (char *) NULL}, - { 0x1036, (char *) "PreviewImageStart", (char *) NULL}, - { 0x1037, (char *) "PreviewImageLength", (char *) NULL}, - { 0x1038, (char *) "AFResult", (char *) NULL}, - { 0x1039, (char *) "CCDScanMode", (char *) NULL}, - { 0x103A, (char *) "NoiseReduction", (char *) NULL}, - { 0x103B, (char *) "InfinityLensStep", (char *) NULL}, - { 0x103C, (char *) "NearLensStep", (char *) NULL}, - { 0x103D, (char *) "LightValueCenter", (char *) NULL}, - { 0x103E, (char *) "LightValuePeriphery", (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"}, - { 0x2100, (char *) "Olympus2100", (char *) "Olympus FE Tags"}, - { 0x2200, (char *) "Olympus2200", (char *) "Olympus FE Tags"}, - { 0x2300, (char *) "Olympus2300", (char *) "Olympus FE Tags"}, - { 0x2400, (char *) "Olympus2400", (char *) "Olympus FE Tags"}, - { 0x2500, (char *) "Olympus2500", (char *) "Olympus FE Tags"}, - { 0x2600, (char *) "Olympus2600", (char *) "Olympus FE Tags"}, - { 0x2700, (char *) "Olympus2700", (char *) "Olympus FE Tags"}, - { 0x2800, (char *) "Olympus2800", (char *) "Olympus FE Tags"}, - { 0x2900, (char *) "Olympus2900", (char *) "Olympus FE Tags"}, - { 0x3000, (char *) "RawInfo", (char *) "Olympus RawInfo Tags"}, - { 0x4000, (char *) "MainInfo", (char *) "Olympus MainInfo Tags"}, - { 0x0000, (char *) NULL, (char *) NULL} - }; - -/** -Minolta maker note -*/ -static TagInfo - exif_minolta_tag_table[] = - { - { 0x0000, (char *) "MakerNoteVersion", (char *) NULL}, - { 0x0001, (char *) "MinoltaCameraSettingsOld", (char *) NULL}, - { 0x0003, (char *) "MinoltaCameraSettings", (char *) NULL}, - { 0x0004, (char *) "MinoltaCameraSettings7D", (char *) NULL}, - { 0x0018, (char *) "ImageStabilization", (char *) NULL}, - { 0x0040, (char *) "CompressedImageSize", (char *) NULL}, - { 0x0081, (char *) "PreviewImage", (char *) NULL}, - { 0x0088, (char *) "PreviewImageStart", (char *) NULL}, - { 0x0089, (char *) "PreviewImageLength", (char *) NULL}, - { 0x0100, (char *) "SceneMode", (char *) NULL}, - { 0x0101, (char *) "ColorMode", (char *) NULL}, - { 0x0102, (char *) "MinoltaQuality", (char *) NULL}, - { 0x0103, (char *) "MinoltaImageSize", (char *) NULL}, - { 0x0104, (char *) "FlashExposureComp", (char *) NULL}, - { 0x0105, (char *) "Teleconverter", (char *) NULL}, - { 0x0107, (char *) "ImageStabilization", (char *) NULL}, - { 0x0109, (char *) "RawAndJpgRecording", (char *) NULL}, - { 0x010A, (char *) "ZoneMatching", (char *) NULL}, - { 0x010B, (char *) "ColorTemperature", (char *) NULL}, - { 0x010C, (char *) "LensType", (char *) NULL}, - { 0x0111, (char *) "ColorCompensationFilter", (char *) NULL}, - { 0x0112, (char *) "WhiteBalanceFineTune", (char *) NULL}, - { 0x0113, (char *) "ImageStabilization", (char *) NULL}, - { 0x0114, (char *) "MinoltaCameraSettings5D", (char *) NULL}, - { 0x0115, (char *) "WhiteBalance", (char *) NULL}, - { 0x0E00, (char *) "PrintIM", (char *) NULL}, - { 0x0F00, (char *) "MinoltaCameraSettings2", (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} - }; - -/** -Nikon type 2 maker note -*/ -static TagInfo - exif_nikon_type2_tag_table[] = - { - { 0x0001, (char *) "MakerNoteVersion", (char *) NULL}, - { 0x0002, (char *) "ISO", (char *) NULL}, - { 0x0003, (char *) "ColorMode", (char *) NULL}, - { 0x0004, (char *) "Quality", (char *) NULL}, - { 0x0005, (char *) "WhiteBalance", (char *) NULL}, - { 0x0006, (char *) "Sharpness", (char *) NULL}, - { 0x0007, (char *) "FocusMode", (char *) NULL}, - { 0x0008, (char *) "FlashSetting", (char *) NULL}, - { 0x0009, (char *) "FlashType", (char *) NULL}, - { 0x000B, (char *) "WhiteBalanceFineTune", (char *) NULL}, - { 0x000F, (char *) "ISOSelection", (char *) NULL}, - { 0x0010, (char *) "DataDump", (char *) NULL}, - { 0x0080, (char *) "ImageAdjustment", (char *) NULL}, - { 0x0082, (char *) "AuxiliaryLens", (char *) NULL}, - { 0x0085, (char *) "ManualFocusDistance", (char *) NULL}, - { 0x0086, (char *) "DigitalZoom", (char *) NULL}, - { 0x0088, (char *) "AFInfo", (char *) NULL}, - { 0x0089, (char *) "ShootingMode", (char *) NULL}, - { 0x008D, (char *) "ColorMode", (char *) NULL}, - { 0x008F, (char *) "SceneMode", (char *) NULL}, - { 0x0092, (char *) "HueAdjustment", (char *) NULL}, - { 0x0094, (char *) "Saturation", (char *) NULL}, - { 0x0095, (char *) "NoiseReduction", (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 *) "MakerNoteVersion", (char *) NULL}, - { 0x0002, (char *) "ISO", (char *) NULL}, - { 0x0003, (char *) "ColorMode", (char *) NULL}, - { 0x0004, (char *) "Quality", (char *) NULL}, - { 0x0005, (char *) "WhiteBalance", (char *) NULL}, - { 0x0006, (char *) "Sharpness", (char *) NULL}, - { 0x0007, (char *) "FocusMode", (char *) NULL}, - { 0x0008, (char *) "FlashSetting", (char *) NULL}, - { 0x0009, (char *) "FlashType", (char *) NULL}, - { 0x000B, (char *) "WhiteBalanceFineTune", (char *) NULL}, - { 0x000C, (char *) "WB_RBLevels", (char *) NULL}, - { 0x000D, (char *) "ProgramShift", (char *) NULL}, - { 0x000E, (char *) "ExposureDifference", (char *) NULL}, - { 0x000F, (char *) "ISOSelection", (char *) NULL}, - { 0x0010, (char *) "DataDump", (char *) NULL}, - { 0x0011, (char *) "PreviewIFD", (char *) NULL}, - { 0x0012, (char *) "FlashExposureComp", (char *) NULL}, - { 0x0013, (char *) "ISOSetting", (char *) NULL}, - { 0x0014, (char *) "ColorBalanceA", (char *) NULL}, - { 0x0016, (char *) "ImageBoundary", (char *) NULL}, - { 0x0017, (char *) "FlashExposureComp", (char *) NULL}, - { 0x0018, (char *) "FlashExposureBracketValue", (char *) NULL}, - { 0x0019, (char *) "ExposureBracketValue", (char *) NULL}, - { 0x001A, (char *) "ImageProcessing", (char *) NULL}, - { 0x001B, (char *) "CropHiSpeed", (char *) NULL}, - { 0x001C, (char *) "ExposureTuning", (char *) NULL}, - { 0x001D, (char *) "SerialNumber", (char *) NULL}, - { 0x001E, (char *) "ColorSpace", (char *) NULL}, - { 0x001F, (char *) "VRInfo", (char *) NULL}, - { 0x0020, (char *) "ImageAuthentication", (char *) NULL}, - { 0x0022, (char *) "ActiveD-Lighting", (char *) NULL}, - { 0x0023, (char *) "PictureControl", (char *) NULL}, - { 0x0024, (char *) "WorldTime", (char *) NULL}, - { 0x0025, (char *) "ISOInfo", (char *) NULL}, - { 0x002A, (char *) "VignetteControl", (char *) NULL}, - { 0x002B, (char *) "DistortInfo", (char *) NULL}, - { 0x0080, (char *) "ImageAdjustment", (char *) NULL}, - { 0x0081, (char *) "ToneComp", (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}, - { 0x008B, (char *) "LensFStops", (char *) NULL}, - { 0x008C, (char *) "ContrastCurve", (char *) NULL}, - { 0x008D, (char *) "ColorHue", (char *) NULL}, - { 0x008F, (char *) "SceneMode", (char *) NULL}, - { 0x0090, (char *) "LightSource", (char *) NULL}, - { 0x0091, (char *) "ShotInfo", (char *) NULL}, - { 0x0092, (char *) "HueAdjustment", (char *) NULL}, - { 0x0093, (char *) "NEFCompression", (char *) NULL}, - { 0x0094, (char *) "Saturation", (char *) NULL}, - { 0x0095, (char *) "NoiseReduction", (char *) NULL}, - { 0x0096, (char *) "LinearizationTable", (char *) NULL}, - { 0x0097, (char *) "ColorBalance", (char *) NULL}, - { 0x0098, (char *) "LensData", (char *) NULL}, - { 0x0099, (char *) "RawImageCenter", (char *) NULL}, - { 0x009A, (char *) "SensorPixelSize", (char *) NULL}, - { 0x009C, (char *) "SceneAssist", (char *) NULL}, - { 0x009E, (char *) "RetouchHistory", (char *) NULL}, - { 0x00A0, (char *) "SerialNumber", (char *) NULL}, - { 0x00A2, (char *) "ImageDataSize", (char *) NULL}, - { 0x00A5, (char *) "ImageCount", (char *) NULL}, - { 0x00A6, (char *) "DeletedImageCount", (char *) NULL}, - { 0x00A7, (char *) "ShutterCount", (char *) NULL}, - { 0x00A8, (char *) "FlashInfo", (char *) NULL}, - { 0x00A9, (char *) "ImageOptimization", (char *) NULL}, - { 0x00AA, (char *) "Saturation", (char *) NULL}, - { 0x00AB, (char *) "VariProgram", (char *) NULL}, - { 0x00AC, (char *) "ImageStabilization", (char *) NULL}, - { 0x00AD, (char *) "AFResponse", (char *) NULL}, - { 0x00B0, (char *) "MultiExposure", (char *) NULL}, - { 0x00B1, (char *) "HighISONoiseReduction", (char *) NULL}, - { 0x00B3, (char *) "ToningEffect", (char *) NULL}, - { 0x00B6, (char *) "PowerUpTime", (char *) NULL}, - { 0x00B7, (char *) "AFInfo2", (char *) NULL}, - { 0x00B8, (char *) "FileInfo", (char *) NULL}, - { 0x00B9, (char *) "AFTune", (char *) NULL}, - { 0x00BD, (char *) "PictureControl", (char *) NULL}, - { 0x0E00, (char *) "PrintIM", (char *) NULL}, - { 0x0E01, (char *) "NikonCaptureData", (char *) NULL}, - { 0x0E09, (char *) "NikonCaptureVersion", (char *) NULL}, - { 0x0E0E, (char *) "NikonCaptureOffsets", (char *) NULL}, - { 0x0E10, (char *) "NikonScanIFD", (char *) NULL}, - { 0x0E1D, (char *) "NikonICCProfile", (char *) NULL}, - { 0x0E1E, (char *) "NikonCaptureOutput", (char *) NULL}, - { 0x0E22, (char *) "NEFBitDepth", (char *) NULL}, - { 0x0000, (char *) NULL, (char *) NULL} - }; - -/** -Panasonic / Leica 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 *) "AFAreaMode", (char *) NULL}, - { 0x001A, (char *) "ImageStabilization", (char *) NULL}, - { 0x001C, (char *) "MacroMode", (char *) NULL}, - { 0x001F, (char *) "ShootingMode", (char *) NULL}, - { 0x0020, (char *) "Audio", (char *) NULL}, - { 0x0021, (char *) "DataDump", (char *) NULL}, - { 0x0022, (char *) "EasyMode", (char *) NULL}, - { 0x0023, (char *) "WhiteBalanceBias", (char *) NULL}, - { 0x0024, (char *) "FlashBias", (char *) NULL}, - { 0x0025, (char *) "InternalSerialNumber", (char *) NULL}, - { 0x0026, (char *) "PanasonicExifVersion", (char *) NULL}, - { 0x0028, (char *) "ColorEffect", (char *) NULL}, - { 0x0029, (char *) "TimeSincePowerOn", (char *) NULL}, - { 0x002A, (char *) "BurstMode", (char *) NULL}, - { 0x002B, (char *) "SequenceNumber", (char *) NULL}, - { 0x002C, (char *) "ContrastMode", (char *) NULL}, - { 0x002D, (char *) "NoiseReduction", (char *) NULL}, - { 0x002E, (char *) "SelfTimer", (char *) NULL}, - { 0x0030, (char *) "Rotation", (char *) NULL}, - { 0x0031, (char *) "AFAssistLamp", (char *) NULL}, - { 0x0032, (char *) "ColorMode", (char *) NULL}, - { 0x0033, (char *) "BabyAge_0x0033", (char *) NULL}, - { 0x0034, (char *) "OpticalZoomMode", (char *) NULL}, - { 0x0035, (char *) "ConversionLens", (char *) NULL}, - { 0x0036, (char *) "TravelDay", (char *) NULL}, - { 0x0039, (char *) "Contrast", (char *) NULL}, - { 0x003A, (char *) "WorldTimeLocation", (char *) NULL}, - { 0x003B, (char *) "TextStamp_0x003B", (char *) NULL}, - { 0x003C, (char *) "ProgramISO", (char *) NULL}, - { 0x003D, (char *) "AdvancedSceneMode", (char *) NULL}, - { 0x003E, (char *) "TextStamp_0x003E", (char *) NULL}, - { 0x003F, (char *) "FacesDetected", (char *) NULL}, - { 0x0040, (char *) "Saturation", (char *) NULL}, - { 0x0041, (char *) "Sharpness", (char *) NULL}, - { 0x0042, (char *) "FilmMode", (char *) NULL}, - { 0x0046, (char *) "WBAdjustAB", (char *) NULL}, - { 0x0047, (char *) "WBAdjustGM", (char *) NULL}, - { 0x004B, (char *) "PanasonicImageWidth", (char *) NULL}, - { 0x004C, (char *) "PanasonicImageHeight", (char *) NULL}, - { 0x004D, (char *) "AFPointPosition", (char *) NULL}, - { 0x004E, (char *) "FaceDetInfo", (char *) "Panasonic FaceDetInfo Tags"}, - { 0x0051, (char *) "LensType", (char *) NULL}, - { 0x0052, (char *) "LensSerialNumber", (char *) NULL}, - { 0x0053, (char *) "AccessoryType", (char *) NULL}, - { 0x0059, (char *) "Transform", (char *) NULL}, - { 0x005D, (char *) "IntelligentExposure", (char *) NULL}, - { 0x0061, (char *) "FaceRecInfo", (char *) "Panasonic FaceRecInfo Tags"}, - { 0x0062, (char *) "FlashWarning", (char *) NULL}, - { 0x0063, (char *) "RecognizedFaceFlags?", (char *) NULL}, - { 0x0065, (char *) "Title", (char *) NULL}, - { 0x0066, (char *) "BabyName", (char *) NULL}, - { 0x0067, (char *) "Location", (char *) NULL}, - { 0x0069, (char *) "Country", (char *) NULL}, - { 0x006B, (char *) "State", (char *) NULL}, - { 0x006D, (char *) "City", (char *) NULL}, - { 0x006F, (char *) "Landmark", (char *) NULL}, - { 0x0070, (char *) "IntelligentResolution", (char *) NULL}, - { 0x0079, (char *) "IntelligentD-Range", (char *) NULL}, - { 0x0E00, (char *) "PrintIM", (char *) NULL}, - { 0x8000, (char *) "MakerNoteVersion", (char *) NULL}, - { 0x8001, (char *) "SceneMode", (char *) NULL}, - { 0x8004, (char *) "WBRedLevel", (char *) NULL}, - { 0x8005, (char *) "WBGreenLevel", (char *) NULL}, - { 0x8006, (char *) "WBBlueLevel", (char *) NULL}, - { 0x8007, (char *) "FlashFired", (char *) NULL}, - { 0x8008, (char *) "TextStamp_0x8008", (char *) NULL}, - { 0x8009, (char *) "TextStamp_0x8009", (char *) NULL}, - { 0x8010, (char *) "BabyAge_0x8010", (char *) NULL}, - { 0x8012, (char *) "Transform", (char *) NULL}, - { 0x0000, (char *) NULL, (char *) NULL} - }; - -/** -Pentax (Asahi) maker note type 1 -*/ -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} - }; - -/** -Pentax maker note type 2 -*/ -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 *) "Pentax PentaxModelID Values"}, - { 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}, - { 0x0015, (char *) "LightReading", (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 *) "Pentax City Values"}, - { 0x0024, (char *) "DestinationCity", (char *) "Pentax City Values"}, - { 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}, - { 0x0035, (char *) "SensorSize", (char *) NULL}, - { 0x0037, (char *) "ColorSpace", (char *) NULL}, - { 0x0039, (char *) "RawImageSize", (char *) NULL}, - { 0x003C, (char *) "AFPointsInFocus", (char *) NULL}, - { 0x003E, (char *) "PreviewImageBorders", (char *) NULL}, - { 0x003F, (char *) "LensType", (char *) "Pentax LensType Values"}, - { 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 *) "Pentax SRInfo Tags"}, - { 0x005D, (char *) "ShutterCount", (char *) NULL}, - { 0x0060, (char *) "FaceInfo", (char *) "Pentax FaceInfo Tags"}, - { 0x0067, (char *) "Hue", (char *) NULL}, - { 0x0068, (char *) "AWBInfo", (char *) "Pentax AWBInfo Tags"}, - { 0x0069, (char *) "DynamicRangeExpansion", (char *) NULL}, - { 0x006B, (char *) "TimeInfo", (char *) "Pentax TimeInfo Tags"}, - { 0x006C, (char *) "HighLowKeyAdj", (char *) NULL}, - { 0x006D, (char *) "ContrastHighlight", (char *) NULL}, - { 0x006E, (char *) "ContrastShadow", (char *) NULL}, - { 0x006F, (char *) "ContrastHighlightShadowAdj", (char *) NULL}, - { 0x0070, (char *) "FineSharpness", (char *) NULL}, - { 0x0071, (char *) "HighISONoiseReduction", (char *) NULL}, - { 0x0072, (char *) "AFAdjustment", (char *) NULL}, - { 0x0073, (char *) "MonochromeFilterEffect", (char *) NULL}, - { 0x0074, (char *) "MonochromeToning", (char *) NULL}, - { 0x0076, (char *) "FaceDetect", (char *) NULL}, - { 0x0077, (char *) "FaceDetectFrameSize", (char *) NULL}, - { 0x0079, (char *) "ShadowCompensation", (char *) NULL}, - { 0x007A, (char *) "ISOAutoParameters", (char *) NULL}, - { 0x007B, (char *) "CrossProcess", (char *) NULL}, - { 0x007D, (char *) "LensCorr", (char *) "Pentax LensCorr Tags"}, - { 0x007F, (char *) "BleachBypassToning", (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 *) "Pentax CameraSettings Tags"}, - { 0x0206, (char *) "AEInfo", (char *) "Pentax AEInfo Tags"}, - { 0x0207, (char *) "LensInfo", (char *) "Pentax LensInfo Tags"}, - { 0x0208, (char *) "FlashInfo", (char *) "Pentax FlashInfo Tags"}, - { 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 *) "Pentax CameraInfo Tags"}, - { 0x0216, (char *) "BatteryInfo", (char *) "Pentax BatteryInfo Tags"}, - { 0x021B, (char *) "SaturationInfo", (char *) NULL}, - { 0x021F, (char *) "AFInfo", (char *) "Pentax AFInfo Tags"}, - { 0x0222, (char *) "ColorInfo", (char *) "Pentax ColorInfo Tags"}, - { 0x0224, (char *) "EVStepInfo", (char *) "Pentax EVStepInfo Tags"}, - { 0x0226, (char *) "ShotInfo", (char *) "Pentax ShotInfo Tags"}, - { 0x0227, (char *) "FacePos", (char *) "Pentax FacePos Tags"}, - { 0x0228, (char *) "FaceSize", (char *) "Pentax FaceSize Tags"}, - { 0x0229, (char *) "SerialNumber", (char *) NULL}, - { 0x022A, (char *) "FilterInfo", (char *) "Pentax FilterInfo Tags"}, - { 0x022B, (char *) "LevelInfo", (char *) "Pentax LevelInfo Tags"}, - { 0x022E, (char *) "Artist", (char *) NULL}, - { 0x022F, (char *) "Copyright", (char *) NULL}, - { 0x0230, (char *) "FirmwareVersion", (char *) NULL}, - { 0x0231, (char *) "ContrastDetectAFArea", (char *) NULL}, - { 0x0235, (char *) "CrossProcessParams", (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[] = - { - { 0x0102, (char *) "Quality", (char *) NULL}, - { 0x0104, (char *) "FlashExposureComp", (char *) NULL}, - { 0x0105, (char *) "Teleconverter", (char *) NULL}, - { 0x0112, (char *) "WhiteBalanceFineTune", (char *) NULL}, - { 0x0114, (char *) "CameraSettings", (char *) NULL}, - { 0x0115, (char *) "WhiteBalance", (char *) NULL}, - { 0x0E00, (char *) "PrintIM", (char *) NULL}, - { 0x1000, (char *) "MultiBurstMode", (char *) NULL}, - { 0x1001, (char *) "MultiBurstImageWidth", (char *) NULL}, - { 0x1002, (char *) "MultiBurstImageHeight", (char *) NULL}, - { 0x1003, (char *) "Panorama", (char *) NULL}, - { 0x2001, (char *) "PreviewImage", (char *) NULL}, - { 0x2004, (char *) "Contrast", (char *) NULL}, - { 0x2005, (char *) "Saturation", (char *) NULL}, - { 0x2006, (char *) "Sharpness", (char *) NULL}, - { 0x2007, (char *) "Brightness", (char *) NULL}, - { 0x2008, (char *) "LongExposureNoiseReduction", (char *) NULL}, - { 0x2009, (char *) "HighISONoiseReduction", (char *) NULL}, - { 0x200A, (char *) "HDR", (char *) NULL}, - { 0x200B, (char *) "MultiFrameNoiseReduction", (char *) NULL}, - { 0x3000, (char *) "ShotInfo", (char *) NULL}, - { 0xB000, (char *) "FileFormat", (char *) NULL}, - { 0xB001, (char *) "SonyModelID", (char *) NULL}, - { 0xB020, (char *) "ColorReproduction", (char *) NULL}, - { 0xB021, (char *) "ColorTemperature", (char *) NULL}, - { 0xB022, (char *) "ColorCompensationFilter", (char *) NULL}, - { 0xB023, (char *) "SceneMode", (char *) NULL}, - { 0xB024, (char *) "ZoneMatching", (char *) NULL}, - { 0xB025, (char *) "DynamicRangeOptimizer", (char *) NULL}, - { 0xB026, (char *) "ImageStabilization", (char *) NULL}, - { 0xB027, (char *) "LensType", (char *) NULL}, - { 0xB028, (char *) "MinoltaMakerNote", (char *) NULL}, - { 0xB029, (char *) "ColorMode", (char *) NULL}, - { 0xB02B, (char *) "FullImageSize", (char *) NULL}, - { 0xB02C, (char *) "PreviewImageSize", (char *) NULL}, - { 0xB040, (char *) "Macro", (char *) NULL}, - { 0xB041, (char *) "ExposureMode", (char *) NULL}, - { 0xB042, (char *) "FocusMode", (char *) NULL}, - { 0xB043, (char *) "AFMode", (char *) NULL}, - { 0xB044, (char *) "AFIlluminator", (char *) NULL}, - { 0xB047, (char *) "Quality2", (char *) NULL}, - { 0xB048, (char *) "FlashLevel", (char *) NULL}, - { 0xB049, (char *) "ReleaseMode", (char *) NULL}, - { 0xB04A, (char *) "SequenceNumber", (char *) NULL}, - { 0xB04B, (char *) "Anti-Blur", (char *) NULL}, - { 0xB04E, (char *) "LongExposureNoiseReduction", (char *) NULL}, - { 0xB04F, (char *) "DynamicRangeOptimizer", (char *) NULL}, - { 0xB052, (char *) "IntelligentAuto", (char *) NULL}, - { 0xB054, (char *) "WhiteBalance2", (char *) NULL}, - { 0x0000, (char *) NULL, (char *) NULL} - }; - -/** -Sigma SD1 maker note -*/ -static TagInfo - exif_sigma_sd1_tag_table[] = - { - { 0x0002, (char *) "SerialNumber", (char *) NULL}, - { 0x0003, (char *) "DriveMode", (char *) NULL}, - { 0x0004, (char *) "ResolutionMode", (char *) NULL}, - { 0x0005, (char *) "AFMode", (char *) NULL}, - { 0x0006, (char *) "FocusSetting", (char *) NULL}, - { 0x0007, (char *) "WhiteBalance", (char *) NULL}, - { 0x0008, (char *) "ExposureMode", (char *) NULL}, - { 0x0009, (char *) "MeteringMode", (char *) NULL}, - { 0x000A, (char *) "LensFocalRange", (char *) NULL}, - { 0x000B, (char *) "ColorSpace", (char *) NULL}, - { 0x000C, (char *) "ExposureCompensation", (char *) NULL}, - { 0x000D, (char *) "Contrast", (char *) NULL}, - { 0x000E, (char *) "Shadow", (char *) NULL}, - { 0x000F, (char *) "Highlight", (char *) NULL}, - { 0x0010, (char *) "Saturation", (char *) NULL}, - { 0x0011, (char *) "Sharpness", (char *) NULL}, - { 0x0012, (char *) "X3FillLight", (char *) NULL}, - { 0x0014, (char *) "ColorAdjustment", (char *) NULL}, - { 0x0015, (char *) "AdjustmentMode", (char *) NULL}, - { 0x0016, (char *) "Quality", (char *) NULL}, - { 0x0017, (char *) "Firmware", (char *) NULL}, - { 0x0018, (char *) "Software", (char *) NULL}, - { 0x0019, (char *) "AutoBracket", (char *) NULL}, - { 0x001A, (char *) "ChrominanceNoiseReduction", (char *) NULL}, - { 0x001B, (char *) "LuminanceNoiseReduction", (char *) NULL}, - { 0x001C, (char *) "PreviewImageStart", (char *) NULL}, - { 0x001D, (char *) "PreviewImageLength", (char *) NULL}, - { 0x001F, (char *) "MakerNoteVersion", (char *) NULL}, - { 0x0026, (char *) "FileFormat", (char *) NULL}, - { 0x002C, (char *) "ColorMode", (char *) NULL}, - { 0x0030, (char *) "Calibration", (char *) NULL}, - { 0x0048, (char *) "LensApertureRange", (char *) NULL}, - { 0x0049, (char *) "FNumber", (char *) NULL}, - { 0x004A, (char *) "ExposureTime", (char *) NULL}, - { 0x004B, (char *) "ExposureTime2", (char *) NULL}, - { 0x004D, (char *) "ExposureCompensation_SD1", (char *) NULL}, - { 0x0055, (char *) "SensorTemperature", (char *) NULL}, - { 0x0056, (char *) "FlashExposureComp", (char *) NULL}, - { 0x0057, (char *) "Firmware_SD1", (char *) NULL}, - { 0x0058, (char *) "WhiteBalance", (char *) NULL}, - { 0x0000, (char *) NULL, (char *) NULL} - }; - -/** -Sigma / Foveon maker note (others than SD1 models) -NB: many tags are not consistent between different models -*/ -static TagInfo - exif_sigma_foveon_tag_table[] = - { - { 0x0002, (char *) "SerialNumber", (char *) NULL}, - { 0x0003, (char *) "DriveMode", (char *) NULL}, - { 0x0004, (char *) "ResolutionMode", (char *) NULL}, - { 0x0005, (char *) "AFMode", (char *) NULL}, - { 0x0006, (char *) "FocusSetting", (char *) NULL}, - { 0x0007, (char *) "WhiteBalance", (char *) NULL}, - { 0x0008, (char *) "ExposureMode", (char *) NULL}, - { 0x0009, (char *) "MeteringMode", (char *) NULL}, - { 0x000A, (char *) "LensFocalRange", (char *) NULL}, - { 0x000B, (char *) "ColorSpace", (char *) NULL}, - { 0x000C, (char *) "ExposureCompensation", (char *) NULL}, - { 0x000D, (char *) "Contrast", (char *) NULL}, - { 0x000E, (char *) "Shadow", (char *) NULL}, - { 0x000F, (char *) "Highlight", (char *) NULL}, - { 0x0010, (char *) "Saturation", (char *) NULL}, - { 0x0011, (char *) "Sharpness", (char *) NULL}, - { 0x0012, (char *) "X3FillLight", (char *) NULL}, - { 0x0014, (char *) "ColorAdjustment", (char *) NULL}, - { 0x0015, (char *) "AdjustmentMode", (char *) NULL}, - { 0x0016, (char *) "Quality", (char *) NULL}, - { 0x0017, (char *) "Firmware", (char *) NULL}, - { 0x0018, (char *) "Software", (char *) NULL}, - { 0x0019, (char *) "AutoBracket", (char *) NULL}, - { 0x001A, (char *) "PreviewImageStart", (char *) NULL}, - { 0x001B, (char *) "PreviewImageLength", (char *) NULL}, - { 0x001C, (char *) "PreviewImageSize", (char *) NULL}, - { 0x001D, (char *) "MakerNoteVersion", (char *) NULL}, - { 0x001F, (char *) "AFPoint", (char *) NULL}, - { 0x0022, (char *) "FileFormat", (char *) NULL}, - { 0x0024, (char *) "Calibration", (char *) NULL}, - { 0x002C, (char *) "ColorMode", (char *) NULL}, - { 0x0030, (char *) "LensApertureRange", (char *) NULL}, - { 0x0031, (char *) "FNumber", (char *) NULL}, - { 0x0032, (char *) "ExposureTime", (char *) NULL}, - { 0x0033, (char *) "ExposureTime2", (char *) NULL}, - { 0x0034, (char *) "BurstShot", (char *) NULL}, - { 0x0035, (char *) "ExposureCompensation", (char *) NULL}, - { 0x0039, (char *) "SensorTemperature", (char *) NULL}, - { 0x003A, (char *) "FlashExposureComp", (char *) NULL}, - { 0x003B, (char *) "Firmware", (char *) NULL}, - { 0x003C, (char *) "WhiteBalance", (char *) NULL}, - { 0x003D, (char *) "PictureMode", (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); - addMetadataModel(TagLib::EXIF_MAKERNOTE_SIGMA_SD1, exif_sigma_sd1_tag_table); - addMetadataModel(TagLib::EXIF_MAKERNOTE_SIGMA_FOVEON, exif_sigma_foveon_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 - if ((_table_map.find(md_model) == _table_map.end()) && (tag_table != NULL)) { - - // add the tag description table - TAGINFO *info_map = new(std::nothrow) TAGINFO(); - if (!info_map) return FALSE; - - 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) { - - if(_table_map.find(md_model) != _table_map.end()) { - - TAGINFO *info_map = (TAGINFO*)_table_map[md_model]; - if(info_map->find(tagID) != info_map->end()) { - 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) { - - if(_table_map.find(md_model) != _table_map.end()) { - - TAGINFO *info_map = (TAGINFO*)_table_map[md_model]; - 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: - case EXIF_MAKERNOTE_SIGMA_SD1: - case EXIF_MAKERNOTE_SIGMA_FOVEON: - 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/plugins/FreeImage/Source/Metadata/XTIFF.cpp b/plugins/FreeImage/Source/Metadata/XTIFF.cpp deleted file mode 100644 index bc63cf38b2..0000000000 --- a/plugins/FreeImage/Source/Metadata/XTIFF.cpp +++ /dev/null @@ -1,661 +0,0 @@ -// ========================================================== -// Metadata functions implementation -// Extended TIFF Directory GEO Tag Support -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Thorsten Radde (support@IdealSoftware.com) -// - Berend Engelbrecht (softwarecave@users.sourceforge.net) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// 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 "../LibTIFF4/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, ¶ms)) { - // 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(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 & writing -// ---------------------------------------------------------- - -/** -Read a single exif tag -*/ -static BOOL -tiff_read_exif_tag(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib, TagLib& tagLib, TIFFDirectory *td, uint32 tag) { - const TIFFField *fip; - uint32 value_count; - int mem_alloc = 0; - void *raw_data = NULL; - - if(tag == TIFFTAG_EXIFIFD) { - return TRUE; - } - - // get the tag key - use NULL to avoid reading GeoTIFF tags - const char *key = tagLib.getTagFieldName(md_model, (WORD)tag, NULL); - if(key == NULL) { - return TRUE; - } - - fip = TIFFFieldWithTag(tif, tag); - if(fip == NULL) { - return TRUE; - } - - if(fip->field_passcount) { //<- "passcount" means "returns count" - if (fip->field_readcount != TIFF_VARIABLE2) { //<- TIFF_VARIABLE2 means "uses LONG count" - - // assume TIFF_VARIABLE (uses SHORT count) - uint16 value_count16; - if(TIFFGetField(tif, tag, &value_count16, &raw_data) != 1) { - return TRUE; - } - value_count = value_count16; - } else { - if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) { - return TRUE; - } - } - } else { - - // determine count - - 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; - } - - // access fields as pointers to data - // (### determining this is NOT robust... and hardly can be. It is implemented looking the _TIFFVGetField code) - - if(fip->field_tag == TIFFTAG_TRANSFERFUNCTION) { - // reading this tag cause a bug probably located somewhere inside libtiff - return TRUE; - } - - 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 - - && fip->field_tag != TIFFTAG_BITSPERSAMPLE //<- these two are tricky - - && fip->field_tag != TIFFTAG_COMPRESSION //<- they are defined as TIFF_VARIABLE but in reality return a single value - ) { - if(TIFFGetField(tif, tag, &raw_data) != 1) { - return TRUE; - } - } else { - - // access fields as values - - const int value_size = _TIFFDataSize(fip->field_type); - raw_data = _TIFFmalloc(value_size * value_count); - mem_alloc = 1; - int ok = FALSE; - - // ### if value_count > 1, tag is PAGENUMBER or HALFTONEHINTS or YCBCRSUBSAMPLING or DOTRANGE, - // all off which are value_count == 2 (see tif_dirinfo.c) - switch(value_count) - { - case 1: - ok = TIFFGetField(tif, tag, raw_data); - break; - case 2: - ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1); - break; -/* # we might need more in the future: - case 3: - ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1, (BYTE*)(raw_data) + value_size*2); - break; -*/ - default: - FreeImage_OutputMessageProc(FIF_TIFF, "Unimplemented variable number of parameters for Tiff Tag %s", fip->field_name); - break; - } - if(ok != 1) { - _TIFFfree(raw_data); - return TRUE; - } - } - } - - // build FreeImage tag from Tiff Tag data we collected - - 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; - - case TIFF_LONG8: // BigTIFF 64-bit unsigned integer - FreeImage_SetTagType(fitag, FIDT_LONG8); - FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); - FreeImage_SetTagCount(fitag, value_count); - FreeImage_SetTagValue(fitag, raw_data); - break; - - case TIFF_IFD8: // BigTIFF 64-bit unsigned integer (offset) - FreeImage_SetTagType(fitag, FIDT_IFD8); - FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); - FreeImage_SetTagCount(fitag, value_count); - FreeImage_SetTagValue(fitag, raw_data); - break; - - case TIFF_SLONG8: // BigTIFF 64-bit signed integer - FreeImage_SetTagType(fitag, FIDT_SLONG8); - 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; -} - -/** -Read all known exif tags -*/ -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++) { - uint32 tag = TIFFGetTagListEntry(tif, i); - // read the tag - if (!tiff_read_exif_tag(tif, md_model, dib, tagLib, td, tag)) - return FALSE; - } - - // we want to know values of standard tags too!! - - // loop over all Core Directory Tags - // ### uses private data, but there is no other way - if(md_model == TagLib::EXIF_MAIN) { - - uint32 lastTag = 0; //<- used to prevent reading some tags twice (as stored in tif_fieldinfo) - - for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) { - const TIFFField *fld = tif->tif_fields[fi]; - - if(fld->field_tag == lastTag) - continue; - - // test if tag value is set - // (lifted directly form LibTiff _TIFFWriteDirectory) - - if ( fld->field_bit == FIELD_CUSTOM ) { - int ci, is_set = FALSE; - - for ( ci = 0; ci < td->td_customValueCount; ci++ ) { - is_set |= (td->td_customValues[ci].info == fld); - } - - if ( !is_set ) { - continue; - } - - } else if (!TIFFFieldSet(tif, fld->field_bit)) { - continue; - } - - // process *all* other tags (some will be ignored) - - tiff_read_exif_tag(tif, md_model, dib, tagLib, td, fld->field_tag); - - - lastTag = fld->field_tag; - } - - } - - return TRUE; - -} - - -/** -Skip tags that are already handled by the LibTIFF writing process -*/ -static BOOL -skip_write_field(TIFF* tif, uint32 tag) { - switch (tag) { - case TIFFTAG_SAMPLEFORMAT: - case TIFFTAG_IMAGEWIDTH: - case TIFFTAG_IMAGELENGTH: - case TIFFTAG_SAMPLESPERPIXEL: - case TIFFTAG_BITSPERSAMPLE: - case TIFFTAG_PHOTOMETRIC: - case TIFFTAG_PLANARCONFIG: - case TIFFTAG_ROWSPERSTRIP: - case TIFFTAG_RESOLUTIONUNIT: - case TIFFTAG_XRESOLUTION: - case TIFFTAG_YRESOLUTION: - case TIFFTAG_SUBFILETYPE: - case TIFFTAG_PAGENUMBER: - case TIFFTAG_COLORMAP: - case TIFFTAG_ORIENTATION: - case TIFFTAG_COMPRESSION: - case TIFFTAG_PREDICTOR: - case TIFFTAG_GROUP3OPTIONS: - case TIFFTAG_FILLORDER: - // skip always, values have been set in SaveOneTIFF() - return TRUE; - break; - - case TIFFTAG_RICHTIFFIPTC: - // skip always, IPTC metadata model is set in tiff_write_iptc_profile() - return TRUE; - break; - - case TIFFTAG_YCBCRCOEFFICIENTS: - case TIFFTAG_REFERENCEBLACKWHITE: - case TIFFTAG_YCBCRSUBSAMPLING: - // skip as they cannot be filled yet - return TRUE; - break; - - case TIFFTAG_PAGENAME: - { - char *value = NULL; - TIFFGetField(tif, TIFFTAG_PAGENAME, &value); - // only skip if no value has been set - if(value == NULL) { - return FALSE; - } else { - return TRUE; - } - } - default: - return FALSE; - break; - } -} - -/** -Write all known exif tags -*/ -BOOL -tiff_write_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) { - char defaultKey[16]; - - // only EXIF_MAIN so far - if(md_model != TagLib::EXIF_MAIN) { - return FALSE; - } - - if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib) == 0) { - return FALSE; - } - - TagLib& tag_lib = TagLib::instance(); - - for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) { - const TIFFField *fld = tif->tif_fields[fi]; - - if(skip_write_field(tif, fld->field_tag)) { - // skip tags that are already handled by the LibTIFF writing process - continue; - } - - FITAG *tag = NULL; - // get the tag key - const char *key = tag_lib.getTagFieldName(TagLib::EXIF_MAIN, (WORD)fld->field_tag, defaultKey); - - if(FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, key, &tag)) { - FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag); - TIFFDataType tif_tag_type = fld->field_type; - - // check for identical formats - - // (enum value are the sames between FREE_IMAGE_MDTYPE and TIFFDataType types) - if ((int)tif_tag_type != (int)tag_type) { - // skip tag or _TIFFmemcpy will fail - continue; - } - // type of storage may differ (e.g. rationnal array vs float array type) - if(_TIFFDataSize(tif_tag_type) != FreeImage_TagDataWidth(tag_type)) { - // skip tag or _TIFFmemcpy will fail - continue; - } - - if(tag_type == FIDT_ASCII) { - TIFFSetField(tif, fld->field_tag, FreeImage_GetTagValue(tag)); - } else { - TIFFSetField(tif, fld->field_tag, FreeImage_GetTagCount(tag), FreeImage_GetTagValue(tag)); - } - } - } - - return TRUE; -} diff --git a/plugins/FreeImage/Source/Plugin.h b/plugins/FreeImage/Source/Plugin.h deleted file mode 100644 index dbb4540ef5..0000000000 --- a/plugins/FreeImage/Source/Plugin.h +++ /dev/null @@ -1,142 +0,0 @@ -// ========================================================== -// 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" - -// ========================================================== - -struct Plugin; - -// ===================================================================== -// Plugin Node -// ===================================================================== - -FI_STRUCT (PluginNode) { - /** FREE_IMAGE_FORMAT attached to this plugin */ - int m_id; - /** Handle to a user plugin DLL (NULL for standard plugins) */ - void *m_instance; - /** The actual plugin, holding the function pointers */ - Plugin *m_plugin; - /** Enable/Disable switch */ - BOOL m_enabled; - - /** Unique format string for the plugin */ - const char *m_format; - /** Description string for the plugin */ - const char *m_description; - /** Comma separated list of file extensions indicating what files this plugin can open */ - const char *m_extension; - /** optional regular expression to help software identifying a bitmap type */ - 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 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); -void DLL_CALLCONV InitEXR(Plugin *plugin, int format_id); -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); -void DLL_CALLCONV InitJNG(Plugin *plugin, int format_id); - -#endif //!PLUGIN_H diff --git a/plugins/FreeImage/Source/Quantizers.h b/plugins/FreeImage/Source/Quantizers.h deleted file mode 100644 index 2a671fad1c..0000000000 --- a/plugins/FreeImage/Source/Quantizers.h +++ /dev/null @@ -1,225 +0,0 @@ -// ============================================================= -// Quantizer objects and functions -// -// 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 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/plugins/FreeImage/Source/ToneMapping.h b/plugins/FreeImage/Source/ToneMapping.h deleted file mode 100644 index 0519933c68..0000000000 --- a/plugins/FreeImage/Source/ToneMapping.h +++ /dev/null @@ -1,44 +0,0 @@ -// ========================================================== -// 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/plugins/FreeImage/Source/Utilities.h b/plugins/FreeImage/Source/Utilities.h deleted file mode 100644 index b743325129..0000000000 --- a/plugins/FreeImage/Source/Utilities.h +++ /dev/null @@ -1,484 +0,0 @@ -// ========================================================== -// Utility functions -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon -// - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// ========================================================== -// 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); - -#if defined(__cplusplus) -extern "C" { -#endif - -/** -Allocate a FIBITMAP with possibly no pixel data -(i.e. only header data and some or all metadata) -@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP -@param type Image type -@param width -@param height -@param bpp -@param red_mask -@param green_mask -@param blue_mask -@see FreeImage_AllocateT -*/ -DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeaderT(BOOL header_only, 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)); - -/** -Allocate a FIBITMAP of type FIT_BITMAP, with possibly no pixel data -(i.e. only header data and some or all metadata) -@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP -@param width -@param height -@param bpp -@param red_mask -@param green_mask -@param blue_mask -@see FreeImage_Allocate -*/ -DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeader(BOOL header_only, int width, int height, int bpp, unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0)); - -#if defined(__cplusplus) -} -#endif - - -// ========================================================== -// 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 - -// ========================================================== -// Template utility functions -// ========================================================== - -/// Max function -template T MAX(const T &a, const T &b) { - return (a > b) ? a: b; -} - -/// Min function -template T MIN(const T &a, const T &b) { - return (a < b) ? a: b; -} - -/// INPLACESWAP adopted from codeguru.com -template void INPLACESWAP(T& a, T& b) { - a ^= b; b ^= a; a ^= b; -} - -/// Clamp function -template T CLAMP(const T &value, const T &min_value, const T &max_value) { - return ((value < min_value) ? min_value : (value > max_value) ? max_value : value); -} - -/** 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 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; - } - } -} - -// ========================================================== -// 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 unsigned -CalculateLine(unsigned width, unsigned bitdepth) { - return (unsigned)( ((unsigned __int64)width * bitdepth + 7) / 8 ); -} - -inline unsigned -CalculatePitch(unsigned line) { - return line + 3 & ~3; -} - -inline unsigned -CalculateUsedPaletteEntries(unsigned 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)); -} - -// ---------------------------------------------------------- - -/** -Fast generic assign (faster than for loop) -@param dst Destination pixel -@param src Source pixel -@param bytesperpixel # of bytes per pixel -*/ -inline void -AssignPixel(BYTE* dst, const BYTE* src, unsigned bytesperpixel) { - switch (bytesperpixel) { - case 1: // FIT_BITMAP (8-bit) - *dst = *src; - break; - - case 2: // FIT_UINT16 / FIT_INT16 / 16-bit - *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); - break; - - case 3: // FIT_BITMAP (24-bit) - *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); - dst[2] = src[2]; - break; - - case 4: // FIT_BITMAP (32-bit) / FIT_UINT32 / FIT_INT32 / FIT_FLOAT - *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); - break; - - case 6: // FIT_RGB16 (3 x 16-bit) - *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); - *(reinterpret_cast(dst + 4)) = *(reinterpret_cast (src + 4)); - break; - - // the rest can be speeded up with int64 - - case 8: // FIT_RGBA16 (4 x 16-bit) - *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); - *(reinterpret_cast(dst + 4)) = *(reinterpret_cast (src + 4)); - break; - - case 12: // FIT_RGBF (3 x 32-bit IEEE floating point) - *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); - *(reinterpret_cast(dst + 4)) = *(reinterpret_cast (src + 4)); - *(reinterpret_cast(dst + 8)) = *(reinterpret_cast (src + 8)); - break; - - case 16: // FIT_RGBAF (4 x 32-bit IEEE floating point) - *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); - *(reinterpret_cast(dst + 4)) = *(reinterpret_cast (src + 4)); - *(reinterpret_cast(dst + 8)) = *(reinterpret_cast (src + 8)); - *(reinterpret_cast(dst + 12)) = *(reinterpret_cast (src + 12)); - break; - - default: - assert(FALSE); - } -} - -/** -Swap red and blue channels in a 24- or 32-bit dib. -@return Returns TRUE if successful, returns FALSE otherwise -@see See definition in Conversion.cpp -*/ -BOOL SwapRedBlue32(FIBITMAP* dib); - -/** -Inplace convert CMYK to RGBA.(8- and 16-bit). -Alpha is filled with the first extra channel if any or white otherwise. -@return Returns TRUE if successful, returns FALSE otherwise -@see See definition in Conversion.cpp -*/ -BOOL ConvertCMYKtoRGBA(FIBITMAP* dib); - -/** -Inplace convert CIELab to RGBA (8- and 16-bit). -@return Returns TRUE if successful, returns FALSE otherwise -@see See definition in Conversion.cpp -*/ -BOOL ConvertLABtoRGB(FIBITMAP* dib); - -/** -RGBA to RGB conversion -@see See definition in Conversion.cpp -*/ -FIBITMAP* RemoveAlphaChannel(FIBITMAP* dib); - - -// ========================================================== -// 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 -// ========================================================== - -/** -Extract the luminance channel L from a RGBF image. -Luminance is calculated from the sRGB model using a D65 white point, using the Rec.709 formula : -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 -*/ -#define LUMA_REC709(r, g, b) (0.2126F * r + 0.7152F * g + 0.0722F * b) - -#define GREY(r, g, b) (BYTE)LUMA_REC709(r, g, b) -/* -#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; \ - } - -// ========================================================== -// Generic error messages -// ========================================================== - -static const char *FI_MSG_ERROR_MEMORY = "Memory allocation failed"; -static const char *FI_MSG_ERROR_DIB_MEMORY = "DIB allocation failed, maybe caused by an invalid image size or by a lack of memory"; -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"; -static const char *FI_MSG_WARNING_INVALID_THUMBNAIL = "Warning: attached thumbnail cannot be written to output file (invalid format) - Thumbnail saving aborted"; - -#endif // UTILITIES_H diff --git a/plugins/FreeImage/Source/Zlib/zconf.h b/plugins/FreeImage/Source/Zlib/zconf.h deleted file mode 100644 index 93c1bb27e3..0000000000 --- a/plugins/FreeImage/Source/Zlib/zconf.h +++ /dev/null @@ -1,468 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2011 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: zconf.h,v 1.8 2012/02/05 18:10:25 drolon Exp $ */ - -#ifndef ZCONF_H -#define ZCONF_H -/* #undef Z_PREFIX */ -/* #undef Z_HAVE_UNISTD_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. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ -# define Z_PREFIX_SET - -/* all linked symbols */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# ifndef Z_SOLO -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# endif -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePending z_deflatePending -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateResetKeep z_deflateResetKeep -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# ifndef Z_SOLO -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflags z_gzflags -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgetc_ z_gzgetc_ -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite -# endif -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetHeader z_inflateGetHeader -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# ifndef Z_SOLO -# define uncompress z_uncompress -# endif -# define zError z_zError -# ifndef Z_SOLO -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# endif -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# ifndef Z_SOLO -# define gzFile z_gzFile -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# endif -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# ifndef Z_SOLO -# define gz_header_s z_gz_header_s -# endif -# define internal_state z_internal_state - -#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 - -#if defined(ZLIB_CONST) && !defined(z_const) -# define z_const const -#else -# define z_const -#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 - -#ifndef Z_ARG /* function prototypes for stdarg */ -# if defined(STDC) || defined(Z_HAVE_STDARG_H) -# define Z_ARG(args) args -# else -# define Z_ARG(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 - /* 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 /*#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_STDARG_H -#endif - -#ifdef STDC -# ifndef Z_SOLO -# include /* for off_t */ -# endif -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 -# define Z_LARGE -#endif - -#if (defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)) && !defined(Z_SOLO) -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -#endif - -#if !defined(SEEK_SET) && !defined(Z_SOLO) -# 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(_WIN32) && (defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0) -# define z_off64_t off64_t -#else -# if defined(_WIN32) -# define z_off64_t __int64 -# else -# define z_off64_t z_off_t -#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/plugins/FreeImage/Source/Zlib/zlib.h b/plugins/FreeImage/Source/Zlib/zlib.h deleted file mode 100644 index 79142d1172..0000000000 --- a/plugins/FreeImage/Source/Zlib/zlib.h +++ /dev/null @@ -1,1732 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.6, January 29th, 2012 - - Copyright (C) 1995-2012 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://tools.ietf.org/html/rfc1950 - (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.6" -#define ZLIB_VERNUM 0x1260 -#define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 6 -#define ZLIB_VER_SUBREVISION 0 - -/* - 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, - 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 { - z_const Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total number 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 number of bytes output so far */ - - z_const 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 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -#define Z_TREES 6 -/* 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, or - 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 accumulate 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. This - completes the current deflate block and follows it with an empty stored block - that is three bits plus filler bits to the next byte, followed by four bytes - (00 00 ff ff). - - If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the - output buffer, but the output is not aligned to a byte boundary. All of the - input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. - This completes the current deflate block and follows it with an empty fixed - codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. - - If flush is set to Z_BLOCK, a deflate block is completed and emitted, as - for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to - seven bits of the current block are held to be written as the next byte after - the next deflate block is completed. In this case, the decompressor may not - be provided enough bits at this point in order to complete decompression of - the data provided so far to the compressor. It may need to wait for the next - block to be emitted. This is for advanced applications that need to control - the emission of deflate blocks. - - 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). Then deflate is guaranteed to - return Z_STREAM_END. If not enough output space is provided, deflate will - not return Z_STREAM_END, and 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 Z_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, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. -*/ - - -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, - Z_BLOCK, or Z_TREES. 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. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - 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 not required to perform an - inflation in one step. However it may be used to inform inflate that a - faster approach can be used for the single inflate() call. Z_FINISH also - informs inflate to not maintain a sliding window if the stream completes, - which reduces inflate's memory footprint. - - 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 effects of the flush parameter in this implementation are - on the return value of inflate() as noted below, when inflate() returns early - when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of - memory for a sliding window when Z_FINISH is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the Adler-32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the Adler-32 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() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). 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. When processing - gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - producted so far. The CRC-32 is checked against the gzip 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 - next_in or next_out was Z_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_STRATEGY 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 any parameter is invalid (such as an invalid - method), or 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. 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. When using the zlib format, this - function must be called immediately after deflateInit, deflateInit2 or - deflateReset, and before any call of deflate. When doing raw deflate, this - function must be called either before any call of deflate, or immediately - after the completion of a deflate block, i.e. after all input has been - consumed and all output has been delivered when using any of the flush - options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. 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 - provided in deflateInit or deflateInit2. 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 (e.g. dictionary being Z_NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if not at a block boundary for raw deflate). 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 Z_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 Z_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(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). If that first deflate() call is provided the - sourceLen input bytes, an output buffer allocated to the size returned by - deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed - to return Z_STREAM_END. Note that it is possible for the compressed size to - be larger than the value returned by deflateBound() if flush options other - than Z_FINISH or Z_NO_FLUSH are used. -*/ - -ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, - unsigned *pending, - int *bits)); -/* - deflatePending() returns the number of bytes and bits of output that have - been generated, but not yet provided in the available output. The bytes not - provided would be due to the available output space having being consumed. - The number of bits of output not provided are between 0 and 7, where they - await more bits to join them in order to fill out a full byte. If pending - or bits are Z_NULL, then those values are not set. - - deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. - */ - -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, Z_BUF_ERROR if there was not enough - room in the internal buffer to insert the bits, 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 zero to request that inflate use the window size in - the zlib header of the compressed stream. - - 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_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -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 at any - time to set the dictionary. If the provided dictionary is smaller than the - window and there is already data in the window, then the provided dictionary - will amend what's there. 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 (e.g. dictionary being Z_NULL) 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 possible full flush point (see above - for the description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync searches for a 00 00 FF FF pattern in the compressed data. - All full flush points have this pattern, but not all occurences of this - pattern are full flush points. - - inflateSync returns Z_OK if a possible 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 Z_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 Z_NULL). -*/ - -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL), or if - the windowBits parameter is invalid. -*/ - -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. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above or -1 << 16 if the provided - 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 or Z_TREES 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 parameters 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_in 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) - */ - -#ifndef Z_SOLO - - /* 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 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. - - 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 uncompressed buffer. - - 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. In - the case where there is not enough room, uncompress() will fill the output - buffer with the uncompressed data up to that point. -*/ - - /* gzip file access functions */ - -/* - This library 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. -*/ - -typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ - -/* -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", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) 'T' will - request transparent writing or appending with no compression and not using - the gzip format. - - "a" can be used instead of "w" to request that the gzip stream that will - be written be appended to the file. "+" will result in an error, since - reading and writing to the same gzip file is not supported. - - These functions, as well as gzip, will read and decode a sequence of gzip - streams in a file. The append function of gzopen() can be used to create - such a file. (Also see gzflush() for another way to do this.) When - appending, gzopen does not test whether the file begins with a gzip stream, - nor does it look for the end of the gzip streams to begin appending. gzopen - will simply append a gzip stream to the existing file. - - 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. When - reading, this will be detected automatically by looking for the magic two- - byte gzip header. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -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 (if 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 fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. If you are using fileno() to get the - file descriptor from a FILE *, then you will have to use dup() to avoid - double-close()ing the file descriptor. Both gzclose() and fclose() will - close the associated file descriptor, so they need to have different file - descriptors. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); -/* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -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 is not in gzip format, gzread copies the given number of - bytes into the buffer directly from the file. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream. Any number of gzip streams may be - concatenated in the input file, and will all be decompressed by gzread(). - If something other than a gzip stream is encountered after a gzip stream, - that remaining trailing garbage is ignored (and no error is returned). - - gzread can be used to read a gzip file that is being concurrently written. - Upon reaching the end of the input, gzread will return with the available - data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then - gzclearerr can be used to clear the end of file indicator in order to permit - gzread to be tried again. Z_OK indicates that a gzip stream was completed - on the last gzread. Z_BUF_ERROR indicates that the input file ended in the - middle of a gzip stream. Note that gzread does not return -1 in the event - of an incomplete gzip stream. This error is deferred until gzclose(), which - will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip - stream. Alternatively, gzerror can be used before gzclose to detect this - case. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -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 written or 0 in case of - error. -*/ - -ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will 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. This can be determined using - zlibCompileFlags(). -*/ - -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. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -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. This is implemented as a macro for speed. - As such, it does not do all of the checking the other functions do. I.e. - it does not check to see if file is NULL, nor whether the structure file - points to has been clobbered or not. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - 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 is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -/* -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, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); - - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). - - When writing, gzdirect() returns true (1) if transparent writing was - requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: - gzdirect() is not needed when writing. Transparent writing must be - explicitly requested, so the application already knows the answer. When - linking statically, using gzdirect() will include all of the zlib code for - gzip file reading and decompression, which may not be desired.) -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the - last read ended in the middle of a gzip stream, or Z_OK on success. -*/ - -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -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. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -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. -*/ - -#endif /* !Z_SOLO */ - - /* 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 Z_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. Note - that the z_off_t type (like off_t) is a signed integer. If len2 is - negative, the result has no meaning or utility. -*/ - -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 Z_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, (int)sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) - -#ifndef Z_SOLO - -/* gzgetc() macro and its supporting function and exposed data structure. Note - * that the real internal state is much larger than the exposed structure. - * This abbreviated structure exposes just enough for the gzgetc() macro. The - * user should not mess with these exposed elements, since their names or - * behavior could change in the future, perhaps even capriciously. They can - * only be used by the gzgetc() macro. You have been warned. - */ -struct gzFile_s { - unsigned have; - unsigned char *next; - z_off64_t pos; -}; -ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); -#define gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc_(g)) - -/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or - * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if - * both are true, the application gets the *64 functions, and the regular - * functions are changed to 64 bits) -- in case these are set on systems - * without large file support, _LFS64_LARGEFILE must also be true - */ -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); -#endif - -#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 -# ifdef Z_PREFIX_SET -# define z_gzopen z_gzopen64 -# define z_gzseek z_gzseek64 -# define z_gztell z_gztell64 -# define z_gzoffset z_gzoffset64 -# define z_adler32_combine z_adler32_combine64 -# define z_crc32_combine z_crc32_combine64 -# else -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# endif -# ifndef _LARGEFILE64_SOURCE - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -# endif -#else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); -#endif - -#else /* Z_SOLO */ - - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - -#endif /* !Z_SOLO */ - -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - -/* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); -ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); -ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); -#ifndef Z_SOLO - ZEXTERN unsigned long ZEXPORT gzflags OF((void)); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/plugins/FreeImage/Source/Zlib/zutil.h b/plugins/FreeImage/Source/Zlib/zutil.h deleted file mode 100644 index 8f33fd3e7d..0000000000 --- a/plugins/FreeImage/Source/Zlib/zutil.h +++ /dev/null @@ -1,248 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2011 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.8 2012/02/05 18:10:25 drolon Exp $ */ - -#ifndef ZUTIL_H -#define ZUTIL_H - -#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) -# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define ZLIB_INTERNAL -#endif - -#include "zlib.h" - -#if defined(STDC) && !defined(Z_SOLO) -# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) -# include -# endif -# include -# include -#endif - -#ifdef Z_SOLO - typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ -#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 -# ifndef Z_SOLO -# 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 -# endif -# else /* MSC or DJGPP */ -# include -# endif -# 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 -# if defined(M_I86) && !defined(Z_SOLO) -# include -# endif -#endif - -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 -# ifndef Z_SOLO -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# 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)) && !defined __INTERIX -# 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 - -#if defined(__BORLANDC__) && !defined(MSDOS) - #pragma warn -8004 - #pragma warn -8008 - #pragma warn -8066 -#endif - -/* provide prototypes for these when building zlib without LFS */ -#if !defined(_WIN32) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -#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(pyr) || defined(Z_SOLO) -# 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 - void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef DEBUG -# include - extern int ZLIB_INTERNAL z_verbose; - extern void ZLIB_INTERNAL 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 - -#ifndef Z_SOLO - voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); - void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); -#endif - -#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/plugins/FreeImage/freeimage-translation.txt b/plugins/FreeImage/freeimage-translation.txt deleted file mode 100644 index 52329c17db..0000000000 --- a/plugins/FreeImage/freeimage-translation.txt +++ /dev/null @@ -1,2 +0,0 @@ -; Common strings that belong to many files -;[] diff --git a/plugins/FreeImage/res/FreeImage.rc b/plugins/FreeImage/res/FreeImage.rc new file mode 100644 index 0000000000..28b78c7627 --- /dev/null +++ b/plugins/FreeImage/res/FreeImage.rc @@ -0,0 +1,103 @@ +// Microsoft Visual C++ generated resource script. +// + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPENSUBCLASS, DIALOG + BEGIN + RIGHTMARGIN, 208 + TOPMARGIN, 7 + END + + IDD_AVATAROPTIONS, DIALOG + BEGIN + RIGHTMARGIN, 207 + BOTTOMMARGIN, 211 + END + + IDD_USER_AVATAR, DIALOG + BEGIN + LEFTMARGIN, 3 + RIGHTMARGIN, 218 + TOPMARGIN, 4 + BOTTOMMARGIN, 148 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// German (Germany) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "\r\n" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" +END + +#endif // APSTUDIO_INVOKED + +#endif // German (Germany) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/FreeImage/res/Version.rc b/plugins/FreeImage/res/Version.rc new file mode 100644 index 0000000000..d741488c4f --- /dev/null +++ b/plugins/FreeImage/res/Version.rc @@ -0,0 +1,42 @@ +// Microsoft Visual C++ generated resource script. +// +#ifdef APSTUDIO_INVOKED +#error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + +#include "afxres.h" +#include "..\src\version.h" + +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#endif //_WIN32 + +VS_VERSION_INFO VERSIONINFO + FILEVERSION __FILEVERSION_STRING + PRODUCTVERSION __FILEVERSION_STRING + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "FileDescription", __DESCRIPTION + VALUE "InternalName", __PLUGIN_NAME + VALUE "LegalCopyright", __COPYRIGHT + VALUE "OriginalFilename", __FILENAME + VALUE "ProductName", __PLUGIN_NAME + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END diff --git a/plugins/FreeImage/src/CacheFile.h b/plugins/FreeImage/src/CacheFile.h new file mode 100644 index 0000000000..a1e5e782c9 --- /dev/null +++ b/plugins/FreeImage/src/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 PageCache; + typedef std::list::iterator PageCacheIt; + typedef std::map PageMap; + typedef std::map::iterator PageMapIt; + +public : + CacheFile(const std::string 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 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/plugins/FreeImage/src/DeprecationManager/Deprecated.cpp b/plugins/FreeImage/src/DeprecationManager/Deprecated.cpp new file mode 100644 index 0000000000..8ca5e71c5c --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/DeprecationManager/DeprecationMgr.cpp b/plugins/FreeImage/src/DeprecationManager/DeprecationMgr.cpp new file mode 100644 index 0000000000..bf82dfa33b --- /dev/null +++ b/plugins/FreeImage/src/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 +#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::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::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/plugins/FreeImage/src/DeprecationManager/DeprecationMgr.h b/plugins/FreeImage/src/DeprecationManager/DeprecationMgr.h new file mode 100644 index 0000000000..9141f23a05 --- /dev/null +++ b/plugins/FreeImage/src/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 called_from; + }; + + std::map 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/plugins/FreeImage/src/FreeImage.h b/plugins/FreeImage/src/FreeImage.h new file mode 100644 index 0000000000..a7090adf59 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage.h @@ -0,0 +1,1104 @@ +// ========================================================== +// FreeImage 3 +// +// Design and implementation by +// - Floris van den Berg (flvdberg@wxs.nl) +// - Hervé Drolon (drolon@infonie.fr) +// +// Contributors: +// - see changes log named 'Whatsnew.txt', see header of each .h and .cpp file +// +// 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 15 +#define FREEIMAGE_RELEASE_SERIAL 3 + +// Compiler options --------------------------------------------------------- + +#include // 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 +typedef int32_t BOOL; +typedef uint8_t BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef int32_t LONG; +typedef int64_t FIINT64; +typedef uint64_t FIUINT64; +#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; +typedef signed __int64 FIINT64; +typedef unsigned __int64 FIUINT64; +#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 + FIDT_LONG8 = 16, // 64-bit unsigned integer + FIDT_SLONG8 = 17, // 64-bit signed integer + FIDT_IFD8 = 18 // 64-bit unsigned integer (offset) +}; + +/** + 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 + FIMD_EXIF_RAW = 11 // Exif metadata as a raw buffer +}; + +/** + 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); +typedef BOOL (DLL_CALLCONV *FI_SupportsNoPixelsProc)(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; + FI_SupportsNoPixelsProc supports_no_pixels_proc; +}; + +typedef void (DLL_CALLCONV *FI_InitProc)(Plugin *plugin, int format_id); + +#endif // PLUGINS + + +// Load / Save flag constants ----------------------------------------------- + +#define FIF_LOAD_NOPIXELS 0x8000 // loading: load the image header only (not supported by all plugins) + +#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 JPEG_OPTIMIZE 0x20000 // on saving, compute optimal Huffman coding tables (can reduce a few percent of file size) +#define JPEG_BASELINE 0x40000 // save basic JPEG, without metadata or any markers +#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 PSD_CMYK 1 // reads tags for separated CMYK (default is conversion to RGB) +#define PSD_LAB 2 // reads tags for CIELab (default is conversion to RGB) +#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 RAW_HALFSIZE 4 // output a half-size color image +#define SGI_DEFAULT 0 +#define TARGA_DEFAULT 0 +#define TARGA_LOAD_RGB888 1 // If set the loader converts RGB555 and ARGB8888 -> RGB888. +#define TARGA_SAVE_RLE 2 // If set, the writer saves with RLE compression +#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 TIFF_LOGLUV 0x10000 // save using LogLuv 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); + +// Header loading routines +DLL_API BOOL DLL_CALLCONV FreeImage_HasPixels(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)); +DLL_API BOOL DLL_CALLCONV FreeImage_SaveMultiBitmapToMemory(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, FIMEMORY *stream, int flags); + +// 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); +DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsNoPixels(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_OpenMultiBitmapU(FREE_IMAGE_FORMAT fif, const wchar_t *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_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, 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); + +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_GetThumbnail(FIBITMAP *dib); +DLL_API BOOL DLL_CALLCONV FreeImage_SetThumbnail(FIBITMAP *dib, FIBITMAP *thumbnail); + +// 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_ConvertToFloat(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToRGBF(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToUINT16(FIBITMAP *dib); +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToRGB16(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 *dst, FIBITMAP *src, 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/plugins/FreeImage/src/FreeImage/BitmapAccess.cpp b/plugins/FreeImage/src/FreeImage/BitmapAccess.cpp new file mode 100644 index 0000000000..584870f359 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/BitmapAccess.cpp @@ -0,0 +1,1210 @@ +// ========================================================== +// 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) +// - 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! +// ========================================================== + +#ifdef _MSC_VER +#pragma warning (disable : 4786) // identifier was truncated to 'number' characters +#endif + +#include +#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__) +#include +#endif // _WIN32 || _WIN64 || __MINGW32__ + +#include "FreeImage.h" +#include "FreeImageIO.h" +#include "Utilities.h" + +#include "../Metadata/FreeImageTag.h" + +// ---------------------------------------------------------- +// Metadata definitions +// ---------------------------------------------------------- + +// helper for map where value is a pointer to a FreeImage tag +typedef std::map TAGMAP; + +// helper for map +typedef std::map 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 + + BOOL has_pixels; // FALSE if the FIBITMAP only contains the header and no pixel data + + FIBITMAP *thumbnail; // optionally contains a thumbnail 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__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) + +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. + +@param header_only If TRUE, calculate a 'header only' FIBITMAP size, otherwise calculate a full FIBITMAP size +@param width +@param height +@param bpp +@see FreeImage_AllocateHeaderT +*/ +static size_t +FreeImage_GetImageSizeHeader(BOOL header_only, unsigned width, unsigned height, unsigned bpp) { + size_t 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); + if (!header_only) { + const size_t header_size = dib_size; + + // pixels are aligned on a 16 bytes boundary + dib_size += (size_t)CalculatePitch(CalculateLine(width, bpp)) * (size_t)height; + + // check for possible malloc overflow using a KISS integer overflow detection mechanism + { + /* + The following constant take into account the additionnal memory used by + aligned malloc functions as well as debug malloc functions. + It is supposed here that using a (8 * FIBITMAP_ALIGNMENT) risk margin will be enough + for the target compiler. + */ + const double FIBITMAP_MAX_MEMORY = (double)((size_t)-1) - 8 * FIBITMAP_ALIGNMENT; + const double dPitch = floor( ((double)bpp * width + 31.0) / 32.0 ) * 4.0; + const double dImageSize = (double)header_size + dPitch * height; + if(dImageSize != (double)dib_size) { + // here, we are sure to encounter a malloc overflow: try to avoid it ... + return 0; + } + if(dImageSize > FIBITMAP_MAX_MEMORY) { + // avoid possible overflow inside C allocation functions + return 0; + } + } + } + + return dib_size; +} + +FIBITMAP * DLL_CALLCONV +FreeImage_AllocateHeaderT(BOOL header_only, 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) { + width = abs(width); + 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(DWORD); + 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 + + size_t dib_size = FreeImage_GetImageSizeHeader(header_only, width, height, bpp); + + if(dib_size == 0) { + // memory allocation will fail (probably a malloc overflow) + free(bitmap); + return NULL; + } + + 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); + + fih->has_pixels = header_only ? FALSE : TRUE; + + // initialize FIICCPROFILE link + + FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap); + iccProfile->size = 0; + iccProfile->data = 0; + iccProfile->flags = 0; + + // initialize metadata models list + + fih->metadata = new(std::nothrow) METADATAMAP; + + // initialize attached thumbnail + + fih->thumbnail = NULL; + + // 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 + + if(bpp == 8) { + // build a default greyscale palette (very useful for image processing) + RGBQUAD *pal = FreeImage_GetPalette(bitmap); + for(int i = 0; i < 256; i++) { + pal[i].rgbRed = (BYTE)i; + pal[i].rgbGreen = (BYTE)i; + pal[i].rgbBlue = (BYTE)i; + } + } + + return bitmap; + } + + free(bitmap); + } + + return NULL; +} + +FIBITMAP * DLL_CALLCONV +FreeImage_AllocateHeader(BOOL header_only, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { + return FreeImage_AllocateHeaderT(header_only, FIT_BITMAP, width, height, bpp, red_mask, green_mask, blue_mask); +} + +FIBITMAP * DLL_CALLCONV +FreeImage_Allocate(int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) { + return FreeImage_AllocateHeaderT(FALSE, 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) { + return FreeImage_AllocateHeaderT(FALSE, type, width, height, bpp, red_mask, green_mask, blue_mask); +} + +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 embedded thumbnail + FreeImage_Unload(FreeImage_GetThumbnail(dib)); + + // 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); + + // check for pixel availability ... + BOOL header_only = FreeImage_HasPixels(dib) ? FALSE : TRUE; + + // allocate a new dib + FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, 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 + + size_t dib_size = FreeImage_GetImageSizeHeader(header_only, 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; + + // reset thumbnail link for new_dib + ((FREEIMAGEHEADER *)new_dib->data)->thumbnail = NULL; + + // 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(std::nothrow) TAGMAP(); + + if(dst_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; + } + } + } + + // copy the thumbnail + FreeImage_SetThumbnail(new_dib, FreeImage_GetThumbnail(dib)); + + return new_dib; + } + + return NULL; +} + +// ---------------------------------------------------------- + +FIBITMAP* DLL_CALLCONV +FreeImage_GetThumbnail(FIBITMAP *dib) { + return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->thumbnail : NULL; +} + +BOOL DLL_CALLCONV +FreeImage_SetThumbnail(FIBITMAP *dib, FIBITMAP *thumbnail) { + if(dib == NULL) { + return FALSE; + } + FIBITMAP *currentThumbnail = ((FREEIMAGEHEADER *)dib->data)->thumbnail; + if(currentThumbnail == thumbnail) { + return TRUE; + } + FreeImage_Unload(currentThumbnail); + + ((FREEIMAGEHEADER *)dib->data)->thumbnail = FreeImage_HasPixels(thumbnail) ? FreeImage_Clone(thumbnail) : NULL; + + return TRUE; +} + +// ---------------------------------------------------------- + +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; +} + +// ---------------------------------------------------------- + +BOOL DLL_CALLCONV +FreeImage_HasPixels(FIBITMAP *dib) { + return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->has_pixels : FALSE; +} + +// ---------------------------------------------------------- + +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) { + FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + switch(image_type) { + case FIT_BITMAP: + if(FreeImage_GetBPP(dib) == 32) { + if(FreeImage_GetColorType(dib) == FIC_RGBALPHA) { + return TRUE; + } + } else { + return ((FREEIMAGEHEADER *)dib->data)->transparent ? TRUE : FALSE; + } + break; + case FIT_RGBA16: + case FIT_RGBAF: + return TRUE; + default: + break; + } + } + 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) { + count = MIN(count, 256); + 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(std::nothrow) TAGMAP(); + + if(dst_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; + } + } + } + + // clone resolution + FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src)); + FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src)); + + 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(std::nothrow) 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(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/plugins/FreeImage/src/FreeImage/CacheFile.cpp b/plugins/FreeImage/src/FreeImage/CacheFile.cpp new file mode 100644 index 0000000000..309faf8faf --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/CacheFile.cpp @@ -0,0 +1,271 @@ +// ========================================================== +// 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 std::string filename, BOOL keep_in_memory) : +m_file(NULL), +m_filename(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) { +} + +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/plugins/FreeImage/src/FreeImage/ColorLookup.cpp b/plugins/FreeImage/src/FreeImage/ColorLookup.cpp new file mode 100644 index 0000000000..3e81abdb95 --- /dev/null +++ b/plugins/FreeImage/src/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 { + const 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, or gray, 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, or gray, 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/plugins/FreeImage/src/FreeImage/Conversion.cpp b/plugins/FreeImage/src/FreeImage/Conversion.cpp new file mode 100644 index 0000000000..3c14bab9dd --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/Conversion.cpp @@ -0,0 +1,513 @@ +// ========================================================== +// Bitmap conversion routines +// +// Design and implementation by +// - Floris van den Berg (flvdberg@wxs.nl) +// - Hervé Drolon (drolon@infonie.fr) +// - Jani Kajala (janik@remedy.fi) +// - 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 "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; + +// ========================================================== +// Utility functions declared in Utilities.h + +BOOL SwapRedBlue32(FIBITMAP* dib) { + if(FreeImage_GetImageType(dib) != FIT_BITMAP) { + return FALSE; + } + + const unsigned bytesperpixel = FreeImage_GetBPP(dib) / 8; + if(bytesperpixel > 4 || bytesperpixel < 3) { + return FALSE; + } + + const unsigned height = FreeImage_GetHeight(dib); + const unsigned pitch = FreeImage_GetPitch(dib); + const unsigned lineSize = FreeImage_GetLine(dib); + + BYTE* line = FreeImage_GetBits(dib); + for(unsigned y = 0; y < height; ++y, line += pitch) { + for(BYTE* pixel = line; pixel < line + lineSize ; pixel += bytesperpixel) { + INPLACESWAP(pixel[0], pixel[2]); + } + } + + return TRUE; +} + +// ---------------------------------------------------------- + +static inline void +assignRGB(WORD r, WORD g, WORD b, WORD* out) { + out[0] = r; + out[1] = g; + out[2] = b; +} + +static inline void +assignRGB(BYTE r, BYTE g, BYTE b, BYTE* out) { + out[FI_RGBA_RED] = r; + out[FI_RGBA_GREEN] = g; + out[FI_RGBA_BLUE] = b; +} + +/** +CMYK -> CMY -> RGB conversion from http://www.easyrgb.com/ + +CMYK to CMY [0-1]: C,M,Y * (1 - K) + K +CMY to RGB [0-1]: (1 - C,M,Y) + +=> R,G,B = (1 - C,M,Y) * (1 - K) +mapped to [0-MAX_VAL]: +(MAX_VAL - C,M,Y) * (MAX_VAL - K) / MAX_VAL +*/ +template +static inline void +CMYKToRGB(T C, T M, T Y, T K, T* out) { + unsigned max_val = std::numeric_limits::max(); + + unsigned r = (max_val - C) * (max_val - K) / max_val; + unsigned g = (max_val - M) * (max_val - K) / max_val; + unsigned b = (max_val - Y) * (max_val - K) / max_val; + + // clamp values to [0..max_val] + T red = (T)CLAMP(r, (unsigned)0, max_val); + T green = (T)CLAMP(g, (unsigned)0, max_val); + T blue = (T)CLAMP(b, (unsigned)0, max_val); + + assignRGB(red, green, blue, out); +} + +template +static void +_convertCMYKtoRGBA(unsigned width, unsigned height, BYTE* line_start, unsigned pitch, unsigned samplesperpixel) { + const BOOL hasBlack = (samplesperpixel > 3) ? TRUE : FALSE; + const T MAX_VAL = std::numeric_limits::max(); + + T K = 0; + for(unsigned y = 0; y < height; y++) { + T *line = (T*)line_start; + + for(unsigned x = 0; x < width; x++) { + if(hasBlack) { + K = line[FI_RGBA_ALPHA]; + line[FI_RGBA_ALPHA] = MAX_VAL; // TODO write the first extra channel as alpha! + } + + CMYKToRGB(line[0], line[1], line[2], K, line); + + line += samplesperpixel; + } + line_start += pitch; + } +} + +BOOL +ConvertCMYKtoRGBA(FIBITMAP* dib) { + if (!FreeImage_HasPixels(dib)) { + return FALSE; + } + + const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + const unsigned bytesperpixel = FreeImage_GetBPP(dib)/8; + + unsigned channelSize = 1; + if (image_type == FIT_RGBA16 || image_type == FIT_RGB16) { + channelSize = sizeof(WORD); + } else if (!(image_type == FIT_BITMAP && (bytesperpixel > 2))) { + return FALSE; + } + + const unsigned width = FreeImage_GetWidth(dib); + const unsigned height = FreeImage_GetHeight(dib); + BYTE *line_start = FreeImage_GetScanLine(dib, 0); + const unsigned pitch = FreeImage_GetPitch(dib); + + unsigned samplesperpixel = FreeImage_GetLine(dib) / width / channelSize; + + if(channelSize == sizeof(WORD)) { + _convertCMYKtoRGBA(width, height, line_start, pitch, samplesperpixel); + } else { + _convertCMYKtoRGBA(width, height, line_start, pitch, samplesperpixel); + } + + return TRUE; +} + +// ---------------------------------------------------------- + +/** +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; +} + +template +static void +CIELabToRGB(float L, float a, float b, T *rgb) { + float X, Y, Z; + float R, G, B; + const float max_val = std::numeric_limits::max(); + + CIELabToXYZ(L, a, b, &X, &Y, &Z); + XYZToRGB(X, Y, Z, &R, &G, &B); + + // clamp values to [0..max_val] + T red = (T)CLAMP(R * max_val, 0.0F, max_val); + T green = (T)CLAMP(G * max_val, 0.0F, max_val); + T blue = (T)CLAMP(B * max_val, 0.0F, max_val); + + assignRGB(red, green, blue, rgb); +} + +template +static void +_convertLABtoRGB(unsigned width, unsigned height, BYTE* line_start, unsigned pitch, unsigned samplesperpixel) { + const unsigned max_val = std::numeric_limits::max(); + const float sL = 100.F / max_val; + const float sa = 256.F / max_val; + const float sb = 256.F / max_val; + + for(unsigned y = 0; y < height; y++) { + T *line = (T*)line_start; + + for(unsigned x = 0; x < width; x++) { + CIELabToRGB(line[0]* sL, line[1]* sa - 128.F, line[2]* sb - 128.F, line); + + line += samplesperpixel; + } + line_start += pitch; + } +} + +BOOL +ConvertLABtoRGB(FIBITMAP* dib) { + if (!FreeImage_HasPixels(dib)) { + return FALSE; + } + + const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + const unsigned bytesperpixel = FreeImage_GetBPP(dib) / 8; + + unsigned channelSize = 1; + if (image_type == FIT_RGBA16 || image_type == FIT_RGB16) { + channelSize = sizeof(WORD); + } else if (!(image_type == FIT_BITMAP && (bytesperpixel > 2))) { + return FALSE; + } + + const unsigned width = FreeImage_GetWidth(dib); + const unsigned height = FreeImage_GetHeight(dib); + BYTE *line_start = FreeImage_GetScanLine(dib, 0); + const unsigned pitch = FreeImage_GetPitch(dib); + + unsigned samplesperpixel = FreeImage_GetLine(dib) / width / channelSize; + + if(channelSize == 1) { + _convertLABtoRGB(width, height, line_start, pitch, samplesperpixel); + } + else { + _convertLABtoRGB(width, height, line_start, pitch, samplesperpixel); + } + + return TRUE; +} + +// ---------------------------------------------------------- + +FIBITMAP* +RemoveAlphaChannel(FIBITMAP* src) { + + if (!FreeImage_HasPixels(src)) { + return NULL; + } + + const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); + + switch(image_type) { + case FIT_BITMAP: + if(FreeImage_GetBPP(src) == 32) { + // convert to 24-bit + return FreeImage_ConvertTo24Bits(src); + } + break; + case FIT_RGBA16: + // convert to RGB16 + return FreeImage_ConvertToRGB16(src); + case FIT_RGBAF: + // convert to RGBF + return FreeImage_ConvertToRGBF(src); + default: + // unsupported image type + return NULL; + } + + return NULL; +} + + +// ========================================================== + +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 (FreeImage_HasPixels(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 (FreeImage_HasPixels(dib) && (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/plugins/FreeImage/src/FreeImage/Conversion16_555.cpp b/plugins/FreeImage/src/FreeImage/Conversion16_555.cpp new file mode 100644 index 0000000000..c0c4785704 --- /dev/null +++ b/plugins/FreeImage/src/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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImage/Conversion16_565.cpp b/plugins/FreeImage/src/FreeImage/Conversion16_565.cpp new file mode 100644 index 0000000000..28e8255b4e --- /dev/null +++ b/plugins/FreeImage/src/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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImage/Conversion24.cpp b/plugins/FreeImage/src/FreeImage/Conversion24.cpp new file mode 100644 index 0000000000..f04b946ef0 --- /dev/null +++ b/plugins/FreeImage/src/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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImage/Conversion32.cpp b/plugins/FreeImage/src/FreeImage/Conversion32.cpp new file mode 100644 index 0000000000..fad74671cd --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/Conversion32.cpp @@ -0,0 +1,345 @@ +// ========================================================== +// 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; + } +} + +// ---------------------------------------------------------- + +inline void +FreeImage_ConvertLine1To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { + 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] = (index < transparent_pixels) ? table[index] : 255; + target += 4; + } +} + +inline void +FreeImage_ConvertLine4To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { + 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; + target[FI_RGBA_ALPHA] = (LOWNIBBLE(source[x]) < transparent_pixels) ? table[LOWNIBBLE(source[x])] : 255; + + 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; + target[FI_RGBA_ALPHA] = (HINIBBLE(source[x] >> 4) < transparent_pixels) ? table[HINIBBLE(source[x]) >> 4] : 255; + } + + low_nibble = !low_nibble; + + target += 4; + } +} + +inline void +FreeImage_ConvertLine8To32MapTransparency(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette, BYTE *table, int transparent_pixels) { + 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] = (source[cols] < transparent_pixels) ? table[source[cols]] : 255; + target += 4; + } +} + +// ---------------------------------------------------------- + +FIBITMAP * DLL_CALLCONV +FreeImage_ConvertTo32Bits(FIBITMAP *dib) { + if (!FreeImage_HasPixels(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); + + BOOL bIsTransparent = FreeImage_IsTransparent(dib); + + switch(bpp) { + case 1: + { + if(bIsTransparent) { + for (int rows = 0; rows < height; rows++) { + FreeImage_ConvertLine1To32MapTransparency(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); + } + } else { + for (int rows = 0; rows < height; rows++) { + FreeImage_ConvertLine1To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); + } + } + + return new_dib; + } + + case 4: + { + if(bIsTransparent) { + for (int rows = 0; rows < height; rows++) { + FreeImage_ConvertLine4To32MapTransparency(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); + } + } else { + for (int rows = 0; rows < height; rows++) { + FreeImage_ConvertLine4To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib)); + } + } + + return new_dib; + } + + case 8: + { + if(bIsTransparent) { + for (int rows = 0; rows < height; rows++) { + FreeImage_ConvertLine8To32MapTransparency(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); + } + } else { + for (int rows = 0; rows < height; rows++) { + FreeImage_ConvertLine8To32(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_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/plugins/FreeImage/src/FreeImage/Conversion4.cpp b/plugins/FreeImage/src/FreeImage/Conversion4.cpp new file mode 100644 index 0000000000..7c09ac824a --- /dev/null +++ b/plugins/FreeImage/src/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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImage/Conversion8.cpp b/plugins/FreeImage/src/FreeImage/Conversion8.cpp new file mode 100644 index 0000000000..867cf756ed --- /dev/null +++ b/plugins/FreeImage/src/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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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)) * sizeof(BYTE)); + 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/plugins/FreeImage/src/FreeImage/ConversionFloat.cpp b/plugins/FreeImage/src/FreeImage/ConversionFloat.cpp new file mode 100644 index 0000000000..181ff396e1 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/ConversionFloat.cpp @@ -0,0 +1,192 @@ +// ========================================================== +// 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 Float +// ---------------------------------------------------------- + +FIBITMAP * DLL_CALLCONV +FreeImage_ConvertToFloat(FIBITMAP *dib) { + FIBITMAP *src = NULL; + FIBITMAP *dst = NULL; + + if (!FreeImage_HasPixels(dib)) return NULL; + + FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); + + // check for allowed conversions + switch(src_type) { + case FIT_BITMAP: + { + // allow conversion from 8-bit + if ((FreeImage_GetBPP(dib) == 8) && (FreeImage_GetColorType(dib) == FIC_MINISBLACK)) { + src = dib; + } else { + src = FreeImage_ConvertToGreyscale(dib); + if (!src) return NULL; + } + break; + } + case FIT_UINT16: + case FIT_RGB16: + case FIT_RGBA16: + case FIT_RGBF: + case FIT_RGBAF: + src = dib; + break; + case FIT_FLOAT: + // float type : clone the src + return FreeImage_Clone(dib); + default: + return NULL; + } + + // allocate dst image + + const unsigned width = FreeImage_GetWidth(src); + const unsigned height = FreeImage_GetHeight(src); + + dst = FreeImage_AllocateT(FIT_FLOAT, width, height); + if (!dst) { + if(src != dib) { + FreeImage_Unload(src); + } + return NULL; + } + + // copy metadata from src to dst + FreeImage_CloneMetadata(dst, src); + + // convert from src type to float + + const unsigned src_pitch = FreeImage_GetPitch(src); + const unsigned dst_pitch = FreeImage_GetPitch(dst); + + const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); + BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); + + switch(src_type) { + case FIT_BITMAP: + { + for(unsigned y = 0; y < height; y++) { + const BYTE *src_pixel = (BYTE*)src_bits; + float *dst_pixel = (float*)dst_bits; + for(unsigned x = 0; x < width; x++) { + // convert and scale to the range [0..1] + dst_pixel[x] = (float)(src_pixel[x]) / 255; + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + + case FIT_UINT16: + { + for(unsigned y = 0; y < height; y++) { + const WORD *src_pixel = (WORD*)src_bits; + float *dst_pixel = (float*)dst_bits; + + for(unsigned x = 0; x < width; x++) { + // convert and scale to the range [0..1] + dst_pixel[x] = (float)(src_pixel[x]) / 65535; + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + + case FIT_RGB16: + { + for(unsigned y = 0; y < height; y++) { + const FIRGB16 *src_pixel = (FIRGB16*)src_bits; + float *dst_pixel = (float*)dst_bits; + + for(unsigned x = 0; x < width; x++) { + // convert and scale to the range [0..1] + dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue) / 65535.0F; + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + + case FIT_RGBA16: + { + for(unsigned y = 0; y < height; y++) { + const FIRGBA16 *src_pixel = (FIRGBA16*)src_bits; + float *dst_pixel = (float*)dst_bits; + + for(unsigned x = 0; x < width; x++) { + // convert and scale to the range [0..1] + dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue) / 65535.0F; + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + + case FIT_RGBF: + { + 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++) { + // convert (assume pixel values are in the range [0..1]) + dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue); + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + + case FIT_RGBAF: + { + for(unsigned y = 0; y < height; y++) { + const FIRGBAF *src_pixel = (FIRGBAF*)src_bits; + float *dst_pixel = (float*)dst_bits; + + for(unsigned x = 0; x < width; x++) { + // convert (assume pixel values are in the range [0..1]) + dst_pixel[x] = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, src_pixel[x].blue); + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + } + + if(src != dib) { + FreeImage_Unload(src); + } + + return dst; +} + diff --git a/plugins/FreeImage/src/FreeImage/ConversionRGB16.cpp b/plugins/FreeImage/src/FreeImage/ConversionRGB16.cpp new file mode 100644 index 0000000000..6b9d17fbed --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/ConversionRGB16.cpp @@ -0,0 +1,144 @@ +// ========================================================== +// 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 RGB16 +// ---------------------------------------------------------- + +FIBITMAP * DLL_CALLCONV +FreeImage_ConvertToRGB16(FIBITMAP *dib) { + FIBITMAP *src = NULL; + FIBITMAP *dst = NULL; + + if (!FreeImage_HasPixels(dib)) return NULL; + + const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); + + // check for allowed conversions + switch(src_type) { + case FIT_BITMAP: + { + // convert to 24-bit if needed + if ((FreeImage_GetBPP(dib) == 24) || (FreeImage_GetBPP(dib) == 32)) { + src = dib; + } else { + src = FreeImage_ConvertTo24Bits(dib); + if (!src) return NULL; + } + break; + } + case FIT_UINT16: + // allow conversion from unsigned 16-bit + src = dib; + break; + case FIT_RGB16: + // RGB16 type : clone the src + return FreeImage_Clone(dib); + break; + case FIT_RGBA16: + // allow conversion from 64-bit RGBA (ignore the alpha channel) + src = dib; + break; + default: + return NULL; + } + + // allocate dst image + + const unsigned width = FreeImage_GetWidth(src); + const unsigned height = FreeImage_GetHeight(src); + + dst = FreeImage_AllocateT(FIT_RGB16, width, height); + if (!dst) { + if(src != dib) { + FreeImage_Unload(src); + } + return NULL; + } + + // copy metadata from src to dst + FreeImage_CloneMetadata(dst, src); + + // convert from src type to RGB16 + + switch(src_type) { + case FIT_BITMAP: + { + // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit) + const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); + + for(unsigned y = 0; y < height; y++) { + const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y); + FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y); + for(unsigned x = 0; x < width; x++) { + dst_bits[x].red = src_bits[FI_RGBA_RED] << 8; + dst_bits[x].green = src_bits[FI_RGBA_GREEN] << 8; + dst_bits[x].blue = src_bits[FI_RGBA_BLUE] << 8; + src_bits += bytespp; + } + } + } + break; + + case FIT_UINT16: + { + for(unsigned y = 0; y < height; y++) { + const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y); + FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y); + for(unsigned x = 0; x < width; x++) { + // convert by copying greyscale channel to each R, G, B channels + dst_bits[x].red = src_bits[x]; + dst_bits[x].green = src_bits[x]; + dst_bits[x].blue = src_bits[x]; + } + } + } + break; + + case FIT_RGBA16: + { + for(unsigned y = 0; y < height; y++) { + const FIRGBA16 *src_bits = (FIRGBA16*)FreeImage_GetScanLine(src, y); + FIRGB16 *dst_bits = (FIRGB16*)FreeImage_GetScanLine(dst, y); + for(unsigned x = 0; x < width; x++) { + // convert and skip alpha channel + dst_bits[x].red = src_bits[x].red; + dst_bits[x].green = src_bits[x].green; + dst_bits[x].blue = src_bits[x].blue; + } + } + } + break; + + default: + break; + } + + if(src != dib) { + FreeImage_Unload(src); + } + + return dst; +} + diff --git a/plugins/FreeImage/src/FreeImage/ConversionRGBF.cpp b/plugins/FreeImage/src/FreeImage/ConversionRGBF.cpp new file mode 100644 index 0000000000..6b8739532f --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/ConversionRGBF.cpp @@ -0,0 +1,241 @@ +// ========================================================== +// 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; + + if (!FreeImage_HasPixels(dib)) return 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_UINT16: + // allow conversion from 16-bit + src = dib; + break; + case FIT_RGB16: + // allow conversion from 48-bit RGB + src = dib; + break; + case FIT_RGBA16: + // allow conversion from 64-bit RGBA (ignore the alpha channel) + src = dib; + break; + case FIT_FLOAT: + // allow conversion from 32-bit float + src = dib; + break; + case FIT_RGBAF: + // allow conversion from 128-bit RGBAF + 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) { + if(src != dib) { + FreeImage_Unload(src); + } + 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.0F; + dst_pixel->green = (float)(src_pixel[FI_RGBA_GREEN]) / 255.0F; + dst_pixel->blue = (float)(src_pixel[FI_RGBA_BLUE]) / 255.0F; + + src_pixel += bytespp; + dst_pixel ++; + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + + case FIT_UINT16: + { + const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); + BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); + + for(unsigned y = 0; y < height; y++) { + const WORD *src_pixel = (WORD*)src_bits; + FIRGBF *dst_pixel = (FIRGBF*)dst_bits; + + for(unsigned x = 0; x < width; x++) { + // convert and scale to the range [0..1] + const float dst_value = (float)src_pixel[x] / 65535.0F; + dst_pixel[x].red = dst_value; + dst_pixel[x].green = dst_value; + dst_pixel[x].blue = dst_value; + } + 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.0F; + dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; + dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; + } + 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.0F; + dst_pixel[x].green = (float)(src_pixel[x].green) / 65535.0F; + dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535.0F; + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + + case FIT_FLOAT: + { + const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src); + BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst); + + for(unsigned y = 0; y < height; y++) { + const float *src_pixel = (float*) src_bits; + FIRGBF *dst_pixel = (FIRGBF*) dst_bits; + + for(unsigned x = 0; x < width; x++) { + // convert by copying greyscale channel to each R, G, B channels + dst_pixel[x].red = src_pixel[x]; + dst_pixel[x].green = src_pixel[x]; + dst_pixel[x].blue = src_pixel[x]; + } + 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/plugins/FreeImage/src/FreeImage/ConversionType.cpp b/plugins/FreeImage/src/FreeImage/ConversionType.cpp new file mode 100644 index 0000000000..23528b60fe --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/ConversionType.cpp @@ -0,0 +1,689 @@ +// ========================================================== +// 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 CONVERT_TYPE +{ +public: + FIBITMAP* convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type); +}; + +template FIBITMAP* +CONVERT_TYPE::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(FreeImage_GetScanLine(src, y)); + Tdst *dst_bits = reinterpret_cast(FreeImage_GetScanLine(dst, y)); + + for(unsigned x = 0; x < width; x++) { + *dst_bits++ = static_cast(*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 CONVERT_TO_BYTE +{ +public: + FIBITMAP* convert(FIBITMAP *src, BOOL scale_linear); +}; + +template FIBITMAP* +CONVERT_TO_BYTE::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(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(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(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 CONVERT_TO_COMPLEX +{ +public: + FIBITMAP* convert(FIBITMAP *src); +}; + +template FIBITMAP* +CONVERT_TO_COMPLEX::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(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 convertByteToUShort; +CONVERT_TYPE convertByteToShort; +CONVERT_TYPE convertByteToULong; +CONVERT_TYPE convertByteToLong; +CONVERT_TYPE convertByteToFloat; +CONVERT_TYPE convertByteToDouble; + +// Convert from type X to type BYTE +CONVERT_TO_BYTE convertUShortToByte; +CONVERT_TO_BYTE convertShortToByte; +CONVERT_TO_BYTE convertULongToByte; +CONVERT_TO_BYTE convertLongToByte; +CONVERT_TO_BYTE convertFloatToByte; +CONVERT_TO_BYTE convertDoubleToByte; + +// Convert from type X to type float +CONVERT_TYPE convertUShortToFloat; +CONVERT_TYPE convertShortToFloat; +CONVERT_TYPE convertULongToFloat; +CONVERT_TYPE convertLongToFloat; + +// Convert from type X to type double +CONVERT_TYPE convertUShortToDouble; +CONVERT_TYPE convertShortToDouble; +CONVERT_TYPE convertULongToDouble; +CONVERT_TYPE convertLongToDouble; +CONVERT_TYPE convertFloatToDouble; + +// Convert from type X to type FICOMPLEX +CONVERT_TO_COMPLEX convertByteToComplex; +CONVERT_TO_COMPLEX convertUShortToComplex; +CONVERT_TO_COMPLEX convertShortToComplex; +CONVERT_TO_COMPLEX convertULongToComplex; +CONVERT_TO_COMPLEX convertLongToComplex; +CONVERT_TO_COMPLEX convertFloatToComplex; +CONVERT_TO_COMPLEX 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 (!FreeImage_HasPixels(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); + } + + const unsigned src_bpp = FreeImage_GetBPP(src); + + switch(src_type) { + case FIT_BITMAP: + switch(dst_type) { + case FIT_UINT16: + dst = FreeImage_ConvertToUINT16(src); + break; + case FIT_INT16: + dst = (src_bpp == 8) ? convertByteToShort.convert(src, dst_type) : NULL; + break; + case FIT_UINT32: + dst = (src_bpp == 8) ? convertByteToULong.convert(src, dst_type) : NULL; + break; + case FIT_INT32: + dst = (src_bpp == 8) ? convertByteToLong.convert(src, dst_type) : NULL; + break; + case FIT_FLOAT: + dst = FreeImage_ConvertToFloat(src); + break; + case FIT_DOUBLE: + dst = (src_bpp == 8) ? convertByteToDouble.convert(src, dst_type) : NULL; + break; + case FIT_COMPLEX: + dst = (src_bpp == 8) ? convertByteToComplex.convert(src) : NULL; + break; + case FIT_RGB16: + dst = FreeImage_ConvertToRGB16(src); + 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 = FreeImage_ConvertToFloat(src); + break; + case FIT_DOUBLE: + dst = convertUShortToDouble.convert(src, dst_type); + break; + case FIT_COMPLEX: + dst = convertUShortToComplex.convert(src); + break; + case FIT_RGB16: + dst = FreeImage_ConvertToRGB16(src); + break; + case FIT_RGBA16: + break; + case FIT_RGBF: + dst = FreeImage_ConvertToRGBF(src); + 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: + dst = FreeImage_ConvertToRGBF(src); + 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: + dst = FreeImage_ConvertToUINT16(src); + break; + case FIT_INT16: + break; + case FIT_UINT32: + break; + case FIT_INT32: + break; + case FIT_FLOAT: + dst = FreeImage_ConvertToFloat(src); + 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: + dst = FreeImage_ConvertToUINT16(src); + break; + case FIT_INT16: + break; + case FIT_UINT32: + break; + case FIT_INT32: + break; + case FIT_FLOAT: + dst = FreeImage_ConvertToFloat(src); + break; + case FIT_DOUBLE: + break; + case FIT_COMPLEX: + break; + case FIT_RGB16: + dst = FreeImage_ConvertToRGB16(src); + 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: + dst = FreeImage_ConvertToFloat(src); + 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: + dst = FreeImage_ConvertToFloat(src); + 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/plugins/FreeImage/src/FreeImage/ConversionUINT16.cpp b/plugins/FreeImage/src/FreeImage/ConversionUINT16.cpp new file mode 100644 index 0000000000..3744cfe3b4 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/ConversionUINT16.cpp @@ -0,0 +1,134 @@ +// ========================================================== +// 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 UINT16 +// ---------------------------------------------------------- + +FIBITMAP * DLL_CALLCONV +FreeImage_ConvertToUINT16(FIBITMAP *dib) { + FIBITMAP *src = NULL; + FIBITMAP *dst = NULL; + + if (!FreeImage_HasPixels(dib)) return NULL; + + const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib); + + // check for allowed conversions + switch(src_type) { + case FIT_BITMAP: + { + // convert to greyscale if needed + if ((FreeImage_GetBPP(dib) == 8) && (FreeImage_GetColorType(dib) == FIC_MINISBLACK)) { + src = dib; + } else { + src = FreeImage_ConvertToGreyscale(dib); + if (!src) return NULL; + } + break; + } + case FIT_UINT16: + // UINT16 type : clone the src + return FreeImage_Clone(dib); + break; + case FIT_RGB16: + // allow conversion from 48-bit RGB + src = dib; + break; + case FIT_RGBA16: + // allow conversion from 64-bit RGBA (ignore the alpha channel) + src = dib; + break; + default: + return NULL; + } + + // allocate dst image + + const unsigned width = FreeImage_GetWidth(src); + const unsigned height = FreeImage_GetHeight(src); + + dst = FreeImage_AllocateT(FIT_UINT16, width, height); + if (!dst) { + if(src != dib) { + FreeImage_Unload(src); + } + return NULL; + } + + // copy metadata from src to dst + FreeImage_CloneMetadata(dst, src); + + // convert from src type to UINT16 + + switch(src_type) { + case FIT_BITMAP: + { + for(unsigned y = 0; y < height; y++) { + const BYTE *src_bits = (BYTE*)FreeImage_GetScanLine(src, y); + WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); + for(unsigned x = 0; x < width; x++) { + dst_bits[x] = src_bits[x] << 8; + } + } + } + break; + + case FIT_RGB16: + { + for(unsigned y = 0; y < height; y++) { + const FIRGB16 *src_bits = (FIRGB16*)FreeImage_GetScanLine(src, y); + WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); + for(unsigned x = 0; x < width; x++) { + // convert to grey + dst_bits[x] = (WORD)LUMA_REC709(src_bits[x].red, src_bits[x].green, src_bits[x].blue); + } + } + } + break; + + case FIT_RGBA16: + { + for(unsigned y = 0; y < height; y++) { + const FIRGBA16 *src_bits = (FIRGBA16*)FreeImage_GetScanLine(src, y); + WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); + for(unsigned x = 0; x < width; x++) { + // convert to grey + dst_bits[x] = (WORD)LUMA_REC709(src_bits[x].red, src_bits[x].green, src_bits[x].blue); + } + } + } + break; + + default: + break; + } + + if(src != dib) { + FreeImage_Unload(src); + } + + return dst; +} + diff --git a/plugins/FreeImage/src/FreeImage/FreeImage.cpp b/plugins/FreeImage/src/FreeImage/FreeImage.cpp new file mode 100644 index 0000000000..b36f10aca1 --- /dev/null +++ b/plugins/FreeImage/src/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 +#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 { + DWORD i; + BYTE 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/plugins/FreeImage/src/FreeImage/FreeImageC.c b/plugins/FreeImage/src/FreeImage/FreeImageC.c new file mode 100644 index 0000000000..9e8125955f --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/FreeImage/FreeImageIO.cpp b/plugins/FreeImage/src/FreeImage/FreeImageIO.cpp new file mode 100644 index 0000000000..b289530be7 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/FreeImageIO.cpp @@ -0,0 +1,168 @@ +// ========================================================== +// 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" + +// ===================================================================== +// File IO functions +// ===================================================================== + +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/plugins/FreeImage/src/FreeImage/GetType.cpp b/plugins/FreeImage/src/FreeImage/GetType.cpp new file mode 100644 index 0000000000..76edc7f3f9 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/FreeImage/Halftoning.cpp b/plugins/FreeImage/src/FreeImage/Halftoning.cpp new file mode 100644 index 0000000000..1542fc9268 --- /dev/null +++ b/plugins/FreeImage/src/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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImage/J2KHelper.cpp b/plugins/FreeImage/src/FreeImage/J2KHelper.cpp new file mode 100644 index 0000000000..44b210aca0 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/J2KHelper.cpp @@ -0,0 +1,500 @@ +// ========================================================== +// 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: + if(FreeImage_GetBPP(dib) == 32) { + // 32-bit image with a fully opaque layer + numcomps = 4; + color_space = CLRSPC_SRGB; + } else { + // 24-bit image + 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/plugins/FreeImage/src/FreeImage/MemoryIO.cpp b/plugins/FreeImage/src/FreeImage/MemoryIO.cpp new file mode 100644 index 0000000000..6ae3fb2e11 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/MemoryIO.cpp @@ -0,0 +1,237 @@ +// ========================================================== +// Memory Input/Output functions +// +// Design and implementation by +// - Ryan Rubley +// - 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) { + if(stream && stream->data) { + 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/plugins/FreeImage/src/FreeImage/MultiPage.cpp b/plugins/FreeImage/src/FreeImage/MultiPage.cpp new file mode 100644 index 0000000000..e5bcee3ded --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/MultiPage.cpp @@ -0,0 +1,990 @@ +// ========================================================== +// 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) +// - Volodymyr Goncharov (volodymyr.goncharov@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! +// ========================================================== + +#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) { + } + virtual ~BlockTypeS() {} +}; + +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 BlockList; +typedef std::list::iterator BlockListIterator; + +// ---------------------------------------------------------- + +FI_STRUCT (MULTIBITMAPHEADER) { + PluginNode *node; + FREE_IMAGE_FORMAT fif; + FreeImageIO *io; + fi_handle handle; + CacheFile *m_cachefile; + std::map locked_pages; + BOOL changed; + int page_count; + BlockList m_blocks; + char *m_filename; + BOOL read_only; + FREE_IMAGE_FORMAT cache_fif; + int load_flags; +}; + +// ===================================================================== +// Helper functions +// ===================================================================== + +inline void +ReplaceExtension(std::string& dst_filename, const std::string& src_filename, const std::string& dst_extension) { + size_t lastDot = src_filename.find_last_of('.'); + if (lastDot == std::string::npos) { + dst_filename = src_filename; + dst_filename += "."; + dst_filename += dst_extension; + } + else { + dst_filename = src_filename.substr(0, lastDot + 1); + dst_filename += dst_extension; + } +} + +// ===================================================================== +// 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_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory, int flags) { + + FILE *handle = NULL; + try { + // 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) { + std::auto_ptr io (new FreeImageIO); + + SetDefaultIO(io.get()); + + if (!create_new) { + handle = fopen(filename, "rb"); + if (handle == NULL) { + return NULL; + } + } + + std::auto_ptr bitmap (new FIMULTIBITMAP); + std::auto_ptr 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.get (); + header->handle = handle; + header->changed = FALSE; + header->read_only = read_only; + header->m_cachefile = NULL; + header->cache_fif = fif; + header->load_flags = flags; + + // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure + + bitmap->data = header.get(); + + // cache the page count + + header->page_count = FreeImage_InternalGetPageCount(bitmap.get()); + + // 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) { + std::string cache_name; + ReplaceExtension(cache_name, filename, "ficache"); + + std::auto_ptr cache_file (new CacheFile(cache_name, keep_cache_in_memory)); + + if (cache_file->open()) { + // we can use release() as std::bad_alloc won't be thrown from here on + header->m_cachefile = cache_file.release(); + } else { + // an error occured ... + fclose(handle); + return NULL; + } + } + // return the multibitmap + // std::bad_alloc won't be thrown from here on + header.release(); // now owned by bitmap + io.release(); // now owned by bitmap + return bitmap.release(); // now owned by caller + } + } + } catch (std::bad_alloc &) { + /** @todo report error */ + } + if (handle) + fclose(handle); + return NULL; +} + +FIMULTIBITMAP * DLL_CALLCONV +FreeImage_OpenMultiBitmapU(FREE_IMAGE_FORMAT fif, const wchar_t *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory, int flags) { + + // convert to single character - no national chars in extensions + char *extension = (char *)malloc(wcslen(filename)+1); + unsigned int i=0; + for (; i < wcslen(filename); i++) // convert 16-bit to 8-bit + extension[i] = (char)(filename[i] & 0x00FF); + // set terminating 0 + extension[i]=0; + FIMULTIBITMAP *fRet = FreeImage_OpenMultiBitmap(fif, extension, create_new, read_only, keep_cache_in_memory, flags); + free(extension); + + return fRet; +} + +FIMULTIBITMAP * DLL_CALLCONV +FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags) { + try { + BOOL read_only = FALSE; // modifications (if any) will be stored into the memory cache + + 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) { + std::auto_ptr bitmap (new FIMULTIBITMAP); + std::auto_ptr header (new MULTIBITMAPHEADER); + std::auto_ptr tmp_io (new FreeImageIO (*io)); + header->io = tmp_io.get(); + header->m_filename = NULL; + header->node = node; + header->fif = fif; + header->handle = handle; + header->changed = FALSE; + header->read_only = read_only; + header->m_cachefile = NULL; + header->cache_fif = fif; + header->load_flags = flags; + + // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure + + bitmap->data = header.get(); + + // cache the page count + + header->page_count = FreeImage_InternalGetPageCount(bitmap.get()); + + // allocate a continueus block to describe the bitmap + + header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1)); + + if (!read_only) { + // set up the cache + std::auto_ptr cache_file (new CacheFile("", TRUE)); + + if (cache_file->open()) { + header->m_cachefile = cache_file.release(); + } + } + tmp_io.release(); + header.release(); + return bitmap.release(); + } + } + } + } catch (std::bad_alloc &) { + /** @todo report error */ + } + return NULL; +} + +BOOL DLL_CALLCONV +FreeImage_SaveMultiBitmapToHandle(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, FreeImageIO *io, fi_handle handle, int flags) { + if (!bitmap || !bitmap->data || !io || !handle) { + return FALSE; + } + + BOOL success = TRUE; + + // 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) { + MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); + + // dst data + void *data = FreeImage_Open(node, io, handle, FALSE); + // src data + void *data_read = NULL; + + if(header->handle) { + // open src + 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 file using handle and io + + 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++) { + + // load the original source data + FIBITMAP *dib = header->node->m_plugin->load_proc(header->io, header->handle, j, header->load_flags, data_read); + + // save the data + success = node->m_plugin->save_proc(io, dib, handle, 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 = node->m_plugin->save_proc(io, dib, handle, count, flags, data); + count++; + + // unload the dib + + FreeImage_Unload(dib); + + break; + } + } + } else { + break; + } + } + + // close the files + + FreeImage_Close(header->node, header->io, header->handle, data_read); + + FreeImage_Close(node, io, handle, data); + + return success; + } + } + + return FALSE; +} + + +BOOL DLL_CALLCONV +FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) { + if (bitmap) { + BOOL success = TRUE; + + if (bitmap->data) { + MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); + + // saves changes only of images loaded directly from a file + if (header->changed && header->m_filename) { + try { + // open a temp file + + std::string spool_name; + + ReplaceExtension(spool_name, header->m_filename, "fispool"); + + // open the spool file and the source file + + FILE *f = fopen(spool_name.c_str(), "w+b"); + + // saves changes + if (f == NULL) { + FreeImage_OutputMessageProc(header->fif, "Failed to open %s, %s", spool_name.c_str(), strerror(errno)); + success = FALSE; + } else { + success = FreeImage_SaveMultiBitmapToHandle(header->fif, bitmap, header->io, (fi_handle)f, flags); + + // close the files + + if (fclose(f) != 0) { + success = FALSE; + FreeImage_OutputMessageProc(header->fif, "Failed to close %s, %s", spool_name.c_str(), strerror(errno)); + } + } + if (header->handle) { + fclose((FILE *)header->handle); + } + + // applies changes to the destination file + + if (success) { + remove(header->m_filename); + success = (rename(spool_name.c_str(), header->m_filename) == 0) ? TRUE:FALSE; + if (!success) { + FreeImage_OutputMessageProc(header->fif, "Failed to rename %s to %s", spool_name.c_str(), header->m_filename); + } + } else { + remove(spool_name.c_str()); + } + } catch (std::bad_alloc &) { + success = FALSE; + } + + } 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; +} + +static BlockReference* +FreeImage_SavePageToBlock(MULTIBITMAPHEADER *header, FIBITMAP *data) { + if (header->read_only || !header->locked_pages.empty()) + return NULL; + + DWORD compressed_size = 0; + BYTE *compressed_data = NULL; + + // compress the bitmap data + + // open a memory handle + FIMEMORY *hmem = FreeImage_OpenMemory(); + if(hmem==NULL) return NULL; + // save the file to memory + if (!FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0)) { + FreeImage_CloseMemory(hmem); + return NULL; + } + // get the buffer from the memory stream + if (!FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size)) { + FreeImage_CloseMemory(hmem); + return NULL; + } + + // write the compressed data to the cache + int ref = header->m_cachefile->writeFile(compressed_data, compressed_size); + // get rid of the compressed data + FreeImage_CloseMemory(hmem); + + return new(std::nothrow) BlockReference(ref, compressed_size); +} + +void DLL_CALLCONV +FreeImage_AppendPage(FIMULTIBITMAP *bitmap, FIBITMAP *data) { + if (!bitmap || !data) + return; + + MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); + + BlockReference *block = FreeImage_SavePageToBlock(header, data); + if(block==NULL) return; + + // 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) + return; + + if (page >= FreeImage_GetPageCount(bitmap)) + return; + + MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); + + BlockReference *block = FreeImage_SavePageToBlock(header, data); + if(block==NULL) return; + + // add a block + if (page > 0) { + BlockListIterator block_source = FreeImage_FindBlock(bitmap, page); + + header->m_blocks.insert(block_source, (BlockTypeS *)block); + } else { + header->m_blocks.push_front((BlockTypeS *)block); + } + + 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 : + delete *i; + header->m_blocks.erase(i); + break; + + case BLOCK_REFERENCE : + header->m_cachefile->deleteFile(((BlockReference *)(*i))->m_reference); + delete *i; + 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::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::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; +} + +// ===================================================================== +// Memory IO Multipage functions +// ===================================================================== + +FIMULTIBITMAP * DLL_CALLCONV +FreeImage_LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags) { + BOOL read_only = FALSE; // modifications (if any) will be stored into the memory cache + + // 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(std::nothrow) FreeImageIO; + + if (io) { + SetMemoryIO(io); + + FIMULTIBITMAP *bitmap = new(std::nothrow) FIMULTIBITMAP; + + if (bitmap) { + MULTIBITMAPHEADER *header = new(std::nothrow) MULTIBITMAPHEADER; + + if (header) { + header->m_filename = NULL; + header->node = node; + header->fif = fif; + header->io = io; + header->handle = (fi_handle)stream; + header->changed = FALSE; + header->read_only = read_only; + 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)); + + if (!read_only) { + // set up the cache + CacheFile *cache_file = new(std::nothrow) CacheFile("", TRUE); + + if (cache_file && cache_file->open()) { + header->m_cachefile = cache_file; + } + } + + return bitmap; + } + + delete bitmap; + } + + delete io; + } + } + } + + return NULL; +} + +BOOL DLL_CALLCONV +FreeImage_SaveMultiBitmapToMemory(FREE_IMAGE_FORMAT fif, FIMULTIBITMAP *bitmap, FIMEMORY *stream, int flags) { + if (stream && stream->data) { + FreeImageIO io; + SetMemoryIO(&io); + + return FreeImage_SaveMultiBitmapToHandle(fif, bitmap, &io, (fi_handle)stream, flags); + } + + return FALSE; +} diff --git a/plugins/FreeImage/src/FreeImage/NNQuantizer.cpp b/plugins/FreeImage/src/FreeImage/NNQuantizer.cpp new file mode 100644 index 0000000000..6eb9aeaf48 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/FreeImage/PSDParser.cpp b/plugins/FreeImage/src/FreeImage/PSDParser.cpp new file mode 100644 index 0000000000..93573d01c0 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PSDParser.cpp @@ -0,0 +1,1053 @@ +// ========================================================== +// Photoshop Loader +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// - Mihail Naydenov (mnaydenov@users.sourceforge.net) +// +// 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 PSDP_BITMAP 0 +#define PSDP_GRAYSCALE 1 +#define PSDP_INDEXED 2 +#define PSDP_RGB 3 +#define PSDP_CMYK 4 +#define PSDP_MULTICHANNEL 7 +#define PSDP_DUOTONE 8 +#define PSDP_LAB 9 + +// PSD compression schemes +#define PSDP_COMPRESSION_NONE 0 // Raw data +#define PSDP_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; iread_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 + BYTE psd_reserved[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + if(memcmp(header.Reserved, psd_reserved, 6) != 0) { + FreeImage_OutputMessageProc(FIF_PSD, "Warning: file header reserved member is not equal to zero"); + } + // 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) ); + _BitsPerChannel = (short)psdGetValue( header.Depth, sizeof(header.Depth) ); + _ColourMode = (short)psdGetValue( header.Mode, sizeof(header.Mode) ); + + return true; + } + } + + return false; +} + +// -------------------------------------------------------------------------- + +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) ); + if ((_Opacity < 0) || (_Opacity > 100)) { + throw "Invalid DisplayInfo::Opacity value"; + } + + 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)); + if(_padding != 0) { + throw "Invalid DisplayInfo::Padding value"; + } + + return nBytes; +} + +// -------------------------------------------------------------------------- + +psdThumbnail::psdThumbnail() : +_Format(-1), _Width(-1), _Height(-1), _WidthBytes(-1), _Size(-1), _CompressedSize(-1), _BitPerPixel(-1), _Planes(-1), _dib(NULL) { +} + +psdThumbnail::~psdThumbnail() { + FreeImage_Unload(_dib); +} + +int psdThumbnail::Read(FreeImageIO *io, fi_handle handle, int iResourceSize, bool isBGR) { + BYTE ShortValue[2], IntValue[4]; + int nBytes=0, n; + + // remove the header size (28 bytes) from the total data size + int iTotalData = iResourceSize - 28; + + const long block_end = io->tell_proc(handle) + iTotalData; + + 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) ); + + const long JFIF_startpos = io->tell_proc(handle); + + if(_dib) { + FreeImage_Unload(_dib); + } + + if(_Format == 1) { + // kJpegRGB thumbnail image + _dib = FreeImage_LoadFromHandle(FIF_JPEG, io, handle); + if(isBGR) { + SwapRedBlue32(_dib); + } + // HACK: manually go to end of thumbnail, because (for some reason) LoadFromHandle consumes more bytes then available! + io->seek_proc(handle, block_end, SEEK_SET); + } + else { + // kRawRGB thumbnail image + // ### Unimplemented (should be trivial) + + // skip the thumbnail part + io->seek_proc(handle, iTotalData, SEEK_CUR); + return iResourceSize; + } + + nBytes += (block_end - JFIF_startpos); + + return nBytes; +} + +//--------------------------------------------------------------------------- + +psdICCProfile::psdICCProfile() : _ProfileSize(0), _ProfileData(NULL) { +} + +psdICCProfile::~psdICCProfile() { + clear(); +} + +void psdICCProfile::clear() { SAFE_DELETE_ARRAY(_ProfileData); _ProfileSize = 0;} + +int psdICCProfile::Read(FreeImageIO *io, fi_handle handle, int size) { + int nBytes = 0, n; + + clear(); + + _ProfileData = new (std::nothrow) BYTE[size]; + if(NULL != _ProfileData) { + n = (int)io->read_proc(_ProfileData, 1, size, handle); + _ProfileSize = size; + nBytes += n * sizeof(BYTE); + } + + return nBytes; +} + +//--------------------------------------------------------------------------- + +/** +Invert only color components, skipping Alpha/Black +(Can be useful as public/utility function) +*/ +static +BOOL invertColor(FIBITMAP* dib) { + FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); + const unsigned Bpp = FreeImage_GetBPP(dib)/8; + + if ((type == FIT_BITMAP && Bpp == 4) || type == FIT_RGBA16) { + const unsigned width = FreeImage_GetWidth(dib); + const unsigned height = FreeImage_GetHeight(dib); + BYTE *line_start = FreeImage_GetScanLine(dib, 0); + const unsigned pitch = FreeImage_GetPitch(dib); + const unsigned triBpp = Bpp - (Bpp == 4 ? 1 : 2); + + for(unsigned y = 0; y < height; y++) { + BYTE *line = line_start; + + for(unsigned x = 0; x < width; x++) { + for(unsigned b=0; b < triBpp; ++b) { + line[b] = ~line[b]; + } + + line += Bpp; + } + line_start += pitch; + } + + return TRUE; + } + else { + return FreeImage_Invert(dib); + } +} + +//--------------------------------------------------------------------------- + +psdParser::psdParser() { + _bThumbnailFilled = false; + _bDisplayInfoFilled = false; + _bResolutionInfoFilled = false; + _bResolutionInfoFilled_v2 = false; + _bCopyright = false; + _GlobalAngle = 30; + _ColourCount = -1; + _TransparentIndex = -1; + _fi_flags = 0; + _fi_format_id = FIF_UNKNOWN; +} + +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); + } + + if ( nBytes == nTotalBytes ) { + bSuccess = true; + } + + return bSuccess; +} + +bool psdParser::ReadImageResources(FreeImageIO *io, fi_handle handle, LONG length) { + psdImageResource oResource; + bool bSuccess = false; + + if(length > 0) { + oResource._Length = length; + } else { + 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) { + int n = 0; + oResource.Reset(); + + n = (int)io->read_proc(&oResource._OSType, sizeof(oResource._OSType), 1, handle); + nBytes += n * sizeof(oResource._OSType); + + if ( (nBytes % 2) != 0 ) { + return false; + } + + 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); + nBytes += _thumbnail.Read(io, handle, oResource._Size, 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 + unsigned skip_length = MIN(oResource._Size, nTotalBytes - nBytes); + io->seek_proc(handle, skip_length, SEEK_CUR); + nBytes += skip_length; + } + break; + } + } + } + } + + if (nBytes == nTotalBytes) { + bSuccess = true; + } + + return bSuccess; + +} + +FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) { + if(handle == NULL) + return NULL; + + bool header_only = (_fi_flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + WORD nCompression = 0; + io->read_proc(&nCompression, sizeof(nCompression), 1, handle); + +#ifndef FREEIMAGE_BIGENDIAN + SwapShort(&nCompression); +#endif + + if ((nCompression != PSDP_COMPRESSION_NONE && nCompression != PSDP_COMPRESSION_RLE)) { + FreeImage_OutputMessageProc(_fi_format_id, "Unsupported compression %d", nCompression); + return NULL; + } + + const unsigned nWidth = _headerInfo._Width; + const unsigned nHeight = _headerInfo._Height; + const unsigned nChannels = _headerInfo._Channels; + const unsigned depth = _headerInfo._BitsPerChannel; + const unsigned bytes = (depth == 1) ? 1 : depth / 8; + + // channel(plane) line (BYTE aligned) + const unsigned lineSize = (_headerInfo._BitsPerChannel == 1) ? (nWidth + 7) / 8 : nWidth * bytes; + + if(nCompression == PSDP_COMPRESSION_RLE && depth > 16) { + FreeImage_OutputMessageProc(_fi_format_id, "Unsupported RLE with depth %d", depth); + return NULL; + } + + // build output buffer + + FIBITMAP* bitmap = NULL; + unsigned dstCh = 0; + + short mode = _headerInfo._ColourMode; + + if(mode == PSDP_MULTICHANNEL && nChannels < 3) { + // CM + mode = PSDP_GRAYSCALE; // C as gray, M as extra channel + } + + bool needPalette = false; + switch (mode) { + case PSDP_BITMAP: + case PSDP_DUOTONE: + case PSDP_INDEXED: + case PSDP_GRAYSCALE: + dstCh = 1; + switch(depth) { + case 16: + bitmap = FreeImage_AllocateHeaderT(header_only, FIT_UINT16, nWidth, nHeight, depth*dstCh); + break; + case 32: + bitmap = FreeImage_AllocateHeaderT(header_only, FIT_FLOAT, nWidth, nHeight, depth*dstCh); + break; + default: // 1-, 8- + needPalette = true; + bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); + break; + } + break; + case PSDP_RGB: + case PSDP_LAB: + case PSDP_CMYK : + case PSDP_MULTICHANNEL : + // force PSDP_MULTICHANNEL CMY as CMYK + dstCh = (mode == PSDP_MULTICHANNEL && !header_only) ? 4 : MIN(nChannels, 4); + if(dstCh < 3) { + throw "Invalid number of channels"; + } + + switch(depth) { + case 16: + bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGB16 : FIT_RGBA16, nWidth, nHeight, depth*dstCh); + break; + case 32: + bitmap = FreeImage_AllocateHeaderT(header_only, dstCh < 4 ? FIT_RGBF : FIT_RGBAF, nWidth, nHeight, depth*dstCh); + break; + default: + bitmap = FreeImage_AllocateHeader(header_only, nWidth, nHeight, depth*dstCh); + break; + } + break; + default: + throw "Unsupported color mode"; + break; + } + if (!bitmap) { + throw FI_MSG_ERROR_DIB_MEMORY; + } + + // write thumbnail + FreeImage_SetThumbnail(bitmap, _thumbnail.getDib()); + + // @todo Add some metadata model + + if(header_only) { + return bitmap; + } + + // Load pixels data + + const unsigned dstChannels = dstCh; + + const unsigned dstBpp = (depth == 1) ? 1 : FreeImage_GetBPP(bitmap)/8; + const unsigned dstLineSize = FreeImage_GetPitch(bitmap); + BYTE* const dst_first_line = FreeImage_GetScanLine(bitmap, nHeight - 1);//<*** flipped + + BYTE* line_start = new BYTE[lineSize]; //< fileline cache + + switch ( nCompression ) { + case PSDP_COMPRESSION_NONE: // raw data + { + for(unsigned c = 0; c < nChannels; c++) { + if(c >= dstChannels) { + // @todo write extra channels + break; + } + + const unsigned channelOffset = c * bytes; + + BYTE* dst_line_start = dst_first_line; + for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped + + io->read_proc(line_start, lineSize, 1, handle); + + for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; + line += bytes, dst_line += dstBpp) { +#ifdef FREEIMAGE_BIGENDIAN + memcpy(dst_line + channelOffset, line, bytes); +#else + // reverse copy bytes + for (unsigned b = 0; b < bytes; ++b) { + dst_line[channelOffset + b] = line[(bytes-1) - b]; + } +#endif // FREEIMAGE_BIGENDIAN + } + } //< h + }//< ch + + SAFE_DELETE_ARRAY(line_start); + + } + break; + + case PSDP_COMPRESSION_RLE: // RLE compression + { + + // The RLE-compressed data is preceeded by a 2-byte line size for each row in the data, + // store an array of these + + // later use this array as WORD rleLineSizeList[nChannels][nHeight]; + WORD *rleLineSizeList = new (std::nothrow) WORD[nChannels*nHeight]; + + if (!rleLineSizeList) { + FreeImage_Unload(bitmap); + SAFE_DELETE_ARRAY(line_start); + throw std::bad_alloc(); + } + + io->read_proc(rleLineSizeList, 2, nChannels * nHeight, handle); + + WORD largestRLELine = 0; + for(unsigned ch = 0; ch < nChannels; ++ch) { + for(unsigned h = 0; h < nHeight; ++h) { + const unsigned index = ch * nHeight + h; + +#ifndef FREEIMAGE_BIGENDIAN + SwapShort(&rleLineSizeList[index]); +#endif + if(largestRLELine < rleLineSizeList[index]) { + largestRLELine = rleLineSizeList[index]; + } + } + } + + BYTE* rle_line_start = new (std::nothrow) BYTE[largestRLELine]; + if (!rle_line_start) { + FreeImage_Unload(bitmap); + SAFE_DELETE_ARRAY(line_start); + SAFE_DELETE_ARRAY(rleLineSizeList); + throw std::bad_alloc(); + } + + // Read the RLE data (assume 8-bit) + + const BYTE* const line_end = line_start + lineSize; + + for (unsigned ch = 0; ch < nChannels; ch++) { + const unsigned channelOffset = ch * bytes; + + BYTE* dst_line_start = dst_first_line; + for(unsigned h = 0; h < nHeight; ++h, dst_line_start -= dstLineSize) {//<*** flipped + const unsigned index = ch * nHeight + h; + + // - read and uncompress line - + + const WORD rleLineSize = rleLineSizeList[index]; + + io->read_proc(rle_line_start, rleLineSize, 1, handle); + + for (BYTE* rle_line = rle_line_start, *line = line_start; + rle_line < rle_line_start + rleLineSize, line < line_end;) { + + int len = *rle_line++; + + // NOTE len is signed byte in PackBits RLE + + if ( len < 128 ) { //<- MSB is not set + // uncompressed packet + + // (len + 1) bytes of data are copied + + ++len; + + // assert we don't write beyound eol + memcpy(line, rle_line, line + len > line_end ? line_end - line : len); + line += len; + rle_line += len; + } + else if ( len > 128 ) { //< MSB is set + + // RLE compressed packet + + // One byte of data is repeated (–len + 1) times + + len ^= 0xFF; // same as (-len + 1) & 0xFF + len += 2; // + + // assert we don't write beyound eol + memset(line, *rle_line++, line + len > line_end ? line_end - line : len); + line += len; + + } + else if ( 128 == len ) { + // Do nothing + } + }//< rle_line + + // - write line to destination - + + if(ch >= dstChannels) { + // @todo write to extra channels + break; + } + + // byte by byte copy a single channel to pixel + for (BYTE *line = line_start, *dst_line = dst_line_start; line < line_start + lineSize; + line += bytes, dst_line += dstBpp) { + +#ifdef FREEIMAGE_BIGENDIAN + memcpy(dst_line + channelOffset, line, bytes); +#else + // reverse copy bytes + for (unsigned b = 0; b < bytes; ++b) { + dst_line[channelOffset + b] = line[(bytes-1) - b]; + } +#endif // FREEIMAGE_BIGENDIAN + } + }//< h + }//< ch + + SAFE_DELETE_ARRAY(line_start); + SAFE_DELETE_ARRAY(rleLineSizeList); + SAFE_DELETE_ARRAY(rle_line_start); + } + break; + + case 2: // ZIP without prediction, no specification + break; + + case 3: // ZIP with prediction, no specification + break; + + default: // Unknown format + break; + + } + + // --- Further process the bitmap --- + + if ((mode == PSDP_CMYK || mode == PSDP_MULTICHANNEL)) { + // CMYK values are "inverted", invert them back + + if(mode == PSDP_MULTICHANNEL) { + invertColor(bitmap); + } else { + FreeImage_Invert(bitmap); + } + + if ((_fi_flags & PSD_CMYK) == PSD_CMYK) { + // keep as CMYK + + if(mode == PSDP_MULTICHANNEL) { + //### we force CMY to be CMYK, but CMY has no ICC. + // Create empty profile and add the flag. + FreeImage_CreateICCProfile(bitmap, NULL, 0); + FreeImage_GetICCProfile(bitmap)->flags |= FIICC_COLOR_IS_CMYK; + } + } + else { + // convert to RGB + + ConvertCMYKtoRGBA(bitmap); + + // The ICC Profile is no longer valid + _iccProfile.clear(); + + // remove the pending A if not present in source + if(nChannels == 4 || nChannels == 3 ) { + FIBITMAP* t = RemoveAlphaChannel(bitmap); + if(t) { + FreeImage_Unload(bitmap); + bitmap = t; + } // else: silently fail + } + } + } + else if ( mode == PSDP_LAB && !((_fi_flags & PSD_LAB) == PSD_LAB)) { + ConvertLABtoRGB(bitmap); + } + else { + if (needPalette && FreeImage_GetPalette(bitmap)) { + + if(mode == PSDP_BITMAP) { + CREATE_GREYSCALE_PALETTE_REVERSE(FreeImage_GetPalette(bitmap), 2); + } + else if(mode == PSDP_INDEXED) { + if (!_colourModeData._plColourData || _colourModeData._Length != 768 || _ColourCount < 0) { + FreeImage_OutputMessageProc(_fi_format_id, "Indexed image has no palette. Using the default grayscale one."); + } else { + _colourModeData.FillPalette(bitmap); + } + } + // GRAYSCALE, DUOTONE - use default grayscale palette + } + +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + if(FreeImage_GetImageType(bitmap) == FIT_BITMAP) { + SwapRedBlue32(bitmap); + } +#endif + } + + return bitmap; +} + +FIBITMAP* psdParser::Load(FreeImageIO *io, fi_handle handle, int s_format_id, int flags) { + FIBITMAP *Bitmap = NULL; + + _fi_flags = flags; + _fi_format_id = s_format_id; + + 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 (!ReadImageResources(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 + FreeImage_CreateICCProfile(Bitmap, _iccProfile._ProfileData, _iccProfile._ProfileSize); + if ((flags & PSD_CMYK) == PSD_CMYK) { + short mode = _headerInfo._ColourMode; + if ((mode == PSDP_CMYK) || (mode == PSDP_MULTICHANNEL)) { + FreeImage_GetICCProfile(Bitmap)->flags |= FIICC_COLOR_IS_CMYK; + } + } + + } catch(const char *text) { + FreeImage_OutputMessageProc(s_format_id, text); + } + catch(const std::exception& e) { + FreeImage_OutputMessageProc(s_format_id, "%s", e.what()); + } + + return Bitmap; +} diff --git a/plugins/FreeImage/src/FreeImage/PSDParser.h b/plugins/FreeImage/src/FreeImage/PSDParser.h new file mode 100644 index 0000000000..15ab5425ca --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PSDParser.h @@ -0,0 +1,271 @@ +// ========================================================== +// Photoshop Loader +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// - Mihail Naydenov (mnaydenov@users.sourceforge.net) +// +// 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]; //! Number 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 _BitsPerChannel;//! 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. + FIBITMAP * _dib; //! JFIF data as uncompressed dib. Note: For resource ID 1033 the data is in BGR format. + +public: + psdThumbnail(); + ~psdThumbnail(); + FIBITMAP* getDib() { return _dib; } + /** + @return Returns the number of bytes read + */ + int Read(FreeImageIO *io, fi_handle handle, int iResourceSize, bool isBGR); + +private: + psdThumbnail(const psdThumbnail&); + psdThumbnail& operator=(const psdThumbnail&); +}; + +class psdICCProfile { +public: + int _ProfileSize; + BYTE * _ProfileData; +public: + psdICCProfile(); + ~psdICCProfile(); + void clear(); + /** + @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; + + int _fi_flags; + int _fi_format_id; + +private: + /** Actually ignore it */ + bool ReadLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle); + FIBITMAP* ReadImageData(FreeImageIO *io, fi_handle handle); + +public: + psdParser(); + ~psdParser(); + FIBITMAP* Load(FreeImageIO *io, fi_handle handle, int s_format_id, int flags=0); + /** Also used by the TIFF plugin */ + bool ReadImageResources(FreeImageIO *io, fi_handle handle, LONG length=0); + /** Used by the TIFF plugin */ + FIBITMAP* GetThumbnail() { + return _thumbnail.getDib(); + } +}; + +#endif // PSDPARSER_H + diff --git a/plugins/FreeImage/src/FreeImage/PixelAccess.cpp b/plugins/FreeImage/src/FreeImage/PixelAccess.cpp new file mode 100644 index 0000000000..158f9997b2 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PixelAccess.cpp @@ -0,0 +1,209 @@ +// ========================================================== +// 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 (!FreeImage_HasPixels(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) { + if (!FreeImage_HasPixels(dib)) { + return NULL; + } + return CalculateScanLine(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), scanline); +} + +BOOL DLL_CALLCONV +FreeImage_GetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value) { + BYTE shift; + + if (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImage/Plugin.cpp b/plugins/FreeImage/src/FreeImage/Plugin.cpp new file mode 100644 index 0000000000..ce2863a72e --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/Plugin.cpp @@ -0,0 +1,747 @@ +// ===================================================================== +// 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 +#include +#else +#include +#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 + // note we have memset to 0, so all unset pointers should be NULL) + + 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_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::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::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::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::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(std::nothrow) 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(InitJNG); + //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); + //s_plugins->AddNode(InitEXR); + //s_plugins->AddNode(InitJ2K); + //s_plugins->AddNode(InitJP2); + //s_plugins->AddNode(InitPFM); + //s_plugins->AddNode(InitPICT); + //s_plugins->AddNode(InitRAW); + } + } +} + +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) { + // cannot save "header only" formats + if(FreeImage_HasPixels(dib) == FALSE) { + FreeImage_OutputMessageProc((int)fif, "FreeImage_SaveToHandle: cannot save \"header only\" formats"); + return FALSE; + } + + 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 = LoadLibraryA(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; +} + +BOOL DLL_CALLCONV +FreeImage_FIFSupportsNoPixels(FREE_IMAGE_FORMAT fif) { + if (s_plugins != NULL) { + PluginNode *node = s_plugins->FindNodeFromFIF(fif); + + return (node != NULL) ? + (node->m_plugin->supports_no_pixels_proc != NULL) ? + node->m_plugin->supports_no_pixels_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/plugins/FreeImage/src/FreeImage/PluginBMP.cpp b/plugins/FreeImage/src/FreeImage/PluginBMP.cpp new file mode 100644 index 0000000000..d69336f3f5 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginBMP.cpp @@ -0,0 +1,1480 @@ +// ========================================================== +// 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) +@return Returns TRUE if successful, returns FALSE otherwise +*/ +static BOOL +LoadPixelData(FreeImageIO *io, fi_handle handle, FIBITMAP *dib, int height, unsigned pitch, unsigned bit_count) { + unsigned count = 0; + + // Load pixel data + // NB: height can be < 0 for BMP data + if (height > 0) { + count = io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle); + if(count != 1) { + return FALSE; + } + } else { + int positiveHeight = abs(height); + for (int c = 0; c < positiveHeight; ++c) { + count = io->read_proc((void *)FreeImage_GetScanLine(dib, positiveHeight - c - 1), pitch, 1, handle); + if(count != 1) { + return FALSE; + } + } + } + + // 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 + + return TRUE; +} + +/** +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 { + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // 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 + + unsigned 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 + unsigned bit_count = bih.biBitCount; + unsigned compression = bih.biCompression; + unsigned 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_AllocateHeader(header_only, 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 + + if(header_only) { + // header only mode + return dib; + } + + // 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 : + if ( LoadPixelData(io, handle, dib, height, pitch, bit_count)) { + return dib; + } else { + throw "Error encountered while decoding BMP data"; + } + break; + + 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_AllocateHeader(header_only, width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]); + } else { + dib = FreeImage_AllocateHeader(header_only, 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(header_only) { + // header only mode + return dib; + } + + // load pixel data and swap as needed if OS is Big Endian + + if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))) { + // seek to the actual pixel data + io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); + } + + 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_AllocateHeader(header_only, width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]); + } else { + if ( bit_count == 32 ) { + dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeader(header_only, 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); + + if(header_only) { + // header only mode + return dib; + } + + // 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 { + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // 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 + + unsigned 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 + unsigned bit_count = bih.biBitCount; + unsigned compression = bih.biCompression; + unsigned 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_AllocateHeader(header_only, 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 + // note that it may contain RGB or RGBA values : we will calculate this + unsigned pal_size = (bitmap_bits_offset - sizeof(BITMAPFILEHEADER) - bih.biSize) / used_colors; + + io->seek_proc(handle, sizeof(BITMAPFILEHEADER) + bih.biSize, SEEK_SET); + + RGBQUAD *pal = FreeImage_GetPalette(dib); + + if(pal_size == 4) { + for (unsigned count = 0; count < used_colors; count++) { + FILE_BGRA bgra; + + io->read_proc(&bgra, sizeof(FILE_BGRA), 1, handle); + + pal[count].rgbRed = bgra.r; + pal[count].rgbGreen = bgra.g; + pal[count].rgbBlue = bgra.b; + } + } else if(pal_size == 3) { + for (unsigned 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; + } + } + + if(header_only) { + // header only mode + return dib; + } + + // 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_AllocateHeader(header_only, width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]); + } else { + dib = FreeImage_AllocateHeader(header_only, 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(header_only) { + // header only mode + return dib; + } + + 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_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeader(header_only, 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); + + if(header_only) { + // header only mode + return dib; + } + + // 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 { + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + 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 + + unsigned used_colors = 0; + unsigned width = bios2_1x.biWidth; + unsigned height = bios2_1x.biHeight; // WARNING: height can be < 0 => check each read_proc using 'height' as a parameter + unsigned bit_count = bios2_1x.biBitCount; + unsigned 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_AllocateHeader(header_only, 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 (unsigned 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; + } + + if(header_only) { + // header only mode + return dib; + } + + // 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_AllocateHeader(header_only, 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); + + if(header_only) { + // header only mode + return dib; + } + + // 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_AllocateHeader(header_only, width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeader(header_only, 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); + + if(header_only) { + // header only mode + return dib; + } + + // 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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + if (handle != NULL) { + BITMAPFILEHEADER bitmapfileheader; + DWORD type = 0; + + // we use this offset value to make seemingly absolute seeks relative in the file + + long offset_in_file = io->tell_proc(handle); + + // read the fileheader + + io->read_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle); +#ifdef FREEIMAGE_BIGENDIAN + SwapFileHeader(&bitmapfileheader); +#endif + + // check the signature + + if ((bitmapfileheader.bfType != 0x4D42) && (bitmapfileheader.bfType != 0x4142)) { + FreeImage_OutputMessageProc(s_format_id, FI_MSG_ERROR_MAGIC_NUMBER); + return NULL; + } + + // read the first byte of the infoheader + + io->read_proc(&type, sizeof(DWORD), 1, handle); + io->seek_proc(handle, 0 - (long)sizeof(DWORD), SEEK_CUR); +#ifdef FREEIMAGE_BIGENDIAN + SwapLong(&type); +#endif + + // call the appropriate load function for the found bitmap type + + switch(type) { + case 12: + // OS/2 and also all Windows versions since Windows 3.0 + return LoadOS21XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); + case 64: + // OS/2 + return LoadOS22XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); + case 40: + // BITMAPINFOHEADER - all Windows versions since Windows 3.0 + return LoadWindowsBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits); + case 52: + // BITMAPV2INFOHEADER (undocumented) + break; + case 56: + // BITMAPV3INFOHEADER (undocumented) + break; + case 108: + // BITMAPV4HEADER - all Windows versions since Windows 95/NT4 (not supported) + break; + case 124: + // BITMAPV5HEADER - Windows 98/2000 and newer (not supported) + break; + default: + break; + } + + 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 = (BYTE*)malloc(FreeImage_GetPitch(dib) * 2 * sizeof(BYTE)); + + 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) { + free(buffer); + return FALSE; + } + } + + buffer[0] = RLE_COMMAND; + buffer[1] = RLE_ENDOFBITMAP; + + if (io->write_proc(buffer, 2, 1, handle) != 1) { + free(buffer); + return FALSE; + } + + free(buffer); +#ifdef FREEIMAGE_BIGENDIAN + } else if (bpp == 16) { + int padding = FreeImage_GetPitch(dib) - FreeImage_GetWidth(dib) * sizeof(WORD); + WORD pad = 0; + WORD pixel; + for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + BYTE *line = FreeImage_GetScanLine(dib, y); + for(unsigned 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(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + BYTE *line = FreeImage_GetScanLine(dib, y); + for(unsigned 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(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + BYTE *line = FreeImage_GetScanLine(dib, y); + for(unsigned 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginCUT.cpp b/plugins/FreeImage/src/FreeImage/PluginCUT.cpp new file mode 100644 index 0000000000..746fa034a6 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginCUT.cpp @@ -0,0 +1,240 @@ +// ========================================================== +// 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 { + WORD width; + WORD height; + LONG 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/x-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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + FIBITMAP *dib = NULL; + + if (!handle) { + return NULL; + } + + try { + CUTHEADER header; + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // read the cut header + + if(io->read_proc(&header, 1, sizeof(CUTHEADER), handle) != sizeof(CUTHEADER)) { + throw FI_MSG_ERROR_PARSING; + } + +#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_AllocateHeader(header_only, header.width, header.height, 8); + + if (dib == NULL) { + throw FI_MSG_ERROR_DIB_MEMORY; + } + + // 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; + } + + if(header_only) { + // header only mode + return dib; + } + + // unpack the RLE bitmap bits + + BYTE *bits = FreeImage_GetScanLine(dib, header.height - 1); + + unsigned i = 0, k = 0; + unsigned pitch = FreeImage_GetPitch(dib); + unsigned size = header.width * header.height; + BYTE count = 0, run = 0; + + while (i < size) { + if(io->read_proc(&count, 1, sizeof(BYTE), handle) != 1) { + throw FI_MSG_ERROR_PARSING; + } + + 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); + + if(io->read_proc(&run, 1, sizeof(BYTE), handle) != 1) { + throw FI_MSG_ERROR_PARSING; + } + + if(k + count <= header.width) { + memset(bits + k, run, count); + } else { + throw FI_MSG_ERROR_PARSING; + } + } else { + if(k + count <= header.width) { + if(io->read_proc(&bits[k], count, sizeof(BYTE), handle) != 1) { + throw FI_MSG_ERROR_PARSING; + } + } else { + throw FI_MSG_ERROR_PARSING; + } + } + + k += count; + i += count; + } + + return dib; + + } catch(const char* text) { + if(dib) { + FreeImage_Unload(dib); + } + FreeImage_OutputMessageProc(s_format_id, text); + 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginDDS.cpp b/plugins/FreeImage/src/FreeImage/PluginDDS.cpp new file mode 100644 index 0000000000..0a1667d7f1 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginDDS.cpp @@ -0,0 +1,651 @@ +// ========================================================== +// 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 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 { +public: + typedef DXT_INFO_1 INFO; +}; + +class DXT_BLOCKDECODER_3 : public DXT_BLOCKDECODER_BASE { +public: + typedef DXT_BLOCKDECODER_BASE 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 { +public: + typedef DXT_BLOCKDECODER_BASE 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 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 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(std::nothrow) Block[(width + 3) / 4]; + if (!input_buffer) return; + + 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 (pbDst, pbSrc, line, 4, 4); + pbSrc += INFO::bytesPerBlock; + pbDst += 4 * 4; + } + } + if (widthRest) { + DecodeDXTBlock (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 (pbDst, pbSrc, line, 4, heightRest); + pbSrc += INFO::bytesPerBlock; + pbDst += 4 * 4; + } + } + if (widthRest) { + DecodeDXTBlock (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 (io, handle, page, flags, data, dib, width, height, line); + break; + case 3: + LoadDXT_Helper (io, handle, page, flags, data, dib, width, height, line); + break; + case 5: + LoadDXT_Helper (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/x-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 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/plugins/FreeImage/src/FreeImage/PluginEXR.cpp b/plugins/FreeImage/src/FreeImage/PluginEXR.cpp new file mode 100644 index 0000000000..b9963a11b2 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginEXR.cpp @@ -0,0 +1,764 @@ +// ========================================================== +// EXR Loader and writer +// +// 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 "../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/IlmImf/ImfPreviewImage.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/x-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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// -------------------------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + bool bUseRgbaInterface = false; + FIBITMAP *dib = NULL; + + if (!handle) { + return NULL; + } + + try { + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // save the stream starting point + const 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(); + + 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 ((components == 1) && channels.findChannel("Y")) { + image_type = FIT_FLOAT; + components = 1; + } else { + 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; + // ignore the other channel + components = 1; + } + } 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")) { + if(channels.findChannel("A")) { + if(components > 4) { + std::string msg = "Warning: converting color model " + exr_color_model + " to RGBA color model"; + FreeImage_OutputMessageProc(s_format_id, msg.c_str()); + } + image_type = FIT_RGBAF; + // ignore other layers if there is more than one alpha layer + components = 4; + } else { + std::string msg = "Warning: converting color model " + exr_color_model + " to RGB color model"; + FreeImage_OutputMessageProc(s_format_id, msg.c_str()); + + image_type = FIT_RGBF; + // ignore other channels + components = 3; + } + } + } + + if(image_type == FIT_UNKNOWN) { + THROW (Iex::InputExc, "Unsupported color model: " << exr_color_model); + } + + // allocate a new dib + dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, 0); + if (!dib) THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY); + + // try to load the preview image + // -------------------------------------------------------------- + + if(file.header().hasPreviewImage()) { + const Imf::PreviewImage& preview = file.header().previewImage(); + const unsigned thWidth = preview.width(); + const unsigned thHeight = preview.height(); + + FIBITMAP* thumbnail = FreeImage_Allocate(thWidth, thHeight, 32); + if(thumbnail) { + const Imf::PreviewRgba *src_line = preview.pixels(); + BYTE *dst_line = FreeImage_GetScanLine(thumbnail, thHeight - 1); + const unsigned dstPitch = FreeImage_GetPitch(thumbnail); + + for (unsigned y = 0; y < thHeight; ++y) { + const Imf::PreviewRgba *src_pixel = src_line; + RGBQUAD* dst_pixel = (RGBQUAD*)dst_line; + + for(unsigned x = 0; x < thWidth; ++x) { + dst_pixel->rgbRed = src_pixel->r; + dst_pixel->rgbGreen = src_pixel->g; + dst_pixel->rgbBlue = src_pixel->b; + dst_pixel->rgbReserved = src_pixel->a; + src_pixel++; + dst_pixel++; + } + src_line += thWidth; + dst_line -= dstPitch; + } + FreeImage_SetThumbnail(dib, thumbnail); + FreeImage_Unload(thumbnail); + } + } + + if(header_only) { + // header only mode + return dib; + } + + // load pixels + // -------------------------------------------------------------- + + const BYTE *bits = FreeImage_GetBits(dib); // pointer to our pixel buffer + const size_t bytespp = sizeof(float) * components; // size of our pixel in bytes + const 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 (used when loading RY BY Y images ) + + 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 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; + + // allow dataWindow with minimal bounds different form zero + size_t offset = - dataWindow.min.x * bytespp - dataWindow.min.y * pitch; + + if(components == 1) { + frameBuffer.insert ("Y", // name + Imf::Slice (pixelType, // type + (char*)(bits + offset), // 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) + offset), // 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; +} + +/** +Set the preview image using the dib embedded thumbnail +*/ +static BOOL +SetPreviewImage(FIBITMAP *dib, Imf::Header& header) { + if (!FreeImage_GetThumbnail(dib)) { + return FALSE; + } + FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); + + if ((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 32)) { + // invalid thumbnail - ignore it + FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL); + } else { + const unsigned thWidth = FreeImage_GetWidth(thumbnail); + const unsigned thHeight = FreeImage_GetHeight(thumbnail); + + Imf::PreviewImage preview(thWidth, thHeight); + + // copy thumbnail to 32-bit RGBA preview image + + const BYTE* src_line = FreeImage_GetScanLine(thumbnail, thHeight - 1); + Imf::PreviewRgba* dst_line = preview.pixels(); + const unsigned srcPitch = FreeImage_GetPitch(thumbnail); + + for (unsigned y = 0; y < thHeight; y++) { + const RGBQUAD* src_pixel = (RGBQUAD*)src_line; + Imf::PreviewRgba* dst_pixel = dst_line; + + for(unsigned x = 0; x < thWidth; x++) { + dst_pixel->r = src_pixel->rgbRed; + dst_pixel->g = src_pixel->rgbGreen; + dst_pixel->b = src_pixel->rgbBlue; + dst_pixel->a = src_pixel->rgbReserved; + + src_pixel++; + dst_pixel++; + } + + src_line -= srcPitch; + dst_line += thWidth; + } + + header.setPreviewImage(preview); + } + + return TRUE; +} + +/** +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 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); + + // handle thumbnail + SetPreviewImage(dib, header); + + // 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(std::nothrow) 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginG3.cpp b/plugins/FreeImage/src/FreeImage/PluginG3.cpp new file mode 100644 index 0000000000..c383a455b7 --- /dev/null +++ b/plugins/FreeImage/src/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 "../LibTIFF4/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 tmsize_t +_g3ReadProc(thandle_t handle, void *buf, tmsize_t size) { + // returns an error when reading the TIFF header + return 0; +} + +static tmsize_t +_g3WriteProc(thandle_t handle, void *buf, tmsize_t size) { + // returns ok when writing the TIFF header + return size; +} + +static toff_t +_g3SeekProc(thandle_t handle, toff_t off, int whence) { + return 0; +} + +static int +_g3CloseProc(thandle_t handle) { + return 0; +} + +static toff_t +_g3SizeProc(thandle_t handle) { + return 0; +} + +static int +_g3MapProc(thandle_t, void** base, toff_t* size) { + return 0; +} + +static void +_g3UnmapProc(thandle_t, void* base, toff_t size) { +} + +// -------------------------------------------------------------- + +static tmsize_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, uint8 *tif_rawdata, tmsize_t tif_rawdatasize) { + return ((tmsize_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, (uint16) 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/plugins/FreeImage/src/FreeImage/PluginGIF.cpp b/plugins/FreeImage/src/FreeImage/PluginGIF.cpp new file mode 100644 index 0000000000..7af1d821d8 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginGIF.cpp @@ -0,0 +1,1398 @@ +// ========================================================== +// GIF Loader and Writer +// +// Design and implementation by +// - Ryan Rubley +// - Raphaël Gaquer +// +// 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 application_extension_offsets; + std::vector comment_extension_offsets; + std::vector graphic_control_extension_offsets; + std::vector 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 = new(std::nothrow) 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(std::nothrow) BYTE[len]; + m_bufferRealSize = len; + } else if ( len > m_bufferRealSize ) { + delete [] m_buffer; + m_buffer = new(std::nothrow) 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 : + // | + 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(std::nothrow) 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; + 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(std::nothrow) 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(std::nothrow) 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 + w - b, 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/plugins/FreeImage/src/FreeImage/PluginHDR.cpp b/plugins/FreeImage/src/FreeImage/PluginHDR.cpp new file mode 100644 index 0000000000..a0334e1143 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginHDR.cpp @@ -0,0 +1,719 @@ +// ========================================================== +// 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 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]; + + const 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/vnd.radiance"; +} + +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 FALSE; +} + +static BOOL DLL_CALLCONV +SupportsExportType(FREE_IMAGE_TYPE type) { + return (type == FIT_RGBF) ? TRUE : FALSE; +} + +static BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// -------------------------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + FIBITMAP *dib = NULL; + + if (!handle) { + return NULL; + } + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + 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_AllocateHeaderT(header_only, FIT_RGBF, width, height); + if (!dib) { + throw FI_MSG_ERROR_MEMORY; + } + + // set the metadata as comments + rgbe_ReadMetadata(dib, &header_info); + + if(header_only) { + // header only mode + return dib; + } + + // 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; + } + } + + } + 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginICO.cpp b/plugins/FreeImage/src/FreeImage/PluginICO.cpp new file mode 100644 index 0000000000..d0ece3514c --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginICO.cpp @@ -0,0 +1,805 @@ +// ========================================================== +// 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& 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/vnd.microsoft.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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +static void * DLL_CALLCONV +Open(FreeImageIO *io, fi_handle handle, BOOL read) { + // Allocate memory for the header structure + ICONHEADER *lpIH = (ICONHEADER*)malloc(sizeof(ICONHEADER)); + if(lpIH == 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* +LoadStandardIcon(FreeImageIO *io, fi_handle handle, int flags, BOOL header_only) { + FIBITMAP *dib = NULL; + + // 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 + unsigned bit_count = bmih.biBitCount; + unsigned line = CalculateLine(width, bit_count); + unsigned pitch = CalculatePitch(line); + + // allocate memory for one icon + + dib = FreeImage_AllocateHeader(header_only, 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(unsigned i = 0; i < CalculateUsedPaletteEntries(bit_count); i++) { + INPLACESWAP(pal[i].rgbRed, pal[i].rgbBlue); + } +#endif + } + + if(header_only) { + // header only mode + return dib; + } + + // 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 dib; +} + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + if (page == -1) { + page = 0; + } + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + 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)); + if(icon_list == NULL) { + return NULL; + } + 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); + + if ((icon_list[page].bWidth == 0) && (icon_list[page].bHeight == 0)) { + // Vista icon support + dib = FreeImage_LoadFromHandle(FIF_PNG, io, handle, header_only ? FIF_LOAD_NOPIXELS : PNG_DEFAULT); + } + else { + // standard icon support + // see http://msdn.microsoft.com/en-us/library/ms997538.aspx + dib = LoadStandardIcon(io, handle, flags, header_only); + } + + free(icon_list); + + return 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 +SaveStandardIcon(FreeImageIO *io, FIBITMAP *dib, fi_handle handle) { + BITMAPINFOHEADER *bmih = NULL; + + // write the BITMAPINFOHEADER + bmih = FreeImage_GetInfoHeader(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(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; + io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle); + } + } + + // write the bits + int width = bmih->biWidth; + int height = bmih->biHeight; + unsigned bit_count = bmih->biBitCount; + unsigned line = CalculateLine(width, bit_count); + unsigned 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(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + BYTE *line = FreeImage_GetScanLine(dib, y); + for(unsigned 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; + } + } + } else +#endif +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB + if (bit_count == 24) { + FILE_BGR bgr; + for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + BYTE *line = FreeImage_GetScanLine(dib, y); + for(unsigned 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; + } + } + } else if (bit_count == 32) { + FILE_BGRA bgra; + for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + BYTE *line = FreeImage_GetScanLine(dib, y); + for(unsigned 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; + } + } + } else +#endif +#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB + { +#endif + BYTE *xor_mask = FreeImage_GetBits(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 (!and_mask) { + return FALSE; + } + + 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); + + return TRUE; +} + +static BOOL DLL_CALLCONV +Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { + ICONHEADER *icon_header = NULL; + std::vector vPages; + int k; + + if (!dib || !handle || !data) { + return FALSE; + } + + // check format limits + unsigned w = FreeImage_GetWidth(dib); + unsigned h = FreeImage_GetHeight(dib); + if ((w < 16) || (w > 256) || (h < 16) || (h > 256) || (w != h)) { + FreeImage_OutputMessageProc(s_format_id, "Unsupported icon size: width x height = %d x %d", w, h); + return FALSE; + } + + if (page == -1) { + page = 0; + } + + // get the icon header + icon_header = (ICONHEADER*)data; + + try { + FIBITMAP *icon_dib = NULL; + + // load all icons + for(k = 0; k < icon_header->idCount; k++) { + icon_dib = Load(io, handle, k, flags, data); + if (!icon_dib) { + throw FI_MSG_ERROR_DIB_MEMORY; + } + 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)); + if (!icon_list) { + throw FI_MSG_ERROR_MEMORY; + } + memset(icon_list, 0, icon_header->idCount * sizeof(ICONDIRENTRY)); + + for(k = 0; k < icon_header->idCount; k++) { + icon_dib = (FIBITMAP*)vPages[k]; + + // convert internal format to ICONDIRENTRY + // take into account Vista icons whose size is 256x256 + const BITMAPINFOHEADER *bmih = FreeImage_GetInfoHeader(icon_dib); + icon_list[k].bWidth = (bmih->biWidth > 255) ? 0 : (BYTE)bmih->biWidth; + icon_list[k].bHeight = (bmih->biHeight > 255) ? 0 : (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)); + } + // initial guess (correct only for standard icons) + icon_list[k].dwBytesInRes = CalculateImageSize(icon_dib); + icon_list[k].dwImageOffset = CalculateImageOffset(vPages, k); + } + + // make a room for icon dir entries, until later update + const long directory_start = io->tell_proc(handle); + io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle); + + // write the image bits for each image + + DWORD dwImageOffset = (DWORD)io->tell_proc(handle); + + for(k = 0; k < icon_header->idCount; k++) { + icon_dib = (FIBITMAP*)vPages[k]; + + if ((icon_list[k].bWidth == 0) && (icon_list[k].bHeight == 0)) { + // Vista icon support + FreeImage_SaveToHandle(FIF_PNG, icon_dib, io, handle, PNG_DEFAULT); + } + else { + // standard icon support + // see http://msdn.microsoft.com/en-us/library/ms997538.aspx + SaveStandardIcon(io, icon_dib, handle); + } + + // update ICONDIRENTRY members + DWORD dwBytesInRes = (DWORD)io->tell_proc(handle) - dwImageOffset; + icon_list[k].dwImageOffset = dwImageOffset; + icon_list[k].dwBytesInRes = dwBytesInRes; + dwImageOffset += dwBytesInRes; + } + + // update the icon descriptions + const long current_pos = io->tell_proc(handle); + io->seek_proc(handle, directory_start, SEEK_SET); +#ifdef FREEIMAGE_BIGENDIAN + SwapIconDirEntries(icon_list, icon_header->idCount); +#endif + io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle); + io->seek_proc(handle, current_pos, SEEK_SET); + + free(icon_list); + + // free the vector class + for(k = 0; k < icon_header->idCount; k++) { + icon_dib = (FIBITMAP*)vPages[k]; + FreeImage_Unload(icon_dib); + } + + return TRUE; + + } catch(const char *text) { + // free the vector class + for(size_t k = 0; k < vPages.size(); k++) { + FIBITMAP *icon_dib = (FIBITMAP*)vPages[k]; + FreeImage_Unload(icon_dib); + } + FreeImage_OutputMessageProc(s_format_id, text); + 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginIFF.cpp b/plugins/FreeImage/src/FreeImage/PluginIFF.cpp new file mode 100644 index 0000000000..b6cd45d6db --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginIFF.cpp @@ -0,0 +1,459 @@ +// ========================================================== +// 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/x-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); + if(pal != NULL) { + unsigned palette_entries = MIN((unsigned)ch_size / 3, FreeImage_GetColorsUsed(dib)); + for (unsigned k = 0; k < palette_entries; 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/plugins/FreeImage/src/FreeImage/PluginJ2K.cpp b/plugins/FreeImage/src/FreeImage/PluginJ2K.cpp new file mode 100644 index 0000000000..6e772afdaa --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginJ2K.cpp @@ -0,0 +1,339 @@ +// ========================================================== +// 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(¶meters); + + 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, ¶meters); + + // 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(¶meters); + + parameters.tcp_numlayers = 0; + // 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, ¶meters); + if (!image) return FALSE; + + // decide if MCT should be used + parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0; + + // 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, ¶meters, 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/plugins/FreeImage/src/FreeImage/PluginJP2.cpp b/plugins/FreeImage/src/FreeImage/PluginJP2.cpp new file mode 100644 index 0000000000..ed1cb267bb --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginJP2.cpp @@ -0,0 +1,339 @@ +// ========================================================== +// 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(¶meters); + + 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, ¶meters); + + // 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(¶meters); + + parameters.tcp_numlayers = 0; + // 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, ¶meters); + if (!image) return FALSE; + + // decide if MCT should be used + parameters.tcp_mct = (image->numcomps == 3) ? 1 : 0; + + // 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, ¶meters, 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/plugins/FreeImage/src/FreeImage/PluginJPEG.cpp b/plugins/FreeImage/src/FreeImage/PluginJPEG.cpp new file mode 100644 index 0000000000..b69ace95bc --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginJPEG.cpp @@ -0,0 +1,1801 @@ +// ========================================================== +// 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) +// - 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! +// ========================================================== + +#ifdef _MSC_VER +#pragma warning (disable : 4786) // identifier was truncated to 'number' characters +#endif + +extern "C" { +#define XMD_H +#undef FAR +#include + +#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 + +#define MAX_JFXX_THUMB_SIZE (MAX_BYTES_IN_MARKER - 5 - 1) + +#define JFXX_TYPE_JPEG 0x10 // JFIF extension marker: JPEG-compressed thumbnail image +#define JFXX_TYPE_8bit 0x11 // JFIF extension marker: palette thumbnail image +#define JFXX_TYPE_24bit 0x13 // JFIF extension marker: RGB thumbnail image + +// ---------------------------------------------------------- +// 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 +// ---------------------------------------------------------- + +/** Fatal errors (print message and exit) */ +static inline void +JPEG_EXIT(j_common_ptr cinfo, int code) { + freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; + error_ptr->pub.msg_code = code; + error_ptr->pub.error_exit(cinfo); +} + +/** Nonfatal errors (we can keep going, but the data is probably corrupt) */ +static inline void +JPEG_WARNING(j_common_ptr cinfo, int code) { + freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; + error_ptr->pub.msg_code = code; + error_ptr->pub.emit_message(cinfo, -1); +} + +/** + 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) { + freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; + + // always display the message + error_ptr->pub.output_message(cinfo); + + // allow JPEG with unknown markers + if(error_ptr->pub.msg_code != JERR_UNKNOWN_MARKER) { + + // let the memory manager delete any temp files before we die + jpeg_destroy(cinfo); + + // return control to the setjmp point + longjmp(error_ptr->setjmp_buffer, 1); + } +} + +/** + 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]; + freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err; + + // create the message + error_ptr->pub.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) { + // let the memory manager delete any temp files before we die + jpeg_destroy((j_common_ptr)cinfo); + + JPEG_EXIT((j_common_ptr)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) { + // let the memory manager delete any temp files before we die + jpeg_destroy((j_common_ptr)cinfo); + + JPEG_EXIT((j_common_ptr)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 + + // let the memory manager delete any temp files before we die + jpeg_destroy((j_common_ptr)cinfo); + + JPEG_EXIT((j_common_ptr)cinfo, JERR_INPUT_EMPTY); + } + + JPEG_WARNING((j_common_ptr)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) +*/ +static 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) + const char *xmp_signature = "http://ns.adobe.com/xap/1.0/"; + // XMP signature is 29 bytes long + const size_t xmp_signature_size = strlen(xmp_signature) + 1; + + size_t length = datalen; + BYTE *profile = (BYTE*)dataptr; + + if(length <= xmp_signature_size) { + // avoid reading corrupted or empty data + return FALSE; + } + + // verify the identifying string + + if(memcmp(xmp_signature, profile, strlen(xmp_signature)) == 0) { + // XMP profile + + profile += xmp_signature_size; + length -= xmp_signature_size; + + // 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_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 +*/ +static BOOL +jpeg_read_exif_profile_raw(FIBITMAP *dib, const BYTE *profile, unsigned int length) { + // marker identifying string for Exif = "Exif\0\0" + BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; + + // verify the identifying string + if(memcmp(exif_signature, profile, sizeof(exif_signature)) != 0) { + // not an Exif profile + return FALSE; + } + + // create a tag + FITAG *tag = FreeImage_CreateTag(); + if(tag) { + FreeImage_SetTagID(tag, EXIF_MARKER); // (JPEG_APP0 + 1) => EXIF marker / Adobe XMP marker + FreeImage_SetTagKey(tag, g_TagLib_ExifRawFieldName); + FreeImage_SetTagLength(tag, (DWORD)length); + FreeImage_SetTagCount(tag, (DWORD)length); + FreeImage_SetTagType(tag, FIDT_BYTE); + FreeImage_SetTagValue(tag, profile); + + // store the tag + FreeImage_SetMetadata(FIMD_EXIF_RAW, dib, FreeImage_GetTagKey(tag), tag); + + // destroy the tag + FreeImage_DeleteTag(tag); + + return TRUE; + } + + return FALSE; +} + +/** + Read JFIF "JFXX" extension APP0 marker + @param dib Input FIBITMAP + @param dataptr Pointer to the APP0 marker + @param datalen APP0 marker length + @return Returns TRUE if successful, FALSE otherwise +*/ +static BOOL +jpeg_read_jfxx(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { + if(datalen < 6) { + return FALSE; + } + + const int id_length = 5; + const BYTE *data = dataptr + id_length; + unsigned remaining = datalen - id_length; + + const BYTE type = *data; + ++data, --remaining; + + switch(type) { + case JFXX_TYPE_JPEG: + { + // load the thumbnail + FIMEMORY* hmem = FreeImage_OpenMemory(const_cast(data), remaining); + FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem); + FreeImage_CloseMemory(hmem); + // store the thumbnail + FreeImage_SetThumbnail(dib, thumbnail); + // then delete it + FreeImage_Unload(thumbnail); + break; + } + case JFXX_TYPE_8bit: + // colormapped uncompressed thumbnail (no supported) + break; + case JFXX_TYPE_24bit: + // truecolor uncompressed thumbnail (no supported) + break; + default: + break; + } + + return TRUE; +} + + +/** + 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_APP0: + // JFIF is handled by libjpeg already, handle JFXX + if(memcmp(marker->data, "JFIF" , 5) == 0) { + continue; + } + if(memcmp(marker->data, "JFXX" , 5) == 0) { + if (!cinfo->saw_JFIF_marker || cinfo->JFIF_minor_version < 2) { + FreeImage_OutputMessageProc(s_format_id, "Warning: non-standard JFXX segment"); + } + jpeg_read_jfxx(dib, marker->data, marker->data_length); + } + // other values such as 'Picasa' : ignore safely unknown APP0 marker + break; + 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); + jpeg_read_exif_profile_raw(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) + const 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_APP1 marker (Exif profile) + @return Returns TRUE if successful, FALSE otherwise +*/ +static BOOL +jpeg_write_exif_profile_raw(j_compress_ptr cinfo, FIBITMAP *dib) { + // marker identifying string for Exif = "Exif\0\0" + BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; + + FITAG *tag_exif = NULL; + FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag_exif); + + if(tag_exif) { + const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_exif); + + // verify the identifying string + if(memcmp(exif_signature, tag_value, sizeof(exif_signature)) != 0) { + // not an Exif profile + return FALSE; + } + + if(NULL != tag_value) { + DWORD tag_length = FreeImage_GetTagLength(tag_exif); + + BYTE *profile = (BYTE*)malloc(tag_length * sizeof(BYTE)); + if(profile == NULL) return FALSE; + + for(DWORD i = 0; i < tag_length; i += 65504L) { + unsigned length = MIN((long)(tag_length - i), 65504L); + + memcpy(profile, tag_value + i, length); + jpeg_write_marker(cinfo, EXIF_MARKER, profile, length); + } + + free(profile); + + return TRUE; + } + } + + return FALSE; +} + +/** + Write thumbnail (JFXX segment, JPEG compressed) +*/ +static BOOL +jpeg_write_jfxx(j_compress_ptr cinfo, FIBITMAP *dib) { + // get the thumbnail to be stored + FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); + if (!thumbnail) { + return TRUE; + } + // check for a compatible output format + if ((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 8) && (FreeImage_GetBPP(thumbnail) != 24)) { + FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL); + return FALSE; + } + + // stores the thumbnail as a baseline JPEG into a memory block + // return the memory block only if its size is within JFXX marker size limit! + FIMEMORY *stream = FreeImage_OpenMemory(); + + if(FreeImage_SaveToMemory(FIF_JPEG, thumbnail, stream, JPEG_BASELINE)) { + // check that the memory block size is within JFXX marker size limit + FreeImage_SeekMemory(stream, 0, SEEK_END); + const long eof = FreeImage_TellMemory(stream); + if(eof > MAX_JFXX_THUMB_SIZE) { + FreeImage_OutputMessageProc(s_format_id, "Warning: attached thumbnail is %d bytes larger than maximum supported size - Thumbnail saving aborted", eof - MAX_JFXX_THUMB_SIZE); + FreeImage_CloseMemory(stream); + return FALSE; + } + } else { + FreeImage_CloseMemory(stream); + return FALSE; + } + + BYTE* thData = NULL; + DWORD thSize = 0; + + FreeImage_AcquireMemory(stream, &thData, &thSize); + + BYTE id_length = 5; //< "JFXX" + BYTE type = JFXX_TYPE_JPEG; + + DWORD totalsize = id_length + sizeof(type) + thSize; + jpeg_write_m_header(cinfo, JPEG_APP0, totalsize); + + jpeg_write_m_byte(cinfo, 'J'); + jpeg_write_m_byte(cinfo, 'F'); + jpeg_write_m_byte(cinfo, 'X'); + jpeg_write_m_byte(cinfo, 'X'); + jpeg_write_m_byte(cinfo, '\0'); + + jpeg_write_m_byte(cinfo, type); + + // write thumbnail to destination. + // We "cram it straight into the data destination module", because write_m_byte is slow + + freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest; + + BYTE* & out = dest->pub.next_output_byte; + size_t & bufRemain = dest->pub.free_in_buffer; + + const BYTE *thData_end = thData + thSize; + + while(thData < thData_end) { + *(out)++ = *(thData)++; + if (--bufRemain == 0) { + // buffer full - flush + if (!dest->pub.empty_output_buffer(cinfo)) { + break; + } + } + } + + FreeImage_CloseMemory(stream); + + return TRUE; +} + +/** + Write JPEG special markers +*/ +static BOOL +write_markers(j_compress_ptr cinfo, FIBITMAP *dib) { + // write thumbnail as a JFXX marker + jpeg_write_jfxx(cinfo, 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); + + // write Exif raw data + jpeg_write_exif_profile_raw(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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + if (handle) { + FIBITMAP *dib = NULL; + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // set up the jpeglib structures + + struct jpeg_decompress_struct cinfo; + ErrorManager fi_error_mgr; + + try { + + // step 1: allocate and initialize JPEG decompression object + + // we set up the normal JPEG error routines, then override error_exit & output_message + cinfo.err = jpeg_std_error(&fi_error_mgr.pub); + fi_error_mgr.pub.error_exit = jpeg_error_exit; + fi_error_mgr.pub.output_message = jpeg_output_message; + + // establish the setjmp return context for jpeg_error_exit to use + if (setjmp(fi_error_mgr.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); + throw (const char*)NULL; + } + + 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_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + if (!dib) throw FI_MSG_ERROR_DIB_MEMORY; + FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK; + } else { + // load as CMYK and convert to RGB + dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + if (!dib) throw FI_MSG_ERROR_DIB_MEMORY; + } + } else { + // RGB or greyscale image + dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 8 * cinfo.num_components, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + if (!dib) throw FI_MSG_ERROR_DIB_MEMORY; + + 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 6: read special markers + + read_markers(&cinfo, dib); + + // --- header only mode => clean-up and return + + if (header_only) { + // release JPEG decompression object + jpeg_destroy_decompress(&cinfo); + // return header data + return dib; + } + + // step 7a: 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 < cinfo.output_width; x++) { + WORD K = (WORD)src[3]; + dst[FI_RGBA_RED] = (BYTE)((K * src[0]) / 255); // C -> R + dst[FI_RGBA_GREEN] = (BYTE)((K * src[1]) / 255); // M -> G + dst[FI_RGBA_BLUE] = (BYTE)((K * src[2]) / 255); // Y -> B + src += 4; + dst += 3; + } + } + } else if ((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) == JPEG_CMYK)) { + // convert from LibJPEG CMYK to standard CMYK + + 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 < cinfo.output_width; x++) { + // CMYK pixels are inverted + dst[0] = ~src[0]; // C + dst[1] = ~src[1]; // M + dst[2] = ~src[2]; // Y + dst[3] = ~src[3]; // K + src += 4; + dst += 4; + } + } + + } 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 7b: 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 + SwapRedBlue32(dib); +#endif + } + + // step 8: finish decompression + + jpeg_finish_decompress(&cinfo); + + // step 9: release JPEG decompression object + + jpeg_destroy_decompress(&cinfo); + + // check for automatic Exif rotation + if (!header_only && ((flags & JPEG_EXIFROTATE) == JPEG_EXIFROTATE)) { + rotate_exif(&dib); + } + + // everything went well. return the loaded dib + + return dib; + + } catch (const char *text) { + jpeg_destroy_decompress(&cinfo); + if(NULL != 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)) { + 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; + ErrorManager fi_error_mgr; + + // Step 1: allocate and initialize JPEG compression object + + // we set up the normal JPEG error routines, then override error_exit & output_message + cinfo.err = jpeg_std_error(&fi_error_mgr.pub); + fi_error_mgr.pub.error_exit = jpeg_error_exit; + fi_error_mgr.pub.output_message = jpeg_output_message; + + // establish the setjmp return context for jpeg_error_exit to use + if (setjmp(fi_error_mgr.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_compress(&cinfo); + throw (const char*)NULL; + } + + // 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); + } + + // compute optimal Huffman coding tables for the image + if ((flags & JPEG_OPTIMIZE) == JPEG_OPTIMIZE) { + cinfo.optimize_coding = TRUE; + } + + // 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 + + // thumbnail support (JFIF 1.02 extension markers) + if(FreeImage_GetThumbnail(dib) != NULL) { + cinfo.write_JFIF_header = 1; //<### force it, though when color is CMYK it will be incorrect + cinfo.JFIF_minor_version = 2; + } + + // baseline JPEG support + if ((flags & JPEG_BASELINE) == JPEG_BASELINE) { + cinfo.write_JFIF_header = 0; // No marker for non-JFIF colorspaces + cinfo.write_Adobe_marker = 0; // write no Adobe marker by default + } + + // 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 + + if ((flags & JPEG_BASELINE) != JPEG_BASELINE) { + 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) { + if(text) { + FreeImage_OutputMessageProc(s_format_id, text); + } + 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginKOALA.cpp b/plugins/FreeImage/src/FreeImage/PluginKOALA.cpp new file mode 100644 index 0000000000..6c3ae52254 --- /dev/null +++ b/plugins/FreeImage/src/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/x-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/plugins/FreeImage/src/FreeImage/PluginMNG.cpp b/plugins/FreeImage/src/FreeImage/PluginMNG.cpp new file mode 100644 index 0000000000..6d2f50ecec --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginMNG.cpp @@ -0,0 +1,153 @@ +// ========================================================== +// MNG loader +// +// Design and implementation by +// - Herve 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; + +// ---------------------------------------------------------- + +#define MNG_SIGNATURE_SIZE 8 // size of the signature + +// ---------------------------------------------------------- + +// ---------------------------------------------------------- +// mng interface (see MNGHelper.cpp) +// ---------------------------------------------------------- + +FIBITMAP* mng_ReadChunks(int format_id, FreeImageIO *io, fi_handle handle, long Offset, int flags = 0); + + +// ========================================================== +// Plugin Implementation +// ========================================================== + +static const char * DLL_CALLCONV +Format() { + return "MNG"; +} + +static const char * DLL_CALLCONV +Description() { + return "Multiple-image 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 +Validate(FreeImageIO *io, fi_handle handle) { + BYTE mng_signature[8] = { 138, 77, 78, 71, 13, 10, 26, 10 }; + BYTE signature[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + io->read_proc(&signature, 1, MNG_SIGNATURE_SIZE, handle); + + return (memcmp(mng_signature, signature, MNG_SIGNATURE_SIZE) == 0) ? TRUE : 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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return 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) { + long offset = MNG_SIGNATURE_SIZE; // move to skip first 8 bytes of signature + + // check the signature (8 bytes) + if(Validate(io, handle) == FALSE) { + return NULL; + } + + // parse chunks and decode a jng or mng bitmap + return mng_ReadChunks(s_format_id, io, handle, offset, flags); +} + + +// ========================================================== +// 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 = Validate; + plugin->mime_proc = MimeType; + plugin->supports_export_bpp_proc = SupportsExportDepth; + plugin->supports_export_type_proc = SupportsExportType; + plugin->supports_icc_profiles_proc = SupportsICCProfiles; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginPCD.cpp b/plugins/FreeImage/src/FreeImage/PluginPCD.cpp new file mode 100644 index 0000000000..87cbe967b2 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginPCD.cpp @@ -0,0 +1,251 @@ +// ========================================================== +// 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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + FIBITMAP *dib = NULL; + unsigned width; + unsigned height; + const unsigned bpp = 24; + int scan_line_add = 1; + int start_scan_line = 0; + + BYTE *y1 = NULL, *y2 = NULL, *cbcr = NULL; + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // 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; + } + + try { + // allocate the dib and write out the header + dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + if (!dib) throw FI_MSG_ERROR_DIB_MEMORY; + + if(header_only) { + return dib; + } + + // 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 = (BYTE*)malloc(width * sizeof(BYTE)); + BYTE *y2 = (BYTE*)malloc(width * sizeof(BYTE)); + BYTE *cbcr = (BYTE*)malloc(width * sizeof(BYTE)); + if (!y1 || !y2 || !cbcr) throw FI_MSG_ERROR_MEMORY; + + 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 (unsigned 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 *bits = FreeImage_GetScanLine(dib, start_scan_line); + for (unsigned x = 0; x < width; x++) { + int r, g, b; + + YUV2RGB(yl[i][x], cbcr[x / 2], cbcr[(width / 2) + (x / 2)], r, g, b); + + bits[FI_RGBA_BLUE] = (BYTE)b; + bits[FI_RGBA_GREEN] = (BYTE)g; + bits[FI_RGBA_RED] = (BYTE)r; + bits += 3; + } + + start_scan_line += scan_line_add; + } + } + + free(cbcr); + free(y2); + free(y1); + + return dib; + + } catch(const char *text) { + if(dib) FreeImage_Unload(dib); + if(cbcr) free(cbcr); + if(y2) free(y2); + if(y1) free(y1); + + FreeImage_OutputMessageProc(s_format_id, text); + + return NULL; + } +} + +// ========================================================== +// 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginPCX.cpp b/plugins/FreeImage/src/FreeImage/PluginPCX.cpp new file mode 100644 index 0000000000..a6feb5fea7 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginPCX.cpp @@ -0,0 +1,659 @@ +// ========================================================== +// 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 BOOL +pcx_validate(FreeImageIO *io, fi_handle handle) { + BYTE pcx_signature = 0x0A; + BYTE signature[4] = { 0, 0, 0, 0 }; + + if(io->read_proc(&signature, 1, 4, handle) != 4) { + return FALSE; + } + // magic number (0x0A = ZSoft Z) + if(signature[0] == pcx_signature) { + // version + if(signature[1] <= 5) { + // encoding + if ((signature[2] == 0) || (signature[2] == 1)) { + // bits per pixel per plane + if ((signature[3] == 1) || (signature[3] == 8)) { + return TRUE; + } + } + } + } + + return FALSE; +} + +static unsigned +readline(FreeImageIO &io, fi_handle handle, BYTE *buffer, unsigned 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; + unsigned 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)++); + } else { + count = 1; + } + } + + count--; + + *(buffer + written++) = value; + } + + } else { + // normal read + + written = 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) { + return pcx_validate(io, handle); +} + +/*! + 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; +} + +static BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +/*! + 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; + BOOL bIsRLE; // True if the file is run-length encoded + + if (!handle) { + return NULL; + } + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + try { + // check PCX identifier + + long start_pos = io->tell_proc(handle); + BOOL validated = pcx_validate(io, handle); + io->seek_proc(handle, start_pos, SEEK_SET); + if (!validated) { + throw FI_MSG_ERROR_MAGIC_NUMBER; + } + + // process the header + + PCXHEADER header; + + if(io->read_proc(&header, sizeof(PCXHEADER), 1, handle) != 1) { + throw FI_MSG_ERROR_PARSING; + } +#ifdef FREEIMAGE_BIGENDIAN + SwapHeader(&header); +#endif + + // allocate a new DIB + + unsigned width = header.window[2] - header.window[0] + 1; + unsigned height = header.window[3] - header.window[1] + 1; + unsigned bitcount = header.bpp * header.planes; + + if (bitcount == 24) { + dib = FreeImage_AllocateHeader(header_only, width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeader(header_only, 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; + } + + if(header_only) { + // header only mode + return dib; + } + + // calculate the line length for the PCX and the DIB + + // length of raster line in bytes + unsigned linelength = header.bytes_per_line * header.planes; + // length of DIB line (rounded to DWORD) in bytes + unsigned pitch = FreeImage_GetPitch(dib); + + // run-length encoding ? + + bIsRLE = (header.encoding == 1) ? TRUE : FALSE; + + // load image data + // --------------- + + line = (BYTE*)malloc(linelength * sizeof(BYTE)); + if (!line) throw FI_MSG_ERROR_MEMORY; + + ReadBuf = (BYTE*)malloc(IO_BUF_SIZE * sizeof(BYTE)); + if (!ReadBuf) throw FI_MSG_ERROR_MEMORY; + + bits = FreeImage_GetScanLine(dib, height - 1); + + int ReadPos = IO_BUF_SIZE; + + if ((header.planes == 1) && ((header.bpp == 1) || (header.bpp == 8))) { + BYTE skip; + unsigned written; + + for (unsigned y = 0; y < height; y++) { + written = readline(*io, handle, bits, linelength, bIsRLE, ReadBuf, &ReadPos); + + // skip trailing garbage at the end of the scanline + + for (unsigned 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; + unsigned index; + BYTE *buffer; + unsigned x, y, written; + + buffer = (BYTE*)malloc(width * sizeof(BYTE)); + if (!buffer) throw FI_MSG_ERROR_MEMORY; + + for (y = 0; y < height; y++) { + written = readline(*io, handle, line, linelength, bIsRLE, 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 = (unsigned)((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 (unsigned count = written; count < linelength; count++) { + if (ReadPos < IO_BUF_SIZE) { + ReadPos++; + } else { + io->read_proc(&skip, sizeof(BYTE), 1, handle); + } + } + + bits -= pitch; + } + + free(buffer); + + } else if ((header.planes == 3) && (header.bpp == 8)) { + BYTE *pline; + + for (unsigned y = 0; y < height; y++) { + readline(*io, handle, line, linelength, bIsRLE, 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; + unsigned 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; + } + + free(line); + free(ReadBuf); + + return dib; + + } catch (const char *text) { + // free allocated memory + + if (dib != NULL) { + FreeImage_Unload(dib); + } + if (line != NULL) { + free(line); + } + if (ReadBuf != NULL) { + free(ReadBuf); + } + + FreeImage_OutputMessageProc(s_format_id, text); + } + + 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginPFM.cpp b/plugins/FreeImage/src/FreeImage/PluginPFM.cpp new file mode 100644 index 0000000000..8ccbd48ba5 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginPFM.cpp @@ -0,0 +1,402 @@ +// ========================================================== +// 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/x-portable-floatmap"; +} + +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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +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; + } + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + 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_AllocateHeaderT(header_only, image_type, width, height); + if (dib == NULL) { + throw FI_MSG_ERROR_DIB_MEMORY; + } + + if(header_only) { + // header only mode + return dib; + } + + // 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginPICT.cpp b/plugins/FreeImage/src/FreeImage/PluginPICT.cpp new file mode 100644 index 0000000000..0c44cb2d1f --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginPICT.cpp @@ -0,0 +1,1342 @@ +// ========================================================== +// 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 +{ + const char * name; + int len; + const 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> 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; + long currentPos = 0; + + while ( !done ) { + WORD opcode = 0; + + // get the current stream position (used to avoid infinite loops) + currentPos = io->tell_proc(handle); + + 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; + } + + if(currentPos == io->tell_proc(handle)) { + // we probaly reached the end of file as we can no longer move forward ... + throw "Invalid PICT file"; + } + } + + 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/plugins/FreeImage/src/FreeImage/PluginPNG.cpp b/plugins/FreeImage/src/FreeImage/PluginPNG.cpp new file mode 100644 index 0000000000..ad398a87e8 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginPNG.cpp @@ -0,0 +1,953 @@ +// ========================================================== +// 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 + +#include "FreeImage.h" +#include "Utilities.h" + +#include "../Metadata/FreeImageTag.h" + +// ---------------------------------------------------------- + +#define PNG_BYTES_TO_CHECK 8 + +// ---------------------------------------------------------- + +#include "../ZLib/zlib.h" +#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) { + (png_structp)png_ptr; + // empty flush implementation +} + +static void +error_handler(png_structp png_ptr, const char *error) { + (png_structp)png_ptr; + throw error; +} + +// in FreeImage warnings disabled + +static void +warning_handler(png_structp png_ptr, const char *warning) { + (png_structp)png_ptr; + (char*)warning; +} + +// ========================================================== +// Metadata routines +// ========================================================== + +static BOOL +ReadMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) { + // XMP keyword + const 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++) { + // create a tag + tag = FreeImage_CreateTag(); + if (!tag) return FALSE; + + DWORD tag_length = (DWORD) MAX(text_ptr[i].text_length, text_ptr[i].itxt_length); + + 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 + const 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 = (char*)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 BOOL DLL_CALLCONV +SupportsNoPixels() { + 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) { + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + 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 = png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr); + + // 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 + // but *do not* expand fully transparent palette entries to a full alpha channel + + if (pixel_depth == 2) { + png_set_expand_gray_1_2_4_to_8(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; + } + + // 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") + + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { + 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_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth); + } + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + if(image_type == FIT_BITMAP) { + dib = FreeImage_AllocateHeader(header_only, width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth); + } + break; + + case PNG_COLOR_TYPE_PALETTE: + dib = FreeImage_AllocateHeader(header_only, width, height, pixel_depth); + + png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries); + + palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib)); + 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; + } + break; + + case PNG_COLOR_TYPE_GRAY: + dib = FreeImage_AllocateHeaderT(header_only, 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)); + } + } + break; + + default: + throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; + } + + // store the transparency table + + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { + // array of alpha (transparency) entries for palette + png_bytep trans_alpha = NULL; + // number of transparent entries + int num_trans = 0; + // graylevel or color sample values of the single transparent color for non-paletted images + png_color_16p trans_color = NULL; + + png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color); + + if ((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) { + // single transparent color + if (trans_color->gray < palette_entries) { + BYTE table[256]; + memset(table, 0xFF, palette_entries); + table[trans_color->gray] = 0; + FreeImage_SetTransparencyTable(dib, table, palette_entries); + } + } else if ((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) { + // transparency table + FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans); + } + } + + // store the background color + + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) { + // 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; + + 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 = PNG_RESOLUTION_UNKNOWN; + + png_get_pHYs(png_ptr,info_ptr, &res_x, &res_y, &res_unit_type); + + if (res_unit_type == PNG_RESOLUTION_METER) { + 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_bytep 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_AllocateHeader) + + FreeImage_CreateICCProfile(dib, profile_data, profile_length); + } + + // --- header only mode => clean-up and return + + if (header_only) { + // 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; + } + + // set the individual row_pointers to point at the correct offsets + + row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep)); + + if (!row_pointers) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + FreeImage_Unload(dib); + return NULL; + } + + // read in the bitmap bits via the pointer table + // allow loading of PNG with minor errors (such as images with several IDAT chunks) + + for (png_uint_32 k = 0; k < height; k++) { + row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k); + } + + png_set_benign_errors(png_ptr, 1); + 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, PNG_RESOLUTION_METER); + } + + // 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_const_bytep)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 (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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginPNM.cpp b/plugins/FreeImage/src/FreeImage/PluginPNM.cpp new file mode 100644 index 0000000000..a30f858851 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginPNM.cpp @@ -0,0 +1,831 @@ +// ========================================================== +// 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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +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; + } + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + 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_AllocateHeader(header_only, width, height, 1); + break; + + case '2': + case '5': + if(maxval > 255) { + // 16-bit greyscale + image_type = FIT_UINT16; + dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height); + } else { + // 8-bit greyscale + dib = FreeImage_AllocateHeader(header_only, width, height, 8); + } + break; + + case '3': + case '6': + if(maxval > 255) { + // 48-bit RGB + image_type = FIT_RGB16; + dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height); + } else { + // 24-bit RGB + dib = FreeImage_AllocateHeader(header_only, 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; + } + + // Build a greyscale palette if needed + + if(image_type == FIT_BITMAP) { + switch(id_two) { + case '1': + case '4': + 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 '2': + case '5': + pal = FreeImage_GetPalette(dib); + for (i = 0; i < 256; i++) { + pal[i].rgbRed = + pal[i].rgbGreen = + pal[i].rgbBlue = (BYTE)i; + } + break; + + default: + break; + } + } + + if(header_only) { + // header only mode + return dib; + } + + // Read the image... + + switch(id_two) { + case '1': + case '4': + // 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) { + // 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; +} + +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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginPSD.cpp b/plugins/FreeImage/src/FreeImage/PluginPSD.cpp new file mode 100644 index 0000000000..e453a31789 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginPSD.cpp @@ -0,0 +1,131 @@ +// ========================================================== +// Photoshop Loader +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// - Mihail Naydenov (mnaydenov@users.sourceforge.net) +// +// 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/vnd.adobe.photoshop"; +} + +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 BOOL DLL_CALLCONV +SupportsNoPixels() { + 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, flags); + + 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginRAS.cpp b/plugins/FreeImage/src/FreeImage/PluginRAS.cpp new file mode 100644 index 0000000000..08fc0c9e17 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginRAS.cpp @@ -0,0 +1,512 @@ +// ========================================================== +// 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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +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) { + return NULL; + } + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + 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_AllocateHeader(header_only, header.width, header.height, header.depth); + break; + + case 24: + dib = FreeImage_AllocateHeader(header_only, header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + break; + + case 32: + dib = FreeImage_AllocateHeader(header_only, 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; + } + } + + if(header_only) { + // header only mode + return dib; + } + + // 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; + + unsigned 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; +} + +// ========================================================== +// 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginRAW.cpp b/plugins/FreeImage/src/FreeImage/PluginRAW.cpp new file mode 100644 index 0000000000..4611824f4d --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginRAW.cpp @@ -0,0 +1,542 @@ +// ========================================================== +// 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 "../LibRawLite/libraw/libraw.h" + +#include "FreeImage.h" +#include "Utilities.h" +#include "../Metadata/FreeImageTag.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 void * make_jas_stream() { + return NULL; + } + 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(INT64 offset, int origin) { + if(substream) return substream->seek(offset, origin); + return _io->seek_proc(_handle, (long)offset, origin); + } + virtual INT64 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 + WORD *raw_data = (WORD*)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 +@param flags JPEG load flags +@return Returns the loaded dib if successfull, returns NULL otherwise +*/ +static FIBITMAP * +libraw_LoadEmbeddedPreview(LibRaw& RawProcessor, int flags) { + FIBITMAP *dib = NULL; + libraw_processed_image_t *thumb_image = NULL; + + try { + // unpack data + if(RawProcessor.unpack_thumb() != LIBRAW_SUCCESS) { + // run silently "LibRaw : failed to run unpack_thumb" + return NULL; + } + + // 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) { + // 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 + RawProcessor.dcraw_clear_mem(thumb_image); + + return dib; + + } catch(const char *text) { + // clean-up and return + if(thumb_image) { + RawProcessor.dcraw_clear_mem(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 + // ----------------------- + + // (-6) 16-bit or 8-bit + RawProcessor.imgdata.params.output_bps = bitspersample; + // (-g power toe_slope) + if(bitspersample == 16) { + // set -g 1 1 for linear curve + RawProcessor.imgdata.params.gamm[0] = 1; + RawProcessor.imgdata.params.gamm[1] = 1; + } else if(bitspersample == 8) { + // by default settings for rec. BT.709 are used: power 2.222 (i.e. gamm[0]=1/2.222) and slope 4.5 + RawProcessor.imgdata.params.gamm[0] = 1/2.222; + RawProcessor.imgdata.params.gamm[1] = 4.5; + } + // (-W) Don't use automatic increase of brightness by histogram + RawProcessor.imgdata.params.no_auto_bright = 1; + // (-a) Use automatic white balance obtained after averaging over the entire image + 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 + RawProcessor.dcraw_clear_mem(processed_image); + + return dib; + + } catch(const char *text) { + // clean-up and return + if(processed_image) { + RawProcessor.dcraw_clear_mem(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() { + /** + Below are known RAW file extensions that you can check using FreeImage_GetFIFFromFormat. + If a file extension is not listed, that doesn't mean that you cannot load it. + Using FreeImage_GetFileType is the best way to know if a RAW file format is supported. + */ + static const char *raw_extensions = + "3fr," // Hasselblad Digital Camera Raw Image Format. + "arw," // Sony Digital Camera Raw Image Format for Alpha devices. + "bay," // Casio Digital Camera Raw File Format. + "bmq," // NuCore Raw Image File. + "cap," // Phase One Digital Camera Raw Image Format. + "cine," // Phantom Software 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," // Sinar 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. + "drf," // Kodak Digital Camera Raw Image Format. + "dsc," // Kodak Digital Camera Raw Image Format. + "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. + "ia," // Sinar Raw Image File. + "iiq," // Phase One Digital Camera Raw Image Format. + "k25," // Kodak DC25 Digital Camera Raw Image Format. + "kc2," // Kodak DCS200 Digital Camera Raw Image Format. + "kdc," // Kodak Digital Camera Raw Image Format. + "mdc," // Minolta RD175 Digital Camera Raw Image Format. + "mef," // Mamiya Digital Camera Raw Image Format. + "mos," // Leaf Raw Image File. + "mrw," // Minolta Dimage Digital Camera Raw Image Format. + "nef," // Nikon Digital Camera Raw Image Format. + "nrw," // Nikon Digital Camera Raw Image Format. + "orf," // Olympus Digital Camera Raw Image Format. + "pef," // Pentax Digital Camera Raw Image Format. + "ptx," // Pentax Digital Camera Raw Image Format. + "pxn," // Logitech Digital Camera Raw Image Format. + "qtk," // Apple Quicktake 100/150 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. + "rw2," // Panasonic LX3 Digital Camera Raw Image Format. + "rwl," // Leica Camera Raw Image Format. + "rwz," // Rawzor Digital Camera Raw Image Format. + "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. + "srw," // Samsung Raw Image Format. + "sti"; // Sinar Capture Shop Raw Image File. +// "x3f" // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor. + return raw_extensions; +} + +static const char * DLL_CALLCONV +RegExpr() { + return NULL; +} + +static const char * DLL_CALLCONV +MimeType() { + return "image/x-dcraw"; +} + +static BOOL DLL_CALLCONV +Validate(FreeImageIO *io, fi_handle handle) { + LibRaw RawProcessor; + BOOL bSuccess = TRUE; + + // wrap the input datastream + LibRaw_freeimage_datastream datastream(io, handle); + + // open the datastream + if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) { + bSuccess = FALSE; // LibRaw : failed to open input stream (unknown format) + } + + // clean-up internal memory allocations + RawProcessor.recycle(); + + return bSuccess; +} + +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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + FIBITMAP *dib = NULL; + LibRaw RawProcessor; + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + try { + // wrap the input datastream + LibRaw_freeimage_datastream datastream(io, handle); + + // set decoding parameters + // the following parameters affect data reading + // -------------------------------------------- + + // (-s [0..N-1]) Select one raw image from input file + RawProcessor.imgdata.params.shot_select = 0; + // (-w) Use camera white balance, if possible (otherwise, fallback to auto_wb) + RawProcessor.imgdata.params.use_camera_wb = 1; + // (-h) outputs the image in 50% size + RawProcessor.imgdata.params.half_size = ((flags & RAW_HALFSIZE) == RAW_HALFSIZE) ? 1 : 0; + + // open the datastream + if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) { + throw "LibRaw : failed to open input stream (unknown format)"; + } + + if(header_only) { + // header only mode + dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, RawProcessor.imgdata.sizes.width, RawProcessor.imgdata.sizes.height); + } + else if ((flags & RAW_PREVIEW) == RAW_PREVIEW) { + // try to get the embedded JPEG + dib = libraw_LoadEmbeddedPreview(RawProcessor, 0); + if (!dib) { + // no JPEG preview: try to load as 8-bit/sample (i.e. RGB 24-bit) + dib = libraw_LoadRawData(RawProcessor, 8); + } + } + else if ((flags & RAW_DISPLAY) == RAW_DISPLAY) { + // load raw data as 8-bit/sample (i.e. RGB 24-bit) + dib = libraw_LoadRawData(RawProcessor, 8); + } + else { + // default: load raw data as linear 16-bit/sample (i.e. RGB 48-bit) + dib = libraw_LoadRawData(RawProcessor, 16); + } + + // save ICC profile if present + if(dib && (NULL != RawProcessor.imgdata.color.profile)) { + FreeImage_CreateICCProfile(dib, RawProcessor.imgdata.color.profile, RawProcessor.imgdata.color.profile_length); + } + + // try to get JPEG embedded Exif metadata + if(dib && !((flags & RAW_PREVIEW) == RAW_PREVIEW)) { + FIBITMAP *metadata_dib = libraw_LoadEmbeddedPreview(RawProcessor, FIF_LOAD_NOPIXELS); + if(metadata_dib) { + FreeImage_CloneMetadata(dib, metadata_dib); + FreeImage_Unload(metadata_dib); + } + } + + // 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 = SupportsICCProfiles; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginSGI.cpp b/plugins/FreeImage/src/FreeImage/PluginSGI.cpp new file mode 100644 index 0000000000..3ac189e0ef --- /dev/null +++ b/plugins/FreeImage/src/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/x-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; iformat_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/plugins/FreeImage/src/FreeImage/PluginTARGA.cpp b/plugins/FreeImage/src/FreeImage/PluginTARGA.cpp new file mode 100644 index 0000000000..4e3f1a720a --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginTARGA.cpp @@ -0,0 +1,1565 @@ +// ========================================================== +// 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 tagTGAEXTENSIONAREA { + WORD extension_size; // Size in bytes of the extension area, always 495 + char author_name[41]; // Name of the author. If not used, bytes should be set to NULL (\0) or spaces + char author_comments[324]; // A comment, organized as four lines, each consisting of 80 characters plus a NULL + WORD datetime_stamp[6]; // Date and time at which the image was created + char job_name[41]; // Job ID + WORD job_time[3]; // Hours, minutes and seconds spent creating the file (for billing, etc.) + char software_id[41]; // The application that created the file + BYTE software_version[3]; + DWORD key_color; + WORD pixel_aspect_ratio[2]; + WORD gamma_value[2]; + DWORD color_correction_offset; // Number of bytes from the beginning of the file to the color correction table if present + DWORD postage_stamp_offset; // Number of bytes from the beginning of the file to the postage stamp image if present + DWORD scan_line_offset; // Number of bytes from the beginning of the file to the scan lines table if present + BYTE attributes_type; // Specifies the alpha channel +} TGAEXTENSIONAREA; + +typedef struct tagTGAFOOTER { + DWORD extension_offset; // extension area offset : offset in bytes from the beginning of the file + DWORD developer_offset; // developer directory offset : offset in bytes from the beginning of the file + char signature[18]; // signature string : contains "TRUEVISION-XFILE.\0" +} TGAFOOTER; + +#ifdef _WIN32 +#pragma pack(pop) +#else +#pragma pack() +#endif + +static const char *FI_MSG_ERROR_CORRUPTED = "Image data corrupted"; + +// ---------------------------------------------------------- +// 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 + +// ========================================================== +// Thumbnail functions +// ========================================================== + +class TargaThumbnail +{ +public: + TargaThumbnail() : _w(0), _h(0), _depth(0), _data(NULL) { + } + ~TargaThumbnail() { + if(_data) { + free(_data); + } + } + + BOOL isNull() const { + return (_data == NULL); + } + + BOOL read(FreeImageIO *io, fi_handle handle, size_t size) { + io->read_proc(&_w, 1, 1, handle); + io->read_proc(&_h, 1, 1, handle); + + const size_t sizeofData = size - 2; + _data = (BYTE*)malloc(sizeofData); + if(_data) { + return (io->read_proc(_data, 1, (unsigned)sizeofData, handle) == sizeofData); + } + return FALSE; + } + + void setDepth(BYTE dp) { + _depth = dp; + } + + FIBITMAP* toFIBITMAP(); + +private: + BYTE _w; + BYTE _h; + BYTE _depth; + BYTE* _data; +}; + +#ifdef FREEIMAGE_BIGENDIAN +static void +swapShortPixels(FIBITMAP* dib) { + if(FreeImage_GetImageType(dib) != FIT_BITMAP) { + return; + } + + const unsigned Bpp = FreeImage_GetBPP(dib)/8; + if(Bpp != 2) { + return; + } + + BYTE* bits = FreeImage_GetBits(dib); + const unsigned height = FreeImage_GetHeight(dib); + const unsigned pitch = FreeImage_GetPitch(dib); + + BYTE* line = bits; + for(unsigned y = 0; y < height; y++, line += pitch) { + for(BYTE* pixel = line; pixel < line + pitch ; pixel += Bpp) { + SwapShort((WORD*)pixel); + } + } +} +#endif // FREEIMAGE_BIGENDIAN + +FIBITMAP* TargaThumbnail::toFIBITMAP() { + if(isNull() || _depth == 0) { + return NULL; + } + + const unsigned line_size = _depth * _w / 8; + FIBITMAP* dib = FreeImage_Allocate(_w, _h, _depth); + if (!dib) { + return NULL; + } + + const BYTE* line = _data; + const BYTE height = _h; + for (BYTE h = 0; h < height; ++h, line += line_size) { + BYTE* dst_line = FreeImage_GetScanLine(dib, height - 1 - h); + memcpy(dst_line, line, line_size); + } + +#ifdef FREEIMAGE_BIGENDIAN + swapShortPixels(dib); +#endif + +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB + SwapRedBlue32(dib); +#endif + + return dib; +} +// ========================================================== +// Internal functions +// ========================================================== + +/** This class is used when loading RLE compressed images, it implements io cache of fixed size. + In general RLE compressed images *should* be compressed line by line with line sizes stored in Scan Line Table section. + In reality, however there are images not obeying the specification, compressing image data continuously across lines, + making it impossible to load the file cached at every line. +*/ +class IOCache +{ +public: + IOCache(FreeImageIO *io, fi_handle handle, size_t size) : + _ptr(NULL), _begin(NULL), _end(NULL), _size(size), _io(io), _handle(handle) { + _begin = (BYTE*)malloc(size); + if (_begin) { + _end = _begin + _size; + _ptr = _end; // will force refill on first access + } + } + + ~IOCache() { + if (_begin != NULL) { + free(_begin); + } + } + + BOOL isNull() { return _begin == NULL;} + + inline + BYTE getByte() { + if (_ptr >= _end) { + // need refill + _ptr = _begin; + _io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle); //### EOF - no problem? + } + + BYTE result = *_ptr; + + _ptr++; + + return result; + } + + inline + BYTE* getBytes(size_t count /*must be < _size!*/) { + if (_ptr + count >= _end) { + + // need refill + + // 'count' bytes might span two cache bounds, + // SEEK back to add the remains of the current cache again into the new one + + long read = long(_ptr - _begin); + long remaining = long(_size - read); + + _io->seek_proc(_handle, -remaining, SEEK_CUR); + + _ptr = _begin; + _io->read_proc(_ptr, sizeof(BYTE), (unsigned)_size, _handle); //### EOF - no problem? + } + + BYTE *result = _ptr; + + _ptr += count; + + return result; + } + +private: + IOCache& operator=(const IOCache& src); // deleted + IOCache(const IOCache& other); // deleted + +private: + BYTE *_ptr; + BYTE *_begin; + BYTE *_end; + const size_t _size; + const FreeImageIO *_io; + const fi_handle _handle; +}; + +#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 +SwapExtensionArea(TGAEXTENSIONAREA *ex) { + SwapShort(&ex->extension_size); + SwapShort(&ex->datetime_stamp[0]); + SwapShort(&ex->datetime_stamp[1]); + SwapShort(&ex->datetime_stamp[2]); + SwapShort(&ex->datetime_stamp[3]); + SwapShort(&ex->datetime_stamp[4]); + SwapShort(&ex->datetime_stamp[5]); + SwapShort(&ex->job_time[0]); + SwapShort(&ex->job_time[1]); + SwapShort(&ex->job_time[2]); + SwapLong (&ex->key_color); + SwapShort(&ex->pixel_aspect_ratio[0]); + SwapShort(&ex->pixel_aspect_ratio[1]); + SwapShort(&ex->gamma_value[0]); + SwapShort(&ex->gamma_value[1]); + SwapLong (&ex->color_correction_offset); + SwapLong (&ex->postage_stamp_offset); + SwapLong (&ex->scan_line_offset); +} + +static void +SwapFooter(TGAFOOTER *footer) { + SwapLong(&footer->extension_offset); + SwapLong(&footer->developer_offset); +} + +#endif // FREEIMAGE_BIGENDIAN + +// ========================================================== +// 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/x-tga"; +} + +static BOOL +isTARGA20(FreeImageIO *io, fi_handle handle) { + const unsigned sizeofSig = 18; + // tga_signature = "TRUEVISION-XFILE." (TGA 2.0 only) + BYTE tga_signature[sizeofSig] = { 84, 82, 85, 69, 86, 73, 83, 73, 79, 78, 45, 88, 70, 73, 76, 69, 46, 0 }; + // get the start offset + const long start_offset = io->tell_proc(handle); + // get the end-of-file + io->seek_proc(handle, 0, SEEK_END); + const long eof = io->tell_proc(handle); + // read the signature + + io->seek_proc(handle, start_offset + eof - sizeofSig, SEEK_SET); + BYTE signature[sizeofSig]; + io->read_proc(&signature, 1, sizeofSig, handle); + + // rewind + io->seek_proc(handle, start_offset, SEEK_SET); + + return (memcmp(tga_signature, signature, sizeofSig) == 0); +} + +static BOOL DLL_CALLCONV +Validate(FreeImageIO *io, fi_handle handle) { + if(isTARGA20(io, handle)) { + return TRUE; + } + + // not a 2.0 image, try testing if it's a valid TGA anyway (not robust) + BOOL bResult = FALSE; + + const long start_offset = io->tell_proc(handle); + + TGAHEADER header; + io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle); + + // rewind + io->seek_proc(handle, start_offset, SEEK_SET); + + switch(header.image_type) { + case TGA_CMAP : + case TGA_RGB: + case TGA_MONO : + case TGA_RLECMAP: + case TGA_RLERGB: + case TGA_RLEMONO: + switch(header.is_pixel_depth) { + case 8 : + case 16: + case 24: + case 32: + bResult = TRUE; + break; + default: + bResult = FALSE; + break; + } + break; + default: + bResult = FALSE; + break; + } + + return bResult; +} + +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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +/** +Used for all 32 and 24 bit loading of uncompressed images +*/ +static void +loadTrueColor(FIBITMAP* dib, int width, int height, int file_pixel_size, FreeImageIO* io, fi_handle handle, BOOL as24bit) { + const int pixel_size = as24bit ? 3 : file_pixel_size; + + // input line cache + BYTE* file_line = (BYTE*)malloc( width * file_pixel_size); + + if (!file_line) { + throw FI_MSG_ERROR_MEMORY; + } + + for (int y = 0; y < height; y++) { + BYTE *bits = FreeImage_GetScanLine(dib, y); + io->read_proc(file_line, file_pixel_size, width, handle); + BYTE *bgra = file_line; + + for (int x = 0; x < width; x++) { + + bits[FI_RGBA_BLUE] = bgra[0]; + bits[FI_RGBA_GREEN] = bgra[1]; + bits[FI_RGBA_RED] = bgra[2]; + + if (!as24bit) { + bits[FI_RGBA_ALPHA] = bgra[3]; + } + + bgra += file_pixel_size; + + bits += pixel_size; + } + } + + free(file_line); +} + +/** +For the generic RLE loader we need to abstract away the pixel format. +We use a specific overload based on bits-per-pixel for each type of pixel +*/ + +template +inline static void +_assignPixel(BYTE* bits, BYTE* val, BOOL as24bit = FALSE) { + // static assert should go here + assert(FALSE); +} + +template <> +inline void +_assignPixel<8>(BYTE* bits, BYTE* val, BOOL as24bit) { + *bits = *val; +} + +template <> +inline void +_assignPixel<16>(BYTE* bits, BYTE* val, BOOL as24bit) { + WORD value(*reinterpret_cast(val)); + +#ifdef FREEIMAGE_BIGENDIAN + SwapShort(&value); +#endif + + if (as24bit) { + bits[FI_RGBA_BLUE] = (BYTE)((((value & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F); + bits[FI_RGBA_GREEN] = (BYTE)((((value & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F); + bits[FI_RGBA_RED] = (BYTE)((((value & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F); + + } else { + *reinterpret_cast(bits) = 0x7FFF & value; + } +} + +template <> +inline void +_assignPixel<24>(BYTE* bits, BYTE* val, BOOL as24bit) { + bits[FI_RGBA_BLUE] = val[0]; + bits[FI_RGBA_GREEN] = val[1]; + bits[FI_RGBA_RED] = val[2]; +} + +template <> +inline void +_assignPixel<32>(BYTE* bits, BYTE* val, BOOL as24bit) { + if (as24bit) { + _assignPixel<24>(bits, val, TRUE); + + } else { +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + *(reinterpret_cast(bits)) = *(reinterpret_cast (val)); +#else // NOTE This is faster then doing reinterpret_cast to int + INPLACESWAP ! + bits[FI_RGBA_BLUE] = val[0]; + bits[FI_RGBA_GREEN] = val[1]; + bits[FI_RGBA_RED] = val[2]; + bits[FI_RGBA_ALPHA] = val[3]; +#endif + } +} + +/** +Generic RLE loader +*/ +template +static void +loadRLE(FIBITMAP* dib, int width, int height, FreeImageIO* io, fi_handle handle, long eof, BOOL as24bit) { + const int file_pixel_size = bPP/8; + const int pixel_size = as24bit ? 3 : file_pixel_size; + + const BYTE bpp = as24bit ? 24 : bPP; + const int line_size = CalculateLine(width, bpp); + + // Note, many of the params can be computed inside the function. + // However, because this is a template function, it will lead to redundant code duplication. + + BYTE rle; + BYTE *line_bits; + + // this is used to guard against writing beyond the end of the image (on corrupted rle block) + const BYTE* dib_end = FreeImage_GetScanLine(dib, height);//< one-past-end row + + // Compute the rough size of a line... + long pixels_offset = io->tell_proc(handle); + long sz = ((eof - pixels_offset) / height); + + // ...and allocate cache of this size (yields good results) + IOCache cache(io, handle, sz); + if(cache.isNull()) { + FreeImage_Unload(dib); + dib = NULL; + return; + } + + int x = 0, y = 0; + + line_bits = FreeImage_GetScanLine(dib, y); + + while (y < height) { + + rle = cache.getByte(); + + BOOL has_rle = rle & 0x80; + rle &= ~0x80; // remove type-bit + + BYTE packet_count = rle + 1; + + //packet_count might be corrupt, test if we are not about to write beyond the last image bit + + if ((line_bits+x) + packet_count*pixel_size > dib_end) { + FreeImage_OutputMessageProc(s_format_id, FI_MSG_ERROR_CORRUPTED); + // return what is left from the bitmap + return; + } + + if (has_rle) { + + // read a pixel value from file... + BYTE *val = cache.getBytes(file_pixel_size); + + //...and fill packet_count pixels with it + + for (int ix = 0; ix < packet_count; ix++) { + _assignPixel((line_bits+x), val, as24bit); + x += pixel_size; + + if (x >= line_size) { + x = 0; + y++; + line_bits = FreeImage_GetScanLine(dib, y); + } + } + + } else { + // no rle commpresion + + // copy packet_count pixels from file to dib + for (int ix = 0; ix < packet_count; ix++) { + BYTE *val = cache.getBytes(file_pixel_size); + _assignPixel((line_bits+x), val, as24bit); + x += pixel_size; + + if (x >= line_size) { + x = 0; + y++; + line_bits = FreeImage_GetScanLine(dib, y); + } + } //< packet_count + } //< has_rle + + } //< while height + +} + +// -------------------------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + FIBITMAP *dib = NULL; + + if (!handle) { + return NULL; + } + + try { + + const BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // 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 footer + + TargaThumbnail thumbnail; + if(isTARGA20(io, handle)) { + TGAFOOTER footer; + const long footer_offset = start_offset + eof - sizeof(footer); + + io->seek_proc(handle, footer_offset, SEEK_SET); + io->read_proc(&footer, sizeof(tagTGAFOOTER), 1, handle); + +#ifdef FREEIMAGE_BIGENDIAN + SwapFooter(&footer); +#endif + BOOL hasExtensionArea = footer.extension_offset > 0; + if(hasExtensionArea) { + TGAEXTENSIONAREA extensionarea; + io->seek_proc(handle, footer.extension_offset, SEEK_SET); + io->read_proc(&extensionarea, sizeof(extensionarea), 1, handle); + +#ifdef FREEIMAGE_BIGENDIAN + SwapExtensionArea(&extensionarea); +#endif + + DWORD postage_stamp_offset = extensionarea.postage_stamp_offset; + BOOL hasThumbnail = (postage_stamp_offset > 0) && (postage_stamp_offset < (DWORD)footer_offset); + if(hasThumbnail) { + io->seek_proc(handle, postage_stamp_offset, SEEK_SET); + thumbnail.read(io, handle, footer_offset - postage_stamp_offset); + } + } + } + + // read and process the bitmap's header + + TGAHEADER header; + + io->seek_proc(handle, start_offset, SEEK_SET); + io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle); + +#ifdef FREEIMAGE_BIGENDIAN + SwapHeader(&header); +#endif + + thumbnail.setDepth(header.is_pixel_depth); + + const int line = CalculateLine(header.is_width, header.is_pixel_depth); + const int pixel_bits = header.is_pixel_depth; + const int pixel_size = pixel_bits/8; + + int fliphoriz = (header.is_image_descriptor & 0x10) ? 1 : 0; + 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_AllocateHeader(header_only, header.is_width, header.is_height, 8); + + if (dib == NULL) { + throw FI_MSG_ERROR_DIB_MEMORY; + } + + // read the palette (even if header only) + + RGBQUAD *palette = FreeImage_GetPalette(dib); + + if (header.color_map_type > 0) { + 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; + + } // switch(header.cm_size) + + free(cmap); + } + + // handle thumbnail + + FIBITMAP* th = thumbnail.toFIBITMAP(); + if(th) { + RGBQUAD* pal = FreeImage_GetPalette(dib); + RGBQUAD* dst_pal = FreeImage_GetPalette(th); + if(dst_pal && pal) { + for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++) { + dst_pal[i] = pal[i]; + } + } + + FreeImage_SetTransparencyTable(th, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); + + FreeImage_SetThumbnail(dib, th); + FreeImage_Unload(th); + } + + if(header_only) { + return dib; + } + + // read in the bitmap bits + + switch (header.image_type) { + case TGA_CMAP: + case TGA_MONO: { + BYTE *bits = NULL; + + for (unsigned count = 0; count < header.is_height; count++) { + bits = FreeImage_GetScanLine(dib, count); + io->read_proc(bits, sizeof(BYTE), line, handle); + } + } + break; + + case TGA_RLECMAP: + case TGA_RLEMONO: { //(8 bit) + loadRLE<8>(dib, header.is_width, header.is_height, io, handle, eof, FALSE); + } + break; + + default : + FreeImage_Unload(dib); + return NULL; + } + } + break; // header.is_pixel_depth == 8 + + case 15 : + + case 16 : { + int pixel_bits = 16; + + // allocate the dib + + if (TARGA_LOAD_RGB888 & flags) { + pixel_bits = 24; + dib = FreeImage_AllocateHeader(header_only, header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + + } else { + dib = FreeImage_AllocateHeader(header_only, 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; + } + + // handle thumbnail + + FIBITMAP* th = thumbnail.toFIBITMAP(); + if(th) { + if(TARGA_LOAD_RGB888 & flags) { + FIBITMAP* t = FreeImage_ConvertTo24Bits(th); + FreeImage_Unload(th); + th = t; + } + + FreeImage_SetThumbnail(dib, th); + FreeImage_Unload(th); + } + + if(header_only) { + return dib; + } + + int line = CalculateLine(header.is_width, pixel_bits); + + const unsigned pixel_size = unsigned(pixel_bits) / 8; + const unsigned src_pixel_size = sizeof(WORD); + + // 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) + // input line cache + BYTE *in_line = (BYTE*)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 = FreeImage_GetScanLine(dib, y); + io->read_proc(in_line, src_pixel_size, header.is_width, handle); + + BYTE *val = in_line; + for (int x = 0; x < line; x += pixel_size) { + + _assignPixel<16>(bits+x, val, TARGA_LOAD_RGB888 & flags); + + val += src_pixel_size; + } + } + + free(in_line); + } + break; + + case TGA_RLERGB: { //(16 bit) + loadRLE<16>(dib, header.is_width, header.is_height, io, handle, eof, TARGA_LOAD_RGB888 & flags); + } + break; + + default : + FreeImage_Unload(dib); + return NULL; + } + } + break; // header.is_pixel_depth == 15 or 16 + + case 24 : { + + dib = FreeImage_AllocateHeader(header_only, 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; + } + + FIBITMAP* th = thumbnail.toFIBITMAP(); + if(th) { + FreeImage_SetThumbnail(dib, th); + FreeImage_Unload(th); + } + + if(header_only) { + return dib; + } + + // read in the bitmap bits + + switch (header.image_type) { + case TGA_RGB: { //(24 bit) + //uncompressed + loadTrueColor(dib, header.is_width, header.is_height, pixel_size,io, handle, TRUE); + } + break; + + case TGA_RLERGB: { //(24 bit) + loadRLE<24>(dib, header.is_width, header.is_height, io, handle, eof, TRUE); + } + break; + + default : + FreeImage_Unload(dib); + return NULL; + } + } + break; // header.is_pixel_depth == 24 + + case 32 : { + int pixel_bits = 32; + + if (TARGA_LOAD_RGB888 & flags) { + pixel_bits = 24; + } + + dib = FreeImage_AllocateHeader(header_only, 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; + } + + // handle thumbnail + + FIBITMAP* th = thumbnail.toFIBITMAP(); + if(th) { + if(TARGA_LOAD_RGB888 & flags) { + FIBITMAP* t = FreeImage_ConvertTo24Bits(th); + FreeImage_Unload(th); + th = t; + } + FreeImage_SetThumbnail(dib, th); + FreeImage_Unload(th); + } + + if(header_only) { + return dib; + } + + // read in the bitmap bits + + switch (header.image_type) { + case TGA_RGB: { //(32 bit) + // uncompressed + loadTrueColor(dib, header.is_width, header.is_height, 4 /*file_pixel_size*/, io, handle, TARGA_LOAD_RGB888 & flags); + } + break; + + case TGA_RLERGB: { //(32 bit) + loadRLE<32>(dib, header.is_width, header.is_height, io, handle, eof, TARGA_LOAD_RGB888 & flags); + } + break; + + default : + FreeImage_Unload(dib); + return NULL; + } + } + break; // header.is_pixel_depth == 32 + + } // switch(header.is_pixel_depth) + + if (flipvert) { + FreeImage_FlipVertical(dib); + } + + if (fliphoriz) { + FreeImage_FlipHorizontal(dib); + } + + return dib; + + } catch (const char *message) { + if (dib) { + FreeImage_Unload(dib); + } + + FreeImage_OutputMessageProc(s_format_id, message); + + return NULL; + } +} + +// -------------------------------------------------------------------------- + +static BOOL +hasValidThumbnail(FIBITMAP* dib) { + FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); + + return thumbnail + && SupportsExportType(FreeImage_GetImageType(thumbnail)) + && SupportsExportDepth(FreeImage_GetBPP(thumbnail)) + // Requirements according to the specification: + && FreeImage_GetBPP(thumbnail) == FreeImage_GetBPP(dib) + && FreeImage_GetImageType(thumbnail) == FreeImage_GetImageType(dib) + && FreeImage_GetWidth(thumbnail) <= 255 + && FreeImage_GetHeight(thumbnail) <= 255; +} + +/** +Writes the ready RLE packet to buffer +*/ +static inline void +flushPacket(BYTE*& dest, unsigned pixel_size, BYTE* packet_begin, BYTE*& packet, BYTE& packet_count, BOOL& has_rle) { + if (packet_count) { + const BYTE type_bit = has_rle ? 0x80 : 0x0; + const BYTE write_count = has_rle ? 1 : packet_count; + + // build packet header: zero-based count + type bit + assert(packet_count >= 1); + BYTE rle = packet_count - 1; + rle |= type_bit; + + // write packet header + *dest = rle; + ++dest; + + // write packet data + memcpy(dest, packet_begin, write_count * pixel_size); + dest += write_count * pixel_size; + + // reset state + packet_count = 0; + packet = packet_begin; + has_rle = FALSE; + } +} + + +static inline void +writeToPacket(BYTE* packet, BYTE* pixel, unsigned pixel_size) { + // Take care of channel and byte order here, because packet will be flushed straight to the file + switch (pixel_size) { + case 1: + *packet = *pixel; + break; + + case 2: { + WORD val(*(WORD*)pixel); +#ifdef FREEIMAGE_BIGENDIAN + SwapShort(&val); +#endif + *(WORD*)packet = val; + } + break; + + case 3: { + packet[0] = pixel[FI_RGBA_BLUE]; + packet[1] = pixel[FI_RGBA_GREEN]; + packet[2] = pixel[FI_RGBA_RED]; + } + break; + + case 4: { +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + *(reinterpret_cast(packet)) = *(reinterpret_cast (pixel)); +#else + packet[0] = pixel[FI_RGBA_BLUE]; + packet[1] = pixel[FI_RGBA_GREEN]; + packet[2] = pixel[FI_RGBA_RED]; + packet[3] = pixel[FI_RGBA_ALPHA]; +#endif + } + break; + + default: + assert(FALSE); + } +} + +static inline BOOL +isEqualPixel(BYTE* lhs, BYTE* rhs, unsigned pixel_size) { + switch (pixel_size) { + case 1: + return *lhs == *rhs; + + case 2: + return *(WORD*)lhs == *(WORD*)rhs; + + case 3: + return *(WORD*)lhs == *(WORD*)rhs && lhs[2] == rhs[2]; + + case 4: + return *(unsigned*)lhs == *(unsigned*)rhs; + + default: + assert(FALSE); + return FALSE; + } +} + +static void +saveRLE(FIBITMAP* dib, FreeImageIO* io, fi_handle handle) { + // Image is compressed line by line, packets don't span multiple lines (TGA2.0 recommendation) + + const unsigned width = FreeImage_GetWidth(dib); + const unsigned height = FreeImage_GetHeight(dib); + const unsigned pixel_size = FreeImage_GetBPP(dib)/8; + const unsigned line_size = FreeImage_GetLine(dib); + + const BYTE max_packet_size = 128; + BYTE packet_count = 0; + BOOL has_rle = FALSE; + + // packet (compressed or not) to be written to line + + BYTE* const packet_begin = (BYTE*)malloc(max_packet_size * pixel_size); + BYTE* packet = packet_begin; + + // line to be written to disk + // Note: we need some extra bytes for anti-commpressed lines. The worst case is: + // 8 bit images were every 3th pixel is different. + // Rle packet becomes two pixels, but nothing is compressed: two byte pixels are transformed into byte header and byte pixel value + // After every rle packet there is a non-rle packet of one pixel: an extra byte for the header will be added for it + // In the end we gain no bytes from compression, but also must insert a byte at every 3th pixel + + // add extra space for anti-commpressed lines + size_t extra_space = (size_t)ceil(width / 3.0); + BYTE* const line_begin = (BYTE*)malloc(width * pixel_size + extra_space); + BYTE* line = line_begin; + + BYTE *current = (BYTE*)malloc(pixel_size); + BYTE *next = (BYTE*)malloc(pixel_size); + + for(unsigned y = 0; y < height; y++) { + BYTE *bits = FreeImage_GetScanLine(dib, y); + + // rewind line pointer + line = line_begin; + + for(unsigned x = 0; x < line_size; x += pixel_size) { + + AssignPixel(current, (bits + x), pixel_size); + + // read next pixel from dib + + if ( x + 1*pixel_size < line_size) { + AssignPixel(next, (bits + x + 1*pixel_size), pixel_size); + + } else { + // last pixel in line + + // include current pixel and flush + if (!has_rle) { + + writeToPacket(packet, current, pixel_size); + packet += pixel_size; + + } + + assert(packet_count < max_packet_size); + + ++packet_count; + + flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); + + // start anew on next line + break; + } + + if(isEqualPixel(current, next, pixel_size)) { + + // has rle + + if (!has_rle) { + // flush non rle packet + + flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); + + // start a rle packet + + has_rle = TRUE; + + writeToPacket(packet, current, pixel_size); + packet += pixel_size; + } + + // otherwise do nothing. We will just increase the count at the end + + } else { + + // no rle + + if(has_rle) { + // flush rle packet + + // include current pixel first + assert(packet_count < max_packet_size); + ++packet_count; + + flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); + + // start anew on the next pixel + continue; + + } else { + + writeToPacket(packet, current, pixel_size); + packet += pixel_size; + } + + } + + // increase counter on every pixel + + ++packet_count; + + if(packet_count == max_packet_size) { + flushPacket(line, pixel_size, packet_begin, packet, packet_count, has_rle); + } + + }//for width + + // write line to disk + io->write_proc(line_begin, 1, (unsigned)(line - line_begin), handle); + + }//for height + + free(line_begin); + free(packet_begin); + free(current); + free(next); +} + +static BOOL DLL_CALLCONV +Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { + if ((dib == NULL) || (handle == NULL)) { + return FALSE; + } + + RGBQUAD *palette = FreeImage_GetPalette(dib); + const unsigned 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 = (TARGA_SAVE_RLE & flags) ? TGA_RLECMAP : 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 = (TARGA_SAVE_RLE & flags) ? TGA_RLERGB : 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 + + + if (TARGA_SAVE_RLE & flags) { + + saveRLE(dib, io, handle); + + } else { + + // -- no rle compression -- + + const unsigned width = header.is_width; + const unsigned height = header.is_height; + const unsigned pixel_size = bpp/8; + + BYTE *line, *const line_begin = (BYTE*)malloc(width * pixel_size); + BYTE *line_source = line_begin; + + for (unsigned y = 0; y < height; y++) { + BYTE *scanline = FreeImage_GetScanLine(dib, y); + + // rewind the line pointer + line = line_begin; + + switch (bpp) { + case 8: { + // don't copy line, read straight from dib + line_source = scanline; + } + break; + + case 16: { + for (unsigned x = 0; x < width; x++) { + WORD pixel = *(((WORD *)scanline) + x); + +#ifdef FREEIMAGE_BIGENDIAN + SwapShort(&pixel); +#endif + *(WORD*)line = pixel; + + line += pixel_size; + } + } + break; + + case 24: { + +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + line_source = scanline; +#else + for (unsigned x = 0; x < width; ++x) { + RGBTRIPLE* trip = ((RGBTRIPLE *)scanline) + x; + line[0] = trip->rgbtBlue; + line[1] = trip->rgbtGreen; + line[2] = trip->rgbtRed; + + line += pixel_size; + } +#endif + } + break; + + case 32: { + +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + line_source = scanline; +#else + for (unsigned x = 0; x < width; ++x) { + RGBQUAD* quad = ((RGBQUAD *)scanline) + x; + line[0] = quad->rgbBlue; + line[1] = quad->rgbGreen; + line[2] = quad->rgbRed; + line[3] = quad->rgbReserved; + + line += pixel_size; + } +#endif + } + break; + + }//switch(bpp) + + // write line to disk + + io->write_proc(line_source, pixel_size, width, handle); + + }//for height + + free(line_begin); + } + + + long extension_offset = 0 ; + if(hasValidThumbnail(dib)) { + // write extension area + + extension_offset = io->tell_proc(handle); + + TGAEXTENSIONAREA ex; + memset(&ex, 0, sizeof(ex)); + + assert(sizeof(ex) == 495); + ex.extension_size = sizeof(ex); + ex.postage_stamp_offset = extension_offset + ex.extension_size + 0 /*< no Scan Line Table*/; + ex.attributes_type = FreeImage_GetBPP(dib) == 32 ? 3 /*< useful Alpha channel data*/ : 0 /*< no Alpha data*/; + +#ifdef FREEIMAGE_BIGENDIAN + SwapExtensionArea(&ex); +#endif + + io->write_proc(&ex, sizeof(ex), 1, handle); + + // (no Scan Line Table) + + // write thumbnail + + io->seek_proc(handle, ex.postage_stamp_offset, SEEK_SET); + + FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib); + BYTE width = (BYTE)FreeImage_GetWidth(thumbnail); + BYTE height = (BYTE)FreeImage_GetHeight(thumbnail); + + io->write_proc(&width, 1, 1, handle); + io->write_proc(&height, 1, 1, handle); + +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB + SwapRedBlue32(dib); +#endif + +#ifdef FREEIMAGE_BIGENDIAN + swapShortPixels(dib); +#endif + + const unsigned line_size = FreeImage_GetLine(thumbnail); + + for (BYTE h = 0; h < height; ++h) { + BYTE* src_line = FreeImage_GetScanLine(thumbnail, height - 1 - h); + io->write_proc(src_line, 1, line_size, handle); + } + } + + // (no Color Correction Table) + + // write the footer + + TGAFOOTER footer; + footer.extension_offset = extension_offset; + footer.developer_offset = 0; + strcpy(footer.signature, "TRUEVISION-XFILE."); + + +#ifdef FREEIMAGE_BIGENDIAN + SwapFooter(&footer); +#endif + + io->write_proc(&footer, sizeof(footer), 1, handle); + + return TRUE; +} + +// ========================================================== +// 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginTIFF.cpp b/plugins/FreeImage/src/FreeImage/PluginTIFF.cpp new file mode 100644 index 0000000000..54f81e0938 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginTIFF.cpp @@ -0,0 +1,2629 @@ +// ========================================================== +// 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) +// - 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! +// ========================================================== + +#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 "FreeImage.h" +#include "Utilities.h" +#include "../LibTIFF4/tiffiop.h" +#include "../Metadata/FreeImageTag.h" +#include "../OpenEXR/Half/half.h" + +#include "FreeImageIO.h" +#include "PSDParser.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); +BOOL tiff_write_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, + LoadAsLogLuv = 5, + LoadAsHalfFloat = 6 +} TIFFLoadMethod; + +// ---------------------------------------------------------- +// local prototypes +// ---------------------------------------------------------- + +static tmsize_t _tiffReadProc(thandle_t handle, void* buf, tmsize_t size); +static tmsize_t _tiffWriteProc(thandle_t handle, void* buf, tmsize_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, void** pbase, toff_t* psize); +static void _tiffUnmapProc(thandle_t fd, void* 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(BOOL header_only, 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); + +static void ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib); + + +// ========================================================== +// Plugin Interface +// ========================================================== + +static int s_format_id; + +typedef struct { + FreeImageIO *io; + fi_handle handle; + TIFF *tif; +} fi_TIFFIO; + +// ---------------------------------------------------------- +// libtiff interface +// ---------------------------------------------------------- + +static tmsize_t +_tiffReadProc(thandle_t handle, void *buf, tmsize_t size) { + fi_TIFFIO *fio = (fi_TIFFIO*)handle; + return fio->io->read_proc(buf, size, 1, fio->handle) * size; +} + +static tmsize_t +_tiffWriteProc(thandle_t handle, void *buf, tmsize_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 + +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, void** base, toff_t* size) { + return 0; +} + +static void +_tiffUnmapProc(thandle_t, void* base, toff_t size) { +} + +/** +Open a TIFF file descriptor for reading or writing +@param handle File handle +@param name Name of the file handle +@param mode Specifies if the file is to be opened for reading ("r") or writing ("w") +*/ +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 reading or writing +@param name +@param mode +*/ +TIFF* +TIFFOpen(const char* name, const char* mode) { + return 0; +} + +// ---------------------------------------------------------- +// TIFF library FreeImage-specific routines. +// ---------------------------------------------------------- + +void* +_TIFFmalloc(tmsize_t s) { + return malloc(s); +} + +void +_TIFFfree(void *p) { + free(p); +} + +void* +_TIFFrealloc(void* p, tmsize_t s) { + return realloc(p, s); +} + +void +_TIFFmemset(void* p, int v, tmsize_t c) { + memset(p, v, (size_t) c); +} + +void +_TIFFmemcpy(void* d, const void* s, tmsize_t c) { + memcpy(d, s, (size_t) c); +} + +int +_TIFFmemcmp(const void* p1, const void* p2, tmsize_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<= 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 header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full 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(BOOL header_only, FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel) { + FIBITMAP *dib = NULL; + + if ((width < 0) || (height < 0)) { + // check for malicious images + return NULL; + } + + int bpp = bitspersample * samplesperpixel; + + if(fit == FIT_BITMAP) { + // standard bitmap type + + if(bpp == 16) { + + if ((samplesperpixel == 2) && (bitspersample == 8)) { + // 8-bit indexed + 8-bit alpha channel -> convert to 8-bit transparent + dib = FreeImage_AllocateHeader(header_only, width, height, 8); + } else { + // 16-bit RGB -> expect it to be 565 + dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK); + } + + } + else { + + dib = FreeImage_AllocateHeader(header_only, width, height, MIN(bpp, 32), FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } + + + } else { + // other bitmap types + + dib = FreeImage_AllocateHeaderT(header_only, 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 48: + // 3 x half float => convert to RGBF + if ((samplesperpixel == 3) && (bitspersample == 16)) { + fit = FIT_RGBF; + } + break; + case 64: + if(samplesperpixel == 2) { + fit = FIT_FLOAT; + } else { + fit = FIT_DOUBLE; + } + break; + case 96: + fit = FIT_RGBF; + break; + default: + if(bpp >= 128) { + fit = FIT_RGBAF; + } + 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(bitspersample == 16) { + 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 96: + 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) { + BOOL bResult = FALSE; + toff_t exif_offset = 0; + + // read EXIF-TIFF tags + bResult = 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; + } + + // read all known exif tags + bResult = tiff_read_exif_tags(tiff, TagLib::EXIF_EXIF, dib); + } + + return bResult; +} + +/** +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 the Exif profile to TIFF + @param dib Input FIBITMAP + @param tiff LibTIFF TIFF handle + @return Returns TRUE if successful, FALSE otherwise +*/ +static BOOL +tiff_write_exif_profile(TIFF *tiff, FIBITMAP *dib) { + BOOL bResult = FALSE; + uint32 exif_offset = 0; + + // write EXIF_MAIN tags, EXIF_EXIF not supported yet + bResult = tiff_write_exif_tags(tiff, TagLib::EXIF_MAIN, dib); + + return bResult; +} + +/** +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); + + // EXIF_MAIN tags + tiff_write_exif_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) || + (type == FIT_RGBAF) + ); +} + +static BOOL DLL_CALLCONV +SupportsICCProfiles() { + return TRUE; +} + +static BOOL DLL_CALLCONV +SupportsNoPixels() { + 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 +@param samplesperpixel TIFFTAG_SAMPLESPERPIXEL tiff tag +@return Returns FALSE if a uncommon bit-depth is encountered, returns TRUE otherwise +*/ +static BOOL +IsValidBitsPerSample(uint16 photometric, uint16 bitspersample, uint16 samplesperpixel) { + + 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)-1; + uint16 samplesperpixel = (uint16)-1; + uint16 photometric = (uint16)-1; + uint16 planar_config = (uint16)-1; + + 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(image_type == FIT_RGBF) { + if ((samplesperpixel == 3) && (bitspersample == 16)) { + // load 3 x 16-bit half as RGBF + loadMethod = LoadAsHalfFloat; + } + } + break; + case PHOTOMETRIC_YCBCR: + case PHOTOMETRIC_CIELAB: + case PHOTOMETRIC_ICCLAB: + case PHOTOMETRIC_ITULAB: + loadMethod = LoadAsRBGA; + break; + case PHOTOMETRIC_LOGLUV: + loadMethod = LoadAsLogLuv; + break; + case PHOTOMETRIC_SEPARATED: + // 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 (!bIsTiled) { + 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 > 1) && (bitspersample == 8)) { + loadMethod = LoadAs8BitTrns; + } else { + loadMethod = LoadAsGenericStrip; + } + break; + default: + loadMethod = LoadAsGenericStrip; + break; + } + + if ((loadMethod == LoadAsGenericStrip) && bIsTiled) { + loadMethod = LoadAsTiled; + } + + return loadMethod; +} + +// ========================================================== +// TIFF thumbnail routines +// ========================================================== + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data); + +/** +Read embedded thumbnail +*/ +static void +ReadThumbnail(FreeImageIO *io, fi_handle handle, void *data, TIFF *tiff, FIBITMAP *dib) { + FIBITMAP* thumbnail = NULL; + + // read exif thumbnail (IFD 1) ... + + uint32 exif_offset = 0; + if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) { + + if(TIFFLastDirectory(tiff) != 0) { + // save current position + long tell_pos = io->tell_proc(handle); + uint16 cur_dir = TIFFCurrentDirectory(tiff); + + // load the thumbnail + int page = 1; + int flags = TIFF_DEFAULT; + thumbnail = Load(io, handle, page, flags, data); + // store the thumbnail (remember to release it later ...) + FreeImage_SetThumbnail(dib, thumbnail); + + // restore current position + io->seek_proc(handle, tell_pos, SEEK_SET); + TIFFSetDirectory(tiff, cur_dir); + } + } + + // ... or read the first subIFD + + if (!thumbnail) { + uint16 subIFD_count = 0; + uint64* subIFD_offsets = NULL; + // ### Theoretically this should also read the first subIFD from a Photoshop-created file with "pyramid". + // It does not however - the tag is there (using Tag Viewer app) but libtiff refuses to read it + if(TIFFGetField(tiff, TIFFTAG_SUBIFD, &subIFD_count, &subIFD_offsets)) { + if(subIFD_count > 0) { + // save current position + long tell_pos = io->tell_proc(handle); + uint16 cur_dir = TIFFCurrentDirectory(tiff); + if(TIFFSetSubDirectory(tiff, subIFD_offsets[0])) { + // load the thumbnail + int page = -1; + int flags = TIFF_DEFAULT; + thumbnail = Load(io, handle, page, flags, data); + // store the thumbnail (remember to release it later ...) + FreeImage_SetThumbnail(dib, thumbnail); + } + // restore current position + io->seek_proc(handle, tell_pos, SEEK_SET); + TIFFSetDirectory(tiff, cur_dir); + } + } + } + + // ... or read Photoshop thumbnail + + if (!thumbnail) { + uint32 ps_size = 0; + void *ps_data = NULL; + + if(TIFFGetField(tiff, TIFFTAG_PHOTOSHOP, &ps_size, &ps_data)) { + FIMEMORY *handle = FreeImage_OpenMemory((BYTE*)ps_data, ps_size); + + FreeImageIO io; + SetMemoryIO(&io); + + psdParser parser; + parser.ReadImageResources(&io, handle, ps_size); + + FreeImage_SetThumbnail(dib, parser.GetThumbnail()); + + FreeImage_CloseMemory(handle); + } + + } + + // release thumbnail + FreeImage_Unload(thumbnail); +} + +// -------------------------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + if (!handle || !data ) { + return NULL; + } + + TIFF *tif = NULL; + uint32 height = 0; + uint32 width = 0; + uint16 bitspersample = 1; + uint16 samplesperpixel = 1; + uint32 rowsperstrip = (uint32)-1; + uint16 photometric = PHOTOMETRIC_MINISWHITE; + uint16 compression = (uint16)-1; + uint16 planar_config; + + FIBITMAP *dib = NULL; + uint32 iccSize = 0; // ICC profile length + void *iccBuf = NULL; // ICC profile data + + const BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + try { + fi_TIFFIO *fio = (fi_TIFFIO*)data; + tif = fio->tif; + + if (page != -1) { + if (!tif || !TIFFSetDirectory(tif, (uint16)page)) { + throw "Error encountered while opening TIFF file"; + } + } + + const BOOL asCMYK = (flags & TIFF_CMYK) == TIFF_CMYK; + + // 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(IsValidBitsPerSample(photometric, bitspersample, samplesperpixel) == 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 = NULL; + + if (!header_only) { + + 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, 1)) { + _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) { // TODO Write to Extra Channels + 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(header_only, image_type, width, height, bitspersample, samplesperpixel); + if (dib == NULL) { + // free the raster pointer and output an error if allocation failed + if(raster) { + _TIFFfree(raster); + } + throw FI_MSG_ERROR_DIB_MEMORY; + } + + // fill in the resolution (english or universal) + + ReadResolution(tif, dib); + + if (!header_only) { + + // 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); + } + + // ### Not correct when header only + FreeImage_SetTransparent(dib, has_alpha); + + } else if(loadMethod == LoadAs8BitTrns) { + // --------------------------------------------------------------------------------- + // 8-bit + 8-bit alpha layer loading + // --------------------------------------------------------------------------------- + + // create a new 8-bit DIB + dib = CreateImageType(header_only, image_type, width, height, bitspersample, MIN(2, 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) + + const tmsize_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 saved 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 && !header_only) { + + 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 && !header_only) { + tmsize_t stripsize = TIFFStripSize(tif) * sizeof(BYTE); + BYTE *buf = (BYTE*)malloc(2 * stripsize); + if(buf == NULL) { + throw FI_MSG_ERROR_MEMORY; + } + 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 + // --------------------------------------------------------------------------------- + + // 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); + + // We use a temp dib to store the alpha for the CMYKA to RGBA conversion + // NOTE this is until we have Extra channels implementation. + // Also then it will be possible to merge LoadAsCMYK with LoadAsGenericStrip + + FIBITMAP *alpha = NULL; + unsigned alpha_pitch = 0; + BYTE *alpha_bits = NULL; + unsigned alpha_Bpp = 0; + + if(isCMYKA && !asCMYK && !header_only) { + if(bitspersample == 16) { + alpha = FreeImage_AllocateT(FIT_UINT16, width, height); + } else if (bitspersample == 8) { + alpha = FreeImage_Allocate(width, height, 8); + } + + if (!alpha) { + FreeImage_OutputMessageProc(s_format_id, "Failed to allocate temporary alpha channel"); + } else { + alpha_bits = FreeImage_GetScanLine(alpha, height - 1); + alpha_pitch = FreeImage_GetPitch(alpha); + alpha_Bpp = FreeImage_GetBPP(alpha) / 8; + } + + } + + // create a new DIB + const uint16 chCount = MIN(samplesperpixel, 4); + dib = CreateImageType(header_only, image_type, width, height, bitspersample, chCount); + if (dib == NULL) { + FreeImage_Unload(alpha); + throw FI_MSG_ERROR_MEMORY; + } + + // fill in the resolution (english or universal) + + ReadResolution(tif, dib); + + if (!header_only) { + + // calculate the line + pitch (separate for scr & dest) + + const tmsize_t src_line = TIFFScanlineSize(tif); + const tmsize_t dst_line = FreeImage_GetLine(dib); + const unsigned dib_pitch = FreeImage_GetPitch(dib); + const unsigned dibBpp = FreeImage_GetBPP(dib) / 8; + const unsigned Bpc = dibBpp / chCount; + const unsigned srcBpp = bitspersample * samplesperpixel / 8; + + assert(Bpc <= 2); //< CMYK is only BYTE or SHORT + + // 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 + + BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); + if(buf == NULL) { + FreeImage_Unload(alpha); + throw FI_MSG_ERROR_MEMORY; + } + + if(planar_config == PLANARCONFIG_CONTIG) { + + // - loop for strip blocks - + + for (uint32 y = 0; y < height; y += rowsperstrip) { + const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); + + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, strips * src_line) == -1) { + free(buf); + FreeImage_Unload(alpha); + throw FI_MSG_ERROR_PARSING; + } + + // - loop for strips - + + if(src_line != dst_line) { + // CMYKA+ + if(alpha) { + for (int l = 0; l < strips; l++) { + for(BYTE *pixel = bits, *al_pixel = alpha_bits, *src_pixel = buf + l * src_line; pixel < bits + dib_pitch; pixel += dibBpp, al_pixel += alpha_Bpp, src_pixel += srcBpp) { + // copy pixel byte by byte + BYTE b = 0; + for ( ; b < dibBpp; ++b) { + pixel[b] = src_pixel[b]; + } + // TODO write the remaining bytes to extra channel(s) + + // HACK write the first alpha to a separate dib (assume BYTE or WORD) + al_pixel[0] = src_pixel[b]; + if(Bpc > 1) { + al_pixel[1] = src_pixel[b + 1]; + } + + } + bits -= dib_pitch; + alpha_bits -= alpha_pitch; + } + } + else { + // alpha/extra channels alloc failed + for (int l = 0; l < strips; l++) { + for(BYTE* pixel = bits, * src_pixel = buf + l * src_line; pixel < bits + dst_line; pixel += dibBpp, src_pixel += srcBpp) { + AssignPixel(pixel, src_pixel, dibBpp); + } + bits -= dib_pitch; + } + } + } + else { + // CMYK to CMYK + for (int l = 0; l < strips; l++) { + BYTE *b = buf + l * src_line; + memcpy(bits, b, src_line); + bits -= dib_pitch; + } + } + + } // height + + } + else if(planar_config == PLANARCONFIG_SEPARATE) { + + BYTE *dib_strip = bits; + BYTE *al_strip = alpha_bits; + + // - loop for strip blocks - + + for (uint32 y = 0; y < height; y += rowsperstrip) { + const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); + + // - loop for channels (planes) - + + for(uint16 sample = 0; sample < samplesperpixel; sample++) { + + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), buf, strips * src_line) == -1) { + free(buf); + FreeImage_Unload(alpha); + throw FI_MSG_ERROR_PARSING; + } + + BYTE *dst_strip = dib_strip; + unsigned dst_pitch = dib_pitch; + uint16 ch = sample; + unsigned Bpp = dibBpp; + + if(sample >= chCount) { + // TODO Write to Extra Channel + + // HACK redirect write to temp alpha + if(alpha && sample == chCount) { + + dst_strip = al_strip; + dst_pitch = alpha_pitch; + + ch = 0; + Bpp = alpha_Bpp; + } + else { + break; + } + } + + const unsigned channelOffset = ch * Bpc; + + // - loop for strips in block - + + BYTE *src_line_begin = buf; + BYTE *dst_line_begin = dst_strip; + for (int l = 0; l < strips; l++, src_line_begin += src_line, dst_line_begin -= dst_pitch ) { + // - loop for pixels in strip - + + const BYTE* const src_line_end = src_line_begin + src_line; + for (BYTE *src_bits = src_line_begin, * dst_bits = dst_line_begin; src_bits < src_line_end; src_bits += Bpc, dst_bits += Bpp) { + AssignPixel(dst_bits + channelOffset, src_bits, Bpc); + } // line + + } // strips + + } // channels + + // done with a strip block, incr to the next + dib_strip -= strips * dib_pitch; + al_strip -= strips * alpha_pitch; + + } //< height + + } + + free(buf); + + if (!asCMYK) { + ConvertCMYKtoRGBA(dib); + + // The ICC Profile is invalid, clear it + iccSize = 0; + iccBuf = NULL; + + if(isCMYKA) { + // HACK until we have Extra channels. (ConvertCMYKtoRGBA will then do the work) + + FreeImage_SetChannel(dib, alpha, FICC_ALPHA); + FreeImage_Unload(alpha); + alpha = NULL; + } + else { + FIBITMAP *t = RemoveAlphaChannel(dib); + if(t) { + FreeImage_Unload(dib); + dib = t; + } + else { + FreeImage_OutputMessageProc(s_format_id, "Cannot allocate memory for buffer. CMYK image converted to RGB + pending Alpha"); + } + } + } + + } // !header_only + + } else if(loadMethod == LoadAsGenericStrip) { + // --------------------------------------------------------------------------------- + // Generic loading + // --------------------------------------------------------------------------------- + + // create a new DIB + const uint16 chCount = MIN(samplesperpixel, 4); + dib = CreateImageType(header_only, image_type, width, height, bitspersample, chCount); + 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); + + if (!header_only) { + // calculate the line + pitch (separate for scr & dest) + + const tmsize_t src_line = TIFFScanlineSize(tif); + const tmsize_t dst_line = FreeImage_GetLine(dib); + const unsigned dst_pitch = FreeImage_GetPitch(dib); + const unsigned Bpp = FreeImage_GetBPP(dib) / 8; + const unsigned srcBpp = bitspersample * samplesperpixel / 8; + + // 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 + + BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE)); + if(buf == NULL) { + throw FI_MSG_ERROR_MEMORY; + } + + BOOL bThrowMessage = FALSE; + + if(planar_config == PLANARCONFIG_CONTIG) { + + for (uint32 y = 0; y < height; y += rowsperstrip) { + int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); + + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, strips * 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; + */ + } + if(src_line == dst_line) { + // channel count match + for (int l = 0; l < strips; l++) { + memcpy(bits, buf + l * src_line, src_line); + bits -= dst_pitch; + } + } + else { + for (int l = 0; l < strips; l++) { + for(BYTE *pixel = bits, *src_pixel = buf + l * src_line; pixel < bits + dst_pitch; pixel += Bpp, src_pixel += srcBpp) { + AssignPixel(pixel, src_pixel, Bpp); + } + bits -= dst_pitch; + } + } + } + } + else if(planar_config == PLANARCONFIG_SEPARATE) { + + const unsigned Bpc = bitspersample / 8; + BYTE* dib_strip = bits; + // - loop for strip blocks - + + for (uint32 y = 0; y < height; y += rowsperstrip) { + const int32 strips = (y + rowsperstrip > height ? height - y : rowsperstrip); + + // - loop for channels (planes) - + + for(uint16 sample = 0; sample < samplesperpixel; sample++) { + + if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), buf, strips * src_line) == -1) { + // ignore errors as they can be frequent and not really valid errors, especially with fax images + bThrowMessage = TRUE; + } + + if(sample >= chCount) { + // TODO Write to Extra Channel + break; + } + + const unsigned channelOffset = sample * Bpc; + + // - loop for strips in block - + + BYTE* src_line_begin = buf; + BYTE* dst_line_begin = dib_strip; + for (int l = 0; l < strips; l++, src_line_begin += src_line, dst_line_begin -= dst_pitch ) { + + // - loop for pixels in strip - + + const BYTE* const src_line_end = src_line_begin + src_line; + + for (BYTE* src_bits = src_line_begin, * dst_bits = dst_line_begin; src_bits < src_line_end; src_bits += Bpc, dst_bits += Bpp) { + // actually assigns channel + AssignPixel(dst_bits + channelOffset, src_bits, Bpc); + } // line + + } // strips + + } // channels + + // done with a strip block, incr to the next + dib_strip -= strips * dst_pitch; + + } // height + + } + free(buf); + + if(bThrowMessage) { + FreeImage_OutputMessageProc(s_format_id, "Warning: parsing error. Image may be incomplete or contain invalid data !"); + } + +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + SwapRedBlue32(dib); +#endif + + } // !header only + + } else if(loadMethod == LoadAsTiled) { + // --------------------------------------------------------------------------------- + // Tiled image loading + // --------------------------------------------------------------------------------- + + uint32 tileWidth, tileHeight; + uint32 src_line = 0; + + // create a new DIB + dib = CreateImageType( header_only, 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"; + } + + // read the tiff lines and save them in the DIB + + if(planar_config == PLANARCONFIG_CONTIG && !header_only) { + + // get the maximum number of bytes required to contain a tile + tmsize_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 saved from up to down + // In a DIB the lines must be saved from down to up + + BYTE *bits = FreeImage_GetScanLine(dib, height - 1); + + 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; + } + +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + SwapRedBlue32(dib); +#endif + free(tileBuffer); + } + else if(planar_config == PLANARCONFIG_SEPARATE) { + throw "Separated tiled TIFF images are not supported"; + } + + + } else if(loadMethod == LoadAsLogLuv) { + // --------------------------------------------------------------------------------- + // RGBF LogLuv compressed loading + // --------------------------------------------------------------------------------- + + double stonits; // input conversion to nits + if (!TIFFGetField(tif, TIFFTAG_STONITS, &stonits)) { + stonits = 1; + } + + // create a new DIB + dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel); + if (dib == NULL) { + throw FI_MSG_ERROR_MEMORY; + } + + // fill in the resolution (english or universal) + + ReadResolution(tif, dib); + + if(planar_config == PLANARCONFIG_CONTIG && !header_only) { + // calculate the line + pitch (separate for scr & dest) + + tmsize_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 + + 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 happen according to the LogLuv specification + throw "Unable to handle PLANARCONFIG_SEPARATE LogLuv images"; + } + + } else if(loadMethod == LoadAsHalfFloat) { + // --------------------------------------------------------------------------------- + // RGBF loading from a half format + // --------------------------------------------------------------------------------- + + // create a new DIB + dib = CreateImageType(header_only, image_type, width, height, bitspersample, samplesperpixel); + if (dib == NULL) { + throw FI_MSG_ERROR_MEMORY; + } + + // fill in the resolution (english or universal) + + ReadResolution(tif, dib); + + if (!header_only) { + + // calculate the line + pitch (separate for scr & dest) + + tmsize_t src_line = TIFFScanlineSize(tif); + unsigned 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) { + uint32 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 half (16-bit) to float (32-bit) + // !!! use OpenEXR half helper class + + half half_value; + + for (uint32 l = 0; l < nrow; l++) { + WORD *src_pixel = (WORD*)(buf + l * src_line); + float *dst_pixel = (float*)bits; + + for(tmsize_t x = 0; x < (tmsize_t)(src_line / sizeof(WORD)); x++) { + half_value.setBits(src_pixel[x]); + dst_pixel[x] = half_value; + } + + bits -= dst_pitch; + } + } + + free(buf); + } + else if(planar_config == PLANARCONFIG_SEPARATE) { + // this use case was never encountered yet + throw "Unable to handle PLANARCONFIG_SEPARATE RGB half float images"; + } + + } // !header only + + } 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 && asCMYK) { + FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK; + } + + // copy TIFF metadata (must be done after FreeImage_Allocate) + + ReadMetadata(tif, dib); + + // copy TIFF thumbnail (must be done after FreeImage_Allocate) + + ReadThumbnail(io, handle, data, tif, dib); + + return (FIBITMAP *)dib; + + } catch (const char *message) { + if(dib) { + FreeImage_Unload(dib); + } + if(message) { + FreeImage_OutputMessageProc(s_format_id, message); + } + return NULL; + } + +} + +// -------------------------------------------------------------------------- + +static BOOL +SaveOneTIFF(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data, unsigned ifd, unsigned ifdCount) { + if (!dib || !handle || !data) { + return FALSE; + } + + try { + fi_TIFFIO *fio = (fi_TIFFIO*)data; + TIFF *out = fio->tif; + + const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + + const uint32 width = FreeImage_GetWidth(dib); + const uint32 height = FreeImage_GetHeight(dib); + const uint16 bitsperpixel = (uint16)FreeImage_GetBPP(dib); + + const FIICCPROFILE* iccProfile = FreeImage_GetICCProfile(dib); + + // setup out-variables based on dib and flag options + + uint16 bitspersample; + uint16 samplesperpixel; + uint16 photometric; + + 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; + 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 { + 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; + // the library converts to and from floating-point XYZ CIE values + if ((flags & TIFF_LOGLUV) == TIFF_LOGLUV) { + photometric = PHOTOMETRIC_LOGLUV; + TIFFSetField(out, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT); + // TIFFSetField(out, TIFFTAG_STONITS, 1.0); // assume unknown + } + else { + // store with default compression (LZW) or with input compression flag + photometric = PHOTOMETRIC_RGB; + } + + } else if (image_type == FIT_RGBAF) { + // 128-bit RGBAF => store with default compression (LZW) or with input compression flag + + samplesperpixel = 4; + bitspersample = bitsperpixel / samplesperpixel; + photometric = PHOTOMETRIC_RGB; + } 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_FILLORDER, FILLORDER_MSB2LSB); + TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, (uint32) -1)); + + // handle metrics + + WriteResolution(out, dib); + + // multi-paging + + if (page >= 0) { + char page_number[20]; + sprintf(page_number, "Page %d", page); + + TIFFSetField(out, TIFFTAG_SUBFILETYPE, (uint32)FILETYPE_PAGE); + TIFFSetField(out, TIFFTAG_PAGENUMBER, (uint16)page, (uint16)0); + TIFFSetField(out, TIFFTAG_PAGENAME, page_number); + + } else { + // is it a thumbnail ? + TIFFSetField(out, TIFFTAG_SUBFILETYPE, (ifd == 0) ? (uint32)0 : (uint32)FILETYPE_REDUCEDIMAGE); + } + + // 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 tag + + WriteCompression(out, bitspersample, samplesperpixel, photometric, flags); + + // metadata + + WriteMetadata(out, dib); + + // thumbnail tag + + if ((ifd == 0) && (ifdCount > 1)) { + uint16 nsubifd = 1; + uint64 subifd[1]; + subifd[0] = 0; + TIFFSetField(out, TIFFTAG_SUBIFD, nsubifd, subifd); + } + + // read the DIB lines from bottom to top + // and save them in the TIF + // ------------------------------------- + + const uint32 pitch = 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 (int y = height - 1; y >= 0; y--) { + BYTE *bits = FreeImage_GetScanLine(dib, y); + + BYTE *p = bits, *b = buffer; + + for(uint32 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 (uint32 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 (uint32 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 (uint32 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; + } + }//< switch (bitsperpixel) + + } else if(image_type == FIT_RGBF && (flags & TIFF_LOGLUV) == TIFF_LOGLUV) { + // 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 (uint32 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 { + // just dump the dib (tiff supports all dib types) + + BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE)); + if(buffer == NULL) { + throw FI_MSG_ERROR_MEMORY; + } + + for (uint32 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); + } + + // write out the directory tag if we wrote a page other than -1 or if we have a thumbnail to write later + + if ( (page >= 0) || ((ifd == 0) && (ifdCount > 1)) ) { + TIFFWriteDirectory(out); + // else: TIFFClose will WriteDirectory + } + + return TRUE; + + } catch(const char *text) { + FreeImage_OutputMessageProc(s_format_id, text); + return FALSE; + } +} + +static BOOL DLL_CALLCONV +Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { + BOOL bResult = FALSE; + + // handle thumbnail as SubIFD + const BOOL bHasThumbnail = (FreeImage_GetThumbnail(dib) != NULL); + const unsigned ifdCount = bHasThumbnail ? 2 : 1; + + FIBITMAP *bitmap = dib; + + for(unsigned ifd = 0; ifd < ifdCount; ifd++) { + // redirect dib to thumbnail for the second pass + if(ifd == 1) { + bitmap = FreeImage_GetThumbnail(dib); + } + + bResult = SaveOneTIFF(io, bitmap, handle, page, flags, data, ifd, ifdCount); + if (!bResult) { + return FALSE; + } + } + + return bResult; +} + +// ========================================================== +// 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} diff --git a/plugins/FreeImage/src/FreeImage/PluginWBMP.cpp b/plugins/FreeImage/src/FreeImage/PluginWBMP.cpp new file mode 100644 index 0000000000..2ff8f023c3 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginWBMP.cpp @@ -0,0 +1,372 @@ +// ========================================================== +// Wireless Bitmap Format Loader and Writer +// +// 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 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/plugins/FreeImage/src/FreeImage/PluginXBM.cpp b/plugins/FreeImage/src/FreeImage/PluginXBM.cpp new file mode 100644 index 0000000000..140029e862 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginXBM.cpp @@ -0,0 +1,399 @@ +// ========================================================== +// XBM Loader +// +// Design and implementation by +// - Hervé Drolon +// 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/plugins/FreeImage/src/FreeImage/PluginXPM.cpp b/plugins/FreeImage/src/FreeImage/PluginXPM.cpp new file mode 100644 index 0000000000..16db443c47 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/PluginXPM.cpp @@ -0,0 +1,487 @@ +// ========================================================== +// 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/x-xpixmap"; +} + +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 BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ---------------------------------------------------------- + +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; + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + //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_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + } else { + dib = FreeImage_AllocateHeader(header_only, width, height, 8); + } + + //build a map of color chars to rgb values + std::map 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 + + if(header_only) { + // header only mode + return dib; + } + + //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 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 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; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} + diff --git a/plugins/FreeImage/src/FreeImage/TIFFLogLuv.cpp b/plugins/FreeImage/src/FreeImage/TIFFLogLuv.cpp new file mode 100644 index 0000000000..124b25f64f --- /dev/null +++ b/plugins/FreeImage/src/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" + // 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/plugins/FreeImage/src/FreeImage/ToneMapping.cpp b/plugins/FreeImage/src/FreeImage/ToneMapping.cpp new file mode 100644 index 0000000000..33ae08ea59 --- /dev/null +++ b/plugins/FreeImage/src/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(FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImage/WuQuantizer.cpp b/plugins/FreeImage/src/FreeImage/WuQuantizer.cpp new file mode 100644 index 0000000000..532fbfc3e6 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/WuQuantizer.cpp @@ -0,0 +1,538 @@ +/////////////////////////////////////////////////////////////////////// +// 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" + +/////////////////////////////////////////////////////////////////////// + +// Size of a 3D array : 33 x 33 x 33 +#define SIZE_3D 35937 + +// 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(SIZE_3D * sizeof(float)); + wt = (LONG*)malloc(SIZE_3D * sizeof(LONG)); + mr = (LONG*)malloc(SIZE_3D * sizeof(LONG)); + mg = (LONG*)malloc(SIZE_3D * sizeof(LONG)); + mb = (LONG*)malloc(SIZE_3D * 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, SIZE_3D * sizeof(float)); + memset(wt, 0, SIZE_3D * sizeof(LONG)); + memset(mr, 0, SIZE_3D * sizeof(LONG)); + memset(mg, 0, SIZE_3D * sizeof(LONG)); + memset(mb, 0, SIZE_3D * 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; + unsigned 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 < SIZE_3D; i++) { + if ( vwt[i] > max ) max = vwt[i]; + } + 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) { + unsigned 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(SIZE_3D * sizeof(BYTE)); + if (tag == NULL) { + throw FI_MSG_ERROR_MEMORY; + } + memset(tag, 0, SIZE_3D * sizeof(BYTE)); + + 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 (unsigned y = 0; y < height; y++) { + BYTE *new_bits = FreeImage_GetBits(new_dib) + (y * npitch); + + for (unsigned 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/plugins/FreeImage/src/FreeImage/ZLibInterface.cpp b/plugins/FreeImage/src/FreeImage/ZLibInterface.cpp new file mode 100644 index 0000000000..3ab6d321f2 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/ZLibInterface.cpp @@ -0,0 +1,223 @@ +// ========================================================== +// 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/zlib.h" +#include "FreeImage.h" +#include "Utilities.h" +#include "../ZLib/zutil.h" /* must be the last header because of error C3163 in VS2008 (_vsnprintf defined in stdio.h) */ + +/** +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/plugins/FreeImage/src/FreeImage/tmoColorConvert.cpp b/plugins/FreeImage/src/FreeImage/tmoColorConvert.cpp new file mode 100644 index 0000000000..367cb13c96 --- /dev/null +++ b/plugins/FreeImage/src/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.
+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; + + 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++) { + 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; + } + const float W = result[0] + result[1] + result[2]; + const 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.
+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; + + 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++) { + 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.
+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; + + const unsigned width = FreeImage_GetWidth(Yxy); + const unsigned height = FreeImage_GetHeight(Yxy); + const 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-5F + 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; + + const unsigned width = FreeImage_GetWidth(src); + const 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; + + const unsigned src_pitch = FreeImage_GetPitch(src); + const 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.0F * red + 0.5F); + dst_pixel[FI_RGBA_GREEN] = (BYTE)(255.0F * green + 0.5F); + dst_pixel[FI_RGBA_BLUE] = (BYTE)(255.0F * blue + 0.5F); + 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; + + const unsigned width = FreeImage_GetWidth(src); + const unsigned height = FreeImage_GetHeight(src); + + FIBITMAP *dst = FreeImage_AllocateT(FIT_FLOAT, width, height); + if (!dst) return NULL; + + const unsigned src_pitch = FreeImage_GetPitch(src); + const 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++) { + const float L = LUMA_REC709(src_pixel[x].red, src_pixel[x].green, 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-5F + 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 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
+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/plugins/FreeImage/src/FreeImage/tmoDrago03.cpp b/plugins/FreeImage/src/FreeImage/tmoDrago03.cpp new file mode 100644 index 0000000000..b820bb3577 --- /dev/null +++ b/plugins/FreeImage/src/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 : (1.099F * pow(*pixel, fgamma) - 0.099F); + 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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImage/tmoFattal02.cpp b/plugins/FreeImage/src/FreeImage/tmoFattal02.cpp new file mode 100644 index 0000000000..bcd4524523 --- /dev/null +++ b/plugins/FreeImage/src/FreeImage/tmoFattal02.cpp @@ -0,0 +1,689 @@ +// ========================================================== +// 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) { + 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); + + const unsigned width = FreeImage_GetWidth(dib); + const unsigned 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); + + const unsigned 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(unsigned y = 0; y < height; y++) { + // work on line y + for(unsigned 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(unsigned x = 0; x < width; x++) { + // work on column x + for(unsigned y = 2; y < height - 2; y++) { + const unsigned 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) { + FIBITMAP *G = NULL; + + try { + const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(H); + if(image_type != FIT_FLOAT) throw(1); + + const unsigned width = FreeImage_GetWidth(H); + const unsigned height = FreeImage_GetHeight(H); + + G = FreeImage_AllocateT(image_type, width, height); + if (!G) throw(1); + + const unsigned 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(unsigned y = 0; y < height; y++) { + const unsigned n = (y == 0 ? 0 : y-1); + const unsigned s = (y+1 == height ? y : y+1); + for(unsigned x = 0; x < width; x++) { + const unsigned w = (x == 0 ? 0 : x-1); + const unsigned e = (x+1 == width ? x : x+1); + // central difference + const float gx = (src_pixel[y*pitch+e] - src_pixel[y*pitch+w]) / divider; // [Hk(x+1, y) - Hk(x-1, y)] / 2**(k+1) + const 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) { + 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]; + + const unsigned width = FreeImage_GetWidth(Gk); + const unsigned height = FreeImage_GetHeight(Gk); + const unsigned 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(unsigned y = 0; y < height; y++) { + for(unsigned 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(unsigned y = 0; y < height; y++) { + for(unsigned 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) { + 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); + + const unsigned width = FreeImage_GetWidth(H); + const unsigned 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); + + const unsigned 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(unsigned y = 0; y < height; y++) { + const unsigned s = (y+1 == height ? y : y+1); + for(unsigned x = 0; x < width; x++) { + const unsigned e = (x+1 == width ? x : x+1); + // forward difference + const unsigned 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(unsigned y0 = 0; y0 < height; y0++) { + for(unsigned x = 0; x < width; x++) { + // backward difference approximation + // divG = Gx(x, y) - Gx(x-1, y) + Gy(x, y) - Gy(x, y-1) + const unsigned index = y0*pitch + x; + divg[index] = gx[index] + gy[index]; + if(x > 0) divg[index] -= gx[index-1]; + if(y0 > 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) { + FIBITMAP *H = NULL; + + try { + // get the luminance channel + FIBITMAP *H = FreeImage_Clone(Y); + if (!H) throw(1); + + const unsigned width = FreeImage_GetWidth(H); + const unsigned height = FreeImage_GetHeight(H); + const unsigned pitch = FreeImage_GetPitch(H); + + // find max & min luminance values + float maxLum = -1e20F, minLum = 1e20F; + + BYTE *bits = (BYTE*)FreeImage_GetBits(H); + for(unsigned y = 0; y < height; y++) { + const float *pixel = (float*)bits; + for(unsigned 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(unsigned y0 = 0; y0 < height; y0++) { + float *pixel = (float*)bits; + for(unsigned 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) { + const unsigned width = FreeImage_GetWidth(Y); + const unsigned height = FreeImage_GetHeight(Y); + const unsigned pitch = FreeImage_GetPitch(Y); + + BYTE *bits = (BYTE*)FreeImage_GetBits(Y); + for(unsigned y = 0; y < height; y++) { + float *pixel = (float*)bits; + for(unsigned 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 unsigned 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 + const unsigned width = FreeImage_GetWidth(H); + const unsigned height = FreeImage_GetHeight(H); + unsigned 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; + + if (!FreeImage_HasPixels(dib)) return NULL; + + try { + + // 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 + + const unsigned width = FreeImage_GetWidth(src); + const unsigned height = FreeImage_GetHeight(src); + + const unsigned rgb_pitch = FreeImage_GetPitch(src); + const unsigned 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(unsigned y = 0; y < height; y++) { + float *Lin = (float*)bits_yin; + float *Lout = (float*)bits_yout; + float *color = (float*)bits; + for(unsigned x = 0; x < width; x++) { + for(unsigned 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/plugins/FreeImage/src/FreeImage/tmoReinhard05.cpp b/plugins/FreeImage/src/FreeImage/tmoReinhard05.cpp new file mode 100644 index 0000000000..969aa4c950 --- /dev/null +++ b/plugins/FreeImage/src/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
+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 (!FreeImage_HasPixels(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
+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/plugins/FreeImage/src/FreeImageIO.h b/plugins/FreeImage/src/FreeImageIO.h new file mode 100644 index 0000000000..b251d474f6 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/FreeImageToolkit/BSplineRotate.cpp b/plugins/FreeImage/src/FreeImageToolkit/BSplineRotate.cpp new file mode 100644 index 0000000000..e4be1d0bd2 --- /dev/null +++ b/plugins/FreeImage/src/FreeImageToolkit/BSplineRotate.cpp @@ -0,0 +1,730 @@ +// ========================================================== +// 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 +#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.
+ 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; + + if (!FreeImage_HasPixels(dib)) return 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/plugins/FreeImage/src/FreeImageToolkit/Channels.cpp b/plugins/FreeImage/src/FreeImageToolkit/Channels.cpp new file mode 100644 index 0000000000..f6e6c5509c --- /dev/null +++ b/plugins/FreeImage/src/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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImageToolkit/ClassicRotate.cpp b/plugins/FreeImage/src/FreeImageToolkit/ClassicRotate.cpp new file mode 100644 index 0000000000..d38d8c1bcd --- /dev/null +++ b/plugins/FreeImage/src/FreeImageToolkit/ClassicRotate.cpp @@ -0,0 +1,917 @@ +// ========================================================== +// Bitmap rotation by means of 3 shears. +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// - Thorsten Radde (support@IdealSoftware.com) +// - 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! +// ========================================================== + +/* + ============================================================ + 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 + +// -------------------------------------------------------------------------- + +/** +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 void +HorizontalSkewT(FIBITMAP *src, FIBITMAP *dst, int row, int iOffset, double weight, const void *bkcolor = NULL) { + int iXPos; + + const unsigned src_width = FreeImage_GetWidth(src); + const 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(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 + const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); + // calculate the number of samples per pixel + const 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); + } + AssignPixel((BYTE*)&pxlOldLeft[0], (BYTE*)bkcolor, bytespp); + } else { + if(iOffset > 0) { + memset(dst_bits, 0, iOffset * bytespp); + } + memset(&pxlOldLeft[0], 0, bytespp); + } + + for(unsigned i = 0; i < src_width; i++) { + // loop through row pixels + AssignPixel((BYTE*)&pxlSrc[0], (BYTE*)src_bits, bytespp); + // calculate weights + for(unsigned j = 0; j < samples; j++) { + pxlLeft[j] = static_cast(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(unsigned j = 0; j < samples; j++) { + pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]); + } + AssignPixel((BYTE*)&dst_bits[iXPos*bytespp], (BYTE*)&pxlSrc[0], bytespp); + } + // save leftover for next pixel in scan + AssignPixel((BYTE*)&pxlOldLeft[0], (BYTE*)&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 + AssignPixel((BYTE*)dst_bits, (BYTE*)&pxlOldLeft[0], bytespp); + + // clear to the right of the skewed line with background + dst_bits += bytespp; + if(bkcolor) { + for(unsigned 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(src, dst, row, iOffset, dWeight, bkcolor); + break; + } + break; + case FIT_UINT16: + case FIT_RGB16: + case FIT_RGBA16: + HorizontalSkewT(src, dst, row, iOffset, dWeight, bkcolor); + break; + case FIT_FLOAT: + case FIT_RGBF: + case FIT_RGBAF: + HorizontalSkewT(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 void +VerticalSkewT(FIBITMAP *src, FIBITMAP *dst, int col, int iOffset, double weight, const void *bkcolor = NULL) { + 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(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 + const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); + // calculate the number of samples per pixel + const unsigned samples = bytespp / sizeof(T); + + const unsigned src_pitch = FreeImage_GetPitch(src); + const unsigned dst_pitch = FreeImage_GetPitch(dst); + const 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(unsigned i = 0; i < src_height; i++) { + // loop through column pixels + AssignPixel((BYTE*)(&pxlSrc[0]), src_bits, bytespp); + // calculate weights + for(unsigned j = 0; j < samples; j++) { + pxlLeft[j] = static_cast(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(unsigned j = 0; j < samples; j++) { + pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]); + } + dst_bits = FreeImage_GetScanLine(dst, iYPos) + index; + AssignPixel(dst_bits, (BYTE*)(&pxlSrc[0]), bytespp); + } + // save leftover for next pixel in scan + AssignPixel((BYTE*)(&pxlOldLeft[0]), (BYTE*)(&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 + AssignPixel((BYTE*)(dst_bits), (BYTE*)(&pxlOldLeft[0]), bytespp); + + // clear below skewed line with background + if(bkcolor) { + while(++iYPos < (int)dst_height) { + dst_bits += dst_pitch; + AssignPixel((BYTE*)(dst_bits), (BYTE*)(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(src, dst, col, iOffset, dWeight, bkcolor); + break; + } + break; + case FIT_UINT16: + case FIT_RGB16: + case FIT_RGBA16: + VerticalSkewT(src, dst, col, iOffset, dWeight, bkcolor); + break; + case FIT_FLOAT: + case FIT_RGBF: + case FIT_RGBAF: + VerticalSkewT(src, dst, col, iOffset, dWeight, bkcolor); + break; + } +} + +/** +Rotates an image by 90 degrees (counter clockwise). +Precise rotation, no filters required.
+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) { + + const unsigned bpp = FreeImage_GetBPP(src); + + const unsigned src_width = FreeImage_GetWidth(src); + const unsigned src_height = FreeImage_GetHeight(src); + const unsigned dst_width = src_height; + const unsigned 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 + const unsigned src_pitch = FreeImage_GetPitch(src); + const unsigned dst_pitch = FreeImage_GetPitch(dst); + + switch(image_type) { + case FIT_BITMAP: + if(bpp == 1) { + // speedy rotate for BW images + + BYTE *bsrc = FreeImage_GetBits(src); + BYTE *bdest = FreeImage_GetBits(dst); + + BYTE *dbitsmax = bdest + dst_height * dst_pitch - 1; + + for(unsigned y = 0; y < src_height; y++) { + // figure out the column we are going to be copying to + const div_t div_r = div(y, 8); + // set bit pos of src column byte + const BYTE bitpos = (BYTE)(128 >> div_r.rem); + BYTE *srcdisp = bsrc + y * src_pitch; + for(unsigned x = 0; x < src_pitch; x++) { + // get source bits + BYTE *sbits = srcdisp + x; + // get destination column + BYTE *nrow = bdest + (dst_height - 1 - (x * 8)) * dst_pitch + div_r.quot; + for (int z = 0; z < 8; z++) { + // get destination byte + 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. + + 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) + const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); + + // for all image blocks of RBLOCK*RBLOCK pixels + + // x-segment + for(unsigned xs = 0; xs < dst_width; xs += RBLOCK) { + // y-segment + for(unsigned ys = 0; ys < dst_height; ys += RBLOCK) { + for(unsigned y = ys; y < MIN(dst_height, ys + RBLOCK); y++) { // do rotation + const unsigned 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(unsigned x = xs; x < MIN(dst_width, xs + RBLOCK); x++) { + // dst.SetPixel(x, y, src.GetPixel(y2, x)); + AssignPixel(dst_bits, src_bits, bytespp); + 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 + const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); + + for(unsigned y = 0; y < dst_height; y++) { + BYTE *src_bits = bsrc + (src_width - 1 - y) * bytespp; + BYTE *dst_bits = bdest + (y * dst_pitch); + for(unsigned x = 0; x < dst_width; x++) { + AssignPixel(dst_bits, src_bits, bytespp); + 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; + + const int bpp = FreeImage_GetBPP(src); + + const int src_width = FreeImage_GetWidth(src); + const int src_height = FreeImage_GetHeight(src); + const int dst_width = src_width; + const 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)); + } + } + break; + } + // else if ((bpp == 8) || (bpp == 24) || (bpp == 32)) FALL TROUGH + 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 + const 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) + AssignPixel(dst_bits, src_bits, bytespp); + src_bits += bytespp; + dst_bits -= bytespp; + } + } + } + break; + } + + return dst; +} + +/** +Rotates an image by 270 degrees (counter clockwise). +Precise rotation, no filters required.
+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 x2, dlineup; + + const unsigned bpp = FreeImage_GetBPP(src); + + const unsigned src_width = FreeImage_GetWidth(src); + const unsigned src_height = FreeImage_GetHeight(src); + const unsigned dst_width = src_height; + const unsigned 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 + const unsigned src_pitch = FreeImage_GetPitch(src); + const unsigned dst_pitch = FreeImage_GetPitch(dst); + + switch(image_type) { + case FIT_BITMAP: + if(bpp == 1) { + // speedy rotate for BW images + + BYTE *bsrc = FreeImage_GetBits(src); + BYTE *bdest = FreeImage_GetBits(dst); + BYTE *dbitsmax = bdest + dst_height * dst_pitch - 1; + dlineup = 8 * dst_pitch - dst_width; + + for(unsigned y = 0; y < src_height; y++) { + // figure out the column we are going to be copying to + const div_t div_r = div(y + dlineup, 8); + // set bit pos of src column byte + const BYTE bitpos = (BYTE)(1 << div_r.rem); + const BYTE *srcdisp = bsrc + y * src_pitch; + for(unsigned x = 0; x < src_pitch; x++) { + // get source bits + const BYTE *sbits = srcdisp + x; + // get destination column + BYTE *nrow = bdest + (x * 8) * dst_pitch + dst_pitch - 1 - div_r.quot; + for(unsigned z = 0; z < 8; z++) { + // get destination byte + 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. + + 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) + const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); + + // for all image blocks of RBLOCK*RBLOCK pixels + + // x-segment + for(unsigned xs = 0; xs < dst_width; xs += RBLOCK) { + // y-segment + for(unsigned ys = 0; ys < dst_height; ys += RBLOCK) { + for(unsigned 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(unsigned y = ys; y < MIN(dst_height, ys + RBLOCK); y++) { + // dst.SetPixel(x, y, src.GetPixel(y, x2)); + AssignPixel(dst_bits, src_bits, bytespp); + 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 + const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); + + for(unsigned 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(unsigned x = 0; x < dst_width; x++) { + AssignPixel(dst_bits, src_bits, bytespp); + 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; + + const unsigned bpp = FreeImage_GetBPP(src); + + const double dRadAngle = dAngle * ROTATE_PI / double(180); // Angle in radians + const double dSinE = sin(dRadAngle); + const double dTan = tan(dRadAngle / 2); + + const unsigned src_width = FreeImage_GetWidth(src); + const unsigned src_height = FreeImage_GetHeight(src); + + FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); + + // Calc first shear (horizontal) destination image dimensions + const unsigned width_1 = src_width + unsigned((double)src_height * fabs(dTan) + 0.5); + const 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 + const 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 + const unsigned width_3 = unsigned(double(src_height) * fabs(dSinE) + double(src_width) * cos(dRadAngle) + 0.5) + 1; + const 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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImageToolkit/Colors.cpp b/plugins/FreeImage/src/FreeImageToolkit/Colors.cpp new file mode 100644 index 0000000000..8b9bbd6482 --- /dev/null +++ b/plugins/FreeImage/src/FreeImageToolkit/Colors.cpp @@ -0,0 +1,967 @@ +// ========================================================== +// Color manipulation routines +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// - Carsten Klein (c.klein@datagis.com) +// - 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" + +// ---------------------------------------------------------- +// 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) { + + if (!FreeImage_HasPixels(src)) return FALSE; + + unsigned i, x, y, k; + + const unsigned width = FreeImage_GetWidth(src); + const unsigned height = FreeImage_GetHeight(src); + const unsigned bpp = FreeImage_GetBPP(src); + + FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); + + if(image_type == FIT_BITMAP) { + 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 < height; y++) { + BYTE *bits = FreeImage_GetScanLine(src, y); + + for (x = 0; x < FreeImage_GetLine(src); x++) { + bits[x] = ~bits[x]; + } + } + } + + break; + } + + case 24 : + case 32 : + { + // Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit) + const unsigned bytespp = FreeImage_GetLine(src) / width; + + for(y = 0; y < height; y++) { + BYTE *bits = FreeImage_GetScanLine(src, y); + for(x = 0; x < width; x++) { + for(k = 0; k < bytespp; k++) { + bits[k] = ~bits[k]; + } + bits += bytespp; + } + } + + break; + } + default: + return FALSE; + } + } + else if ((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) { + // Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) + const unsigned wordspp = (FreeImage_GetLine(src) / width) / sizeof(WORD); + + for(y = 0; y < height; y++) { + WORD *bits = (WORD*)FreeImage_GetScanLine(src, y); + for(x = 0; x < width; x++) { + for(k = 0; k < wordspp; k++) { + bits[k] = ~bits[k]; + } + bits += wordspp; + } + } + } + else { + // anything else ... + return FALSE; + } + + 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.
+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.
+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. The size of 'LUT' is assumed to be 256. +@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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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
+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 (!FreeImage_HasPixels(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
+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 (!FreeImage_HasPixels(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. The size of 'histo' is assumed to be 256. +@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 (!FreeImage_HasPixels(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(). The + size of 'LUT' is assumed to be 256. + @param brightness Percentage brightness value where -100 <= brightness <= 100
+ 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
+ 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
+ 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
+ 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 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 (!FreeImage_HasPixels(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 count colors specified in srccolors to + these specified in dstcolors. Thereby, color srccolors[N], + if found in the image, will be replaced by color dstcolors[N]. If + parameter swap is TRUE, additionally all colors specified in + dstcolors are also mapped to these specified in srccolors. For + high color images, the actual image data will be modified whereas, for + palletized images only the palette will be changed.
+ + The function returns the number of pixels changed or zero, if no pixels were + changed. + + Both arrays srccolors and dstcolors are assumed not to hold less + than count colors.
+ + 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).
+ + Note, that this behaviour is different from what FreeImage_ApplyPaletteIndexMapping() + does, which modifies the actual image data on palletized images. + + @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 + srccolors and dstcolors. + @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 (!FreeImage_HasPixels(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 color_a and 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.
+ + Note, that this behaviour is different from what FreeImage_SwapPaletteIndices() + does, which modifies the actual image data on palletized images.
+ + This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:
+ return FreeImage_ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, TRUE); + + @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 count palette indices specified in + srcindices to these specified in dstindices. Thereby, index + srcindices[N], if present in the image, will be replaced by index + dstindices[N]. If parameter swap is TRUE, additionally all indices + specified in dstindices are also mapped to these specified in + srcindices.
+ + The function returns the number of pixels changed or zero, if no pixels were + changed. + + Both arrays srcindices and dstindices are assumed not to hold less + than count indices.
+ + Note, that this behaviour is different from what FreeImage_ApplyColorMapping() + does, which modifies the actual image data on palletized images. + + @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 + srcindices and dstindices. + @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 (!FreeImage_HasPixels(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 index_a and + index_b on a palletized image. Therefore, not the palette, but the + actual image data will be modified.
+ + Note, that this behaviour is different from what FreeImage_SwapColors() does + on palletized images, which only swaps the colors in the palette.
+ + This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:
+ return FreeImage_ApplyPaletteIndexMapping(dib, index_a, index_b, 1, TRUE); + + @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/plugins/FreeImage/src/FreeImageToolkit/CopyPaste.cpp b/plugins/FreeImage/src/FreeImageToolkit/CopyPaste.cpp new file mode 100644 index 0000000000..753fdc736e --- /dev/null +++ b/plugins/FreeImage/src/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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImageToolkit/Display.cpp b/plugins/FreeImage/src/FreeImageToolkit/Display.cpp new file mode 100644 index 0000000000..3e4807042d --- /dev/null +++ b/plugins/FreeImage/src/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:
+output = alpha * foreground + (1-alpha) * background
+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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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] + 127) / 255 ); + bits[FI_RGBA_GREEN] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_GREEN] + 127) / 255 ); + bits[FI_RGBA_RED] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_RED] + 127) / 255 ); + } + } + } + return TRUE; +} + diff --git a/plugins/FreeImage/src/FreeImageToolkit/Filters.h b/plugins/FreeImage/src/FreeImageToolkit/Filters.h new file mode 100644 index 0000000000..7a45c493f4 --- /dev/null +++ b/plugins/FreeImage/src/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.
+ Filters used in this library have been mainly taken from the following references :
+Main reference :
+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 + +Heckbert references :
+
    +
  • Oppenheim A.V., Schafer R.W., Digital Signal Processing, Prentice-Hall, 1975 +
  • Hamming R.W., Digital Filters, Prentice-Hall, Englewood Cliffs, NJ, 1983 +
  • Pratt W.K., Digital Image Processing, John Wiley and Sons, 1978 +
  • 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. +
+ +*/ +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
+ Box, pulse, Fourier window, 1st order (constant) b-spline.

+ + Reference :
+ Glassner A.S., Principles of digital image synthesis. Morgan Kaufmann Publishers, Inc, San Francisco, Vol. 2, 1995 +*/ +class CBoxFilter : public CGenericFilter +{ +public: + /** + Constructor
+ 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
+ + 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.

+ + Reference :
+ 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
+ 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
+ + When using CBicubicFilter filters, you have to set parameters b and c such that
+ b + 2 * c = 1
+ in order to use the numerically most accurate filter.
+ This gives for b = 0 the maximum value for c = 0.5, which is the Catmull-Rom + spline and a good suggestion for sharpness.

+ + + References :
+
    +
  • 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. +
  • 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. +
+ +*/ +class CCatmullRomFilter : public CGenericFilter +{ +public: + + /** + Constructor
+ 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
+ + 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.

+ +*/ +class CLanczos3Filter : public CGenericFilter +{ +public: + /** + Constructor
+ 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
+ +*/ +class CBSplineFilter : public CGenericFilter +{ +public: + + /** + Constructor
+ 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
+ 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/plugins/FreeImage/src/FreeImageToolkit/Flip.cpp b/plugins/FreeImage/src/FreeImageToolkit/Flip.cpp new file mode 100644 index 0000000000..c7898a7813 --- /dev/null +++ b/plugins/FreeImage/src/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 (!FreeImage_HasPixels(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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImageToolkit/JPEGTransform.cpp b/plugins/FreeImage/src/FreeImageToolkit/JPEGTransform.cpp new file mode 100644 index 0000000000..2d7399dcb2 --- /dev/null +++ b/plugins/FreeImage/src/FreeImageToolkit/JPEGTransform.cpp @@ -0,0 +1,410 @@ +// ========================================================== +// 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 + +#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 + + // Prepare transformation workspace + // Fails right away if perfect flag is TRUE and transformation is not perfect + if ( !jtransform_request_workspace(&srcinfo, &transfoptions)) { + FreeImage_OutputMessageProc(FIF_JPEG, "Transformation is not perfect"); + throw(1); + } + + // 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/plugins/FreeImage/src/FreeImageToolkit/MultigridPoissonSolver.cpp b/plugins/FreeImage/src/FreeImageToolkit/MultigridPoissonSolver.cpp new file mode 100644 index 0000000000..a31961447a --- /dev/null +++ b/plugins/FreeImage/src/FreeImageToolkit/MultigridPoissonSolver.cpp @@ -0,0 +1,505 @@ +// ========================================================== +// 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 multigrid 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 (!FreeImage_HasPixels(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++; + if ((1 << size) < MAX(width, height)) { + size++; + } + // size must be of the form 2^j + 1 for some integer j + size = 1 + (1 << size); + + // 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/plugins/FreeImage/src/FreeImageToolkit/Rescale.cpp b/plugins/FreeImage/src/FreeImageToolkit/Rescale.cpp new file mode 100644 index 0000000000..e79e5f456c --- /dev/null +++ b/plugins/FreeImage/src/FreeImageToolkit/Rescale.cpp @@ -0,0 +1,231 @@ +// ========================================================== +// 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 (!FreeImage_HasPixels(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(std::nothrow) CBoxFilter(); + break; + case FILTER_BICUBIC: + pFilter = new(std::nothrow) CBicubicFilter(); + break; + case FILTER_BILINEAR: + pFilter = new(std::nothrow) CBilinearFilter(); + break; + case FILTER_BSPLINE: + pFilter = new(std::nothrow) CBSplineFilter(); + break; + case FILTER_CATMULLROM: + pFilter = new(std::nothrow) CCatmullRomFilter(); + break; + case FILTER_LANCZOS3: + pFilter = new(std::nothrow) CLanczos3Filter(); + break; + } + + if (!pFilter) { + return NULL; + } + + 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); + FreeImage_Unload(src24); src24 = NULL; + // color quantize to 8-bit + dst = FreeImage_ColorQuantize(dst24, FIQ_NNQUANT); + // free and return + 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 (!FreeImage_HasPixels(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/plugins/FreeImage/src/FreeImageToolkit/Resize.cpp b/plugins/FreeImage/src/FreeImageToolkit/Resize.cpp new file mode 100644 index 0000000000..5421bd47ab --- /dev/null +++ b/plugins/FreeImage/src/FreeImageToolkit/Resize.cpp @@ -0,0 +1,656 @@ +// ========================================================== +// 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, unsigned uDstSize, unsigned uSrcSize) { + unsigned u; + double dWidth; + double dFScale = 1.0; + const double dFilterWidth = pFilter->GetWidth(); + + // scale factor + const 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 + const double dOffset = (0.5 / dScale) - 0.5; + + + for(u = 0; u < m_LineLength; u++) { + // scan through line of contributions + const 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 + const 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(unsigned 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
+ This class performs filtered zoom. It scales an image to the desired dimensions with + any of the CGenericFilter derived filter class.
+ It works with 8-, 24- and 32-bit buffers.

+ + References :
+ [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) { + unsigned src_width = FreeImage_GetWidth(src); + unsigned 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(unsigned 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(unsigned 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. + --- The theory --- + Try to minimize calculations by counting the number of convolution multiplies + if(dst_width*src_height <= src_width*dst_height) { + // xy filtering + } else { + // yx filtering + } + --- The practice --- + Try to minimize calculations by counting the number of vertical convolutions (the most time consuming task) + if(dst_width*dst_height <= src_width*dst_height) { + // xy filtering + } else { + // yx filtering + } + */ + + if(dst_width <= 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: + { + const BYTE *src_bits = FreeImage_GetBits(src); + BYTE *dst_bits = FreeImage_GetBits(dst); + memcpy(dst_bits, src_bits, dst_height * FreeImage_GetPitch(dst)); + } + break; + } + } + else { + + // 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 + const 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; + const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary + const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary + + for(unsigned i = iLeft; i <= iRight; i++) { + // scan between boundaries + // accumulate weighted effect of each neighboring pixel + const double weight = weightsTable.getWeight(x, i-iLeft); + + const 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)CLAMP((int)(value + 0.5), 0, 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) + const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); + + for(unsigned y = 0; y < dst_height; y++) { + // scale each row + const 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 = 32 bpp max + const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary + const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary + + for(unsigned i = iLeft; i <= iRight; i++) { + // scan between boundaries + // accumulate weighted effect of each neighboring pixel + const double weight = weightsTable.getWeight(x, i-iLeft); + + unsigned index = i * bytespp; // pixel index + 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)CLAMP((int)(value[j] + 0.5), 0, 0xFF); + } + + 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) + const unsigned wordspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(WORD); + + for(unsigned y = 0; y < dst_height; y++) { + // scale each row + const 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 = 64 bpp max + const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary + const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary + + for(unsigned i = iLeft; i <= iRight; i++) { + // scan between boundaries + // accumulate weighted effect of each neighboring pixel + const double weight = weightsTable.getWeight(x, i-iLeft); + + unsigned index = i * wordspp; // pixel index + 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)CLAMP((int)(value[j] + 0.5), 0, 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) + const unsigned floatspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(float); + + for(unsigned y = 0; y < dst_height; y++) { + // scale each row + const 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 = 128 bpp max + const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary + const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary + + for(unsigned i = iLeft; i <= iRight; i++) { + // scan between boundaries + // accumulate weighted effect of each neighboring pixel + const double weight = weightsTable.getWeight(x, i-iLeft); + + unsigned index = i * floatspp; // pixel index + 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: + { + const BYTE *src_bits = FreeImage_GetBits(src); + BYTE *dst_bits = FreeImage_GetBits(dst); + memcpy(dst_bits, src_bits, dst_height * FreeImage_GetPitch(dst)); + } + break; + } + + } + else { + + // 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; + + const unsigned src_pitch = FreeImage_GetPitch(src); + const 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; + const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary + const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary + + BYTE *src_bits = FreeImage_GetScanLine(src, iLeft); + + for(unsigned i = iLeft; i <= iRight; i++) { + // scan between boundaries + // accumulate weighted effect of each neighboring pixel + const double weight = weightsTable.getWeight(y, i-iLeft); + + const 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)CLAMP((int)(value + 0.5), 0, 0xFF); + + 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) + const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); + + const unsigned src_pitch = FreeImage_GetPitch(src); + const unsigned dst_pitch = FreeImage_GetPitch(dst); + + for(unsigned x = 0; x < dst_width; x++) { + const unsigned index = x * bytespp; // pixel index + + // 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 = 32 bpp max + const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary + const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary + + const BYTE *src_bits = FreeImage_GetScanLine(src, iLeft) + index; + + for(unsigned i = iLeft; i <= iRight; i++) { + // scan between boundaries + // accumulate weighted effect of each neighboring pixel + const 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)CLAMP((int)(value[j] + 0.5), 0, 0xFF); + } + + 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) + const unsigned wordspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(WORD); + + const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(WORD); + const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(WORD); + + for(unsigned x = 0; x < dst_width; x++) { + const unsigned index = x * wordspp; // pixel index + + // 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 = 64 bpp max + const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary + const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary + + const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, iLeft) + index; + + for(unsigned i = iLeft; i <= iRight; i++) { + // scan between boundaries + // accumulate weighted effect of each neighboring pixel + const 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)CLAMP((int)(value[j] + 0.5), 0, 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) + const unsigned floatspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(float); + + const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(float); + const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(float); + + for(unsigned x = 0; x < dst_width; x++) { + const unsigned index = x * floatspp; // pixel index + + // 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 = 128 bpp max + const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary + const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary + + const float *src_bits = (float*)FreeImage_GetScanLine(src, iLeft) + index; + + for(unsigned i = iLeft; i <= iRight; i++) { + // scan between boundaries + // accumulate weighted effect of each neighboring pixel + const 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/plugins/FreeImage/src/FreeImageToolkit/Resize.h b/plugins/FreeImage/src/FreeImageToolkit/Resize.h new file mode 100644 index 0000000000..0d5d0b451a --- /dev/null +++ b/plugins/FreeImage/src/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.
+ This class stores contribution information for an entire line (row or column). +*/ +class CWeightsTable +{ +/** + Sampled filter weight table.
+ Contribution information for a single pixel +*/ +typedef struct { + /// Normalized weights of neighboring pixels + double *Weights; + /// Bounds of source pixels window + unsigned Left, Right; +} Contribution; + +private: + /// Row (or column) of contribution weights + Contribution *m_WeightTable; + /// Filter window size (of affecting source pixels) + unsigned m_WindowSize; + /// Length of line (no. of rows / cols) + unsigned m_LineLength; + +public: + /** + Constructor
+ Allocate and compute the weights table + @param pFilter Filter used for upsampling or downsampling + @param uDstSize Length (in pixels) of the destination line buffer + @param uSrcSize Length (in pixels) of the source line buffer + */ + CWeightsTable(CGenericFilter *pFilter, unsigned uDstSize, unsigned uSrcSize); + + /** + Destructor
+ 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(unsigned dst_pos, unsigned 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 + */ + unsigned getLeftBoundary(unsigned 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 + */ + unsigned getRightBoundary(unsigned dst_pos) { + return m_WeightTable[dst_pos].Right; + } +}; + +// --------------------------------------------- + +/** + CResizeEngine
+ This class performs filtered zoom. It scales an image to the desired dimensions with + any of the CGenericFilter derived filter class.
+ It works with 8-, 24- and 32-bit buffers.

+ + References :
+ [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/plugins/FreeImage/src/LibJPEG/ansi2knr.c b/plugins/FreeImage/src/LibJPEG/ansi2knr.c new file mode 100644 index 0000000000..dcfb5d9255 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/ansi2knr.c @@ -0,0 +1,739 @@ +/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. */ + +/*$Id: ansi2knr.c,v 1.6 2012/01/29 12:23:24 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, <>) + * 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 + * . 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 + + 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 + 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 + 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 + ) + 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 + + 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 ; + 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 ; + properly erase prototype args in function parameters, + contributed by Jim Avera ; + 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 +#endif + +#include +#include + +#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 +# else +# include +# endif + +#else /* not HAVE_CONFIG_H */ + +/* Otherwise do it the hard way */ + +# ifdef BSD +# include +# else +# ifdef VMS + extern int strlen(), strncmp(); +# else +# include +# endif +# endif + +#endif /* not HAVE_CONFIG_H */ + +#if STDC_HEADERS +# include +#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 +# 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/plugins/FreeImage/src/LibJPEG/cderror.h b/plugins/FreeImage/src/LibJPEG/cderror.h new file mode 100644 index 0000000000..e19c475c5c --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/cderror.h @@ -0,0 +1,134 @@ +/* + * cderror.h + * + * Copyright (C) 1994-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 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_EMPTY, "Empty BMP image") +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/plugins/FreeImage/src/LibJPEG/cdjpeg.c b/plugins/FreeImage/src/LibJPEG/cdjpeg.c new file mode 100644 index 0000000000..89fe633728 --- /dev/null +++ b/plugins/FreeImage/src/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 /* to declare isupper(), tolower() */ +#ifdef NEED_SIGNAL_CATCHER +#include /* to declare signal() */ +#endif +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* 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/plugins/FreeImage/src/LibJPEG/cdjpeg.h b/plugins/FreeImage/src/LibJPEG/cdjpeg.h new file mode 100644 index 0000000000..ed024ac3ae --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/change.log b/plugins/FreeImage/src/LibJPEG/change.log new file mode 100644 index 0000000000..ce71abd2eb --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/change.log @@ -0,0 +1,346 @@ +CHANGE LOG for Independent JPEG Group's JPEG software + + +Version 8d 15-Jan-2012 +----------------------- + +Add cjpeg -rgb option to create RGB JPEG files. +Using this switch suppresses the conversion from RGB +colorspace input to the default YCbCr JPEG colorspace. +This feature allows true lossless JPEG coding of RGB color images. +The recommended command for this purpose is currently +cjpeg -rgb -block 1 -arithmetic. +SmartScale capable decoder (introduced with IJG JPEG 8) required. +Thank to Michael Koch for the initial suggestion. + +Add option to disable the region adjustment in the transupp crop code. +Thank to Jeffrey Friedl for the suggestion. + +Thank to Richard Jones and Edd Dawson for various minor corrections. + +Thank to Akim Demaille for configure.ac cleanup. + + +Version 8c 16-Jan-2011 +----------------------- + +Add option to compression library and cjpeg (-block N) to use +different DCT block size. +All N from 1 to 16 are possible. Default is 8 (baseline format). +Larger values produce higher compression, +smaller values produce higher quality. +SmartScale capable decoder (introduced with IJG JPEG 8) required. + + +Version 8b 16-May-2010 +----------------------- + +Repair problem in new memory source manager with corrupt JPEG data. +Thank to Ted Campbell and Samuel Chun for the report. + +Repair problem in Makefile.am test target. +Thank to anonymous user for the report. + +Support MinGW installation with automatic configure. +Thank to Volker Grabsch for the suggestion. + + +Version 8a 28-Feb-2010 +----------------------- + +Writing tables-only datastreams via jpeg_write_tables works again. + +Support 32-bit BMPs (RGB image with Alpha channel) for read in cjpeg. +Thank to Brett Blackham for the suggestion. + +Improve accuracy in floating point IDCT calculation. +Thank to Robert Hooke for the hint. + + +Version 8 10-Jan-2010 +---------------------- + +jpegtran now supports the same -scale option as djpeg for "lossless" resize. +An implementation of the JPEG SmartScale extension is required for this +feature. A (draft) specification of the JPEG SmartScale extension is +available as a contributed document at ITU and ISO. Revision 2 or later +of the document is required (latest document version is Revision 3). +The SmartScale extension will enable more features beside lossless resize +in future implementations, as described in the document (new compression +options). + +Add sanity check in BMP reader module to avoid cjpeg crash for empty input +image (thank to Isaev Ildar of ISP RAS, Moscow, RU for reporting this error). + +Add data source and destination managers for read from and write to +memory buffers. New API functions jpeg_mem_src and jpeg_mem_dest. +Thank to Roberto Boni from Italy for the suggestion. + + +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/plugins/FreeImage/src/LibJPEG/cjpeg.c b/plugins/FreeImage/src/LibJPEG/cjpeg.c new file mode 100644 index 0000000000..a999eeef1c --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/cjpeg.c @@ -0,0 +1,643 @@ +/* + * cjpeg.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2011 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 /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* 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"); + fprintf(stderr, " -rgb Create RGB 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 C_ARITH_CODING_SUPPORTED + fprintf(stderr, " -arithmetic Use arithmetic coding\n"); +#endif +#ifdef DCT_SCALING_SUPPORTED + fprintf(stderr, " -block N DCT block size (1..16; default is 8)\n"); +#endif +#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"); + 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", 2)) { + /* Force baseline-compatible output (8-bit quantizer values). */ + force_baseline = TRUE; + + } else if (keymatch(arg, "block", 2)) { + /* Set DCT block size. */ +#if defined DCT_SCALING_SUPPORTED && JPEG_LIB_VERSION_MAJOR >= 8 && \ + (JPEG_LIB_VERSION_MAJOR > 8 || JPEG_LIB_VERSION_MINOR >= 3) + int val; + + if (++argn >= argc) /* advance to next argument */ + usage(); + if (sscanf(argv[argn], "%d", &val) != 1) + usage(); + if (val < 1 || val > 16) + usage(); + cinfo->block_size = val; +#else + fprintf(stderr, "%s: sorry, block size setting not supported\n", + progname); + exit(EXIT_FAILURE); +#endif + + } 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, "rgb", 3)) { + /* Force an RGB JPEG file to be generated. */ + jpeg_set_colorspace(cinfo, JCS_RGB); + + } 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/plugins/FreeImage/src/LibJPEG/ckconfig.c b/plugins/FreeImage/src/LibJPEG/ckconfig.c new file mode 100644 index 0000000000..fb9429af08 --- /dev/null +++ b/plugins/FreeImage/src/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 +#endif + +#define HAVE_STDLIB_H /* same thing for stdlib.h */ +#ifdef HAVE_STDLIB_H +#include +#endif + +#include /* 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 +#else +#include +#endif + +/* On some systems (especially older Unix machines), type size_t is + * defined only in the include file . 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 +#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 " 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 " with + * "typedef unsigned int size_t;". + */ + +#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */ + +#ifdef NEED_SPECIAL_INCLUDE +#include +#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/plugins/FreeImage/src/LibJPEG/djpeg.c b/plugins/FreeImage/src/LibJPEG/djpeg.c new file mode 100644 index 0000000000..363c628cbe --- /dev/null +++ b/plugins/FreeImage/src/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 /* to declare isprint() */ + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* 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/plugins/FreeImage/src/LibJPEG/example.c b/plugins/FreeImage/src/LibJPEG/example.c new file mode 100644 index 0000000000..e21cf12126 --- /dev/null +++ b/plugins/FreeImage/src/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 + +/* + * 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" + +/* + * is used for the optional error recovery mechanism shown in + * the second part of the example. + */ + +#include + + + +/******************** 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/plugins/FreeImage/src/LibJPEG/jaricom.c b/plugins/FreeImage/src/LibJPEG/jaricom.c new file mode 100644 index 0000000000..690068861f --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jaricom.c @@ -0,0 +1,153 @@ +/* + * jaricom.c + * + * Developed 1997-2011 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.3 in the JPEG spec (D.2 in the draft), + * 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(i,a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b) + +const INT32 jpeg_aritab[113+1] = { +/* + * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS + */ + V( 0, 0x5a1d, 1, 1, 1 ), + V( 1, 0x2586, 14, 2, 0 ), + V( 2, 0x1114, 16, 3, 0 ), + V( 3, 0x080b, 18, 4, 0 ), + V( 4, 0x03d8, 20, 5, 0 ), + V( 5, 0x01da, 23, 6, 0 ), + V( 6, 0x00e5, 25, 7, 0 ), + V( 7, 0x006f, 28, 8, 0 ), + V( 8, 0x0036, 30, 9, 0 ), + V( 9, 0x001a, 33, 10, 0 ), + V( 10, 0x000d, 35, 11, 0 ), + V( 11, 0x0006, 9, 12, 0 ), + V( 12, 0x0003, 10, 13, 0 ), + V( 13, 0x0001, 12, 13, 0 ), + V( 14, 0x5a7f, 15, 15, 1 ), + V( 15, 0x3f25, 36, 16, 0 ), + V( 16, 0x2cf2, 38, 17, 0 ), + V( 17, 0x207c, 39, 18, 0 ), + V( 18, 0x17b9, 40, 19, 0 ), + V( 19, 0x1182, 42, 20, 0 ), + V( 20, 0x0cef, 43, 21, 0 ), + V( 21, 0x09a1, 45, 22, 0 ), + V( 22, 0x072f, 46, 23, 0 ), + V( 23, 0x055c, 48, 24, 0 ), + V( 24, 0x0406, 49, 25, 0 ), + V( 25, 0x0303, 51, 26, 0 ), + V( 26, 0x0240, 52, 27, 0 ), + V( 27, 0x01b1, 54, 28, 0 ), + V( 28, 0x0144, 56, 29, 0 ), + V( 29, 0x00f5, 57, 30, 0 ), + V( 30, 0x00b7, 59, 31, 0 ), + V( 31, 0x008a, 60, 32, 0 ), + V( 32, 0x0068, 62, 33, 0 ), + V( 33, 0x004e, 63, 34, 0 ), + V( 34, 0x003b, 32, 35, 0 ), + V( 35, 0x002c, 33, 9, 0 ), + V( 36, 0x5ae1, 37, 37, 1 ), + V( 37, 0x484c, 64, 38, 0 ), + V( 38, 0x3a0d, 65, 39, 0 ), + V( 39, 0x2ef1, 67, 40, 0 ), + V( 40, 0x261f, 68, 41, 0 ), + V( 41, 0x1f33, 69, 42, 0 ), + V( 42, 0x19a8, 70, 43, 0 ), + V( 43, 0x1518, 72, 44, 0 ), + V( 44, 0x1177, 73, 45, 0 ), + V( 45, 0x0e74, 74, 46, 0 ), + V( 46, 0x0bfb, 75, 47, 0 ), + V( 47, 0x09f8, 77, 48, 0 ), + V( 48, 0x0861, 78, 49, 0 ), + V( 49, 0x0706, 79, 50, 0 ), + V( 50, 0x05cd, 48, 51, 0 ), + V( 51, 0x04de, 50, 52, 0 ), + V( 52, 0x040f, 50, 53, 0 ), + V( 53, 0x0363, 51, 54, 0 ), + V( 54, 0x02d4, 52, 55, 0 ), + V( 55, 0x025c, 53, 56, 0 ), + V( 56, 0x01f8, 54, 57, 0 ), + V( 57, 0x01a4, 55, 58, 0 ), + V( 58, 0x0160, 56, 59, 0 ), + V( 59, 0x0125, 57, 60, 0 ), + V( 60, 0x00f6, 58, 61, 0 ), + V( 61, 0x00cb, 59, 62, 0 ), + V( 62, 0x00ab, 61, 63, 0 ), + V( 63, 0x008f, 61, 32, 0 ), + V( 64, 0x5b12, 65, 65, 1 ), + V( 65, 0x4d04, 80, 66, 0 ), + V( 66, 0x412c, 81, 67, 0 ), + V( 67, 0x37d8, 82, 68, 0 ), + V( 68, 0x2fe8, 83, 69, 0 ), + V( 69, 0x293c, 84, 70, 0 ), + V( 70, 0x2379, 86, 71, 0 ), + V( 71, 0x1edf, 87, 72, 0 ), + V( 72, 0x1aa9, 87, 73, 0 ), + V( 73, 0x174e, 72, 74, 0 ), + V( 74, 0x1424, 72, 75, 0 ), + V( 75, 0x119c, 74, 76, 0 ), + V( 76, 0x0f6b, 74, 77, 0 ), + V( 77, 0x0d51, 75, 78, 0 ), + V( 78, 0x0bb6, 77, 79, 0 ), + V( 79, 0x0a40, 77, 48, 0 ), + V( 80, 0x5832, 80, 81, 1 ), + V( 81, 0x4d1c, 88, 82, 0 ), + V( 82, 0x438e, 89, 83, 0 ), + V( 83, 0x3bdd, 90, 84, 0 ), + V( 84, 0x34ee, 91, 85, 0 ), + V( 85, 0x2eae, 92, 86, 0 ), + V( 86, 0x299a, 93, 87, 0 ), + V( 87, 0x2516, 86, 71, 0 ), + V( 88, 0x5570, 88, 89, 1 ), + V( 89, 0x4ca9, 95, 90, 0 ), + V( 90, 0x44d9, 96, 91, 0 ), + V( 91, 0x3e22, 97, 92, 0 ), + V( 92, 0x3824, 99, 93, 0 ), + V( 93, 0x32b4, 99, 94, 0 ), + V( 94, 0x2e17, 93, 86, 0 ), + V( 95, 0x56a8, 95, 96, 1 ), + V( 96, 0x4f46, 101, 97, 0 ), + V( 97, 0x47e5, 102, 98, 0 ), + V( 98, 0x41cf, 103, 99, 0 ), + V( 99, 0x3c3d, 104, 100, 0 ), + V( 100, 0x375e, 99, 93, 0 ), + V( 101, 0x5231, 105, 102, 0 ), + V( 102, 0x4c0f, 106, 103, 0 ), + V( 103, 0x4639, 107, 104, 0 ), + V( 104, 0x415e, 103, 99, 0 ), + V( 105, 0x5627, 105, 106, 1 ), + V( 106, 0x50e7, 108, 107, 0 ), + V( 107, 0x4b85, 109, 103, 0 ), + V( 108, 0x5597, 110, 109, 0 ), + V( 109, 0x504f, 111, 107, 0 ), + V( 110, 0x5a10, 110, 111, 1 ), + V( 111, 0x5522, 112, 109, 0 ), + V( 112, 0x59eb, 112, 111, 1 ), +/* + * This last entry is used for fixed probability estimate of 0.5 + * as suggested in Section 10.3 Table 5 of ITU-T Rec. T.851. + */ + V( 113, 0x5a1d, 113, 113, 0 ) +}; diff --git a/plugins/FreeImage/src/LibJPEG/jcapimin.c b/plugins/FreeImage/src/LibJPEG/jcapimin.c new file mode 100644 index 0000000000..639ce86f44 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jcapimin.c @@ -0,0 +1,288 @@ +/* + * jcapimin.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2003-2010 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 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; + } + + /* Must do it here for emit_dqt in case jpeg_write_tables is used */ + cinfo->block_size = DCTSIZE; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + + 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/plugins/FreeImage/src/LibJPEG/jcapistd.c b/plugins/FreeImage/src/LibJPEG/jcapistd.c new file mode 100644 index 0000000000..c0320b1b19 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jcarith.c b/plugins/FreeImage/src/LibJPEG/jcarith.c new file mode 100644 index 0000000000..033f67069e --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jcarith.c @@ -0,0 +1,937 @@ +/* + * jcarith.c + * + * Developed 1997-2011 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]; + + /* Statistics bin for coding with fixed probability 0.5 */ + unsigned char fixed_bin[4]; +} 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. + * + * 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) +{ + 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.3(D.2): + * Qe values and probability estimation state machine + */ + sv = *st; + qe = jpeg_aritab[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); + + /* Re-initialize statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (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; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + 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) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << 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; + const int * natural_order; + + /* 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--; + } + + natural_order = cinfo->natural_order; + + /* 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; ke > 0; 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)[natural_order[ke]]) >= 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 */ + for (;;) { + if ((v = (*block)[natural_order[k]]) >= 0) { + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 0); + break; + } + } else { + v = -v; + if (v >>= cinfo->Al) { + arith_encode(cinfo, st + 1, 1); + arith_encode(cinfo, entropy->fixed_bin, 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; + 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--; + } + + st = entropy->fixed_bin; /* use fixed probability estimation */ + Al = cinfo->Al; + + /* Encode the MCU data blocks */ + for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { + /* 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; + const int * natural_order; + + /* 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--; + } + + natural_order = cinfo->natural_order; + + /* 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; ke > 0; 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)[natural_order[ke]]) >= 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 > 0; kex--) + if ((v = (*block)[natural_order[kex]]) >= 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 */ + for (;;) { + if ((v = (*block)[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->fixed_bin, 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->fixed_bin, 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; + const int * natural_order; + + /* 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--; + } + + natural_order = cinfo->natural_order; + + /* 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) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << 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 */ + + if ((ke = cinfo->lim_Se) == 0) continue; + tbl = compptr->ac_tbl_no; + + /* Establish EOB (end-of-block) index */ + do { + if ((*block)[natural_order[ke]]) break; + } while (--ke); + + /* Figure F.5: Encode_AC_Coefficients */ + for (k = 0; k < ke;) { + st = entropy->ac_stats[tbl] + 3 * k; + arith_encode(cinfo, st, 0); /* EOB decision */ + while ((v = (*block)[natural_order[++k]]) == 0) { + arith_encode(cinfo, st + 1, 0); + st += 3; + } + arith_encode(cinfo, st + 1, 1); + /* Figure F.6: Encoding nonzero value v */ + /* Figure F.7: Encoding the sign of v */ + if (v > 0) { + arith_encode(cinfo, entropy->fixed_bin, 0); + } else { + v = -v; + arith_encode(cinfo, entropy->fixed_bin, 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 < cinfo->lim_Se */ + if (k < cinfo->lim_Se) { + st = entropy->ac_stats[tbl] + 3 * k; + 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; + + /* Allocate & initialize requested statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* DC needs no table for refinement scan */ + if (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; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + 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; + } + + /* Initialize index for fixed probability estimation */ + entropy->fixed_bin[0] = 113; +} diff --git a/plugins/FreeImage/src/LibJPEG/jccoefct.c b/plugins/FreeImage/src/LibJPEG/jccoefct.c new file mode 100644 index 0000000000..924a703dda --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jccoefct.c @@ -0,0 +1,454 @@ +/* + * jccoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2003-2011 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 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. */ + FMEMZERO((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. */ + FMEMZERO((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 */ + FMEMZERO((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]; + FMEMZERO((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/plugins/FreeImage/src/LibJPEG/jccolor.c b/plugins/FreeImage/src/LibJPEG/jccolor.c new file mode 100644 index 0000000000..3e2d0e9277 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jccolor.c @@ -0,0 +1,490 @@ +/* + * jccolor.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2011 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 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< 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. + * No colorspace conversion, but change from interleaved + * to separate-planes representation. + */ + +METHODDEF(void) +rgb_convert (j_compress_ptr cinfo, + JSAMPARRAY input_buf, JSAMPIMAGE output_buf, + JDIMENSION output_row, int num_rows) +{ + 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++) { + /* We can dispense with GETJSAMPLE() here */ + outptr0[col] = inptr[RGB_RED]; + outptr1[col] = inptr[RGB_GREEN]; + outptr2[col] = inptr[RGB_BLUE]; + inptr += RGB_PIXELSIZE; + } + } +} + + +/* + * 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 (cinfo->input_components != RGB_PIXELSIZE) + ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); + break; + + 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 || + cinfo->in_color_space == JCS_YCbCr) + 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 + 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) + cconvert->pub.color_convert = rgb_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/plugins/FreeImage/src/LibJPEG/jcdctmgr.c b/plugins/FreeImage/src/LibJPEG/jcdctmgr.c new file mode 100644 index 0000000000..0bbdbb685d --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jchuff.c b/plugins/FreeImage/src/LibJPEG/jchuff.c new file mode 100644 index 0000000000..257d7aa1f5 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jchuff.c @@ -0,0 +1,1576 @@ +/* + * 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) */ + + /* 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... */ +} 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)<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)<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_dc_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->dc_count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->dc_derived_tbls[tbl_no]; + emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); + } +} + + +INLINE +LOCAL(void) +emit_ac_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol) +{ + if (entropy->gather_statistics) + entropy->ac_count_ptrs[tbl_no][symbol]++; + else { + c_derived_tbl * tbl = entropy->ac_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_ac_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_dc_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, Al; + const int * natural_order; + 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); + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* 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)[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_ac_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_ac_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, Al; + const int * natural_order; + 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); + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* 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)[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_ac_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_ac_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); + + /* Emit output bit for newly-nonzero coef */ + temp = ((*block)[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; + int Se = state->cinfo->lim_Se; + const int * natural_order = state->cinfo->natural_order; + + /* 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 <= Se; k++) { + if ((temp = block[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; + int Se = cinfo->lim_Se; + const int * natural_order = cinfo->natural_order; + + /* 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 <= Se; k++) { + if ((temp = block[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, tbl; + jpeg_component_info * compptr; + JHUFF_TBL **htblptr; + boolean did_dc[NUM_HUFF_TBLS]; + boolean did_ac[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_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]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_tbl_no; + if (! did_dc[tbl]) { + htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); + jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[tbl]); + did_dc[tbl] = TRUE; + } + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (! did_ac[tbl]) { + 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->ac_count_ptrs[tbl]); + did_ac[tbl] = 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, 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)); + } + } + + /* Initialize AC stuff */ + entropy->ac_tbl_no = cinfo->cur_comp_info[0]->ac_tbl_no; + 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]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) { + tbl = compptr->dc_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->dc_count_ptrs[tbl] == NULL) + entropy->dc_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->dc_count_ptrs[tbl], 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, tbl, + & entropy->dc_derived_tbls[tbl]); + } + /* Initialize DC predictions to 0 */ + entropy->saved.last_dc_val[ci] = 0; + } + /* AC needs no table when not present */ + if (cinfo->Se) { + tbl = compptr->ac_tbl_no; + if (gather_statistics) { + if (tbl < 0 || tbl >= NUM_HUFF_TBLS) + ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); + if (entropy->ac_count_ptrs[tbl] == NULL) + entropy->ac_count_ptrs[tbl] = (long *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + 257 * SIZEOF(long)); + MEMZERO(entropy->ac_count_ptrs[tbl], 257 * SIZEOF(long)); + } else { + jpeg_make_c_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); + } + } + } + + /* 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; + + /* 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; + } + + if (cinfo->progressive_mode) + entropy->bit_buffer = NULL; /* needed only in AC refinement scan */ +} diff --git a/plugins/FreeImage/src/LibJPEG/jcinit.c b/plugins/FreeImage/src/LibJPEG/jcinit.c new file mode 100644 index 0000000000..0ba310f217 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jcmainct.c b/plugins/FreeImage/src/LibJPEG/jcmainct.c new file mode 100644 index 0000000000..7de75d1675 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jcmarker.c b/plugins/FreeImage/src/LibJPEG/jcmarker.c new file mode 100644 index 0000000000..606c19af39 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jcmarker.c @@ -0,0 +1,682 @@ +/* + * jcmarker.c + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2003-2010 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 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 <= cinfo->lim_Se; i++) { + if (qtbl->quantval[cinfo->natural_order[i]] > 255) + prec = 1; + } + + if (! qtbl->sent_table) { + emit_marker(cinfo, M_DQT); + + emit_2bytes(cinfo, + prec ? cinfo->lim_Se * 2 + 2 + 1 + 2 : cinfo->lim_Se + 1 + 1 + 2); + + emit_byte(cinfo, index + (prec<<4)); + + for (i = 0; i <= cinfo->lim_Se; i++) { + /* The table entries must be emitted in zigzag order. */ + unsigned int qval = qtbl->quantval[cinfo->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 needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) + dc_in_use[compptr->dc_tbl_no] = 1; + /* AC needs no table when not present */ + if (cinfo->Se) + 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]; + + if (length) { + 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); + + /* 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. + */ + + /* DC needs no table for refinement scan */ + td = cinfo->Ss == 0 && cinfo->Ah == 0 ? compptr->dc_tbl_no : 0; + /* AC needs no table when not present */ + ta = cinfo->Se ? compptr->ac_tbl_no : 0; + + 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_pseudo_sos (j_compress_ptr cinfo) +/* Emit a pseudo SOS marker */ +{ + emit_marker(cinfo, M_SOS); + + emit_2bytes(cinfo, 2 + 1 + 3); /* length */ + + emit_byte(cinfo, 0); /* Ns */ + + emit_byte(cinfo, 0); /* Ss */ + emit_byte(cinfo, cinfo->block_size * cinfo->block_size - 1); /* Se */ + emit_byte(cinfo, 0); /* Ah/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, and a conditional pseudo SOS marker. + * 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 || cinfo->block_size != DCTSIZE) { + 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 */ + } + + /* Check to emit pseudo SOS marker */ + if (cinfo->progressive_mode && cinfo->block_size != DCTSIZE) + emit_pseudo_sos(cinfo); +} + + +/* + * 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]; + /* DC needs no table for refinement scan */ + if (cinfo->Ss == 0 && cinfo->Ah == 0) + emit_dht(cinfo, compptr->dc_tbl_no, FALSE); + /* AC needs no table when not present */ + if (cinfo->Se) + 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/plugins/FreeImage/src/LibJPEG/jcmaster.c b/plugins/FreeImage/src/LibJPEG/jcmaster.c new file mode 100644 index 0000000000..caf80a53b3 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jcmaster.c @@ -0,0 +1,858 @@ +/* + * jcmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2003-2011 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 + + /* Sanity check on input image dimensions to prevent overflow in + * following calculation. + * We do check jpeg_width and jpeg_height in initial_setup below, + * but image_width and image_height can come from arbitrary data, + * and we need some space for multiplication by block_size. + */ + if (((long) cinfo->image_width >> 24) || ((long) cinfo->image_height >> 24)) + ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); + + /* Compute actual JPEG image dimensions and DCT scaling choices. */ + if (cinfo->scale_num >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/1 scaling */ + cinfo->jpeg_width = cinfo->image_width * cinfo->block_size; + cinfo->jpeg_height = cinfo->image_height * cinfo->block_size; + cinfo->min_DCT_h_scaled_size = 1; + cinfo->min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num * 2 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/2 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 2L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 2L); + cinfo->min_DCT_h_scaled_size = 2; + cinfo->min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/3 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 3L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 3L); + cinfo->min_DCT_h_scaled_size = 3; + cinfo->min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num * 4 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/4 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 4L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 4L); + cinfo->min_DCT_h_scaled_size = 4; + cinfo->min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * 5 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/5 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 5L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 5L); + cinfo->min_DCT_h_scaled_size = 5; + cinfo->min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * 6 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/6 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 6L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 6L); + cinfo->min_DCT_h_scaled_size = 6; + cinfo->min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * 7 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/7 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 7L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 7L); + cinfo->min_DCT_h_scaled_size = 7; + cinfo->min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num * 8 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/8 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 8L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 8L); + cinfo->min_DCT_h_scaled_size = 8; + cinfo->min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * 9 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/9 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 9L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 9L); + cinfo->min_DCT_h_scaled_size = 9; + cinfo->min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * 10 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/10 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 10L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 10L); + cinfo->min_DCT_h_scaled_size = 10; + cinfo->min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * 11 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/11 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 11L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 11L); + cinfo->min_DCT_h_scaled_size = 11; + cinfo->min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * 12 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/12 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 12L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 12L); + cinfo->min_DCT_h_scaled_size = 12; + cinfo->min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * 13 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/13 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 13L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 13L); + cinfo->min_DCT_h_scaled_size = 13; + cinfo->min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * 14 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/14 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 14L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 14L); + cinfo->min_DCT_h_scaled_size = 14; + cinfo->min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * 15 >= cinfo->scale_denom * cinfo->block_size) { + /* Provide block_size/15 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 15L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 15L); + cinfo->min_DCT_h_scaled_size = 15; + cinfo->min_DCT_v_scaled_size = 15; + } else { + /* Provide block_size/16 scaling */ + cinfo->jpeg_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * cinfo->block_size, 16L); + cinfo->jpeg_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * cinfo->block_size, 16L); + 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) +jpeg_calc_trans_dimensions (j_compress_ptr cinfo) +{ + if (cinfo->min_DCT_h_scaled_size != cinfo->min_DCT_v_scaled_size) + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, + cinfo->min_DCT_h_scaled_size, cinfo->min_DCT_v_scaled_size); + + cinfo->block_size = cinfo->min_DCT_h_scaled_size; +} + + +LOCAL(void) +initial_setup (j_compress_ptr cinfo, boolean transcode_only) +/* Do computations that are needed before master selection phase */ +{ + int ci, ssize; + jpeg_component_info *compptr; + long samplesperrow; + JDIMENSION jd_samplesperrow; + + if (transcode_only) + jpeg_calc_trans_dimensions(cinfo); + else + jpeg_calc_jpeg_dimensions(cinfo); + + /* Sanity check on block_size */ + if (cinfo->block_size < 1 || cinfo->block_size > 16) + ERREXIT2(cinfo, JERR_BAD_DCTSIZE, cinfo->block_size, cinfo->block_size); + + /* Derive natural_order from block_size */ + switch (cinfo->block_size) { + case 2: cinfo->natural_order = jpeg_natural_order2; break; + case 3: cinfo->natural_order = jpeg_natural_order3; break; + case 4: cinfo->natural_order = jpeg_natural_order4; break; + case 5: cinfo->natural_order = jpeg_natural_order5; break; + case 6: cinfo->natural_order = jpeg_natural_order6; break; + case 7: cinfo->natural_order = jpeg_natural_order7; break; + default: cinfo->natural_order = jpeg_natural_order; break; + } + + /* Derive lim_Se from block_size */ + cinfo->lim_Se = cinfo->block_size < DCTSIZE ? + cinfo->block_size * cinfo->block_size - 1 : DCTSIZE2-1; + + /* 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 * cinfo->block_size)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + /* 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 * cinfo->block_size)); + 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 * cinfo->block_size)); + /* 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 * cinfo->block_size)); +} + + +#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); + } + } +} + + +LOCAL(void) +reduce_script (j_compress_ptr cinfo) +/* Adapt scan script for use with reduced block size; + * assume that script has been validated before. + */ +{ + jpeg_scan_info * scanptr; + int idxout, idxin; + + /* Circumvent const declaration for this function */ + scanptr = (jpeg_scan_info *) cinfo->scan_info; + idxout = 0; + + for (idxin = 0; idxin < cinfo->num_scans; idxin++) { + /* After skipping, idxout becomes smaller than idxin */ + if (idxin != idxout) + /* Copy rest of data; + * note we stay in given chunk of allocated memory. + */ + scanptr[idxout] = scanptr[idxin]; + if (scanptr[idxout].Ss > cinfo->lim_Se) + /* Entire scan out of range - skip this entry */ + continue; + if (scanptr[idxout].Se > cinfo->lim_Se) + /* Limit scan to end of block */ + scanptr[idxout].Se = cinfo->lim_Se; + idxout++; + } + + cinfo->num_scans = idxout; +} + +#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]]; + } + if (cinfo->progressive_mode) { + cinfo->Ss = scanptr->Ss; + cinfo->Se = scanptr->Se; + cinfo->Ah = scanptr->Ah; + cinfo->Al = scanptr->Al; + return; + } + } + 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 = cinfo->block_size * cinfo->block_size - 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 * cinfo->block_size)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->jpeg_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + + 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, transcode_only); + + if (cinfo->scan_info != NULL) { +#ifdef C_MULTISCAN_FILES_SUPPORTED + validate_script(cinfo); + if (cinfo->block_size < DCTSIZE) + reduce_script(cinfo); +#else + ERREXIT(cinfo, JERR_NOT_COMPILED); +#endif + } else { + cinfo->progressive_mode = FALSE; + cinfo->num_scans = 1; + } + + if ((cinfo->progressive_mode || cinfo->block_size < DCTSIZE) && + !cinfo->arith_code) /* TEMPORARY HACK ??? */ + /* assume default tables no good for progressive or downscale mode */ + cinfo->optimize_coding = TRUE; + + /* 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/plugins/FreeImage/src/LibJPEG/jcomapi.c b/plugins/FreeImage/src/LibJPEG/jcomapi.c new file mode 100644 index 0000000000..9b1fa7568a --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jconfig.h b/plugins/FreeImage/src/LibJPEG/jconfig.h new file mode 100644 index 0000000000..44e5c52ee5 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jconfig.h @@ -0,0 +1,47 @@ +/* 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 */ diff --git a/plugins/FreeImage/src/LibJPEG/jconfig.txt b/plugins/FreeImage/src/LibJPEG/jconfig.txt new file mode 100644 index 0000000000..27086a3644 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jconfig.txt @@ -0,0 +1,164 @@ +/* + * 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 file. + */ +#define HAVE_STDDEF_H + +/* Define this if your system has an ANSI-conforming file. + */ +#define HAVE_STDLIB_H + +/* Define this if your system does not have an ANSI/SysV , + * but does have a BSD-style . + */ +#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 + * 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 + +/* Define "boolean" as unsigned char, not int, on Windows systems. + */ +#ifdef _WIN32 +#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 + + +/* + * 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/plugins/FreeImage/src/LibJPEG/jcparam.c b/plugins/FreeImage/src/LibJPEG/jcparam.c new file mode 100644 index 0000000000..1c81d2ec59 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jcprepct.c b/plugins/FreeImage/src/LibJPEG/jcprepct.c new file mode 100644 index 0000000000..be44cc4b45 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jcsample.c b/plugins/FreeImage/src/LibJPEG/jcsample.c new file mode 100644 index 0000000000..4d36f85f35 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jctrans.c b/plugins/FreeImage/src/LibJPEG/jctrans.c new file mode 100644 index 0000000000..f7d7b81491 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jctrans.c @@ -0,0 +1,382 @@ +/* + * jctrans.c + * + * Copyright (C) 1995-1998, Thomas G. Lane. + * Modified 2000-2011 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 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; + dstinfo->jpeg_width = srcinfo->output_width; + dstinfo->jpeg_height = srcinfo->output_height; + dstinfo->min_DCT_h_scaled_size = srcinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_v_scaled_size = srcinfo->min_DCT_v_scaled_size; + /* 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) +{ + /* 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)); + FMEMZERO((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/plugins/FreeImage/src/LibJPEG/jdapimin.c b/plugins/FreeImage/src/LibJPEG/jdapimin.c new file mode 100644 index 0000000000..7f1ce4c05b --- /dev/null +++ b/plugins/FreeImage/src/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 = cinfo->block_size; /* 1:1 scaling */ + cinfo->scale_denom = cinfo->block_size; + 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/plugins/FreeImage/src/LibJPEG/jdapistd.c b/plugins/FreeImage/src/LibJPEG/jdapistd.c new file mode 100644 index 0000000000..9d74537772 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jdarith.c b/plugins/FreeImage/src/LibJPEG/jdarith.c new file mode 100644 index 0000000000..092f8af5fe --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdarith.c @@ -0,0 +1,776 @@ +/* + * jdarith.c + * + * Developed 1997-2011 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]; + + /* Statistics bin for coding with fixed probability 0.5 */ + unsigned char fixed_bin[4]; +} 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. + * + * 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) +{ + 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.3(D.2): + * Qe values and probability estimation state machine + */ + sv = *st; + qe = jpeg_aritab[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); + + /* Re-initialize statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (! cinfo->progressive_mode || (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 && cinfo->lim_Se) || + (cinfo->progressive_mode && 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) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << 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; + const int * natural_order; + + /* 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 */ + + natural_order = cinfo->natural_order; + + /* 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 */ + sign = arith_decode(cinfo, entropy->fixed_bin); + 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)[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; + 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--; + } + + st = entropy->fixed_bin; /* use fixed probability estimation */ + 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++) { + /* 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; + const int * natural_order; + + /* 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 */ + + natural_order = cinfo->natural_order; + + /* 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; kex > 0; kex--) + if ((*block)[natural_order[kex]]) 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 + 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 */ + if (arith_decode(cinfo, entropy->fixed_bin)) + *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; + const int * natural_order; + + /* 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 */ + + natural_order = cinfo->natural_order; + + /* 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) ((1L << cinfo->arith_dc_L[tbl]) >> 1)) + entropy->dc_context[ci] = 0; /* zero diff category */ + else if (m > (int) ((1L << 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 */ + + if (cinfo->lim_Se == 0) continue; + tbl = compptr->ac_tbl_no; + k = 0; + + /* Figure F.20: Decode_AC_coefficients */ + do { + st = entropy->ac_stats[tbl] + 3 * k; + if (arith_decode(cinfo, st)) break; /* EOB flag */ + for (;;) { + k++; + if (arith_decode(cinfo, st + 1)) break; + st += 3; + if (k >= cinfo->lim_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 */ + sign = arith_decode(cinfo, entropy->fixed_bin); + 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)[natural_order[k]] = (JCOEF) v; + } while (k < cinfo->lim_Se); + } + + 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 > cinfo->lim_Se) + 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. + */ + if (cinfo->Ss != 0 || cinfo->Ah != 0 || cinfo->Al != 0 || + (cinfo->Se < DCTSIZE2 && cinfo->Se != cinfo->lim_Se)) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + /* Select MCU decoding routine */ + entropy->pub.decode_mcu = decode_mcu; + } + + /* Allocate & initialize requested statistics areas */ + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + if (! cinfo->progressive_mode || (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 && cinfo->lim_Se) || + (cinfo->progressive_mode && 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; + } + + /* Initialize index for fixed probability estimation */ + entropy->fixed_bin[0] = 113; + + 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/plugins/FreeImage/src/LibJPEG/jdatadst.c b/plugins/FreeImage/src/LibJPEG/jdatadst.c new file mode 100644 index 0000000000..6981fb73de --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdatadst.c @@ -0,0 +1,267 @@ +/* + * jdatadst.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2012 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 compression data destination routines for the case of + * emitting JPEG data to memory or 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" + +#ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ +extern void * malloc JPP((size_t size)); +extern void free JPP((void *ptr)); +#endif + + +/* 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 */ + + +/* Expanded data destination object for memory output */ + +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + + unsigned char ** outbuffer; /* target buffer */ + unsigned long * outsize; + unsigned char * newbuffer; /* newly allocated buffer */ + JOCTET * buffer; /* start of buffer */ + size_t bufsize; +} my_mem_destination_mgr; + +typedef my_mem_destination_mgr * my_mem_dest_ptr; + + +/* + * 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; +} + +METHODDEF(void) +init_mem_destination (j_compress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * 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; +} + +METHODDEF(boolean) +empty_mem_output_buffer (j_compress_ptr cinfo) +{ + size_t nextsize; + JOCTET * nextbuffer; + my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; + + /* Try to allocate new buffer with double size */ + nextsize = dest->bufsize * 2; + nextbuffer = (JOCTET *) malloc(nextsize); + + if (nextbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + + MEMCOPY(nextbuffer, dest->buffer, dest->bufsize); + + if (dest->newbuffer != NULL) + free(dest->newbuffer); + + dest->newbuffer = nextbuffer; + + dest->pub.next_output_byte = nextbuffer + dest->bufsize; + dest->pub.free_in_buffer = dest->bufsize; + + dest->buffer = nextbuffer; + dest->bufsize = nextsize; + + 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); +} + +METHODDEF(void) +term_mem_destination (j_compress_ptr cinfo) +{ + my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; + + *dest->outbuffer = dest->buffer; + *dest->outsize = dest->bufsize - dest->pub.free_in_buffer; +} + + +/* + * 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; +} + + +/* + * Prepare for output to a memory buffer. + * The caller may supply an own initial buffer with appropriate size. + * Otherwise, or when the actual data output exceeds the given size, + * the library adapts the buffer size as necessary. + * The standard library functions malloc/free are used for allocating + * larger memory, so the buffer is available to the application after + * finishing compression, and then the application is responsible for + * freeing the requested memory. + */ + +GLOBAL(void) +jpeg_mem_dest (j_compress_ptr cinfo, + unsigned char ** outbuffer, unsigned long * outsize) +{ + my_mem_dest_ptr dest; + + if (outbuffer == NULL || outsize == NULL) /* sanity check */ + ERREXIT(cinfo, JERR_BUFFER_SIZE); + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same buffer without re-executing jpeg_mem_dest. + */ + 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_mem_destination_mgr)); + } + + dest = (my_mem_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_mem_destination; + dest->pub.empty_output_buffer = empty_mem_output_buffer; + dest->pub.term_destination = term_mem_destination; + dest->outbuffer = outbuffer; + dest->outsize = outsize; + dest->newbuffer = NULL; + + if (*outbuffer == NULL || *outsize == 0) { + /* Allocate initial buffer */ + dest->newbuffer = *outbuffer = (unsigned char *) malloc(OUTPUT_BUF_SIZE); + if (dest->newbuffer == NULL) + ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); + *outsize = OUTPUT_BUF_SIZE; + } + + dest->pub.next_output_byte = dest->buffer = *outbuffer; + dest->pub.free_in_buffer = dest->bufsize = *outsize; +} diff --git a/plugins/FreeImage/src/LibJPEG/jdatasrc.c b/plugins/FreeImage/src/LibJPEG/jdatasrc.c new file mode 100644 index 0000000000..7be59a88a1 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdatasrc.c @@ -0,0 +1,275 @@ +/* + * jdatasrc.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2011 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 decompression data source routines for the case of + * reading JPEG data from memory or 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; +} + +METHODDEF(void) +init_mem_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * 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; +} + +METHODDEF(boolean) +fill_mem_input_buffer (j_decompress_ptr cinfo) +{ + static const JOCTET mybuffer[4] = { + (JOCTET) 0xFF, (JOCTET) JPEG_EOI, 0, 0 + }; + + /* The whole JPEG data is expected to reside in the supplied memory + * buffer, so any request for more data beyond the given buffer size + * is treated as an error. + */ + WARNMS(cinfo, JWRN_JPEG_EOF); + + /* Insert a fake EOI marker */ + + cinfo->src->next_input_byte = mybuffer; + cinfo->src->bytes_in_buffer = 2; + + 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) +{ + struct jpeg_source_mgr * src = 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->bytes_in_buffer) { + num_bytes -= (long) src->bytes_in_buffer; + (void) (*src->fill_input_buffer) (cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->next_input_byte += (size_t) num_bytes; + src->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 */ +} + + +/* + * Prepare for input from a supplied memory buffer. + * The buffer must contain the whole JPEG data. + */ + +GLOBAL(void) +jpeg_mem_src (j_decompress_ptr cinfo, + unsigned char * inbuffer, unsigned long insize) +{ + struct jpeg_source_mgr * src; + + if (inbuffer == NULL || insize == 0) /* Treat empty input as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + + /* The source object is made permanent so that a series of JPEG images + * can be read from the same buffer by calling jpeg_mem_src only before + * the first one. + */ + 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(struct jpeg_source_mgr)); + } + + src = cinfo->src; + src->init_source = init_mem_source; + src->fill_input_buffer = fill_mem_input_buffer; + src->skip_input_data = skip_input_data; + src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->term_source = term_source; + src->bytes_in_buffer = (size_t) insize; + src->next_input_byte = (JOCTET *) inbuffer; +} diff --git a/plugins/FreeImage/src/LibJPEG/jdcoefct.c b/plugins/FreeImage/src/LibJPEG/jdcoefct.c new file mode 100644 index 0000000000..ed02fc378f --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdcoefct.c @@ -0,0 +1,741 @@ +/* + * jdcoefct.c + * + * Copyright (C) 1994-1997, Thomas G. Lane. + * Modified 2002-2011 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 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. */ + if (cinfo->lim_Se) /* can bypass in DC only case */ + FMEMZERO((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< 0 && pred >= (1<= 0) { + pred = (int) (((Q10<<7) + num) / (Q10<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q20<<7) + num) / (Q20<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q11<<7) + num) / (Q11<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<= 0) { + pred = (int) (((Q02<<7) + num) / (Q02<<8)); + if (Al > 0 && pred >= (1< 0 && pred >= (1<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; + } + if (cinfo->lim_Se == 0) /* DC only case: want to bypass later */ + FMEMZERO((void FAR *) buffer, + (size_t) (D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK))); + 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/plugins/FreeImage/src/LibJPEG/jdcolor.c b/plugins/FreeImage/src/LibJPEG/jdcolor.c new file mode 100644 index 0000000000..83e4d069ab --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdcolor.c @@ -0,0 +1,512 @@ +/* + * jdcolor.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2011 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 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 */ + + /* Private state for RGB->Y conversion */ + INT32 * rgb_y_tab; /* => table for RGB to Y conversion */ +} my_color_deconverter; + +typedef my_color_deconverter * my_cconvert_ptr; + + +/**************** YCbCr -> RGB conversion: most common case **************/ +/**************** RGB -> Y conversion: less 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 + * + * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B + * + * 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<Y conversion and divide it up into + * three parts, instead of doing three 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 three 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 TABLE_SIZE (3*(MAXJSAMPLE+1)) + + +/* + * 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 **************/ + + +/* + * Initialize for RGB->grayscale colorspace conversion. + */ + +LOCAL(void) +build_rgb_y_table (j_decompress_ptr cinfo) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + INT32 * rgb_y_tab; + INT32 i; + + /* Allocate and fill in the conversion tables. */ + cconvert->rgb_y_tab = rgb_y_tab = (INT32 *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, + (TABLE_SIZE * SIZEOF(INT32))); + + for (i = 0; i <= MAXJSAMPLE; i++) { + rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i; + rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i; + rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; + } +} + + +/* + * Convert RGB to grayscale. + */ + +METHODDEF(void) +rgb_gray_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 r, g, b; + register INT32 * ctab = cconvert->rgb_y_tab; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + 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++) { + r = GETJSAMPLE(inptr0[col]); + g = GETJSAMPLE(inptr1[col]); + b = GETJSAMPLE(inptr2[col]); + /* Y */ + outptr[col] = (JSAMPLE) + ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) + >> SCALEBITS); + } + } +} + + +/* + * No colorspace change, but conversion from separate-planes + * to interleaved representation. + */ + +METHODDEF(void) +rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + + 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++) { + /* We can dispense with GETJSAMPLE() here */ + outptr[RGB_RED] = inptr0[col]; + outptr[RGB_GREEN] = inptr1[col]; + outptr[RGB_BLUE] = inptr2[col]; + outptr += RGB_PIXELSIZE; + } + } +} + + +/* + * 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 if (cinfo->jpeg_color_space == JCS_RGB) { + cconvert->pub.color_convert = rgb_gray_convert; + build_rgb_y_table(cinfo); + } 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) { + cconvert->pub.color_convert = rgb_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/plugins/FreeImage/src/LibJPEG/jdct.h b/plugins/FreeImage/src/LibJPEG/jdct.h new file mode 100644 index 0000000000..360dec80c9 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jddctmgr.c b/plugins/FreeImage/src/LibJPEG/jddctmgr.c new file mode 100644 index 0000000000..0ded9d5741 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jddctmgr.c @@ -0,0 +1,384 @@ +/* + * jddctmgr.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2002-2010 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 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 + * We apply a further scale factor of 1/8. + */ + 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] * 0.125); + 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/plugins/FreeImage/src/LibJPEG/jdhuff.c b/plugins/FreeImage/src/LibJPEG/jdhuff.c new file mode 100644 index 0000000000..06f92fe47f --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdhuff.c @@ -0,0 +1,1541 @@ +/* + * 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< 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. */ + boolean insufficient_data; /* set TRUE after emitting warning */ + 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 } +}; + +static const int jpeg_zigzag_order7[7][7] = { + { 0, 1, 5, 6, 14, 15, 27 }, + { 2, 4, 7, 13, 16, 26, 28 }, + { 3, 8, 12, 17, 25, 29, 38 }, + { 9, 11, 18, 24, 30, 37, 39 }, + { 10, 19, 23, 31, 36, 40, 45 }, + { 20, 22, 32, 35, 41, 44, 46 }, + { 21, 33, 34, 42, 43, 47, 48 } +}; + +static const int jpeg_zigzag_order6[6][6] = { + { 0, 1, 5, 6, 14, 15 }, + { 2, 4, 7, 13, 16, 25 }, + { 3, 8, 12, 17, 24, 26 }, + { 9, 11, 18, 23, 27, 32 }, + { 10, 19, 22, 28, 31, 33 }, + { 20, 21, 29, 30, 34, 35 } +}; + +static const int jpeg_zigzag_order5[5][5] = { + { 0, 1, 5, 6, 14 }, + { 2, 4, 7, 13, 15 }, + { 3, 8, 12, 16, 21 }, + { 9, 11, 17, 20, 22 }, + { 10, 18, 19, 23, 24 } +}; + +static const int jpeg_zigzag_order4[4][4] = { + { 0, 1, 5, 6 }, + { 2, 4, 7, 12 }, + { 3, 8, 11, 13 }, + { 9, 10, 14, 15 } +}; + +static const int jpeg_zigzag_order3[3][3] = { + { 0, 1, 5 }, + { 2, 4, 6 }, + { 3, 7, 8 } +}; + +static const int jpeg_zigzag_order2[2][2] = { + { 0, 1 }, + { 2, 3 } +}; + + +/* + * 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 (! ((huff_entropy_ptr) cinfo->entropy)->insufficient_data) { + WARNMS(cinfo, JWRN_HIT_MARKER); + ((huff_entropy_ptr) 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->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->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; + register int s, k, r; + unsigned int EOBRUN; + int Se, Al; + const int * natural_order; + 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->insufficient_data) { + + Se = cinfo->Se; + Al = cinfo->Al; + natural_order = cinfo->natural_order; + + /* 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)[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; + register int s, k, r; + unsigned int EOBRUN; + int Se, p1, m1; + const int * natural_order; + 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->insufficient_data) { + + Se = cinfo->Se; + p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */ + m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */ + natural_order = cinfo->natural_order; + + /* 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 + 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 = 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 + 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, + * partial blocks. + */ + +METHODDEF(boolean) +decode_mcu_sub (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) +{ + huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; + const int * natural_order; + int Se, 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->insufficient_data) { + + natural_order = cinfo->natural_order; + Se = cinfo->lim_Se; + + /* 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 natural_order[] will save us + * if k > Se, which could happen if the data is corrupted. + */ + (*block)[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 <= Se; 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; +} + + +/* + * Decode one MCU's worth of Huffman-compressed coefficients, + * full-size blocks. + */ + +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->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, tbl, 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 > cinfo->lim_Se) + 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 */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->derived_tbls[tbl]); + } + } else { + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->derived_tbls[tbl]); + /* remember the single active table */ + entropy->ac_derived_tbl = entropy->derived_tbls[tbl]; + } + /* 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->Ah != 0 || cinfo->Al != 0 || + ((cinfo->is_baseline || cinfo->Se < DCTSIZE2) && + cinfo->Se != cinfo->lim_Se)) + WARNMS(cinfo, JWRN_NOT_SEQUENTIAL); + + /* Select MCU decoding routine */ + /* We retain the hard-coded case for full-size blocks. + * This is not necessary, but it appears that this version is slightly + * more performant in the given implementation. + * With an improved implementation we would prefer a single optimized + * function. + */ + if (cinfo->lim_Se != DCTSIZE2-1) + entropy->pub.decode_mcu = decode_mcu_sub; + else + entropy->pub.decode_mcu = decode_mcu; + + for (ci = 0; ci < cinfo->comps_in_scan; ci++) { + compptr = cinfo->cur_comp_info[ci]; + /* Compute derived values for Huffman tables */ + /* We may do this more than once for a table, but it's not expensive */ + tbl = compptr->dc_tbl_no; + jpeg_make_d_derived_tbl(cinfo, TRUE, tbl, + & entropy->dc_derived_tbls[tbl]); + if (cinfo->lim_Se) { /* AC needs no table when not present */ + tbl = compptr->ac_tbl_no; + jpeg_make_d_derived_tbl(cinfo, FALSE, tbl, + & entropy->ac_derived_tbls[tbl]); + } + /* 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; + i = compptr->DCT_h_scaled_size; + switch (cinfo->lim_Se) { + case (1*1-1): + entropy->coef_limit[blkn] = 1; + break; + case (2*2-1): + if (ci <= 0 || ci > 2) ci = 2; + if (i <= 0 || i > 2) i = 2; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order2[ci - 1][i - 1]; + break; + case (3*3-1): + if (ci <= 0 || ci > 3) ci = 3; + if (i <= 0 || i > 3) i = 3; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order3[ci - 1][i - 1]; + break; + case (4*4-1): + if (ci <= 0 || ci > 4) ci = 4; + if (i <= 0 || i > 4) i = 4; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order4[ci - 1][i - 1]; + break; + case (5*5-1): + if (ci <= 0 || ci > 5) ci = 5; + if (i <= 0 || i > 5) i = 5; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order5[ci - 1][i - 1]; + break; + case (6*6-1): + if (ci <= 0 || ci > 6) ci = 6; + if (i <= 0 || i > 6) i = 6; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order6[ci - 1][i - 1]; + break; + case (7*7-1): + if (ci <= 0 || ci > 7) ci = 7; + if (i <= 0 || i > 7) i = 7; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order7[ci - 1][i - 1]; + break; + default: + if (ci <= 0 || ci > 8) ci = 8; + if (i <= 0 || i > 8) i = 8; + entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1]; + break; + } + } 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->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/plugins/FreeImage/src/LibJPEG/jdinput.c b/plugins/FreeImage/src/LibJPEG/jdinput.c new file mode 100644 index 0000000000..2c5c717b9c --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdinput.c @@ -0,0 +1,661 @@ +/* + * 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 */ + + int inheaders; /* Nonzero 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. + */ + + +/* + * 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. + */ + +GLOBAL(void) +jpeg_core_output_dimensions (j_decompress_ptr cinfo) +/* Do computations that are needed before master selection phase. + * This function is used for transcoding and full decompression. + */ +{ +#ifdef IDCT_SCALING_SUPPORTED + int ci; + jpeg_component_info *compptr; + + /* Compute actual output image dimensions and DCT scaling choices. */ + if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom) { + /* Provide 1/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 1; + cinfo->min_DCT_v_scaled_size = 1; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 2) { + /* Provide 2/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 2L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 2L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 2; + cinfo->min_DCT_v_scaled_size = 2; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 3) { + /* Provide 3/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 3L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 3L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 3; + cinfo->min_DCT_v_scaled_size = 3; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 4) { + /* Provide 4/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 4L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 4L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 4; + cinfo->min_DCT_v_scaled_size = 4; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 5) { + /* Provide 5/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 5L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 5L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 5; + cinfo->min_DCT_v_scaled_size = 5; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 6) { + /* Provide 6/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 6L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 6L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 6; + cinfo->min_DCT_v_scaled_size = 6; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 7) { + /* Provide 7/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 7L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 7L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 7; + cinfo->min_DCT_v_scaled_size = 7; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 8) { + /* Provide 8/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 8L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 8L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 8; + cinfo->min_DCT_v_scaled_size = 8; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 9) { + /* Provide 9/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 9L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 9L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 9; + cinfo->min_DCT_v_scaled_size = 9; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 10) { + /* Provide 10/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 10L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 10L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 10; + cinfo->min_DCT_v_scaled_size = 10; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 11) { + /* Provide 11/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 11L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 11L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 11; + cinfo->min_DCT_v_scaled_size = 11; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 12) { + /* Provide 12/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 12L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 12L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 12; + cinfo->min_DCT_v_scaled_size = 12; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 13) { + /* Provide 13/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 13L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 13L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 13; + cinfo->min_DCT_v_scaled_size = 13; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 14) { + /* Provide 14/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 14L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 14L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 14; + cinfo->min_DCT_v_scaled_size = 14; + } else if (cinfo->scale_num * cinfo->block_size <= cinfo->scale_denom * 15) { + /* Provide 15/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 15L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 15L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 15; + cinfo->min_DCT_v_scaled_size = 15; + } else { + /* Provide 16/block_size scaling */ + cinfo->output_width = (JDIMENSION) + jdiv_round_up((long) cinfo->image_width * 16L, (long) cinfo->block_size); + cinfo->output_height = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * 16L, (long) cinfo->block_size); + cinfo->min_DCT_h_scaled_size = 16; + cinfo->min_DCT_v_scaled_size = 16; + } + + /* Recompute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size; + compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size; + } + +#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, + * and has computed unscaled downsampled_width and downsampled_height. + */ + +#endif /* IDCT_SCALING_SUPPORTED */ +} + + +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); + } + + /* Derive block_size, natural_order, and lim_Se */ + if (cinfo->is_baseline || (cinfo->progressive_mode && + cinfo->comps_in_scan)) { /* no pseudo SOS marker */ + cinfo->block_size = DCTSIZE; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + } else + switch (cinfo->Se) { + case (1*1-1): + cinfo->block_size = 1; + cinfo->natural_order = jpeg_natural_order; /* not needed */ + cinfo->lim_Se = cinfo->Se; + break; + case (2*2-1): + cinfo->block_size = 2; + cinfo->natural_order = jpeg_natural_order2; + cinfo->lim_Se = cinfo->Se; + break; + case (3*3-1): + cinfo->block_size = 3; + cinfo->natural_order = jpeg_natural_order3; + cinfo->lim_Se = cinfo->Se; + break; + case (4*4-1): + cinfo->block_size = 4; + cinfo->natural_order = jpeg_natural_order4; + cinfo->lim_Se = cinfo->Se; + break; + case (5*5-1): + cinfo->block_size = 5; + cinfo->natural_order = jpeg_natural_order5; + cinfo->lim_Se = cinfo->Se; + break; + case (6*6-1): + cinfo->block_size = 6; + cinfo->natural_order = jpeg_natural_order6; + cinfo->lim_Se = cinfo->Se; + break; + case (7*7-1): + cinfo->block_size = 7; + cinfo->natural_order = jpeg_natural_order7; + cinfo->lim_Se = cinfo->Se; + break; + case (8*8-1): + cinfo->block_size = 8; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (9*9-1): + cinfo->block_size = 9; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (10*10-1): + cinfo->block_size = 10; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (11*11-1): + cinfo->block_size = 11; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (12*12-1): + cinfo->block_size = 12; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (13*13-1): + cinfo->block_size = 13; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (14*14-1): + cinfo->block_size = 14; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (15*15-1): + cinfo->block_size = 15; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + case (16*16-1): + cinfo->block_size = 16; + cinfo->natural_order = jpeg_natural_order; + cinfo->lim_Se = DCTSIZE2-1; + break; + default: + ERREXIT4(cinfo, JERR_BAD_PROGRESSION, + cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al); + break; + } + + /* We initialize DCT_scaled_size and min_DCT_scaled_size to block_size. + * In the full decompressor, + * this will be overridden by jpeg_calc_output_dimensions in jdmaster.c; + * but in the transcoder, + * jpeg_calc_output_dimensions is not used, so we must do it here. + */ + cinfo->min_DCT_h_scaled_size = cinfo->block_size; + cinfo->min_DCT_v_scaled_size = cinfo->block_size; + + /* Compute dimensions of components */ + for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; + ci++, compptr++) { + compptr->DCT_h_scaled_size = cinfo->block_size; + compptr->DCT_v_scaled_size = cinfo->block_size; + /* 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 * cinfo->block_size)); + compptr->height_in_blocks = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + /* 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 * cinfo->block_size)); + + /* 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 * cinfo->block_size)); + cinfo->MCU_rows_in_scan = (JDIMENSION) + jdiv_round_up((long) cinfo->image_height, + (long) (cinfo->max_v_samp_factor * cinfo->block_size)); + + 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. + * + * Note: This function should NOT return a pseudo SOS marker (with zero + * component number) to the caller. A pseudo marker received by + * read_markers is processed and then skipped for other 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; + + for (;;) { /* Loop to pass pseudo SOS marker */ + val = (*cinfo->marker->read_markers) (cinfo); + + switch (val) { + case JPEG_REACHED_SOS: /* Found SOS */ + if (inputctl->inheaders) { /* 1st SOS */ + if (inputctl->inheaders == 1) + initial_setup(cinfo); + if (cinfo->comps_in_scan == 0) { /* pseudo SOS marker */ + inputctl->inheaders = 2; + break; + } + inputctl->inheaders = 0; + /* 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! */ + if (cinfo->comps_in_scan == 0) /* unexpected pseudo SOS marker */ + break; + start_input_pass(cinfo); + } + return val; + 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; + } + return val; + case JPEG_SUSPENDED: + return val; + default: + 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 = 1; + /* 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 = 1; +} diff --git a/plugins/FreeImage/src/LibJPEG/jdmainct.c b/plugins/FreeImage/src/LibJPEG/jdmainct.c new file mode 100644 index 0000000000..02723ca732 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jdmarker.c b/plugins/FreeImage/src/LibJPEG/jdmarker.c new file mode 100644 index 0000000000..f2a9cc4295 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdmarker.c @@ -0,0 +1,1406 @@ +/* + * jdmarker.c + * + * Copyright (C) 1991-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 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_baseline, boolean is_prog, + boolean is_arith) +/* Process a SOFn marker */ +{ + INT32 length; + int c, ci; + jpeg_component_info * compptr; + INPUT_VARS(cinfo); + + cinfo->is_baseline = is_baseline; + 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 > MAX_COMPS_IN_SCAN || + (n == 0 && !cinfo->progressive_mode)) + /* pseudo SOS marker only allowed in progressive mode */ + 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 (non-pseudo) SOS marker */ + if (n) 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, count, i; + int n, prec; + unsigned int tmp; + JQUANT_TBL *quant_ptr; + const int *natural_order; + INPUT_VARS(cinfo); + + INPUT_2BYTES(cinfo, length, return FALSE); + length -= 2; + + while (length > 0) { + length--; + 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]; + + if (prec) { + if (length < DCTSIZE2 * 2) { + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length >> 1; + } else + count = DCTSIZE2; + } else { + if (length < DCTSIZE2) { + /* Initialize full table for safety. */ + for (i = 0; i < DCTSIZE2; i++) { + quant_ptr->quantval[i] = 1; + } + count = length; + } else + count = DCTSIZE2; + } + + switch (count) { + case (2*2): natural_order = jpeg_natural_order2; break; + case (3*3): natural_order = jpeg_natural_order3; break; + case (4*4): natural_order = jpeg_natural_order4; break; + case (5*5): natural_order = jpeg_natural_order5; break; + case (6*6): natural_order = jpeg_natural_order6; break; + case (7*7): natural_order = jpeg_natural_order7; break; + default: natural_order = jpeg_natural_order; break; + } + + for (i = 0; i < count; 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[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 -= count; + if (prec) length -= count; + } + + 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. + * + * Note: This function may return a pseudo SOS marker (with zero + * component number) for treat by input controller's consume_input. + * consume_input itself should filter out (skip) the pseudo marker + * after processing for the caller. + */ + +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 */ + if (! get_sof(cinfo, TRUE, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF1: /* Extended sequential, Huffman */ + if (! get_sof(cinfo, FALSE, FALSE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF2: /* Progressive, Huffman */ + if (! get_sof(cinfo, FALSE, TRUE, FALSE)) + return JPEG_SUSPENDED; + break; + + case M_SOF9: /* Extended sequential, arithmetic */ + if (! get_sof(cinfo, FALSE, FALSE, TRUE)) + return JPEG_SUSPENDED; + break; + + case M_SOF10: /* Progressive, arithmetic */ + if (! get_sof(cinfo, FALSE, 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/plugins/FreeImage/src/LibJPEG/jdmaster.c b/plugins/FreeImage/src/LibJPEG/jdmaster.c new file mode 100644 index 0000000000..fef72a21b4 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdmaster.c @@ -0,0 +1,531 @@ +/* + * jdmaster.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2002-2011 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. + * This function is used for full decompression. + */ +{ +#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); + + /* Compute core output image dimensions and DCT scaling choices. */ + jpeg_core_output_dimensions(cinfo); + +#ifdef IDCT_SCALING_SUPPORTED + + /* 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 * cinfo->block_size)); + 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 * cinfo->block_size)); + } + +#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: + cinfo->out_color_components = RGB_PIXELSIZE; + break; + 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/plugins/FreeImage/src/LibJPEG/jdmerge.c b/plugins/FreeImage/src/LibJPEG/jdmerge.c new file mode 100644 index 0000000000..37444468c2 --- /dev/null +++ b/plugins/FreeImage/src/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<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/plugins/FreeImage/src/LibJPEG/jdpostct.c b/plugins/FreeImage/src/LibJPEG/jdpostct.c new file mode 100644 index 0000000000..571563d728 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jdsample.c b/plugins/FreeImage/src/LibJPEG/jdsample.c new file mode 100644 index 0000000000..7bc8885b02 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jdtrans.c b/plugins/FreeImage/src/LibJPEG/jdtrans.c new file mode 100644 index 0000000000..22dd47fb5c --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jdtrans.c @@ -0,0 +1,140 @@ +/* + * jdtrans.c + * + * Copyright (C) 1995-1997, Thomas G. Lane. + * Modified 2000-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 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; + + /* Compute output image dimensions and related values. */ + jpeg_core_output_dimensions(cinfo); + + /* 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/plugins/FreeImage/src/LibJPEG/jerror.c b/plugins/FreeImage/src/LibJPEG/jerror.c new file mode 100644 index 0000000000..3da7be86a0 --- /dev/null +++ b/plugins/FreeImage/src/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 +#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/plugins/FreeImage/src/LibJPEG/jerror.h b/plugins/FreeImage/src/LibJPEG/jerror.h new file mode 100644 index 0000000000..1cfb2b19d8 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jfdctflt.c b/plugins/FreeImage/src/LibJPEG/jfdctflt.c new file mode 100644 index 0000000000..74d0d862dc --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jfdctfst.c b/plugins/FreeImage/src/LibJPEG/jfdctfst.c new file mode 100644 index 0000000000..8cad5f2293 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jfdctint.c b/plugins/FreeImage/src/LibJPEG/jfdctint.c new file mode 100644 index 0000000000..1dde58c499 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jidctflt.c b/plugins/FreeImage/src/LibJPEG/jidctflt.c new file mode 100644 index 0000000000..23ae9d333b --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jidctflt.c @@ -0,0 +1,235 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * Modified 2010 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 + * 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 = cinfo->sample_range_limit; + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + + /* 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 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ + tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 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*3] = tmp3 + tmp4; + wsptr[DCTSIZE*4] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + + 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 */ + + /* Apply signed->unsigned and prepare float->int conversion */ + z5 = wsptr[0] + ((FAST_FLOAT) CENTERJSAMPLE + (FAST_FLOAT) 0.5); + tmp10 = z5 + wsptr[4]; + tmp11 = z5 - 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 = z5 - z12 * ((FAST_FLOAT) 1.082392200); /* 2*(c2-c6) */ + tmp12 = z5 - z10 * ((FAST_FLOAT) 2.613125930); /* 2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 - tmp5; + + /* Final output stage: float->int conversion and range-limit */ + + outptr[0] = range_limit[((int) (tmp0 + tmp7)) & RANGE_MASK]; + outptr[7] = range_limit[((int) (tmp0 - tmp7)) & RANGE_MASK]; + outptr[1] = range_limit[((int) (tmp1 + tmp6)) & RANGE_MASK]; + outptr[6] = range_limit[((int) (tmp1 - tmp6)) & RANGE_MASK]; + outptr[2] = range_limit[((int) (tmp2 + tmp5)) & RANGE_MASK]; + outptr[5] = range_limit[((int) (tmp2 - tmp5)) & RANGE_MASK]; + outptr[3] = range_limit[((int) (tmp3 + tmp4)) & RANGE_MASK]; + outptr[4] = range_limit[((int) (tmp3 - tmp4)) & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif /* DCT_FLOAT_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibJPEG/jidctfst.c b/plugins/FreeImage/src/LibJPEG/jidctfst.c new file mode 100644 index 0000000000..dba4216fb9 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jidctint.c b/plugins/FreeImage/src/LibJPEG/jidctint.c new file mode 100644 index 0000000000..dcdf7ce454 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jinclude.h b/plugins/FreeImage/src/LibJPEG/jinclude.h new file mode 100644 index 0000000000..0a4f15146a --- /dev/null +++ b/plugins/FreeImage/src/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 . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * 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 . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * 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 +#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 +#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/plugins/FreeImage/src/LibJPEG/jmemansi.c b/plugins/FreeImage/src/LibJPEG/jmemansi.c new file mode 100644 index 0000000000..b5da4743fb --- /dev/null +++ b/plugins/FreeImage/src/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 /* 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/plugins/FreeImage/src/LibJPEG/jmemdos.c b/plugins/FreeImage/src/LibJPEG/jmemdos.c new file mode 100644 index 0000000000..0955047ecc --- /dev/null +++ b/plugins/FreeImage/src/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 /* 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 /* 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 /* 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/plugins/FreeImage/src/LibJPEG/jmemdosa.asm b/plugins/FreeImage/src/LibJPEG/jmemdosa.asm new file mode 100644 index 0000000000..c6ec48b346 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/jmemmac.c b/plugins/FreeImage/src/LibJPEG/jmemmac.c new file mode 100644 index 0000000000..a6f043ed46 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jmemmac.c @@ -0,0 +1,289 @@ +/* + * 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 /* we use the MacOS memory manager */ +#include /* we use the MacOS File stuff */ +#include /* we use the MacOS HFS stuff */ +#include /* for smSystemScript */ +#include /* we use Gestalt to test for specific functionality */ + +#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<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/plugins/FreeImage/src/LibJPEG/jmemmgr.c b/plugins/FreeImage/src/LibJPEG/jmemmgr.c new file mode 100644 index 0000000000..f0e83fb950 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jmemmgr.c @@ -0,0 +1,1119 @@ +/* + * jmemmgr.c + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 2011 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 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 /* 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) { + FMEMZERO((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) { + FMEMZERO((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/plugins/FreeImage/src/LibJPEG/jmemname.c b/plugins/FreeImage/src/LibJPEG/jmemname.c new file mode 100644 index 0000000000..e28b212f48 --- /dev/null +++ b/plugins/FreeImage/src/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 /* 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 , 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 /* 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 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/plugins/FreeImage/src/LibJPEG/jmemnobs.c b/plugins/FreeImage/src/LibJPEG/jmemnobs.c new file mode 100644 index 0000000000..eb8c337725 --- /dev/null +++ b/plugins/FreeImage/src/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 /* 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/plugins/FreeImage/src/LibJPEG/jmemsys.h b/plugins/FreeImage/src/LibJPEG/jmemsys.h new file mode 100644 index 0000000000..6c3c6d348f --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jmemsys.h @@ -0,0 +1,198 @@ +/* + * 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 +#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/plugins/FreeImage/src/LibJPEG/jmorecfg.h b/plugins/FreeImage/src/LibJPEG/jmorecfg.h new file mode 100644 index 0000000000..6c085c36a6 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jmorecfg.h @@ -0,0 +1,369 @@ +/* + * jmorecfg.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2011 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 _BASETSD_H /* MinGW is slightly different */ +#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */ +typedef long INT32; +#endif +#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. 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/plugins/FreeImage/src/LibJPEG/jpegint.h b/plugins/FreeImage/src/LibJPEG/jpegint.h new file mode 100644 index 0000000000..c0d5c14202 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jpegint.h @@ -0,0 +1,426 @@ +/* + * jpegint.h + * + * Copyright (C) 1991-1997, Thomas G. Lane. + * Modified 1997-2011 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)); +}; + +/* 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 jzero_far jZeroFar +#define jcopy_sample_rows jCopySamples +#define jcopy_block_row jCopyBlocks +#define jpeg_zigzag_order jZIGTable +#define jpeg_natural_order jZAGTable +#define jpeg_natural_order7 jZAG7Table +#define jpeg_natural_order6 jZAG6Table +#define jpeg_natural_order5 jZAG5Table +#define jpeg_natural_order4 jZAG4Table +#define jpeg_natural_order3 jZAG3Table +#define jpeg_natural_order2 jZAG2Table +#define jpeg_aritab jAriTab +#endif /* NEED_SHORT_EXTERNAL_NAMES */ + + +/* 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 in jutils.c do it the hard way. + */ + +#ifndef NEED_FAR_POINTERS /* normal case, same as regular macro */ +#define FMEMZERO(target,size) MEMZERO(target,size) +#else /* 80x86 case */ +#ifdef USE_FMEM +#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) +#else +EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero)); +#define FMEMZERO(target,size) jzero_far(target, size) +#endif +#endif + + +/* 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)); +/* 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 */ +extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */ +extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */ +extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */ +extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */ +extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */ +extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */ + +/* Arithmetic coding probability estimation tables in jaricom.c */ +extern const INT32 jpeg_aritab[]; + +/* 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/plugins/FreeImage/src/LibJPEG/jpeglib.h b/plugins/FreeImage/src/LibJPEG/jpeglib.h new file mode 100644 index 0000000000..1327cffa96 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jpeglib.h @@ -0,0 +1,1160 @@ +/* + * jpeglib.h + * + * Copyright (C) 1991-1998, Thomas G. Lane. + * Modified 2002-2011 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 IDs for the JPEG library. + * Might be useful for tests like "#if JPEG_LIB_VERSION >= 80". + */ + +#define JPEG_LIB_VERSION 80 /* Compatibility version 8.0 */ +#define JPEG_LIB_VERSION_MAJOR 8 +#define JPEG_LIB_VERSION_MINOR 4 + + +/* 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 coefficients */ +#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_h_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 */ + + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) */ + + /* + * 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 is_baseline; /* TRUE if Baseline SOF0 encountered */ + 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 */ + + /* These fields are derived from Se of first SOS marker. + */ + int block_size; /* the basic DCT block size: 1..16 */ + const int * natural_order; /* natural-order position array for entropy decode */ + int lim_Se; /* min( Se, DCTSIZE2-1 ) for entropy decode */ + + /* 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_mem_dest jMemDest +#define jpeg_mem_src jMemSrc +#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_core_output_dimensions jCoreDimensions +#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)); + +/* Data source and destination managers: memory buffers. */ +EXTERN(void) jpeg_mem_dest JPP((j_compress_ptr cinfo, + unsigned char ** outbuffer, + unsigned long * outsize)); +EXTERN(void) jpeg_mem_src JPP((j_decompress_ptr cinfo, + unsigned char * inbuffer, + unsigned long insize)); + +/* 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_core_output_dimensions JPP((j_decompress_ptr cinfo)); +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/plugins/FreeImage/src/LibJPEG/jpegtran.c b/plugins/FreeImage/src/LibJPEG/jpegtran.c new file mode 100644 index 0000000000..2193ffe377 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jpegtran.c @@ -0,0 +1,560 @@ +/* + * jpegtran.c + * + * Copyright (C) 1995-2011, 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 a command-line user interface for JPEG transcoding. + * It is very similar to cjpeg.c, and partly to djpeg.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 /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* 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 char * scaleoption; /* -scale 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 + fprintf(stderr, "Switches for modifying the image:\n"); +#if TRANSFORMS_SUPPORTED + 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"); +#endif + fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); +#if TRANSFORMS_SUPPORTED + fprintf(stderr, " -transpose Transpose image\n"); + fprintf(stderr, " -transverse Transverse transpose image\n"); + fprintf(stderr, " -trim Drop non-transformable edge blocks\n"); +#endif + fprintf(stderr, "Switches for advanced users:\n"); +#ifdef C_ARITH_CODING_SUPPORTED + fprintf(stderr, " -arithmetic Use arithmetic coding\n"); +#endif + 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_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; + scaleoption = NULL; + copyoption = JCOPYOPT_DEFAULT; + transformoption.transform = JXFORM_NONE; + transformoption.perfect = FALSE; + transformoption.trim = 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, "scale", 4)) { + /* Scale the output image by a fraction M/N. */ + if (++argn >= argc) /* advance to next argument */ + usage(); + scaleoption = argv[argn]; + /* We must postpone processing until decompression startup. */ + + } 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); + + /* Adjust default decompression parameters */ + if (scaleoption != NULL) + if (sscanf(scaleoption, "%d/%d", + &srcinfo.scale_num, &srcinfo.scale_denom) < 1) + usage(); + + /* 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 + /* Fail right away if -perfect is given and transformation is not perfect. + */ + if (!jtransform_request_workspace(&srcinfo, &transformoption)) { + fprintf(stderr, "%s: transformation is not perfect\n", progname); + exit(EXIT_FAILURE); + } +#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/plugins/FreeImage/src/LibJPEG/jquant1.c b/plugins/FreeImage/src/LibJPEG/jquant1.c new file mode 100644 index 0000000000..9d11f70669 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jquant1.c @@ -0,0 +1,857 @@ +/* + * jquant1.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2011 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 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 */ + FMEMZERO((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 */ + FMEMZERO((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++) + FMEMZERO((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/plugins/FreeImage/src/LibJPEG/jquant2.c b/plugins/FreeImage/src/LibJPEG/jquant2.c new file mode 100644 index 0000000000..38fc2af7a5 --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jquant2.c @@ -0,0 +1,1311 @@ +/* + * jquant2.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2011 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 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<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<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>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<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. */ + FMEMZERO((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++) { + FMEMZERO((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/plugins/FreeImage/src/LibJPEG/jutils.c b/plugins/FreeImage/src/LibJPEG/jutils.c new file mode 100644 index 0000000000..5b16b6d03c --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jutils.c @@ -0,0 +1,227 @@ +/* + * jutils.c + * + * Copyright (C) 1991-1996, Thomas G. Lane. + * Modified 2009-2011 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 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 +}; + +const int jpeg_natural_order7[7*7+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, 14, 21, 28, 35, + 42, 49, 50, 43, 36, 29, 22, 30, + 37, 44, 51, 52, 45, 38, 46, 53, + 54, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order6[6*6+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 41, 34, 27, + 20, 13, 21, 28, 35, 42, 43, 36, + 29, 37, 44, 45, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order5[5*5+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 12, + 19, 26, 33, 34, 27, 20, 28, 35, + 36, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order4[4*4+16] = { + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 25, 18, 11, 19, 26, 27, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order3[3*3+16] = { + 0, 1, 8, 16, 9, 2, 10, 17, + 18, + 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */ + 63, 63, 63, 63, 63, 63, 63, 63 +}; + +const int jpeg_natural_order2[2*2+16] = { + 0, 1, 8, 9, + 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 macro */ +#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,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)) +#else +/* This function is for use by the FMEMZERO macro defined in jpegint.h. + * Do not call this function directly, use the FMEMZERO macro instead. + */ +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. */ +{ + register char FAR * ptr = (char FAR *) target; + register size_t count; + + for (count = bytestozero; count > 0; count--) { + *ptr++ = 0; + } +} +#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 +} diff --git a/plugins/FreeImage/src/LibJPEG/jversion.h b/plugins/FreeImage/src/LibJPEG/jversion.h new file mode 100644 index 0000000000..5d4915103e --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/jversion.h @@ -0,0 +1,14 @@ +/* + * jversion.h + * + * Copyright (C) 1991-2012, 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 "8d 15-Jan-2012" + +#define JCOPYRIGHT "Copyright (C) 2012, Thomas G. Lane, Guido Vollbeding" diff --git a/plugins/FreeImage/src/LibJPEG/rdbmp.c b/plugins/FreeImage/src/LibJPEG/rdbmp.c new file mode 100644 index 0000000000..dfdf96ff5c --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/rdbmp.c @@ -0,0 +1,480 @@ +/* + * rdbmp.c + * + * Copyright (C) 1994-1996, Thomas G. Lane. + * Modified 2009-2010 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 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; +} + + +METHODDEF(JDIMENSION) +get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) +/* This version is for reading 32-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++; + inptr++; /* skip the 4th byte (Alpha channel) */ + 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, get_24bit_row, or get_32bit_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; + case 32: + source->pub.get_pixel_rows = get_32bit_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; + INT32 biHeight; + 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; + } + 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; + case 32: /* RGB image + Alpha channel */ + TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight); + break; + default: + ERREXIT(cinfo, JERR_BMP_BADDEPTH); + break; + } + 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); + return; + } + + if (biWidth <= 0 || biHeight <= 0) + ERREXIT(cinfo, JERR_BMP_EMPTY); + if (biPlanes != 1) + ERREXIT(cinfo, JERR_BMP_BADPLANES); + + /* 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 if (source->bits_per_pixel == 32) + row_width = (JDIMENSION) (biWidth * 4); + 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/plugins/FreeImage/src/LibJPEG/rdcolmap.c b/plugins/FreeImage/src/LibJPEG/rdcolmap.c new file mode 100644 index 0000000000..eebf8346c5 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/rdgif.c b/plugins/FreeImage/src/LibJPEG/rdgif.c new file mode 100644 index 0000000000..b0757e718f --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/rdjpgcom.c b/plugins/FreeImage/src/LibJPEG/rdjpgcom.c new file mode 100644 index 0000000000..ab09b443ff --- /dev/null +++ b/plugins/FreeImage/src/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, */ + +#ifdef HAVE_LOCALE_H +#include /* Bill Allombert: use locale for isprint */ +#endif +#include /* to declare isupper(), tolower() */ +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* to declare setmode() */ +#endif + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* 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/plugins/FreeImage/src/LibJPEG/rdppm.c b/plugins/FreeImage/src/LibJPEG/rdppm.c new file mode 100644 index 0000000000..9dcd2dc216 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/rdrle.c b/plugins/FreeImage/src/LibJPEG/rdrle.c new file mode 100644 index 0000000000..df871e00a4 --- /dev/null +++ b/plugins/FreeImage/src/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 + +/* + * 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/plugins/FreeImage/src/LibJPEG/rdswitch.c b/plugins/FreeImage/src/LibJPEG/rdswitch.c new file mode 100644 index 0000000000..5eebcc1e5c --- /dev/null +++ b/plugins/FreeImage/src/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 /* 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/plugins/FreeImage/src/LibJPEG/rdtarga.c b/plugins/FreeImage/src/LibJPEG/rdtarga.c new file mode 100644 index 0000000000..d7ffc33ebd --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/transupp.c b/plugins/FreeImage/src/LibJPEG/transupp.c new file mode 100644 index 0000000000..016f383d4f --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/transupp.c @@ -0,0 +1,1597 @@ +/* + * transupp.c + * + * Copyright (C) 1997-2011, 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 /* 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->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + + 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->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + + 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->output_height / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); + + 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->output_height / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + + 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->output_width / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); + + 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->output_width / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_height / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); + + 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->output_height / + (dstinfo->max_h_samp_factor * dstinfo->min_DCT_h_scaled_size); + MCU_rows = srcinfo->output_width / + (dstinfo->max_v_samp_factor * dstinfo->min_DCT_v_scaled_size); + + 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 + * [f]x[f]{+-}{+-} + * 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; + if (*spec == 'f' || *spec == 'F') { + spec++; + info->crop_width_set = JCROP_FORCE; + } else + info->crop_width_set = JCROP_POS; + } + if (*spec == 'x' || *spec == 'X') { + /* fetch height */ + spec++; + if (! jt_read_integer(&spec, &info->crop_height)) + return FALSE; + if (*spec == 'f' || *spec == 'F') { + spec++; + info->crop_height_set = JCROP_FORCE; + } else + 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->iMCU_sample_width; + if (MCU_cols > 0 && info->x_crop_offset + MCU_cols == + full_width / info->iMCU_sample_width) + info->output_width = MCU_cols * info->iMCU_sample_width; +} + +LOCAL(void) +trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height) +{ + JDIMENSION MCU_rows; + + MCU_rows = info->output_height / info->iMCU_sample_height; + if (MCU_rows > 0 && info->y_crop_offset + MCU_rows == + full_height / info->iMCU_sample_height) + info->output_height = MCU_rows * info->iMCU_sample_height; +} + + +/* 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). + * + * This function returns FALSE right away if -perfect is given + * and transformation is not perfect. Otherwise returns TRUE. + */ + +GLOBAL(boolean) +jtransform_request_workspace (j_decompress_ptr srcinfo, + jpeg_transform_info *info) +{ + jvirt_barray_ptr *coef_arrays; + boolean need_workspace, transpose_it; + jpeg_component_info *compptr; + JDIMENSION xoffset, yoffset; + JDIMENSION 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; + + /* Compute output image dimensions and related values. */ + jpeg_core_output_dimensions(srcinfo); + + /* Return right away if -perfect is given and transformation is not perfect. + */ + if (info->perfect) { + if (info->num_components == 1) { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->min_DCT_h_scaled_size, + srcinfo->min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } else { + if (!jtransform_perfect_transform(srcinfo->output_width, + srcinfo->output_height, + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size, + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size, + info->transform)) + return FALSE; + } + } + + /* 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->output_height; + info->output_height = srcinfo->output_width; + if (info->num_components == 1) { + info->iMCU_sample_width = srcinfo->min_DCT_v_scaled_size; + info->iMCU_sample_height = srcinfo->min_DCT_h_scaled_size; + } else { + info->iMCU_sample_width = + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; + info->iMCU_sample_height = + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; + } + break; + default: + info->output_width = srcinfo->output_width; + info->output_height = srcinfo->output_height; + if (info->num_components == 1) { + info->iMCU_sample_width = srcinfo->min_DCT_h_scaled_size; + info->iMCU_sample_height = srcinfo->min_DCT_v_scaled_size; + } else { + info->iMCU_sample_width = + srcinfo->max_h_samp_factor * srcinfo->min_DCT_h_scaled_size; + info->iMCU_sample_height = + srcinfo->max_v_samp_factor * srcinfo->min_DCT_v_scaled_size; + } + 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 */ + if (info->crop_width_set == JCROP_FORCE) + info->output_width = info->crop_width; + else + info->output_width = + info->crop_width + (xoffset % info->iMCU_sample_width); + if (info->crop_height_set == JCROP_FORCE) + info->output_height = info->crop_height; + else + info->output_height = + info->crop_height + (yoffset % info->iMCU_sample_height); + /* Save x/y offsets measured in iMCUs */ + info->x_crop_offset = xoffset / info->iMCU_sample_width; + info->y_crop_offset = yoffset / info->iMCU_sample_height; + } 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->output_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->output_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->output_height); + trim_bottom_edge(info, srcinfo->output_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->output_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->output_width); + trim_bottom_edge(info, srcinfo->output_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->output_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->iMCU_sample_width); + height_in_iMCUs = (JDIMENSION) + jdiv_round_up((long) info->output_height, + (long) info->iMCU_sample_height); + 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; + } else + info->workspace_coef_arrays = NULL; + + return TRUE; +} + + +/* 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; + JDIMENSION jtemp; + UINT16 qtemp; + + /* Transpose image dimensions */ + jtemp = dstinfo->image_width; + dstinfo->image_width = dstinfo->image_height; + dstinfo->image_height = jtemp; + itemp = dstinfo->min_DCT_h_scaled_size; + dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size; + dstinfo->min_DCT_v_scaled_size = itemp; + + /* 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 rotate/flip, resize, and crop operations. + */ + dstinfo->jpeg_width = info->output_width; + dstinfo->jpeg_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->jpeg_width != srcinfo->image_width || + dstinfo->jpeg_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->jpeg_width, dstinfo->jpeg_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 * cinfo.block_size + * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size + * 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/plugins/FreeImage/src/LibJPEG/transupp.h b/plugins/FreeImage/src/LibJPEG/transupp.h new file mode 100644 index 0000000000..9aa0af385a --- /dev/null +++ b/plugins/FreeImage/src/LibJPEG/transupp.h @@ -0,0 +1,213 @@ +/* + * transupp.h + * + * Copyright (C) 1997-2011, 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 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.) + * The adjustment of the region dimensions may be optionally disabled. + * + * We also provide a lossless-resize option, which is kind of a lossless-crop + * operation in the DCT coefficient block domain - it discards higher-order + * coefficients and losslessly preserves lower-order coefficients of a + * sub-block. + * + * Rotate/flip transform, resize, and crop can be requested together in a + * single invocation. The crop is applied last --- that is, the crop region + * is specified in terms of the destination image after transform/resize. + * + * 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 for xoffset or yoffset, + * positive or forced for width or height. + */ + +typedef enum { + JCROP_UNSET, + JCROP_POS, + JCROP_NEG, + JCROP_FORCE +} 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; /* (forced disables adjustment) */ + JDIMENSION crop_height; /* Height of selected region */ + JCROP_CODE crop_height_set; /* (forced disables adjustment) */ + 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 iMCU_sample_width; /* destination iMCU size */ + int iMCU_sample_height; +} 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(boolean) 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/plugins/FreeImage/src/LibJPEG/wrbmp.c b/plugins/FreeImage/src/LibJPEG/wrbmp.c new file mode 100644 index 0000000000..2b8146e2c0 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibJPEG/wrgif.c b/plugins/FreeImage/src/LibJPEG/wrgif.c new file mode 100644 index 0000000000..13f953b567 --- /dev/null +++ b/plugins/FreeImage/src/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 . + * 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/plugins/FreeImage/src/LibJPEG/wrjpgcom.c b/plugins/FreeImage/src/LibJPEG/wrjpgcom.c new file mode 100644 index 0000000000..7d10ee66e8 --- /dev/null +++ b/plugins/FreeImage/src/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, */ + +#ifndef HAVE_STDLIB_H /* should declare malloc() */ +extern void * malloc (); +#endif +#include /* to declare isupper(), tolower() */ +#ifdef USE_SETMODE +#include /* to declare setmode()'s parameter macros */ +/* If you have setmode() but not , just delete this line: */ +#include /* to declare setmode() */ +#endif + +#ifdef USE_CCOMMAND /* command-line reader for Macintosh */ +#ifdef __MWERKS__ +#include /* Metrowerks needs this */ +#include /* ... and this */ +#endif +#ifdef THINK_C +#include /* 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/plugins/FreeImage/src/LibJPEG/wrppm.c b/plugins/FreeImage/src/LibJPEG/wrppm.c new file mode 100644 index 0000000000..1e56d9c50e --- /dev/null +++ b/plugins/FreeImage/src/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<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/plugins/FreeImage/src/LibJPEG/wrrle.c b/plugins/FreeImage/src/LibJPEG/wrrle.c new file mode 100644 index 0000000000..7a00c0dd11 --- /dev/null +++ b/plugins/FreeImage/src/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 + +/* + * 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/plugins/FreeImage/src/LibJPEG/wrtarga.c b/plugins/FreeImage/src/LibJPEG/wrtarga.c new file mode 100644 index 0000000000..65662738d9 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/Changes b/plugins/FreeImage/src/LibMNG/Changes new file mode 100644 index 0000000000..fbf2ac572f --- /dev/null +++ b/plugins/FreeImage/src/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 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/plugins/FreeImage/src/LibMNG/LICENSE b/plugins/FreeImage/src/LibMNG/LICENSE new file mode 100644 index 0000000000..5878e32a2a --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/README b/plugins/FreeImage/src/LibMNG/README new file mode 100644 index 0000000000..35b12596f1 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/README.autoconf b/plugins/FreeImage/src/LibMNG/README.autoconf new file mode 100644 index 0000000000..97167b7d74 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/README.config b/plugins/FreeImage/src/LibMNG/README.config new file mode 100644 index 0000000000..97fcb31606 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/README.contrib b/plugins/FreeImage/src/LibMNG/README.contrib new file mode 100644 index 0000000000..2d51ac50a1 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/README.examples b/plugins/FreeImage/src/LibMNG/README.examples new file mode 100644 index 0000000000..9f23b5077b --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/README.footprint b/plugins/FreeImage/src/LibMNG/README.footprint new file mode 100644 index 0000000000..ae47da2c1a --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/README.packaging b/plugins/FreeImage/src/LibMNG/README.packaging new file mode 100644 index 0000000000..32fb2da8be --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng.h b/plugins/FreeImage/src/LibMNG/libmng.h new file mode 100644 index 0000000000..8513bf1127 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_callback_xs.c b/plugins/FreeImage/src/LibMNG/libmng_callback_xs.c new file mode 100644 index 0000000000..e8f1efeb66 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_chunk_descr.c b/plugins/FreeImage/src/LibMNG/libmng_chunk_descr.c new file mode 100644 index 0000000000..5a4bfa0381 --- /dev/null +++ b/plugins/FreeImage/src/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 /* 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/plugins/FreeImage/src/LibMNG/libmng_chunk_descr.h b/plugins/FreeImage/src/LibMNG/libmng_chunk_descr.h new file mode 100644 index 0000000000..5126cb2775 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_chunk_io.c b/plugins/FreeImage/src/LibMNG/libmng_chunk_io.c new file mode 100644 index 0000000000..a75945f063 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_chunk_io.h b/plugins/FreeImage/src/LibMNG/libmng_chunk_io.h new file mode 100644 index 0000000000..b47f8639b9 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_chunk_prc.c b/plugins/FreeImage/src/LibMNG/libmng_chunk_prc.c new file mode 100644 index 0000000000..6c8e5897f5 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_chunk_prc.h b/plugins/FreeImage/src/LibMNG/libmng_chunk_prc.h new file mode 100644 index 0000000000..96db17498e --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_chunk_xs.c b/plugins/FreeImage/src/LibMNG/libmng_chunk_xs.c new file mode 100644 index 0000000000..1c4ec2e50d --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_chunks.h b/plugins/FreeImage/src/LibMNG/libmng_chunks.h new file mode 100644 index 0000000000..6c50d8b867 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_cms.c b/plugins/FreeImage/src/LibMNG/libmng_cms.c new file mode 100644 index 0000000000..f215271f2a --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_cms.h b/plugins/FreeImage/src/LibMNG/libmng_cms.h new file mode 100644 index 0000000000..d442a3fa6a --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_conf.h b/plugins/FreeImage/src/LibMNG/libmng_conf.h new file mode 100644 index 0000000000..5f6fdb91a5 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_data.h b/plugins/FreeImage/src/LibMNG/libmng_data.h new file mode 100644 index 0000000000..dd715b0989 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_display.c b/plugins/FreeImage/src/LibMNG/libmng_display.c new file mode 100644 index 0000000000..65a5c31d95 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_display.h b/plugins/FreeImage/src/LibMNG/libmng_display.h new file mode 100644 index 0000000000..3dc6ca2d91 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_dither.c b/plugins/FreeImage/src/LibMNG/libmng_dither.c new file mode 100644 index 0000000000..3ba2a7069c --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_dither.h b/plugins/FreeImage/src/LibMNG/libmng_dither.h new file mode 100644 index 0000000000..250c0b9d28 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_error.c b/plugins/FreeImage/src/LibMNG/libmng_error.c new file mode 100644 index 0000000000..89501a2eae --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_error.h b/plugins/FreeImage/src/LibMNG/libmng_error.h new file mode 100644 index 0000000000..14eb450a28 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_filter.c b/plugins/FreeImage/src/LibMNG/libmng_filter.c new file mode 100644 index 0000000000..ad57a3be90 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_filter.h b/plugins/FreeImage/src/LibMNG/libmng_filter.h new file mode 100644 index 0000000000..5ff4cb609b --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_hlapi.c b/plugins/FreeImage/src/LibMNG/libmng_hlapi.c new file mode 100644 index 0000000000..ef0c2e1484 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_jpeg.c b/plugins/FreeImage/src/LibMNG/libmng_jpeg.c new file mode 100644 index 0000000000..409f6df74d --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_jpeg.h b/plugins/FreeImage/src/LibMNG/libmng_jpeg.h new file mode 100644 index 0000000000..ef9dbf204d --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_memory.h b/plugins/FreeImage/src/LibMNG/libmng_memory.h new file mode 100644 index 0000000000..9da16a460b --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_object_prc.c b/plugins/FreeImage/src/LibMNG/libmng_object_prc.c new file mode 100644 index 0000000000..570d346aa6 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_object_prc.h b/plugins/FreeImage/src/LibMNG/libmng_object_prc.h new file mode 100644 index 0000000000..46d201ca0e --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_objects.h b/plugins/FreeImage/src/LibMNG/libmng_objects.h new file mode 100644 index 0000000000..ab7290fdf3 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_pixels.c b/plugins/FreeImage/src/LibMNG/libmng_pixels.c new file mode 100644 index 0000000000..9990ee67bb --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_pixels.h b/plugins/FreeImage/src/LibMNG/libmng_pixels.h new file mode 100644 index 0000000000..203d1c1f99 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_prop_xs.c b/plugins/FreeImage/src/LibMNG/libmng_prop_xs.c new file mode 100644 index 0000000000..d4afc87d09 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_read.c b/plugins/FreeImage/src/LibMNG/libmng_read.c new file mode 100644 index 0000000000..3a6e49fcac --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_read.h b/plugins/FreeImage/src/LibMNG/libmng_read.h new file mode 100644 index 0000000000..e6399532b7 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_trace.c b/plugins/FreeImage/src/LibMNG/libmng_trace.c new file mode 100644 index 0000000000..ffb7b57d2e --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_trace.h b/plugins/FreeImage/src/LibMNG/libmng_trace.h new file mode 100644 index 0000000000..d8621c34c3 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_types.h b/plugins/FreeImage/src/LibMNG/libmng_types.h new file mode 100644 index 0000000000..08086b69f2 --- /dev/null +++ b/plugins/FreeImage/src/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 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 +#endif + +#ifdef MNG_INCLUDE_LCMS /* little cms by Marti Maria Saguer */ +#ifndef ZLIB_DLL +#undef FAR +#endif +#include +#endif /* MNG_INCLUDE_LCMS */ + +#ifdef MNG_INCLUDE_IJG6B /* IJG's jpgsrc6b */ +#include +#ifdef MNG_USE_SETJMP +#include /* 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 /* "calloc" & "free" & "abs" */ +#endif + +#include /* get proper integer widths */ + +#ifdef WIN32 +#if defined __BORLANDC__ +#include /* defines "memcpy" for BCB */ +#else +#include /* defines "memcpy" for other win32 platforms */ +#endif +#include /* "strncmp" + "strcmp" */ +#else /* WIN32 */ +#ifdef BSD +#include /* defines "memcpy", etc for BSD (?) */ +#else +#include /* defines "memcpy", etc for all others (???) */ +#endif +#endif /* WIN32 */ + +#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS) +#include /* 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/plugins/FreeImage/src/LibMNG/libmng_write.c b/plugins/FreeImage/src/LibMNG/libmng_write.c new file mode 100644 index 0000000000..22ed3a01e4 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_write.h b/plugins/FreeImage/src/LibMNG/libmng_write.h new file mode 100644 index 0000000000..31e5d1b622 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_zlib.c b/plugins/FreeImage/src/LibMNG/libmng_zlib.c new file mode 100644 index 0000000000..894bc74ac7 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibMNG/libmng_zlib.h b/plugins/FreeImage/src/LibMNG/libmng_zlib.h new file mode 100644 index 0000000000..4309344ded --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibPNG/ANNOUNCE b/plugins/FreeImage/src/LibPNG/ANNOUNCE new file mode 100644 index 0000000000..e8498a379c --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/ANNOUNCE @@ -0,0 +1,42 @@ + +Libpng 1.5.9 - February 18, 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.5.9.tar.xz (LZMA-compressed, recommended) + libpng-1.5.9.tar.gz + libpng-1.5.9.tar.bz2 + +Source files with CRLF line endings (for Windows), without the +"configure" script + + lpng159.7z (LZMA-compressed, recommended) + lpng159.zip + +Other information: + + libpng-1.5.9-README.txt + libpng-1.5.9-LICENSE.txt + +Changes since the last public release (1.5.8): + + Rebuilt configure scripts in the tar distributions. + Removed two unused definitions from scripts/pnglibconf.h.prebuilt + Removed some unused arrays (with #ifdef) from png_read_push_finish_row(). + Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h + Fixed CVE-2011-3026 buffer overrun bug. Deal more correctly with the test + on iCCP chunk length. Also removed spurious casts that may hide problems + on 16-bit systems. + +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/plugins/FreeImage/src/LibPNG/CHANGES b/plugins/FreeImage/src/LibPNG/CHANGES new file mode 100644 index 0000000000..fb3a90be8c --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/CHANGES @@ -0,0 +1,3820 @@ +#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_ functions to be + png_set_. We now have corresponding png_get_ + 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() behavior + 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 behavior + Tested NODIV support and made it default behavior (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 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". + comment out (with #ifdef) all the new declarations 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 " 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. + Added #ifdef to remove some redundancy 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 + Use #ifdef to comment out 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 (CVE-2006-7244) + +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.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.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 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.4.0beta1 [April 20, 2006] + Enabled iTXt support (changes png_struct, thus requires so-number change). + Cleaned up PNG_ASSEMBLER_CODE_SUPPORTED vs PNG_MMX_CODE_SUPPORTED + Eliminated PNG_1_0_X and PNG_1_2_X macros. + Removed deprecated functions png_read_init, png_write_init, png_info_init, + png_permit_empty_plte, png_set_gray_1_2_4_to_8, png_check_sig, and + removed the deprecated macro PNG_MAX_UINT. + Moved "PNG_INTERNAL" parts of png.h and pngconf.h into pngintrn.h + Removed many WIN32_WCE #ifdefs (Cosmin). + Reduced dependency on C-runtime library when on Windows (Simon-Pierre) + Replaced sprintf() with png_sprintf() (Simon-Pierre) + +Version 1.4.0beta2 [April 20, 2006] + Revised makefiles and configure to avoid making links to libpng.so.* + Moved some leftover MMX-related defines from pngconf.h to pngintrn.h + Updated scripts/pngos2.def, pngw32.def, and projects/wince/png32ce.def + +Version 1.4.0beta3 [May 10, 2006] + Updated scripts/pngw32.def to comment out MMX functions. + Added PNG_NO_GET_INT_32 and PNG_NO_SAVE_INT_32 macros. + Scripts/libpng.pc.in contained "configure" style version info and would + not work with makefiles. + Revised pngconf.h and added pngconf.h.in, so makefiles and configure can + pass defines to libpng and applications. + +Version 1.4.0beta4 [May 11, 2006] + Revised configure.ac, Makefile.am, and many of the makefiles to write + their defines in pngconf.h. + +Version 1.4.0beta5 [May 15, 2006] + Added a missing semicolon in Makefile.am and Makefile.in + Deleted extraneous square brackets from configure.ac + +Version 1.4.0beta6 [June 2, 2006] + Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + Changed sonum from 0 to 1. + Removed unused prototype for png_check_sig() from png.h + +Version 1.4.0beta7 [June 16, 2006] + Exported png_write_sig (Cosmin). + Optimized buffer in png_handle_cHRM() (Cosmin). + Set pHYs = 2835 x 2835 pixels per meter, and added + sCAL = 0.352778e-3 x 0.352778e-3 meters, in pngtest.png (Cosmin). + Added png_set_benign_errors(), png_benign_error(), png_chunk_benign_error(). + Added typedef for png_int_32 and png_uint_32 on 64-bit systems. + Added "(unsigned long)" typecast on png_uint_32 variables in printf lists. + +Version 1.4.0beta8 [June 22, 2006] + Added demonstration of user chunk support in pngtest.c, to support the + public sTER chunk and a private vpAg chunk. + +Version 1.4.0beta9 [July 3, 2006] + Removed ordinals from scripts/pngw32.def and removed png_info_int and + png_set_gray_1_2_4_to_8 entries. + Inline call of png_get_uint_32() in png_get_uint_31(). + Use png_get_uint_31() to get vpAg width and height in pngtest.c + Removed WINCE and Netware projects. + Removed standalone Y2KINFO file. + +Version 1.4.0beta10 [July 12, 2006] + Eliminated automatic copy of pngconf.h to pngconf.h.in from configure and + some makefiles, because it was not working reliably. Instead, distribute + pngconf.h.in along with pngconf.h and cause configure and some of the + makefiles to update pngconf.h from pngconf.h.in. + Added pngconf.h to DEPENDENCIES in Makefile.am + +Version 1.4.0beta11 [August 19, 2006] + Removed AC_FUNC_MALLOC from configure.ac. + Added a warning when writing iCCP profile with mismatched profile length. + Patched pnggccrd.c to assemble on x86_64 platforms. + Moved chunk header reading into a separate function png_read_chunk_header() + in pngrutil.c. The chunk header (len+sig) is now serialized in a single + operation (Cosmin). + Implemented support for I/O states. Added png_ptr member io_state, and + functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + (Cosmin). + Added png_get_io_chunk_name and png_get_io_state to scripts/*.def (Cosmin). + Renamed scripts/pngw32.* to scripts/pngwin.* (Cosmin). + Removed the include directories and libraries from CFLAGS and LDFLAGS + in scripts/makefile.gcc (Cosmin). + Used png_save_uint_32() to set vpAg width and height in pngtest.c (Cosmin). + Cast to proper type when getting/setting vpAg units in pngtest.c (Cosmin). + Added pngintrn.h to the Visual C++ projects (Cosmin). + Removed scripts/list (Cosmin). + Updated copyright year in scripts/pngwin.def (Cosmin). + Removed PNG_TYPECAST_NULL and used standard NULL consistently (Cosmin). + Disallowed the user to redefine png_size_t, and enforced a consistent use + of png_size_t across libpng (Cosmin). + Changed the type of png_ptr->rowbytes, PNG_ROWBYTES() and friends + to png_size_t (Cosmin). + Removed png_convert_size() and replaced png_sizeof with sizeof (Cosmin). + Removed some unnecessary type casts (Cosmin). + Changed prototype of png_get_compression_buffer_size() and + png_set_compression_buffer_size() to work with png_size_t instead of + png_uint_32 (Cosmin). + Removed png_memcpy_check() and png_memset_check() (Cosmin). + Fixed a typo (png_byte --> png_bytep) in libpng.3 and libpng.txt (Cosmin). + Clarified that png_zalloc() does not clear the allocated memory, + and png_zalloc() and png_zfree() cannot be PNGAPI (Cosmin). + Renamed png_mem_size_t to png_alloc_size_t, fixed its definition in + pngconf.h, and used it in all memory allocation functions (Cosmin). + Renamed pngintrn.h to pngpriv.h, added a comment at the top of the file + mentioning that the symbols declared in that file are private, and + updated the scripts and the Visual C++ projects accordingly (Cosmin). + Removed circular references between pngconf.h and pngconf.h.in in + scripts/makefile.vc*win32 (Cosmin). + Removing trailing '.' from the warning and error messages (Cosmin). + Added pngdefs.h that is built by makefile or configure, instead of + pngconf.h.in (Glenn). + Detect and fix attempt to write wrong iCCP profile length. + +Version 1.4.0beta12 [October 19, 2006] + Changed "logical" to "bitwise" in the documentation. + Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h + Add a typecast to stifle compiler warning in pngrutil.c + +Version 1.4.0beta13 [November 10, 2006] + Fix potential buffer overflow in sPLT chunk handler. + Fix Makefile.am to not try to link to noexistent files. + +Version 1.4.0beta14 [November 15, 2006] + Check all exported functions for NULL png_ptr. + +Version 1.4.0beta15 [November 17, 2006] + Relocated two 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 + Add "install: all" in Makefile.am so "configure; make install" will work. + +Version 1.4.0beta16 [November 17, 2006] + Added a typecast in png_zalloc(). + +Version 1.4.0beta17 [December 4, 2006] + Changed "new_key[79] = '\0';" to "(*new_key)[79] = '\0';" in pngwutil.c + Add "png_bytep" typecast to profile while calculating length in pngwutil.c + +Version 1.4.0beta18 [December 7, 2006] + Added scripts/CMakeLists.txt + +Version 1.4.0beta19 [May 16, 2007] + Revised scripts/CMakeLists.txt + Rebuilt configure and Makefile.in with newer tools. + Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. + Added scripts/makefile.nommx + +Version 1.4.0beta20 [July 9, 2008] + Moved several PNG_HAVE_* macros from pngpriv.h to png.h because applications + calling set_unknown_chunk_location() need them. + Moved several macro definitions from pngpriv.h to pngconf.h + Merge with changes to the 1.2.X branch, as of 1.2.30beta04. + Deleted all use of the MMX assembler code and Intel-licensed optimizations. + Revised makefile.mingw + +Version 1.4.0beta21 [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.4.0beta22 [July 21, 2008] + Change "purpose" and "buffer" to png_ptr->chunkdata to avoid memory leaking. + +Version 1.4.0beta23 [July 22, 2008] + Change "chunkdata = NULL" to "png_ptr->chunkdata = NULL" several places in + png_decompress_chunk(). + +Version 1.4.0beta24 [July 25, 2008] + Change 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. + Define PNG_NO_ERROR_NUMBERS by default in pngconf.h + +Version 1.4.0beta25 [July 30, 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. + Added png_push_have_buffer() function to pngpread.c + Eliminated PNG_BIG_ENDIAN_SUPPORTED and associated png_get_* macros. + Made inline expansion of png_get_*() optional with PNG_USE_READ_MACROS. + Eliminated all PNG_USELESS_TESTS and PNG_CORRECT_PALETTE_SUPPORTED code. + Synced contrib directory and configure files with libpng-1.2.30beta06. + Eliminated no-longer-used pngdefs.h (but it's still built in the makefiles) + Relocated a misplaced "#endif /* PNG_NO_WRITE_FILTER */" in pngwutil.c + +Version 1.4.0beta26 [August 4, 2008] + Removed png_push_have_buffer() function in pngpread.c. It increased the + compiled library size slightly. + 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. + Updated contrib/visupng/cexcept.h to version 2.0.1 + Added PNG_LITERAL_CHARACTER macros for #, [, and ]. + +Version 1.4.0beta27 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Moved newline character from individual png_debug messages into the + png_debug macros. + Allow user to #define their own png_debug, png_debug1, and png_debug2. + +Version 1.4.0beta28 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Added PNG_STRING_NEWLINE macro + +Version 1.4.0beta29 [August 9, 2008] + Revised usage of PNG_STRING_NEWLINE to work on non-ISO compilers. + Added PNG_STRING_COPYRIGHT macro. + Added non-ISO versions of png_debug macros. + +Version 1.4.0beta30 [August 14, 2008] + Added premultiplied alpha feature (Volker Wiendl). + +Version 1.4.0beta31 [August 18, 2008] + Moved png_set_premultiply_alpha from pngtrans.c to pngrtran.c + Removed extra crc check at the end of png_handle_cHRM(). Bug introduced + in libpng-1.4.0beta20. + +Version 1.4.0beta32 [August 19, 2008] + Added PNG_WRITE_FLUSH_SUPPORTED block around new png_flush() call. + Revised PNG_NO_STDIO version of png_write_flush() + +Version 1.4.0beta33 [August 20, 2008] + Added png_get|set_chunk_cache_max() to limit the total number of sPLT, + text, and unknown chunks that can be stored. + +Version 1.4.0beta34 [September 6, 2008] + Shortened tIME_string to 29 bytes in pngtest.c + Fixed off-by-one error introduced in png_push_read_zTXt() function in + libpng-1.2.30beta04/pngpread.c (Harald van Dijk) + +Version 1.4.0beta35 [October 6, 2008] + Changed "trans_values" to "trans_color". + Changed so-number from 0 to 14. Some OS do not like 0. + 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.4.0beta36 [October 25, 2008] + Sync with tEXt vulnerability fix in libpng-1.2.33rc02. + +Version 1.4.0beta37 [November 13, 2008] + Added png_check_cHRM in png.c and moved checking from pngget.c, pngrutil.c, + and pngwrite.c + +Version 1.4.0beta38 [November 22, 2008] + Added check for zero-area RGB cHRM triangle in png_check_cHRM() and + png_check_cHRM_fixed(). + +Version 1.4.0beta39 [November 23, 2008] + Revised png_warning() to write its message on standard output by default + when warning_fn is NULL. + +Version 1.4.0beta40 [November 24, 2008] + Eliminated png_check_cHRM(). Instead, always use 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. + +Version 1.4.0beta41 [November 26, 2008] + Fixed string vs pointer-to-string error in png_check_keyword(). + Rearranged test expressions in png_check_cHRM_fixed() to avoid internal + overflows. + Added PNG_NO_CHECK_cHRM conditional. + +Version 1.4.0beta42, 43 [December 1, 2008] + Merge png_debug with version 1.2.34beta04. + +Version 1.4.0beta44 [December 6, 2008] + Removed redundant check for key==NULL before calling png_check_keyword() + to ensure that new_key gets initialized and removed extra warning + (Merge with version 1.2.34beta05 -- Arvan Pritchard). + +Version 1.4.0beta45 [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.4.0beta46 [December 10, 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.4.0beta47 [December 15, 2008] + Support for dithering was disabled by default, because it has never + been well tested and doesn't work very well. The code has not + been removed, however, and can be enabled by building libpng with + PNG_READ_DITHER_SUPPORTED defined. + +Version 1.4.0beta48 [February 14, 2009] + Added new exported function png_calloc(). + Combined several instances of png_malloc(); png_memset() into png_calloc(). + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined. + +Version 1.4.0beta49 [February 28, 2009] + Added png_fileno() macro to pngconf.h, used in pngwio.c + Corrected order of #ifdef's in png_debug definition in png.h + Fixed bug introduced in libpng-1.4.0beta48 with the memset arguments + for pcal_params. + Fixed order of #ifdef directives in the png_debug defines in png.h + (bug introduced in libpng-1.2.34/1.4.0beta29). + Revised comments in png_set_read_fn() and png_set_write_fn(). + +Version 1.4.0beta50 [March 18, 2009] + Use png_calloc() instead of png_malloc() to allocate big_row_buf when + reading an interlaced file, to avoid a possible UMR. + Undid revision of PNG_NO_STDIO version of png_write_flush(). Users + having trouble with fflush() can build with PNG_NO_WRITE_FLUSH defined + or supply their own flush_fn() replacement. + Revised libpng*.txt and png.h documentation about use of png_write_flush() + and png_set_write_fn(). + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h + +Version 1.4.0beta51 [March 21, 2009] + Removed new png_fileno() macro from pngconf.h . + +Version 1.4.0beta52 [March 27, 2009] + Relocated png_do_chop() ahead of building gamma tables in pngrtran.c + This avoids building 16-bit gamma tables unnecessarily. + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h + Added a section on differences between 1.0.x and 1.2.x to libpng.3/libpng.txt + +Version 1.4.0beta53 [April 1, 2009] + Removed some remaining MMX macros from pngpriv.h + Fixed potential memory leak of "new_name" in png_write_iCCP() (Ralph Giles) + +Version 1.4.0beta54 [April 13, 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. + Eliminated internal use of setjmp() in pngread.c and pngwrite.c + Reordered ancillary chunks in pngtest.png to be the same as what + pngtest now produces, and made some cosmetic changes to pngtest output. + Eliminated deprecated png_read_init_3() and png_write_init_3() functions. + +Version 1.4.0beta55 [April 15, 2009] + Simplified error handling in pngread.c and pngwrite.c by putting + the new png_read_cleanup() and png_write_cleanup() functions inline. + +Version 1.4.0beta56 [April 25, 2009] + 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.4.0beta57 [May 2, 2009] + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined (again). + Rebuilt configure scripts with autoconf-2.63 instead of 2.62 + Removed pngprefs.h and MMX from makefiles + +Version 1.4.0beta58 [May 14, 2009] + Changed pngw32.def to pngwin.def in makefile.mingw (typo was introduced + in beta57). + Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) + +Version 1.4.0beta59 [May 15, 2009] + Reformated sources in libpng style (3-space intentation, comment format) + Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG) + Added sections about the git repository and our coding style to the + documentation + Relocated misplaced #endif in pngwrite.c, sCAL chunk handler. + +Version 1.4.0beta60 [May 19, 2009] + 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.4.0beta61 [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. + More reformatting of comments, mostly to capitalize sentences. + +Version 1.4.0beta62 [June 2, 2009] + 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 + Reformatted several remaining "else statement" into two lines. + Added a section to the libpng documentation about using png_get_io_ptr() + in configure scripts to detect the presence of libpng. + +Version 1.4.0beta63 [June 15, 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. + +Version 1.4.0beta64 [June 24, 2009] + Eliminated PNG_LEGACY_SUPPORTED code. + Moved the various unknown chunk macro definitions outside of the + PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. + +Version 1.4.0beta65 [June 26, 2009] + Added a reference to the libpng license in each file. + +Version 1.4.0beta66 [June 27, 2009] + Refer to the libpng license instead of the libpng license in each file. + +Version 1.4.0beta67 [July 6, 2009] + Relocated INVERT_ALPHA within png_read_png() and png_write_png(). + Added high-level API transform PNG_TRANSFORM_GRAY_TO_RGB. + Added an "xcode" project to the projects directory (Alam Arias). + +Version 1.4.0beta68 [July 19, 2009] + Avoid some tests in filter selection in pngwutil.c + +Version 1.4.0beta69 [July 25, 2009] + Simplified the new filter-selection test. This runs faster in the + common "PNG_ALL_FILTERS" and PNG_FILTER_NONE cases. + Removed extraneous declaration from the new call to png_read_gray_to_rgb() + (bug introduced in libpng-1.4.0beta67). + Fixed up xcode project (Alam Arias) + Added a prototype for png_64bit_product() in png.c + +Version 1.4.0beta70 [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.4.0beta71 [July 29, 2009] + Rebuilt configure scripts with autoconf-2.64. + +Version 1.4.0beta72 [August 1, 2009] + Replaced *.tar.lzma with *.tar.xz in distribution. Get the xz codec + from . + +Version 1.4.0beta73 [August 1, 2009] + Reject attempt to write iCCP chunk with negative embedded profile length + (JD Chen) (CVE-2009-5063). + +Version 1.4.0beta74 [August 8, 2009] + Changed png_ptr and info_ptr member "trans" to "trans_alpha". + +Version 1.4.0beta75 [August 21, 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.4.0beta76 [August 22, 2009] + Moved an incorrectly located test in png_read_row() in pngread.c + +Version 1.4.0beta77 [August 27, 2009] + Removed lpXYZ.tar.bz2 (with CRLF), KNOWNBUG, libpng-x.y.z-KNOWNBUG.txt, + and the "noconfig" files from the distribution. + Moved CMakeLists.txt from scripts into the main libpng directory. + Various bugfixes and improvements to CMakeLists.txt (Philip Lowman) + +Version 1.4.0beta78 [August 31, 2009] + Converted all PNG_NO_* tests to PNG_*_SUPPORTED everywhere except pngconf.h + Eliminated PNG_NO_FREE_ME and PNG_FREE_ME_SUPPORTED macros. + Use png_malloc plus a loop instead of png_calloc() to initialize + row_pointers in png_read_png(). + +Version 1.4.0beta79 [September 1, 2009] + Eliminated PNG_GLOBAL_ARRAYS and PNG_LOCAL_ARRAYS; always use local arrays. + Eliminated PNG_CALLOC_SUPPORTED macro and always provide png_calloc(). + +Version 1.4.0beta80 [September 17, 2009] + Removed scripts/libpng.icc + Changed typecast of filler from png_byte to png_uint_16 in png_set_filler(). + (Dennis Gustafsson) + Fixed typo introduced in beta78 in pngtest.c ("#if def " should be "#ifdef ") + +Version 1.4.0beta81 [September 23, 2009] + Eliminated unused PNG_FLAG_FREE_* defines from pngpriv.h + Expanded TAB characters in pngrtran.c + Removed PNG_CONST from all "PNG_CONST PNG_CHNK" declarations to avoid + compiler complaints about doubly declaring things "const". + Changed all "#if [!]defined(X)" to "if[n]def X" where possible. + Eliminated unused png_ptr->row_buf_size + +Version 1.4.0beta82 [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 + +Version 1.4.0beta83 [September 25, 2009] + Revised png_check_IHDR() to eliminate bogus complaint about filter_type. + +Version 1.4.0beta84 [September 30, 2009] + Fixed some inconsistent indentation in pngconf.h + Revised png_check_IHDR() to add a test for width variable less than 32-bit. + +Version 1.4.0beta85 [October 1, 2009] + Revised png_check_IHDR() again, to check info_ptr members instead of + the contents of the returned parameters. + +Version 1.4.0beta86 [October 9, 2009] + Updated the "xcode" project (Alam Arias). + Eliminated a shadowed declaration of "pp" in png_handle_sPLT(). + +Version 1.4.0rc01 [October 19, 2009] + Trivial cosmetic changes. + +Version 1.4.0beta87 [October 30, 2009] + Moved version 1.4.0 back into beta. + +Version 1.4.0beta88 [October 30, 2009] + Revised libpng*.txt section about differences between 1.2.x and 1.4.0 + because most of the new features have now been ported back to 1.2.41 + +Version 1.4.0beta89 [November 1, 2009] + More bugfixes and improvements to CMakeLists.txt (Philip Lowman) + Removed a harmless extra png_set_invert_alpha() from pngwrite.c + 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.4.0beta90 [November 2, 2009] + Removed all remaining WIN32_WCE #ifdefs except those involving the + time.h "tm" structure + +Version 1.4.0beta91 [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.4.0beta92 [November 4, 2009] + 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 + Revised libpng*.txt to describe differences from 1.2.40 to 1.4.0 (instead + of differences from 1.2.41 to 1.4.0) + +Version 1.4.0beta93 [November 7, 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". + They should work but still need to be updated to remove + references to pnggccrd.c or pngvcrd.c and ASM building. + Added README.txt to the beos, cbuilder5, netware, and xcode projects warning + that they need to be updated, to remove references to pnggccrd.c and + pngvcrd.c and to depend on pngpriv.h + Removed three direct references to read_info_ptr members in pngtest.c + that were detected by the new PNG_DEPSTRUCT macro. + Moved the png_debug macro definitions and the png_read_destroy(), + png_write_destroy() and png_far_to_near() prototypes from png.h + to pngpriv.h (John Bowler) + Moved the synopsis lines for png_read_destroy(), png_write_destroy() + png_debug(), png_debug1(), and png_debug2() from libpng.3 to libpngpf.3. + +Version 1.4.0beta94 [November 9, 2009] + Removed the obsolete, unused pnggccrd.c and pngvcrd.c files. + Updated CMakeLists.txt to add "-DPNG_CONFIGURE_LIBPNG" to the definitions. + Removed dependency of pngtest.o on pngpriv.h in the makefiles. + Only #define PNG_DEPSTRUCT, etc. in pngconf.h if not already defined. + +Version 1.4.0beta95 [November 10, 2009] + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Added -DPNG_CONFIGURE_LIBPNG to contrib/pngminm/*/makefile + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Corrected the png_get_IHDR() call in contrib/gregbook/readpng2.c + Changed pngminim/*/gather.sh to stop trying to remove pnggccrd.c and pngvcrd.c + Added dependency on pngpriv.h in contrib/pngminim/*/makefile + +Version 1.4.0beta96 [November 12, 2009] + Renamed scripts/makefile.wce to scripts/makefile.cegcc + Revised Makefile.am to use libpng.sys while building libpng.so + so that only PNG_EXPORT functions are exported. + Removed the deprecated png_check_sig() function/macro. + Removed recently removed function names from scripts/*.def + Revised pngtest.png to put chunks in the same order written by pngtest + (evidently the same change made in libpng-1.0beta54 was lost). + Added PNG_PRIVATE macro definition in pngconf.h for possible future use. + +Version 1.4.0beta97 [November 13, 2009] + Restored pngtest.png to the libpng-1.4.0beta7 version. + Removed projects/beos and netware.txt; no one seems to be supporting them. + Revised Makefile.in + +Version 1.4.0beta98 [November 13, 2009] + Added the "xcode" project to zip distributions, + Fixed a typo in scripts/pngwin.def introduced in beta97. + +Version 1.4.0beta99 [November 14, 2009] + Moved libpng-config.in and libpng.pc-configure.in out of the scripts + directory, to libpng-config.in and libpng-pc.in, respectively, and + modified Makefile.am and configure.ac accordingly. Now "configure" + needs nothing from the "scripts" directory. + Avoid redefining PNG_CONST in pngconf.h + +Version 1.4.0beta100 [November 14, 2009] + Removed ASM builds from projects/visualc6 and projects/visualc71 + Removed scripts/makefile.nommx and makefile.vcawin32 + Revised CMakeLists.txt to account for new location of libpng-config.in + and libpng-pc.in + Updated INSTALL to reflect removal and relocation of files. + +Version 1.4.0beta101 [November 14, 2009] + Restored the binary files (*.jpg, *.png, some project files) that were + accidentally deleted from the zip and 7z distributions when the xcode + project was added. + +Version 1.4.0beta102 [November 18, 2009] + Added libpng-config.in and libpng-pc.in to the zip and 7z distributions. + Fixed a typo in projects/visualc6/pngtest.dsp, introduced in beta100. + Moved descriptions of makefiles and other scripts out of INSTALL into + scripts/README.txt + Updated the copyright year in scripts/pngwin.rc from 2006 to 2009. + +Version 1.4.0beta103 [November 21, 2009] + Removed obsolete comments about ASM from projects/visualc71/README_zlib.txt + Align row_buf on 16-byte boundary in memory. + Restored the PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED guard around the call + to png_flush() after png_write_IEND(). See 1.4.0beta32, 1.4.0beta50 + changes above and 1.2.30, 1.2.30rc01 and rc03 in 1.2.41 CHANGES. Someone + needs this feature. + Make the 'png_jmpbuf' macro expand to a call that records the correct + longjmp function as well as returning a pointer to the setjmp + jmp_buf buffer, and marked direct access to jmpbuf 'deprecated'. + (John Bowler) + +Version 1.4.0beta104 [November 22, 2009] + Removed png_longjmp_ptr from scripts/*.def and libpng.3 + Rebuilt configure scripts with autoconf-2.65 + +Version 1.4.0beta105 [November 25, 2009] + Use fast integer PNG_DIVIDE_BY_255() or PNG_DIVIDE_BY_65535() + to accomplish alpha premultiplication when + PNG_READ_COMPOSITE_NODIV_SUPPORTED is defined. + Changed "/255" to "/255.0" in background calculations to make it clear + that the 255 is used as a double. + +Version 1.4.0beta106 [November 27, 2009] + Removed premultiplied alpha feature. + +Version 1.4.0beta107 [December 4, 2009] + Updated README + Added "#define PNG_NO_PEDANTIC_WARNINGS" in the libpng source files. + Removed "-DPNG_CONFIGURE_LIBPNG" from the makefiles and projects. + 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/libpng15 instead of in + $prefix/include/libpng/libpng15. + +Version 1.4.0beta108 [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.4.0beta109 [December 13, 2009] + Added "bit_depth" parameter to the private png_build_gamma_table() function. + Pass bit_depth=8 to png_build_gamma_table() when bit_depth is 16 but the + PNG_16_TO_8 transform has been set, to avoid unnecessary build of 16-bit + tables. + +Version 1.4.0rc02 [December 20, 2009] + Declared png_cleanup_needed "volatile" in pngread.c and pngwrite.c + +Version 1.4.0rc03 [December 22, 2009] + Renamed libpng-pc.in back to libpng.pc.in and revised CMakeLists.txt + (revising the change in 1.4.0beta99) + +Version 1.4.0rc04 [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.4.0rc05 [December 25, 2009] + Changed "libpng-pc.in" to "libpng.pc.in" in configure.ac, configure, and + Makefile.in to be consistent with changes in libpng-1.4.0rc03 + +Version 1.4.0rc06 [December 29, 2009] + Reverted the gamma_table changes from libpng-1.4.0beta109. + Fixed some indentation errors. + +Version 1.4.0rc07 [January 1, 2010] + Revised libpng*.txt and libpng.3 about 1.2.x->1.4.x differences. + Use png_calloc() instead of png_malloc(); png_memset() in pngrutil.c + Update copyright year to 2010. + +Version 1.4.0rc08 [January 2, 2010] + Avoid deprecated references to png_ptr-io_ptr and png_ptr->error_ptr + in pngtest.c + +Version 1.4.0 [January 3, 2010] + No changes. + +Version 1.4.1beta01 [January 8, 2010] + Updated CMakeLists.txt for consistent indentation and to avoid an + unclosed if-statement warning (Philip Lowman). + Revised Makefile.am and Makefile.in to remove references to Y2KINFO, + KNOWNBUG, and libpng.la (Robert Schwebel). + Revised the makefiles to install the same files and symbolic + links as configure, except for libpng.la and libpng14.la. + Make png_set|get_compression_buffer_size() available even when + PNG_WRITE_SUPPORTED is not enabled. + Revised Makefile.am and Makefile.in to simplify their maintenance. + Revised scripts/makefile.linux to install a link to libpng14.so.14.1 + +Version 1.4.1beta02 [January 9, 2010] + Revised the rest of the makefiles to install a link to libpng14.so.14.1 + +Version 1.4.1beta03 [January 10, 2010] + Removed png_set_premultiply_alpha() from scripts/*.def + +Version 1.4.1rc01 [January 16, 2010] + No changes. + +Version 1.4.1beta04 [January 23, 2010] + Revised png_decompress_chunk() to improve speed and memory usage when + decoding large chunks. + Added png_set|get_chunk_malloc_max() functions. + +Version 1.4.1beta05 [January 26, 2010] + Relocated "int k" declaration in pngtest.c to minimize its scope. + +Version 1.4.1beta06 [January 28, 2010] + Revised png_decompress_chunk() to use a two-pass method suggested by + John Bowler. + +Version 1.4.1beta07 [February 6, 2010] + Folded some long lines in the source files. + Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, + and a PNG_USER_LIMITS_SUPPORTED flag. + Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as + png_ptr->png_user_chunk_malloc_max. + Revised png_push_save_buffer() to do fewer but larger png_malloc() calls. + +Version 1.4.1beta08 [February 6, 2010] + Minor cleanup and updating of dates and copyright year. + +Version 1.5.0beta01 [February 7, 2010] + Moved declaration of png_struct into private pngstruct.h and png_info + into pnginfo.h + +Version 1.4.1beta09 and 1.5.0beta02 [February 7, 2010] + Reverted to original png_push_save_buffer() code. + +Version 1.4.1beta10 and 1.5.0beta03 [February 8, 2010] + Return allocated "old_buffer" in png_push_save_buffer() before + calling png_error(), to avoid a potential memory leak. + Updated configure script to use SO number 15. + +Version 1.5.0beta04 [February 9, 2010] + Removed malformed "incomplete struct declaration" of png_info from png.h + +Version 1.5.0beta05 [February 12, 2010] + Removed PNG_DEPSTRUCT markup in pngstruct.h and pnginfo.h, and undid the + linewrapping that it entailed. + Revised comments in pngstruct.h and pnginfo.h and added pointers to + the libpng license. + Changed PNG_INTERNAL to PNG_EXPOSE_INTERNAL_STRUCTURES + Removed the cbuilder5 project, which has not been updated to 1.4.0. + +Version 1.4.1beta12 and 1.5.0beta06 [February 14, 2010] + Fixed type declaration of png_get_chunk_malloc_max() in pngget.c (Daisuke + Nishikawa) + +Version 1.5.0beta07 [omitted] + +Version 1.5.0beta08 [February 19, 2010] + Changed #ifdef PNG_NO_STDIO_SUPPORTED to #ifdef PNG_NO_CONSOLE_IO_SUPPORTED + wherever png_snprintf() is used to construct error and warning messages. + Noted in scripts/makefile.mingw that it expects to be run under MSYS. + Removed obsolete unused MMX-querying support from contrib/gregbook + Added exported png_longjmp() function. + Removed the AIX redefinition of jmpbuf in png.h + Added -D_ALLSOURCE in configure.ac, makefile.aix, and CMakeLists.txt + when building on AIX. + +Version 1.5.0beta09 [February 19, 2010] + Removed -D_ALLSOURCE from configure.ac, makefile.aix, and CMakeLists.txt. + Changed the name of png_ptr->jmpbuf to png_ptr->png_jmpbuf in pngstruct.h + +Version 1.5.0beta10 [February 25, 2010] + Removed unused gzio.c from contrib/pngminim gather and makefile scripts + Removed replacement error handlers from contrib/gregbook. Because of + the new png_longjmp() function they are no longer needed. + +Version 1.5.0beta11 [March 6, 2010] + Removed checking for already-included setjmp.h from pngconf.h + Fixed inconsistent indentations and made numerous cosmetic changes. + Revised the "SEE ALSO" style of libpng.3, libpngpf.3, and png.5 + +Version 1.5.0beta12 [March 9, 2010] + Moved "#include png.h" inside pngpriv.h and removed "#include png.h" from + the source files, along with "#define PNG_EXPOSE_INTERNAL_STRUCTURES" + and "#define PNG_NO_PEDANTIC_WARNINGS" (John Bowler). + Created new pngdebug.h and moved debug definitions there. + +Version 1.5.0beta13 [March 10, 2010] + Protect pngstruct.h, pnginfo.h, and pngdebug.h from being included twice. + Revise the "#ifdef" blocks in png_inflate() so it will compile when neither + PNG_USER_CHUNK_MALLOC_MAX nor PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + is defined. + Removed unused png_measure_compressed_chunk() from pngpriv.h and libpngpf.3 + Moved the 'config.h' support from pngconf.h to pngpriv.h + Removed PNGAPI from the png_longjmp_ptr typedef. + Eliminated dependence of pngtest.c on the private pngdebug.h file. + Make all png_debug macros into *unterminated* statements or + expressions (i.e. a trailing ';' must always be added) and correct + the format statements in various png_debug messages. + +Version 1.5.0beta14 [March 14, 2010] + Removed direct access to png_ptr->io_ptr from the Windows code in pngtest.c + Revised Makefile.am to account for recent additions and replacements. + Corrected CE and OS/2 DEF files (scripts/png*def) for symbols removed and + added ordinal numbers to the Windows DEF file and corrected the duplicated + ordinal numbers on CE symbols that are commented out. + Added back in export symbols that can be present in the Windows build but + are disabled by default. + PNG_EXPORT changed to include an 'ordinal' field for DEF file generation. + PNG_CALLBACK added to make callback definitions uniform. PNGAPI split + into PNGCAPI (base C form), PNGAPI (exports) and PNGCBAPI (callbacks), + and appropriate changes made to all files. Cygwin builds re-hinged to + allow procedure call standard changes and to remove the need for the DEF + file (fixes build on Cygwin). + Enabled 'attribute' warnings that are relevant to library APIs and callbacks. + Changed rules for generation of the various symbol files and added a new + rule for a DEF file (which is also added to the distribution). + Updated the symbol file generation to stop it adding spurious spaces + to EOL (coming from preprocessor macro expansion). Added a facility + to join tokens in the output and rewrite *.dfn to use this. + Eliminated scripts/*.def in favor of libpng.def; updated projects/visualc71 + and removed scripts/makefile.cygwin. + Made PNG_BUILD_DLL safe: it can be set whenever a DLL is being built. + Removed the include of sys/types.h - apparently unnecessary now on the + platforms on which it happened (all but Mac OS and RISC OS). + Moved the Mac OS test into pngpriv.h (the only place it is used.) + +Version 1.5.0beta15 [March 17, 2010] + Added symbols.chk target to Makefile.am to validate the symbols in png.h + against the new DEF file scripts/symbols.def. + Changed the default DEF file back to pngwin.def. + Removed makefile.mingw. + Eliminated PNG_NO_EXTERN and PNG_ALL_EXTERN + +Version 1.5.0beta16 [April 1, 2010] + Make png_text_struct independent of PNG_iTXt_SUPPORTED, so that + fields are initialized in all configurations. The READ/WRITE + macros (PNG_(READ|WRITE)_iTXt_SUPPORTED) still function as + before to disable code to actually read or write iTXt chunks + and iTXt_SUPPORTED can be used to detect presence of either + read or write support (but it is probably better to check for + the one actually required - read or write.) + Combined multiple png_warning() calls for a single error. + Restored the macro definition of png_check_sig(). + +Version 1.5.0beta17 [April 17, 2010] + Added some "(long)" typecasts to printf calls in png_handle_cHRM(). + Documented the fact that png_set_dither() was disabled since libpng-1.4.0. + Reenabled png_set_dither() but renamed it to png_set_quantize() to reflect + more accurately what it actually does. At the same time, renamed + the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros to + PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS. + Added some "(long)" typecasts to printf calls in png_handle_cHRM(). + Freeze build-time only configuration in the build. + In all prior versions of libpng most configuration options + controlled by compiler #defines had to be repeated by the + application code that used libpng. This patch changes this + so that compilation options that can only be changed at build + time are frozen in the build. Options that are compiler + dependent (and those that are system dependent) are evaluated + each time - pngconf.h holds these. Options that can be changed + per-file in the application are in png.h. Frozen options are + in the new installed header file pnglibconf.h (John Bowler) + Removed the xcode project because it has not been updated to work + with libpng-1.5.0. + Removed the ability to include optional pngusr.h + +Version 1.5.0beta18 [April 17, 2010] + Restored the ability to include optional pngusr.h + Moved replacements for png_error() and png_warning() from the + contrib/pngminim project to pngerror.c, for use when warnings or + errors are disabled via PNG_NO_WARN or PNG_NO_ERROR_TEXT, to avoid + storing unneeded error/warning text. + Updated contrib/pngminim project to work with the new pnglibconf.h + Added some PNG_NO_* defines to contrib/pngminim/*/pngusr.h to save space. + +Version 1.5.0beta19 [April 24, 2010] + Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the functions + to read and write ints to be disabled independently of PNG_USE_READ_MACROS, + which allows libpng to be built with the functions even though the default + is to use the macros - this allows applications to choose at app build + time whether or not to use macros (previously impossible because the + functions weren't in the default build.) + Changed Windows calling convention back to __cdecl for API functions. + For Windows/x86 platforms only: + __stdcall is no longer needed for Visual Basic, so libpng-1.5.0 uses + __cdecl throughout (both API functions and callbacks) on Windows/x86 + platforms. + Replaced visualc6 and visualc71 projects with new vstudio project + Relaxed the overly-restrictive permissions of some files. + +Version 1.5.0beta20 [April 24, 2010] + Relaxed more overly-restrictive permissions of some files. + +Version 1.5.0beta21 [April 27, 2010] + Removed some unwanted binary bytes and changed CRLF to NEWLINE in the new + vstudio project files, and some trivial editing of some files in the + scripts directory. + Set PNG_NO_READ_BGR, PNG_NO_IO_STATE, and PNG_NO_TIME_RFC1123 in + contrib/pngminim/decoder/pngusr.h to make a smaller decoder application. + +Version 1.5.0beta22 [April 28, 2010] + Fixed dependencies of GET_INT_32 - it does not require READ_INT_FUNCTIONS + because it has a macro equivalent. + Improved the options.awk script; added an "everything off" option. + Revised contrib/pngminim to use the "everything off" option in pngusr.dfa. + +Version 1.5.0beta23 [April 29, 2010] + Corrected PNG_REMOVED macro to take five arguments. + The macro was documented with two arguments (name,ordinal), however + the symbol checking .dfn files assumed five arguments. The five + argument form seems more useful so it is changed to that. + Corrected PNG_UNKNOWN_CHUNKS_SUPPORTED to PNG_HANDLE_AS_UNKNOWN_SUPPORTED + in gregbook/readpng2.c + Corrected protection of png_get_user_transform_ptr. The API declaration in + png.h is removed if both READ and WRITE USER_TRANSFORM are turned off + but was left defined in pngtrans.c + Added logunsupported=1 to cause pnglibconf.h to document disabled options. + This makes the installed pnglibconf.h more readable but causes no + other change. The intention is that users of libpng will find it + easier to understand if an API they need is missing. + Include png_reset_zstream() in png.c only when PNG_READ_SUPPORTED is defined. + Removed dummy_inflate.c from contrib/pngminim/encoder + Removed contrib/pngminim/*/gather.sh; gathering is now done in the makefile. + +Version 1.5.0beta24 [May 7, 2010] + Use bitwise "&" instead of arithmetic mod in pngrutil.c calculation of the + offset of the png_ptr->rowbuf pointer into png_ptr->big_row_buf. + Added more blank lines for readability. + +Version 1.5.0beta25 [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.5.0beta26 [June 18, 2010] + In pngpread.c: png_push_process_row() add check for too many rows. + +Version 1.5.0beta27 [June 18, 2010] + Removed the check added in beta25 as it is now redundant. + +Version 1.5.0beta28 [June 20, 2010] + Rewrote png_process_IDAT_data to consistently treat extra data as warnings + and handle end conditions more cleanly. + Removed the new (beta26) check in png_push_process_row(). + +Version 1.5.0beta29 [June 21, 2010] + Revised scripts/options.awk to work on Sunos (but still doesn't work) + Added comment to options.awk and contrib/pngminim/*/makefile to try nawk. + +Version 1.5.0beta30 [June 22, 2010] + Stop memory leak when reading a malformed sCAL chunk. + +Version 1.5.0beta31 [June 26, 2010] + Revised pngpread.c patch of beta28 to avoid an endless loop. + Removed some trailing blanks. + +Version 1.5.0beta32 [June 26, 2010] + Removed leftover scripts/options.patch and scripts/options.rej + +Version 1.5.0beta33 [July 6, 3010] + Made FIXED and FLOATING options consistent in the APIs they enable and + disable. Corrected scripts/options.awk to handle both command line + options and options specified in the .dfa files. + Changed char *msg to PNG_CONST char *msg in pngrutil.c + Make png_set_sRGB_gAMA_and_cHRM set values using either the fixed or + floating point APIs, but not both. + Reversed patch to remove error handler when the jmp_buf is stored in the + main program structure, not the png_struct. + The error handler is needed because the default handler in libpng will + always use the jmp_buf in the library control structure; this is never + set. The gregbook code is a useful example because, even though it + uses setjmp/longjmp, it shows how error handling can be implemented + using control mechanisms not directly supported by libpng. The + technique will work correctly with mechanisms such as Microsoft + Structure Exceptions or C++ exceptions (compiler willing - note that gcc + does not by default support interworking of C and C++ error handling.) + Reverted changes to call png_longjmp in contrib/gregbook where it is not + appropriate. If mainprog->jmpbuf is used by setjmp, then png_longjmp + cannot be used. + Changed "extern PNG_EXPORT" to "PNG_EXPORT" in png.h (Jan Nijtmans) + Changed "extern" to "PNG_EXTERN" in pngpriv.h (except for the 'extern "C" {') + +Version 1.5.0beta34 [July 12, 2010] + Put #ifndef PNG_EXTERN, #endif around the define PNG_EXTERN in pngpriv.h + +Version 1.5.0beta35 [July 24, 2010] + Removed some newly-added TAB characters. + Added -DNO_PNG_SNPRINTF to CFLAGS in scripts/makefile.dj2 + Moved the definition of png_snprintf() outside of the enclosing + #ifdef blocks in pngconf.h + +Version 1.5.0beta36 [July 29, 2010] + Patches by John Bowler: + Fixed point APIs are now supported throughout (no missing APIs). + Internal fixed point arithmetic support exists for all internal floating + point operations. + sCAL validates the floating point strings it is passed. + Safe, albeit rudimentary, Watcom support is provided by PNG_API_RULE==2 + Two new APIs exist to get the number of passes without turning on the + PNG_INTERLACE transform and to get the number of rows in the current + pass. + A new test program, pngvalid.c, validates the gamma code. + Errors in the 16-bit gamma correction (overflows) have been corrected. + cHRM chunk testing is done consistently (previously the floating point + API bypassed it, because the test really didn't work on FP, now the test + is performed on the actual values to be stored in the PNG file so it + works in the FP case too.) + Most floating point APIs now simply call the fixed point APIs after + converting the values to the fixed point form used in the PNG file. + The standard headers no longer include zlib.h, which is currently only + required for pngstruct.h and can therefore be internal. + Revised png_get_int_32 to undo the PNG two's complement representation of + negative numbers. + +Version 1.5.0beta37 [July 30, 2010] + Added a typecast in png_get_int_32() in png.h and pngrutil.h to avoid + a compiler warning. + Replaced oFFs 0,0 with oFFs -10,20 in pngtest.png + +Version 1.5.0beta38 [July 31, 2010] + Implemented remaining "_fixed" functions. + Corrected a number of recently introduced warnings mostly resulting from + safe but uncast assignments to shorter integers. Also added a zlib + VStudio release library project because the latest zlib Official Windows + build does not include such a thing. + Revised png_get_int_16() to be similar to png_get_int_32(). + Restored projects/visualc71. + +Version 1.5.0beta39 [August 2, 2010] + VisualC/GCC warning fixes, VisualC build fixes + The changes include support for function attributes in VC in addition to + those already present in GCC - necessary because without these some + warnings are unavoidable. Fixes include signed/unsigned fixes in + pngvalid and checks with gcc -Wall -Wextra -Wunused. + VC requires function attributes on function definitions as well as + declarations, PNG_FUNCTION has been added to enable this and the + relevant function definitions changed. + +Version 1.5.0beta40 [August 6, 2010] + Correct use of _WINDOWS_ in pngconf.h + Removed png_mem_ #defines; they are no longer used. + Added the sRGB chunk to pngtest.png + +Version 1.5.0beta41 [August 11, 2010] + Added the cHRM chunk to pngtest.png + Don't try to use version-script with cygwin/mingw. + Revised contrib/gregbook to work under cygwin/mingw. + +Version 1.5.0beta42 [August 18, 2010] + Add .dll.a to the list of extensions to be symlinked by Makefile.am (Yaakov) + Made all API functions that have const arguments and constant string + literal pointers declare them (John Bowler). + +Version 1.5.0beta43 [August 20, 2010] + Removed spurious tabs, shorten long lines (no source change) + Also added scripts/chkfmt to validate the format of all the files that can + reasonably be validated (it is suggested to run "make distclean" before + checking, because some machine generated files have long lines.) + Reformatted the CHANGES file to be more consistent throughout. + Made changes to address various issues identified by GCC, mostly + signed/unsigned and shortening problems on assignment but also a few + difficult to optimize (for GCC) loops. + Fixed non-GCC fixed point builds. In png.c a declaration was misplaced + in an earlier update. Fixed to declare the auto variables at the head. + Use cexcept.h in pngvalid.c. + +Version 1.5.0beta44 [August 24, 2010] + Updated CMakeLists.txt to use CMAKE_INSTALL_LIBDIR variable; useful for + installing libpng in /usr/lib64 (Funda Wang). + Revised CMakeLists.txt to put the man pages in share/man/man* not man/man* + Revised CMakeLists.txt to make symlinks instead of copies when installing. + Changed PNG_LIB_NAME from pngNN to libpngNN in CMakeLists.txt (Philip Lowman) + Implemented memory checks within pngvalid + Reformatted/rearranged pngvalid.c to assist use of progressive reader. + Check interlaced images in pngvalid + Clarified pngusr.h comments in pnglibconf.dfa + Simplified the pngvalid error-handling code now that cexcept.h is in place. + Implemented progressive reader in pngvalid.c for standard tests + Implemented progressive read in pngvalid.c gamma tests + Turn on progressive reader in pngvalid.c by default and tidy code. + +Version 1.5.0beta45 [August 26, 2010] + Added an explicit make step to projects/vstudio for pnglibconf.h + Also corrected zlib.vcxproj into which Visual Studio had introduced + what it calls an "authoring error". The change to make pnglibconf.h + simply copies the file; in the future it may actually generate the + file from scripts/pnglibconf.dfa as the other build systems do. + Changed pngvalid to work when floating point APIs are disabled + Renamed the prebuilt scripts/pnglibconf.h to scripts/pnglibconf.h.prebuilt + Supply default values for PNG_USER_PRIVATEBUILD and PNG_USER_DLLFNAME_POSTFIX + in pngpriv.h in case the user neglected to define them in their pngusr.h + +Version 1.5.0beta46 [August 28, 2010] + Added new private header files to libpng_sources in CMakeLists.txt + Added PNG_READ_16BIT, PNG_WRITE_16BIT, and PNG_16BIT options. + Added reference to scripts/pnglibconf.h.prebuilt in the visualc71 project. + +Version 1.5.0beta47 [September 11, 2010] + Fixed a number of problems with 64-bit compilation reported by Visual + Studio 2010 (John Bowler). + +Version 1.5.0beta48 [October 4, 2010] + Updated CMakeLists.txt (Philip Lowman). + Revised autogen.sh to recognize and use $AUTOCONF, $AUTOMAKE, $AUTOHEADER, + $AUTOPOINT, $ACLOCAL and $LIBTOOLIZE + Fixed problem with symbols creation in Makefile.am which was assuming that + all versions of ccp write to standard output by default (Martin Banky). The + bug was introduced in libpng-1.2.9beta5. + Removed unused mkinstalldirs. + +Version 1.5.0beta49 [October 8, 2010] + Undid Makefile.am revision of 1.5.0beta48. + +Version 1.5.0beta50 [October 14, 2010] + Revised Makefile.in to account for mkinstalldirs being removed. + Added some "(unsigned long)" typecasts in printf statements in pngvalid.c. + Suppressed a compiler warning in png_handle_sPLT(). + Check for out-of-range text compression mode in png_set_text(). + +Version 1.5.0beta51 [October 15, 2010] + Changed embedded dates to "(PENDING RELEASE) in beta releases (and future + rc releases) to minimize the difference between releases. + +Version 1.5.0beta52 [October 16, 2010] + Restored some of the embedded dates (in png.h, png.c, documentation, etc.) + +Version 1.5.0beta53 [October 18, 2010] + Updated INSTALL to mention using "make maintainer-clean" and to remove + obsolete statement about a custom ltmain.sh + Disabled "color-tests" by default in Makefile.am so it will work with + automake versions earlier than 1.11.1 + Use document name "libpng-manual.txt" instead of "libpng-.txt" + to simplify version differences. + Removed obsolete remarks about setjmp handling from INSTALL. + Revised and renamed the typedef in png.h and png.c that was designed + to catch library and header mismatch. + +Version 1.5.0beta54 [November 10, 2010] + Require 48 bytes, not 64 bytes, for big_row_buf in overflow checks. + Used a consistent structure for the pngget.c functions. + +Version 1.5.0beta55 [November 21, 2010] + Revised png_get_uint_32, png_get_int_32, png_get_uint_16 (Cosmin) + Moved reading of file signature into png_read_sig (Cosmin) + Fixed atomicity of chunk header serialization (Cosmin) + Added test for io_state in pngtest.c (Cosmin) + Added "#!/bin/sh" at the top of contrib/pngminim/*/gather.sh scripts. + Changes to remove gcc warnings (John Bowler) + Certain optional gcc warning flags resulted in warnings in libpng code. + With these changes only -Wconversion and -Wcast-qual cannot be turned on. + Changes are trivial rearrangements of code. -Wconversion is not possible + for pngrutil.c (because of the widespread use of += et al on variables + smaller than (int) or (unsigned int)) and -Wcast-qual is not possible + with pngwio.c and pngwutil.c because the 'write' callback and zlib + compression both fail to declare their input buffers with 'const'. + +Version 1.5.0beta56 [December 7, 2010] + Added the private PNG_UNUSED() macro definition in pngpriv.h. + Added some commentary about PNG_EXPORT in png.h and pngconf.h + Revised PNG_EXPORT() macro and added PNG_EXPORTA() macro, with the + objective of simplifying and improving the cosmetic appearance of png.h. + Fixed some incorrect "=" macro names in pnglibconf.dfa + Included documentation of changes in 1.5.0 from 1.4.x in libpng-manual.txt + +Version 1.5.0beta57 [December 9, 2010] + Documented the pngvalid gamma error summary with additional comments and + print statements. + Improved missing symbol handling in checksym.awk; symbols missing in both + the old and new files can now be optionally ignored, treated as errors + or warnings. + Removed references to pngvcrd.c and pnggccrd.c from the vstudio project. + Updated "libpng14" to "libpng15" in the visualc71 project. + Enabled the strip16 tests in pngvalid.` + Don't display test results (except PASS/FAIL) when running "make test". + Instead put them in pngtest-log.txt + Added "--with-zprefix=" to configure.ac + Updated the prebuilt configuration files to autoconf version 2.68 + +Version 1.5.0beta58 [December 19, 2010] + Fixed interlace image handling and add test cases (John Bowler) + Fixed the clean rule in Makefile.am to remove pngtest-log.txt + Made minor changes to work around warnings in gcc 3.4 + +Version 1.5.0rc01 [December 27, 2010] + No changes. + +Version 1.5.0rc02 [December 27, 2010] + Eliminated references to the scripts/*.def files in project/visualc71. + +Version 1.5.0rc03 [December 28, 2010] + Eliminated scripts/*.def and revised Makefile.am accordingly + +Version 1.5.0rc04 [December 29, 2010] + Fixed bug in background transformation handling in pngrtran.c (it was + looking for the flag in png_ptr->transformations instead of in + png_ptr->flags) (David Raymond). + +Version 1.5.0rc05 [December 31, 2010] + Fixed typo in a comment in CMakeLists.txt (libpng14 => libpng15) (Cosmin) + +Version 1.5.0rc06 [January 4, 2011] + Changed the new configure option "zprefix=string" to "zlib-prefix=string" + +Version 1.5.0rc07 [January 4, 2011] + Updated copyright year. + +Version 1.5.0 [January 6, 2011] + No changes. + +version 1.5.1beta01 [January 8, 2011] + Added description of png_set_crc_action() to the manual. + Added a note in the manual that the type of the iCCP profile was changed + from png_charpp to png_bytepp in png_get_iCCP(). This change happened + in version 1.5.0beta36 but is not noted in the CHANGES. Similarly, + it was changed from png_charpp to png_const_bytepp in png_set_iCCP(). + Ensure that png_rgb_to_gray ignores palette mapped images, if libpng + internally happens to call it with one, and fixed a failure to handle + palette mapped images correctly. This fixes CVE-2690. + +Version 1.5.1beta02 [January 14, 2011] + Fixed a bug in handling of interlaced images (bero at arklinux.org). + Updated CMakeLists.txt (Clifford Yapp) + +Version 1.5.1beta03 [January 14, 2011] + Fixed typecasting of some png_debug() statements (Cosmin) + +Version 1.5.1beta04 [January 16, 2011] + Updated documentation of png_set|get_tRNS() (Thomas Klausner). + Mentioned in the documentation that applications must #include "zlib.h" + if they need access to anything in zlib.h, and that a number of + macros such as png_memset() are no longer accessible by applications. + Corrected pngvalid gamma test "sample" function to access all of the color + samples of each pixel, instead of sampling the red channel three times. + Prefixed variable names index, div, exp, gamma with "png_" to avoid "shadow" + warnings, and (mistakenly) changed png_exp() to exp(). + +Version 1.5.1beta05 [January 16, 2011] + Changed variable names png_index, png_div, png_exp, and png_gamma to + char_index, divisor, exp_b10, and gamma_val, respectively, and + changed exp() back to png_exp(). + +Version 1.5.1beta06 [January 20, 2011] + Prevent png_push_crc_skip() from hanging while reading an unknown chunk + or an over-large compressed zTXt chunk with the progressive reader. + Eliminated more GCC "shadow" warnings. + Revised png_fixed() in png.c to avoid compiler warning about reaching the + end without returning anything. + +Version 1.5.1beta07 [January 22, 2011] + In the manual, describe the png_get_IHDR() arguments in the correct order. + Added const_png_structp and const_png_infop types, and used them in + prototypes for most png_get_*() functions. + +Version 1.5.1beta08 [January 23, 2011] + Added png_get_io_chunk_type() and deprecated png_get_io_chunk_name() + Added synopses for the IO_STATE functions and other missing synopses + to the manual. Removed the synopses from libpngpf.3 because they + were out of date and no longer useful. Better information can be + obtained by reading the prototypes and comments in pngpriv.h + Attempted to fix cpp on Solaris with S. Studio 12 cc, fix build + Added a make macro DFNCPP that is a CPP that will accept the tokens in + a .dfn file and adds configure stuff to test for such a CPP. ./configure + should fail if one is not available. + Corrected const_png_ in png.h to png_const_ to avoid polluting the namespace. + Added png_get_current_row_number and png_get_current_pass_number for the + benefit of the user transform callback. + Added png_process_data_pause and png_process_data_skip for the benefit of + progressive readers that need to stop data processing or want to optimize + skipping of unread data (e.g., if the reader marks a chunk to be skipped.) + +Version 1.5.1beta09 [January 24, 2011] + Enhanced pngvalid, corrected an error in gray_to_rgb, corrected doc error. + pngvalid contains tests of transforms, which tests are currently disabled + because they are incompletely tested. gray_to_rgb was failing to expand + the bit depth for smaller bit depth images; this seems to be a long + standing error and resulted, apparently, in invalid output + (CVE-2011-0408, CERT VU#643140). The documentation did not accurately + describe what libpng really does when converting RGB to gray. + +Version 1.5.1beta10 [January 27, 2010] + Fixed incorrect examples of callback prototypes in the manual, that were + introduced in libpng-1.0.0. + In addition the order of the png_get_uint macros with respect to the + relevant function definitions has been reversed. This helps the + preprocessing of the symbol files be more robust. Furthermore, the + symbol file preprocessing now uses -DPNG_NO_USE_READ_MACROS even when + the library may actually be built with PNG_USE_READ_MACROS; this stops + the read macros interfering with the symbol file format. + Made the manual, synopses, and function prototypes use the function + argument names file_gamma, int_file_gamma, and srgb_intent consistently. + +Version 1.5.1beta11 [January 28, 2011] + Changed PNG_UNUSED from "param=param;" to "{if(param){}}". + Corrected local variable type in new API png_process_data_skip() + The type was self-evidently incorrect but only causes problems on 64-bit + architectures. + Added transform tests to pngvalid and simplified the arguments. + +Version 1.5.1rc01 [January 29, 2011] + No changes. + +Version 1.5.1rc02 [January 31, 2011] + Added a request in the manual that applications do not use "png_" or + "PNG_" to begin any of their own symbols. + Changed PNG_UNUSED to "(void)param;" and updated the commentary in pngpriv.h + +Version 1.5.1 [February 3, 2011] + No changes. + +Version 1.5.2beta01 [February 13, 2011] + More -Wshadow fixes for older gcc compilers. Older gcc versions apparently + check formal parameters names in function declarations (as well as + definitions) to see if they match a name in the global namespace. + Revised PNG_EXPORTA macro to not use an empty parameter, to accommodate the + old VisualC++ preprocessor. + Turned on interlace handling in png_read_png(). + Fixed gcc pendantic warnings. + Handle longjmp in Cygwin. + Fixed png_get_current_row_number() in the interlaced case. + Cleaned up ALPHA flags and transformations. + Implemented expansion to 16 bits. + +Version 1.5.2beta02 [February 19, 2011] + Fixed mistake in the descriptions of user read_transform and write_transform + function prototypes in the manual. The row_info struct is png_row_infop. + Reverted png_get_current_row_number() to previous (1.5.2beta01) behavior. + Corrected png_get_current_row_number documentation + Fixed the read/write row callback documentation. + This documents the current behavior, where the callback is called after + every row with information pertaining to the next row. + +Version 1.5.2beta03 [March 3, 2011] + Fixed scripts/makefile.vcwin32 + Updated contrib/pngsuite/README to add the word "modify". + Define PNG_ALLOCATED to blank when _MSC_VER<1300. + +Version 1.5.2rc01 [March 19, 2011] + Define remaining attributes to blank when MSC_VER<1300. + ifdef out mask arrays in pngread.c when interlacing is not supported. + +Version 1.5.2rc02 [March 22, 2011] + Added a hint to try CPP=/bin/cpp if "cpp -E" fails in scripts/pnglibconf.mak + and in contrib/pngminim/*/makefile, eg., on SunOS 5.10, and removed "strip" + from the makefiles. + Fixed a bug (present since libpng-1.0.7) that makes png_handle_sPLT() fail + to compile when PNG_NO_POINTER_INDEXING is defined (Chubanov Kirill) + +Version 1.5.2rc03 [March 24, 2011] + Don't include standard header files in png.h while building the symbol table, + to avoid cpp failure on SunOS (introduced PNG_BUILDING_SYMBOL_TABLE macro). + +Version 1.5.2 [March 31, 2011] + No changes. + +Version 1.5.3beta01 [April 1, 2011] + Re-initialize the zlib compressor before compressing non-IDAT chunks. + Added API functions (png_set_text_compression_level() and four others) to + set parameters for zlib compression of non-IDAT chunks. + +Version 1.5.3beta02 [April 3, 2011] + Updated scripts/symbols.def with new API functions. + Only compile the new zlib re-initializing code when text or iCCP is + supported, using PNG_WRITE_COMPRESSED_TEXT_SUPPORTED macro. + Improved the optimization of the zlib CMF byte (see libpng-1.2.6beta03). + Optimize the zlib CMF byte in non-IDAT compressed chunks + +Version 1.5.3beta03 [April 16, 2011] + Fixed gcc -ansi -pedantic compile. A strict ANSI system does not have + snprintf, and the "__STRICT_ANSI__" detects that condition more reliably + than __STDC__ (John Bowler). + Removed the PNG_PTR_NORETURN attribute because it too dangerous. It tells + the compiler that a user supplied callback (the error handler) does not + return, yet there is no guarantee in practice that the application code + will correctly implement the error handler because the compiler only + issues a warning if there is a mistake (John Bowler). + Removed the no-longer-used PNG_DEPSTRUCT macro. + Updated the zlib version to 1.2.5 in the VStudio project. + Fixed 64-bit builds where png_uint_32 is smaller than png_size_t in + pngwutil.c (John Bowler). + Fixed bug with stripping the filler or alpha channel when writing, that + was introduced in libpng-1.5.2beta01 (bug report by Andrew Church). + +Version 1.5.3beta04 [April 27, 2011] + Updated pngtest.png with the new zlib CMF optimization. + Cleaned up conditional compilation code and of background/gamma handling + Internal changes only except a new option to avoid compiling the + png_build_grayscale_palette API (which is not used at all internally.) + The main change is to move the transform tests (READ_TRANSFORMS, + WRITE_TRANSFORMS) up one level to the caller of the APIs. This avoids + calls to spurious functions if all transforms are disabled and slightly + simplifies those functions. Pngvalid modified to handle this. + A minor change is to stop the strip_16 and expand_16 interfaces from + disabling each other; this allows the future alpha premultiplication + code to use 16-bit intermediate values while still producing 8-bit output. + png_do_background and png_do_gamma have been simplified to take a single + pointer to the png_struct rather than pointers to every item required + from the png_struct. This makes no practical difference to the internal + code. + A serious bug in the pngvalid internal routine 'standard_display_init' has + been fixed - this failed to initialize the red channel and accidentally + initialized the alpha channel twice. + Changed png_struct jmp_buf member name from png_jmpbuf to tmp_jmpbuf to + avoid a possible clash with the png_jmpbuf macro on some platforms. + +Version 1.5.3beta05 [May 6, 2011] + Added the "_POSIX_SOURCE" feature test macro to ensure libpng sees the + correct API. _POSIX_SOURCE is defined in pngpriv.h, pngtest.c and + pngvalid.c to ensure that POSIX conformant systems disable non-POSIX APIs. + Removed png_snprintf and added formatted warning messages. This change adds + internal APIs to allow png_warning messages to have parameters without + requiring the host OS to implement snprintf. As a side effect the + dependency of the tIME-supporting RFC1132 code on stdio is removed and + PNG_NO_WARNINGS does actually work now. + Pass "" instead of '\0' to png_default_error() in png_err(). This mistake + was introduced in libpng-1.2.20beta01. This fixes CVE-2011-2691. + Added PNG_WRITE_OPTIMIZE_CMF_SUPPORTED macro to make the zlib "CMF" byte + optimization configureable. + IDAT compression failed if preceded by a compressed text chunk (bug + introduced in libpng-1.5.3beta01-02). This was because the attempt to + reset the zlib stream in png_write_IDAT happened after the first IDAT + chunk had been deflated - much too late. In this change internal + functions were added to claim/release the z_stream and, hopefully, make + the code more robust. Also deflateEnd checking is added - previously + libpng would ignore an error at the end of the stream. + +Version 1.5.3beta06 [May 8, 2011] + Removed the -D_ALL_SOURCE from definitions for AIX in CMakeLists.txt + Implemented premultiplied alpha support: png_set_alpha_mode API + +Version 1.5.3beta07 [May 11, 2011] + Added expand_16 support to the high level interface. + Added named value and 'flag' gamma support to png_set_gamma. Made a minor + change from the previous (unreleased) ABI/API to hide the exact value used + for Macs - it's not a good idea to embed this in the ABI! + Moved macro definitions for PNG_HAVE_IHDR, PNG_HAVE_PLTE, and PNG_AFTER_IDAT + from pngpriv.h to png.h because they must be visible to applications + that call png_set_unknown_chunks(). + Check for up->location !PNG_AFTER_IDAT when writing unknown chunks + before IDAT. + +Version 1.5.3beta08 [May 16, 2011] + Improved "pngvalid --speed" to exclude more of pngvalid from the time. + Documented png_set_alpha_mode(), other changes in libpng.3/libpng-manual.txt + The cHRM chunk now sets the defaults for png_set_rgb_to_gray() (when negative + parameters are supplied by the caller), while in the absence of cHRM + sRGB/Rec 709 values are still used. This introduced a divide-by-zero + bug in png_handle_cHRM(). + The bKGD chunk no longer overwrites the background value set by + png_set_background(), allowing the latter to be used before the file + header is read. It never performed any useful function to override + the default anyway. + Added memory overwrite and palette image checks to pngvalid.c + Previously palette image code was poorly checked. Since the transformation + code has a special palette path in most cases this was a severe weakness. + Minor cleanup and some extra checking in pngrutil.c and pngrtran.c. When + expanding an indexed image, always expand to RGBA if transparency is + present. + +Version 1.5.3beta09 [May 17, 2011] + Reversed earlier 1.5.3 change of transformation order; move png_expand_16 + back where it was. The change doesn't work because it requires 16-bit + gamma tables when the code only generates 8-bit ones. This fails + silently; the libpng code just doesn't do any gamma correction. Moving + the tests back leaves the old, inaccurate, 8-bit gamma calculations, but + these are clearly better than none! + +Version 1.5.3beta10 [May 20, 2011] + + png_set_background() and png_expand_16() did not work together correctly. + This problem is present in 1.5.2; if png_set_background is called with + need_expand false and the matching 16 bit color libpng erroneously just + treats it as an 8-bit color because of where png_do_expand_16 is in the + transform list. This simple fix reduces the supplied colour to 8-bits, + so it gets smashed, but this is better than the current behavior. + Added tests for expand16, more fixes for palette image tests to pngvalid. + Corrects the code for palette image tests and disables attempts to + validate palette colors. + +Version 1.5.3rc01 [June 3, 2011] + No changes. + +Version 1.5.3rc02 [June 8, 2011] + Fixed uninitialized memory read in png_format_buffer() (Bug report by + Frank Busse, CVE-2011-2501, related to CVE-2004-0421). + +Version 1.5.3beta11 [June 11, 2011] + Fixed png_handle_sCAL which is broken in 1.5. This fixes CVE 2011-2692. + Added sCAL to pngtest.png + Revised documentation about png_set_user_limits() to say that it also affects + png writing. + Revised handling of png_set_user_limits() so that it can increase the + limit beyond the PNG_USER_WIDTH|HEIGHT_MAX; previously it could only + reduce it. + Make the 16-to-8 scaling accurate. Dividing by 256 with no rounding is + wrong (high by one) 25% of the time. Dividing by 257 with rounding is + wrong in 128 out of 65536 cases. Getting the right answer all the time + without division is easy. + Added "_SUPPORTED" to the PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION macro. + Added projects/owatcom, an IDE project for OpenWatcom to replace + scripts/makefile.watcom. This project works with OpenWatcom 1.9. The + IDE autogenerates appropriate makefiles (libpng.mk) for batch processing. + The project is configurable, unlike the Visual Studio project, so long + as the developer has an awk. + Changed png_set_gAMA to limit the gamma value range so that the inverse + of the stored value cannot overflow the fixed point representation, + and changed other things OpenWatcom warns about. + Revised pngvalid.c to test PNG_ALPHA_MODE_SUPPORTED correctly. This allows + pngvalid to build when ALPHA_MODE is not supported, which is required if + it is to build on libpng 1.4. + Removed string/memory macros that are no longer used and are not + necessarily fully supportable, particularly png_strncpy and png_snprintf. + Added log option to pngvalid.c and attempted to improve gamma messages. + +Version 1.5.3 [omitted] + People found the presence of a beta release following an rc release + to be confusing; therefore we bump the version to libpng-1.5.4beta01 + and there will be no libpng-1.5.3 release. + +Version 1.5.4beta01 [June 14, 2011] + Made it possible to undefine PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED + to get the same (inaccurate) output as libpng-1.5.2 and earlier. + Moved definitions of PNG_HAVE_IHDR, PNG_AFTER_IDAT, and PNG_HAVE_PLTE + outside of an unknown-chunk block in png.h because they are also + needed for other uses. + +Version 1.5.4beta02 [June 14, 2011] + Fixed and clarified LEGACY 16-to-8 scaling code. + Added png_set_chop_16() API, to match inaccurate results from previous + libpng versions. + Removed the ACCURATE and LEGACY options (they are no longer useable) + Use the old scaling method for background if png_set_chop_16() was + called. + Made png_set_chop_16() API removeable by disabling PNG_CHOP_16_TO_8_SUPPORTED + +Version 1.5.4beta03 [June 15, 2011] + Fixed a problem in png_do_expand_palette() exposed by optimization in + 1.5.3beta06 + Also removed a spurious and confusing "trans" member ("trans") from png_info. + The palette expand optimization prevented expansion to an intermediate RGBA + form if tRNS was present but alpha was marked to be stripped; this exposed + a check for tRNS in png_do_expand_palette() which is inconsistent with the + code elsewhere in libpng. + Correction to the expand_16 code; removed extra instance of + png_set_scale_16_to_8 from pngpriv.h + +Version 1.5.4beta04 [June 16, 2011] + Added a missing "#ifdef PNG_READ_BACKGROUND_SUPPORTED/#endif" in pngrtran.c + Added PNG_TRANSFORM_CHOP_16 to the high-level read transforms. + Made PNG_READ_16_TO_8_ACCURATE_SCALE configurable again. If this is + not enabled, png_set_strip_16() and png_do_scale_16_to_8() aren't built. + Revised contrib/visupng, gregbook, and pngminim to demonstrate chop_16_to_8 + +Version 1.5.4beta05 [June 16, 2011] + Renamed png_set_strip_16() to png_set_scale_16() and renamed + png_set_chop_16() to png_set_strip(16) in an attempt to minimize the + behavior changes between libpng14 and libpng15. + +Version 1.5.4beta06 [June 18, 2011] + Fixed new bug that was causing both strip_16 and scale_16 to be applied. + +Version 1.5.4beta07 [June 19, 2011] + Fixed pngvalid, simplified macros, added checking for 0 in sCAL. + The ACCURATE scale macro is no longer defined in 1.5 - call the + png_scale_16_to_8 API. Made sure that PNG_READ_16_TO_8 is still defined + if the png_strip_16_to_8 API is present. png_check_fp_number now + maintains some state so that positive, negative and zero values are + identified. sCAL uses these to be strictly spec conformant. + +Version 1.5.4beta08 [June 23, 2011] + Fixed pngvalid if ACCURATE_SCALE is defined. + Updated scripts/pnglibconf.h.prebuilt. + +Version 1.5.4rc01 [June 30, 2011] + Define PNG_ALLOCATED to "restrict" only if MSC_VER >= 1400. + +Version 1.5.4 [July 7, 2011] + No changes. + +Version 1.5.5beta01 [July 13, 2011] + Fixed some typos and made other minor changes in the manual. + Updated contrib/pngminus/makefile.std (Samuli Souminen) + +Version 1.5.5beta02 [July 14, 2011] + Revised Makefile.am and Makefile.in to look in the right directory for + pnglibconf.h.prebuilt + +Version 1.5.5beta03 [July 27, 2011] + Enabled compilation with g++ compiler. This compiler does not recognize + the file extension, so it always compiles with C++ rules. Made minor + changes to pngrutil.c to cast results where C++ expects it but C does not. + Minor editing of libpng.3 and libpng-manual.txt. + +Version 1.5.5beta04 [July 29, 2011] + Revised CMakeLists.txt (Clifford Yapp) + Updated commentary about the png_rgb_to_gray() default coefficients + in the manual and in pngrtran.c + +Version 1.5.5beta05 [August 17, 2011] + Prevent unexpected API exports from non-libpng DLLs on Windows. The "_DLL" + is removed from the test of whether a DLL is being built (this erroneously + caused the libpng APIs to be marked as DLL exports in static builds under + Microsoft Visual Studio). Almost all of the libpng building configuration + is moved from pngconf.h to pngpriv.h, but PNG_DLL_EXPORT remains in + pngconf.h, though, so that it is colocated with the import definition (it + is no longer used anywhere in the installed headers). The VStudio project + definitions have been cleaned up: "_USRDLL" has been removed from the + static library builds (this was incorrect), and PNG_USE_DLL has been added + to pngvalid to test the functionality (pngtest does not supply it, + deliberately). The spurious "_EXPORTS" has been removed from the + libpng build (all these errors were a result of copy/paste between project + configurations.) + Added new types and internal functions for CIE RGB end point handling to + pngpriv.h (functions yet to be implemented). + +Version 1.5.5beta06 [August 26, 2011] + Ensure the CMAKE_LIBRARY_OUTPUT_DIRECTORY is set in CMakeLists.txt + (Clifford Yap) + Fixes to rgb_to_gray and cHRM XYZ APIs (John Bowler): + The rgb_to_gray code had errors when combined with gamma correction. + Some pixels were treated as true grey when they weren't and such pixels + and true grey ones were not gamma corrected (the original value of the + red component was used instead). APIs to get and set cHRM using color + space end points have been added and the rgb_to_gray code that defaults + based on cHRM, and the divide-by-zero bug in png_handle_cHRM (CERT + VU#477046, CVE-2011-3328, introduced in 1.5.4) have been corrected. + A considerable number of tests has been added to pngvalid for the + rgb_to_gray transform. + Arithmetic errors in rgb_to_gray whereby the calculated gray value was + truncated to the bit depth rather than rounded have been fixed except in + the 8-bit non-gamma-corrected case (where consistency seems more important + than correctness.) The code still has considerable inaccuracies in the + 8-bit case because 8-bit linear arithmetic is used. + +Version 1.5.5beta07 [September 7, 2011] + Added "$(ARCH)" option to makefile.darwin + Added SunOS support to configure.ac and Makefile.am + Changed png_chunk_benign_error() to png_warning() in png.c, in + png_XYZ_from_xy_checked(). + +Version 1.5.5beta08 [September 10, 2011] + Fixed 64-bit compilation errors (gcc). The errors fixed relate + to conditions where types that are 32 bits in the GCC 32-bit + world (uLong and png_size_t) become 64 bits in the 64-bit + world. This produces potential truncation errors which the + compiler correctly flags. + Relocated new HAVE_SOLARIS_LD definition in configure.ac + Constant changes for 64-bit compatibility (removal of L suffixes). The + 16-bit cases still use "L" as we don't have a 16-bit test system. + +Version 1.5.5rc01 [September 15, 2011] + Removed "L" suffixes in pngpriv.h + +Version 1.5.5 [September 22, 2011] + No changes. + +Version 1.5.6beta01 [September 22, 2011] + Fixed some 64-bit type conversion warnings in pngrtran.c + Moved row_info from png_struct to a local variable. + The various interlace mask arrays have been made into arrays of + bytes and made PNG_CONST and static (previously some arrays were + marked PNG_CONST and some weren't). + Additional checks have been added to the transform code to validate the + pixel depths after the transforms on both read and write. + Removed some redundant code from pngwrite.c, in png_destroy_write_struct(). + Changed chunk reading/writing code to use png_uint_32 instead of png_byte[4]. + This removes the need to allocate temporary strings for chunk names on + the stack in the read/write code. Unknown chunk handling still uses the + string form because this is exposed in the API. + +Version 1.5.6beta02 [September 26, 2011] + Added a note in the manual the png_read_update_info() must be called only + once with a particular info_ptr. + Fixed a typo in the definition of the new PNG_STRING_FROM_CHUNK(s,c) macro. + +Version 1.5.6beta03 [September 28, 2011] + Revised test-pngtest.sh to report FAIL when pngtest fails. + Added "--strict" option to pngtest, to report FAIL when the failure is + only because the resulting valid files are different. + Revised CMakeLists.txt to work with mingw and removed some material from + CMakeLists.txt that is no longer useful in libpng-1.5. + +Version 1.5.6beta04 [October 5, 2011] + Fixed typo in Makefile.in and Makefile.am ("-M Wl" should be "-M -Wl")." + +Version 1.5.6beta05 [October 12, 2011] + Speed up png_combine_row() for interlaced images. This reduces the generality + of the code, allowing it to be optimized for Adam7 interlace. The masks + passed to png_combine_row() are now generated internally, avoiding + some code duplication and localizing the interlace handling somewhat. + Align png_struct::row_buf - previously it was always unaligned, caused by + a bug in the code that attempted to align it; the code needs to subtract + one from the pointer to take account of the filter byte prepended to + each row. + Optimized png_combine_row() when rows are aligned. This gains a small + percentage for 16-bit and 32-bit pixels in the typical case where the + output row buffers are appropriately aligned. The optimization was not + previously possible because the png_struct buffer was always misaligned. + Fixed bug in png_write_chunk_header() debug print, introduced in 1.5.6beta01. + +Version 1.5.6beta06 [October 17, 2011] + Removed two redundant tests for unitialized row. + Fixed a relatively harmless memory overwrite in compressed text writing + with a 1 byte zlib buffer. + Add ability to call png_read_update_info multiple times to pngvalid.c. + Fixes for multiple calls to png_read_update_info. These fixes attend to + most of the errors revealed in pngvalid, however doing the gamma work + twice results in inaccuracies that can't be easily fixed. There is now + a warning in the code if this is going to happen. + Turned on multiple png_read_update_info in pngvalid transform tests. + Prevent libpng from overwriting unused bits at the end of the image when + it is not byte aligned, while reading. Prior to libpng-1.5.6 libpng would + overwrite the partial byte at the end of each row if the row width was not + an exact multiple of 8 bits and the image is not interlaced. + +Version 1.5.6beta07 [October 21, 2011] + Made png_ptr->prev_row an aligned pointer into png_ptr->big_prev_row + (Mans Rullgard). + +Version 1.5.6rc01 [October 26, 2011] + Changed misleading "Missing PLTE before cHRM" warning to "Out of place cHRM" + +Version 1.5.6rc02 [October 27, 2011] + Added LSR() macro to defend against buggy compilers that evaluate non-taken + code branches and complain about out-of-range shifts. + +Version 1.5.6rc03 [October 28, 2011] + Renamed the LSR() macro to PNG_LSR() and added PNG_LSL() macro. + Fixed compiler warnings with Intel and MSYS compilers. The logical shift + fix for Microsoft Visual C is required by other compilers, so this + enables that fix for all compilers when using compile-time constants. + Under MSYS 'byte' is a name declared in a system header file, so we + changed the name of a local variable to avoid the warnings that result. + Added #define PNG_ALIGN_TYPE PNG_ALIGN_NONE to contrib/pngminim/*/pngusr.h + +Version 1.5.6 [November 3, 2011] + No changes. + +Version 1.5.7beta01 [November 4, 2011] + Added support for ARM processor (Mans Rullgard) + Fixed bug in pngvalid on early allocation failure; fixed type cast in + pngmem.c; pngvalid would attempt to call png_error() if the allocation + of a png_struct or png_info failed. This would probably have led to a + crash. The pngmem.c implementation of png_malloc() included a cast + to png_size_t which would fail on large allocations on 16-bit systems. + Fix for the preprocessor of the Intel C compiler. The preprocessor + splits adjacent @ signs with a space; this changes the concatentation + token from @-@-@ to PNG_JOIN; that should work with all compiler + preprocessors. + Paeth filter speed improvements from work by Siarhei Siamashka. This + changes the 'Paeth' reconstruction function to improve the GCC code + generation on x86. The changes are only part of the suggested ones; + just the changes that definitely improve speed and remain simple. + The changes also slightly increase the clarity of the code. + +Version 1.5.7beta02 [November 11, 2011] + Check compression_type parameter in png_get_iCCP and remove spurious + casts. The compression_type parameter is always assigned to, so must + be non-NULL. The cast of the profile length potentially truncated the + value unnecessarily on a 16-bit int system, so the cast of the (byte) + compression type to (int) is specified by ANSI-C anyway. + Fixed FP division by zero in pngvalid.c; the 'test_pixel' code left + the sBIT fields in the test pixel as 0, which resulted in a floating + point division by zero which was irrelevant but causes systems where + FP exceptions cause a crash. Added code to pngvalid to turn on FP + exceptions if the appropriate glibc support is there to ensure this is + tested in the future. + Updated scripts/pnglibconf.mak and scripts/makefile.std to handle the + new PNG_JOIN macro. + Added versioning to pnglibconf.h comments. + Simplified read/write API initial version; basic read/write tested on + a variety of images, limited documentation (in the header file.) + Installed more accurate linear to sRGB conversion tables. The slightly + modified tables reduce the number of 16-bit values that + convert to an off-by-one 8-bit value. The "makesRGB.c" code that was used + to generate the tables is now in a contrib/sRGBtables sub-directory. + +Version 1.5.7beta03 [November 17, 2011] + Removed PNG_CONST from the sRGB table declarations in pngpriv.h and png.c + Added run-time detection of NEON support. + Added contrib/libtests; includes simplified API test and timing test and + a color conversion utility for rapid checking of failed 'pngstest' results. + Multiple transform bug fixes plus a work-round for double gamma correction. + libpng does not support more than one transform that requires linear data + at once - if this is tried typically the results is double gamma + correction. Since the simplified APIs can need rgb to gray combined with + a compose operation it is necessary to do one of these outside the main + libpng transform code. This check-in also contains fixes to various bugs + in the simplified APIs themselves and to some bugs in compose and rgb to + gray (on palette) itself. + Fixes for C++ compilation using g++ When libpng source is compiled + using g++. The compiler imposes C++ rules on the C source; thus it + is desireable to make the source work with either C or C++ rules + without throwing away useful error information. This change adds + png_voidcast to allow C semantic (void*) cases or the corresponding + C++ static_cast operation, as appropriate. + Added --noexecstack to assembler file compilation. GCC does not set + this on assembler compilation, even though it does on C compilation. + This creates security issues if assembler code is enabled; the + work-around is to set it by default in the flags for $(CCAS) + Work around compilers that don't support declaration of const data. Some + compilers fault 'extern const' data declarations (because the data is + not initialized); this turns on const-ness only for compilers where + this is known to work. + +Version 1.5.7beta04 [November 17, 2011] + Since the gcc driver does not recognize the --noexecstack flag, we must + use the -Wa prefix to have it passed through to the assembler. + Also removed a duplicate setting of this flag. + Added files that were omitted from the libpng-1.5.7beta03 zip distribution. + +Version 1.5.7beta05 [November 25, 2011] + Removed "zTXt" from warning in generic chunk decompression function. + Validate time settings passed to pngset() and png_convert_to_rfc1123() + (Frank Busse). + Added MINGW support to CMakeLists.txt + Reject invalid compression flag or method when reading the iTXt chunk. + Backed out 'simplified' API changes. The API seems too complex and there + is a lack of consensus or enthusiasm for the proposals. The API also + reveals significant bugs inside libpng (double gamma correction and the + known bug of being unable to retrieve a corrected palette). It seems + better to wait until the bugs, at least, are corrected. + Moved pngvalid.c into contrib/libtests + Rebuilt Makefile.in, configure, etc., with autoconf-2.68 + +Version 1.5.7rc01 [December 1, 2011] + Replaced an "#if" with "#ifdef" in pngrtran.c + Revised #if PNG_DO_BC block in png.c (use #ifdef and add #else) + +Version 1.5.7rc02 [December 5, 2011] + Revised project files and contrib/pngvalid/pngvalid.c to account for + the relocation of pngvalid into contrib/libtests. + Revised pngconf.h to use " __declspec(restrict)" only when MSC_VER >= 1400, + as in libpng-1.5.4. + Put CRLF line endings in the owatcom project files. + +Version 1.5.7rc03 [December 7, 2011] + Updated CMakeLists.txt to account for the relocation of pngvalid.c + +Version 1.5.7 [December 15, 2011] + Minor fixes to pngvalid.c for gcc 4.6.2 compatibility to remove warnings + reported by earlier versions. + +Version 1.5.8beta01 [January 15, 2011] + Removed '#include config.h"' from contrib/libtests/pngvalid.c. It's not + needed and causes trouble for VPATH building. + Moved AC_MSG_CHECKING([if libraries can be versioned]) later to the proper + location in configure.ac (Gilles Espinasse). + Fix bug in pngerror.c: some long warnings were being improperly truncated + (CVE-2011-3464, bug introduced in libpng-1.5.3beta05). + +Version 1.5.8rc01 [January 21, 2012] + No changes. + +Version 1.5.8rc02 [January 25, 2012] + Fixed Min/GW uninstall to remove libpng.dll.a + Conditionalize the install rules for MINGW and CYGWIN in CMakeLists.txt + +Version 1.5.8 [February 1, 2012] + No changes. + +Version 1.5.9beta01 [February 3, 2012] + Rebuilt configure scripts in the tar distributions. + +Version 1.5.9beta02 [February 16, 2012] + Removed two unused definitions from scripts/pnglibconf.h.prebuilt + Removed some unused arrays (with #ifdef) from png_read_push_finish_row(). + Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h + +Version 1.5.9rc01 [February 17, 2012] + Fixed CVE-2011-3026 buffer overrun bug. Deal more correctly with the test + on iCCP chunk length. Also removed spurious casts that may hide problems + on 16-bit systems. + +Version 1.5.9 [February 18, 2012] + No changes. + +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/plugins/FreeImage/src/LibPNG/INSTALL b/plugins/FreeImage/src/LibPNG/INSTALL new file mode 100644 index 0000000000..c2d6c9e24a --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/INSTALL @@ -0,0 +1,135 @@ + +Installing libpng + +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. To be really sure that you aren't using any of the included +pre-built scripts, you can do this: + + ./configure --enable-maintainer-mode + make maintainer-clean + ./autogen.sh + ./configure [--prefix=/path] [other options] + make + make install + make check + +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-x.y.z" or "libpngNN" and "zlib-1.2.5" +or "zlib125") 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, libpng.pc.in, + libpng-config.in, aclocal.m4, config.h.in, config.sub, + depcomp, install-sh, mkinstalldirs, test-pngtest.sh + contrib + gregbook + pngminim + pngminus + pngsuite + visupng + projects + visualc71 + vstudio + scripts + makefile.* + *.def (module definition files) + etc. + 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 pnglibconf.dfa 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". + +Further information can be found in the README and libpng-manual.txt +files, in the individual makefiles, in png.h, and the manual pages +libpng.3 and png.5. diff --git a/plugins/FreeImage/src/LibPNG/KNOWNBUG b/plugins/FreeImage/src/LibPNG/KNOWNBUG new file mode 100644 index 0000000000..f3ddc5245f --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/KNOWNBUG @@ -0,0 +1,29 @@ + +Known bugs in libpng version 1.2.43 + +1. December 4, 2009: The PNG_NO_ERROR_NUMBERS macro was inadvertently + defined in libpng-1.2.41/pngconf.h, which may cause a problem with + building a binary-compatible library. + + STATUS: This will be fixed in libpng-1.2.42. In the meantime, simply + delete the definition from line : + +2. 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. + +3. 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. + +4. 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/plugins/FreeImage/src/LibPNG/LICENSE b/plugins/FreeImage/src/LibPNG/LICENSE new file mode 100644 index 0000000000..0c927409ac --- /dev/null +++ b/plugins/FreeImage/src/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.5.9, February 18, 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 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 +February 18, 2012 diff --git a/plugins/FreeImage/src/LibPNG/README b/plugins/FreeImage/src/LibPNG/README new file mode 100644 index 0000000000..c648a5ad78 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/README @@ -0,0 +1,202 @@ +README for libpng version 1.5.9 - February 18, 2012 (shared library 15.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*.zip if you want DOS-style line endings. + +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_ and +png_get_ 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-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-manual.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.info-zip.org/pub/infozip/zlib + +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/documents/ + +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.sourceforge.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-implement list, however. + +Please do not send general questions about PNG. Send them to +png-mng-misc at lists.sf.net (subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-misc to +subscribe). 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 sixteen 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.3 => manual page for libpng (includes libpng-manual.txt) + libpng-manual.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 (public) + pngpriv.h => Library function and interface declarations (private) + pngconf.h => System specific library configuration (public) + pngstruct.h => png_struct declaration (private) + pnginfo.h => png_info struct declaration (private) + pngdebug.h => debugging macros (private) + 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 + 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 + cbuilder5 => Contains a Borland workspace for building + libpng and zlib + visualc6 => Contains a Microsoft Visual C++ (MSVC) + workspace for building libpng and zlib + visualc71 => Contains a Microsoft Visual C++ (MSVC) + workspace for building libpng and zlib + xcode => Contains an Apple xcode + workspace for building libpng and zlib + scripts => Directory containing scripts for building libpng: + (see scripts/README.txt for the list of scripts) + +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://www-mddsp.enel.ucalgary.ca/People/adilger/ + +-Guy Eric Schalnat (original author and former maintainer, 1995-1996) + (formerly of Group 42, Inc) + Internet: gschal at infinet.com diff --git a/plugins/FreeImage/src/LibPNG/TODO b/plugins/FreeImage/src/LibPNG/TODO new file mode 100644 index 0000000000..b1660a413a --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/TODO @@ -0,0 +1,27 @@ +/* +TODO - list of things to do for libpng: + +Final bug fixes. +Better C++ wrapper/full C++ implementation? +Fix problem with C++ and EXTERN "C". +cHRM transformation. +Remove setjmp/longjmp usage 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). +Avoid building gamma tables whenever possible. +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. +Switch to the simpler zlib (zlib/libpng) license if legally possible. +Extend pngvalid.c to validate more of the libpng transformations. + +*/ diff --git a/plugins/FreeImage/src/LibPNG/Y2KINFO b/plugins/FreeImage/src/LibPNG/Y2KINFO new file mode 100644 index 0000000000..7776d83732 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/Y2KINFO @@ -0,0 +1,55 @@ + Y2K compliance in libpng: + ========================= + + February 25, 2010 + + 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.43 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/plugins/FreeImage/src/LibPNG/configure b/plugins/FreeImage/src/LibPNG/configure new file mode 100644 index 0000000000..9da0f74eca --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/configure @@ -0,0 +1,19 @@ + +echo " + There is no \"configure\" script in this distribution of + libpng-1.5.9. + + 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.5.9.tar.gz, libpng-1.5.9.tar.xz, or libpng-1.5.9.tar.bz2 + + If the line endings in the files look funny, which is likely to be the + case if you were trying to run \"configure\" on a Linux machine, you may + wish to get the other distribution of libpng. It is available in both + tar.gz/tar.xz (UNIX style line endings) and .7z/.zip (DOS style line + endings) formats. +" + diff --git a/plugins/FreeImage/src/LibPNG/libpng.3 b/plugins/FreeImage/src/LibPNG/libpng.3 new file mode 100644 index 0000000000..1d72ab4cae --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/libpng.3 @@ -0,0 +1,5952 @@ +.TH LIBPNG 3 "February 18, 2012" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.5.9 +.SH SYNOPSIS +\fI\fB + +\fB#include \fP + +\fI\fB + +\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP + +\fI\fB + +\fBvoid png_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_build_grayscale_palette (int \fP\fIbit_depth\fP\fB, png_colorp \fIpalette\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_calloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\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 + +\fBvoid png_data_freer (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIfreer\fP\fB, png_uint_32 \fImask)\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_err (png_structp \fIpng_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_bKGD (png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_uint_32 png_get_cHRM_XYZ (png_structp \fIpng_ptr, + +\fBpng_const_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*red_X\fP\fB, double \fP\fI*red_Y\fP\fB, double \fI*red_Z, + +\fBdouble \fP\fI*green_X\fP\fB, double \fP\fI*green_Y\fP\fB, double \fP\fI*green_Z\fP\fB, double \fI*blue_X, + +\fBdouble \fP\fI*blue_Y\fP\fB, double \fI*blue_Z\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM_XYZ_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_fixed_point \fP\fI*int_red_X\fP\fB, png_fixed_point \fP\fI*int_red_Y\fP\fB, png_fixed_point \fP\fI*int_red_Z\fP\fB, png_fixed_point \fP\fI*int_green_X\fP\fB, png_fixed_point \fP\fI*int_green_Y\fP\fB, png_fixed_point \fP\fI*int_green_Z\fP\fB, png_fixed_point \fP\fI*int_blue_X\fP\fB, png_fixed_point \fP\fI*int_blue_Y\fP\fB, png_fixed_point \fI*int_blue_Z\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_chunk_cache_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_alloc_size_t png_get_chunk_malloc_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_color_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_compression_buffer_size (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_compression_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_copyright (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_current_row_number \fI(png_const_structp\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_current_pass_number \fI(png_const_structp\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_error_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_filter_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_header_version (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_hIST (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_iCCP (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_bytepp \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_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_image_width (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_int_32 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_interlace_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_const_bytep png_get_io_chunk_name (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_io_chunk_type (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_io_state (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_libpng_ver (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_mem_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_oFFs (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pHYs_dpi (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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 + +\fBpng_fixed_point png_get_pixel_aspect_ratio_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_progressive_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_PLTE (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_structp \fIpng_ptr) + +\fBpng_uint_32 png_get_rowbytes (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_bytepp png_get_rows (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sBIT (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP + +\fI\fB + +\fBvoid png_get_sCAL (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, double* \fP\fIwidth\fP\fB, double* \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_get_sCAL_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_fixed_pointp \fP\fIwidth\fP\fB, png_fixed_pointp \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_get_sCAL_s (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_charpp \fP\fIwidth\fP\fB, png_charpp \fIheight\fP\fB);\fP + +\fI\fB + +\fBpng_bytep png_get_signature (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sPLT (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sRGB (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int \fI*file_srgb_intent\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_text (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_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_const_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_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans_alpha\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_color\fP\fB);\fP + +\fI\fB + +\fB/* This function is really an inline macro. \fI*/ + +\fBpng_uint_16 png_get_uint_16 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_uint_31 (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fB/* This function is really an inline macro. \fI*/ + +\fBpng_uint_32 png_get_uint_32 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_unknown_chunks (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_chunk_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_height_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_transform_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_width_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_valid (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_x_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_fixed_point png_get_x_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_x_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_x_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_y_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_fixed_point png_get_y_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_y_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_y_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_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_info_init_3 (png_infopp \fP\fIinfo_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP + +\fI\fB + +\fBvoid png_longjmp (png_structp \fP\fIpng_ptr\fP\fB, int \fIval\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc_default (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc_warn (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_permit_mng_features (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fImng_features_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 + +\fBpng_size_t png_process_data_pause \fP\fI(png_structp\fP\fB, int \fIsave\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_process_data_skip \fI(png_structp\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_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 + +\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 + +\fBint png_reset_zstream (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_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 + +\fBvoid png_set_alpha_mode (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImode\fP\fB, double \fIoutput_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_alpha_mode_fixed (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImode\fP\fB, png_fixed_point \fIoutput_gamma\fP\fB);\fP + +\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_background_fixed (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, png_uint_32 \fIbackground_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_benign_errors (png_structp \fP\fIpng_ptr\fP\fB, int \fIallowed\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_cHRM_XYZ (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIred_X\fP\fB, double \fP\fIred_Y\fP\fB, double \fP\fIred_Z\fP\fB, double \fP\fIgreen_X\fP\fB, double \fIgreen_Y, + +\fBdouble \fP\fIgreen_Z\fP\fB, double \fP\fIblue_X\fP\fB, double \fP\fIblue_Y\fP\fB, double \fIblue_Z\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_cHRM_XYZ_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\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_red_Z\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_green_Z\fP\fB, png_fixed_point \fP\fIint_blue_X\fP\fB, png_fixed_point \fP\fIint_blue_Y\fP\fB, png_fixed_point \fIint_blue_Z\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_chunk_cache_max (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIuser_chunk_cache_max\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_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_16 (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_filter_heuristics_fixed (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_fixed_point_p \fP\fIfilter_weights\fP\fB, png_fixed_point_p \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_gamma_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIscreen_gamma\fP\fB, png_uint_32 \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_const_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_const_bytep \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 + +\fBjmp_buf* png_set_longjmp_fn (png_structp \fP\fIpng_ptr\fP\fB, png_longjmp_ptr \fP\fIlongjmp_fn\fP\fB, size_t \fIjmp_buf_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_chunk_malloc_max (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIuser_chunk_cache_max\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 + +\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_quantize (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_quantize\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_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_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_uint_32 \fP\fIred\fP\fB, png_uint_32 \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, int \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_fixed_point \fP\fIwidth\fP\fB, png_fixed_point \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL_s (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_charp \fP\fIwidth\fP\fB, png_charp \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_scale_16 (png_structp \fIpng_ptr\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 \fIsrgb_intent\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 \fIsrgb_intent\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_strip_error_numbers (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIstrip_mode\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_text_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP + +\fI\fB + +\fBvoid \fP\fIpng_set_text_compression_method\fP\fB, (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod)\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_alpha\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_color\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_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 + +\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_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 + +\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 + +\fBvoid png_write_sig (png_structp \fIpng_ptr\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-manual.txt file that accompanies libpng. +.SH LIBPNG.TXT +libpng-manual.txt - A description on how to use and modify libpng + + libpng version 1.5.9 - February 18, 2012 + Updated and distributed by Glenn Randers-Pehrson + + Copyright (c) 1998-2011 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.5.9 - February 18, 2012 + Updated and distributed by Glenn Randers-Pehrson + Copyright (c) 1998-2011 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 +. 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 and as a +W3C Recommendation . + +Some additional chunks are described in the special-purpose public chunks +documents at . + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, . + +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, . +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. Both are internal structures that are no longer exposed +in the libpng interface (as of libpng 1.5.0). + +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, and direct access to the png_info fields was +deprecated.. + +The png_struct structure is the object used by the library to decode a +single image. As of 1.5.0 this structure is also not exposed. + +Almost all libpng APIs require a pointer to a png_struct as the first argument. +Many (in particular the png_set and png_get APIs) also require a pointer +to png_info as the second argument. Some application visible macros +defined in png.h designed for basic data access (reading and writing +integers in the PNG format) don't take a png_info pointer, but it's almost +always safe to assume that a (png_struct*) has to be passed to call an API +function. + +You can have more than one png_info structure associated with an image, +as illustrated in pngtest.c, one for information valid prior to the +IDAT chunks and another (called "end_info" below) for things after them. + +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 + +and also (as of libpng-1.5.0) the zlib header file, if you need it: + +#include + +.SS Types + +The png.h header file defines a number of integral types used by the +APIs. Most of these are fairly obvious; for example types corresponding +to integers of particular sizes and types for passing color values. + +One exception is how non-integral numbers are handled. For application +convenience most APIs that take such numbers have C (double) arguments, +however internally PNG, and libpng, use 32 bit signed integers and encode +the value by multiplying by 100,000. As of libpng 1.5.0 a convenience +macro PNG_FP_1 is defined in png.h along with a type (png_fixed_point) +which is simply (png_int_32). + +All APIs that take (double) arguments also have a matching API that +takes the corresponding fixed point integer arguments. The fixed point +API has the same name as the floating point one with "_fixed" appended. +The actual range of values permitted in the APIs is frequently less than +the full range of (png_fixed_point) (-21474 to +21474). When APIs require +a non-negative argument the type is recorded as png_uint_32 above. Consult +the header file and the text below for more information. + +Special care must be take with sCAL chunk handling because the chunk itself +uses non-integral values encoded as strings containing decimal floating point +numbers. See the comments in the header file. + +.SS Configuration + +The main header file function declarations are frequently protected by C +preprocessing directives of the form: + + #ifdef PNG_feature_SUPPORTED + declare-function + #endif + ... + #ifdef PNG_feature_SUPPORTED + use-function + #endif + +The library can be built without support for these APIs, although a +standard build will have all implemented APIs. Application programs +should check the feature macros before using an API for maximum +portability. From libpng 1.5.0 the feature macros set during the build +of libpng are recorded in the header file "pnglibconf.h" and this file +is always included by png.h. + +If you don't need to change the library configuration from the default, skip to +the next section ("Reading"). + +Notice that some of the makefiles in the 'scripts' directory and (in 1.5.0) all +of the build project files in the 'projects' directory simply copy +scripts/pnglibconf.h.prebuilt to pnglibconf.h. This means that these build +systems do not permit easy auto-configuration of the library - they only +support the default configuration. + +The easiest way to make minor changes to the libpng configuration when +auto-configuration is supported is to add definitions to the command line +using (typically) CPPFLAGS. For example: + +CPPFLAGS=-DPNG_NO_FLOATING_ARITHMETIC + +will change the internal libpng math implementation for gamma correction and +other arithmetic calculations to fixed point, avoiding the need for fast +floating point support. The result can be seen in the generated pnglibconf.h - +make sure it contains the changed feature macro setting. + +If you need to make more extensive configuration changes - more than one or two +feature macro settings - you can either add -DPNG_USER_CONFIG to the build +command line and put a list of feature macro settings in pngusr.h or you can set +DFA_XTRA (a makefile variable) to a file containing the same information in the +form of 'option' settings. + +A. Changing pnglibconf.h + +A variety of methods exist to build libpng. Not all of these support +reconfiguration of pnglibconf.h. To reconfigure pnglibconf.h it must either be +rebuilt from scripts/pnglibconf.dfa using awk or it must be edited by hand. + +Hand editing is achieved by copying scripts/pnglibconf.h.prebuilt to +pnglibconf.h and changing the lines defining the supported features, paying +very close attention to the 'option' information in scripts/pnglibconf.dfa +that describes those features and their requirements. This is easy to get +wrong. + +B. Configuration using DFA_XTRA + +Rebuilding from pnglibconf.dfa is easy if a functioning 'awk', or a later +variant such as 'nawk' or 'gawk', is available. The configure build will +automatically find an appropriate awk and build pnglibconf.h. +The scripts/pnglibconf.mak file contains a set of make rules for doing the +same thing if configure is not used, and many of the makefiles in the scripts +directory use this approach. + +When rebuilding simply write a new file containing changed options and set +DFA_XTRA to the name of this file. This causes the build to append the new file +to the end of scripts/pnglibconf.dfa. The pngusr.dfa file should contain lines +of the following forms: + +everything = off + +This turns all optional features off. Include it at the start of pngusr.dfa to +make it easier to build a minimal configuration. You will need to turn at least +some features on afterward to enable either reading or writing code, or both. + +option feature on +option feature off + +Enable or disable a single feature. This will automatically enable other +features required by a feature that is turned on or disable other features that +require a feature which is turned off. Conflicting settings will cause an error +message to be emitted by awk. + +setting feature default value + +Changes the default value of setting 'feature' to 'value'. There are a small +number of settings listed at the top of pnglibconf.h, they are documented in the +source code. Most of these values have performance implications for the library +but most of them have no visible effect on the API. Some can also be overridden +from the API. + +This method of building a customized pnglibconf.h is illustrated in +contrib/pngminim/*. See the "$(PNGCONF):" target in the makefile and +pngusr.dfa in these directories. + +C. Configuration using PNG_USR_CONFIG + +If -DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file +pngusr.h will automatically be included before the options in +scripts/pnglibconf.dfa are processed. Your pngusr.h file should contain only +macro definitions turning features on or off or setting settings. + +Apart from the global setting "everything = off" all the options listed above +can be set using macros in pngusr.h: + +#define PNG_feature_SUPPORTED + +is equivalent to: + +option feature on + +#define PNG_NO_feature + +is equivalent to: + +option feature off + +#define PNG_feature value + +is equivalent to: + +setting feature default value + +Notice that in both cases, pngusr.dfa and pngusr.h, the contents of the +pngusr file you supply override the contents of scripts/pnglibconf.dfa + +If confusing or incomprehensible behavior results it is possible to +examine the intermediate file pnglibconf.dfn to find the full set of +dependency information for each setting and option. Simply locate the +feature in the file and read the C comments that precede it. + +This method is also illustrated in the contrib/pngminim/* makefiles and +pngusr.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); + } + +If you want to use your own memory allocation routines, +use a libpng that was built with PNG_USER_MEM_SUPPORTED defined, 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 longjmp buffer 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); + } + +Pass (png_infopp)NULL instead of &end_info if you didn't create +an end_info structure. + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +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); + +You can change the zlib compression buffer size to be used while +reading compressed data with + + png_set_compression_buffer_size(png_ptr, buffer_size); + +where the default size is 8192 bytes. Note that the buffer size +is changed immediately and the buffer is reallocated immediately, +instead of setting a flag to be acted upon later. + +If you want CRC errors to be handled in a different manner than +the default, use + + png_set_crc_action(png_ptr, crit_action, ancil_action); + +The values for png_set_crc_action() say how libpng is 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. + +Choices for (int) crit_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +Choices for (int) ancil_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_DISCARD 2 warn/discard data + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +.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_structp png_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_structp png_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); + +When this function is called the row has already been completely processed and +the 'row' and 'pass' refer to the next row to be handled. For the +non-interlaced case the row that was just handled is simply one less than the +passed in row number, and pass will always be 0. For the interlaced case the +same applies unless the row value is 0, in which case the row just handled was +the last one from one of the preceding passes. Because interlacing may skip a +pass you cannot be sure that the preceding pass is just 'pass-1', if you really +need to know what the last pass is record (row,pass) from the callback and use +the last recorded value each time. + +As with the user transform you can find the output row using the +PNG_ROW_FROM_PASS_ROW macro. + +.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. +If you know that your application will never make use of some particular +chunks, use PNG_HANDLE_CHUNK_NEVER (or 1) as demonstrated below. + +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 change 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(). + +When writing a PNG datastream, put this statement before calling +png_write_info() or png_write_png(). + +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. + +You can also set a limit on the amount of memory that a compressed chunk +other than IDAT can occupy, with + + png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); + +and you can retrieve the limit with + + chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); + +Any chunks that would cause either of these limits to be exceeded will +be ignored. + +.SS Information about your system + +If you intend to display the PNG or to incorporate it in other image data you +need to tell libpng information about your display or drawing surface so that +libpng can convert the values in the image to match the display. + +From libpng-1.5.4 this information can be set before reading the PNG file +header. In earlier versions png_set_gamma() existed but behaved incorrectly if +called before the PNG file header had been read and png_set_alpha_mode() did not +exist. + +If you need to support versions prior to libpng-1.5.4 test the version number +as illustrated below using "PNG_LIBPNG_VER >= 10504" and follow the procedures +described in the appropriate manual page. + +You give libpng the encoding expected by your system expressed as a 'gamma' +value. You can also specify a default encoding for the PNG file in +case the required information is missing from the file. By default libpng +assumes that the PNG data matches your system, to keep this default call: + + png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/); + +or you can use the fixed point equivalent: + + png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma, PNG_FP_1/screen_gamma); + +If you don't know the gamma for your system it is probably 2.2 - a good +approximation to the IEC standard for display systems (sRGB). If images are +too contrasty or washed out you got the value wrong - check your system +documentation! + +Many systems permit the system gamma to be changed via a lookup table in the +display driver, a few systems, including older Macs, change the response by +default. As of 1.5.4 three special values are available to handle common +situations: + + PNG_DEFAULT_sRGB: Indicates that the system conforms to the IEC 61966-2-1 + standard. This matches almost all systems. + PNG_GAMMA_MAC_18: Indicates that the system is an older (pre Mac OS 10.6) + Apple Macintosh system with the default settings. + PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates that the + system expects data with no gamma encoding. + +You would use the linear (unencoded) value if you need to process the pixel +values further because this avoids the need to decode and reencode each +component value whenever arithmetic is performed. A lot of graphics software +uses linear values for this reason, often with higher precision component values +to preserve overall accuracy. + +The second thing you may need to tell libpng about is how your system handles +alpha channel information. Some, but not all, PNG files contain an alpha +channel. To display these files correctly you need to compose the data onto a +suitable background, as described in the PNG specification. + +Libpng only supports composing onto a single color (using png_set_background; +see below). Otherwise you must do the composition yourself and, in this case, +you may need to call png_set_alpha_mode: + +#if PNG_LIBPNG_VER >= 10504 + png_set_alpha_mode(png_ptr, mode, screen_gamma); +#else + png_set_gamma(png_ptr, screen_gamma, 1.0/screen_gamma); +#endif + +The screen_gamma value is the same as the argument to png_set_gamma; however, +how it affects the output depends on the mode. png_set_alpha_mode() sets the +file gamma default to 1/screen_gamma, so normally you don't need to call +png_set_gamma. If you need different defaults call png_set_gamma() before +png_set_alpha_mode() - if you call it after it will override the settings made +by png_set_alpha_mode(). + +The mode is as follows: + + PNG_ALPHA_PNG: The data is encoded according to the PNG specification. Red, +green and blue, or gray, components are gamma encoded color +values and are not premultiplied by the alpha value. The +alpha value is a linear measure of the contribution of the +pixel to the corresponding final output pixel. + +You should normally use this format if you intend to perform +color correction on the color values; most, maybe all, color +correction software has no handling for the alpha channel and, +anyway, the math to handle pre-multiplied component values is +unnecessarily complex. + +Before you do any arithmetic on the component values you need +to remove the gamma encoding and multiply out the alpha +channel. See the PNG specification for more detail. It is +important to note that when an image with an alpha channel is +scaled, linear encoded, pre-multiplied component values must +be used! + +The remaining modes assume you don't need to do any further color correction or +that if you do, your color correction software knows all about alpha (it +probably doesn't!) + + PNG_ALPHA_STANDARD: The data libpng produces +is encoded in the standard way +assumed by most correctly written graphics software. +The gamma encoding will be removed by libpng and the +linear component values will be pre-multiplied by the +alpha channel. + +With this format the final image must be re-encoded to +match the display gamma before the image is displayed. +If your system doesn't do that, yet still seems to +perform arithmetic on the pixels without decoding them, +it is broken - check out the modes below. + +With PNG_ALPHA_STANDARD libpng always produces linear +component values, whatever screen_gamma you supply. The +screen_gamma value is, however, used as a default for +the file gamma if the PNG file has no gamma information. + +If you call png_set_gamma() after png_set_alpha_mode() you +will override the linear encoding. Instead the +pre-multiplied pixel values will be gamma encoded but +the alpha channel will still be linear. This may +actually match the requirements of some broken software, +but it is unlikely. + +While linear 8-bit data is often used it has +insufficient precision for any image with a reasonable +dynamic range. To avoid problems, and if your software +supports it, use png_set_expand_16() to force all +components to 16 bits. + + PNG_ALPHA_OPTIMIZED: This mode is the same +as PNG_ALPHA_STANDARD except that +completely opaque pixels are gamma encoded according to +the screen_gamma value. Pixels with alpha less than 1.0 +will still have linear components. + +Use this format if you have control over your +compositing software and do don't do other arithmetic +(such as scaling) on the data you get from libpng. Your +compositing software can simply copy opaque pixels to +the output but still has linear values for the +non-opaque pixels. + +In normal compositing, where the alpha channel encodes +partial pixel coverage (as opposed to broad area +translucency), the inaccuracies of the 8-bit +representation of non-opaque pixels are irrelevant. + +You can also try this format if your software is broken; +it might look better. + + PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD; +however, all component values, +including the alpha channel are gamma encoded. This is +an appropriate format to try if your software, or more +likely hardware, is totally broken, i.e., if it performs +linear arithmetic directly on gamma encoded values. + +In most cases of broken software or hardware the bug in the final display +manifests as a subtle halo around composited parts of the image. You may not +even perceive this as a halo; the composited part of the image may simply appear +separate from the background, as though it had been cut out of paper and pasted +on afterward. + +If you don't have to deal with bugs in software or hardware, or if you can fix +them, there are three recommended ways of using png_set_alpha_mode(): + + png_set_alpha_mode(png_ptr, PNG_ALPHA_PNG, + screen_gamma); + +You can do color correction on the result (libpng does not currently +support color correction internally). When you handle the alpha channel +you need to undo the gamma encoding and multiply out the alpha. + + png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, + screen_gamma); + png_set_expand_16(png_ptr); + +If you are using the high level interface, don't call png_set_expand_16(); +instead pass PNG_TRANSFORM_EXPAND_16 to the interface. + +With this mode you can't do color correction, but you can do arithmetic, +including composition and scaling, on the data without further processing. + + png_set_alpha_mode(png_ptr, PNG_ALPHA_OPTIMIZED, + screen_gamma); + +You can avoid the expansion to 16-bit components with this mode, but you +lose the ability to scale the image or perform other linear arithmetic. +All you can do is compose the result onto a matching output. Since this +mode is libpng-specific you also need to write your own composition +software. + +If you don't need, or can't handle, the alpha channel you can call +png_set_background() to remove it by compositing against a fixed color. Don't +call png_set_strip_alpha() to do this - it will leave spurious pixel values in +transparent parts of this image. + + png_set_background(png_ptr, &background_color, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1); + +The background_color is an RGB or grayscale value according to the data format +libpng will produce for you. Because you don't yet know the format of the PNG +file, if you call png_set_background at this point you must arrange for the +format produced by libpng to always have 8-bit or 16-bit components and then +store the color as an 8-bit or 16-bit color as appropriate. The color contains +separate gray and RGB component values, so you can let libpng produce gray or +RGB output according to the input format, but low bit depth grayscale images +must always be converted to at least 8-bit format. (Even though low bit depth +grayscale images can't have an alpha channel they can have a transparent +color!) + +You set the transforms you need later, either as flags to the high level +interface or libpng API calls for the low level interface. For reference the +settings and API calls required are: + +8-bit values: + PNG_TRANSFORM_SCALE_16 | PNG_EXPAND + png_set_expand(png_ptr); png_set_scale_16(png_ptr); + + If you must get exactly the same inaccurate results + produced by default in versions prior to libpng-1.5.4, + use PNG_TRANSFORM_STRIP_16 and png_set_strip_16(png_ptr) + instead. + +16-bit values: + PNG_TRANSFORM_EXPAND_16 + png_set_expand_16(png_ptr); + +In either case palette image data will be expanded to RGB. If you just want +color data you can add PNG_TRANSFORM_GRAY_TO_RGB or png_set_gray_to_rgb(png_ptr) +to the list. + +Calling png_set_background before the PNG file header is read will not work +prior to libpng-1.5.4. Because the failure may result in unexpected warnings or +errors it is therefore much safer to call png_set_background after the head has +been read. Unfortunately this means that prior to libpng-1.5.4 it cannot be +used with the high level interface. + +.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_SCALE_16 Strip 16-bit samples to + 8-bit accurately + PNG_TRANSFORM_STRIP_16 Chop 16-bit samples to + 8-bit less accurately + 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) + PNG_TRANSFORM_EXPAND_16 Expand samples to 16 bits + +(This excludes setting a background color, doing gamma transformation, +quantizing, 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) and +png_get_(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_ 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, &file_gamma); + png_get_gAMA_fixed(png_ptr, info_ptr, &int_file_gamma); + + file_gamma - the gamma at which the file is + written (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which the + file is written + + png_get_cHRM(png_ptr, info_ptr, &white_x, &white_y, &red_x, &red_y, + &green_x, &green_y, &blue_x, &blue_y) + png_get_cHRM_XYZ(png_ptr, info_ptr, &red_X, &red_Y, &red_Z, &green_X, + &green_Y, &green_Z, &blue_X, &blue_Y, &blue_Z) + png_get_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) + png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, &int_red_X, &int_red_Y, + &int_red_Z, &int_green_X, &int_green_Y, &int_green_Z, + &int_blue_X, &int_blue_Y, &int_blue_Z) + + {white,red,green,blue}_{x,y} + A color space encoding specified using the chromaticities + of the end points and the white point. (PNG_INFO_cHRM) + + {red,green,blue}_{X,Y,Z} + A color space encoding specified using the encoding end + points - the CIE tristimulus specification of the intended + color of the red, green and blue channels in the PNG RGB + data. The white point is simply the sum of the three end + points. (PNG_INFO_cHRM) + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + + file_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_type - 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_alpha, + &num_trans, &trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values of + the single transparent color for + non-paletted images (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 (of type + png_color_16p) (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. Prior to + libpng-1.4.0 the library was built by default without + iTXt support. Also note that when iTXt is supported, + they contain NULL pointers when the "compression" + field contains PNG_TEXT_COMPRESSION_NONE or + PNG_TEXT_COMPRESSION_zTXt. + + 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); + + num_spalettes - number of sPLT chunks read. + + palette_ptr - array of palette structures holding + contents of one or more 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 (can be negative) + + offset_y - positive offset from the top edge + of the screen (can be negative) + + 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 + (expressed as a string) + + 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 value of "location" is a bitwise "or" of + + PNG_HAVE_IHDR (0x01) + PNG_HAVE_PLTE (0x02) + PNG_AFTER_IDAT (0x08) + +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 + + Note that because of the way the resolutions are + stored internally, the inch conversions won't + come out to exactly even number. For example, + 72 dpi is stored as 0.28346 pixels/meter, and + when this is retrieved it is 71.9988 dpi, so + be sure to round the returned value appropriately + if you want to display a reasonable-looking result. + +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. The + remark about inexact inch conversions applies here + as well, because a value in inches can't always be + converted to microns and back without some loss + of precision. + +For more information, see 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. + +Transformations you request are ignored if they don't have any meaning for a +particular input data format. However some transformations can have an effect +as a result of a previous transformation. If you specify a contradictory set of +transformations, for example both adding and removing the alpha channel, you +cannot predict the final result. + +The color used for the transparency values should be supplied in the same +format/depth as the current image data. It is stored in the same format/depth +as the image data in a tRNS chunk, so this is what libpng expects for this data. + +The color used for the background value depends on the need_expand argument as +described 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_scale_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(), png_set_strip_16(), +or png_set_scale_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 (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); + +The first two 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.5.2, png_set_expand_16() was added. It behaves as +png_set_expand(); however, the resultant channels have 16 bits rather than 8. +Use this when the output color or gray channels are made linear to avoid fairly +severe accuracy loss. + + if (bit_depth < 16) + png_set_expand_16(png_ptr); + +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) +#if PNG_LIBPNG_VER >= 10504 + png_set_scale_16(png_ptr); +#else + png_set_strip_16(png_ptr); +#endif + +(The more accurate "png_set_scale_16()" API became available in libpng version +1.5.4). + +If you need to process the alpha channel on the image separately from the image +data (for example if you convert it to a bitmap mask) it is possible to have +libpng strip the channel leaving just RGB or gray data: + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +If you strip the alpha channel you need to find some other way of dealing with +the information. If, instead, you want to convert the image to an opaque +version with no alpha channel use png_set_background; see below. + +As of libpng version 1.5.2, almost all useful expansions are supported, the +major ommissions are conversion of grayscale to indexed images (which can be +done trivially in the application) and conversion of indexed to grayscale (which +can be done by a trivial manipulation of the palette.) + +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 - [G] - - - - - - - - - - - - - + 31 [Q] Q [Q] [Q] [Q] Q Q Q Q Q Q [Q] [Q] Q Q + 0 1 G + . . G G G G G G B B GB GB + 0T lt Gt t + . Gt G G Gt G G Bt Bt GBt GBt + 0O lt Gt t . + Gt Gt G Gt Gt G Bt Bt GBt GBt + 2 C P C C C + . . C - - CB CB B B + 2T Ct - Ct C C t + t - - - CBt CBt Bt Bt + 2O Ct - Ct C C t t + - - - CBt CBt Bt Bt + 3 [Q] p [Q] [Q] [Q] Q Q Q + . . [Q] [Q] Q Q + 3T [Qt] p [Qt][Q] [Q] Qt Qt Qt t + t [Qt][Qt] Qt Qt + 3O [Qt] p [Qt][Q] [Q] Qt Qt Qt t t + [Qt][Qt] Qt Qt + 4A lA G A T T GA GT GT GA GT GT + BA G GBA + 4O lA GBA A T T GA GT GT GA GT GT BA + GBA G + 6A CA PA CA C C A T tT PA P P C CBA + BA + 6O CA PBA CA C C A tT T PA P P CBA C BA + + +Within the matrix, + "+" identifies entries where 'from' and 'to' are the same. + "-" means the transformation is not supported. + "." means nothing is necessary (a tRNS chunk can just be ignored). + "t" means the transformation is obtained by png_set_tRNS. + "A" means the transformation is obtained by png_set_add_alpha(). + "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() (and by png_set_expand() if there + is no transparency in the original or the final format). + "C" means the transformation is obtained by png_set_gray_to_rgb(). + "G" means the transformation is obtained by png_set_rgb_to_gray(). + "P" means the transformation is obtained by + png_set_expand_palette_to_rgb(). + "p" means the transformation is obtained by png_set_packing(). + "Q" means the transformation is obtained by png_set_quantize(). + "T" means the transformation is obtained by png_set_tRNS_to_alpha(). + "B" means the transformation is obtained by png_set_background(), or + png_strip_alpha(). + +When an entry has multiple transforms listed all are required to cause the +right overall transformation. When two transforms are separated by a comma +either will do the job. When transforms are enclosed in [] the transform should +do the job but this is currently unimplemented - a different format will result +if the suggested transformations are used. + +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(png_ptr, error_action, double red_weight, + double 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 + + green_weight: weight of green component + If either weight is negative, default + weights are used. + +In the corresponding fixed point API the red_weight and green_weight values are +simply scaled by 100,000: + + png_set_rgb_to_gray(png_ptr, error_action, png_fixed_point red_weight, + png_fixed_point green_weight); + +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. Background and sBIT data +will be silently converted to grayscale, using the green channel +data for sBIT, regardless of the error_action setting. + +The default values come from the PNG file cHRM chunk if present; otherwise, the +defaults correspond to the ITU-R recommendation 709, and also the sRGB color +space, as recommended in the Charles Poynton's Colour FAQ, +, in section 9: + + + + Y = 0.2126 * R + 0.7152 * G + 0.0722 * B + +Previous versions of this document, 1998 through 2002, recommended a slightly +different formula: + + Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + +Libpng uses an integer approximation: + + Y = (6968 * R + 23434 * G + 2366 * B)/32768 + +The calculation is done in a linear colorspace, if the image gamma +can be determined. + +The png_set_background() function has been described already; it tells libpng to +composite images with alpha or simple transparency against the supplied +background color. For compatibility with versions of libpng earlier than +libpng-1.5.4 it is recommended that you call the function after reading the file +header, even if you don't want to use the color in a bKGD chunk, if one exists. + +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 how the color is represented, both the format of the +component values in the color (the number of bits) and the gamma encoding of the +color. The function takes two arguments, background_gamma_mode and need_expand +to convey this information, however only two combinations are likely to be +useful: + + 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/*needs to be expanded*/, 1); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*do not expand*/, 1); + +The second call was described above - my_background is in the format of the +final, display, output produced by libpng. Because you now know the format of +the PNG it is possible to avoid the need to choose either 8-bit or 16-bit +output and to retain palette images (the palette colors will be modified +appropriately and the tRNS chunk removed.) However, if you are doing this, +take great care not to ask for transformations without checking first that +they apply! + +In the first call the background color has the original bit depth and color type +of the PNG file. So, for palette images the color is supplied as a palette +index and for low bit greyscale images the color is a reduced bit value in +image_background->gray. + +If you didn't call png_set_gamma() before reading the file header, for example +if you need your code to remain compatible with older versions of libpng prior +to libpng-1.5.4, this is the place to call it. + +Do not call it if you called png_set_alpha_mode(); doing so will damage the +settings put in place by png_set_alpha_mode(). (If png_set_alpha_mode() is +supported then you can certainly do png_set_gamma() before reading the PNG +header.) + +This API unconditionally sets the screen and file gamma values, so it will +override the value in the PNG file unless it is called before the PNG file +reading starts. For this reason you must always call it with the PNG file +value when you call it in this position: + + if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) + png_set_gamma(png_ptr, screen_gamma, file_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_quantize() +will do that. Note that this is a simple match quantization that merely +finds the closest color available. This should work fairly well with +optimized palettes, but fairly badly with linear color cubes. If you +pass a palette that is larger than 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, libpng 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_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_quantize(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_structp png_ptr, png_row_infop + 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. Take care with +interlaced images if you do the interlace yourself - the width of the row is the +width in 'row_info', not the overall image width. + +If supported, libpng provides two information routines that you can use to find +where you are in processing the image: + + png_get_current_pass_number(png_structp png_ptr); + png_get_current_row_number(png_structp png_ptr); + +Don't try using these outside a transform callback - firstly they are only +supported if user transforms are supported, secondly they may well return +unexpected results unless the row is actually being processed at the moment they +are called. + +With interlaced +images the value returned is the row in the input sub-image image. Use +PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to +find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). + +The discussion of interlace handling above contains more information on how to +use these values. + +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. + + png_read_update_info(png_ptr, info_ptr); + +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. You may +only call png_read_update_info() once with a particular 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. + +Remember: Before you call png_read_update_info(), the png_get_*() +functions return the values corresponding to the original PNG image. +After you call png_read_update_info the values refer to the image +that libpng will output. Consequently you must call all the png_set_ +functions before you call png_read_update_info(). This is particularly +important for png_set_interlace_handling() - if you are going to call +png_read_update_info() you must call png_set_interlace_handling() before +it unless you want to receive interlaced output. + +.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() (unless you call +png_read_update_info()) 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); +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. This number is defined (from libpng 1.5) as +PNG_INTERLACE_ADAM7_PASSES in png.h + +libpng can fill out those images or it can give them to you "as is". +It is almost always better to have libpng handle the interlacing for you. +If you want the images 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, as is likely, 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. +You then need to read the whole image 'number_of_passes' times. Each time +will distribute the pixels from the current pass to the correct place in +the output image, so you need to supply the same rows to png_read_rows in +each 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); + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images. +Each of the images is a valid image by itself, however you will almost +certainly need to distribute the pixels from each sub-image to the +correct place. This is where everything gets very tricky. + +If you want to retrieve the separate images you must pass the correct +number of rows to each successive call of png_read_rows(). The calculation +gets pretty complicated for small images, where some sub-images may +not even exist because either their width or height ends up zero. +libpng provides two macros to help you in 1.5 and later versions: + + png_uint_32 width = PNG_PASS_COLS(image_width, pass_number); + png_uint_32 height = PNG_PASS_ROWS(image_height, pass_number); + +Respectively these tell you the width and height of the sub-image +corresponding to the numbered pass. 'pass' is in in the range 0 to 6 - +this can be confusing because the specification refers to the same passes +as 1 to 7! Be careful, you must check both the width and height before +calling png_read_rows() and not call it for that pass if either is zero. + +You can, of course, read each sub-image row by row. If you want to +produce optimal code to make a pixel-by-pixel transformation of an +interlaced image this is the best approach; read each row of each pass, +transform it, and write it out to a new interlaced image. + +If you want to de-interlace the image yourself libpng provides further +macros to help that tell you where to place the pixels in the output image. +Because the interlacing scheme is rectangular - sub-image pixels are always +arranged on a rectangular grid - all you need to know for each pass is the +starting column and row in the output image of the first pixel plus the +spacing between each pixel. As of libpng 1.5 there are four macros to +retrieve this information: + + png_uint_32 x = PNG_PASS_START_COL(pass); + png_uint_32 y = PNG_PASS_START_ROW(pass); + png_uint_32 xStep = 1U << PNG_PASS_COL_SHIFT(pass); + png_uint_32 yStep = 1U << PNG_PASS_ROW_SHIFT(pass); + +These allow you to write the obvious loop: + + png_uint_32 input_y = 0; + png_uint_32 output_y = PNG_PASS_START_ROW(pass); + + while (output_y < output_image_height) + { + png_uint_32 input_x = 0; + png_uint_32 output_x = PNG_PASS_START_COL(pass); + + while (output_x < output_image_width) + { + image[output_y][output_x] = + subimage[pass][input_y][input_x++]; + + output_x += xStep; + } + + ++input_y; + output_y += yStep; + } + +Notice that the steps between successive output rows and columns are +returned as shifts. This is possible because the pixels in the subimages +are always a power of 2 apart - 1, 2, 4 or 8 pixels - in the original +image. In practice you may need to directly calculate the output coordinate +given an input coordinate. libpng provides two further macros for this +purpose: + + png_uint_32 output_x = PNG_COL_FROM_PASS_COL(input_x, pass); + png_uint_32 output_y = PNG_ROW_FROM_PASS_ROW(input_y, pass); + +Finally a pair of macros are provided to tell you if a particular image +row or column appears in a given pass: + + int col_in_pass = PNG_COL_IN_INTERLACE_PASS(output_x, pass); + int row_in_pass = PNG_ROW_IN_INTERLACE_PASS(output_y, pass); + +Bear in mind that you will probably also need to check the width and height +of the pass in addition to the above to be sure the pass even exists! + +With any luck you are convinced by now that you don't want to do your own +interlace handling. In reality normally the only good reason for doing this +is if you are processing PNG files on a pixel-by-pixel basis and don't want +to load the whole file into memory when it is interlaced. + +libpng includes a test program, pngvalid, that illustrates reading and +writing of interlaced images. If you can't get interlacing to work in your +code and don't want to leave it to libpng (the recommended approach), see +how pngvalid.c does it. + +.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. + + 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); + } + + png_read_end(png_ptr, end_info); + +If you are not interested, you should still call png_read_end() +but you can pass NULL, avoiding the need to create an end_info structure. + + png_read_end(png_ptr, (png_infop)NULL); + +If you don't call png_read_end(), then your file pointer will be +left pointing to the first chunk after the last IDAT, which is probably +not what you want if you expect to read something beyond the end of +the PNG datastream. + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +or, if you didn't create an end_info structure, + + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + +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) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_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); + + /* At this point you can call png_process_data_skip if + you want to handle data the library will skip yourself; + it simply returns the number of bytes to skip (and stops + libpng skipping that number of bytes on the next + png_process_data call). + 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 is where you turn on interlace handling, + assuming you don't want to do it yourself. + + If you need to you can stop the processing of + your original input data at this point by calling + png_process_data_pause. This returns the number + of unprocessed bytes from the last png_process_data + call - it is up to you to ensure that the next call + sees these bytes again. If you don't want to bother + with this you can get libpng to cache the unread + bytes by setting the 'save' parameter (see png.h) but + then libpng will have to copy the data internally. + */ + } + + /* 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. + + If you did not turn on interlace handling then + the callback is called for each row of each + sub-image when the image is interlaced. In this + case 'row_num' is the row in the sub-image, not + the row in the output image as it is in all other + cases. + + For the non-NULL rows of interlaced images when + you have switched on libpng interlace handling, + 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 if you switch on interlace handling; + */ + + 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. + + You can also call png_process_data_pause in this + callback - see above. + */ + } + + 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_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +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_structp 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); + +When this function is called the row has already been completely processed and +it has also been written out. The 'row' and 'pass' refer to the next row to be +handled. For the +non-interlaced case the row that was just handled is simply one less than the +passed in row number, and pass will always be 0. For the interlaced case the +same applies unless the row value is 0, in which case the row just handled was +the last one from one of the preceding passes. Because interlacing may skip a +pass you cannot be sure that the preceding pass is just 'pass-1', if you really +need to know what the last pass is record (row,pass) from the callback and use +the last recorded value each time. + +As with the user transform you can find the output row using the +PNG_ROW_FROM_PASS_ROW macro. + +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. + + #include zlib.h + + /* Set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* Set other zlib parameters for compressing IDAT */ + 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) + + /* Set zlib parameters for text compression + * If you don't call these, the parameters + * fall back on those defined for IDAT chunks + */ + png_set_text_compression_mem_level(png_ptr, 8); + png_set_text_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_text_compression_window_bits(png_ptr, 15); + png_set_text_compression_method(png_ptr, 8); + +.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, file_gamma); + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); + + file_gamma - the gamma at which the image was + created (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which + the image was created + + png_set_cHRM(png_ptr, info_ptr, white_x, white_y, red_x, red_y, + green_x, green_y, blue_x, blue_y) + png_set_cHRM_XYZ(png_ptr, info_ptr, red_X, red_Y, red_Z, green_X, + green_Y, green_Z, blue_X, blue_Y, blue_Z) + 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) + png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, int_red_X, int_red_Y, + int_red_Z, int_green_X, int_green_Y, int_green_Z, + int_blue_X, int_blue_Y, int_blue_Z) + + {white,red,green,blue}_{x,y} + A color space encoding specified using the chromaticities + of the end points and the white point. + + {red,green,blue}_{X,Y,Z} + A color space encoding specified using the encoding end + points - the CIE tristimulus specification of the intended + color of the red, green and blue channels in the PNG RGB + data. The white point is simply the sum of the three end + points. + + 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_type - 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_alpha, + num_trans, trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values + (in order red, green, blue) of the + single transparent color for + non-paletted images (PNG_INFO_tRNS) + + png_set_hIST(png_ptr, info_ptr, hist); + + hist - histogram of palette (array of + png_uint_16) (PNG_INFO_hIST) + + 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 (of type + png_color_16p) (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. Prior to + libpng-1.4.0 the library was built by default without + iTXt support. Also note that when iTXt is supported, + they contain NULL pointers when the "compression" + field contains PNG_TEXT_COMPRESSION_NONE or + PNG_TEXT_COMPRESSION_zTXt. + + 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 + expressed as a string + + 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 a few hundred 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_structp png_ptr, png_row_infop + 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. If supported +libpng also supplies an information routine that may be called from +your callback: + + png_get_current_row_number(png_ptr); + png_get_current_pass_number(png_ptr); + +This returns the current row passed to the transform. With interlaced +images the value returned is the row in the input sub-image image. Use +PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to +find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). + +The discussion of interlace handling above contains more information on how to +use these values. + +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 the sub-images +(png_set_interlace_handling() returns the number of 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); + +Think carefully before you write an interlaced image. Typically code that +reads such images reads all the image data into memory, uncompressed, before +doing any processing. Only code that can display an image on the fly can +take advantage of the interlacing and even then the image has to be exactly +the correct size for the output device, because scaling an image requires +adjacent pixels and these are not available until all the passes have been +read. + +If you do write an interlaced image you will hardly ever need to handle +the interlacing yourself. Call png_set_interlace_handling() and use the +approach described above. + +The only time it is conceivable that you will really need to write an +interlaced image pass-by-pass is when you have read one pass by pass and +made some pixel-by-pixel transformation to it, as described in the read +code above. In this case use the PNG_PASS_ROWS and PNG_PASS_COLS macros +to determine the size of each sub-image in turn and simply write the rows +you obtained from the read code. + +.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) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_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 clears the newly +allocated memory to zero. There is limited support for certain systems +with segmented memory architectures and the types of pointers declared by +png.h match this; you will have to use appropriate pointers in your +application. 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_alloc_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_NO_SETJMP, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish, +as long as your function does not return. + +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), +which is illustrated in pngvalid.c and in contrib/visupng. + +.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 private or unknown chunks in a generic method, +via callback functions, instead of by modifying libpng functions. This +is illustrated in pngtest.c, which uses a callback function to handle a +private "vpAg" chunk and the new "sTER" chunk, which are both unknown to +libpng. + +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 placed in pngpriv.h, +which is only used by the routines inside libpng itself. +The files in libpng proper only include pngpriv.h and png.h, which +%14%in turn includes pngconf.h. +in turn includes pngconf.h and, as of libpng-1.5.0, pnglibconf.h. +As of libpng-1.5.0, pngpriv.h also includes three other private header +files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material +that previously appeared in the public headers. + +.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: + + #include zlib.h + 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. + + #include zlib.h + 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. + + #include zlib.h + 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); + +As of libpng version 1.5.4, additional APIs became +available to set these separately for non-IDAT +compressed chunks such as zTXt, iTXt, and iCCP: + + #include zlib.h + #if PNG_LIBPNG_VER <= 10504 + png_set_text_compression_level(png_ptr, level); + + png_set_text_compression_mem_level(png_ptr, level); + + png_set_text_compression_strategy(png_ptr, + strategy); + + png_set_text_compression_window_bits(png_ptr, + window_bits); + + png_set_text_compression_method(png_ptr, method); + #endif + +.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_. + +In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead. + +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 1.4.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). + +Note that this function does not take a png_ptr, so you can call it +before you've created one. + +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. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x + +Private libpng prototypes and macro definitions were moved from +png.h and pngconf.h into a new pngpriv.h header file. + +Functions png_set_benign_errors(), png_benign_error(), and +png_chunk_benign_error() were added. + +Support for setting the maximum amount of memory that the application +will allocate for reading chunks was added, as a security measure. +The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() +were added to the library. + +We implemented support for I/O states by adding png_ptr member io_state +and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + +We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level +input transforms. + +Checking for and reporting of errors in the IHDR chunk is more thorough. + +Support for global arrays was removed, to improve thread safety. + +Some obsolete/deprecated macros and functions have been removed. + +Typecasted NULL definitions such as + #define png_voidp_NULL (png_voidp)NULL +were eliminated. If you used these in your application, just use +NULL instead. + +The png_struct and info_struct members "trans" and "trans_values" were +changed to "trans_alpha" and "trans_color", respectively. + +The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles +were removed. + +The PNG_1_0_X and PNG_1_2_X macros were eliminated. + +The PNG_LEGACY_SUPPORTED macro was eliminated. + +Many WIN32_WCE #ifdefs were removed. + +The functions png_read_init(info_ptr), png_write_init(info_ptr), +png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() +have been removed. They have been deprecated since libpng-0.95. + +The png_permit_empty_plte() was removed. It has been deprecated +since libpng-1.0.9. Use png_permit_mng_features() instead. + +We removed the obsolete stub functions 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(), and png_mmx_supported() + +We removed the obsolete png_check_sig(), png_memcpy_check(), and +png_memset_check() functions. Instead use !png_sig_cmp(), memcpy(), +and memset(), respectively. + +The function png_set_gray_1_2_4_to_8() was removed. It has been +deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with +png_set_expand_gray_1_2_4_to_8() because the former function also +expanded any tRNS chunk to an alpha channel. + +Macros for png_get_uint_16, png_get_uint_32, and png_get_int_32 +were added and are used by default instead of the corresponding +functions. Unfortunately, +from libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. + +We changed the prototype for png_malloc() from + png_malloc(png_structp png_ptr, png_uint_32 size) +to + png_malloc(png_structp png_ptr, png_alloc_size_t size) + +This also applies to the prototype for the user replacement malloc_fn(). + +The png_calloc() function was added and is used in place of +of "png_malloc(); memset();" except in the case in png_read_png() +where the array consists of pointers; in this case a "for" loop is used +after the png_malloc() to set the pointers to NULL, to give robust. +behavior in case the application runs out of memory part-way through +the process. + +We changed the prototypes of png_get_compression_buffer_size() and +png_set_compression_buffer_size() to work with png_size_t instead of +png_uint_32. + +Support for numbered error messages was removed by default, since we +never got around to actually numbering the error messages. The function +png_set_strip_error_numbers() was removed from the library by default. + +The png_zalloc() and png_zfree() functions are no longer exported. +The png_zalloc() function no longer zeroes out the memory that it +allocates. + +Support for dithering was disabled by default in libpng-1.4.0, because +it has not been well tested and doesn't actually "dither". +The code was not +removed, however, and could be enabled by building libpng with +PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support +was reenabled, but the function was renamed png_set_quantize() to +reflect more accurately what it actually does. At the same time, +the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to +PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS, and PNG_READ_DITHER_SUPPORTED +was renamed to PNG_READ_QUANTIZE_SUPPORTED. + +We removed the trailing '.' from the warning and error messages. + +.SH X. Changes to Libpng from version 1.4.x to 1.5.x + +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. + +A. Changes that affect users of libpng + +There are no substantial API changes between the non-deprecated parts of +the 1.4.5 API and the 1.5.0 API, however the ability to directly access +the main libpng control structures, png_struct and png_info, deprecated +in earlier versions of libpng, has been completely removed from +libpng 1.5. + +We no longer include zlib.h in png.h. Applications that need access +to information in zlib.h will need to add the '#include "zlib.h"' +directive. It does not matter whether it is placed prior to or after +the '"#include png.h"' directive. + +We moved the png_strcpy(), png_strncpy(), png_strlen(), png_memcpy(), +png_memcmp(), png_sprintf, and png_memcpy() macros into a private +header file (pngpriv.h) that is not accessible to applications. + +In png_get_iCCP, the type of "profile" was changed from png_charpp +to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep. + +There are changes of form in png.h, including new and changed macros to +declare parts of the API. Some API functions with arguments that are +pointers to data not modified within the function have been corrected to +declare these arguments with PNG_CONST. + +Much of the internal use of C macros to control the library build has also +changed and some of this is visible in the exported header files, in +particular the use of macros to control data and API elements visible +during application compilation may require significant revision to +application code. (It is extremely rare for an application to do this.) + +Any program that compiled against libpng 1.4 and did not use deprecated +features or access internal library structures should compile and work +against libpng 1.5, except for the change in the prototype for +png_get_iCCP() and png_set_iCCP() API functions mentioned above. + +libpng 1.5.0 adds PNG_ PASS macros to help in the reading and writing of +interlaced images. The macros return the number of rows and columns in +each pass and information that can be used to de-interlace and (if +absolutely necessary) interlace an image. + +libpng 1.5.0 adds an API png_longjmp(png_ptr, value). This API calls +the application-provided png_longjmp_ptr on the internal, but application +initialized, longjmp buffer. It is provided as a convenience to avoid +the need to use the png_jmpbuf macro, which had the unnecessary side +effect of resetting the internal png_longjmp_ptr value. + +libpng 1.5.0 includes a complete fixed point API. By default this is +present along with the corresponding floating point API. In general the +fixed point API is faster and smaller than the floating point one because +the PNG file format used fixed point, not floating point. This applies +even if the library uses floating point in internal calculations. A new +macro, PNG_FLOATING_ARITHMETIC_SUPPORTED, reveals whether the library +uses floating point arithmetic (the default) or fixed point arithmetic +internally for performance critical calculations such as gamma correction. +In some cases, the gamma calculations may produce slightly different +results. This has changed the results in png_rgb_to_gray and in alpha +composition (png_set_background for example). This applies even if the +original image was already linear (gamma == 1.0) and, therefore, it is +not necessary to linearize the image. This is because libpng has *not* +been changed to optimize that case correctly, yet. + +Fixed point support for the sCAL chunk comes with an important caveat; +the sCAL specification uses a decimal encoding of floating point values +and the accuracy of PNG fixed point values is insufficient for +representation of these values. Consequently a "string" API +(png_get_sCAL_s and png_set_sCAL_s) is the only reliable way of reading +arbitrary sCAL chunks in the absence of either the floating point API or +internal floating point calculations. + +Applications no longer need to include the optional distribution header +file pngusr.h or define the corresponding macros during application +build in order to see the correct variant of the libpng API. From 1.5.0 +application code can check for the corresponding _SUPPORTED macro: + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED + /* code that uses the inch conversion APIs. */ +#endif + +This macro will only be defined if the inch conversion functions have been +compiled into libpng. The full set of macros, and whether or not support +has been compiled in, are available in the header file pnglibconf.h. +This header file is specific to the libpng build. Notice that prior to +1.5.0 the _SUPPORTED macros would always have the default definition unless +reset by pngusr.h or by explicit settings on the compiler command line. +These settings may produce compiler warnings or errors in 1.5.0 because +of macro redefinition. + +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. libpng 1.5.0 +is consistent with the implementation in 1.4.5 and 1.2.x (where the macro +did not exist.) + +Applications can now choose whether to use these macros or to call the +corresponding function by defining PNG_USE_READ_MACROS or +PNG_NO_USE_READ_MACROS before including png.h. Notice that this is +only supported from 1.5.0 -defining PNG_NO_USE_READ_MACROS prior to 1.5.0 +will lead to a link failure. + +Prior to libpng-1.5.4, the zlib compressor used the same set of parameters +when compressing the IDAT data and textual data such as zTXt and iCCP. +In libpng-1.5.4 we reinitialized the zlib stream for each type of data. +We added five png_set_text_*() functions for setting the parameters to +use with textual data. + +Prior to libpng-1.5.4, the PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +option was off by default, and slightly inaccurate scaling occurred. +This option can no longer be turned off, and the choice of accurate +or inaccurate 16-to-8 scaling is by using the new png_set_scale_16_to_8() +API for accurate scaling or the old png_set_strip_16_to_8() API for simple +chopping. + +Prior to libpng-1.5.4, the png_set_user_limits() function could only be +used to reduce the width and height limits from the value of +PNG_USER_WIDTH_MAX and PNG_USER_HEIGHT_MAX, although this document said +that it could be used to override them. Now this function will reduce or +increase the limits. + +B. Changes to the build and configuration of libpng + +Details of internal changes to the library code can be found in the CHANGES +file and in the GIT repository logs. These will be of no concern to the vast +majority of library users or builders, however the few who configure libpng +to a non-default feature set may need to change how this is done. + +There should be no need for library builders to alter build scripts if +these use the distributed build support - configure or the makefiles - +however users of the makefiles may care to update their build scripts +to build pnglibconf.h where the corresponding makefile does not do so. + +Building libpng with a non-default configuration has changed completely. +The old method using pngusr.h should still work correctly even though the +way pngusr.h is used in the build has been changed; however, library +builders will probably want to examine the changes to take advantage of +new capabilities and to simplify their build system. + +B.1 Specific changes to library configuration capabilities + +The library now supports a complete fixed point implementation and can +thus be used on systems that have no floating point support or very +limited or slow support. Previously gamma correction, an essential part +of complete PNG support, required reasonably fast floating point. + +As part of this the choice of internal implementation has been made +independent of the choice of fixed versus floating point APIs and all the +missing fixed point APIs have been implemented. + +The exact mechanism used to control attributes of API functions has +changed. A single set of operating system independent macro definitions +is used and operating system specific directives are defined in +pnglibconf.h + +As part of this the mechanism used to choose procedure call standards on +those systems that allow a choice has been changed. At present this only +affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems +running on Intel processors. As before, PNGAPI is defined where required +to control the exported API functions; however, two new macros, PNGCBAPI +and PNGCAPI, are used instead for callback functions (PNGCBAPI) and +(PNGCAPI) for functions that must match a C library prototype (currently +only png_longjmp_ptr, which must match the C longjmp function.) The new +approach is documented in pngconf.h + +Despite these changes, libpng 1.5.0 only supports the native C function +calling standard on those platforms tested so far (__cdecl on Microsoft +Windows). This is because the support requirements for alternative +calling conventions seem to no longer exist. Developers who find it +necessary to set PNG_API_RULE to 1 should advise the mailing list +(png-mng-implement) of this and library builders who use Openwatcom and +therefore set PNG_API_RULE to 2 should also contact the mailing list. + +A new test program, pngvalid, is provided in addition to pngtest. +pngvalid validates the arithmetic accuracy of the gamma correction +calculations and includes a number of validations of the file format. +A subset of the full range of tests is run when "make check" is done +(in the 'configure' build.) pngvalid also allows total allocated memory +usage to be evaluated and performs additional memory overwrite validation. + +Many changes to individual feature macros have been made. The following +are the changes most likely to be noticed by library builders who +configure libpng: + +1) All feature macros now have consistent naming: + +#define PNG_NO_feature turns the feature off +#define PNG_feature_SUPPORTED turns the feature on + +pnglibconf.h contains one line for each feature macro which is either: + +#define PNG_feature_SUPPORTED + +if the feature is supported or: + +/*#undef PNG_feature_SUPPORTED*/ + +if it is not. Library code consistently checks for the 'SUPPORTED' macro. +It does not, and libpng applications should not, check for the 'NO' macro +which will not normally be defined even if the feature is not supported. +The 'NO' macros are only used internally for setting or not setting the +corresponding 'SUPPORTED' macros. + +Compatibility with the old names is provided as follows: + +PNG_INCH_CONVERSIONS turns on PNG_INCH_CONVERSIONS_SUPPORTED + +And the following definitions disable the corresponding feature: + +PNG_SETJMP_NOT_SUPPORTED disables SETJMP +PNG_READ_TRANSFORMS_NOT_SUPPORTED disables READ_TRANSFORMS +PNG_NO_READ_COMPOSITED_NODIV disables READ_COMPOSITE_NODIV +PNG_WRITE_TRANSFORMS_NOT_SUPPORTED disables WRITE_TRANSFORMS +PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED disables READ_ANCILLARY_CHUNKS +PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED disables WRITE_ANCILLARY_CHUNKS + +Library builders should remove use of the above, inconsistent, names. + +2) Warning and error message formatting was previously conditional on +the STDIO feature. The library has been changed to use the +CONSOLE_IO feature instead. This means that if CONSOLE_IO is disabled +the library no longer uses the printf(3) functions, even though the +default read/write implementations use (FILE) style stdio.h functions. + +3) Three feature macros now control the fixed/floating point decisions: + +PNG_FLOATING_POINT_SUPPORTED enables the floating point APIs + +PNG_FIXED_POINT_SUPPORTED enables the fixed point APIs; however, in +practice these are normally required internally anyway (because the PNG +file format is fixed point), therefore in most cases PNG_NO_FIXED_POINT +merely stops the function from being exported. + +PNG_FLOATING_ARITHMETIC_SUPPORTED chooses between the internal floating +point implementation or the fixed point one. Typically the fixed point +implementation is larger and slower than the floating point implementation +on a system that supports floating point, however it may be faster on a +system which lacks floating point hardware and therefore uses a software +emulation. + +4) Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the +functions to read and write ints to be disabled independently of +PNG_USE_READ_MACROS, which allows libpng to be built with the functions +even though the default is to use the macros - this allows applications +to choose at app buildtime whether or not to use macros (previously +impossible because the functions weren't in the default build.) + +B.2 Changes to the configuration mechanism + +Prior to libpng-1.5.0 library builders who needed to configure libpng +had either to modify the exported pngconf.h header file to add system +specific configuration or had to write feature selection macros into +pngusr.h and cause this to be included into pngconf.h by defining +PNG_USER_CONFIG. The latter mechanism had the disadvantage that an +application built without PNG_USER_CONFIG defined would see the +unmodified, default, libpng API and thus would probably fail to link. + +These mechanisms still work in the configure build and in any makefile +build that builds pnglibconf.h, although the feature selection macros +have changed somewhat as described above. In 1.5.0, however, pngusr.h is +processed only once, when the exported header file pnglibconf.h is built. +pngconf.h no longer includes pngusr.h, therefore pngusr.h is ignored after the +build of pnglibconf.h and it is never included in an application build. + +The rarely used alternative of adding a list of feature macros to the +CFLAGS setting in the build also still works, however the macros will be +copied to pnglibconf.h and this may produce macro redefinition warnings +when the individual C files are compiled. + +All configuration now only works if pnglibconf.h is built from +scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan +(the original author of awk) maintains C source code of that awk and this +and all known later implementations (often called by subtly different +names - nawk and gawk for example) are adequate to build pnglibconf.h. +The Sun Microsystems (now Oracle) program 'awk' is an earlier version +and does not work; this may also apply to other systems that have a +functioning awk called 'nawk'. + +Configuration options are now documented in scripts/pnglibconf.dfa. This +file also includes dependency information that ensures a configuration is +consistent; that is, if a feature is switched off dependent features are +also removed. As a recommended alternative to using feature macros in +pngusr.h a system builder may also define equivalent options in pngusr.dfa +(or, indeed, any file) and add that to the configuration by setting +DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate +how to do this, and a case where pngusr.h is still required. + +.SH XI. 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 XII. 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 + +We also accept patches built from the tar or zip distributions, and +simple verbal discriptions of bug fixes, reported either to the +SourceForge bug tracker, to the png-mng-implement at lists.sf.net +mailing list, or directly to glennrp. + +.SH XIII. 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; + + /* This is a multiple-line + * comment. + */ + statement; + +Very short comments can be placed after 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 programmers. 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 +pngpriv.h +above the comment that says + + /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +To avoid polluting the global namespace, the names of all exported +functions and variables begin with "png_", and all publicly visible C +preprocessor macros begin with "PNG_". We request that applications that +use libpng *not* begin any of their own symbols with either of these strings. + +We put a space after each comma and after each semicolon +in "for" statements, and we put spaces before and after each +C binary operator and after "for" or "while", and before +"?". 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 prefer to express integers that are used as bit masks in hex format, +with an even number of lower-case hex digits (e.g., 0x00, 0xff, 0x0100). + +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 XIV. Y2K Compliance in libpng + +February 18, 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.5.9 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 12.so.0.1.0.17rc1 + 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + 1.0.17 10 10017 12.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 12.so.0.1.0.18rc1-5 + 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + 1.0.18 10 10018 12.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-7 13 10210 12.so.0.10[.0] + 1.2.10rc1-2 13 10210 12.so.0.10[.0] + 1.2.10 13 10210 12.so.0.10[.0] + 1.4.0beta1-6 14 10400 14.so.0.0[.0] + 1.2.11beta1-4 13 10210 12.so.0.11[.0] + 1.4.0beta7-8 14 10400 14.so.0.0[.0] + 1.2.11 13 10211 12.so.0.11[.0] + 1.2.12 13 10212 12.so.0.12[.0] + 1.4.0beta9-14 14 10400 14.so.0.0[.0] + 1.2.13 13 10213 12.so.0.13[.0] + 1.4.0beta15-36 14 10400 14.so.0.0[.0] + 1.4.0beta37-87 14 10400 14.so.14.0[.0] + 1.4.0rc01 14 10400 14.so.14.0[.0] + 1.4.0beta88-109 14 10400 14.so.14.0[.0] + 1.4.0rc02-08 14 10400 14.so.14.0[.0] + 1.4.0 14 10400 14.so.14.0[.0] + 1.4.1beta01-03 14 10401 14.so.14.1[.0] + 1.4.1rc01 14 10401 14.so.14.1[.0] + 1.4.1beta04-12 14 10401 14.so.14.1[.0] + 1.4.1 14 10401 14.so.14.1[.0] + 1.4.2 14 10402 14.so.14.2[.0] + 1.4.3 14 10403 14.so.14.3[.0] + 1.4.4 14 10404 14.so.14.4[.0] + 1.5.0beta01-58 15 10500 15.so.15.0[.0] + 1.5.0rc01-07 15 10500 15.so.15.0[.0] + 1.5.0 15 10500 15.so.15.0[.0] + 1.5.1beta01-11 15 10501 15.so.15.1[.0] + 1.5.1rc01-02 15 10501 15.so.15.1[.0] + 1.5.1 15 10501 15.so.15.1[.0] + 1.5.2beta01-03 15 10502 15.so.15.2[.0] + 1.5.2rc01-03 15 10502 15.so.15.2[.0] + 1.5.2 15 10502 15.so.15.2[.0] + 1.5.3beta01-10 15 10503 15.so.15.3[.0] + 1.5.3rc01-02 15 10503 15.so.15.3[.0] + 1.5.3beta11 15 10503 15.so.15.3[.0] + 1.5.3 [omitted] + 1.5.4beta01-08 15 10504 15.so.15.4[.0] + 1.5.4rc01 15 10504 15.so.15.4[.0] + 1.5.4 15 10504 15.so.15.4[.0] + 1.5.5beta01-08 15 10505 15.so.15.5[.0] + 1.5.5rc01 15 10505 15.so.15.5[.0] + 1.5.5 15 10505 15.so.15.5[.0] + 1.5.6beta01-07 15 10506 15.so.15.6[.0] + 1.5.6rc01-03 15 10506 15.so.15.6[.0] + 1.5.6 15 10506 15.so.15.6[.0] + 1.5.7beta01-05 15 10507 15.so.15.7[.0] + 1.5.7rc01-03 15 10507 15.so.15.7[.0] + 1.5.7 15 10507 15.so.15.7[.0] + 1.5.8beta01 15 10508 15.so.15.8[.0] + 1.5.8rc01 15 10508 15.so.15.8[.0] + 1.5.8 15 10508 15.so.15.8[.0] + 1.5.9beta01-02 15 10509 15.so.15.9[.0] + 1.5.9rc01 15 10509 15.so.15.9[.0] + 1.5.9 15 10509 15.so.15.9[.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 "rcN". + +.SH "SEE ALSO" +.BR "png"(5), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(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://ds.internic.net/rfc/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 + + +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.5.9 - February 18, 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.5.9, February 18, 2012, are +Copyright (c) 2004,2006-2007 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 +February 18, 2012 + +.\" end of man page + diff --git a/plugins/FreeImage/src/LibPNG/libpng.txt b/plugins/FreeImage/src/LibPNG/libpng.txt new file mode 100644 index 0000000000..f1eefbbb37 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/libpng.txt @@ -0,0 +1,3352 @@ +libpng.txt - A description on how to use and modify libpng + + libpng version 1.4.3 - June 26, 2010 + Updated and distributed by Glenn Randers-Pehrson + + 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.4.3 - June 26, 2010 + 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 +. 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 and as a +W3C Recommendation . + +Some additional chunks are described in the special-purpose public chunks +documents at . + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, . + +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, . +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 + +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_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +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); + +You can change the zlib compression buffer size to be used while +reading compressed data with + + png_set_compression_buffer_size(png_ptr, buffer_size); + +where the default size is 8192 bytes. Note that the buffer size +is changed immediately and the buffer is reallocated immediately, +instead of setting a flag to be acted upon later. + +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. + +You can also set a limit on the amount of memory that a compressed chunk +other than IDAT can occupy, with + + png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); + +and you can retrieve the limit with + + chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); + +Any chunks that would cause either of these limits to be exceeded will +be ignored. + +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, +quantizing, 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) and +png_get_(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_ 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_alpha, + &num_trans, &trans_color); + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + trans_color - 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.4.3, 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); + +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, +Copyright (c) 1998-01-04 Charles Poynton + + 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_quantize() +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_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_quantize(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_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +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_alpha, + num_trans, trans_color); + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + trans_color - 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_alloc_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_NO_SETJMP, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish, +as long as your function does not return. + +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 placed in pngpriv.h, +which is only used by the routines inside libpng itself. +The files in libpng proper only include pngpriv.h and png.h, which +in turn 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. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x + +Private libpng prototypes and macro definitions were moved from +png.h and pngconf.h into a new pngpriv.h header file. + +Functions png_set_benign_errors(), png_benign_error(), and +png_chunk_benign_error() were added. + +Support for setting the maximum amount of memory that the application +will allocate for reading chunks was added, as a security measure. +The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() +were added to the library. + +We implemented support for I/O states by adding png_ptr member io_state +and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + +We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level +input transforms. + +Checking for and reporting of errors in the IHDR chunk is more thorough. + +Support for global arrays was removed, to improve thread safety. + +Some obsolete/deprecated macros and functions have been removed. + +Typecasted NULL definitions such as + #define png_voidp_NULL (png_voidp)NULL +were eliminated. If you used these in your application, just use +NULL instead. + +The png_struct and info_struct members "trans" and "trans_values" were +changed to "trans_alpha" and "trans_color", respectively. + +The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles +were removed. + +The PNG_1_0_X and PNG_1_2_X macros were eliminated. + +The PNG_LEGACY_SUPPORTED macro was eliminated. + +Many WIN32_WCE #ifdefs were removed. + +The functions png_read_init(info_ptr), png_write_init(info_ptr), +png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() +have been removed. They have been deprecated since libpng-0.95. + +The png_permit_empty_plte() was removed. It has been deprecated +since libpng-1.0.9. Use png_permit_mng_features() instead. + +We removed the obsolete stub functions 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(), and png_mmx_supported() + +We removed the obsolete png_check_sig(), png_memcpy_check(), and +png_memset_check() functions. Instead use !png_sig_cmp(), png_memcpy(), +and png_memset(), respectively. + +The function png_set_gray_1_2_4_to_8() was removed. It has been +deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with +png_set_expand_gray_1_2_4_to_8() because the former function also +expanded palette images. + +We changed the prototype for png_malloc() from + png_malloc(png_structp png_ptr, png_uint_32 size) +to + png_malloc(png_structp png_ptr, png_alloc_size_t size) + +This also applies to the prototype for the user replacement malloc_fn(). + +The png_calloc() function was added and is used in place of +of "png_malloc(); png_memset();" except in the case in png_read_png() +where the array consists of pointers; in this case a "for" loop is used +after the png_malloc() to set the pointers to NULL, to give robust. +behavior in case the application runs out of memory part-way through +the process. + +We changed the prototypes of png_get_compression_buffer_size() and +png_set_compression_buffer_size() to work with png_size_t instead of +png_uint_32. + +Support for numbered error messages was removed by default, since we +never got around to actually numbering the error messages. The function +png_set_strip_error_numbers() was removed from the library by default. + +The png_zalloc() and png_zfree() functions are no longer exported. +The png_zalloc() function no longer zeroes out the memory that it +allocates. + +Support for dithering was disabled by default in libpng-1.4.0, because +been well tested and doesn't actually "dither". The code was not +removed, however, and could be enabled by building libpng with +PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support +was reenabled, but the function was renamed png_set_quantize() to +reflect more accurately what it actually does. At the same time, +the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to +PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS. + +We removed the trailing '.' from the warning and error messages. + +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; + + /* This is a multiple-line + * comment. + */ + statement; + +Very short comments can be placed after 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 +pngpriv.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", and before +"?". 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 + +June 26, 2010 + +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.4.3 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/plugins/FreeImage/src/LibPNG/libpngpf.3 b/plugins/FreeImage/src/LibPNG/libpngpf.3 new file mode 100644 index 0000000000..ef54f7b5b0 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/libpngpf.3 @@ -0,0 +1,28 @@ +.TH LIBPNGPF 3 "February 18, 2012" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.5.9 +(private functions) +.SH SYNOPSIS +\fB#include \fI"pngpriv.h" + +\fI\fB + +\fBAs of libpng version \fP\fI1.5.1\fP\fB, this section is no longer \fP\fImaintained\fP\fB, now \fIthat + +\fBthe private function prototypes are hidden in pngpriv.h and not \fIaccessible + +\fBto applications. Look in pngpriv.h for the prototypes and a short \fIdescription + +\fBof each \fIfunction. + +\fI\fB + +.SH DESCRIPTION +The functions previously listed here are used privately by libpng +and are not recommended for use by applications. They are +not "exported" to applications using shared libraries. + +.SH SEE ALSO +.BR "png"(5), " libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) +.SH AUTHOR +Glenn Randers-Pehrson diff --git a/plugins/FreeImage/src/LibPNG/png.5 b/plugins/FreeImage/src/LibPNG/png.5 new file mode 100644 index 0000000000..6df917d4ae --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/png.5 @@ -0,0 +1,74 @@ +.TH PNG 5 "February 18, 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" +.BR "libpng"(3), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) +.LP +PNG specification (second edition), November 2003: +.IP +.br + 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 behavior as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_const_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))); +} + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib */ +PNG_FUNCTION(voidpf /* PRIVATE */, +png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) +{ + png_voidp ptr; + png_structp p=(png_structp)png_ptr; + png_uint_32 save_flags=p->flags; + png_alloc_size_t 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_alloc_size_t)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; + + return ((voidpf)ptr); +} + +/* Function to free memory for zlib */ +void /* PRIVATE */ +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) +{ + /* The cast is safe because the crc is a 32 bit value. */ + png_ptr->crc = (png_uint_32)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_const_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name)) + { + 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; + } + + /* 'uLong' is defined as unsigned long, this means that on some systems it is + * a 64 bit value. crc32, however, returns 32 bits so the following cast is + * safe. 'uInt' may be no more than 16 bits, so it is necessary to perform a + * loop here. + */ + if (need_crc && length > 0) + { + uLong crc = png_ptr->crc; /* Should never issue a warning */ + + do + { + uInt safeLength = (uInt)length; + if (safeLength == 0) + safeLength = (uInt)-1; /* evil, but safe */ + + crc = crc32(crc, ptr, safeLength); + + /* The following should never issue compiler warnings, if they do the + * target system has characteristics that will probably violate other + * assumptions within the libpng code. + */ + ptr += safeLength; + length -= safeLength; + } + while (length > 0); + + /* And the following is always safe because the crc is only 32 bits. */ + png_ptr->crc = (png_uint_32)crc; + } +} + +/* Check a user supplied version number, called from both read and write + * functions that create a png_struct + */ +int +png_user_version_check(png_structp png_ptr, png_const_charp user_png_ver) +{ + if (user_png_ver) + { + int 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')) + { +#ifdef PNG_WARNINGS_SUPPORTED + size_t pos = 0; + char m[128]; + + pos = png_safecat(m, sizeof m, pos, "Application built with libpng-"); + pos = png_safecat(m, sizeof m, pos, user_png_ver); + pos = png_safecat(m, sizeof m, pos, " but running with "); + pos = png_safecat(m, sizeof m, pos, png_libpng_ver); + + png_warning(png_ptr, m); +#endif + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + + return 0; + } + } + + /* Success return. */ + return 1; +} + +/* 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_FUNCTION(png_infop,PNGAPI +png_create_info_struct,(png_structp png_ptr),PNG_ALLOCATED) +{ + 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. + */ + +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)); +} + +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"); +} + +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 */ + if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) + { + 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 */ + if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->trans_alpha); + info_ptr->trans_alpha = NULL; + info_ptr->valid &= ~PNG_INFO_tRNS; + } +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* Free any sCAL entry */ + if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) + { + 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; + info_ptr->valid &= ~PNG_INFO_sCAL; + } +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* Free any pCAL entry */ + if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) + { + 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 */ + if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) + { + 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 */ + if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) + { + 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; + } + + if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) + { + 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 < 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 */ + if ((mask & PNG_FREE_HIST) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; + } +#endif + + /* Free any PLTE entry that was internally allocated */ + if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) + { + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; + info_ptr->num_palette = 0; + } + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Free any image bits attached to the info structure */ + if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) + { + 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 + + if (num != -1) + mask &= ~PNG_FREE_MUL; + + info_ptr->free_me &= ~mask; +} + +/* 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 or otherwise disabled PNG_STDIO_SUPPORTED, 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_const_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_const_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 (ptime->year > 9999 /* RFC1123 limitation */ || + ptime->month == 0 || ptime->month > 12 || + ptime->day == 0 || ptime->day > 31 || + ptime->hour > 23 || ptime->minute > 59 || + ptime->second > 60) + { + png_warning(png_ptr, "Ignoring invalid time value"); + return (NULL); + } + + { + size_t pos = 0; + char number_buf[5]; /* enough for a four-digit year */ + +# define APPEND_STRING(string)\ + pos = png_safecat(png_ptr->time_buffer, sizeof png_ptr->time_buffer,\ + pos, (string)) +# define APPEND_NUMBER(format, value)\ + APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value))) +# define APPEND(ch)\ + if (pos < (sizeof png_ptr->time_buffer)-1)\ + png_ptr->time_buffer[pos++] = (ch) + + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day); + APPEND(' '); + APPEND_STRING(short_months[(ptime->month - 1)]); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second); + APPEND_STRING(" +0000"); /* This reliably terminates the buffer */ + +# undef APPEND +# undef APPEND_NUMBER +# undef APPEND_STRING + } + + return png_ptr->time_buffer; +} +# endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_const_charp PNGAPI +png_get_copyright(png_const_structp png_ptr) +{ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef PNG_STRING_COPYRIGHT + return PNG_STRING_COPYRIGHT +#else +# ifdef __STDC__ + return PNG_STRING_NEWLINE \ + "libpng version 1.5.9 - February 18, 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 "libpng version 1.5.9 - February 18, 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_const_charp PNGAPI +png_get_libpng_ver(png_const_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + return png_get_header_ver(png_ptr); +} + +png_const_charp PNGAPI +png_get_header_ver(png_const_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ + return PNG_LIBPNG_VER_STRING; +} + +png_const_charp PNGAPI +png_get_header_version(png_const_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef __STDC__ + return PNG_HEADER_VERSION_STRING +# ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +# endif + PNG_STRING_NEWLINE; +#else + return PNG_HEADER_VERSION_STRING; +#endif +} + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_structp png_ptr, png_const_bytep chunk_name) +{ + /* Check chunk_name and return "keep" value if it's on the list, else 0 */ + png_const_bytep p, p_end; + + if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list <= 0) + return PNG_HANDLE_CHUNK_AS_DEFAULT; + + p_end = png_ptr->chunk_list; + p = p_end + png_ptr->num_chunk_list*5; /* beyond end */ + + /* The code is the fifth byte after each four byte string. Historically this + * code was always searched from the end of the list, so it should continue + * to do so in case there are duplicated entries. + */ + do /* num_chunk_list > 0, so at least one */ + { + p -= 5; + if (!png_memcmp(chunk_name, p, 4)) + return p[4]; + } + while (p > p_end); + + return PNG_HANDLE_CHUNK_AS_DEFAULT; +} + +int /* PRIVATE */ +png_chunk_unknown_handling(png_structp png_ptr, png_uint_32 chunk_name) +{ + png_byte chunk_string[5]; + + PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name); + return png_handle_as_unknown(png_ptr, chunk_string); +} +#endif + +#ifdef PNG_READ_SUPPORTED +/* 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 /* PNG_READ_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_WRITE_SUPPORTED) +/* png_convert_size: a PNGAPI but no longer in png.h, so deleted + * at libpng 1.5.5! + */ + +/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ +# ifdef PNG_CHECK_cHRM_SUPPORTED + +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; + + /* (x,y,z) values are first limited to 0..100000 (PNG_FP_1), the white + * y must also be greater than 0. To test for the upper limit calculate + * (PNG_FP_1-y) - x must be <= to this for z to be >= 0 (and the expression + * cannot overflow.) At this point we know x and y are >= 0 and (x+y) is + * <= PNG_FP_1. The previous test on PNG_MAX_UINT_31 is removed because it + * pointless (and it produces compiler warnings!) + */ + 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; + } + /* And (x+y) must be <= PNG_FP_1 (so z is >= 0) */ + if (white_x > PNG_FP_1 - white_y) + { + png_warning(png_ptr, "Invalid cHRM white point"); + ret = 0; + } + + if (red_x > PNG_FP_1 - red_y) + { + png_warning(png_ptr, "Invalid cHRM red point"); + ret = 0; + } + + if (green_x > PNG_FP_1 - green_y) + { + png_warning(png_ptr, "Invalid cHRM green point"); + ret = 0; + } + + if (blue_x > PNG_FP_1 - 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 */ + +#ifdef PNG_cHRM_SUPPORTED +/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for + * cHRM, as opposed to using chromaticities. These internal APIs return + * non-zero on a parameter error. The X, Y and Z values are required to be + * positive and less than 1.0. + */ +int png_xy_from_XYZ(png_xy *xy, png_XYZ XYZ) +{ + png_int_32 d, dwhite, whiteX, whiteY; + + d = XYZ.redX + XYZ.redY + XYZ.redZ; + if (!png_muldiv(&xy->redx, XYZ.redX, PNG_FP_1, d)) return 1; + if (!png_muldiv(&xy->redy, XYZ.redY, PNG_FP_1, d)) return 1; + dwhite = d; + whiteX = XYZ.redX; + whiteY = XYZ.redY; + + d = XYZ.greenX + XYZ.greenY + XYZ.greenZ; + if (!png_muldiv(&xy->greenx, XYZ.greenX, PNG_FP_1, d)) return 1; + if (!png_muldiv(&xy->greeny, XYZ.greenY, PNG_FP_1, d)) return 1; + dwhite += d; + whiteX += XYZ.greenX; + whiteY += XYZ.greenY; + + d = XYZ.blueX + XYZ.blueY + XYZ.blueZ; + if (!png_muldiv(&xy->bluex, XYZ.blueX, PNG_FP_1, d)) return 1; + if (!png_muldiv(&xy->bluey, XYZ.blueY, PNG_FP_1, d)) return 1; + dwhite += d; + whiteX += XYZ.blueX; + whiteY += XYZ.blueY; + + /* The reference white is simply the same of the end-point (X,Y,Z) vectors, + * thus: + */ + if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1; + if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1; + + return 0; +} + +int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy) +{ + png_fixed_point red_inverse, green_inverse, blue_scale; + png_fixed_point left, right, denominator; + + /* Check xy and, implicitly, z. Note that wide gamut color spaces typically + * have end points with 0 tristimulus values (these are impossible end + * points, but they are used to cover the possible colors.) + */ + if (xy.redx < 0 || xy.redx > PNG_FP_1) return 1; + if (xy.redy < 0 || xy.redy > PNG_FP_1-xy.redx) return 1; + if (xy.greenx < 0 || xy.greenx > PNG_FP_1) return 1; + if (xy.greeny < 0 || xy.greeny > PNG_FP_1-xy.greenx) return 1; + if (xy.bluex < 0 || xy.bluex > PNG_FP_1) return 1; + if (xy.bluey < 0 || xy.bluey > PNG_FP_1-xy.bluex) return 1; + if (xy.whitex < 0 || xy.whitex > PNG_FP_1) return 1; + if (xy.whitey < 0 || xy.whitey > PNG_FP_1-xy.whitex) return 1; + + /* The reverse calculation is more difficult because the original tristimulus + * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 + * derived values were recorded in the cHRM chunk; + * (red,green,blue,white)x(x,y). This loses one degree of freedom and + * therefore an arbitrary ninth value has to be introduced to undo the + * original transformations. + * + * Think of the original end-points as points in (X,Y,Z) space. The + * chromaticity values (c) have the property: + * + * C + * c = --------- + * X + Y + Z + * + * For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the + * three chromaticity values (x,y,z) for each end-point obey the + * relationship: + * + * x + y + z = 1 + * + * This describes the plane in (X,Y,Z) space that intersects each axis at the + * value 1.0; call this the chromaticity plane. Thus the chromaticity + * calculation has scaled each end-point so that it is on the x+y+z=1 plane + * and chromaticity is the intersection of the vector from the origin to the + * (X,Y,Z) value with the chromaticity plane. + * + * To fully invert the chromaticity calculation we would need the three + * end-point scale factors, (red-scale, green-scale, blue-scale), but these + * were not recorded. Instead we calculated the reference white (X,Y,Z) and + * recorded the chromaticity of this. The reference white (X,Y,Z) would have + * given all three of the scale factors since: + * + * color-C = color-c * color-scale + * white-C = red-C + green-C + blue-C + * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale + * + * But cHRM records only white-x and white-y, so we have lost the white scale + * factor: + * + * white-C = white-c*white-scale + * + * To handle this the inverse transformation makes an arbitrary assumption + * about white-scale: + * + * Assume: white-Y = 1.0 + * Hence: white-scale = 1/white-y + * Or: red-Y + green-Y + blue-Y = 1.0 + * + * Notice the last statement of the assumption gives an equation in three of + * the nine values we want to calculate. 8 more equations come from the + * above routine as summarised at the top above (the chromaticity + * calculation): + * + * Given: color-x = color-X / (color-X + color-Y + color-Z) + * Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0 + * + * This is 9 simultaneous equations in the 9 variables "color-C" and can be + * solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix + * determinants, however this is not as bad as it seems because only 28 of + * the total of 90 terms in the various matrices are non-zero. Nevertheless + * Cramer's rule is notoriously numerically unstable because the determinant + * calculation involves the difference of large, but similar, numbers. It is + * difficult to be sure that the calculation is stable for real world values + * and it is certain that it becomes unstable where the end points are close + * together. + * + * So this code uses the perhaps slighly less optimal but more understandable + * and totally obvious approach of calculating color-scale. + * + * This algorithm depends on the precision in white-scale and that is + * (1/white-y), so we can immediately see that as white-y approaches 0 the + * accuracy inherent in the cHRM chunk drops off substantially. + * + * libpng arithmetic: a simple invertion of the above equations + * ------------------------------------------------------------ + * + * white_scale = 1/white-y + * white-X = white-x * white-scale + * white-Y = 1.0 + * white-Z = (1 - white-x - white-y) * white_scale + * + * white-C = red-C + green-C + blue-C + * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale + * + * This gives us three equations in (red-scale,green-scale,blue-scale) where + * all the coefficients are now known: + * + * red-x*red-scale + green-x*green-scale + blue-x*blue-scale + * = white-x/white-y + * red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1 + * red-z*red-scale + green-z*green-scale + blue-z*blue-scale + * = (1 - white-x - white-y)/white-y + * + * In the last equation color-z is (1 - color-x - color-y) so we can add all + * three equations together to get an alternative third: + * + * red-scale + green-scale + blue-scale = 1/white-y = white-scale + * + * So now we have a Cramer's rule solution where the determinants are just + * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve + * multiplication of three coefficients so we can't guarantee to avoid + * overflow in the libpng fixed point representation. Using Cramer's rule in + * floating point is probably a good choice here, but it's not an option for + * fixed point. Instead proceed to simplify the first two equations by + * eliminating what is likely to be the largest value, blue-scale: + * + * blue-scale = white-scale - red-scale - green-scale + * + * Hence: + * + * (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale = + * (white-x - blue-x)*white-scale + * + * (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale = + * 1 - blue-y*white-scale + * + * And now we can trivially solve for (red-scale,green-scale): + * + * green-scale = + * (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale + * ----------------------------------------------------------- + * green-x - blue-x + * + * red-scale = + * 1 - blue-y*white-scale - (green-y - blue-y) * green-scale + * --------------------------------------------------------- + * red-y - blue-y + * + * Hence: + * + * red-scale = + * ( (green-x - blue-x) * (white-y - blue-y) - + * (green-y - blue-y) * (white-x - blue-x)) / white-y + * ------------------------------------------------------------------------- + * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) + * + * green-scale = + * ( (red-y - blue-y) * (white-x - blue-x) - + * (red-x - blue-x) * (white-y - blue-y)) / white-y + * ------------------------------------------------------------------------- + * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) + * + * Accuracy: + * The input values have 5 decimal digits of accuracy. The values are all in + * the range 0 < value < 1, so simple products are in the same range but may + * need up to 10 decimal digits to preserve the original precision and avoid + * underflow. Because we are using a 32-bit signed representation we cannot + * match this; the best is a little over 9 decimal digits, less than 10. + * + * The approach used here is to preserve the maximum precision within the + * signed representation. Because the red-scale calculation above uses the + * difference between two products of values that must be in the range -1..+1 + * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The + * factor is irrelevant in the calculation because it is applied to both + * numerator and denominator. + * + * Note that the values of the differences of the products of the + * chromaticities in the above equations tend to be small, for example for + * the sRGB chromaticities they are: + * + * red numerator: -0.04751 + * green numerator: -0.08788 + * denominator: -0.2241 (without white-y multiplication) + * + * The resultant Y coefficients from the chromaticities of some widely used + * color space definitions are (to 15 decimal places): + * + * sRGB + * 0.212639005871510 0.715168678767756 0.072192315360734 + * Kodak ProPhoto + * 0.288071128229293 0.711843217810102 0.000085653960605 + * Adobe RGB + * 0.297344975250536 0.627363566255466 0.075291458493998 + * Adobe Wide Gamut RGB + * 0.258728243040113 0.724682314948566 0.016589442011321 + */ + /* By the argument, above overflow should be impossible here. The return + * value of 2 indicates an internal error to the caller. + */ + if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.redy - xy.bluey, 7)) return 2; + if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.redx - xy.bluex, 7)) return 2; + denominator = left - right; + + /* Now find the red numerator. */ + if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2; + if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.whitex-xy.bluex, 7)) return 2; + + /* Overflow is possible here and it indicates an extreme set of PNG cHRM + * chunk values. This calculation actually returns the reciprocal of the + * scale value because this allows us to delay the multiplication of white-y + * into the denominator, which tends to produce a small number. + */ + if (!png_muldiv(&red_inverse, xy.whitey, denominator, left-right) || + red_inverse <= xy.whitey /* r+g+b scales = white scale */) + return 1; + + /* Similarly for green_inverse: */ + if (!png_muldiv(&left, xy.redy-xy.bluey, xy.whitex-xy.bluex, 7)) return 2; + if (!png_muldiv(&right, xy.redx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2; + if (!png_muldiv(&green_inverse, xy.whitey, denominator, left-right) || + green_inverse <= xy.whitey) + return 1; + + /* And the blue scale, the checks above guarantee this can't overflow but it + * can still produce 0 for extreme cHRM values. + */ + blue_scale = png_reciprocal(xy.whitey) - png_reciprocal(red_inverse) - + png_reciprocal(green_inverse); + if (blue_scale <= 0) return 1; + + + /* And fill in the png_XYZ: */ + if (!png_muldiv(&XYZ->redX, xy.redx, PNG_FP_1, red_inverse)) return 1; + if (!png_muldiv(&XYZ->redY, xy.redy, PNG_FP_1, red_inverse)) return 1; + if (!png_muldiv(&XYZ->redZ, PNG_FP_1 - xy.redx - xy.redy, PNG_FP_1, + red_inverse)) + return 1; + + if (!png_muldiv(&XYZ->greenX, xy.greenx, PNG_FP_1, green_inverse)) return 1; + if (!png_muldiv(&XYZ->greenY, xy.greeny, PNG_FP_1, green_inverse)) return 1; + if (!png_muldiv(&XYZ->greenZ, PNG_FP_1 - xy.greenx - xy.greeny, PNG_FP_1, + green_inverse)) + return 1; + + if (!png_muldiv(&XYZ->blueX, xy.bluex, blue_scale, PNG_FP_1)) return 1; + if (!png_muldiv(&XYZ->blueY, xy.bluey, blue_scale, PNG_FP_1)) return 1; + if (!png_muldiv(&XYZ->blueZ, PNG_FP_1 - xy.bluex - xy.bluey, blue_scale, + PNG_FP_1)) + return 1; + + return 0; /*success*/ +} + +int png_XYZ_from_xy_checked(png_structp png_ptr, png_XYZ *XYZ, png_xy xy) +{ + switch (png_XYZ_from_xy(XYZ, xy)) + { + case 0: /* success */ + return 1; + + case 1: + /* The chunk may be technically valid, but we got png_fixed_point + * overflow while trying to get XYZ values out of it. This is + * entirely benign - the cHRM chunk is pretty extreme. + */ + png_warning(png_ptr, + "extreme cHRM chunk cannot be converted to tristimulus values"); + break; + + default: + /* libpng is broken; this should be a warning but if it happens we + * want error reports so for the moment it is an error. + */ + png_error(png_ptr, "internal error in png_XYZ_from_xy"); + break; + } + + /* ERROR RETURN */ + return 0; +} +#endif + +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) + +# 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) +# 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 */ + - 48 /* 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"); +} + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* ASCII to fp functions */ +/* Check an ASCII formated floating point value, see the more detailed + * comments in pngpriv.h + */ +/* The following is used internally to preserve the sticky flags */ +#define png_fp_add(state, flags) ((state) |= (flags)) +#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) + +int /* PRIVATE */ +png_check_fp_number(png_const_charp string, png_size_t size, int *statep, + png_size_tp whereami) +{ + int state = *statep; + png_size_t i = *whereami; + + while (i < size) + { + int type; + /* First find the type of the next character */ + switch (string[i]) + { + case 43: type = PNG_FP_SAW_SIGN; break; + case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break; + case 46: type = PNG_FP_SAW_DOT; break; + case 48: type = PNG_FP_SAW_DIGIT; break; + case 49: case 50: case 51: case 52: + case 53: case 54: case 55: case 56: + case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break; + case 69: + case 101: type = PNG_FP_SAW_E; break; + default: goto PNG_FP_End; + } + + /* Now deal with this type according to the current + * state, the type is arranged to not overlap the + * bits of the PNG_FP_STATE. + */ + switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY)) + { + case PNG_FP_INTEGER + PNG_FP_SAW_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, type); + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_DOT: + /* Ok as trailer, ok as lead of fraction. */ + if (state & PNG_FP_SAW_DOT) /* two dots */ + goto PNG_FP_End; + + else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */ + png_fp_add(state, type); + + else + png_fp_set(state, PNG_FP_FRACTION | type); + + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT: + if (state & PNG_FP_SAW_DOT) /* delayed fraction */ + png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); + + png_fp_add(state, type | PNG_FP_WAS_VALID); + + break; + + case PNG_FP_INTEGER + PNG_FP_SAW_E: + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: + goto PNG_FP_End; ** no sign in fraction */ + + /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: + goto PNG_FP_End; ** Because SAW_DOT is always set */ + + case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT: + png_fp_add(state, type | PNG_FP_WAS_VALID); + break; + + case PNG_FP_FRACTION + PNG_FP_SAW_E: + /* This is correct because the trailing '.' on an + * integer is handled above - so we can only get here + * with the sequence ".E" (with no preceding digits). + */ + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, PNG_FP_SAW_SIGN); + + break; + + /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: + goto PNG_FP_End; */ + + case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT: + png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID); + + break; + + /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: + goto PNG_FP_End; */ + + default: goto PNG_FP_End; /* I.e. break 2 */ + } + + /* The character seems ok, continue. */ + ++i; + } + +PNG_FP_End: + /* Here at the end, update the state and return the correct + * return code. + */ + *statep = state; + *whereami = i; + + return (state & PNG_FP_SAW_DIGIT) != 0; +} + + +/* The same but for a complete string. */ +int +png_check_fp_string(png_const_charp string, png_size_t size) +{ + int state=0; + png_size_t char_index=0; + + if (png_check_fp_number(string, size, &state, &char_index) && + (char_index == size || string[char_index] == 0)) + return state /* must be non-zero - see above */; + + return 0; /* i.e. fail */ +} +#endif /* pCAL or sCAL */ + +#ifdef PNG_READ_sCAL_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +/* Utility used below - a simple accurate power of ten from an integral + * exponent. + */ +static double +png_pow10(int power) +{ + int recip = 0; + double d = 1; + + /* Handle negative exponent with a reciprocal at the end because + * 10 is exact whereas .1 is inexact in base 2 + */ + if (power < 0) + { + if (power < DBL_MIN_10_EXP) return 0; + recip = 1, power = -power; + } + + if (power > 0) + { + /* Decompose power bitwise. */ + double mult = 10; + do + { + if (power & 1) d *= mult; + mult *= mult; + power >>= 1; + } + while (power > 0); + + if (recip) d = 1/d; + } + /* else power is 0 and d is 1 */ + + return d; +} + +/* Function to format a floating point value in ASCII with a given + * precision. + */ +void /* PRIVATE */ +png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size, + double fp, unsigned int precision) +{ + /* We use standard functions from math.h, but not printf because + * that would require stdio. The caller must supply a buffer of + * sufficient size or we will png_error. The tests on size and + * the space in ascii[] consumed are indicated below. + */ + if (precision < 1) + precision = DBL_DIG; + + /* Enforce the limit of the implementation precision too. */ + if (precision > DBL_DIG+1) + precision = DBL_DIG+1; + + /* Basic sanity checks */ + if (size >= precision+5) /* See the requirements below. */ + { + if (fp < 0) + { + fp = -fp; + *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */ + --size; + } + + if (fp >= DBL_MIN && fp <= DBL_MAX) + { + int exp_b10; /* A base 10 exponent */ + double base; /* 10^exp_b10 */ + + /* First extract a base 10 exponent of the number, + * the calculation below rounds down when converting + * from base 2 to base 10 (multiply by log10(2) - + * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to + * be increased. Note that the arithmetic shift + * performs a floor() unlike C arithmetic - using a + * C multiply would break the following for negative + * exponents. + */ + (void)frexp(fp, &exp_b10); /* exponent to base 2 */ + + exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ + + /* Avoid underflow here. */ + base = png_pow10(exp_b10); /* May underflow */ + + while (base < DBL_MIN || base < fp) + { + /* And this may overflow. */ + double test = png_pow10(exp_b10+1); + + if (test <= DBL_MAX) + ++exp_b10, base = test; + + else + break; + } + + /* Normalize fp and correct exp_b10, after this fp is in the + * range [.1,1) and exp_b10 is both the exponent and the digit + * *before* which the decimal point should be inserted + * (starting with 0 for the first digit). Note that this + * works even if 10^exp_b10 is out of range because of the + * test on DBL_MAX above. + */ + fp /= base; + while (fp >= 1) fp /= 10, ++exp_b10; + + /* Because of the code above fp may, at this point, be + * less than .1, this is ok because the code below can + * handle the leading zeros this generates, so no attempt + * is made to correct that here. + */ + + { + int czero, clead, cdigits; + char exponent[10]; + + /* Allow up to two leading zeros - this will not lengthen + * the number compared to using E-n. + */ + if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ + { + czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ + exp_b10 = 0; /* Dot added below before first output. */ + } + else + czero = 0; /* No zeros to add */ + + /* Generate the digit list, stripping trailing zeros and + * inserting a '.' before a digit if the exponent is 0. + */ + clead = czero; /* Count of leading zeros */ + cdigits = 0; /* Count of digits in list. */ + + do + { + double d; + + fp *= 10; + /* Use modf here, not floor and subtract, so that + * the separation is done in one step. At the end + * of the loop don't break the number into parts so + * that the final digit is rounded. + */ + if (cdigits+czero-clead+1 < (int)precision) + fp = modf(fp, &d); + + else + { + d = floor(fp + .5); + + if (d > 9) + { + /* Rounding up to 10, handle that here. */ + if (czero > 0) + { + --czero, d = 1; + if (cdigits == 0) --clead; + } + else + { + while (cdigits > 0 && d > 9) + { + int ch = *--ascii; + + if (exp_b10 != (-1)) + ++exp_b10; + + else if (ch == 46) + { + ch = *--ascii, ++size; + /* Advance exp_b10 to '1', so that the + * decimal point happens after the + * previous digit. + */ + exp_b10 = 1; + } + + --cdigits; + d = ch - 47; /* I.e. 1+(ch-48) */ + } + + /* Did we reach the beginning? If so adjust the + * exponent but take into account the leading + * decimal point. + */ + if (d > 9) /* cdigits == 0 */ + { + if (exp_b10 == (-1)) + { + /* Leading decimal point (plus zeros?), if + * we lose the decimal point here it must + * be reentered below. + */ + int ch = *--ascii; + + if (ch == 46) + ++size, exp_b10 = 1; + + /* Else lost a leading zero, so 'exp_b10' is + * still ok at (-1) + */ + } + else + ++exp_b10; + + /* In all cases we output a '1' */ + d = 1; + } + } + } + fp = 0; /* Guarantees termination below. */ + } + + if (d == 0) + { + ++czero; + if (cdigits == 0) ++clead; + } + else + { + /* Included embedded zeros in the digit count. */ + cdigits += czero - clead; + clead = 0; + + while (czero > 0) + { + /* exp_b10 == (-1) means we just output the decimal + * place - after the DP don't adjust 'exp_b10' any + * more! + */ + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; + /* PLUS 1: TOTAL 4 */ + --exp_b10; + } + *ascii++ = 48, --czero; + } + + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; /* counted + above */ + --exp_b10; + } + *ascii++ = (char)(48 + (int)d), ++cdigits; + } + } + while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); + + /* The total output count (max) is now 4+precision */ + + /* Check for an exponent, if we don't need one we are + * done and just need to terminate the string. At + * this point exp_b10==(-1) is effectively if flag - it got + * to '-1' because of the decrement after outputing + * the decimal point above (the exponent required is + * *not* -1!) + */ + if (exp_b10 >= (-1) && exp_b10 <= 2) + { + /* The following only happens if we didn't output the + * leading zeros above for negative exponent, so this + * doest add to the digit requirement. Note that the + * two zeros here can only be output if the two leading + * zeros were *not* output, so this doesn't increase + * the output count. + */ + while (--exp_b10 >= 0) *ascii++ = 48; + + *ascii = 0; + + /* Total buffer requirement (including the '\0') is + * 5+precision - see check at the start. + */ + return; + } + + /* Here if an exponent is required, adjust size for + * the digits we output but did not count. The total + * digit output here so far is at most 1+precision - no + * decimal point and no leading or trailing zeros have + * been output. + */ + size -= cdigits; + + *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ + + /* The following use of an unsigned temporary avoids ambiguities in + * the signed arithmetic on exp_b10 and permits GCC at least to do + * better optimization. + */ + { + unsigned int uexp_b10; + + if (exp_b10 < 0) + { + *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ + uexp_b10 = -exp_b10; + } + + else + uexp_b10 = exp_b10; + + cdigits = 0; + + while (uexp_b10 > 0) + { + exponent[cdigits++] = (char)(48 + uexp_b10 % 10); + uexp_b10 /= 10; + } + } + + /* Need another size check here for the exponent digits, so + * this need not be considered above. + */ + if ((int)size > cdigits) + { + while (cdigits > 0) *ascii++ = exponent[--cdigits]; + + *ascii = 0; + + return; + } + } + } + else if (!(fp >= DBL_MIN)) + { + *ascii++ = 48; /* '0' */ + *ascii = 0; + return; + } + else + { + *ascii++ = 105; /* 'i' */ + *ascii++ = 110; /* 'n' */ + *ascii++ = 102; /* 'f' */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} + +# endif /* FLOATING_POINT */ + +# ifdef PNG_FIXED_POINT_SUPPORTED +/* Function to format a fixed point value in ASCII. + */ +void /* PRIVATE */ +png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size, + png_fixed_point fp) +{ + /* Require space for 10 decimal digits, a decimal point, a minus sign and a + * trailing \0, 13 characters: + */ + if (size > 12) + { + png_uint_32 num; + + /* Avoid overflow here on the minimum integer. */ + if (fp < 0) + *ascii++ = 45, --size, num = -fp; + else + num = fp; + + if (num <= 0x80000000) /* else overflowed */ + { + unsigned int ndigits = 0, first = 16 /* flag value */; + char digits[10]; + + while (num) + { + /* Split the low digit off num: */ + unsigned int tmp = num/10; + num -= tmp*10; + digits[ndigits++] = (char)(48 + num); + /* Record the first non-zero digit, note that this is a number + * starting at 1, it's not actually the array index. + */ + if (first == 16 && num > 0) + first = ndigits; + num = tmp; + } + + if (ndigits > 0) + { + while (ndigits > 5) *ascii++ = digits[--ndigits]; + /* The remaining digits are fractional digits, ndigits is '5' or + * smaller at this point. It is certainly not zero. Check for a + * non-zero fractional digit: + */ + if (first <= 5) + { + unsigned int i; + *ascii++ = 46; /* decimal point */ + /* ndigits may be <5 for small numbers, output leading zeros + * then ndigits digits to first: + */ + i = 5; + while (ndigits < i) *ascii++ = 48, --i; + while (ndigits >= first) *ascii++ = digits[--ndigits]; + /* Don't output the trailing zeros! */ + } + } + else + *ascii++ = 48; + + /* And null terminate the string: */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} +# endif /* FIXED_POINT */ +#endif /* READ_SCAL */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) +png_fixed_point +png_fixed(png_structp png_ptr, double fp, png_const_charp text) +{ + double r = floor(100000 * fp + .5); + + if (r > 2147483647. || r < -2147483648.) + png_fixed_error(png_ptr, text); + + return (png_fixed_point)r; +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || \ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED) +/* muldiv functions */ +/* This API takes signed arguments and rounds the result to the nearest + * integer (or, for a fixed point number - the standard argument - to + * the nearest .00001). Overflow and divide by zero are signalled in + * the result, a boolean - true on success, false on overflow. + */ +int +png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + /* Return a * times / divisor, rounded. */ + if (divisor != 0) + { + if (a == 0 || times == 0) + { + *res = 0; + return 1; + } + else + { +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a; + r *= times; + r /= divisor; + r = floor(r+.5); + + /* A png_fixed_point is a 32-bit integer. */ + if (r <= 2147483647. && r >= -2147483648.) + { + *res = (png_fixed_point)r; + return 1; + } +#else + int negative = 0; + png_uint_32 A, T, D; + png_uint_32 s16, s32, s00; + + if (a < 0) + negative = 1, A = -a; + else + A = a; + + if (times < 0) + negative = !negative, T = -times; + else + T = times; + + if (divisor < 0) + negative = !negative, D = -divisor; + else + D = divisor; + + /* Following can't overflow because the arguments only + * have 31 bits each, however the result may be 32 bits. + */ + s16 = (A >> 16) * (T & 0xffff) + + (A & 0xffff) * (T >> 16); + /* Can't overflow because the a*times bit is only 30 + * bits at most. + */ + s32 = (A >> 16) * (T >> 16) + (s16 >> 16); + s00 = (A & 0xffff) * (T & 0xffff); + + s16 = (s16 & 0xffff) << 16; + s00 += s16; + + if (s00 < s16) + ++s32; /* carry */ + + if (s32 < D) /* else overflow */ + { + /* s32.s00 is now the 64-bit product, do a standard + * division, we know that s32 < D, so the maximum + * required shift is 31. + */ + int bitshift = 32; + png_fixed_point result = 0; /* NOTE: signed */ + + while (--bitshift >= 0) + { + png_uint_32 d32, d00; + + if (bitshift > 0) + d32 = D >> (32-bitshift), d00 = D << bitshift; + + else + d32 = 0, d00 = D; + + if (s32 > d32) + { + if (s00 < d00) --s32; /* carry */ + s32 -= d32, s00 -= d00, result += 1<= d00) + s32 = 0, s00 -= d00, result += 1<= (D >> 1)) + ++result; + + if (negative) + result = -result; + + /* Check for overflow. */ + if ((negative && result <= 0) || (!negative && result >= 0)) + { + *res = result; + return 1; + } + } +#endif + } + } + + return 0; +} +#endif /* READ_GAMMA || INCH_CONVERSIONS */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* The following is for when the caller doesn't much care about the + * result. + */ +png_fixed_point +png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + png_fixed_point result; + + if (png_muldiv(&result, a, times, divisor)) + return result; + + png_warning(png_ptr, "fixed point overflow ignored"); + return 0; +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */ +/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ +png_fixed_point +png_reciprocal(png_fixed_point a) +{ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(1E10/a+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, 100000, 100000, a)) + return res; +#endif + + return 0; /* error/overflow */ +} + +/* A local convenience routine. */ +static png_fixed_point +png_product2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a * 1E-5; + r *= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, a, b, 100000)) + return res; +#endif + + return 0; /* overflow */ +} + +/* The inverse of the above. */ +png_fixed_point +png_reciprocal2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = 1E15/a; + r /= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + /* This may overflow because the range of png_fixed_point isn't symmetric, + * but this API is only used for the product of file and screen gamma so it + * doesn't matter that the smallest number it can produce is 1/21474, not + * 1/100000 + */ + png_fixed_point res = png_product2(a, b); + + if (res != 0) + return png_reciprocal(res); +#endif + + return 0; /* overflow */ +} +#endif /* READ_GAMMA */ + +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2, + * 2010: moved from pngset.c) */ +/* + * 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; +} +#endif /* CHECK_cHRM */ + +#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */ +#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* Fixed point gamma. + * + * To calculate gamma this code implements fast log() and exp() calls using only + * fixed point arithmetic. This code has sufficient precision for either 8-bit + * or 16-bit sample values. + * + * The tables used here were calculated using simple 'bc' programs, but C double + * precision floating point arithmetic would work fine. The programs are given + * at the head of each table. + * + * 8-bit log table + * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to + * 255, so it's the base 2 logarithm of a normalized 8-bit floating point + * mantissa. The numbers are 32-bit fractions. + */ +static png_uint_32 +png_8bit_l2[128] = +{ +# ifdef PNG_DO_BC + for (i=128;i<256;++i) { .5 - l(i/255)/l(2)*65536*65536; } +# else + 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U, + 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U, + 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U, + 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U, + 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U, + 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U, + 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U, + 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U, + 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U, + 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U, + 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U, + 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U, + 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U, + 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U, + 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U, + 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U, + 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U, + 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U, + 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U, + 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U, + 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U, + 24347096U, 0U +# endif + +#if 0 + /* The following are the values for 16-bit tables - these work fine for the + * 8-bit conversions but produce very slightly larger errors in the 16-bit + * log (about 1.2 as opposed to 0.7 absolute error in the final value). To + * use these all the shifts below must be adjusted appropriately. + */ + 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, + 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, + 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068, + 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782, + 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887, + 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339, + 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098, + 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132, + 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415, + 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523, + 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495, + 1119, 744, 372 +#endif +}; + +PNG_STATIC png_int_32 +png_log8bit(unsigned int x) +{ + unsigned int lg2 = 0; + /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log, + * because the log is actually negate that means adding 1. The final + * returned value thus has the range 0 (for 255 input) to 7.994 (for 1 + * input), return 7.99998 for the overflow (log 0) case - so the result is + * always at most 19 bits. + */ + if ((x &= 0xff) == 0) + return 0xffffffff; + + if ((x & 0xf0) == 0) + lg2 = 4, x <<= 4; + + if ((x & 0xc0) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x80) == 0) + lg2 += 1, x <<= 1; + + /* result is at most 19 bits, so this cast is safe: */ + return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16)); +} + +/* The above gives exact (to 16 binary places) log2 values for 8-bit images, + * for 16-bit images we use the most significant 8 bits of the 16-bit value to + * get an approximation then multiply the approximation by a correction factor + * determined by the remaining up to 8 bits. This requires an additional step + * in the 16-bit case. + * + * We want log2(value/65535), we have log2(v'/255), where: + * + * value = v' * 256 + v'' + * = v' * f + * + * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128 + * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less + * than 258. The final factor also needs to correct for the fact that our 8-bit + * value is scaled by 255, whereas the 16-bit values must be scaled by 65535. + * + * This gives a final formula using a calculated value 'x' which is value/v' and + * scaling by 65536 to match the above table: + * + * log2(x/257) * 65536 + * + * Since these numbers are so close to '1' we can use simple linear + * interpolation between the two end values 256/257 (result -368.61) and 258/257 + * (result 367.179). The values used below are scaled by a further 64 to give + * 16-bit precision in the interpolation: + * + * Start (256): -23591 + * Zero (257): 0 + * End (258): 23499 + */ +PNG_STATIC png_int_32 +png_log16bit(png_uint_32 x) +{ + unsigned int lg2 = 0; + + /* As above, but now the input has 16 bits. */ + if ((x &= 0xffff) == 0) + return 0xffffffff; + + if ((x & 0xff00) == 0) + lg2 = 8, x <<= 8; + + if ((x & 0xf000) == 0) + lg2 += 4, x <<= 4; + + if ((x & 0xc000) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x8000) == 0) + lg2 += 1, x <<= 1; + + /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional + * value. + */ + lg2 <<= 28; + lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4; + + /* Now we need to interpolate the factor, this requires a division by the top + * 8 bits. Do this with maximum precision. + */ + x = ((x << 16) + (x >> 9)) / (x >> 8); + + /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24, + * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly + * 16 bits to interpolate to get the low bits of the result. Round the + * answer. Note that the end point values are scaled by 64 to retain overall + * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust + * the overall scaling by 6-12. Round at every step. + */ + x -= 1U << 24; + + if (x <= 65536U) /* <= '257' */ + lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12); + + else + lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12); + + /* Safe, because the result can't have more than 20 bits: */ + return (png_int_32)((lg2 + 2048) >> 12); +} + +/* The 'exp()' case must invert the above, taking a 20-bit fixed point + * logarithmic value and returning a 16 or 8-bit number as appropriate. In + * each case only the low 16 bits are relevant - the fraction - since the + * integer bits (the top 4) simply determine a shift. + * + * The worst case is the 16-bit distinction between 65535 and 65534, this + * requires perhaps spurious accuracy in the decoding of the logarithm to + * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance + * of getting this accuracy in practice. + * + * To deal with this the following exp() function works out the exponent of the + * frational part of the logarithm by using an accurate 32-bit value from the + * top four fractional bits then multiplying in the remaining bits. + */ +static png_uint_32 +png_32bit_exp[16] = +{ +# ifdef PNG_DO_BC + for (i=0;i<16;++i) { .5 + e(-i/16*l(2))*2^32; } +# else + /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */ + 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, + 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, + 2553802834U, 2445529972U, 2341847524U, 2242560872U +# endif +}; + +/* Adjustment table; provided to explain the numbers in the code below. */ +#ifdef PNG_DO_BC +for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} + 11 44937.64284865548751208448 + 10 45180.98734845585101160448 + 9 45303.31936980687359311872 + 8 45364.65110595323018870784 + 7 45395.35850361789624614912 + 6 45410.72259715102037508096 + 5 45418.40724413220722311168 + 4 45422.25021786898173001728 + 3 45424.17186732298419044352 + 2 45425.13273269940811464704 + 1 45425.61317555035558641664 + 0 45425.85339951654943850496 +#endif + +PNG_STATIC png_uint_32 +png_exp(png_fixed_point x) +{ + if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ + { + /* Obtain a 4-bit approximation */ + png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; + + /* Incorporate the low 12 bits - these decrease the returned value by + * multiplying by a number less than 1 if the bit is set. The multiplier + * is determined by the above table and the shift. Notice that the values + * converge on 45426 and this is used to allow linear interpolation of the + * low bits. + */ + if (x & 0x800) + e -= (((e >> 16) * 44938U) + 16U) >> 5; + + if (x & 0x400) + e -= (((e >> 16) * 45181U) + 32U) >> 6; + + if (x & 0x200) + e -= (((e >> 16) * 45303U) + 64U) >> 7; + + if (x & 0x100) + e -= (((e >> 16) * 45365U) + 128U) >> 8; + + if (x & 0x080) + e -= (((e >> 16) * 45395U) + 256U) >> 9; + + if (x & 0x040) + e -= (((e >> 16) * 45410U) + 512U) >> 10; + + /* And handle the low 6 bits in a single block. */ + e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9; + + /* Handle the upper bits of x. */ + e >>= x >> 16; + return e; + } + + /* Check for overflow */ + if (x <= 0) + return png_32bit_exp[0]; + + /* Else underflow */ + return 0; +} + +PNG_STATIC png_byte +png_exp8bit(png_fixed_point lg2) +{ + /* Get a 32-bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the + * second, rounding, step can't overflow because of the first, subtraction, + * step. + */ + x -= x >> 8; + return (png_byte)((x + 0x7fffffU) >> 24); +} + +PNG_STATIC png_uint_16 +png_exp16bit(png_fixed_point lg2) +{ + /* Get a 32-bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */ + x -= x >> 16; + return (png_uint_16)((x + 32767U) >> 16); +} +#endif /* FLOATING_ARITHMETIC */ + +png_byte +png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 255) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(255*pow(value/255.,gamma_val*.00001)+.5); + return (png_byte)r; +# else + png_int_32 lg2 = png_log8bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp8bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_byte)value; +} + +png_uint_16 +png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 65535) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5); + return (png_uint_16)r; +# else + png_int_32 lg2 = png_log16bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp16bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_uint_16)value; +} + +/* This does the right thing based on the bit_depth field of the + * png_struct, interpreting values as 8-bit or 16-bit. While the result + * is nominally a 16-bit value if bit depth is 8 then the result is + * 8-bit (as are the arguments.) + */ +png_uint_16 /* PRIVATE */ +png_gamma_correct(png_structp png_ptr, unsigned int value, + png_fixed_point gamma_val) +{ + if (png_ptr->bit_depth == 8) + return png_gamma_8bit_correct(value, gamma_val); + + else + return png_gamma_16bit_correct(value, gamma_val); +} + +/* This is the shared test on whether a gamma value is 'significant' - whether + * it is worth doing gamma correction. + */ +int /* PRIVATE */ +png_gamma_significant(png_fixed_point gamma_val) +{ + return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || + gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; +} + +/* Internal function to build a single 16-bit table - the table consists of + * 'num' 256-entry subtables, where 'num' is determined by 'shift' - the amount + * to shift the input values right (or 16-number_of_signifiant_bits). + * + * The caller is responsible for ensuring that the table gets cleaned up on + * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument + * should be somewhere that will be cleaned. + */ +static void +png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + /* Various values derived from 'shift': */ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); + unsigned int i; + + png_uint_16pp table = *ptable = + (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); + + for (i = 0; i < num; i++) + { + png_uint_16p sub_table = table[i] = + (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16)); + + /* The 'threshold' test is repeated here because it can arise for one of + * the 16-bit tables even if the others don't hit it. + */ + if (png_gamma_significant(gamma_val)) + { + /* The old code would overflow at the end and this would cause the + * 'pow' function to return a result >1, resulting in an + * arithmetic error. This code follows the spec exactly; ig is + * the recovered input sample, it always has 8-16 bits. + * + * We want input * 65535/max, rounded, the arithmetic fits in 32 + * bits (unsigned) so long as max <= 32767. + */ + unsigned int j; + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + /* Inline the 'max' scaling operation: */ + double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5); + sub_table[j] = (png_uint_16)d; +# else + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = png_gamma_16bit_correct(ig, gamma_val); +# endif + } + } + else + { + /* We must still build a table, but do it the fast way. */ + unsigned int j; + + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; + + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = (png_uint_16)ig; + } + } + } +} + +/* NOTE: this function expects the *inverse* of the overall gamma transformation + * required. + */ +static void +png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + unsigned int i; + png_uint_32 last; + + png_uint_16pp table = *ptable = + (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); + + /* 'num' is the number of tables and also the number of low bits of the + * input 16-bit value used to select a table. Each table is itself indexed + * by the high 8 bits of the value. + */ + for (i = 0; i < num; i++) + table[i] = (png_uint_16p)png_malloc(png_ptr, + 256 * png_sizeof(png_uint_16)); + + /* 'gamma_val' is set to the reciprocal of the value calculated above, so + * pow(out,g) is an *input* value. 'last' is the last input value set. + * + * In the loop 'i' is used to find output values. Since the output is + * 8-bit there are only 256 possible values. The tables are set up to + * select the closest possible output value for each input by finding + * the input value at the boundary between each pair of output values + * and filling the table up to that boundary with the lower output + * value. + * + * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit + * values the code below uses a 16-bit value in i; the values start at + * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last + * entries are filled with 255). Start i at 128 and fill all 'last' + * table entries <= 'max' + */ + last = 0; + for (i = 0; i < 255; ++i) /* 8-bit output value */ + { + /* Find the corresponding maximum input value */ + png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */ + + /* Find the boundary value in 16 bits: */ + png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val); + + /* Adjust (round) to (16-shift) bits: */ + bound = (bound * max + 32768U)/65535U + 1U; + + while (last < bound) + { + table[last & (0xffU >> shift)][last >> (8U - shift)] = out; + last++; + } + } + + /* And fill in the final entries. */ + while (last < (num << 8)) + { + table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U; + last++; + } +} + +/* Build a single 8-bit table: same as the 16-bit case but much simpler (and + * typically much faster). Note that libpng currently does no sBIT processing + * (apparently contrary to the spec) so a 256-entry table is always generated. + */ +static void +png_build_8bit_table(png_structp png_ptr, png_bytepp ptable, + PNG_CONST png_fixed_point gamma_val) +{ + unsigned int i; + png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); + + if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++) + table[i] = png_gamma_8bit_correct(i, gamma_val); + + else for (i=0; i<256; ++i) + table[i] = (png_byte)i; +} + +/* Used from png_read_destroy and below to release the memory used by the gamma + * tables. + */ +void /* PRIVATE */ +png_destroy_gamma_table(png_structp png_ptr) +{ + png_free(png_ptr, png_ptr->gamma_table); + png_ptr->gamma_table = NULL; + + 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); + png_ptr->gamma_16_table = NULL; + } + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_free(png_ptr, png_ptr->gamma_from_1); + png_ptr->gamma_from_1 = NULL; + png_free(png_ptr, png_ptr->gamma_to_1); + png_ptr->gamma_to_1 = NULL; + + 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); + png_ptr->gamma_16_from_1 = NULL; + } + 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); + png_ptr->gamma_16_to_1 = NULL; + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ +} + +/* 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. + */ +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr, int bit_depth) +{ + png_debug(1, "in png_build_gamma_table"); + + /* Remove any existing table; this copes with multiple calls to + * png_read_update_info. The warning is because building the gamma tables + * multiple times is a performance hit - it's harmless but the ability to call + * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible + * to warn if the app introduces such a hit. + */ + if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) + { + png_warning(png_ptr, "gamma table being rebuilt"); + png_destroy_gamma_table(png_ptr); + } + + if (bit_depth <= 8) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_table, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, + png_reciprocal(png_ptr->gamma)); + + png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->gamma/* Probably doing rgb_to_gray */); + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ + } + else + { + png_byte shift, sig_bit; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = png_ptr->sig_bit.red; + + if (png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + + if (png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + sig_bit = png_ptr->sig_bit.gray; + + /* 16-bit gamma code uses this equation: + * + * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] + * + * Where 'iv' is the input color value and 'ov' is the output value - + * pow(iv, gamma). + * + * Thus the gamma table consists of up to 256 256-entry tables. The table + * is selected by the (8-gamma_shift) most significant of the low 8 bits of + * the color value then indexed by the upper 8 bits: + * + * table[low bits][high 8 bits] + * + * So the table 'n' corresponds to all those 'iv' of: + * + * ..<(n+1 << gamma_shift)-1> + * + */ + if (sig_bit > 0 && sig_bit < 16U) + shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */ + + else + shift = 0; /* keep all 16 bits */ + + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) + { + /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively + * the significant bits in the *input* when the output will + * eventually be 8 bits. By default it is 11. + */ + if (shift < (16U - PNG_MAX_GAMMA_8)) + shift = (16U - PNG_MAX_GAMMA_8); + } + + if (shift > 8U) + shift = 8U; /* Guarantees at least one table! */ + + png_ptr->gamma_shift = shift; + +#ifdef PNG_16BIT_SUPPORTED + /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now + * PNG_COMPOSE). This effectively smashed the background calculation for + * 16-bit output because the 8-bit table assumes the result will be reduced + * to 8 bits. + */ + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) +#endif + png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#ifdef PNG_16BIT_SUPPORTED + else + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) + { + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, + png_reciprocal(png_ptr->gamma)); + + /* Notice that the '16 from 1' table should be full precision, however + * the lookup on this table still uses gamma_shift, so it can't be. + * TODO: fix this. + */ + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->gamma/* Probably doing rgb_to_gray */); + } +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ + } +} +#endif /* READ_GAMMA */ +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/plugins/FreeImage/src/LibPNG/png.h b/plugins/FreeImage/src/LibPNG/png.h new file mode 100644 index 0000000000..81267675a5 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/png.h @@ -0,0 +1,2658 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.5.9 - February 18, 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.5.9 - February 18, 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 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.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 12.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 12.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-7 13 10210 12.so.0.10[.0] + * 1.2.10rc1-2 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.4.0beta1-5 14 10400 14.so.0.0[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.4.0beta7-8 14 10400 14.so.0.0[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.4.0beta9-14 14 10400 14.so.0.0[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.4.0beta15-36 14 10400 14.so.0.0[.0] + * 1.4.0beta37-87 14 10400 14.so.14.0[.0] + * 1.4.0rc01 14 10400 14.so.14.0[.0] + * 1.4.0beta88-109 14 10400 14.so.14.0[.0] + * 1.4.0rc02-08 14 10400 14.so.14.0[.0] + * 1.4.0 14 10400 14.so.14.0[.0] + * 1.4.1beta01-03 14 10401 14.so.14.1[.0] + * 1.4.1rc01 14 10401 14.so.14.1[.0] + * 1.4.1beta04-12 14 10401 14.so.14.1[.0] + * 1.4.1 14 10401 14.so.14.1[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * 1.4.4 14 10404 14.so.14.4[.0] + * 1.5.0beta01-58 15 10500 15.so.15.0[.0] + * 1.5.0rc01-07 15 10500 15.so.15.0[.0] + * 1.5.0 15 10500 15.so.15.0[.0] + * 1.5.1beta01-11 15 10501 15.so.15.1[.0] + * 1.5.1rc01-02 15 10501 15.so.15.1[.0] + * 1.5.1 15 10501 15.so.15.1[.0] + * 1.5.2beta01-03 15 10502 15.so.15.2[.0] + * 1.5.2rc01-03 15 10502 15.so.15.2[.0] + * 1.5.2 15 10502 15.so.15.2[.0] + * 1.5.3beta01-10 15 10503 15.so.15.3[.0] + * 1.5.3rc01-02 15 10503 15.so.15.3[.0] + * 1.5.3beta11 15 10503 15.so.15.3[.0] + * 1.5.3 [omitted] + * 1.5.4beta01-08 15 10504 15.so.15.4[.0] + * 1.5.4rc01 15 10504 15.so.15.4[.0] + * 1.5.4 15 10504 15.so.15.4[.0] + * 1.5.5beta01-08 15 10505 15.so.15.5[.0] + * 1.5.5rc01 15 10505 15.so.15.5[.0] + * 1.5.5 15 10505 15.so.15.5[.0] + * 1.5.6beta01-07 15 10506 15.so.15.6[.0] + * 1.5.6rc01-03 15 10506 15.so.15.6[.0] + * 1.5.6 15 10506 15.so.15.6[.0] + * 1.5.7beta01-05 15 10507 15.so.15.7[.0] + * 1.5.7rc01-03 15 10507 15.so.15.7[.0] + * 1.5.7 15 10507 15.so.15.7[.0] + * 1.5.8beta01 15 10508 15.so.15.8[.0] + * 1.5.8rc01 15 10508 15.so.15.8[.0] + * 1.5.8 15 10508 15.so.15.8[.0] + * 1.5.9beta01-02 15 10509 15.so.15.9[.0] + * 1.5.9rc01 15 10509 15.so.15.9[.0] + * 1.5.9 15 10509 15.so.15.9[.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 "rcN". + * + * 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-manual.txt or libpng.3 for more information. The PNG + * specification is available as a W3C Recommendation and as an ISO + * Specification, +# endif + + /* Need the time information for converting tIME chunks, it + * defines struct tm: + */ +# ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on all operating systems */ +# include +# endif +# endif + +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * 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 /* From pnglibconf.h */ +# 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 */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 2. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 3. Exported library functions. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ +/* Section 1: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 2: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_5_9; + +/* 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_CONST png_color FAR * png_const_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_CONST png_color_16 FAR * png_const_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_CONST png_color_8 FAR * png_const_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_CONST png_sPLT_entry FAR * png_const_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_CONST png_sPLT_t FAR * png_const_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" fields can be a + * regular C string, an empty string, or a NULL pointer. + * However, the structure returned by png_get_text() will always contain + * the "text" field as a regular zero-terminated C string (possibly + * empty), never a NULL pointer, so it can be safely used in printf() and + * other string-handling functions. Note that the "itxt_length", "lang", and + * "lang_key" members of the structure only exist when the library is built + * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by + * default without iTXt support. Also note that when iTXt *is* supported, + * the "lang" and "lang_key" fields contain NULL pointers when the + * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or + * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the + * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" + * which is always 0 or 1, or its "compression method" which is always 0. + */ +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 */ + 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 */ +} png_text; +typedef png_text FAR * png_textp; +typedef PNG_CONST png_text FAR * png_const_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_CONST png_time FAR * png_const_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. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; + 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_CONST png_unknown_chunk FAR * png_const_unknown_chunkp; +typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; +#endif + +/* Values for the unknown chunk location byte */ + +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* The complete definition of png_info has, as of libpng-1.5.0, + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_info_def png_info; +typedef png_info FAR * png_infop; +typedef PNG_CONST png_info FAR * png_const_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)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) + +/* 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_ 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 0x8000 /* 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_size_t 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; + +/* The complete definition of png_struct has, as of libpng-1.5.0, + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_struct_def png_struct; +typedef PNG_CONST png_struct FAR * png_const_structp; +typedef png_struct FAR * png_structp; + +/* 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. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +#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 */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* 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 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); + +typedef png_struct FAR * FAR * png_structpp; + +/* Section 3: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.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. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (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). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_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). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (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 */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, + (png_const_structp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, + png_size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, 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), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, 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), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), + PNG_ALLOCATED); + +PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structp png_ptr, png_infop info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structp png_ptr, png_infop info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, + (png_structp png_ptr, + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + PNG_CONST struct tm FAR * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, + (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. */ +PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, + int error_action, double red, double green)); +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)); + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp + png_ptr)); +#endif + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels of + * a PNG file are returned when an alpha channel, or tRNS chunk in a palette + * file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel. The gamma encoded color channels must be + * scaled according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and reencode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. The + * advantage is that the color channels can be resampled (the image can be + * scaled) in this form. The disadvantage is that normal practice is to store + * linear, not (gamma) encoded, values and this requires 16-bit channels for + * still images rather than the 8-bit channels that are just about sufficient if + * gamma encoding is used. In addition all non-transparent pixel values, + * including completely opaque ones, must be gamma encoded to produce the final + * image. This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the + * latter being the two common names for associated alpha color channels.) + * + * Since it is not necessary to perform arithmetic on opaque color values so + * long as they are not to be resampled and are in the final color space it is + * possible to optimize the handling of alpha by storing the opaque pixels in + * the PNG format (adjusted for the output color space) while storing partially + * opaque pixels in the standard, linear, format. The accuracy required for + * standard alpha composition is relatively low, because the pixels are + * isolated, therefore typically the accuracy loss in storing 8-bit linear + * values is acceptable. (This is not true if the alpha channel is used to + * simulate transparency over large areas - use 16 bits or the PNG mode in + * this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is + * treated as opaque only if the alpha value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode, + double output_gamma)); +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr, + int mode, png_fixed_point output_gamma)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. The values used + * correspond to the normal numbers used to describe the overall gamma of a + * computer display system; for example 2.2 for an sRGB conformant system. The + * values are scaled by 100000 in the _fixed version of the API (so 220000 for + * sRGB.) + * + * The inverse of the value is always used to provide a default for the PNG file + * encoding if it has no gAMA chunk and if png_set_gamma() has not been called + * to override the PNG gamma information. + * + * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode + * opaque pixels however pixels with lower alpha values are not encoded, + * regardless of the output gamma setting. + * + * When the standard Porter Duff handling is requested with mode 1 the output + * encoding is set to be linear and the output_gamma value is only relevant + * as a default for input data that has no gamma information. The linear output + * encoding will be overridden if png_set_gamma() is called - the results may be + * highly unexpected! + * + * The following numbers are derived from the sRGB standard and the research + * behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of + * 0.45455 (1/2.2) for PNG. The value implicitly includes any viewing + * correction required to take account of any differences in the color + * environment of the original scene and the intended display environment; the + * value expresses how to *decode* the image for display, not how the original + * data was *encoded*. + * + * sRGB provides a peg for the PNG standard by defining a viewing environment. + * sRGB itself, and earlier TV standards, actually use a more complex transform + * (a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is + * limited to simple power laws.) By saying that an image for direct display on + * an sRGB conformant system should be stored with a gAMA chunk value of 45455 + * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification + * makes it possible to derive values for other display systems and + * environments. + * + * The Mac value is deduced from the sRGB based on an assumption that the actual + * extra viewing correction used in early Mac display systems was implemented as + * a power 1.45 lookup table. + * + * Any system where a programmable lookup table is used or where the behavior of + * the final display device characteristics can be changed requires system + * specific code to obtain the current characteristic. However this can be + * difficult and most PNG gamma correction only requires an approximate value. + * + * By default, if png_set_alpha_mode() is not called, libpng assumes that all + * values are unencoded, linear, values and that the output device also has a + * linear characteristic. This is only very rarely correct - it is invariably + * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the + * default if you don't know what the right answer is! + * + * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS + * 10.6) which used a correction table to implement a somewhat lower gamma on an + * otherwise sRGB system. + * + * Both these values are reserved (not simple gamma values) in order to allow + * more precise correction internally in the future. + * + * NOTE: the following values can be passed to either the fixed or floating + * point APIs, but the floating point API will also accept floating point + * values. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceeded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the ouput gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (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. */ +PNG_EXPORT(39, void, png_set_filler, (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. */ +PNG_EXPORT(40, void, png_set_add_alpha, + (png_structp png_ptr, png_uint_32 filler, + int flags)); +#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. */ +PNG_EXPORT(41, void, png_set_swap, (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. */ +PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_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. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)); +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# 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_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, + (png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ +PNG_FP_EXPORT(50, void, png_set_gamma, + (png_structp png_ptr, double screen_gamma, + double override_file_gamma)); +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)); +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, + (png_structp png_ptr, png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, + (png_structp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, + (png_structp png_ptr, int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() 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. + */ +PNG_EXPORT(67, void, png_set_filter, + (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 + +#ifdef 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. + */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)); +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_fixed_point_p + filter_weights, png_const_fixed_point_p filter_costs)); +#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 */ + +#ifdef PNG_WRITE_SUPPORTED +/* 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. + */ +PNG_EXPORT(69, void, png_set_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, + int method)); +#endif + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, (png_structp + png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr, + int method)); +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ + +/* 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-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (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. + */ + +PNG_EXPORT(75, void, png_set_error_fn, + (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 */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_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. + */ +PNG_EXPORT(77, void, png_set_write_fn, (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. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (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). */ +PNG_EXPORT(82, void, png_set_mem_fn, (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 */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (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 */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_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. + */ +PNG_EXPORT(90, void, 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)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, + (png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +PNG_EXPORTA(94, png_voidp, png_malloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, + (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +PNG_EXPORT(99, void, png_data_freer, + (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask)); + +/* 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 +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, + (png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, + png_const_charp warning_message)); +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +# undef png_benign_error +PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Same, chunk name is prepended to message. */ +# undef png_chunk_benign_error +PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ 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_ 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. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, + png_const_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(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, + (png_const_structp png_ptr, png_const_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, + (png_const_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, + png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, + png_const_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_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_structp png_ptr, + png_const_infop info_ptr, double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, double *blue_X, + double *blue_Y, double *blue_Z)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */ +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structp png_ptr, + png_const_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 +PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, + (png_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, 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_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_structp png_ptr, + png_infop info_ptr, double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, double blue_X, + double blue_Y, double blue_Z)); +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (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)); +PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, + (png_const_structp png_ptr, png_const_infop info_ptr, + double *file_gamma)); +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_file_gamma)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, + png_infop info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, 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_method, int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, 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_method, int compression_method, int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, + (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 +PNG_EXPORT(147, png_uint_32, png_get_pCAL, + (png_const_structp png_ptr, png_const_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 +PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr, + png_infop info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, + (png_structp png_ptr, png_infop info_ptr, + png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, + (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, + png_const_infop info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, + (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, + png_infop info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, png_bytepp profile, + png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, + (png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, png_const_bytep profile, + png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, png_uint_32, png_get_sPLT, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, + (png_structp png_ptr, png_infop info_ptr, + png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, png_uint_32, png_get_text, + (png_const_structp png_ptr, png_const_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 +PNG_EXPORT(163, void, png_set_text, + (png_structp png_ptr, png_infop info_ptr, + png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, + (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, + (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, + (png_const_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, + (png_structp png_ptr, png_infop info_ptr, + png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, double *width, double *height)); +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_structp png_ptr, png_const_infop info_ptr, int *unit, + png_fixed_point *width, + png_fixed_point *height)); +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, + (png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height)); +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, + png_infop info_ptr, int unit, png_fixed_point width, + png_fixed_point height)); +PNG_EXPORT(171, void, png_set_sCAL_s, + (png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight)); +#endif /* PNG_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. Because this turns off the default handling for chunks + that would otherwise be recognized the behavior of libpng transformations may + well become incorrect! + keep = 0: PNG_HANDLE_CHUNK_AS_DEFAULT: follow default behavior + = 1: PNG_HANDLE_CHUNK_NEVER: do not keep + = 2: PNG_HANDLE_CHUNK_IF_SAFE: keep only if safe-to-copy + = 3: PNG_HANDLE_CHUNK_ALWAYS: keep even if unsafe-to-copy +*/ +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, + (png_structp png_ptr, int keep, + png_const_bytep chunk_list, int num_chunks)); + +/* The handling code is returned; the result is therefore true (non-zero) if + * special handling is required, false for the default handling. + */ +PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, + png_const_bytep chunk_name)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, + png_infop info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, + png_const_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); + */ +PNG_EXPORT(177, void, png_set_invalid, + (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. */ +PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (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 + +/* 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 +PNG_EXPORT(185, void, png_set_strip_error_numbers, + (png_structp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structp png_ptr, png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, + png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, + png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr)); + +PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name, + (png_structp png_ptr), PNG_DEPRECATED); +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ + (((yIn)<>(((7-(off))-(pass))<<2)) & 0xF) | \ + ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#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)) + 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)*(65535 \ + - (png_uint_32)(alpha)) + 32768); \ + (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)) + \ + 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)(65535 - (png_uint_32)(alpha)) + \ + 32767) / 65535) +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, + png_const_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). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* 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. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define png_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define png_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define png_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ + : (png_int_32)png_get_uint_32(buf))) +#endif + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) Maintainer, remember to add an entry to + * scripts/symbols.def as well. + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(233); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/plugins/FreeImage/src/LibPNG/pngconf.h b/plugins/FreeImage/src/LibPNG/pngconf.h new file mode 100644 index 0000000000..121d204ccd --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngconf.h @@ -0,0 +1,596 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.5.9 - February 18, 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 + +#ifndef PNG_BUILDING_SYMBOL_TABLE +/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C + * definition file for machine specific limits, this may impact the + * correctness of the definitons below (see uses of INT_MAX). + */ +# ifndef PNG_NO_LIMITS_H +# include +# endif + +/* For the memory copy APIs (i.e. the standard definitions of these), + * because this file defines png_memcpy and so on the base APIs must + * be defined here. + */ +# ifdef BSD +# include +# else +# include +# endif + +/* For png_FILE_p - this provides the standard definition of a + * FILE + */ +# ifdef PNG_STDIO_SUPPORTED +# include +# endif +#endif + +/* This controls optimization of the reading of 16 and 32 bit values + * from PNG files. It can be set on a per-app-file basis - it + * just changes whether a macro is used to the function is called. + * The library builder sets the default, if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG 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) () +# else +# define PNGARG(arglist) arglist +# endif /* _NO_PROTO */ + +# endif /* OF */ + +#endif /* PNGARG */ + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows sytems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. Not used in the + * public header files; see pngpriv.h for how it is used + * in the libpng build. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows/x86 systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)) &&\ + ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\ + defined(_M_X64) || defined(_M_IA64)) + /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes + * builds under Cygwin or MinGW. Also includes Watcom builds but these need + * special treatment because they are not compatible with GCC or Visual C + * because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) + ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows/x86 */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* PNG_IMPEXP may be set on the compilation system command line or (if not set) + * then in an internal header file when building the library, otherwise (when + * using the library) it is set here. + */ +#ifndef PNG_IMPEXP +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) + */ +#ifndef PNG_FUNCTION +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ +#ifndef PNG_EXPORTA + +# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ + PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ + extern attributes) +#endif + +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + +#define PNG_EXPORT(ordinal, type, name, args)\ + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +#endif + +/* 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-1.2.41. + */ + +#ifndef PNG_NO_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. + */ +# if defined(__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 +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __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 +# endif /* __GNUC__ */ + +# if defined(_MSC_VER) && (_MSC_VER >= 1300) +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* not supported */ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_ALLOCATED +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif +# endif +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif +# endif /* _MSC_VER */ +#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_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +/* 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. + * + * This should not change how the APIs are called, so it can be done + * on a per-file basis in the application. + */ +#ifndef PNG_CONST +# ifndef PNG_NO_CONST +# define PNG_CONST const +# else +# define PNG_CONST +# endif +#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. + */ + +#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) +typedef unsigned int png_uint_32; +typedef int png_int_32; +#else +typedef unsigned long png_uint_32; +typedef long png_int_32; +#endif +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +#ifdef PNG_NO_SIZE_T +typedef unsigned int png_size_t; +#else +typedef size_t png_size_t; +#endif +#define png_sizeof(x) (sizeof (x)) + +/* The following is needed for medium model support. It cannot be in the + * pngpriv.h header. 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 /* only used in build */ +# 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 +# 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., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef PNG_CONST void FAR * png_const_voidp; +typedef png_byte FAR * png_bytep; +typedef PNG_CONST png_byte FAR * png_const_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef PNG_CONST png_int_32 FAR * png_const_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST png_int_16 FAR * png_const_int_16p; +typedef char FAR * png_charp; +typedef PNG_CONST char FAR * png_const_charp; +typedef png_fixed_point FAR * png_fixed_point_p; +typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p; +typedef png_size_t FAR * png_size_tp; +typedef PNG_CONST png_size_t FAR * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +typedef PNG_CONST double FAR * png_const_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; + +/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, + * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 + * to png_alloc_size_t are not necessary; in fact, it is recommended + * not to use them at all so that the compiler can complain when something + * turns out to be problematic. + * Casts in the other direction (from png_alloc_size_t to png_size_t or + * png_uint_32) should be explicitly applied; however, we do not expect + * to encounter practical situations that require such conversions. + */ +#if defined(__TURBOC__) && !defined(__FLAT__) + typedef unsigned long png_alloc_size_t; +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + typedef unsigned long png_alloc_size_t; +# else + /* This is an attempt to detect an old Windows system where (int) is + * actually 16 bits, in that case png_malloc must have an argument with a + * bigger size to accomodate the requirements of the library. + */ +# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ + (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) + typedef DWORD png_alloc_size_t; +# else + typedef png_size_t png_alloc_size_t; +# endif +# endif +#endif + +#endif /* PNGCONF_H */ diff --git a/plugins/FreeImage/src/LibPNG/pngdebug.h b/plugins/FreeImage/src/LibPNG/pngdebug.h new file mode 100644 index 0000000000..96c1ea42b3 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngdebug.h @@ -0,0 +1,157 @@ + +/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c + * + * 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.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* 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. + * + * png_debug[1-2]?(level, message ,arg{0-2}) + * Expands to a statement (either a simple expression or a compound + * do..while(0) statement) that outputs a message with parameter + * substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG + * is undefined, 0 or 1 every png_debug expands to a simple expression + * (actually ((void)0)). + * + * level: level of detail of message, starting at 0. A level 'n' + * message is preceded by 'n' tab characters (not implemented + * on Microsoft compilers unless PNG_DEBUG_FILE is also + * defined, to allow debug DLL compilation with no standard IO). + * message: a printf(3) style text string. A trailing '\n' is added + * to the message. + * arg: 0 to 2 arguments for printf(3) style substitution in message. + */ +#ifndef PNGDEBUG_H +#define PNGDEBUG_H +/* These settings control the formatting of messages in png.c and pngerror.c */ +/* Moved to pngdebug.h at 1.5.0 */ +# 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 +# ifndef PNG_STRING_NEWLINE +# define PNG_STRING_NEWLINE "\n" +# endif + +#ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +# include +# 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_STDIO_SUPPORTED +# include /* not included yet */ +# endif +# 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) \ + do { \ + 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":"")))); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + 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); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + 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); \ + } while (0) +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + 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); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + 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); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + 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); \ + } while (0) +# 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) ((void)0) +#endif +#ifndef png_debug1 +# define png_debug1(l, m, p1) ((void)0) +#endif +#ifndef png_debug2 +# define png_debug2(l, m, p1, p2) ((void)0) +#endif +#endif /* PNGDEBUG_H */ diff --git a/plugins/FreeImage/src/LibPNG/pngerror.c b/plugins/FreeImage/src/LibPNG/pngerror.c new file mode 100644 index 0000000000..9df97f583c --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngerror.c @@ -0,0 +1,685 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.5.8 [February 1, 2011] + * 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 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. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +static PNG_FUNCTION(void, 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 +PNG_FUNCTION(void,PNGAPI +png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) +{ +#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 +PNG_FUNCTION(void,PNGAPI +png_err,(png_structp png_ptr),PNG_NORETURN) +{ + /* Prior to 1.5.2 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 */ + +/* Utility to safely appends strings to a buffer. This never errors out so + * error checking is not required in the caller. + */ +size_t +png_safecat(png_charp buffer, size_t bufsize, size_t pos, + png_const_charp string) +{ + if (buffer != NULL && pos < bufsize) + { + if (string != NULL) + while (*string != '\0' && pos < bufsize-1) + buffer[pos++] = *string++; + + buffer[pos] = '\0'; + } + + return pos; +} + +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. + */ +png_charp +png_format_number(png_const_charp start, png_charp end, int format, + png_alloc_size_t number) +{ + int count = 0; /* number of digits output */ + int mincount = 1; /* minimum number required */ + int output = 0; /* digit output (for the fixed point format) */ + + *--end = '\0'; + + /* This is written so that the loop always runs at least once, even with + * number zero. + */ + while (end > start && (number != 0 || count < mincount)) + { + + static const char digits[] = "0123456789ABCDEF"; + + switch (format) + { + case PNG_NUMBER_FORMAT_fixed: + /* Needs five digits (the fraction) */ + mincount = 5; + if (output || number % 10 != 0) + { + *--end = digits[number % 10]; + output = 1; + } + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02u: + /* Expects at least 2 digits. */ + mincount = 2; + /* fall through */ + + case PNG_NUMBER_FORMAT_u: + *--end = digits[number % 10]; + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02x: + /* This format expects at least two digits */ + mincount = 2; + /* fall through */ + + case PNG_NUMBER_FORMAT_x: + *--end = digits[number & 0xf]; + number >>= 4; + break; + + default: /* an error */ + number = 0; + break; + } + + /* Keep track of the number of digits added */ + ++count; + + /* Float a fixed number here: */ + if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start) + { + /* End of the fraction, but maybe nothing was output? In that case + * drop the decimal point. If the number is a true zero handle that + * here. + */ + if (output) + *--end = '.'; + else if (number == 0) /* and !output */ + *--end = '0'; + } + } + + return end; +} +#endif + +#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); +} + +/* These functions support 'formatted' warning messages with up to + * PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter + * is introduced by @, where 'number' starts at 1. This follows the + * standard established by X/Open for internationalizable error messages. + */ +void +png_warning_parameter(png_warning_parameters p, int number, + png_const_charp string) +{ + if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) + (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); +} + +void +png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, + png_alloc_size_t value) +{ + char buffer[PNG_NUMBER_BUFFER_SIZE]; + png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); +} + +void +png_warning_parameter_signed(png_warning_parameters p, int number, int format, + png_int_32 value) +{ + png_alloc_size_t u; + png_charp str; + char buffer[PNG_NUMBER_BUFFER_SIZE]; + + /* Avoid overflow by doing the negate in a png_alloc_size_t: */ + u = (png_alloc_size_t)value; + if (value < 0) + u = ~u + 1; + + str = PNG_FORMAT_NUMBER(buffer, format, u); + + if (value < 0 && str > buffer) + *--str = '-'; + + png_warning_parameter(p, number, str); +} + +void +png_formatted_warning(png_structp png_ptr, png_warning_parameters p, + png_const_charp message) +{ + /* The internal buffer is just 192 bytes - enough for all our messages, + * overflow doesn't happen because this code checks! If someone figures + * out how to send us a message longer than 192 bytes, all that will + * happen is that the message will be truncated appropriately. + */ + size_t i = 0; /* Index in the msg[] buffer: */ + char msg[192]; + + /* Each iteration through the following loop writes at most one character + * to msg[i++] then returns here to validate that there is still space for + * the trailing '\0'. It may (in the case of a parameter) read more than + * one character from message[]; it must check for '\0' and continue to the + * test if it finds the end of string. + */ + while (i<(sizeof msg)-1 && *message != '\0') + { + /* '@' at end of string is now just printed (previously it was skipped); + * it is an error in the calling code to terminate the string with @. + */ + if (p != NULL && *message == '@' && message[1] != '\0') + { + int parameter_char = *++message; /* Consume the '@' */ + static const char valid_parameters[] = "123456789"; + int parameter = 0; + + /* Search for the parameter digit, the index in the string is the + * parameter to use. + */ + while (valid_parameters[parameter] != parameter_char && + valid_parameters[parameter] != '\0') + ++parameter; + + /* If the parameter digit is out of range it will just get printed. */ + if (parameter < PNG_WARNING_PARAMETER_COUNT) + { + /* Append this parameter */ + png_const_charp parm = p[parameter]; + png_const_charp pend = p[parameter] + (sizeof p[parameter]); + + /* No need to copy the trailing '\0' here, but there is no guarantee + * that parm[] has been initialized, so there is no guarantee of a + * trailing '\0': + */ + while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend) + msg[i++] = *parm++; + + /* Consume the parameter digit too: */ + ++message; + continue; + } + + /* else not a parameter and there is a character after the @ sign; just + * copy that. This is known not to be '\0' because of the test above. + */ + } + + /* At this point *message can't be '\0', even in the bad parameter case + * above where there is a lone '@' at the end of the message string. + */ + msg[i++] = *message++; + } + + /* i is always less than (sizeof msg), so: */ + msg[i] = '\0'; + + /* And this is the formatted message, it may be larger than + * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these are + * not (currently) formatted. + */ + png_warning(png_ptr, msg); +} +#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) +{ + png_uint_32 chunk_name = png_ptr->chunk_name; + int iout = 0, ishift = 24; + + while (ishift >= 0) + { + int c = (int)(chunk_name >> ishift) & 0xff; + + ishift -= 8; + 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++] = (char)c; + } + } + + if (error_message == NULL) + buffer[iout] = '\0'; + + else + { + int iin = 0; + + buffer[iout++] = ':'; + buffer[iout++] = ' '; + + 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'; + } +} +#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_FUNCTION(void,PNGAPI +png_chunk_error,(png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + 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 && 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 */ + +#ifdef PNG_ERROR_TEXT_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_FUNCTION(void, +png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN) +{ +# define fixed_message "fixed point overflow in " +# define fixed_message_ln ((sizeof fixed_message)-1) + int iin; + char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; + png_memcpy(msg, fixed_message, fixed_message_ln); + iin = 0; + if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) + { + msg[fixed_message_ln + iin] = name[iin]; + ++iin; + } + msg[fixed_message_ln + iin] = 0; + png_error(png_ptr, msg); +} +#endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This API only exists if ANSI-C style error handling is used, + * otherwise it is necessary for png_default_error to be overridden. + */ +jmp_buf* PNGAPI +png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn, + size_t jmp_buf_size) +{ + if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf)) + return NULL; + + png_ptr->longjmp_fn = longjmp_fn; + return &png_ptr->longjmp_buffer; +} +#endif + +/* 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 PNG_FUNCTION(void /* PRIVATE */, +png_default_error,(png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + /* Check on NULL only added in 1.5.4 */ + if (error_message != NULL && *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 ? error_message : + "undefined"); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + PNG_UNUSED(error_message) /* Make compiler happy */ +#endif + png_longjmp(png_ptr, 1); +} + +PNG_FUNCTION(void,PNGAPI +png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN) +{ +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr && png_ptr->longjmp_fn) + { +# ifdef USE_FAR_KEYWORD + { + jmp_buf tmp_jmpbuf; + png_memcpy(tmp_jmpbuf, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); + png_ptr->longjmp_fn(tmp_jmpbuf, val); + } + +# else + png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val); +# endif + } +#endif + /* Here if not setjmp support or if png_ptr is null. */ + PNG_ABORT(); +} + +#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 + PNG_UNUSED(warning_message) /* Make compiler happy */ +#endif + PNG_UNUSED(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->longjmp_buffer, 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; +#ifdef PNG_WARNINGS_SUPPORTED + png_ptr->warning_fn = warning_fn; +#else + PNG_UNUSED(warning_fn) +#endif +} + + +/* 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_const_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/plugins/FreeImage/src/LibPNG/pngget.c b/plugins/FreeImage/src/LibPNG/pngget.c new file mode 100644 index 0000000000..1889e9903e --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngget.c @@ -0,0 +1,1124 @@ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.5.7 [December 15, 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 + * + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +png_uint_32 PNGAPI +png_get_valid(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + + return(0); +} + +png_size_t PNGAPI +png_get_rowbytes(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + + return(0); +} + +#ifdef PNG_INFO_IMAGE_SUPPORTED +png_bytepp PNGAPI +png_get_rows(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + + 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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->height; + + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->y_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (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)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#endif + + return ((float)0.0); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr, + png_const_infop info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) + && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 + && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX + && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX) + { + png_fixed_point res; + + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); + + /* The following casts work because a PNG 4 byte integer only has a valid + * range of 0..2^31-1; otherwise the cast might overflow. + */ + if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1, + (png_int_32)info_ptr->x_pixels_per_unit)) + return res; + } +#endif + + return 0; +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (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 (info_ptr->y_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->y_offset); + } +#endif + + return (0); +} + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED +static png_uint_32 +ppi_from_ppm(png_uint_32 ppm) +{ +#if 0 + /* The conversion is *(2.54/100), in binary (32 digits): + * .00000110100000001001110101001001 + */ + png_uint_32 t1001, t1101; + ppm >>= 1; /* .1 */ + t1001 = ppm + (ppm >> 3); /* .1001 */ + t1101 = t1001 + (ppm >> 1); /* .1101 */ + ppm >>= 20; /* .000000000000000000001 */ + t1101 += t1101 >> 15; /* .1101000000000001101 */ + t1001 >>= 11; /* .000000000001001 */ + t1001 += t1001 >> 12; /* .000000000001001000000001001 */ + ppm += t1001; /* .000000000001001000001001001 */ + ppm += t1101; /* .110100000001001110101001001 */ + return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */ +#else + /* The argument is a PNG unsigned integer, so it is not permitted + * to be bigger than 2^31. + */ + png_fixed_point result; + if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, + 5000)) + return result; + + /* Overflow. */ + return 0; +#endif +} + +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr)); +} + +#ifdef PNG_FIXED_POINT_SUPPORTED +static png_fixed_point +png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns) +{ + /* Convert from metres * 1,000,000 to inches * 100,000, meters to + * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. + * Notice that this can overflow - a warning is output and 0 is + * returned. + */ + return png_muldiv_warn(png_ptr, microns, 500, 127); +} + +png_fixed_point PNGAPI +png_get_x_offset_inches_fixed(png_structp png_ptr, + png_const_infop info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_x_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_y_offset_inches_fixed(png_structp png_ptr, + png_const_infop info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_y_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_x_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_y_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_const_structp png_ptr, png_const_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_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_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + + return (0); +} + +png_const_bytep PNGAPI +png_get_signature(png_const_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + + return (NULL); +} + +#ifdef PNG_bKGD_SUPPORTED +png_uint_32 PNGAPI +png_get_bKGD(png_const_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 +/* The XYZ APIs were added in 1.5.5 to take advantage of the code added at the + * same time to correct the rgb grayscale coefficient defaults obtained from the + * cHRM chunk in 1.5.4 + */ +png_uint_32 PNGFAPI +png_get_cHRM_XYZ_fixed(png_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_red_X, png_fixed_point *int_red_Y, + png_fixed_point *int_red_Z, png_fixed_point *int_green_X, + png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, + png_fixed_point *int_blue_Z) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_xy xy; + png_XYZ XYZ; + + png_debug1(1, "in %s retrieval function", "cHRM_XYZ"); + + xy.whitex = info_ptr->x_white; + xy.whitey = info_ptr->y_white; + xy.redx = info_ptr->x_red; + xy.redy = info_ptr->y_red; + xy.greenx = info_ptr->x_green; + xy.greeny = info_ptr->y_green; + xy.bluex = info_ptr->x_blue; + xy.bluey = info_ptr->y_blue; + + /* The *_checked function handles error reporting, so just return 0 if + * there is a failure here. + */ + if (png_XYZ_from_xy_checked(png_ptr, &XYZ, xy)) + { + if (int_red_X != NULL) + *int_red_X = XYZ.redX; + if (int_red_Y != NULL) + *int_red_Y = XYZ.redY; + if (int_red_Z != NULL) + *int_red_Z = XYZ.redZ; + if (int_green_X != NULL) + *int_green_X = XYZ.greenX; + if (int_green_Y != NULL) + *int_green_Y = XYZ.greenY; + if (int_green_Z != NULL) + *int_green_Z = XYZ.greenZ; + if (int_blue_X != NULL) + *int_blue_X = XYZ.blueX; + if (int_blue_Y != NULL) + *int_blue_Y = XYZ.blueY; + if (int_blue_Z != NULL) + *int_blue_Z = XYZ.blueZ; + + return (PNG_INFO_cHRM); + } + } + + return (0); +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_const_structp png_ptr, png_const_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 = png_float(png_ptr, info_ptr->x_white, "cHRM white X"); + if (white_y != NULL) + *white_y = png_float(png_ptr, info_ptr->y_white, "cHRM white Y"); + if (red_x != NULL) + *red_x = png_float(png_ptr, info_ptr->x_red, "cHRM red X"); + if (red_y != NULL) + *red_y = png_float(png_ptr, info_ptr->y_red, "cHRM red Y"); + if (green_x != NULL) + *green_x = png_float(png_ptr, info_ptr->x_green, "cHRM green X"); + if (green_y != NULL) + *green_y = png_float(png_ptr, info_ptr->y_green, "cHRM green Y"); + if (blue_x != NULL) + *blue_x = png_float(png_ptr, info_ptr->x_blue, "cHRM blue X"); + if (blue_y != NULL) + *blue_y = png_float(png_ptr, info_ptr->y_blue, "cHRM blue Y"); + return (PNG_INFO_cHRM); + } + + return (0); +} + +png_uint_32 PNGAPI +png_get_cHRM_XYZ(png_structp png_ptr, png_const_infop info_ptr, + double *red_X, double *red_Y, double *red_Z, double *green_X, + double *green_Y, double *green_Z, double *blue_X, double *blue_Y, + double *blue_Z) +{ + png_XYZ XYZ; + + if (png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, + &XYZ.redX, &XYZ.redY, &XYZ.redZ, &XYZ.greenX, &XYZ.greenY, &XYZ.greenZ, + &XYZ.blueX, &XYZ.blueY, &XYZ.blueZ) & PNG_INFO_cHRM) + { + if (red_X != NULL) + *red_X = png_float(png_ptr, XYZ.redX, "cHRM red X"); + if (red_Y != NULL) + *red_Y = png_float(png_ptr, XYZ.redY, "cHRM red Y"); + if (red_Z != NULL) + *red_Z = png_float(png_ptr, XYZ.redZ, "cHRM red Z"); + if (green_X != NULL) + *green_X = png_float(png_ptr, XYZ.greenX, "cHRM green X"); + if (green_Y != NULL) + *green_Y = png_float(png_ptr, XYZ.greenY, "cHRM green Y"); + if (green_Z != NULL) + *green_Z = png_float(png_ptr, XYZ.greenZ, "cHRM green Z"); + if (blue_X != NULL) + *blue_X = png_float(png_ptr, XYZ.blueX, "cHRM blue X"); + if (blue_Y != NULL) + *blue_Y = png_float(png_ptr, XYZ.blueY, "cHRM blue Y"); + if (blue_Z != NULL) + *blue_Z = png_float(png_ptr, XYZ.blueZ, "cHRM blue Z"); + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_const_structp png_ptr, png_const_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->x_white; + if (white_y != NULL) + *white_y = info_ptr->y_white; + if (red_x != NULL) + *red_x = info_ptr->x_red; + if (red_y != NULL) + *red_y = info_ptr->y_red; + if (green_x != NULL) + *green_x = info_ptr->x_green; + if (green_y != NULL) + *green_y = info_ptr->y_green; + if (blue_x != NULL) + *blue_x = info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +png_uint_32 PNGFAPI +png_get_gAMA_fixed(png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *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 = info_ptr->gamma; + return (PNG_INFO_gAMA); + } + + return (0); +} +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_const_structp png_ptr, png_const_infop info_ptr, + double *file_gamma) +{ + png_fixed_point igamma; + png_uint_32 ok = png_get_gAMA_fixed(png_ptr, info_ptr, &igamma); + + if (ok) + *file_gamma = png_float(png_ptr, igamma, "png_get_gAMA"); + + return ok; +} + +# endif +#endif + +#ifdef PNG_sRGB_SUPPORTED +png_uint_32 PNGAPI +png_get_sRGB(png_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, + png_bytepp 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 && compression_type != 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 = info_ptr->iccp_proflen; + *compression_type = info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + + return (0); +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +png_uint_32 PNGAPI +png_get_sPLT(png_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_const_structp png_ptr, png_const_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_FIXED_POINT_SUPPORTED +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_fixed(png_structp png_ptr, png_const_infop info_ptr, + int *unit, png_fixed_point *width, png_fixed_point *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + /*TODO: make this work without FP support */ + *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); + *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), + "sCAL height"); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING_ARITHMETIC */ +# endif /* FIXED_POINT */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_const_structp png_ptr, png_const_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 = atof(info_ptr->scal_s_width); + *height = atof(info_ptr->scal_s_height); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING POINT */ +png_uint_32 PNGAPI +png_get_sCAL_s(png_const_structp png_ptr, png_const_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 /* sCAL */ + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs(png_const_structp png_ptr, png_const_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 /* pHYs */ + +png_uint_32 PNGAPI +png_get_PLTE(png_const_structp png_ptr, png_const_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_const_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_const_structp png_ptr, png_const_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 0x%lx retrieval function", + (unsigned long)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_const_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_const_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) +{ + 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_alpha != NULL) + { + *trans_alpha = info_ptr->trans_alpha; + retval |= PNG_INFO_tRNS; + } + + if (trans_color != NULL) + *trans_color = &(info_ptr->trans_color); + } + + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_color != NULL) + { + *trans_color = &(info_ptr->trans_color); + retval |= PNG_INFO_tRNS; + } + + if (trans_alpha != NULL) + *trans_alpha = NULL; + } + + if (num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + + return (retval); +} +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +int PNGAPI +png_get_unknown_chunks(png_const_structp png_ptr, png_const_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return 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_const_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_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_ptr : NULL); +} +#endif + +png_size_t PNGAPI +png_get_compression_buffer_size(png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->zbuf_size : 0); +} + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* These functions were added to libpng 1.2.6 and were enabled + * by default in libpng-1.4.0 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_width_max : 0); +} + +png_uint_32 PNGAPI +png_get_user_height_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_height_max : 0); +} + +/* This function was added to libpng 1.4.0 */ +png_uint_32 PNGAPI +png_get_chunk_cache_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_cache_max : 0); +} + +/* This function was added to libpng 1.4.1 */ +png_alloc_size_t PNGAPI +png_get_chunk_malloc_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +/* These functions were added to libpng 1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +png_uint_32 PNGAPI +png_get_io_state (png_structp png_ptr) +{ + return png_ptr->io_state; +} + +png_uint_32 PNGAPI +png_get_io_chunk_type (png_const_structp png_ptr) +{ + return png_ptr->chunk_name; +} + +png_const_bytep PNGAPI +png_get_io_chunk_name (png_structp png_ptr) +{ + PNG_CSTRING_FROM_CHUNK(png_ptr->io_chunk_string, png_ptr->chunk_name); + return png_ptr->io_chunk_string; +} +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibPNG/pnginfo.h b/plugins/FreeImage/src/LibPNG/pnginfo.h new file mode 100644 index 0000000000..bbfb105aaf --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pnginfo.h @@ -0,0 +1,269 @@ + +/* pnginfo.h - header file for PNG reference library + * + * 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.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + + /* 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, using png_set_*() functions, 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 libpng-1.5.0 this was moved into a separate private + * file that is not visible to applications. + * + * 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. + */ +#ifndef PNGINFO_H +#define PNGINFO_H + +struct png_info_def +{ + /* the following are necessary for every PNG file */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following is informational only on read, and not used on writes. */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ + png_byte signature[8]; /* 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) + /* 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. + */ + png_fixed_point gamma; +#endif + +#ifdef PNG_sRGB_SUPPORTED + /* GR-P, 0.96a */ + /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ + png_byte srgb_intent; /* 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; /* number of comments read or comments to write */ + int max_text; /* current size of text array */ + png_textp text; /* array of comments read or comments 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; +#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; /* 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_alpha; /* alpha values for paletted image */ + png_color_16 trans_color; /* 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; +#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; /* x offset on page */ + png_int_32 y_offset; /* y offset on page */ + png_byte offset_unit_type; /* 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; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit; /* vertical pixel density */ + png_byte phys_unit_type; /* 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; +#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. + */ + png_fixed_point x_white; + png_fixed_point y_white; + png_fixed_point x_red; + png_fixed_point y_red; + png_fixed_point x_green; + png_fixed_point y_green; + png_fixed_point x_blue; + png_fixed_point y_blue; +#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; /* pCAL chunk description string */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ + png_charpp pcal_params; /* ASCII strings containing parameter values */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams; /* number of parameters given in pcal_params */ +#endif + +/* New members added in libpng-1.0.6 */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#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; + int unknown_chunks_num; +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* iCCP chunk data. */ + png_charp iccp_name; /* profile name */ + png_bytep iccp_profile; /* International Color Consortium profile data */ + png_uint_32 iccp_proflen; /* ICC profile data length */ + png_byte iccp_compression; /* Always zero */ +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes; + png_uint_32 splt_palettes_num; +#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. Data values are valid if (valid & PNG_INFO_sCAL) is + * non-zero. + */ + png_byte scal_unit; /* unit of physical scale */ + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ +#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; /* the image bits */ +#endif + +}; +#endif /* PNGINFO_H */ diff --git a/plugins/FreeImage/src/LibPNG/pnglibconf.h b/plugins/FreeImage/src/LibPNG/pnglibconf.h new file mode 100644 index 0000000000..8022a5a881 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pnglibconf.h @@ -0,0 +1,187 @@ + +/* libpng STANDARD API DEFINITION */ + +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.5.4 - last changed on June 22, 2011 */ + +/* Copyright (c) 1998-2011 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 */ + +/* pnglibconf.h */ +/* Derived from: scripts/pnglibconf.dfa */ +/* If you edit this file by hand you must obey the rules expressed in */ +/* pnglibconf.dfa with respect to the dependencies between the following */ +/* symbols. It is much better to generate a new file using */ +/* scripts/libpngconf.mak */ + +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* settings */ +#define PNG_API_RULE 0 +#define PNG_CALLOC_SUPPORTED +#define PNG_COST_SHIFT 3 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_sCAL_PRECISION 5 +#define PNG_USER_CHUNK_CACHE_MAX 0 +#define PNG_USER_CHUNK_MALLOC_MAX 0 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_WEIGHT_SHIFT 8 +#define PNG_ZBUF_SIZE 8192 +/* end of settings */ +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGN_MEMORY_SUPPORTED +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_cHRM_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED +/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +#endif /* PNGLCONF_H */ diff --git a/plugins/FreeImage/src/LibPNG/pngmem.c b/plugins/FreeImage/src/LibPNG/pngmem.c new file mode 100644 index 0000000000..25b5c73546 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngmem.c @@ -0,0 +1,667 @@ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.5.7 [December 15, 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 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. + */ + +#include "pngpriv.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_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct,(int type),PNG_ALLOCATED) +{ +# ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), + PNG_ALLOCATED) +{ +# 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; + memset(&dummy_struct, 0, sizeof dummy_struct); + dummy_struct.mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(&dummy_struct, (png_alloc_size_t)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, NULL, 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; + memset(&dummy_struct, 0, sizeof dummy_struct); + dummy_struct.mem_ptr=mem_ptr; + (*(free_fn))(&dummy_struct, 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_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + 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, 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_FUNCTION(png_voidp,PNGAPI +png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + 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, mem_level, window_bits; + png_byte huge * hptr; + int window_bits + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + window_bits = + png_ptr->zlib_window_bits >= png_ptr->zlib_text_window_bits ? + png_ptr->zlib_window_bits : png_ptr->zlib_text_window_bits; + + if (window_bits > 14) + num_blocks = (int)(1 << (window_bits - 14)); + + else + num_blocks = 1; + + mem_level = + png_ptr->zlib_mem_level >= png_ptr->zlib_text_mem_level ? + png_ptr->zlib_mem_level : png_ptr->zlib_text_mem_level; + + if (mem_level >= 7) + num_blocks += (int)(1 << (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_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct,(int type),PNG_ALLOCATED) +{ +# ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, 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_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), + PNG_ALLOCATED) +{ +# 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, NULL, 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_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + 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_FUNCTION(png_voidp,PNGAPI +png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + 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 */ + +/* 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_FUNCTION(png_voidp,PNGAPI +png_malloc_warn,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + 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); +} + + +#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_const_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/plugins/FreeImage/src/LibPNG/pngpread.c b/plugins/FreeImage/src/LibPNG/pngpread.c new file mode 100644 index 0000000000..eda5a6c80f --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngpread.c @@ -0,0 +1,1843 @@ + +/* pngpread.c - read a png file in push mode + * + * Last changed in libpng 1.5.9 [February 18, 2012] + * 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 + */ + +#include "pngpriv.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); + } +} + +png_size_t PNGAPI +png_process_data_pause(png_structp png_ptr, int save) +{ + if (png_ptr != NULL) + { + /* It's easiest for the caller if we do the save, then the caller doesn't + * have to supply the same data again: + */ + if (save) + png_push_save_buffer(png_ptr); + else + { + /* This includes any pending saved bytes: */ + png_size_t remaining = png_ptr->buffer_size; + png_ptr->buffer_size = 0; + + /* So subtract the saved buffer size, unless all the data + * is actually 'saved', in which case we just return 0 + */ + if (png_ptr->save_buffer_size < remaining) + return remaining - png_ptr->save_buffer_size; + } + } + + return 0; +} + +png_uint_32 PNGAPI +png_process_data_skip(png_structp png_ptr) +{ + png_uint_32 remaining = 0; + + if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE && + png_ptr->skip_length > 0) + { + /* At the end of png_process_data the buffer size must be 0 (see the loop + * above) so we can detect a broken call here: + */ + if (png_ptr->buffer_size != 0) + png_error(png_ptr, + "png_process_data_skip called inside png_process_data"); + + /* If is impossible for there to be a saved buffer at this point - + * otherwise we could not be in SKIP mode. This will also happen if + * png_process_skip is called inside png_process_data (but only very + * rarely.) + */ + if (png_ptr->save_buffer_size != 0) + png_error(png_ptr, "png_process_data_skip called with saved data"); + + remaining = png_ptr->skip_length; + png_ptr->skip_length = 0; + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + + return remaining; +} + +/* 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; + } + +#ifdef PNG_READ_tEXt_SUPPORTED + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } + +#endif + 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) +{ + png_uint_32 chunk_name; + + /* 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]; + png_byte chunk_tag[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, chunk_tag, 4); + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + chunk_name = png_ptr->chunk_name; + + if (chunk_name == png_IDAT) + { + /* This is here above the if/else case statement below because if the + * unknown handling marks 'IDAT' as unknown then the IDAT handling case is + * completely skipped. + * + * TODO: there must be a better way of doing this. + */ + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + } + + if (chunk_name == png_IHDR) + { + 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 (chunk_name == png_IEND) + { + 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_chunk_unknown_handling(png_ptr, chunk_name)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + if (chunk_name == png_IDAT) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + + if (chunk_name == png_PLTE) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (chunk_name == png_IDAT) + { + 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 (chunk_name == png_PLTE) + { + 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 (chunk_name == png_IDAT) + { + /* 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_benign_error(png_ptr, "Too many IDATs 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_ptr->chunk_name == png_gAMA) + { + 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_ptr->chunk_name == png_sBIT) + { + 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_ptr->chunk_name == png_cHRM) + { + 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 (chunk_name == png_sRGB) + { + 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_ptr->chunk_name == png_iCCP) + { + 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 (chunk_name == png_sPLT) + { + 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 (chunk_name == png_tRNS) + { + 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 (chunk_name == png_bKGD) + { + 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 (chunk_name == png_hIST) + { + 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 (chunk_name == png_pHYs) + { + 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 (chunk_name == png_oFFs) + { + 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 (chunk_name == png_pCAL) + { + 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 (chunk_name == png_sCAL) + { + 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 (chunk_name == png_tIME) + { + 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 (chunk_name == png_tEXt) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (chunk_name == png_zTXt) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (chunk_name == png_iTXt) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_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_push_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 = png_ptr->save_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'save_buffer_size', but + * they are of different types and we don't know which variable has the + * fewest bits. Carefully select the smaller and cast it to the type of + * the larger - this cannot overflow. Do not cast in the following test + * - it will break on either 16 or 64 bit platforms. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + 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 = png_ptr->current_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'current_buffer_size', here, + * the same problem exists as above and the same solution. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + 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 PNGCBAPI +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, 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) +{ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + png_byte chunk_tag[4]; + + /* TODO: this code can be commoned up with the same code in push_read */ + 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, chunk_tag, 4); + png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_ptr->chunk_name != png_IDAT) + { + 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 = png_ptr->save_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. Do not cast in the following test - it + * will break on either 16 or 64 bit platforms. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_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 -= idat_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 = png_ptr->current_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_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 -= idat_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 someplace 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 (a stream with a missing end code) can still + * be handled, 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 in IDAT"); +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + /* 1.5.6: row_info moved out of png_struct to a local here. */ + png_row_info row_info; + + row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ + row_info.color_type = png_ptr->color_type; + row_info.bit_depth = png_ptr->bit_depth; + row_info.channels = png_ptr->channels; + row_info.pixel_depth = png_ptr->pixel_depth; + row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); + + if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) + { + if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) + png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, + png_ptr->prev_row + 1, png_ptr->row_buf[0]); + else + png_error(png_ptr, "bad adaptive filter value"); + } + + /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before + * 1.5.6, while the buffer really is this big in current versions of libpng + * it may not be in the future, so this was changed just to copy the + * interlaced row count: + */ + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) + png_do_read_transformations(png_ptr, &row_info); +#endif + + /* The transformed pixel depth should match the depth now in row_info. */ + if (png_ptr->transformed_pixel_depth == 0) + { + png_ptr->transformed_pixel_depth = row_info.pixel_depth; + if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) + png_error(png_ptr, "progressive row overflow"); + } + + else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) + png_error(png_ptr, "internal progressive row size calculation error"); + + +#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) + png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, + png_ptr->transformations); + + 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, 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, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, 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, 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, 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, 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, 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, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, 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, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + default: + 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, 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_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + static PNG_CONST png_byte FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte 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 + static PNG_CONST png_byte 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(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 */ +} + +#ifdef PNG_READ_tEXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place tEXt"); + /* NOT REACHED */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; + text_ptr->itxt_length = 0; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place zTXt"); + /* NOT REACHED */ + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + /* zTXt can't have zero text */ + if (text >= key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep)text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + key_size + 1)); + + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + png_memcpy(text, key, key_size); + + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + + *(text + text_size) = '\0'; + } + + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + 1)); + + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; + text_ptr->itxt_length = 0; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place iTXt"); + /* NOT REACHED */ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (lang = key; *lang; lang++) + /* Empty loop */ ; + + if (lang < key + png_ptr->current_text_size - 3) + lang++; + + comp_flag = *lang++; + lang++; /* Skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + text=lang_key; + + if (lang_key < key + png_ptr->current_text_size - 1) + { + for (; *text; text++) + /* Empty loop */ ; + } + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_ptr->current_text = NULL; + + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk"); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip = 0; + png_uint_32 chunk_name = png_ptr->chunk_name; + + if (PNG_CHUNK_CRITICAL(chunk_name)) + { +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_chunk_unknown_handling(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"); + + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + /* TODO: the code below is apparently just using the + * png_struct::unknown_chunk member as a temporarily variable, it should be + * possible to eliminate both it and the temporary buffer. + */ + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > 65535) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - 65535; + length = 65535; + } +#endif + /* This is just a record for the user; libpng doesn't use the character + * form of the name. + */ + PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); + + png_ptr->unknown_chunk.size = length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, + png_ptr->unknown_chunk.size); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, + png_ptr->unknown_chunk.size); + } + +#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_CHUNK_CRITICAL(png_ptr->chunk_name)) + if (png_chunk_unknown_handling(png_ptr, chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + 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_push_crc_skip(png_ptr, skip); +} + +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); +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, png_bytep old_row, + png_const_bytep new_row) +{ + if (png_ptr == NULL) + return; + + /* new_row is a flag here - if it is NULL then the app callback was called + * from an empty row (see the calls to png_struct::row_fn below), otherwise + * it must be png_ptr->row_buf+1 + */ + if (new_row != NULL) + png_combine_row(png_ptr, old_row, 1/*display*/); +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +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_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibPNG/pngpriv.h b/plugins/FreeImage/src/LibPNG/pngpriv.h new file mode 100644 index 0000000000..02cc5d8c53 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngpriv.h @@ -0,0 +1,1629 @@ + +/* pngpriv.h - private declarations for use inside libpng + * + * For conditions of distribution and use, see copyright notice in png.h + * 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.) + * + * Last changed in libpng 1.5.7 [December 15, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The symbols declared in this file (including the functions declared + * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public + * interface, and are not recommended for use by regular applications. + * Some of them may become public in the future; others may stay private, + * change in an incompatible way, or even disappear. + * Although the libpng users are not forbidden to include this header, + * they should be well aware of the issues that may arise from doing so. + */ + +#ifndef PNGPRIV_H +#define PNGPRIV_H + +/* Feature Test Macros. The following are defined here to ensure that correctly + * implemented libraries reveal the APIs libpng needs to build and hide those + * that are not needed and potentially damaging to the compilation. + * + * Feature Test Macros must be defined before any system header is included (see + * POSIX 1003.1 2.8.2 "POSIX Symbols." + * + * These macros only have an effect if the operating system supports either + * POSIX 1003.1 or C99, or both. On other operating systems (particularly + * Windows/Visual Studio) there is no effect; the OS specific tests below are + * still required (as of 2011-05-02.) + */ +#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ + +/* This is required for the definition of abort(), used as a last ditch + * error handler when all else fails. + */ +#include + +/* This is used to find 'offsetof', used below for alignment tests. */ +#include + +#define PNGLIB_BUILD /*libpng is being built, not used*/ + +#ifdef PNG_USER_CONFIG +# include "pngusr.h" + /* These should have been defined in pngusr.h */ +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD "Custom libpng build" +# endif +# ifndef PNG_USER_DLLFNAME_POSTFIX +# define PNG_USER_DLLFNAME_POSTFIX "Cb" +# endif +#endif + +/* Is this a build of a DLL where compilation of the object modules requires + * different preprocessor settings to those required for a simple library? If + * so PNG_BUILD_DLL must be set. + * + * If libpng is used inside a DLL but that DLL does not export the libpng APIs + * PNG_BUILD_DLL must not be set. To avoid the code below kicking in build a + * static library of libpng then link the DLL against that. + */ +#ifndef PNG_BUILD_DLL +# ifdef DLL_EXPORT + /* This is set by libtool when files are compiled for a DLL; libtool + * always compiles twice, even on systems where it isn't necessary. Set + * PNG_BUILD_DLL in case it is necessary: + */ +# define PNG_BUILD_DLL +# else +# ifdef _WINDLL + /* This is set by the Microsoft Visual Studio IDE in projects that + * build a DLL. It can't easily be removed from those projects (it + * isn't visible in the Visual Studio UI) so it is a fairly reliable + * indication that PNG_IMPEXP needs to be set to the DLL export + * attributes. + */ +# define PNG_BUILD_DLL +# else +# ifdef __DLL__ + /* This is set by the Borland C system when compiling for a DLL + * (as above.) + */ +# define PNG_BUILD_DLL +# else + /* Add additional compiler cases here. */ +# endif +# endif +# endif +#endif /* Setting PNG_BUILD_DLL if required */ + +/* See pngconf.h for more details: the builder of the library may set this on + * the command line to the right thing for the specific compilation system or it + * may be automagically set above (at present we know of no system where it does + * need to be set on the command line.) + * + * PNG_IMPEXP must be set here when building the library to prevent pngconf.h + * setting it to the "import" setting for a DLL build. + */ +#ifndef PNG_IMPEXP +# ifdef PNG_BUILD_DLL +# define PNG_IMPEXP PNG_DLL_EXPORT +# else + /* Not building a DLL, or the DLL doesn't require specific export + * definitions. + */ +# define PNG_IMPEXP +# endif +#endif + +/* No warnings for private or deprecated functions in the build: */ +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE +#endif + +#include "png.h" +#include "pnginfo.h" +#include "pngstruct.h" + +/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */ +#ifndef PNG_DLL_EXPORT +# define PNG_DLL_EXPORT +#endif + +/* This is used for 16 bit gamma tables - only the top level pointers are const, + * this could be changed: + */ +typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; + +/* Added at libpng-1.2.9 */ +/* Moved to pngpriv.h at libpng-1.5.0 */ + +/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" + * script. We may need it here to get the correct configuration on things + * like limits. + */ +#ifdef PNG_CONFIGURE_LIBPNG +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +#endif + +/* Moved to pngpriv.h at libpng-1.5.0 */ +/* NOTE: some of these may have been used in external applications as + * these definitions were exposed in pngconf.h prior to 1.5. + */ + +/* 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. + * + * zlib provides 'MAXSEG_64K' which, if defined, indicates the + * same limit and pngconf.h (already included) sets the limit + * if certain operating systems are detected. + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +#ifndef PNG_UNUSED +/* Unused formal parameter warnings are silenced using the following macro + * which is expected to have no bad effects on performance (optimizing + * compilers will probably remove it entirely). Note that if you replace + * it with something other than whitespace, you must include the terminating + * semicolon. + */ +# define PNG_UNUSED(param) (void)param; +#endif + +/* 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 + +/* PNG_STATIC is used to mark internal file scope functions if they need to be + * accessed for implementation tests (see the code in tests/?*). + */ +#ifndef PNG_STATIC +# define PNG_STATIC static +#endif + +/* C99 restrict is used where possible, to do this 'restrict' is defined as + * empty if we can't be sure it is supported. configure builds have already + * done this work. + */ +#ifdef PNG_CONFIGURE_LIBPNG +# define PNG_RESTRICT restrict +#else + /* Modern compilers support restrict, but assume not for anything not + * recognized here: + */ +# if defined __GNUC__ || defined _MSC_VER || defined __WATCOMC__ +# define PNG_RESTRICT restrict +# else +# define PNG_RESTRICT +# endif +#endif + +/* If warnings or errors are turned off the code is disabled or redirected here. + * From 1.5.4 functions have been added to allow very limited formatting of + * error and warning messages - this code will also be disabled here. + */ +#ifdef PNG_WARNINGS_SUPPORTED +# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p; +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +# define png_warning_parameter(p,number,string) ((void)0) +# define png_warning_parameter_unsigned(p,number,format,value) ((void)0) +# define png_warning_parameter_signed(p,number,format,value) ((void)0) +# define png_formatted_warning(pp,p,message) ((void)(pp)) +# define PNG_WARNING_PARAMETERS(p) +#endif +#ifndef PNG_ERROR_TEXT_SUPPORTED +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +# define png_fixed_error(s1,s2) png_err(s1) +#endif + +/* C allows up-casts from (void*) to any pointer and (const void*) to any + * pointer to a const object. C++ regards this as a type error and requires an + * explicit, static, cast and provides the static_cast<> rune to ensure that + * const is not cast away. + */ +#ifdef __cplusplus +# define png_voidcast(type, value) static_cast(value) +#else +# define png_voidcast(type, value) (value) +#endif /* __cplusplus */ + +#ifndef PNG_EXTERN +/* The functions exported by PNG_EXTERN are 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 might be made available again. + * + * 1.5.7: turned the use of 'extern' back on, since it is localized to pngpriv.h + * it should be safe now (it is unclear why it was turned off.) + */ +# define PNG_EXTERN extern +#endif + +/* Some fixed point APIs are still required even if not exported because + * they get used by the corresponding floating point APIs. This magic + * deals with this: + */ +#ifdef PNG_FIXED_POINT_SUPPORTED +# define PNGFAPI PNGAPI +#else +# define PNGFAPI /* PRIVATE */ +#endif + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) + /* png.c requires the following ANSI-C constants if the conversion of + * floating point to ASCII is implemented therein: + * + * DBL_DIG Maximum number of decimal digits (can be set to any constant) + * DBL_MIN Smallest normalized fp number (can be set to an arbitrary value) + * DBL_MAX Maximum floating point number (can be set to an arbitrary value) + */ +# include + +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ + defined(_WIN32) || defined(__WIN32__) +# include /* defines _WINDOWS_ macro */ +#endif + +/* Moved here around 1.5.0beta36 from pngconf.h */ +/* Users may want to use these so they are not private. Any library + * functions that are passed far data must be model-independent. + */ + +/* Memory model/platform independent fns */ +#ifndef PNG_ABORT +# ifdef _WINDOWS_ +# define PNG_ABORT() ExitProcess(0) +# else +# define PNG_ABORT() abort() +# endif +#endif + +#ifdef USE_FAR_KEYWORD +/* 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_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +#else +# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strlen lstrlenA +# define png_memcmp memcmp +# define png_memcpy CopyMemory +# define png_memset memset +# else +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +# endif +#endif + +/* These macros may need to be architecture dependent. */ +#define PNG_ALIGN_NONE 0 /* do not use data alignment */ +#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */ +#ifdef offsetof +# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */ +#else +# define PNG_ALIGN_OFFSET -1 /* prevent the use of this */ +#endif +#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */ + +#ifndef PNG_ALIGN_TYPE + /* Default to using aligned access optimizations and requiring alignment to a + * multiple of the data type size. Override in a compiler specific fashion + * if necessary by inserting tests here: + */ +# define PNG_ALIGN_TYPE PNG_ALIGN_SIZE +#endif + +#if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE + /* This is used because in some compiler implementations non-aligned + * structure members are supported, so the offsetof approach below fails. + * Set PNG_ALIGN_TO_SIZE=0 for compiler combinations where unaligned access + * is good for performance. Do not do this unless you have tested the result + * and understand it. + */ +# define png_alignof(type) (sizeof (type)) +#else +# if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET +# define png_alignof(type) offsetof(struct{char c; type t;}, t) +# else +# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS +# define png_alignof(type) (1) +# endif + /* Else leave png_alignof undefined to prevent use thereof */ +# endif +#endif + +/* This implicitly assumes alignment is always to a power of 2. */ +#ifdef png_alignof +# define png_isaligned(ptr, type)\ + ((((const char*)ptr-(const char*)0) & (png_alignof(type)-1)) == 0) +#else +# define png_isaligned(ptr, type) 0 +#endif + +/* End of memory model/platform independent support */ +/* End of 1.5.0beta36 move from pngconf.h */ + +/* CONSTANTS and UTILITY MACROS + * These are used internally by libpng and not exposed in the API + */ + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. Three of these + * are defined in png.h because they need to be visible to applications + * that call png_set_unknown_chunk(). + */ +/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ +/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ +#define PNG_HAVE_IDAT 0x04 +/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ +#define PNG_HAVE_IEND 0x10 +#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_QUANTIZE 0x0040 +#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ +#define PNG_BACKGROUND_EXPAND 0x0100 +#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ +#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000 +#define PNG_PACKSWAP 0x10000 +#define PNG_SWAP_ALPHA 0x20000 +#define PNG_STRIP_ALPHA 0x40000 +#define PNG_INVERT_ALPHA 0x80000 +#define PNG_USER_TRANSFORM 0x100000 +#define PNG_RGB_TO_GRAY_ERR 0x200000 +#define PNG_RGB_TO_GRAY_WARN 0x400000 +#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */ +#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */ +#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */ +#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */ + /* 0x8000000 unused */ + /* 0x10000000 unused */ + /* 0x20000000 unused */ + /* 0x40000000 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_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#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_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000 +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000 +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000 + /* 0x200000 unused */ + /* 0x400000 unused */ +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000 /* Added to libpng-1.4.0 */ +#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000 /* 5 lines added */ +#define PNG_FLAG_ZTXT_CUSTOM_LEVEL 0x2000000 /* to libpng-1.5.4 */ +#define PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL 0x4000000 +#define PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS 0x8000000 +#define PNG_FLAG_ZTXT_CUSTOM_METHOD 0x10000000 + /* 0x20000000 unused */ + /* 0x40000000 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) + +/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib + * can handle at once. This type need be no larger than 16 bits (so maximum of + * 65535), this define allows us to discover how big it is, but limited by the + * maximuum for png_size_t. The value can be overriden in a library build + * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably + * lower value (e.g. 255 works). A lower value may help memory usage (slightly) + * and may even improve performance on some systems (and degrade it on others.) + */ +#ifndef ZLIB_IO_MAX +# define ZLIB_IO_MAX ((uInt)-1) +#endif + +/* 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 ? \ + ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ + (( ((png_size_t)(width) * ((png_size_t)(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)) + +/* Conversions between fixed and floating point, only defined if + * required (to make sure the code doesn't accidentally use float + * when it is supposedly disabled.) + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* The floating point conversion can't overflow, though it can and + * does lose accuracy relative to the original fixed point value. + * In practice this doesn't matter because png_fixed_point only + * stores numbers with very low precision. The png_ptr and s + * arguments are unused by default but are there in case error + * checking becomes a requirement. + */ +#define png_float(png_ptr, fixed, s) (.00001 * (fixed)) + +/* The fixed point conversion performs range checking and evaluates + * its argument multiple times, so must be used with care. The + * range checking uses the PNG specification values for a signed + * 32 bit fixed point value except that the values are deliberately + * rounded-to-zero to an integral value - 21474 (21474.83 is roughly + * (2^31-1) * 100000). 's' is a string that describes the value being + * converted. + * + * NOTE: this macro will raise a png_error if the range check fails, + * therefore it is normally only appropriate to use this on values + * that come from API calls or other sources where an out of range + * error indicates a programming error, not a data error! + * + * NOTE: by default this is off - the macro is not used - because the + * function call saves a lot of code. + */ +#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED +#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\ + ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0)) +#else +PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp, + png_const_charp text)); +#endif +#endif + +/* Constants for known chunk types. If you need to add a chunk, define the name + * here. For historical reasons these constants have the form png_; i.e. + * the prefix is lower case. Please use decimal values as the parameters to + * match the ISO PNG specification and to avoid relying on the C locale + * interpretation of character values. + * + * Prior to 1.5.6 these constants were strings, as of 1.5.6 png_uint_32 values + * are computed and a new macro (PNG_STRING_FROM_CHUNK) added to allow a string + * to be generated if required. + * + * PNG_32b correctly produces a value shifted by up to 24 bits, even on + * architectures where (int) is only 16 bits. + */ +#define PNG_32b(b,s) ((png_uint_32)(b) << (s)) +#define PNG_CHUNK(b1,b2,b3,b4) \ + (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0)) + +#define png_IHDR PNG_CHUNK( 73, 72, 68, 82) +#define png_IDAT PNG_CHUNK( 73, 68, 65, 84) +#define png_IEND PNG_CHUNK( 73, 69, 78, 68) +#define png_PLTE PNG_CHUNK( 80, 76, 84, 69) +#define png_bKGD PNG_CHUNK( 98, 75, 71, 68) +#define png_cHRM PNG_CHUNK( 99, 72, 82, 77) +#define png_gAMA PNG_CHUNK(103, 65, 77, 65) +#define png_hIST PNG_CHUNK(104, 73, 83, 84) +#define png_iCCP PNG_CHUNK(105, 67, 67, 80) +#define png_iTXt PNG_CHUNK(105, 84, 88, 116) +#define png_oFFs PNG_CHUNK(111, 70, 70, 115) +#define png_pCAL PNG_CHUNK(112, 67, 65, 76) +#define png_sCAL PNG_CHUNK(115, 67, 65, 76) +#define png_pHYs PNG_CHUNK(112, 72, 89, 115) +#define png_sBIT PNG_CHUNK(115, 66, 73, 84) +#define png_sPLT PNG_CHUNK(115, 80, 76, 84) +#define png_sRGB PNG_CHUNK(115, 82, 71, 66) +#define png_sTER PNG_CHUNK(115, 84, 69, 82) +#define png_tEXt PNG_CHUNK(116, 69, 88, 116) +#define png_tIME PNG_CHUNK(116, 73, 77, 69) +#define png_tRNS PNG_CHUNK(116, 82, 78, 83) +#define png_zTXt PNG_CHUNK(122, 84, 88, 116) + +/* The following will work on (signed char*) strings, whereas the get_uint_32 + * macro will fail on top-bit-set values because of the sign extension. + */ +#define PNG_CHUNK_FROM_STRING(s)\ + PNG_CHUNK(0xff&(s)[0], 0xff&(s)[1], 0xff&(s)[2], 0xff&(s)[3]) + +/* This uses (char), not (png_byte) to avoid warnings on systems where (char) is + * signed and the argument is a (char[]) This macro will fail miserably on + * systems where (char) is more than 8 bits. + */ +#define PNG_STRING_FROM_CHUNK(s,c)\ + (void)(((char*)(s))[0]=(char)((c)>>24), ((char*)(s))[1]=(char)((c)>>16),\ + ((char*)(s))[2]=(char)((c)>>8), ((char*)(s))[3]=(char)((c))) + +/* Do the same but terminate with a null character. */ +#define PNG_CSTRING_FROM_CHUNK(s,c)\ + (void)(PNG_STRING_FROM_CHUNK(s,c), ((char*)(s))[4] = 0) + +/* Test on flag values as defined in the spec (section 5.4): */ +#define PNG_CHUNK_ANCILLIARY(c) (1 & ((c) >> 29)) +#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLIARY(c)) +#define PNG_CHUNK_PRIVATE(c) (1 & ((c) >> 21)) +#define PNG_CHUNK_RESERVED(c) (1 & ((c) >> 13)) +#define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >> 5)) + +/* Gamma values (new at libpng-1.5.4): */ +#define PNG_GAMMA_MAC_OLD 151724 /* Assume '1.8' is really 2.2/1.45! */ +#define PNG_GAMMA_MAC_INVERSE 65909 +#define PNG_GAMMA_sRGB_INVERSE 45455 + + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* These 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. + */ + +/* Check the user version string for compatibility, returns false if the version + * numbers aren't compatible. + */ +PNG_EXTERN int png_user_version_check(png_structp png_ptr, + png_const_charp user_png_ver); + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct,PNGARG((int type)), + PNG_ALLOCATED); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct_2, + PNGARG((int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)), + PNG_ALLOCATED); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* 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)); + +/* Function to allocate memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN PNG_FUNCTION(voidpf,png_zalloc,PNGARG((voidpf png_ptr, uInt items, + uInt size)),PNG_ALLOCATED); + +/* Function to free memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +/* Next four functions are used internally as callbacks. PNGCBAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to + * PNGCBAPI at 1.5.0 + */ + +PNG_EXTERN void PNGCBAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGCBAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGCBAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED +PNG_EXTERN void PNGCBAPI png_default_flush PNGARG((png_structp png_ptr)); +# endif +#endif + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Read and check the PNG file signature */ +PNG_EXTERN void png_read_sig PNGARG((png_structp png_ptr, png_infop info_ptr)); + +/* Read the chunk header (length + type name) */ +PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr)); + +/* 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)); + +/* 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)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_READ_COMPRESSED_TEXT_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)); +#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)); + +/* 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)); + +/* 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_const_bytep ptr, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* 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_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, + png_const_colorp palette, png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#ifdef PNG_WRITE_gAMA_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +# endif +# ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, + png_fixed_point file_gamma)); +# endif +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, + png_const_color_8p sbit, int color_type)); +#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)); +# endif +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)); +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_const_charp name, int compression_type, + png_const_charp profile, int proflen)); + /* 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_const_sPLT_tp palette)); +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, + png_const_bytep trans, png_const_color_16p values, int number, + int color_type)); +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_const_color_16p values, int color_type)); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, + png_const_uint_16p hist, int num_hist)); +#endif + +/* Chunks that have keywords */ +#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_const_charp key, png_charpp new_key)); +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_const_charp key, + png_const_charp text, png_size_t text_len)); +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_const_charp key, + png_const_charp text, png_size_t text_len, int compression)); +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_const_charp key, png_const_charp lang, + png_const_charp lang_key, png_const_charp text)); +#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_const_textp text_ptr, int num_text)); +#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)); +#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_const_charp units, png_charpp params)); +#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)); +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_const_timep mod_time)); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_const_charp width, png_const_charp height)); +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +/* Combine a row of data, dealing with alpha, etc. if requested. 'row' is an + * array of png_ptr->width pixels. If the image is not interlaced or this + * is the final pass this just does a png_memcpy, otherwise the "display" flag + * is used to determine whether to copy pixels that are not in the current pass. + * + * Because 'png_do_read_interlace' (below) replicates pixels this allows this + * function to achieve the documented 'blocky' appearance during interlaced read + * if display is 1 and the 'sparkle' appearance, where existing pixels in 'row' + * are not changed if they are not in the current pass, when display is 0. + * + * 'display' must be 0 or 1, otherwise the memcpy will be done regardless. + * + * The API always reads from the png_struct row buffer and always assumes that + * it is full width (png_do_read_interlace has already been called.) + * + * This function is only ever used to write to row buffers provided by the + * caller of the relevant libpng API and the row must have already been + * transformed by the read transformations. + * + * The PNG_USE_COMPILE_TIME_MASKS option causes generation of pre-computed + * bitmasks for use within the code, otherwise runtime generated masks are used. + * The default is compile time masks. + */ +#ifndef PNG_USE_COMPILE_TIME_MASKS +# define PNG_USE_COMPILE_TIME_MASKS 1 +#endif +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int display)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Expand an interlaced row: the 'row_info' describes the pass data that has + * been read in and must correspond to the pixels in 'row', the pixels are + * expanded (moved apart) in 'row' to match the final layout, when doing this + * the pixels are *replicated* to the intervening space. This is essential for + * the correct operation of png_combine_row, above. + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); +#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)); +#endif + +/* Unfilter a row: check the filter value before calling this, there is no point + * calling it for PNG_FILTER_VALUE_NONE. + */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp pp, png_row_infop row_info, + png_bytep row, png_const_bytep prev_row, int filter)); + +PNG_EXTERN void png_read_filter_row_up_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_sub3_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_sub4_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_avg3_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_avg4_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_paeth3_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_paeth4_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); + +/* 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)); + +/* 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)); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* Optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* 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)); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_channel PNGARG((png_row_infop row_info, + png_bytep row, int at_start)); +#endif + +#ifdef PNG_16BIT_SUPPORTED +#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)); +#endif +#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)); +#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)); +#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)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_8p sig_bits)); +#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)); +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_scale_16_to_8 PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep palette_lookup, + png_const_bytep quantize_lookup)); + +# ifdef PNG_CORRECT_PALETTE_SUPPORTED +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# 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)); +#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)); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_8p bit_depth)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) +PNG_EXTERN void png_do_compose PNGARG((png_row_infop row_info, + png_bytep row, png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, + png_bytep row, png_structp png_ptr)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +PNG_EXTERN void png_do_encode_alpha PNGARG((png_row_infop row_info, + png_bytep row, png_structp png_ptr)); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_const_colorp palette, png_const_bytep trans, + int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_16p trans_color)); +#endif + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +PNG_EXTERN void png_do_expand_16 PNGARG((png_row_infop row_info, + png_bytep row)); +#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_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)); +#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)); +#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)); +#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)); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED +PNG_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)); +#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)); +#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)); +#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)); +#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)); +#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)); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED +PNG_EXTERN void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#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)); +#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)); +#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)); +#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)); +#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)); +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +#endif + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_uint_32 chunk_name)); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +/* Exactly as png_handle_as_unknown() except that the argument is a 32-bit chunk + * name, not a string. + */ +PNG_EXTERN int png_chunk_unknown_handling PNGARG((png_structp png_ptr, + png_uint_32 chunk_name)); +#endif + +/* Handle the transformations for reading and writing */ +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr, + png_row_infop row_info)); +#endif +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr, + png_row_infop row_info)); +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +# 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_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# 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_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# 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_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# 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_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +/* Added at libpng version 1.4.0 */ +#ifdef PNG_CHECK_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)); +#endif + +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 and 1.4.0 */ +/* Currently only used by png_check_cHRM_fixed */ +PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2, + unsigned long *hi_product, unsigned long *lo_product)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +/* Added at libpng version 1.5.5 */ +typedef struct png_xy +{ + png_fixed_point redx, redy; + png_fixed_point greenx, greeny; + png_fixed_point bluex, bluey; + png_fixed_point whitex, whitey; +} png_xy; + +typedef struct png_XYZ +{ + png_fixed_point redX, redY, redZ; + png_fixed_point greenX, greenY, greenZ; + png_fixed_point blueX, blueY, blueZ; +} png_XYZ; + +/* The conversion APIs return 0 on success, non-zero on a parameter error. They + * allow conversion between the above representations of a color encoding. When + * converting from XYZ end points to chromaticities the absolute magnitude of + * the end points is lost, when converting back the sum of the Y values of the + * three end points will be 1.0 + */ +PNG_EXTERN int png_xy_from_XYZ PNGARG((png_xy *xy, png_XYZ XYZ)); +PNG_EXTERN int png_XYZ_from_xy PNGARG((png_XYZ *XYZ, png_xy xy)); +PNG_EXTERN int png_XYZ_from_xy_checked PNGARG((png_structp png_ptr, + png_XYZ *XYZ, png_xy xy)); +#endif + +/* Added at libpng version 1.4.0 */ +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)); + +/* Free all memory used by the read (old method - NOT DLL EXPORTED) */ +PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr, png_infop end_info_ptr)); + +/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr)); + +#ifdef USE_FAR_KEYWORD /* memory model conversion function */ +PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr, png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr, + png_const_charp name),PNG_NORETURN); +#endif + +/* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite + * the end. Always leaves the buffer nul terminated. Never errors out (and + * there is no error code.) + */ +PNG_EXTERN size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos, + png_const_charp string); + +/* Various internal functions to handle formatted warning messages, currently + * only implemented for warnings. + */ +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. This utility only + * does unsigned values. + */ +PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end, + int format, png_alloc_size_t number); + +/* Convenience macro that takes an array: */ +#define PNG_FORMAT_NUMBER(buffer,format,number) \ + png_format_number(buffer, buffer + (sizeof buffer), format, number) + +/* Suggested size for a number buffer (enough for 64 bits and a sign!) */ +#define PNG_NUMBER_BUFFER_SIZE 24 + +/* These are the integer formats currently supported, the name is formed from + * the standard printf(3) format string. + */ +#define PNG_NUMBER_FORMAT_u 1 /* chose unsigned API! */ +#define PNG_NUMBER_FORMAT_02u 2 +#define PNG_NUMBER_FORMAT_d 1 /* chose signed API! */ +#define PNG_NUMBER_FORMAT_02d 2 +#define PNG_NUMBER_FORMAT_x 3 +#define PNG_NUMBER_FORMAT_02x 4 +#define PNG_NUMBER_FORMAT_fixed 5 /* choose the signed API */ +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* New defines and members adding in libpng-1.5.4 */ +# define PNG_WARNING_PARAMETER_SIZE 32 +# define PNG_WARNING_PARAMETER_COUNT 8 + +/* An l-value of this type has to be passed to the APIs below to cache the + * values of the parameters to a formatted warning message. + */ +typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][ + PNG_WARNING_PARAMETER_SIZE]; + +PNG_EXTERN void png_warning_parameter(png_warning_parameters p, int number, + png_const_charp string); + /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters, + * including the trailing '\0'. + */ +PNG_EXTERN void png_warning_parameter_unsigned(png_warning_parameters p, + int number, int format, png_alloc_size_t value); + /* Use png_alloc_size_t because it is an unsigned type as big as any we + * need to output. Use the following for a signed value. + */ +PNG_EXTERN void png_warning_parameter_signed(png_warning_parameters p, + int number, int format, png_int_32 value); + +PNG_EXTERN void png_formatted_warning(png_structp png_ptr, + png_warning_parameters p, png_const_charp message); + /* 'message' follows the X/Open approach of using @1, @2 to insert + * parameters previously supplied using the above functions. Errors in + * specifying the paramters will simple result in garbage substitutions. + */ +#endif + +/* ASCII to FP interfaces, currently only implemented if sCAL + * support is required. + */ +#if defined(PNG_READ_sCAL_SUPPORTED) +/* MAX_DIGITS is actually the maximum number of characters in an sCAL + * width or height, derived from the precision (number of significant + * digits - a build time settable option) and assumpitions about the + * maximum ridiculous exponent. + */ +#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) + +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_ascii_from_fp PNGARG((png_structp png_ptr, png_charp ascii, + png_size_t size, double fp, unsigned int precision)); +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr, + png_charp ascii, png_size_t size, png_fixed_point fp)); +#endif /* FIXED_POINT */ +#endif /* READ_sCAL */ + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* An internal API to validate the format of a floating point number. + * The result is the index of the next character. If the number is + * not valid it will be the index of a character in the supposed number. + * + * The format of a number is defined in the PNG extensions specification + * and this API is strictly conformant to that spec, not anyone elses! + * + * The format as a regular expression is: + * + * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)? + * + * or: + * + * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)? + * + * The complexity is that either integer or fraction must be present and the + * fraction is permitted to have no digits only if the integer is present. + * + * NOTE: The dangling E problem. + * There is a PNG valid floating point number in the following: + * + * PNG floating point numb1.ers are not greedy. + * + * Working this out requires *TWO* character lookahead (because of the + * sign), the parser does not do this - it will fail at the 'r' - this + * doesn't matter for PNG sCAL chunk values, but it requires more care + * if the value were ever to be embedded in something more complex. Use + * ANSI-C strtod if you need the lookahead. + */ +/* State table for the parser. */ +#define PNG_FP_INTEGER 0 /* before or in integer */ +#define PNG_FP_FRACTION 1 /* before or in fraction */ +#define PNG_FP_EXPONENT 2 /* before or in exponent */ +#define PNG_FP_STATE 3 /* mask for the above */ +#define PNG_FP_SAW_SIGN 4 /* Saw +/- in current state */ +#define PNG_FP_SAW_DIGIT 8 /* Saw a digit in current state */ +#define PNG_FP_SAW_DOT 16 /* Saw a dot in current state */ +#define PNG_FP_SAW_E 32 /* Saw an E (or e) in current state */ +#define PNG_FP_SAW_ANY 60 /* Saw any of the above 4 */ + +/* These three values don't affect the parser. They are set but not used. + */ +#define PNG_FP_WAS_VALID 64 /* Preceding substring is a valid fp number */ +#define PNG_FP_NEGATIVE 128 /* A negative number, including "-0" */ +#define PNG_FP_NONZERO 256 /* A non-zero value */ +#define PNG_FP_STICKY 448 /* The above three flags */ + +/* This is available for the caller to store in 'state' if required. Do not + * call the parser after setting it (the parser sometimes clears it.) + */ +#define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ + +/* Result codes for the parser (boolean - true meants ok, false means + * not ok yet.) + */ +#define PNG_FP_MAYBE 0 /* The number may be valid in the future */ +#define PNG_FP_OK 1 /* The number is valid */ + +/* Tests on the sticky non-zero and negative flags. To pass these checks + * the state must also indicate that the whole number is valid - this is + * achieved by testing PNG_FP_SAW_DIGIT (see the implementation for why this + * is equivalent to PNG_FP_OK above.) + */ +#define PNG_FP_NZ_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NEGATIVE | PNG_FP_NONZERO) + /* NZ_MASK: the string is valid and a non-zero negative value */ +#define PNG_FP_Z_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NONZERO) + /* Z MASK: the string is valid and a non-zero value. */ + /* PNG_FP_SAW_DIGIT: the string is valid. */ +#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT) +#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK) +#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK) + +/* The actual parser. This can be called repeatedly, it updates + * the index into the string and the state variable (which must + * be initialzed to 0). It returns a result code, as above. There + * is no point calling the parser any more if it fails to advance to + * the end of the string - it is stuck on an invalid character (or + * terminated by '\0'). + * + * Note that the pointer will consume an E or even an E+ then leave + * a 'maybe' state even though a preceding integer.fraction is valid. + * The PNG_FP_WAS_VALID flag indicates that a preceding substring was + * a valid number. It's possible to recover from this by calling + * the parser again (from the start, with state 0) but with a string + * that omits the last character (i.e. set the size to the index of + * the problem character.) This has not been tested within libpng. + */ +PNG_EXTERN int png_check_fp_number PNGARG((png_const_charp string, + png_size_t size, int *statep, png_size_tp whereami)); + +/* This is the same but it checks a complete string and returns true + * only if it just contains a floating point number. As of 1.5.4 this + * function also returns the state at the end of parsing the number if + * it was valid (otherwise it returns 0.) This can be used for testing + * for negative or zero values using the sticky flag. + */ +PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string, + png_size_t size)); +#endif /* pCAL || sCAL */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) ||\ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) +/* Added at libpng version 1.5.0 */ +/* This is a utility to provide a*times/div (rounded) and indicate + * if there is an overflow. The result is a boolean - false (0) + * for overflow, true (1) if no overflow, in which case *res + * holds the result. + */ +PNG_EXTERN int png_muldiv PNGARG((png_fixed_point_p res, png_fixed_point a, + png_int_32 multiplied_by, png_int_32 divided_by)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* Same deal, but issue a warning on overflow and return 0. */ +PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr, + png_fixed_point a, png_int_32 multiplied_by, png_int_32 divided_by)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Calculate a reciprocal - used for gamma values. This returns + * 0 if the argument is 0 in order to maintain an undefined value, + * there are no warnings. + */ +PNG_EXTERN png_fixed_point png_reciprocal PNGARG((png_fixed_point a)); + +/* The same but gives a reciprocal of the product of two fixed point + * values. Accuracy is suitable for gamma calculations but this is + * not exact - use png_muldiv for that. + */ +PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a, + png_fixed_point b)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Internal fixed point gamma correction. These APIs are called as + * required to convert single values - they don't need to be fast, + * they are not used when processing image pixel values. + * + * While the input is an 'unsigned' value it must actually be the + * correct bit value - 0..255 or 0..65535 as required. + */ +PNG_EXTERN png_uint_16 png_gamma_correct PNGARG((png_structp png_ptr, + unsigned int value, png_fixed_point gamma_value)); +PNG_EXTERN int png_gamma_significant PNGARG((png_fixed_point gamma_value)); +PNG_EXTERN png_uint_16 png_gamma_16bit_correct PNGARG((unsigned int value, + png_fixed_point gamma_value)); +PNG_EXTERN png_byte png_gamma_8bit_correct PNGARG((unsigned int value, + png_fixed_point gamma_value)); +PNG_EXTERN void png_destroy_gamma_table(png_structp png_ptr); +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, + int bit_depth)); +#endif + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +#include "pngdebug.h" + +#ifdef __cplusplus +} +#endif + +#endif /* PNGPRIV_H */ diff --git a/plugins/FreeImage/src/LibPNG/pngread.c b/plugins/FreeImage/src/LibPNG/pngread.c new file mode 100644 index 0000000000..e2641d540f --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngread.c @@ -0,0 +1,1308 @@ + +/* pngread.c - read a PNG file + * + * Last changed in libpng 1.5.7 [December 15, 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 routines that an application calls directly to + * read a PNG file or stream. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Create a PNG structure for reading, and allocate any memory needed. */ +PNG_FUNCTION(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),PNG_ALLOCATED) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory + * needed. + */ +PNG_FUNCTION(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),PNG_ALLOCATED) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; + volatile int png_cleanup_needed = 0; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf tmp_jmpbuf; +#endif +#endif + + png_debug(1, "in png_create_read_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + malloc_fn, 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; + +# ifdef PNG_USER_CHUNK_CACHE_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_SET_USER_CHUNK_MALLOC_MAX + /* Added at libpng-1.2.43 and 1.4.1 */ + png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; +# endif +#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(tmp_jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ +#endif + PNG_ABORT(); +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), tmp_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); + + /* Call the general version checker (shared with read and write code): */ + if (!png_user_version_check(png_ptr, user_png_ver)) + png_cleanup_needed = 1; + + if (!png_cleanup_needed) + { + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size); + + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + if (!png_cleanup_needed) + { + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: + break; /* Do nothing */ + + case Z_MEM_ERROR: + png_warning(png_ptr, "zlib memory error"); + png_cleanup_needed = 1; + break; + + case Z_STREAM_ERROR: + png_warning(png_ptr, "zlib stream error"); + png_cleanup_needed = 1; + break; + + case Z_VERSION_ERROR: + png_warning(png_ptr, "zlib version error"); + png_cleanup_needed = 1; + break; + + default: png_warning(png_ptr, "Unknown zlib error"); + png_cleanup_needed = 1; + } + } + + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + 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); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, NULL, NULL); + + + return (png_ptr); +} + + +#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; + + /* Read and check the PNG file signature. */ + png_read_sig(png_ptr, info_ptr); + + for (;;) + { + png_uint_32 length = png_read_chunk_header(png_ptr); + png_uint_32 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 (chunk_name == png_IDAT) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (chunk_name == png_IHDR) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (chunk_name == png_IEND) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_chunk_unknown_handling(png_ptr, chunk_name) != + PNG_HANDLE_CHUNK_AS_DEFAULT) + { + if (chunk_name == png_IDAT) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, length); + + if (chunk_name == png_PLTE) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (chunk_name == png_IDAT) + { + 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 (chunk_name == png_PLTE) + png_handle_PLTE(png_ptr, info_ptr, length); + + else if (chunk_name == png_IDAT) + { + 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 (chunk_name == png_bKGD) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (chunk_name == png_cHRM) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (chunk_name == png_gAMA) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (chunk_name == png_hIST) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (chunk_name == png_oFFs) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (chunk_name == png_pCAL) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (chunk_name == png_sCAL) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (chunk_name == png_pHYs) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (chunk_name == png_sBIT) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (chunk_name == png_sRGB) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (chunk_name == png_iCCP) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (chunk_name == png_sPLT) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (chunk_name == png_tEXt) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (chunk_name == png_tIME) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (chunk_name == png_tRNS) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (chunk_name == png_zTXt) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (chunk_name == png_iTXt) + 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; + + png_read_start_row(png_ptr); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + png_read_transform_info(png_ptr, info_ptr); +#else + PNG_UNUSED(info_ptr) +#endif +} + +#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) + 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) +{ + int ret; + + png_row_info row_info; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_read_row (row %lu, pass %d)", + (unsigned long)png_ptr->row_number, png_ptr->pass); + + /* png_read_start_row sets the information (in particular iwidth) for this + * interlace pass. + */ + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + + /* 1.5.6: row_info moved out of png_struct to a local here. */ + row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ + row_info.color_type = png_ptr->color_type; + row_info.bit_depth = png_ptr->bit_depth; + row_info.channels = png_ptr->channels; + row_info.pixel_depth = png_ptr->pixel_depth; + row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); + + 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. + * Notice that the pixels we have from previous rows have been transformed + * already; we can only combine like with like (transformed or + * untransformed) and, because of the libpng API for interlaced images, this + * means we must transform before de-interlacing. + */ + 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, 1/*display*/); + 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, 1/*display*/); + + 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, 1/*display*/); + + 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, 1/*display*/); + + 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, 1/*display*/); + + 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, 1/*display*/); + + png_read_finish_row(png_ptr); + return; + } + break; + + default: + 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_ptr->chunk_name != png_IDAT) + 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_benign_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); + + if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) + { + if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) + png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, + png_ptr->prev_row + 1, png_ptr->row_buf[0]); + else + png_error(png_ptr, "bad adaptive filter value"); + } + + /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before + * 1.5.6, while the buffer really is this big in current versions of libpng + * it may not be in the future, so this was changed just to copy the + * interlaced count: + */ + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.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(&row_info, png_ptr->row_buf + 1); + } +#endif + + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) + png_do_read_transformations(png_ptr, &row_info); +#endif + + /* The transformed pixel depth should match the depth now in row_info. */ + if (png_ptr->transformed_pixel_depth == 0) + { + png_ptr->transformed_pixel_depth = row_info.pixel_depth; + if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) + png_error(png_ptr, "sequential row overflow"); + } + + else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) + png_error(png_ptr, "internal sequential row size calculation error"); + +#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) + png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, + png_ptr->transformations); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 1/*display*/); + + if (row != NULL) + png_combine_row(png_ptr, row, 0/*row*/); + } + + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, -1/*ignored*/); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, -1/*ignored*/); + } + 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, NULL); + rp++; + } + + else if (dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, 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 + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + pass = png_set_interlace_handling(png_ptr); + /* And make sure transforms are initialized. */ + png_start_read_image(png_ptr); + } + else + { + if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) + { + /* Caller called png_start_read_image or png_read_update_info without + * first turning on the PNG_INTERLACE transform. We can fix this here, + * but the caller should do it! + */ + png_warning(png_ptr, "Interlace handling should be turned on when " + "using png_read_image"); + /* Make sure this is set correctly */ + png_ptr->num_rows = png_ptr->height; + } + + /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in + * the above error case. + */ + 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; + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, 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 + { + png_uint_32 length = png_read_chunk_header(png_ptr); + png_uint_32 chunk_name = png_ptr->chunk_name; + + if (chunk_name == png_IHDR) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (chunk_name == png_IEND) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_chunk_unknown_handling(png_ptr, chunk_name) != + PNG_HANDLE_CHUNK_AS_DEFAULT) + { + if (chunk_name == png_IDAT) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + } + png_handle_unknown(png_ptr, info_ptr, length); + if (chunk_name == png_PLTE) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + + else if (chunk_name == png_IDAT) + { + /* 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_benign_error(png_ptr, "Too many IDATs found"); + + png_crc_finish(png_ptr, length); + } + else if (chunk_name == png_PLTE) + png_handle_PLTE(png_ptr, info_ptr, length); + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (chunk_name == png_bKGD) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (chunk_name == png_cHRM) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (chunk_name == png_gAMA) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (chunk_name == png_hIST) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (chunk_name == png_oFFs) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (chunk_name == png_pCAL) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (chunk_name == png_sCAL) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (chunk_name == png_pHYs) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (chunk_name == png_sBIT) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (chunk_name == png_sRGB) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (chunk_name == png_iCCP) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (chunk_name == png_sPLT) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (chunk_name == png_tEXt) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (chunk_name == png_tIME) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (chunk_name == png_tRNS) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (chunk_name == png_zTXt) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (chunk_name == png_iTXt) + 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; +#ifdef PNG_WARNINGS_SUPPORTED + png_error_ptr warning_fn; +#endif + 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); + +#ifdef PNG_READ_GAMMA_SUPPORTED + png_destroy_gamma_table(png_ptr); +#endif + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->big_prev_row); + png_free(png_ptr, png_ptr->chunkdata); + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->quantize_index); +#endif + + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; + +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#endif + + inflateEnd(&png_ptr->zstream); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#ifdef PNG_TEXT_SUPPORTED + png_free(png_ptr, png_ptr->current_text); +#endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + + /* 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->longjmp_buffer, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + warning_fn = png_ptr->warning_fn; +#endif + 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; +#ifdef PNG_WARNINGS_SUPPORTED + png_ptr->warning_fn = warning_fn; +#endif + 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->longjmp_buffer, 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 || info_ptr == NULL) + return; + + /* 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_SCALE_16_TO_8_SUPPORTED + /* Tell libpng to strip 16-bit/color files down to 8 bits per color. + */ + if (transforms & PNG_TRANSFORM_SCALE_16) + { + /* Added at libpng-1.5.4. "strip_16" produces the same result that it + * did in earlier versions, while "scale_16" is now more accurate. + */ + png_set_scale_16(png_ptr); + } +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* If both SCALE and STRIP are required pngrtran will effectively cancel the + * latter by doing SCALE first. This is ok and allows apps not to check for + * which is supported to get the right answer. + */ + 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 quantizing. + */ + +#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 + +/* Added at libpng-1.5.4 */ +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (transforms & PNG_TRANSFORM_EXPAND_16) + png_set_expand_16(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* We use png_read_image and rely on that for interlace handling, but we also + * call png_read_update_info therefore must turn on interlace handling now: + */ + (void)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 (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + if (info_ptr->row_pointers == NULL) + { + png_uint_32 iptr; + + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); + for (iptr=0; iptrheight; iptr++) + info_ptr->row_pointers[iptr] = NULL; + + info_ptr->free_me |= PNG_FREE_ROWS; + + 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); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) + +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibPNG/pngrio.c b/plugins/FreeImage/src/LibPNG/pngrio.c new file mode 100644 index 0000000000..d0d9d8a737 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngrio.c @@ -0,0 +1,176 @@ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.5.0 [January 6, 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 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(...). + */ + +#include "pngpriv.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 PNGCBAPI +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. + */ + check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr); + + 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 PNGCBAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t 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) + { + check = fread(n_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, read, io_ptr); + 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, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibPNG/pngrtran.c b/plugins/FreeImage/src/LibPNG/pngrtran.c new file mode 100644 index 0000000000..bbee10ce56 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngrtran.c @@ -0,0 +1,5023 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * Last changed in libpng 1.5.7 [December 15, 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. + */ + +#include "pngpriv.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; + } +} + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS via a background color */ +void PNGFAPI +png_set_background_fixed(png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma) +{ + png_debug(1, "in png_set_background_fixed"); + + 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_COMPOSE | PNG_STRIP_ALPHA; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + png_memcpy(&(png_ptr->background), background_color, + png_sizeof(png_color_16)); + png_ptr->background_gamma = background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + if (need_expand) + png_ptr->transformations |= PNG_BACKGROUND_EXPAND; + else + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_background(png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_set_background_fixed(png_ptr, background_color, background_gamma_code, + need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); +} +# endif /* FLOATING_POINT */ +#endif /* READ_BACKGROUND */ + +/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the + * one that pngrtran does first (scale) happens. This is necessary to allow the + * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. + */ +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +void PNGAPI +png_set_scale_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_scale_16"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SCALE_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +/* Chop 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->transformations |= PNG_STRIP_ALPHA; +} +#endif + +#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) +static png_fixed_point +translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma, + int is_screen) +{ + /* Check for flag values. The main reason for having the old Mac value as a + * flag is that it is pretty near impossible to work out what the correct + * value is from Apple documentation - a working Mac system is needed to + * discover the value! + */ + if (output_gamma == PNG_DEFAULT_sRGB || + output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) + { + /* If there is no sRGB support this just sets the gamma to the standard + * sRGB value. (This is a side effect of using this function!) + */ +# ifdef PNG_READ_sRGB_SUPPORTED + png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; +# endif + if (is_screen) + output_gamma = PNG_GAMMA_sRGB; + else + output_gamma = PNG_GAMMA_sRGB_INVERSE; + } + + else if (output_gamma == PNG_GAMMA_MAC_18 || + output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) + { + if (is_screen) + output_gamma = PNG_GAMMA_MAC_OLD; + else + output_gamma = PNG_GAMMA_MAC_INVERSE; + } + + return output_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +static png_fixed_point +convert_gamma_value(png_structp png_ptr, double output_gamma) +{ + /* The following silently ignores cases where fixed point (times 100,000) + * gamma values are passed to the floating point API. This is safe and it + * means the fixed point constants work just fine with the floating point + * API. The alternative would just lead to undetected errors and spurious + * bug reports. Negative values fail inside the _fixed API unless they + * correspond to the flag values. + */ + if (output_gamma > 0 && output_gamma < 128) + output_gamma *= PNG_FP_1; + + /* This preserves -1 and -2 exactly: */ + output_gamma = floor(output_gamma + .5); + + if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) + png_fixed_error(png_ptr, "gamma value"); + + return (png_fixed_point)output_gamma; +} +# endif +#endif /* READ_ALPHA_MODE || READ_GAMMA */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +void PNGFAPI +png_set_alpha_mode_fixed(png_structp png_ptr, int mode, + png_fixed_point output_gamma) +{ + int compose = 0; + png_fixed_point file_gamma; + + png_debug(1, "in png_set_alpha_mode"); + + if (png_ptr == NULL) + return; + + output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); + + /* Validate the value to ensure it is in a reasonable range. The value + * is expected to be 1 or greater, but this range test allows for some + * viewing correction values. The intent is to weed out users of this API + * who use the inverse of the gamma value accidentally! Since some of these + * values are reasonable this may have to be changed. + */ + if (output_gamma < 70000 || output_gamma > 300000) + png_error(png_ptr, "output gamma out of expected range"); + + /* The default file gamma is the inverse of the output gamma; the output + * gamma may be changed below so get the file value first: + */ + file_gamma = png_reciprocal(output_gamma); + + /* There are really 8 possibilities here, composed of any combination + * of: + * + * premultiply the color channels + * do not encode non-opaque pixels + * encode the alpha as well as the color channels + * + * The differences disappear if the input/output ('screen') gamma is 1.0, + * because then the encoding is a no-op and there is only the choice of + * premultiplying the color channels or not. + * + * png_set_alpha_mode and png_set_background interact because both use + * png_compose to do the work. Calling both is only useful when + * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along + * with a default gamma value. Otherwise PNG_COMPOSE must not be set. + */ + switch (mode) + { + case PNG_ALPHA_PNG: /* default: png standard */ + /* No compose, but it may be set by png_set_background! */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + /* The output is linear: */ + output_gamma = PNG_FP_1; + break; + + case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; + /* output_gamma records the encoding of opaque pixels! */ + break; + + case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ + compose = 1; + png_ptr->transformations |= PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + default: + png_error(png_ptr, "invalid alpha mode"); + } + + /* Only set the default gamma if the file gamma has not been set (this has + * the side effect that the gamma in a second call to png_set_alpha_mode will + * be ignored.) + */ + if (png_ptr->gamma == 0) + png_ptr->gamma = file_gamma; + + /* But always set the output gamma: */ + png_ptr->screen_gamma = output_gamma; + + /* Finally, if pre-multiplying, set the background fields to achieve the + * desired result. + */ + if (compose) + { + /* And obtain alpha pre-multiplication by composing on black: */ + png_memset(&png_ptr->background, 0, sizeof png_ptr->background); + png_ptr->background_gamma = png_ptr->gamma; /* just in case */ + png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; + + if (png_ptr->transformations & PNG_COMPOSE) + png_error(png_ptr, + "conflicting calls to set alpha mode and background"); + + png_ptr->transformations |= PNG_COMPOSE; + } + + /* New API, make sure apps call the correct initializers: */ + png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma) +{ + png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, + output_gamma)); +} +# endif +#endif + +#ifdef PNG_READ_QUANTIZE_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_quantize" indicates + * whether we need a quantizing 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_quantize(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize) +{ + png_debug(1, "in png_set_quantize"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_QUANTIZE; + + if (!full_quantize) + { + int i; + + png_ptr->quantize_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->quantize_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->quantize_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the quantize_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->quantize_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->quantize_sort[j]] + < histogram[png_ptr->quantize_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->quantize_sort[j]; + png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; + png_ptr->quantize_sort[j + 1] = t; + done = 0; + } + } + + if (done) + break; + } + + /* Swap the palette around, and set up a table, if necessary */ + if (full_quantize) + { + 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->quantize_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->quantize_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->quantize_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* Indicate where the color went */ + png_ptr->quantize_index[j] = (png_byte)i; + png_ptr->quantize_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->quantize_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->quantize_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->quantize_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->quantize_sort); + png_ptr->quantize_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_quantize) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->quantize_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[next_j]; + + if ((int)png_ptr->quantize_index[k] == + num_new_palette) + png_ptr->quantize_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_quantize) + { + int i; + png_bytep distance; + int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + + PNG_QUANTIZE_BLUE_BITS; + int num_red = (1 << PNG_QUANTIZE_RED_BITS); + int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); + int num_blue = (1 << PNG_QUANTIZE_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_QUANTIZE_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_QUANTIZE_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_QUANTIZE_BLUE_BITS + + PNG_QUANTIZE_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_QUANTIZE_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 /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +void PNGFAPI +png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, + png_fixed_point file_gamma) +{ + png_debug(1, "in png_set_gamma_fixed"); + + if (png_ptr == NULL) + return; + + /* New in libpng-1.5.4 - reserve particular negative values as flags. */ + scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); + file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); + +#if PNG_LIBPNG_VER >= 10600 + /* Checking the gamma values for being >0 was added in 1.5.4 along with the + * premultiplied alpha support; this actually hides an undocumented feature + * of the previous implementation which allowed gamma processing to be + * disabled in background handling. There is no evidence (so far) that this + * was being used; however, png_set_background itself accepted and must still + * accept '0' for the gamma value it takes, because it isn't always used. + * + * Since this is an API change (albeit a very minor one that removes an + * undocumented API feature) it will not be made until libpng-1.6.0. + */ + if (file_gamma <= 0) + png_error(png_ptr, "invalid file gamma in png_set_gamma"); + + if (scrn_gamma <= 0) + png_error(png_ptr, "invalid screen gamma in png_set_gamma"); +#endif + + /* Set the gamma values unconditionally - this overrides the value in the PNG + * file if a gAMA chunk was present. png_set_alpha_mode provides a + * different, easier, way to default the file gamma. + */ + png_ptr->gamma = file_gamma; + png_ptr->screen_gamma = scrn_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) +{ + png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), + convert_gamma_value(png_ptr, file_gamma)); +} +# endif /* FLOATING_POINT_SUPPORTED */ +#endif /* READ_GAMMA */ + +#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; +} + +/* 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; +} + + + +/* 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_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise + * it may not work correctly.) + */ +void PNGAPI +png_set_expand_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_16"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; + + /* New API, make sure apps call the correct initializers: */ + png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; +} +#endif + +#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"); + + if (png_ptr != NULL) + { + /* Because rgb must be 8 bits or more: */ + png_set_expand_gray_1_2_4_to_8(png_ptr); + png_ptr->transformations |= PNG_GRAY_TO_RGB; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +void PNGFAPI +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 PNG_ERROR_ACTION_NONE: + png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + + case PNG_ERROR_ACTION_WARN: + png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + + case PNG_ERROR_ACTION_ERROR: + png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + break; + + default: + png_error(png_ptr, "invalid error action to rgb_to_gray"); + break; + } + 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 + { + if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) + { + png_uint_16 red_int, green_int; + + /* NOTE: this calculation does not round, but this behavior is retained + * for consistency, the inaccuracy is very small. The code here always + * overwrites the coefficients, regardless of whether they have been + * defaulted or set already. + */ + red_int = (png_uint_16)(((png_uint_32)red*32768)/100000); + green_int = (png_uint_16)(((png_uint_32)green*32768)/100000); + + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_coefficients_set = 1; + } + + else + { + if (red >= 0 && green >= 0) + png_warning(png_ptr, + "ignoring out of range rgb_to_gray coefficients"); + + /* Use the defaults, from the cHRM chunk if set, else the historical + * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See + * png_do_rgb_to_gray for more discussion of the values. In this case + * the coefficients are not marked as 'set' and are not overwritten if + * something has already provided a default. + */ + if (png_ptr->rgb_to_gray_red_coeff == 0 && + png_ptr->rgb_to_gray_green_coeff == 0) + { + png_ptr->rgb_to_gray_red_coeff = 6968; + png_ptr->rgb_to_gray_green_coeff = 23434; + /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ + } + } + } +} + +#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) +{ + if (png_ptr == NULL) + return; + + png_set_rgb_to_gray_fixed(png_ptr, error_action, + png_fixed(png_ptr, red, "rgb to gray red coefficient"), + png_fixed(png_ptr, green, "rgb to gray green coefficient")); +} +#endif /* FLOATING POINT */ + +#endif + +#if defined(PNG_READ_USER_TRANSFORM_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 +} +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +/* In the case of gamma transformations 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. + */ +static int /* PRIVATE */ +png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) +{ + /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma + * correction as a difference of the overall transform from 1.0 + * + * We want to compare the threshold with s*f - 1, if we get + * overflow here it is because of wacky gamma values so we + * turn on processing anyway. + */ + png_fixed_point gtest; + return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || + png_gamma_significant(gtest); +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ + +/*For the moment 'png_init_palette_transformations' and + * 'png_init_rgb_transformations' only do some flag canceling optimizations. + * The intent is that these two routines should have palette or rgb operations + * extracted from 'png_init_read_transformations'. + */ +static void /* PRIVATE */ +png_init_palette_transformations(png_structp png_ptr) +{ + /* Called to handle the (input) palette case. In png_do_read_transformations + * the first step is to expand the palette if requested, so this code must + * take care to only make changes that are invariant with respect to the + * palette expansion, or only do them if there is no expansion. + * + * STRIP_ALPHA has already been handled in the caller (by setting num_trans + * to 0.) + */ + int input_has_alpha = 0; + int input_has_transparency = 0; + + if (png_ptr->num_trans > 0) + { + int i; + + /* Ignore if all the entries are opaque (unlikely!) */ + for (i=0; inum_trans; ++i) + if (png_ptr->trans_alpha[i] == 255) + continue; + else if (png_ptr->trans_alpha[i] == 0) + input_has_transparency = 1; + else + input_has_alpha = 1; + } + + /* If no alpha we can optimize. */ + if (!input_has_alpha) + { + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + if (!input_has_transparency) + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); + } + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + /* png_set_background handling - deals with the complexity of whether the + * background color is in the file format or the screen format in the case + * where an 'expand' will happen. + */ + + /* The following code cannot be entered in the alpha pre-multiplication case + * because PNG_BACKGROUND_EXPAND is cancelled below. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + { + 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) + { + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop = png_ptr->num_trans; + + for (i=0; itrans_alpha[i] = (png_byte)(255 - + png_ptr->trans_alpha[i]); + } + } +#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ + } + } /* background expand and (therefore) no alpha association. */ +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ +} + +static void /* PRIVATE */ +png_init_rgb_transformations(png_structp png_ptr) +{ + /* Added to libpng-1.5.4: check the color type to determine whether there + * is any alpha or transparency in the image and simply cancel the + * background and alpha mode stuff if there isn't. + */ + int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; + int input_has_transparency = png_ptr->num_trans > 0; + + /* If no alpha we can optimize. */ + if (!input_has_alpha) + { + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; +# endif + + if (!input_has_transparency) + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); + } + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + /* png_set_background handling - deals with the complexity of whether the + * background color is in the file format or the screen format in the case + * where an 'expand' will happen. + */ + + /* The following code cannot be entered in the alpha pre-multiplication case + * because PNG_BACKGROUND_EXPAND is cancelled below. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND) && + !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + /* i.e., GRAY or GRAY_ALPHA */ + { + { + /* Expand background and tRNS chunks */ + int gray = png_ptr->background.gray; + int trans_gray = png_ptr->trans_color.gray; + + switch (png_ptr->bit_depth) + { + case 1: + gray *= 0xff; + trans_gray *= 0xff; + break; + + case 2: + gray *= 0x55; + trans_gray *= 0x55; + break; + + case 4: + gray *= 0x11; + trans_gray *= 0x11; + break; + + default: + + case 8: + /* Already 8 bits, fall through */ + + case 16: + /* Already a full 16 bits */ + break; + } + + png_ptr->background.red = png_ptr->background.green = + png_ptr->background.blue = (png_uint_16)gray; + + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.red = png_ptr->trans_color.green = + png_ptr->trans_color.blue = (png_uint_16)trans_gray; + } + } + } /* background expand and (therefore) no alpha association. */ +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ +} + +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); + + /* This internal function is called from png_read_start_row in pngrutil.c + * and it is called before the 'rowbytes' calculation is done, so the code + * in here can change or update the transformations flags. + * + * First do updates that do not depend on the details of the PNG image data + * being processed. + */ + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds + * png_set_alpha_mode and this is another source for a default file gamma so + * the test needs to be performed later - here. In addition prior to 1.5.4 + * the tests were repeated for the PALETTE color type here - this is no + * longer necessary (and doesn't seem to have been necessary before.) + */ + { + /* The following temporary indicates if overall gamma correction is + * required. + */ + int gamma_correction = 0; + + if (png_ptr->gamma != 0) /* has been set */ + { + if (png_ptr->screen_gamma != 0) /* screen set too */ + gamma_correction = png_gamma_threshold(png_ptr->gamma, + png_ptr->screen_gamma); + + else + /* Assume the output matches the input; a long time default behavior + * of libpng, although the standard has nothing to say about this. + */ + png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma); + } + + else if (png_ptr->screen_gamma != 0) + /* The converse - assume the file matches the screen, note that this + * perhaps undesireable default can (from 1.5.4) be changed by calling + * png_set_alpha_mode (even if the alpha handling mode isn't required + * or isn't changed from the default.) + */ + png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma); + + else /* neither are set */ + /* Just in case the following prevents any processing - file and screen + * are both assumed to be linear and there is no way to introduce a + * third gamma value other than png_set_background with 'UNIQUE', and, + * prior to 1.5.4 + */ + png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1; + + /* Now turn the gamma transformation on or off as appropriate. Notice + * that PNG_GAMMA just refers to the file->screen correction. Alpha + * composition may independently cause gamma correction because it needs + * linear data (e.g. if the file has a gAMA chunk but the screen gamma + * hasn't been specified.) In any case this flag may get turned off in + * the code immediately below if the transform can be handled outside the + * row loop. + */ + if (gamma_correction) + png_ptr->transformations |= PNG_GAMMA; + + else + png_ptr->transformations &= ~PNG_GAMMA; + } +#endif + + /* Certain transformations have the effect of preventing other + * transformations that happen afterward in png_do_read_transformations, + * resolve the interdependencies here. From the code of + * png_do_read_transformations the order is: + * + * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) + * 2) PNG_STRIP_ALPHA (if no compose) + * 3) PNG_RGB_TO_GRAY + * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY + * 5) PNG_COMPOSE + * 6) PNG_GAMMA + * 7) PNG_STRIP_ALPHA (if compose) + * 8) PNG_ENCODE_ALPHA + * 9) PNG_SCALE_16_TO_8 + * 10) PNG_16_TO_8 + * 11) PNG_QUANTIZE (converts to palette) + * 12) PNG_EXPAND_16 + * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY + * 14) PNG_INVERT_MONO + * 15) PNG_SHIFT + * 16) PNG_PACK + * 17) PNG_BGR + * 18) PNG_PACKSWAP + * 19) PNG_FILLER (includes PNG_ADD_ALPHA) + * 20) PNG_INVERT_ALPHA + * 21) PNG_SWAP_ALPHA + * 22) PNG_SWAP_BYTES + * 23) PNG_USER_TRANSFORM [must be last] + */ +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + !(png_ptr->transformations & PNG_COMPOSE)) + { + /* Stripping the alpha channel happens immediately after the 'expand' + * transformations, before all other transformation, so it cancels out + * the alpha handling. It has the side effect negating the effect of + * PNG_EXPAND_tRNS too: + */ + png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | + PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen + * so transparency information would remain just so long as it wasn't + * expanded. This produces unexpected API changes if the set of things + * that do PNG_EXPAND_tRNS changes (perfectly possible given the + * documentation - which says ask for what you want, accept what you + * get.) This makes the behavior consistent from 1.5.4: + */ + png_ptr->num_trans = 0; + } +#endif /* STRIP_ALPHA supported, no COMPOSE */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA + * settings will have no effect. + */ + if (!png_gamma_significant(png_ptr->screen_gamma)) + { + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + } +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) && \ + defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(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. + * + * TODO: this code needs to be revised to avoid the complexity and + * interdependencies. The color type of the background should be recorded in + * png_set_background, along with the bit depth, then the code has a record + * of exactly what color space the background is currently in. + */ + if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) + { + /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if + * the file was grayscale the background value is gray. + */ + if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } + + else if (png_ptr->transformations & PNG_COMPOSE) + { + /* PNG_COMPOSE: png_set_background was called with need_expand false, + * so the color is in the color space of the output or png_set_alpha_mode + * was called and the color is black. Ignore RGB_TO_GRAY because that + * happens before GRAY_TO_RGB. + */ + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if (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 /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */ + + /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations + * can be performed directly on the palette, and some (such as rgb to gray) + * can be optimized inside the palette. This is particularly true of the + * composite (background and alpha) stuff, which can be pretty much all done + * in the palette even if the result is expanded to RGB or gray afterward. + * + * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and + * earlier and the palette stuff is actually handled on the first row. This + * leads to the reported bug that the palette returned by png_get_PLTE is not + * updated. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_init_palette_transformations(png_ptr); + + else + png_init_rgb_transformations(png_ptr); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_EXPAND_16_SUPPORTED) + if ((png_ptr->transformations & PNG_EXPAND_16) && + (png_ptr->transformations & PNG_COMPOSE) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + png_ptr->bit_depth != 16) + { + /* TODO: fix this. Because the expand_16 operation is after the compose + * handling the background color must be 8, not 16, bits deep, but the + * application will supply a 16-bit value so reduce it here. + * + * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at + * present, so that case is ok (until do_expand_16 is moved.) + * + * NOTE: this discards the low 16 bits of the user supplied background + * color, but until expand_16 works properly there is no choice! + */ +# define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16)) + CHOP(png_ptr->background.red); + CHOP(png_ptr->background.green); + CHOP(png_ptr->background.blue); + CHOP(png_ptr->background.gray); +# undef CHOP + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ + defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) + if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) && + (png_ptr->transformations & PNG_COMPOSE) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + png_ptr->bit_depth == 16) + { + /* On the other hand, if a 16-bit file is to be reduced to 8-bits per + * component this will also happen after PNG_COMPOSE and so the background + * color must be pre-expanded here. + * + * TODO: fix this too. + */ + png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257); + png_ptr->background.green = + (png_uint_16)(png_ptr->background.green * 257); + png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257); + png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257); + } +#endif + + /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the + * background support (see the comments in scripts/pnglibconf.dfa), this + * allows pre-multiplication of the alpha channel to be implemented as + * compositing on black. This is probably sub-optimal and has been done in + * 1.5.4 betas simply to enable external critique and testing (i.e. to + * implement the new API quickly, without lots of internal changes.) + */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +# ifdef PNG_READ_BACKGROUND_SUPPORTED + /* Includes ALPHA_MODE */ + png_ptr->background_1 = png_ptr->background; +# endif + + /* This needs to change - in the palette image case a whole set of tables are + * built when it would be quicker to just calculate the correct value for + * each palette entry directly. Also, the test is too tricky - why check + * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that + * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the + * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction + * the gamma tables will not be built even if composition is required on a + * gamma encoded value. + * + * In 1.5.4 this is addressed below by an additional check on the individual + * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the + * tables. + */ + if ((png_ptr->transformations & PNG_GAMMA) + || ((png_ptr->transformations & PNG_RGB_TO_GRAY) + && (png_gamma_significant(png_ptr->gamma) || + png_gamma_significant(png_ptr->screen_gamma))) + || ((png_ptr->transformations & PNG_COMPOSE) + && (png_gamma_significant(png_ptr->gamma) + || png_gamma_significant(png_ptr->screen_gamma) +# ifdef PNG_READ_BACKGROUND_SUPPORTED + || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE + && png_gamma_significant(png_ptr->background_gamma)) +# endif + )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) + && png_gamma_significant(png_ptr->screen_gamma)) + ) + { + png_build_gamma_table(png_ptr, png_ptr->bit_depth); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_COMPOSE) + { + /* Issue a warning about this combination: because RGB_TO_GRAY is + * optimized to do the gamma transform if present yet do_background has + * to do the same thing if both options are set a + * double-gamma-correction happens. This is true in all versions of + * libpng to date. + */ + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + png_warning(png_ptr, + "libpng does not support gamma+background+rgb_to_gray"); + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + /* We don't get to here unless there is a tRNS chunk with non-opaque + * entries - see the checking code at the start of this function. + */ + 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 + { + png_fixed_point g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = PNG_FP_1; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->gamma); + gs = png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + default: + g = PNG_FP_1; /* back_1 */ + gs = PNG_FP_1; /* back */ + break; + } + + if (png_gamma_significant(gs)) + { + back.red = png_gamma_8bit_correct(png_ptr->background.red, + gs); + back.green = png_gamma_8bit_correct(png_ptr->background.green, + gs); + back.blue = png_gamma_8bit_correct(png_ptr->background.blue, + gs); + } + + else + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + + if (png_gamma_significant(g)) + { + back_1.red = png_gamma_8bit_correct(png_ptr->background.red, + g); + back_1.green = png_gamma_8bit_correct( + png_ptr->background.green, g); + back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, + g); + } + + else + { + back_1.red = (png_byte)png_ptr->background.red; + back_1.green = (png_byte)png_ptr->background.green; + back_1.blue = (png_byte)png_ptr->background.blue; + } + } + + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && + png_ptr->trans_alpha[i] != 0xff) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans_alpha[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans_alpha[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_alpha[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_alpha[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. + * + * NOTE: this is highly dubious; it removes the transformations in + * place. This seems inconsistent with the general treatment of the + * transformations elsewhere. + */ + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); + } /* color_type == PNG_COLOR_TYPE_PALETTE */ + + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + int gs_sig, g_sig; + png_fixed_point g = PNG_FP_1; /* Correction to linear */ + png_fixed_point gs = PNG_FP_1; /* Correction to screen */ + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = png_ptr->screen_gamma; + /* gs = PNG_FP_1; */ + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->gamma); + gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + + default: + png_error(png_ptr, "invalid background gamma type"); + } + + g_sig = png_gamma_significant(g); + gs_sig = png_gamma_significant(gs); + + if (g_sig) + png_ptr->background_1.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, g); + + if (gs_sig) + png_ptr->background.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, gs); + + 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 */ + if (g_sig) + { + png_ptr->background_1.red = png_gamma_correct(png_ptr, + png_ptr->background.red, g); + + png_ptr->background_1.green = png_gamma_correct(png_ptr, + png_ptr->background.green, g); + + png_ptr->background_1.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, g); + } + + if (gs_sig) + { + png_ptr->background.red = png_gamma_correct(png_ptr, + png_ptr->background.red, gs); + + png_ptr->background.green = png_gamma_correct(png_ptr, + png_ptr->background.green, gs); + + png_ptr->background.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, gs); + } + } + + 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; + } + + /* The background is now in screen gamma: */ + png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN; + } /* color_type != PNG_COLOR_TYPE_PALETTE */ + }/* png_ptr->transformations & PNG_BACKGROUND */ + + else + /* Transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* RGB_TO_GRAY needs to have non-gamma-corrected values! */ + && ((png_ptr->transformations & PNG_EXPAND) == 0 || + (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) +#endif + ) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + /*NOTE: there are other transformations that should probably be in here + * too. + */ + 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; + } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED */ + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + /* No GAMMA transformation (see the hanging else 4 lines above) */ + if ((png_ptr->transformations & PNG_COMPOSE) && + (png_ptr->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_alpha[i] == 0) + { + palette[i] = back; + } + + else if (png_ptr->trans_alpha[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans_alpha[i], back.red); + + png_composite(palette[i].green, palette[i].green, + png_ptr->trans_alpha[i], back.green); + + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans_alpha[i], back.blue); + } + } + + png_ptr->transformations &= ~PNG_COMPOSE; + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#ifdef PNG_READ_SHIFT_SUPPORTED + if ((png_ptr->transformations & PNG_SHIFT) && + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = png_ptr->num_palette; + int shift = 8 - png_ptr->sig_bit.red; + + /* significant bits can be in the range 1 to 7 for a meaninful result, if + * the number of significant bits is 0 then no shift is done (this is an + * error condition which is silently ignored.) + */ + if (shift > 0 && shift < 8) for (i=0; ipalette[i].red; + + component >>= shift; + png_ptr->palette[i].red = (png_byte)component; + } + + shift = 8 - png_ptr->sig_bit.green; + if (shift > 0 && shift < 8) for (i=0; ipalette[i].green; + + component >>= shift; + png_ptr->palette[i].green = (png_byte)component; + } + + shift = 8 - png_ptr->sig_bit.blue; + if (shift > 0 && shift < 8) for (i=0; ipalette[i].blue; + + component >>= shift; + png_ptr->palette[i].blue = (png_byte)component; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ +} + +/* 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) + { + /* This check must match what actually happens in + * png_do_expand_palette; if it ever checks the tRNS chunk to see if + * it is all opaque we must do the same (at present it does not.) + */ + if (png_ptr->num_trans > 0) + 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 + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + /* The following is almost certainly wrong unless the background value is in + * the screen space! + */ + if (png_ptr->transformations & PNG_COMPOSE) + info_ptr->background = png_ptr->background; +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), + * however it seems that the code in png_init_read_transformations, which has + * been called before this from png_read_update_info->png_read_start_row + * sometimes does the gamma transform and cancels the flag. + */ + info_ptr->gamma = png_ptr->gamma; +#endif + + if (info_ptr->bit_depth == 16) + { +# ifdef PNG_READ_16BIT_SUPPORTED +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# else + /* No 16 bit support: force chopping 16-bit input down to 8, in this case + * the app program can chose if both APIs are available by setting the + * correct scaling to use. + */ +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* For compatibility with previous versions use the strip method by + * default. This code works because if PNG_SCALE_16_TO_8 is already + * set the code below will do that in preference to the chop. + */ + png_ptr->transformations |= PNG_16_TO_8; + info_ptr->bit_depth = 8; +# else + +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_ptr->transformations |= PNG_SCALE_16_TO_8; + info_ptr->bit_depth = 8; +# else + + CONFIGURATION ERROR: you must enable at least one 16 to 8 method +# endif +# endif +#endif /* !READ_16BIT_SUPPORTED */ + } + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type = (png_byte)(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_byte)(info_ptr->color_type & + ~PNG_COLOR_MASK_COLOR); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + 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_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 && + info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + info_ptr->bit_depth = 16; + } +#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->transformations & PNG_STRIP_ALPHA) + { + info_ptr->color_type = (png_byte)(info_ptr->color_type & + ~PNG_COLOR_MASK_ALPHA); + info_ptr->num_trans = 0; + } +#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 */ + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } +#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); + + /* Adding in 1.5.4: cache the above value in png_struct so that we can later + * check in png_rowbytes that the user buffer won't get overwritten. Note + * that the field is not always set - if png_read_update_info isn't called + * the application has to either not do any transforms or get the calculation + * right itself. + */ + png_ptr->info_rowbytes = info_ptr->rowbytes; + +#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_row_infop row_info) +{ + png_debug(1, "in png_do_read_transformations"); + + if (png_ptr->row_buf == NULL) + { + /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this + * error is incredibly rare and incredibly easy to debug without this + * information. + */ + png_error(png_ptr, "NULL row buffer"); + } + + /* The following is debugging; prior to 1.5.4 the code was never compiled in; + * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro + * PNG_WARN_UNINITIALIZED_ROW removed. In 1.5 the new flag is set only for + * selected new APIs to ensure that there is no API change. + */ + if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && + !(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 (but not enabled until 1.5.4). + */ + png_error(png_ptr, "Uninitialized row"); + } + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(row_info, png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); + } + + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(row_info, png_ptr->row_buf + 1, + &(png_ptr->trans_color)); + + else + png_do_expand(row_info, png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + !(png_ptr->transformations & PNG_COMPOSE) && + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(row_info, png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); +#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, 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(row_info, png_ptr->row_buf + 1); +#endif + +#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ + (defined PNG_READ_ALPHA_MODE_SUPPORTED) + if (png_ptr->transformations & PNG_COMPOSE) + png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if ((png_ptr->transformations & PNG_GAMMA) && +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Because RGB_TO_GRAY does the gamma transform. */ + !(png_ptr->transformations & PNG_RGB_TO_GRAY) && +#endif +#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ + (defined PNG_READ_ALPHA_MODE_SUPPORTED) + /* Because PNG_COMPOSE does the gamma transform if there is something to + * do (if there is an alpha channel or transparency.) + */ + !((png_ptr->transformations & PNG_COMPOSE) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + /* Because png_init_read_transformations transforms the palette, unless + * RGB_TO_GRAY will do the transform. + */ + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + (png_ptr->transformations & PNG_COMPOSE) && + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA || + row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(row_info, png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + if ((png_ptr->transformations & PNG_ENCODE_ALPHA) && + (row_info->color_type & PNG_COLOR_MASK_ALPHA)) + png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* There is no harm in doing both of these because only one has any effect, + * by putting the 'scale' option first if the app asks for scale (either by + * calling the API or in a TRANSFORM flag) this is what happens. + */ + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + png_do_quantize(row_info, png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->quantize_index); + + if (row_info->rowbytes == 0) + png_error(png_ptr, "png_do_quantize returned rowbytes=0"); + } +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED + /* Do the expansion now, after all the arithmetic has been done. Notice + * that previous transformations can handle the PNG_EXPAND_16 flag if this + * is efficient (particularly true in the case of gamma correction, where + * better accuracy results faster!) + */ + if (png_ptr->transformations & PNG_EXPAND_16) + png_do_expand_16(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /*NOTE: moved here in 1.5.4 (from much later in this list.) */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(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(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(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(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(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_16BIT_SUPPORTED +#ifdef PNG_READ_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(row_info, png_ptr->row_buf + 1); +#endif +#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 */ + row_info, /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t 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) + row_info->bit_depth = png_ptr->user_transform_depth; + + if (png_ptr->user_transform_channels) + row_info->channels = png_ptr->user_transform_channels; +#endif + row_info->pixel_depth = (png_byte)(row_info->bit_depth * + row_info->channels); + + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 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"); + + if (row_info->bit_depth < 8) + { + 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; + } + + default: + 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_const_color_8p sig_bits) +{ + int color_type; + + png_debug(1, "in png_do_unshift"); + + /* The palette case has already been handled in the _init routine. */ + color_type = row_info->color_type; + + if (color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int bit_depth = row_info->bit_depth; + + if (color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = bit_depth - sig_bits->red; + shift[channels++] = bit_depth - sig_bits->green; + shift[channels++] = bit_depth - sig_bits->blue; + } + + else + { + shift[channels++] = bit_depth - sig_bits->gray; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = bit_depth - sig_bits->alpha; + } + + { + int c, have_shift; + + for (c = have_shift = 0; c < channels; ++c) + { + /* A shift of more than the bit depth is an error condition but it + * gets ignored here. + */ + if (shift[c] <= 0 || shift[c] >= bit_depth) + shift[c] = 0; + + else + have_shift = 1; + } + + if (!have_shift) + return; + } + + switch (bit_depth) + { + default: + /* Must be 1bpp gray: should not be here! */ + /* NOTREACHED */ + break; + + case 2: + /* Must be 2bpp gray */ + /* assert(channels == 1 && shift[0] == 1) */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + + while (bp < bp_end) + { + int b = (*bp >> 1) & 0x55; + *bp++ = (png_byte)b; + } + break; + } + + case 4: + /* Must be 4bpp gray */ + /* assert(channels == 1) */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + int gray_shift = shift[0]; + int mask = 0xf >> gray_shift; + + mask |= mask << 4; + + while (bp < bp_end) + { + int b = (*bp >> gray_shift) & mask; + *bp++ = (png_byte)b; + } + break; + } + + case 8: + /* Single byte components, G, GA, RGB, RGBA */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + int channel = 0; + + while (bp < bp_end) + { + int b = *bp >> shift[channel]; + if (++channel >= channels) + channel = 0; + *bp++ = (png_byte)b; + } + break; + } + +#ifdef PNG_READ_16BIT_SUPPORTED + case 16: + /* Double byte components, G, GA, RGB, RGBA */ + { + png_bytep bp = row; + png_bytep bp_end = bp + row_info->rowbytes; + int channel = 0; + + while (bp < bp_end) + { + int value = (bp[0] << 8) + bp[1]; + + value >>= shift[channel]; + if (++channel >= channels) + channel = 0; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale rows of bit depth 16 down to 8 accurately */ +void /* PRIVATE */ +png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_scale_16_to_8"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destination */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + + while (sp < ep) + { + /* The input is an array of 16 bit components, these must be scaled to + * 8 bits each. For a 16 bit value V the required value (from the PNG + * specification) is: + * + * (V * 255) / 65535 + * + * This reduces to round(V / 257), or floor((V + 128.5)/257) + * + * Represent V as the two byte value vhi.vlo. Make a guess that the + * result is the top byte of V, vhi, then the correction to this value + * is: + * + * error = floor(((V-vhi.vhi) + 128.5) / 257) + * = floor(((vlo-vhi) + 128.5) / 257) + * + * This can be approximated using integer arithmetic (and a signed + * shift): + * + * error = (vlo-vhi+128) >> 8; + * + * The approximate differs from the exact answer only when (vlo-vhi) is + * 128; it then gives a correction of +1 when the exact correction is + * 0. This gives 128 errors. The exact answer (correct for all 16 bit + * input values) is: + * + * error = (vlo-vhi+128)*65535 >> 24; + * + * An alternative arithmetic calculation which also gives no errors is: + * + * (V * 255 + 32895) >> 16 + */ + + png_int_32 tmp = *sp++; /* must be signed! */ + tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; + *dp++ = (png_byte)tmp; + } + + 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_STRIP_16_TO_8_SUPPORTED +void /* PRIVATE */ +/* Simply discard the low byte. This was the default behavior prior + * to libpng-1.5.4. + */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destination */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + + while (sp < ep) + { + *dp++ = *sp; + sp += 2; /* skip low byte */ + } + + 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"); + + { + 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; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* 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]; + } + } +#endif + } + + 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; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* 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 + } + } +} +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_uint_32 row_width; + png_debug(1, "in png_do_read_invert_alpha"); + + row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + 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; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* 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; + } + } +#endif + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + 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); + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + 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 + } +} +#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; + +#ifdef PNG_READ_16BIT_SUPPORTED + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); +#endif + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler"); + + if ( + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from G to GX */ + 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; + } + + else + { + /* This changes the data from G to XG */ + 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; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from GG to GGXX */ + 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; + } + + else + { + /* This changes the data from GG to XXGG */ + 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; + } + } +#endif + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RGB to RGBX */ + 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; + } + + else + { + /* This changes the data from RGB to XRGB */ + 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; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + 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; + } + + else + { + /* This changes the data from RRGGBB to XXRRGGBB */ + 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; + } + } +#endif + } /* 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 && + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + /* This changes G to RGB */ + 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 + { + /* This changes GG to RRGGBB */ + 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) + { + /* This changes GA to RGBA */ + 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 + { + /* This changes GGAA to RRGGBBAA */ + 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)(row_info->channels + 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 of 1998-01-04 at + * (THIS LINK IS DEAD June 2008 but + * versions dated 1998 through November 2002 have been archived at + * http://web.archive.org/web/20000816232553/http://www.inforamp.net/ + * ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) + * Charles Poynton poynton at poynton.com + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * Poynton's current link (as of January 2003 through July 2011): + * + * has changed the numbers slightly: + * + * Y = 0.2126*R + 0.7152*G + 0.0722*B + * + * which can be expressed with integers as + * + * Y = (6966 * R + 23436 * G + 2366 * B)/32768 + * + * Historically, however, libpng uses numbers derived from the ITU-R Rec 709 + * end point chromaticities and the D65 white point. Depending on the + * precision used for the D65 white point this produces a variety of different + * numbers, however if the four decimal place value used in ITU-R Rec 709 is + * used (0.3127,0.3290) the Y calculation would be: + * + * Y = (6968 * R + 23435 * G + 2366 * B)/32768 + * + * While this is correct the rounding results in an overflow for white, because + * the sum of the rounded coefficients is 32769, not 32768. Consequently + * libpng uses, instead, the closest non-overflowing approximation: + * + * Y = (6968 * R + 23434 * G + 2366 * B)/32768 + * + * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk + * (including an sRGB chunk) then the chromaticities are used to calculate the + * coefficients. See the chunk handling in pngrutil.c for more information. + * + * In all cases the calculation is to be done in a linear colorspace. If no + * gamma information is available to correct the encoding of the original RGB + * values this results in an implicit assumption that the original PNG RGB + * values were linear. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). Because + * the API takes just red and green coefficients the blue coefficient is + * calculated to make the sum 32768. This will result in different rounding + * to that used above. + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray"); + + if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + PNG_CONST png_uint_32 bc = 32768 - rc - gc; + PNG_CONST png_uint_32 row_width = row_info->width; + PNG_CONST int have_alpha = + (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; + + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + /* Notice that gamma to/from 1 are not necessarily inverses (if + * there is an overall gamma correction). Prior to 1.5.5 this code + * checked the linearized values for equality; this doesn't match + * the documentation, the original values must be checked. + */ + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + + if (red != green || red != blue) + { + red = png_ptr->gamma_to_1[red]; + green = png_ptr->gamma_to_1[green]; + blue = png_ptr->gamma_to_1[blue]; + + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red + gc*green + bc*blue + 16384)>>15]; + } + + else + { + /* If there is no overall correction the table will not be + * set. + */ + if (png_ptr->gamma_table != NULL) + red = png_ptr->gamma_table[red]; + + *(dp++) = red; + } + + if (have_alpha) + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + 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; + /*NOTE: this is the historical approach which simply + * truncates the results. + */ + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + } + + else + *(dp++) = red; + + if (have_alpha) + *(dp++) = *(sp++); + } + } + } + + 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; + png_uint_32 i; + + 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) + { + if (png_ptr->gamma_16_table != NULL) + w = png_ptr->gamma_16_table[(red&0xff) + >> png_ptr->gamma_shift][red>>8]; + + else + 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 + 16384)>>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); + + if (have_alpha) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + } + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + + 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; + + /* From 1.5.5 in the 16 bit case do the accurate conversion even + * in the 'fast' case - this is because this is where the code + * ends up when handling linear 16 bit data. + */ + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> + 15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + + if (have_alpha) + { + *(dp++) = *(sp++); + *(dp++) = *(sp++); + } + } + } + } + + row_info->channels = (png_byte)(row_info->channels - 2); + row_info->color_type = (png_byte)(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 +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +/* 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. This API is not used internally. + */ +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; + } +} +#endif + + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ + (defined PNG_READ_ALPHA_MODE_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_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr) +{ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; + png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; + png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; + png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; + png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; + int gamma_shift = png_ptr->gamma_shift; +#endif + + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; + int shift; + + png_debug(1, "in png_do_compose"); + + { + 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) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->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) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->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) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->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) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->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) + == png_ptr->trans_color.gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(png_ptr->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 == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; + + else + *sp = gamma_table[*sp]; + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->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 == png_ptr->trans_color.gray) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->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 == png_ptr->trans_color.gray) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + } + } + break; + } + + default: + 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 == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->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 == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->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 == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->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 == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->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; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *sp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.gray; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.gray); + if (!optimize) + w = gamma_from_1[w]; + *sp = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_byte a = *(sp + 1); + + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; + + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background_1.gray); + } + } + } + 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; + for (i = 0; i < row_width; i++, sp += 4) + { + 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]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, png_ptr->background_1.gray); + if (optimize) + w = v; + else + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } + + else if (a < 0xffff) + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, png_ptr->background_1.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + } + 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; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.red); + if (!optimize) w = gamma_from_1[w]; + *sp = w; + + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, png_ptr->background_1.green); + if (!optimize) w = gamma_from_1[w]; + *(sp + 1) = w; + + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, png_ptr->background_1.blue); + if (!optimize) w = gamma_from_1[w]; + *(sp + 2) = w; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) + { + png_byte a = *(sp + 3); + + if (a == 0) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + + else if (a < 0xff) + { + png_composite(*sp, *sp, a, png_ptr->background.red); + + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); + + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->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; + for (i = 0; i < row_width; i++, sp += 8) + { + 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]; + *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 if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v, w; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, png_ptr->background_1.red); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, png_ptr->background_1.green); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, png_ptr->background_1.blue); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else if (a < 0xffff) + { + 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, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + default: + break; + } + } +} +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */ + +#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_structp png_ptr) +{ + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; + int gamma_shift = png_ptr->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 (((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; + } + + default: + break; + } + } +} +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* Encode the alpha channel to the output gamma (the input channel is always + * linear.) Called only with color types that have an alpha channel. Needs the + * from_1 tables. + */ +void /* PRIVATE */ +png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr) +{ + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_encode_alpha"); + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + if (row_info->bit_depth == 8) + { + PNG_CONST png_bytep table = png_ptr->gamma_from_1; + + if (table != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; + + /* The alpha channel is the last component: */ + row += step - 1; + + for (; row_width > 0; --row_width, row += step) + *row = table[*row]; + + return; + } + } + + else if (row_info->bit_depth == 16) + { + PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; + PNG_CONST int gamma_shift = png_ptr->gamma_shift; + + if (table != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; + + /* The alpha channel is the last component: */ + row += step - 2; + + for (; row_width > 0; --row_width, row += step) + { + png_uint_16 v; + + v = table[*(row + 1) >> gamma_shift][*row]; + *row = (png_byte)((v >> 8) & 0xff); + *(row + 1) = (png_byte)(v & 0xff); + } + + return; + } + } + } + + /* Only get to here if called with a weird row_info; no harm has been done, + * so just issue a warning. + */ + png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); +} +#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_const_colorp palette, png_const_bytep trans_alpha, 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 (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; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (row_info->bit_depth == 8) + { + { + if (num_trans > 0) + { + 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_alpha[*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; + } + } + } + } +} + +/* 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_const_color_16p trans_color) +{ + 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"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->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; + } + + default: + break; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_color != 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 = (png_byte)((gray >> 8) & 0xff); + png_byte gray_low = (png_byte)(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_color) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->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 = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->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_EXPAND_16_SUPPORTED +/* If the bit depth is 8 and the color type is not a palette type expand the + * whole row to 16 bits. Has no effect otherwise. + */ +void /* PRIVATE */ +png_do_expand_16(png_row_infop row_info, png_bytep row) +{ + if (row_info->bit_depth == 8 && + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + /* The row have a sequence of bytes containing [0..255] and we need + * to turn it into another row containing [0..65535], to do this we + * calculate: + * + * (input / 255) * 65535 + * + * Which happens to be exactly input * 257 and this can be achieved + * simply by byte replication in place (copying backwards). + */ + png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ + png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ + while (dp > sp) + dp[-2] = dp[-1] = *--sp, dp -= 2; + + row_info->rowbytes *= 2; + row_info->bit_depth = 16; + row_info->pixel_depth = (png_byte)(row_info->channels * 16); + } +} +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +void /* PRIVATE */ +png_do_quantize(png_row_infop row_info, png_bytep row, + png_const_bytep palette_lookup, png_const_bytep quantize_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_quantize"); + + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) + { + 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_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_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) + { + 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_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_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 && + quantize_lookup) + { + sp = row; + + for (i = 0; i < row_width; i++, sp++) + { + *sp = quantize_lookup[*sp]; + } + } + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#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 ( + (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 = (s0 + s1 + 65536) & 0xffff; + png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; + *(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/plugins/FreeImage/src/LibPNG/pngrutil.c b/plugins/FreeImage/src/LibPNG/pngrutil.c new file mode 100644 index 0000000000..995896dbc5 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngrutil.c @@ -0,0 +1,4158 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * Last changed in libpng 1.5.9 [February 18, 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. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +#define png_strtod(p,a,b) strtod(a,b) + +png_uint_32 PNGAPI +png_get_uint_31(png_structp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range"); + + return (uval); +} + +#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) +/* The following is a variation on the above for use with the fixed + * point values used for gAMA and cHRM. Instead of png_error it + * issues a warning and returns (-1) - an invalid value because both + * gAMA and cHRM use *unsigned* integers for fixed point values. + */ +#define PNG_FIXED_ERROR (-1) + +static png_fixed_point /* PRIVATE */ +png_get_fixed_point(png_structp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval <= PNG_UINT_31_MAX) + return (png_fixed_point)uval; /* known to be in range */ + + /* The caller can turn off the warning by passing NULL. */ + if (png_ptr != NULL) + png_warning(png_ptr, "PNG fixed point integer out of range"); + + return PNG_FIXED_ERROR; +} +#endif + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +/* NOTE: the read macros will obscure these definitions, so that if + * PNG_USE_READ_MACROS is set the library will not use them internally, + * but the APIs will still be available externally. + * + * The parentheses around "PNGAPI function_name" in the following three + * functions are necessary because they allow the macros to co-exist with + * these (unused but exported) functions. + */ + +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 (PNGAPI +png_get_uint_32)(png_const_bytep buf) +{ + png_uint_32 uval = + ((png_uint_32)(*(buf )) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + ((png_uint_32)(*(buf + 3)) ) ; + + return uval; +} + +/* 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 there + * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore + * the following code does a two's complement to native conversion. + */ +png_int_32 (PNGAPI +png_get_int_32)(png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + if ((uval & 0x80000000) == 0) /* non-negative */ + return uval; + + uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ + return -(png_int_32)uval; +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 (PNGAPI +png_get_uint_16)(png_const_bytep buf) +{ + /* ANSI-C requires an int value to accomodate at least 16 bits so this + * works and allows the compiler not to worry about possible narrowing + * on 32 bit systems. (Pre-ANSI systems did not make integers smaller + * than 16 bits either.) + */ + unsigned int val = + ((unsigned int)(*buf) << 8) + + ((unsigned int)(*(buf + 1))); + + return (png_uint_16)val; +} + +#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */ + +/* Read and check the PNG file signature */ +void /* PRIVATE */ +png_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked, num_to_check; + + /* Exit if the user application does not expect a signature. */ + if (png_ptr->sig_bytes >= 8) + return; + + num_checked = png_ptr->sig_bytes; + num_to_check = 8 - num_checked; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; +#endif + + /* The signature must be serialized in a single I/O call. */ + 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; +} + +/* 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; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; +#endif + + /* Read the length and the chunk name. + * This must be performed in a single I/O call. + */ + 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_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4); + + png_debug2(0, "Reading %lx chunk, length = %lu", + (unsigned long)png_ptr->chunk_name, (unsigned long)length); + + /* Reset the crc and run it over the chunk name. */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, buf + 4, 4); + + /* Check to see if chunk name is valid. */ + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; +#endif + + 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_CHUNK_ANCILLIARY(png_ptr->chunk_name) ? + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) : + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + + else + { + png_chunk_benign_error(png_ptr, "CRC error"); + return (0); + } + + 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_CHUNK_ANCILLIARY(png_ptr->chunk_name)) + { + 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; + } + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; +#endif + + /* The chunk CRC must be serialized in a single I/O call. */ + 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); +} + +#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED +static png_size_t +png_inflate(png_structp png_ptr, png_bytep data, png_size_t size, + png_bytep output, png_size_t output_size) +{ + png_size_t count = 0; + + /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't + * even necessarily handle 65536 bytes) because the type uInt is "16 bits or + * more". Consequently it is necessary to chunk the input to zlib. This + * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value + * that can be stored in a uInt.) It is possible to set ZLIB_IO_MAX to a + * lower value in pngpriv.h and this may sometimes have a performance + * advantage, because it forces access of the input data to be separated from + * at least some of the use by some period of time. + */ + png_ptr->zstream.next_in = data; + /* avail_in is set below from 'size' */ + png_ptr->zstream.avail_in = 0; + + while (1) + { + int ret, avail; + + /* The setting of 'avail_in' used to be outside the loop; by setting it + * inside it is possible to chunk the input to zlib and simply rely on + * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o + * data to be passed through zlib at the unavoidable cost of requiring a + * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX + * input bytes. + */ + if (png_ptr->zstream.avail_in == 0 && size > 0) + { + if (size <= ZLIB_IO_MAX) + { + /* The value is less than ZLIB_IO_MAX so the cast is safe: */ + png_ptr->zstream.avail_in = (uInt)size; + size = 0; + } + + else + { + png_ptr->zstream.avail_in = ZLIB_IO_MAX; + size -= ZLIB_IO_MAX; + } + } + + /* 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) + { + png_size_t space = avail; /* > 0, see above */ + + if (output != 0 && output_size > count) + { + png_size_t copy = output_size - count; + + if (space < copy) + copy = space; + + png_memcpy(output + count, png_ptr->zbuf, copy); + } + count += space; + } + + 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. + */ +# ifdef PNG_WARNINGS_SUPPORTED + { + png_const_charp msg; + + if (png_ptr->zstream.msg != 0) + msg = png_ptr->zstream.msg; + + else switch (ret) + { + case Z_BUF_ERROR: + msg = "Buffer error in compressed datastream"; + break; + + case Z_DATA_ERROR: + msg = "Data error in compressed datastream"; + break; + + default: + msg = "Incomplete compressed datastream"; + break; + } + + png_chunk_warning(png_ptr, msg); + } +# endif + + /* 0 means an error - notice that this code simply 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_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + || (png_ptr->user_chunk_malloc_max && + (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1)) +#else +# ifdef PNG_USER_CHUNK_MALLOC_MAX + || ((PNG_USER_CHUNK_MALLOC_MAX > 0) && + prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) +# endif +#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_charp)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) */ + { + PNG_WARNING_PARAMETERS(p) + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, comp_type); + png_formatted_warning(png_ptr, p, "Unknown compression type @1"); + + /* 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_charp)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 /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */ + +/* 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) + { + default: /* invalid, png_set_IHDR calls png_error */ + 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", (unsigned long)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_benign_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); + + PNG_UNUSED(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; + 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_get_fixed_point(NULL, buf); + + /* Check for zero gamma or an error. */ + if (igamma <= 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with out of range gamma"); + + return; + } + +# ifdef PNG_READ_sRGB_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(igamma, 45500, 500)) + { + PNG_WARNING_PARAMETERS(p) + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, igamma); + png_formatted_warning(png_ptr, p, + "Ignoring incorrect gAMA value @1 when sRGB is also present"); + return; + } + } +# endif /* PNG_READ_sRGB_SUPPORTED */ + +# ifdef PNG_READ_GAMMA_SUPPORTED + /* Gamma correction on read is supported. */ + png_ptr->gamma = igamma; +# endif + /* And set the 'info' structure members. */ + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +} +#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]; + png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue, + y_blue; + + 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, "Out of place cHRM chunk"); + + 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; + + x_white = png_get_fixed_point(NULL, buf); + y_white = png_get_fixed_point(NULL, buf + 4); + x_red = png_get_fixed_point(NULL, buf + 8); + y_red = png_get_fixed_point(NULL, buf + 12); + x_green = png_get_fixed_point(NULL, buf + 16); + y_green = png_get_fixed_point(NULL, buf + 20); + x_blue = png_get_fixed_point(NULL, buf + 24); + y_blue = png_get_fixed_point(NULL, buf + 28); + + if (x_white == PNG_FIXED_ERROR || + y_white == PNG_FIXED_ERROR || + x_red == PNG_FIXED_ERROR || + y_red == PNG_FIXED_ERROR || + x_green == PNG_FIXED_ERROR || + y_green == PNG_FIXED_ERROR || + x_blue == PNG_FIXED_ERROR || + y_blue == PNG_FIXED_ERROR) + { + png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities"); + return; + } + +#ifdef PNG_READ_sRGB_SUPPORTED + if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(x_red, 64000, 1000) || + PNG_OUT_OF_RANGE(y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(y_green, 60000, 1000) || + PNG_OUT_OF_RANGE(x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(y_blue, 6000, 1000)) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, x_white); + png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_fixed, y_white); + png_warning_parameter_signed(p, 3, PNG_NUMBER_FORMAT_fixed, x_red); + png_warning_parameter_signed(p, 4, PNG_NUMBER_FORMAT_fixed, y_red); + png_warning_parameter_signed(p, 5, PNG_NUMBER_FORMAT_fixed, x_green); + png_warning_parameter_signed(p, 6, PNG_NUMBER_FORMAT_fixed, y_green); + png_warning_parameter_signed(p, 7, PNG_NUMBER_FORMAT_fixed, x_blue); + png_warning_parameter_signed(p, 8, PNG_NUMBER_FORMAT_fixed, y_blue); + + png_formatted_warning(png_ptr, p, + "Ignoring incorrect cHRM white(@1,@2) r(@3,@4)g(@5,@6)b(@7,@8) " + "when sRGB is also present"); + } + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Store the _white values as default coefficients for the rgb to gray + * operation if it is supported. Check if the transform is already set to + * avoid destroying the transform values. + */ + if (!png_ptr->rgb_to_gray_coefficients_set) + { + /* png_set_background has not been called and we haven't seen an sRGB + * chunk yet. Find the XYZ of the three end points. + */ + png_XYZ XYZ; + png_xy xy; + + xy.redx = x_red; + xy.redy = y_red; + xy.greenx = x_green; + xy.greeny = y_green; + xy.bluex = x_blue; + xy.bluey = y_blue; + xy.whitex = x_white; + xy.whitey = y_white; + + if (png_XYZ_from_xy_checked(png_ptr, &XYZ, xy)) + { + /* The success case, because XYZ_from_xy normalises to a reference + * white Y of 1.0 we just need to scale the numbers. This should + * always work just fine. It is an internal error if this overflows. + */ + { + png_fixed_point r, g, b; + if (png_muldiv(&r, XYZ.redY, 32768, PNG_FP_1) && + r >= 0 && r <= 32768 && + png_muldiv(&g, XYZ.greenY, 32768, PNG_FP_1) && + g >= 0 && g <= 32768 && + png_muldiv(&b, XYZ.blueY, 32768, PNG_FP_1) && + b >= 0 && b <= 32768 && + r+g+b <= 32769) + { + /* We allow 0 coefficients here. r+g+b may be 32769 if two or + * all of the coefficients were rounded up. Handle this by + * reducing the *largest* coefficient by 1; this matches the + * approach used for the default coefficients in pngrtran.c + */ + int add = 0; + + if (r+g+b > 32768) + add = -1; + else if (r+g+b < 32768) + add = 1; + + if (add != 0) + { + if (g >= r && g >= b) + g += add; + else if (r >= g && r >= b) + r += add; + else + b += add; + } + + /* Check for an internal error. */ + if (r+g+b != 32768) + png_error(png_ptr, + "internal error handling cHRM coefficients"); + + png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r; + png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g; + } + + /* This is a png_error at present even though it could be ignored - + * it should never happen, but it is important that if it does, the + * bug is fixed. + */ + else + png_error(png_ptr, "internal error handling cHRM->XYZ"); + } + } + } +#endif + + png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red, + x_green, y_green, x_blue, y_blue); +} +#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)) + { + if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500, 500)) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, + info_ptr->gamma); + + png_formatted_warning(png_ptr, p, + "Ignoring incorrect gAMA value @1 when sRGB is also present"); + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_red, 64000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_green, 60000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_READ_cHRM_SUPPORTED */ + + /* This is recorded for use when handling the cHRM chunk above. An sRGB + * chunk unconditionally overwrites the coefficients for grayscale conversion + * too. + */ + png_ptr->is_sRGB = 1; + +# ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Don't overwrite user supplied values: */ + if (!png_ptr->rgb_to_gray_coefficients_set) + { + /* These numbers come from the sRGB specification (or, since one has to + * pay much money to get a copy, the wikipedia sRGB page) the + * chromaticity values quoted have been inverted to get the reverse + * transformation from RGB to XYZ and the 'Y' coefficients scaled by + * 32768 (then rounded). + * + * sRGB and ITU Rec-709 both truncate the values for the D65 white + * point to four digits and, even though it actually stores five + * digits, the PNG spec gives the truncated value. + * + * This means that when the chromaticities are converted back to XYZ + * end points we end up with (6968,23435,2366), which, as described in + * pngrtran.c, would overflow. If the five digit precision and up is + * used we get, instead: + * + * 6968*R + 23435*G + 2365*B + * + * (Notice that this rounds the blue coefficient down, rather than the + * choice used in pngrtran.c which is to round the green one down.) + */ + png_ptr->rgb_to_gray_red_coeff = 6968; /* 0.212639005871510 */ + png_ptr->rgb_to_gray_green_coeff = 23434; /* 0.715168678767756 */ + /* png_ptr->rgb_to_gray_blue_coeff = 2366; 0.072192315360734 */ + + /* The following keeps the cHRM chunk from destroying the + * coefficients again in the event that it follows the sRGB chunk. + */ + png_ptr->rgb_to_gray_coefficients_set = 1; + } +# endif + + 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; + png_alloc_size_t 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 = 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)) ); + + /* NOTE: the following guarantees that 'profile_length' fits into 32 bits, + * because profile_size is a 32 bit value. + */ + if (profile_size < profile_length) + profile_length = profile_size; + + /* And the following guarantees that profile_size == profile_length. */ + if (profile_size > profile_length) + { + PNG_WARNING_PARAMETERS(p) + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + + png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_u, profile_size); + png_warning_parameter_unsigned(p, 2, PNG_NUMBER_FORMAT_u, profile_length); + png_formatted_warning(png_ptr, p, + "Ignoring iCCP chunk with declared size = @1 and actual length = @2"); + return; + } + + png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, + compression_type, (png_bytep)png_ptr->chunkdata + prefix_length, + profile_size); + 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; + png_sPLT_entryp pp; + png_uint_32 data_length; + int entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + png_uint_32 dl; + png_size_t max_dl; + + 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); + + /* WARNING: this may break if size_t is less than 32 bits; it is assumed + * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a + * potential breakage point if the types in pngconf.h aren't exactly right. + */ + slength = 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); + /* This must fit in a png_uint_32 because it is derived from the original + * chunk data length (and use 'length', not 'slength' here for clarity - + * they are guaranteed to be the same, see the tests above.) + */ + data_length = length - (png_uint_32)(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; + } + + dl = (png_int_32)(data_length / entry_size); + max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry); + + if (dl > max_dl) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + + new_palette.nentries = (png_int_32)(data_length / entry_size); + + 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[i].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_color.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_color.red = png_get_uint_16(buf); + png_ptr->trans_color.green = png_get_uint_16(buf + 2); + png_ptr->trans_color.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_color)); +} +#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_color_16 background; + + 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) + { + 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; + } + + background.red = (png_uint_16)png_ptr->palette[buf[0]].red; + background.green = (png_uint_16)png_ptr->palette[buf[0]].green; + background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue; + } + + else + background.red = background.green = background.blue = 0; + + background.gray = 0; + } + + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + background.index = 0; + background.red = + background.green = + background.blue = + background.gray = png_get_uint_16(buf); + } + + else + { + background.index = 0; + background.red = png_get_uint_16(buf); + background.green = png_get_uint_16(buf + 2); + background.blue = png_get_uint_16(buf + 4); + background.gray = 0; + } + + png_set_bKGD(png_ptr, info_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; + } + + num = length / 2 ; + + if (num != (unsigned int)png_ptr->num_palette || num > + (unsigned int)PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + 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 (%u 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 = 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_size_t)(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_size_t slength, i; + int state; + + 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 (%u 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 = length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + /* Validate the unit. */ + if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2) + { + png_warning(png_ptr, "Invalid sCAL ignored: invalid unit"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + /* Validate the ASCII numbers, need two ASCII numbers separated by + * a '\0' and they need to fit exactly in the chunk data. + */ + i = 1; + state = 0; + + if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || + i >= slength || png_ptr->chunkdata[i++] != 0) + png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format"); + + else if (!PNG_FP_IS_POSITIVE(state)) + png_warning(png_ptr, "Invalid sCAL chunk ignored: non-positive width"); + + else + { + png_size_t heighti = i; + + state = 0; + if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || + i != slength) + png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format"); + + else if (!PNG_FP_IS_POSITIVE(state)) + png_warning(png_ptr, + "Invalid sCAL chunk ignored: non-positive height"); + + else + /* This is the (only) success case. */ + png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], + png_ptr->chunkdata+1, png_ptr->chunkdata+heighti); + } + + /* Clean up - just free the temporarily allocated buffer. */ + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#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 = 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_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; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; + 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 = 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_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; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; + 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 = 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++; + } + + if (comp_type || (comp_flag && comp_flag != PNG_TEXT_COMPRESSION_zTXt)) + { + png_warning(png_ptr, "Unknown iTXt compression type or method"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + 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_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) + { + if (png_ptr->chunk_name != png_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + } + + if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_chunk_unknown_handling(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 > 65535) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - 65535; + length = 65535; + } +#endif + + /* TODO: this code is very close to the unknown handling in pngpread.c, + * maybe it can be put into a common utility routine? + * png_struct::unknown_chunk is just used as a temporary variable, along + * with the data into which the chunk is read. These can be eliminated. + */ + PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); + 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_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_CHUNK_CRITICAL(png_ptr->chunk_name)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_chunk_unknown_handling(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 + PNG_UNUSED(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. + */ + +/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is: + * + * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + */ + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name) +{ + int i; + + png_debug(1, "in png_check_chunk_name"); + + for (i=1; i<=4; ++i) + { + int c = chunk_name & 0xff; + + if (c < 65 || c > 122 || (c > 90 && c < 97)) + png_chunk_error(png_ptr, "invalid chunk type"); + + chunk_name >>= 8; + } +} + +/* 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 'display' value; if 'display' is true then the whole row + * (dp) is filled from the start by replicating the available pixels. If + * 'display' is false only those pixels present in the pass are filled in. + */ +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep dp, int display) +{ + unsigned int pixel_depth = png_ptr->transformed_pixel_depth; + png_const_bytep sp = png_ptr->row_buf + 1; + png_uint_32 row_width = png_ptr->width; + unsigned int pass = png_ptr->pass; + png_bytep end_ptr = 0; + png_byte end_byte = 0; + unsigned int end_mask; + + png_debug(1, "in png_combine_row"); + + /* Added in 1.5.6: it should not be possible to enter this routine until at + * least one row has been read from the PNG data and transformed. + */ + if (pixel_depth == 0) + png_error(png_ptr, "internal row logic error"); + + /* Added in 1.5.4: the pixel depth should match the information returned by + * any call to png_read_update_info at this point. Do not continue if we got + * this wrong. + */ + if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes != + PNG_ROWBYTES(pixel_depth, row_width)) + png_error(png_ptr, "internal row size calculation error"); + + /* Don't expect this to ever happen: */ + if (row_width == 0) + png_error(png_ptr, "internal row width error"); + + /* Preserve the last byte in cases where only part of it will be overwritten, + * the multiply below may overflow, we don't care because ANSI-C guarantees + * we get the low bits. + */ + end_mask = (pixel_depth * row_width) & 7; + if (end_mask != 0) + { + /* end_ptr == NULL is a flag to say do nothing */ + end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1; + end_byte = *end_ptr; +# ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) /* little-endian byte */ + end_mask = 0xff << end_mask; + + else /* big-endian byte */ +# endif + end_mask = 0xff >> end_mask; + /* end_mask is now the bits to *keep* from the destination row */ + } + + /* For non-interlaced images this reduces to a png_memcpy(). A png_memcpy() + * will also happen if interlacing isn't supported or if the application + * does not call png_set_interlace_handling(). In the latter cases the + * caller just gets a sequence of the unexpanded rows from each interlace + * pass. + */ +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) && + pass < 6 && (display == 0 || + /* The following copies everything for 'display' on passes 0, 2 and 4. */ + (display == 1 && (pass & 1) != 0))) + { + /* Narrow images may have no bits in a pass; the caller should handle + * this, but this test is cheap: + */ + if (row_width <= PNG_PASS_START_COL(pass)) + return; + + if (pixel_depth < 8) + { + /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit + * into 32 bits, then a single loop over the bytes using the four byte + * values in the 32-bit mask can be used. For the 'display' option the + * expanded mask may also not require any masking within a byte. To + * make this work the PACKSWAP option must be taken into account - it + * simply requires the pixels to be reversed in each byte. + * + * The 'regular' case requires a mask for each of the first 6 passes, + * the 'display' case does a copy for the even passes in the range + * 0..6. This has already been handled in the test above. + * + * The masks are arranged as four bytes with the first byte to use in + * the lowest bits (little-endian) regardless of the order (PACKSWAP or + * not) of the pixels in each byte. + * + * NOTE: the whole of this logic depends on the caller of this function + * only calling it on rows appropriate to the pass. This function only + * understands the 'x' logic; the 'y' logic is handled by the caller. + * + * The following defines allow generation of compile time constant bit + * masks for each pixel depth and each possibility of swapped or not + * swapped bytes. Pass 'p' is in the range 0..6; 'x', a pixel index, + * is in the range 0..7; and the result is 1 if the pixel is to be + * copied in the pass, 0 if not. 'S' is for the sparkle method, 'B' + * for the block method. + * + * With some compilers a compile time expression of the general form: + * + * (shift >= 32) ? (a >> (shift-32)) : (b >> shift) + * + * Produces warnings with values of 'shift' in the range 33 to 63 + * because the right hand side of the ?: expression is evaluated by + * the compiler even though it isn't used. Microsoft Visual C (various + * versions) and the Intel C compiler are known to do this. To avoid + * this the following macros are used in 1.5.6. This is a temporary + * solution to avoid destabilizing the code during the release process. + */ +# if PNG_USE_COMPILE_TIME_MASKS +# define PNG_LSR(x,s) ((x)>>((s) & 0x1f)) +# define PNG_LSL(x,s) ((x)<<((s) & 0x1f)) +# else +# define PNG_LSR(x,s) ((x)>>(s)) +# define PNG_LSL(x,s) ((x)<<(s)) +# endif +# define S_COPY(p,x) (((p)<4 ? PNG_LSR(0x80088822,(3-(p))*8+(7-(x))) :\ + PNG_LSR(0xaa55ff00,(7-(p))*8+(7-(x)))) & 1) +# define B_COPY(p,x) (((p)<4 ? PNG_LSR(0xff0fff33,(3-(p))*8+(7-(x))) :\ + PNG_LSR(0xff55ff00,(7-(p))*8+(7-(x)))) & 1) + + /* Return a mask for pass 'p' pixel 'x' at depth 'd'. The mask is + * little endian - the first pixel is at bit 0 - however the extra + * parameter 's' can be set to cause the mask position to be swapped + * within each byte, to match the PNG format. This is done by XOR of + * the shift with 7, 6 or 4 for bit depths 1, 2 and 4. + */ +# define PIXEL_MASK(p,x,d,s) \ + (PNG_LSL(((PNG_LSL(1U,(d)))-1),(((x)*(d))^((s)?8-(d):0)))) + + /* Hence generate the appropriate 'block' or 'sparkle' pixel copy mask. + */ +# define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) +# define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0) + + /* Combine 8 of these to get the full mask. For the 1-bpp and 2-bpp + * cases the result needs replicating, for the 4-bpp case the above + * generates a full 32 bits. + */ +# define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1))) + +# define S_MASK(p,d,s) MASK_EXPAND(S_MASKx(p,0,d,s) + S_MASKx(p,1,d,s) +\ + S_MASKx(p,2,d,s) + S_MASKx(p,3,d,s) + S_MASKx(p,4,d,s) +\ + S_MASKx(p,5,d,s) + S_MASKx(p,6,d,s) + S_MASKx(p,7,d,s), d) + +# define B_MASK(p,d,s) MASK_EXPAND(B_MASKx(p,0,d,s) + B_MASKx(p,1,d,s) +\ + B_MASKx(p,2,d,s) + B_MASKx(p,3,d,s) + B_MASKx(p,4,d,s) +\ + B_MASKx(p,5,d,s) + B_MASKx(p,6,d,s) + B_MASKx(p,7,d,s), d) + +#if PNG_USE_COMPILE_TIME_MASKS + /* Utility macros to construct all the masks for a depth/swap + * combination. The 's' parameter says whether the format is PNG + * (big endian bytes) or not. Only the three odd-numbered passes are + * required for the display/block algorithm. + */ +# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\ + S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) } + +# define B_MASKS(d,s) { B_MASK(1,d,s), S_MASK(3,d,s), S_MASK(5,d,s) } + +# define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2)) + + /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and + * then pass: + */ + static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = + { + /* Little-endian byte masks for PACKSWAP */ + { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, + /* Normal (big-endian byte) masks - PNG format */ + { S_MASKS(1,1), S_MASKS(2,1), S_MASKS(4,1) } + }; + + /* display_mask has only three entries for the odd passes, so index by + * pass>>1. + */ + static PNG_CONST png_uint_32 display_mask[2][3][3] = + { + /* Little-endian byte masks for PACKSWAP */ + { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, + /* Normal (big-endian byte) masks - PNG format */ + { B_MASKS(1,1), B_MASKS(2,1), B_MASKS(4,1) } + }; + +# define MASK(pass,depth,display,png)\ + ((display)?display_mask[png][DEPTH_INDEX(depth)][pass>>1]:\ + row_mask[png][DEPTH_INDEX(depth)][pass]) + +#else /* !PNG_USE_COMPILE_TIME_MASKS */ + /* This is the runtime alternative: it seems unlikely that this will + * ever be either smaller or faster than the compile time approach. + */ +# define MASK(pass,depth,display,png)\ + ((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png)) +#endif /* !PNG_USE_COMPILE_TIME_MASKS */ + + /* Use the appropriate mask to copy the required bits. In some cases + * the byte mask will be 0 or 0xff, optimize these cases. row_width is + * the number of pixels, but the code copies bytes, so it is necessary + * to special case the end. + */ + png_uint_32 pixels_per_byte = 8 / pixel_depth; + png_uint_32 mask; + +# ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + mask = MASK(pass, pixel_depth, display, 0); + + else +# endif + mask = MASK(pass, pixel_depth, display, 1); + + for (;;) + { + png_uint_32 m; + + /* It doesn't matter in the following if png_uint_32 has more than + * 32 bits because the high bits always match those in m<<24; it is, + * however, essential to use OR here, not +, because of this. + */ + m = mask; + mask = (m >> 8) | (m << 24); /* rotate right to good compilers */ + m &= 0xff; + + if (m != 0) /* something to copy */ + { + if (m != 0xff) + *dp = (png_byte)((*dp & ~m) | (*sp & m)); + else + *dp = *sp; + } + + /* NOTE: this may overwrite the last byte with garbage if the image + * is not an exact number of bytes wide; libpng has always done + * this. + */ + if (row_width <= pixels_per_byte) + break; /* May need to restore part of the last byte */ + + row_width -= pixels_per_byte; + ++dp; + ++sp; + } + } + + else /* pixel_depth >= 8 */ + { + unsigned int bytes_to_copy, bytes_to_jump; + + /* Validate the depth - it must be a multiple of 8 */ + if (pixel_depth & 7) + png_error(png_ptr, "invalid user transform pixel depth"); + + pixel_depth >>= 3; /* now in bytes */ + row_width *= pixel_depth; + + /* Regardless of pass number the Adam 7 interlace always results in a + * fixed number of pixels to copy then to skip. There may be a + * different number of pixels to skip at the start though. + */ + { + unsigned int offset = PNG_PASS_START_COL(pass) * pixel_depth; + + row_width -= offset; + dp += offset; + sp += offset; + } + + /* Work out the bytes to copy. */ + if (display) + { + /* When doing the 'block' algorithm the pixel in the pass gets + * replicated to adjacent pixels. This is why the even (0,2,4,6) + * passes are skipped above - the entire expanded row is copied. + */ + bytes_to_copy = (1<<((6-pass)>>1)) * pixel_depth; + + /* But don't allow this number to exceed the actual row width. */ + if (bytes_to_copy > row_width) + bytes_to_copy = row_width; + } + + else /* normal row; Adam7 only ever gives us one pixel to copy. */ + bytes_to_copy = pixel_depth; + + /* In Adam7 there is a constant offset between where the pixels go. */ + bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth; + + /* And simply copy these bytes. Some optimization is possible here, + * depending on the value of 'bytes_to_copy'. Special case the low + * byte counts, which we know to be frequent. + * + * Notice that these cases all 'return' rather than 'break' - this + * avoids an unnecessary test on whether to restore the last byte + * below. + */ + switch (bytes_to_copy) + { + case 1: + for (;;) + { + *dp = *sp; + + if (row_width <= bytes_to_jump) + return; + + dp += bytes_to_jump; + sp += bytes_to_jump; + row_width -= bytes_to_jump; + } + + case 2: + /* There is a possibility of a partial copy at the end here; this + * slows the code down somewhat. + */ + do + { + dp[0] = sp[0], dp[1] = sp[1]; + + if (row_width <= bytes_to_jump) + return; + + sp += bytes_to_jump; + dp += bytes_to_jump; + row_width -= bytes_to_jump; + } + while (row_width > 1); + + /* And there can only be one byte left at this point: */ + *dp = *sp; + return; + + case 3: + /* This can only be the RGB case, so each copy is exactly one + * pixel and it is not necessary to check for a partial copy. + */ + for (;;) + { + dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2]; + + if (row_width <= bytes_to_jump) + return; + + sp += bytes_to_jump; + dp += bytes_to_jump; + row_width -= bytes_to_jump; + } + + default: +#if PNG_ALIGN_TYPE != PNG_ALIGN_NONE + /* Check for double byte alignment and, if possible, use a + * 16-bit copy. Don't attempt this for narrow images - ones that + * are less than an interlace panel wide. Don't attempt it for + * wide bytes_to_copy either - use the png_memcpy there. + */ + if (bytes_to_copy < 16 /*else use png_memcpy*/ && + png_isaligned(dp, png_uint_16) && + png_isaligned(sp, png_uint_16) && + bytes_to_copy % sizeof (png_uint_16) == 0 && + bytes_to_jump % sizeof (png_uint_16) == 0) + { + /* Everything is aligned for png_uint_16 copies, but try for + * png_uint_32 first. + */ + if (png_isaligned(dp, png_uint_32) && + png_isaligned(sp, png_uint_32) && + bytes_to_copy % sizeof (png_uint_32) == 0 && + bytes_to_jump % sizeof (png_uint_32) == 0) + { + png_uint_32p dp32 = (png_uint_32p)dp; + png_const_uint_32p sp32 = (png_const_uint_32p)sp; + unsigned int skip = (bytes_to_jump-bytes_to_copy) / + sizeof (png_uint_32); + + do + { + size_t c = bytes_to_copy; + do + { + *dp32++ = *sp32++; + c -= sizeof (png_uint_32); + } + while (c > 0); + + if (row_width <= bytes_to_jump) + return; + + dp32 += skip; + sp32 += skip; + row_width -= bytes_to_jump; + } + while (bytes_to_copy <= row_width); + + /* Get to here when the row_width truncates the final copy. + * There will be 1-3 bytes left to copy, so don't try the + * 16-bit loop below. + */ + dp = (png_bytep)dp32; + sp = (png_const_bytep)sp32; + do + *dp++ = *sp++; + while (--row_width > 0); + return; + } + + /* Else do it in 16-bit quantities, but only if the size is + * not too large. + */ + else + { + png_uint_16p dp16 = (png_uint_16p)dp; + png_const_uint_16p sp16 = (png_const_uint_16p)sp; + unsigned int skip = (bytes_to_jump-bytes_to_copy) / + sizeof (png_uint_16); + + do + { + size_t c = bytes_to_copy; + do + { + *dp16++ = *sp16++; + c -= sizeof (png_uint_16); + } + while (c > 0); + + if (row_width <= bytes_to_jump) + return; + + dp16 += skip; + sp16 += skip; + row_width -= bytes_to_jump; + } + while (bytes_to_copy <= row_width); + + /* End of row - 1 byte left, bytes_to_copy > row_width: */ + dp = (png_bytep)dp16; + sp = (png_const_bytep)sp16; + do + *dp++ = *sp++; + while (--row_width > 0); + return; + } + } +#endif /* PNG_ALIGN_ code */ + + /* The true default - use a png_memcpy: */ + for (;;) + { + png_memcpy(dp, sp, bytes_to_copy); + + if (row_width <= bytes_to_jump) + return; + + sp += bytes_to_jump; + dp += bytes_to_jump; + row_width -= bytes_to_jump; + if (bytes_to_copy > row_width) + bytes_to_copy = row_width; + } + } + + /* NOT REACHED*/ + } /* pixel_depth >= 8 */ + + /* Here if pixel_depth < 8 to check 'end_ptr' below. */ + } + else +#endif + + /* If here then the switch above wasn't used so just png_memcpy the whole row + * from the temporary row buffer (notice that this overwrites the end of the + * destination row if it is a partial byte.) + */ + png_memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width)); + + /* Restore the overwritten bits from the last byte if necessary. */ + if (end_ptr != NULL) + *end_ptr = (png_byte)((end_byte & end_mask) | (*end_ptr & ~end_mask)); +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +void /* PRIVATE */ +png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, + png_uint_32 transformations /* Because these may affect the byte layout */) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Offset to next interlace block */ + static 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) & 0x0f); + 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 + PNG_UNUSED(transformations) /* Silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +static void +png_read_filter_row_sub(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_size_t istop = row_info->rowbytes; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + + PNG_UNUSED(prev_row) + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } +} + +static void +png_read_filter_row_up(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_bytep rp = row; + png_const_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } +} + +static void +png_read_filter_row_avg(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t 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++ + *(rp-bpp)) / 2 ) & 0xff); + + rp++; + } +} + +static void +png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp_end = row + row_info->rowbytes; + int a, c; + + /* First pixel/byte */ + c = *prev_row++; + a = *row + c; + *row++ = (png_byte)a; + + /* Remainder */ + while (row < rp_end) + { + int b, pa, pb, pc, p; + + a &= 0xff; /* From previous iteration or start */ + b = *prev_row++; + + 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 + + /* Find the best predictor, the least of pa, pb, pc favoring the earlier + * ones in the case of a tie. + */ + if (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; + + /* Calculate the current pixel in a, and move the previous row pixel to c + * for the next time round the loop + */ + c = b; + a += *row; + *row++ = (png_byte)a; + } +} + +static void +png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp_end = row + bpp; + + /* Process the first pixel in the row completely (this is the same as 'up' + * because there is only one candidate predictor for the first row). + */ + while (row < rp_end) + { + int a = *row + *prev_row++; + *row++ = (png_byte)a; + } + + /* Remainder */ + rp_end += row_info->rowbytes - bpp; + + while (row < rp_end) + { + int a, b, c, pa, pb, pc, p; + + c = *(prev_row - bpp); + a = *(row - bpp); + b = *prev_row++; + + 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 (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; + + c = b; + a += *row; + *row++ = (png_byte)a; + } +} + +#ifdef PNG_ARM_NEON + +#ifdef __linux__ +#include +#include +#include + +static int png_have_hwcap(unsigned cap) +{ + FILE *f = fopen("/proc/self/auxv", "r"); + Elf32_auxv_t aux; + int have_cap = 0; + + if (!f) + return 0; + + while (fread(&aux, sizeof(aux), 1, f) > 0) + { + if (aux.a_type == AT_HWCAP && + aux.a_un.a_val & cap) + { + have_cap = 1; + break; + } + } + + fclose(f); + + return have_cap; +} +#endif /* __linux__ */ + +static void +png_init_filter_functions_neon(png_structp pp, unsigned int bpp) +{ +#ifdef __linux__ + if (!png_have_hwcap(HWCAP_NEON)) + return; +#endif + + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon; + + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth3_neon; + } + + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth4_neon; + } +} +#endif /* PNG_ARM_NEON */ + +static void +png_init_filter_functions(png_structp pp) +{ + unsigned int bpp = (pp->pixel_depth + 7) >> 3; + + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub; + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg; + if (bpp == 1) + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_1byte_pixel; + else + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_multibyte_pixel; + +#ifdef PNG_ARM_NEON + png_init_filter_functions_neon(pp, bpp); +#endif +} + +void /* PRIVATE */ +png_read_filter_row(png_structp pp, png_row_infop row_info, png_bytep row, + png_const_bytep prev_row, int filter) +{ + if (pp->read_filter[0] == NULL) + png_init_filter_functions(pp); + if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST) + pp->read_filter[filter-1](row_info, row, prev_row); +} + +#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 */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte 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; + + /* TO DO: don't do this if prev_row isn't needed (requires + * read-ahead of the next row's filter byte. + */ + png_memset(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]; + } + + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; /* libpng deinterlacing sees every row */ + + } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + 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_crc_finish(png_ptr, 0); + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_ptr->chunk_name != png_IDAT) + 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 */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte 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; +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + png_init_read_transformations(png_ptr); +#endif +#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; + + /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of + * calculations to calculate the final pixel depth, then + * png_do_read_transforms actually does the transforms. This means that the + * code which effectively calculates this value is actually repeated in three + * separate places. They must all match. Innocent changes to the order of + * transformations can and will break libpng in a way that causes memory + * overwrites. + * + * TODO: fix this. + */ +#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_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16) + { +# ifdef PNG_READ_EXPAND_SUPPORTED + /* In fact it is an error if it isn't supported, but checking is + * the safe way. + */ + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->bit_depth < 16) + max_pixel_depth *= 2; + } + else +# endif + png_ptr->transformations &= ~PNG_EXPAND_16; + } +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & (PNG_FILLER)) + { + 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 || + png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + 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 + + /* This value is stored in png_struct and double checked in the row read + * code. + */ + png_ptr->maximum_pixel_depth = (png_byte)max_pixel_depth; + png_ptr->transformed_pixel_depth = 0; /* calculated on demand */ + + /* 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 + 48 > png_ptr->old_big_row_buf_size) + { + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->big_prev_row); + + if (png_ptr->interlaced) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 48); + + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + + png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + +#ifdef PNG_ALIGNED_MEMORY_SUPPORTED + /* Use 16-byte aligned memory for row_buf with at least 16 bytes + * of padding before and after row_buf; treat prev_row similarly. + * NOTE: the alignment is to the start of the pixels, one beyond the start + * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this + * was incorrect; the filter byte was aligned, which had the exact + * opposite effect of that intended. + */ + { + png_bytep temp = png_ptr->big_row_buf + 32; + int extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->row_buf = temp - extra - 1/*filter byte*/; + + temp = png_ptr->big_prev_row + 32; + extra = (int)((temp - (png_bytep)0) & 0x0f); + png_ptr->prev_row = temp - extra - 1/*filter byte*/; + } + +#else + /* Use 31 bytes of padding before and 17 bytes after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 31; + png_ptr->prev_row = png_ptr->big_prev_row + 31; +#endif + png_ptr->old_big_row_buf_size = row_bytes + 48; + } + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->rowbytes > 65535) + png_error(png_ptr, "This image requires a row greater than 64KB"); + +#endif + if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory"); + + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %u,", png_ptr->width); + png_debug1(3, "height = %u,", png_ptr->height); + png_debug1(3, "iwidth = %u,", png_ptr->iwidth); + png_debug1(3, "num_rows = %u,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", + (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibPNG/pngset.c b/plugins/FreeImage/src/LibPNG/pngset.c new file mode 100644 index 0000000000..e753ca8867 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngset.c @@ -0,0 +1,1284 @@ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.5.7 [December 15, 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 + * + * 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. + */ + +#include "pngpriv.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_const_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 +void PNGFAPI +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->x_white = white_x; + info_ptr->y_white = white_y; + info_ptr->x_red = red_x; + info_ptr->y_red = red_y; + info_ptr->x_green = green_x; + info_ptr->y_green = green_y; + info_ptr->x_blue = blue_x; + info_ptr->y_blue = blue_y; + info_ptr->valid |= PNG_INFO_cHRM; + } +} + +void PNGFAPI +png_set_cHRM_XYZ_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, png_fixed_point int_green_X, + png_fixed_point int_green_Y, png_fixed_point int_green_Z, + png_fixed_point int_blue_X, png_fixed_point int_blue_Y, + png_fixed_point int_blue_Z) +{ + png_XYZ XYZ; + png_xy xy; + + png_debug1(1, "in %s storage function", "cHRM XYZ fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + XYZ.redX = int_red_X; + XYZ.redY = int_red_Y; + XYZ.redZ = int_red_Z; + XYZ.greenX = int_green_X; + XYZ.greenY = int_green_Y; + XYZ.greenZ = int_green_Z; + XYZ.blueX = int_blue_X; + XYZ.blueY = int_blue_Y; + XYZ.blueZ = int_blue_Z; + + if (png_xy_from_XYZ(&xy, XYZ)) + png_error(png_ptr, "XYZ values out of representable range"); + + png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy, + xy.greenx, xy.greeny, xy.bluex, xy.bluey); +} + +# 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_set_cHRM_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, white_x, "cHRM White X"), + png_fixed(png_ptr, white_y, "cHRM White Y"), + png_fixed(png_ptr, red_x, "cHRM Red X"), + png_fixed(png_ptr, red_y, "cHRM Red Y"), + png_fixed(png_ptr, green_x, "cHRM Green X"), + png_fixed(png_ptr, green_y, "cHRM Green Y"), + png_fixed(png_ptr, blue_x, "cHRM Blue X"), + png_fixed(png_ptr, blue_y, "cHRM Blue Y")); +} + +void PNGAPI +png_set_cHRM_XYZ(png_structp png_ptr, png_infop info_ptr, double red_X, + double red_Y, double red_Z, double green_X, double green_Y, double green_Z, + double blue_X, double blue_Y, double blue_Z) +{ + png_set_cHRM_XYZ_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, red_X, "cHRM Red X"), + png_fixed(png_ptr, red_Y, "cHRM Red Y"), + png_fixed(png_ptr, red_Z, "cHRM Red Z"), + png_fixed(png_ptr, green_X, "cHRM Red X"), + png_fixed(png_ptr, green_Y, "cHRM Red Y"), + png_fixed(png_ptr, green_Z, "cHRM Red Z"), + png_fixed(png_ptr, blue_X, "cHRM Red X"), + png_fixed(png_ptr, blue_Y, "cHRM Red Y"), + png_fixed(png_ptr, blue_Z, "cHRM Red Z")); +} +# endif /* PNG_FLOATING_POINT_SUPPORTED */ + +#endif /* PNG_cHRM_SUPPORTED */ + +#ifdef PNG_gAMA_SUPPORTED +void PNGFAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + file_gamma) +{ + png_debug1(1, "in %s storage function", "gAMA"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't + * occur. Since the fixed point representation is assymetrical it is + * possible for 1/gamma to overflow the limit of 21474 and this means the + * gamma value must be at least 5/100000 and hence at most 20000.0. For + * safety the limits here are a little narrower. The values are 0.00016 to + * 6250.0, which are truly ridiculous gammma values (and will produce + * displays that are all black or all white.) + */ + if (file_gamma < 16 || file_gamma > 625000000) + png_warning(png_ptr, "Out of range gamma value ignored"); + + else + { + info_ptr->gamma = file_gamma; + info_ptr->valid |= PNG_INFO_gAMA; + } +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, + "png_set_gAMA")); +} +# endif +#endif + +#ifdef PNG_hIST_SUPPORTED +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_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; + } + + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); + + /* 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_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; + info_ptr->free_me |= PNG_FREE_HIST; +} +#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 RRGGBBAA pixels */ + - 48 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = 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_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params) +{ + png_size_t 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); + + /* TODO: validate format of calibration name and unit name */ + + /* Check that the type matches the specification. */ + if (type < 0 || type > 3) + png_error(png_ptr, "Invalid pCAL equation type"); + + /* Validate params[nparams] */ + for (i=0; ipcal_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, 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, length); + + info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, + (png_size_t)((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], length); + } + + info_ptr->valid |= PNG_INFO_pCAL; + info_ptr->free_me |= PNG_FREE_PCAL; +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight) +{ + png_size_t lengthw = 0, lengthh = 0; + + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Double check the unit (should never get here with an invalid + * unit unless this is an API call.) + */ + if (unit != 1 && unit != 2) + png_error(png_ptr, "Invalid sCAL unit"); + + if (swidth == NULL || (lengthw = png_strlen(swidth)) == 0 || + swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw)) + png_error(png_ptr, "Invalid sCAL width"); + + if (sheight == NULL || (lengthh = png_strlen(sheight)) == 0 || + sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh)) + png_error(png_ptr, "Invalid sCAL height"); + + info_ptr->scal_unit = (png_byte)unit; + + ++lengthw; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); + + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw); + + 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, lengthw); + + ++lengthh; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); + + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh); + + 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, lengthh); + + info_ptr->valid |= PNG_INFO_sCAL; + info_ptr->free_me |= PNG_FREE_SCAL; +} + +# 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"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width, + PNG_sCAL_PRECISION); + png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height, + PNG_sCAL_PRECISION); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit, + png_fixed_point width, png_fixed_point height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fixed(png_ptr, swidth, sizeof swidth, width); + png_ascii_from_fixed(png_ptr, sheight, sizeof sheight, height); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# 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_const_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. + */ + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); + + /* 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; + + info_ptr->free_me |= PNG_FREE_PLTE; + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#ifdef PNG_sBIT_SUPPORTED +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_const_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 srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)srgb_intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int srgb_intent) +{ + 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, srgb_intent); + +# ifdef PNG_gAMA_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); +# endif + +# ifdef PNG_cHRM_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + /* color x y */ + /* white */ 31270, 32900, + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000 + ); +# endif /* cHRM */ +} +#endif /* sRGB */ + + +#ifdef PNG_iCCP_SUPPORTED +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_bytep new_iccp_profile; + png_size_t 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_bytep)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; + info_ptr->free_me |= PNG_FREE_ICCP; + 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_const_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_const_textp text_ptr, int num_text) +{ + int i; + + png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" : + (unsigned long)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) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_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_size_t)(info_ptr->max_text * png_sizeof(png_text))); + + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + 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_size_t)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + return(1); + info_ptr->free_me |= PNG_FREE_TEXT; + } + + 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; + + if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || + text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) + { + png_warning(png_ptr, "text compression mode is out of range"); + 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_size_t) + (key_len + text_length + lang_len + lang_key_len + 4)); + + if (textp->key == NULL) + return(1); + + png_debug2(2, "Allocated %lu bytes at %p in png_set_text", + (unsigned long)(png_uint_32) + (key_len + lang_len + lang_key_len + text_length + 4), + textp->key); + + png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); + *(textp->key + key_len) = '\0'; + + 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 + { + textp->lang=NULL; + textp->lang_key=NULL; + 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; + textp->itxt_length = 0; + } + + 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_const_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; + + if (mod_time->month == 0 || mod_time->month > 12 || + mod_time->day == 0 || mod_time->day > 31 || + mod_time->hour > 23 || mod_time->minute > 59 || + mod_time->second > 60) + { + png_warning(png_ptr, "Ignoring invalid time value"); + 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_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) +{ + png_debug1(1, "in %s storage function", "tRNS"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans_alpha != NULL) + { + /* It may not actually be necessary to set png_ptr->trans_alpha here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); + + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + png_ptr->trans_alpha = info_ptr->trans_alpha = + (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH); + + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + } + + if (trans_color != NULL) + { + int sample_max = (1 << info_ptr->bit_depth); + + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max))) + png_warning(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth"); + + png_memcpy(&(info_ptr->trans_color), trans_color, + 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; + info_ptr->free_me |= PNG_FREE_TRNS; + } +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_const_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_size_t)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_const_sPLT_tp from = entries + i; + png_size_t 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, + 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; + info_ptr->free_me |= PNG_FREE_SPLT; +} +#endif /* PNG_sPLT_SUPPORTED */ + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_const_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_size_t)(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, + (png_size_t)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_const_unknown_chunkp from = unknowns + i; + + png_memcpy(to->name, 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_size_t)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; + info_ptr->free_me |= PNG_FREE_UNKN; +} + +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 < + info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#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_const_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_size_t)(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; inum_chunk_list = old_num_chunks + num_chunks; + png_ptr->chunk_list = new_list; + png_ptr->free_me |= PNG_FREE_LIST; +} +#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_size_t size) +{ + if (png_ptr == NULL) + return; + + png_free(png_ptr, png_ptr->zbuf); + + if (size > ZLIB_IO_MAX) + { + png_warning(png_ptr, "Attempt to set buffer size beyond max ignored"); + png_ptr->zbuf_size = ZLIB_IO_MAX; + size = ZLIB_IO_MAX; /* must fit */ + } + + else + png_ptr->zbuf_size = (uInt)size; + + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + + /* The following ensures a relatively safe failure if this gets called while + * the buffer is actually in use. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = 0; + png_ptr->zstream.avail_in = 0; +} + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~mask; +} + + + +#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; +} + +/* This function was added to libpng 1.4.0 */ +void PNGAPI +png_set_chunk_cache_max (png_structp png_ptr, + png_uint_32 user_chunk_cache_max) +{ + if (png_ptr) + png_ptr->user_chunk_cache_max = user_chunk_cache_max; +} + +/* This function was added to libpng 1.4.1 */ +void PNGAPI +png_set_chunk_malloc_max (png_structp png_ptr, + png_alloc_size_t user_chunk_malloc_max) +{ + if (png_ptr) + png_ptr->user_chunk_malloc_max = user_chunk_malloc_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_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibPNG/pngstruct.h b/plugins/FreeImage/src/LibPNG/pngstruct.h new file mode 100644 index 0000000000..1824c49114 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngstruct.h @@ -0,0 +1,358 @@ + +/* pngstruct.h - header file for PNG reference library + * + * 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.) + * + * Last changed in libpng 1.5.9 [February 18, 2012] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* 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. + */ + +#ifndef PNGSTRUCT_H +#define PNGSTRUCT_H +/* zlib.h defines the structure z_stream, an instance of which is included + * in this structure and is required for decompressing the LZ compressed + * data in PNG files. + */ +#include "zlib.h" + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf longjmp_buffer; /* used in png_error */ + png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ +#ifdef PNG_WARNINGS_SUPPORTED + png_error_ptr warning_fn; /* function for printing warnings */ +#endif + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn; /* 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; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + uInt zbuf_size; /* size of zbuf (typically 65536) */ +#ifdef PNG_WRITE_SUPPORTED + +/* Added in 1.5.4: state to keep track of whether the zstream has been + * initialized and if so whether it is for IDAT or some other chunk. + */ +#define PNG_ZLIB_UNINITIALIZED 0 +#define PNG_ZLIB_FOR_IDAT 1 +#define PNG_ZLIB_FOR_TEXT 2 /* anything other than IDAT */ +#define PNG_ZLIB_USE_MASK 3 /* bottom two bits */ +#define PNG_ZLIB_IN_USE 4 /* a flag value */ + + png_uint_32 zlib_state; /* State of zlib initialization */ +/* End of material added at libpng 1.5.4 */ + + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ +#endif +/* Added at libpng 1.5.4 */ +#if defined(PNG_WRITE_COMPRESSED_TEXT_SUPPORTED) || \ + defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED) + int zlib_text_level; /* holds zlib compression level */ + int zlib_text_method; /* holds zlib compression method */ + int zlib_text_window_bits; /* holds zlib compression window bits */ + int zlib_text_mem_level; /* holds zlib compression memory level */ + int zlib_text_strategy; /* holds zlib compression strategy */ +#endif +/* End of material added at libpng 1.5.4 */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_size_t rowbytes; /* size of row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row. + * This is a pointer into big_prev_row + */ + png_bytep row_buf; /* buffer to save current (unfiltered) row. + * This is a pointer into big_row_buf + */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ + png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row: write only */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write: write only */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + png_byte maximum_pixel_depth; + /* pixel depth used for the row buffers */ + png_byte transformed_pixel_depth; + /* pixel depth after read/write transforms */ + png_byte io_chunk_string[5]; + /* string name of chunk */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + png_byte background_gamma_type; + png_fixed_point background_gamma; + png_color_16 background; /* background color in screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn; /* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ + png_fixed_point gamma; /* file gamma value */ + png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ + + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* 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_alpha; /* alpha values for paletted files */ + png_color_16 trans_color; /* transparent color for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# ifdef PNG_TEXT_SUPPORTED + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && 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_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup; /* lookup table for quantizing */ + png_bytep quantize_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + char time_buffer[29]; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int num_chunk_list; + png_bytep chunk_list; +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + /* Added in 1.5.5 to record an sRGB chunk in the png. */ + png_byte is_sRGB; +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status; + /* Added in libpng 1.5.5 to record setting of coefficients: */ + png_byte rgb_to_gray_coefficients_set; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + /* deleted in 1.5.5: rgb_to_gray_blue_coeff; */ +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) +/* Changed from png_byte to png_uint_32 at version 1.2.0 */ + png_uint_32 mng_features_permitted; +#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; +#endif + +/* New members added in libpng-1.2.0 */ + +/* 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; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep quantize_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is + in the palette */ + png_bytep palette_to_index; /* 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; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; + + /* 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; + + /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. + */ + png_alloc_size_t user_chunk_malloc_max; +#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; +#endif + +/* New member added in libpng-1.2.26 */ + png_size_t old_big_row_buf_size; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata; /* buffer for reading chunk data */ + +#ifdef PNG_IO_STATE_SUPPORTED +/* New member added in libpng-1.4.0 */ + png_uint_32 io_state; +#endif + +/* New member added in libpng-1.5.6 */ + png_bytep big_prev_row; + + void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row); +}; +#endif /* PNGSTRUCT_H */ diff --git a/plugins/FreeImage/src/LibPNG/pngtest.c b/plugins/FreeImage/src/LibPNG/pngtest.c new file mode 100644 index 0000000000..840517400b --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngtest.c @@ -0,0 +1,1820 @@ + +/* pngtest.c - a simple test program to test libpng + * + * Last changed in libpng 1.5.6 [November 3, 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 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 _POSIX_SOURCE 1 + +#include "zlib.h" +#include "png.h" +/* Copied from pngpriv.h but only used in error messages below. */ +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif +# include +# include +# include +# define FCLOSE(file) fclose(file) + +#ifndef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +/* Makes pngtest verbose so we can find problems. */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if PNG_DEBUG > 1 +# define pngtest_debug(m) ((void)fprintf(stderr, m "\n")) +# define pngtest_debug1(m,p1) ((void)fprintf(stderr, m "\n", p1)) +# define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2)) +#else +# define pngtest_debug(m) ((void)0) +# define pngtest_debug1(m,p1) ((void)0) +# define pngtest_debug2(m,p1,p2) ((void)0) +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ +#endif + +/* The code uses memcmp and memcpy on large objects (typically row pointers) so + * it is necessary to do soemthing special on certain architectures, note that + * the actual support for this was effectively removed in 1.4, so only the + * memory remains in this program: + */ +#define CVT_PTR(ptr) (ptr) +#define CVT_PTR_NOCHECK(ptr) (ptr) +#define png_memcmp memcmp +#define png_memcpy memcpy +#define png_memset memset + +/* 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 +#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; +static int strict = 0; + +int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); + +#ifdef __TURBOC__ +#include +#endif + +/* Defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* For DOS */ + +/* 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 PNGCBAPI +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void PNGCBAPI +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 PNGCBAPI +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void PNGCBAPI +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 PNGCBAPI +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void PNGCBAPI +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 PNGCBAPI +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void PNGCBAPI +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; nbit_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; nbit_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. + */ + +#ifdef PNG_IO_STATE_SUPPORTED +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op); +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op) +{ + png_uint_32 io_state = png_get_io_state(png_ptr); + int err = 0; + + /* Check if the current operation (reading / writing) is as expected. */ + if ((io_state & PNG_IO_MASK_OP) != io_op) + png_error(png_ptr, "Incorrect operation in I/O state"); + + /* Check if the buffer size specific to the current location + * (file signature / header / data / crc) is as expected. + */ + switch (io_state & PNG_IO_MASK_LOC) + { + case PNG_IO_SIGNATURE: + if (data_length > 8) + err = 1; + break; + case PNG_IO_CHUNK_HDR: + if (data_length != 8) + err = 1; + break; + case PNG_IO_CHUNK_DATA: + break; /* no restrictions here */ + case PNG_IO_CHUNK_CRC: + if (data_length != 4) + err = 1; + break; + default: + err = 1; /* uninitialized */ + } + if (err) + png_error(png_ptr, "Bad I/O state or buffer size"); +} +#endif + +#ifndef USE_FAR_KEYWORD +static void PNGCBAPI +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) + { + check = fread(data, 1, length, (png_FILE_p)io_ptr); + } + + if (check != length) + { + png_error(png_ptr, "Read Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} +#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 PNGCBAPI +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t 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_get_io_ptr(png_ptr)); + if ((png_bytep)n_data == data) + { + check = fread(n_data, 1, length, io_ptr); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, 1, io_ptr); + 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"); + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} +#endif /* USE_FAR_KEYWORD */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +static void PNGCBAPI +pngtest_flush(png_structp png_ptr) +{ + /* Do nothing; fflush() is said to be just a waste of energy. */ + PNG_UNUSED(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 PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#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 PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t 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_get_io_ptr(png_ptr)); + + if ((png_bytep)near_data == data) + { + check = fwrite(near_data, 1, length, io_ptr); + } + + 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 */ + err = fwrite(buf, 1, written, io_ptr); + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#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 PNGCBAPI +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 PNGCBAPI +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_alloc_size_t 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 PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr, + png_alloc_size_t size)); +void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); + +png_voidp +PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t 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_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_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + + png_set_mem_fn(png_ptr, + NULL, png_debug_malloc, 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 %p\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 PNGCBAPI +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 %p\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 PNGCBAPI 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 tmp_jmpbuf; +#endif +#endif + + char inbuf[256], outbuf[256]; + + row_buf = NULL; + + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "wb")) == NULL) + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + pngtest_debug("Allocating read and write structures"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + read_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, 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, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + write_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif +#endif + pngtest_debug("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 + pngtest_debug("Setting jmpbuf for read struct"); +#ifdef USE_FAR_KEYWORD + if (setjmp(tmp_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), tmp_jmpbuf, png_sizeof(jmp_buf)); +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Setting jmpbuf for write struct"); +#ifdef USE_FAR_KEYWORD + + if (setjmp(tmp_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), tmp_jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif +#endif + + pngtest_debug("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 + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + /* Normally one would use Z_DEFAULT_STRATEGY for text compression. + * This is here just to make pngtest replicate the results from libpng + * versions prior to 1.5.4, and to test this new API. + */ + png_set_text_compression_strategy(write_ptr, Z_FILTERED); +#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, NULL); +#endif + png_set_read_status_fn(read_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, + 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, + NULL, 0); +#endif + + pngtest_debug("Reading info struct"); + png_read_info(read_ptr, read_info_ptr); + + pngtest_debug("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_bytep 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, ¶ms)) + { + 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) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + + if (verbose) + printf("\n Text compression=%d\n", text_ptr->compression); + + 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_alpha; + int num_trans; + png_color_16p trans_color; + + if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans, + &trans_color)) + { + 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_color->gray > sample_max) || + (color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max)))) + png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, + trans_color); + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + + if (num_unknowns) + { + int 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 < num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("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 + pngtest_debug("Allocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("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++) + { + pngtest_debug1("Writing row data for pass %d", pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug2("\t0x%08lx (%u 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, 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 + pngtest_debug2("Freeing row buffer (pass %d, y = %u)", 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 + + pngtest_debug("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) + { + pngtest_debug1("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 = png_get_unknown_chunks(read_ptr, end_info_ptr, + &unknowns); + + if (num_unknowns) + { + int 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 < 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 + + pngtest_debug("Destroying data structs"); +#ifdef SINGLE_ROWBUF_ALLOC + pngtest_debug("destroying row_buf for read_ptr"); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("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 + pngtest_debug("destroying write_end_info_ptr"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + pngtest_debug("destroying write_ptr, write_info_ptr"); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + pngtest_debug("Destruction complete."); + + FCLOSE(fpin); + FCLOSE(fpout); + + pngtest_debug("Opening files for comparison"); + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + for (;;) + { + png_size_t num_in, num_out; + + num_in = fread(inbuf, 1, 1, fpin); + num_out = fread(outbuf, 1, 1, fpout); + + 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); + + if (strict != 0) + return (1); + + else + 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); + + if (strict != 0) + return (1); + + else + 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); + + /* 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 if (strcmp(argv[1], "--strict") == 0) + { + status_dots_requested = 0; + verbose = 1; + inname = argv[2]; + strict++; + } + + 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; isize, + (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 png_libpng_version_1_5_9 Your_png_h_is_not_version_1_5_9; diff --git a/plugins/FreeImage/src/LibPNG/pngtrans.c b/plugins/FreeImage/src/LibPNG/pngtrans.c new file mode 100644 index 0000000000..53d9a25b95 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngtrans.c @@ -0,0 +1,678 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * Last changed in libpng 1.5.4 [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 + */ + +#include "pngpriv.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_const_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; + png_ptr->filler = (png_uint_16)filler; + + 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; + } +} + +/* 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 + +#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 && + */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_size_t i; + png_size_t 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_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 2) + { + *rp = (png_byte)(~(*rp)); + rp += 2; + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 4) + { + *rp = (png_byte)(~(*rp)); + *(rp + 1) = (png_byte)(~(*(rp + 1))); + rp += 4; + } + } +#endif +} +#endif + +#ifdef PNG_16BIT_SUPPORTED +#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 (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 +#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 (row_info->bit_depth < 8) + { + png_bytep rp; + png_const_bytep end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = onebppswaptable; + + else if (row_info->bit_depth == 2) + table = twobppswaptable; + + else if (row_info->bit_depth == 4) + table = 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 a channel - this used to be 'png_do_strip_filler' but it used a + * somewhat weird combination of flags to determine what to do. All the calls + * to png_do_strip_filler are changed in 1.5.2 to call this instead with the + * correct arguments. + * + * The routine isn't general - the channel must be the channel at the start or + * end (not in the middle) of each pixel. + */ +void /* PRIVATE */ +png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) +{ + png_bytep sp = row; /* source pointer */ + png_bytep dp = row; /* destination pointer */ + png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */ + + /* At the start sp will point to the first byte to copy and dp to where + * it is copied to. ep always points just beyond the end of the row, so + * the loop simply copies (channels-1) channels until sp reaches ep. + * + * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc. + * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc. + */ + + /* GA, GX, XG cases */ + if (row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + if (at_start) /* Skip initial filler */ + ++sp; + else /* Skip initial channel and, for sp, the filler */ + sp += 2, ++dp; + + /* For a 1 pixel wide image there is nothing to do */ + while (sp < ep) + *dp++ = *sp, sp += 2; + + row_info->pixel_depth = 8; + } + + else if (row_info->bit_depth == 16) + { + if (at_start) /* Skip initial filler */ + sp += 2; + else /* Skip initial channel and, for sp, the filler */ + sp += 4, dp += 2; + + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp, sp += 3; + + row_info->pixel_depth = 16; + } + + else + return; /* bad bit depth */ + + row_info->channels = 1; + + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_GRAY; + } + + /* RGBA, RGBX, XRGB cases */ + else if (row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + if (at_start) /* Skip initial filler */ + ++sp; + else /* Skip initial channels and, for sp, the filler */ + sp += 4, dp += 3; + + /* Note that the loop adds 3 to dp and 4 to sp each time. */ + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; + + row_info->pixel_depth = 24; + } + + else if (row_info->bit_depth == 16) + { + if (at_start) /* Skip initial filler */ + sp += 2; + else /* Skip initial channels and, for sp, the filler */ + sp += 8, dp += 6; + + while (sp < ep) + { + /* Copy 6 bytes, skip 2 */ + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp, sp += 3; + } + + row_info->pixel_depth = 48; + } + + else + return; /* bad bit depth */ + + row_info->channels = 3; + + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_RGB; + } + + else + return; /* The filler channel has gone already */ + + /* Fix the rowbytes value. */ + row_info->rowbytes = dp-row; +} +#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 ((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; + } + } + } + +#ifdef PNG_16BIT_SUPPORTED + 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 + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +#ifdef PNG_USER_TRANSFORM_PTR_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; + 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; +} +#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. + */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +png_voidp PNGAPI +png_get_user_transform_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return ((png_voidp)png_ptr->user_transform_ptr); +} +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +png_uint_32 PNGAPI +png_get_current_row_number(png_const_structp png_ptr) +{ + /* See the comments in png.h - this is the sub-image row when reading and + * interlaced image. + */ + if (png_ptr != NULL) + return png_ptr->row_number; + + return PNG_UINT_32_MAX; /* help the app not to fail silently */ +} + +png_byte PNGAPI +png_get_current_pass_number(png_const_structp png_ptr) +{ + if (png_ptr != NULL) + return png_ptr->pass; + return 8; /* invalid */ +} +#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */ +#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED || + PNG_WRITE_USER_TRANSFORM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibPNG/pngwio.c b/plugins/FreeImage/src/LibPNG/pngwio.c new file mode 100644 index 0000000000..8eacf9f6d4 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngwio.c @@ -0,0 +1,254 @@ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.5.0 [January 6, 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 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(...). + */ + +#include "pngpriv.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_const_bytep data, png_size_t length) +{ + /* NOTE: write_data_fn must not change the buffer! */ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, (png_bytep)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 PNGCBAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); + + 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 PNGCBAPI +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) + { + check = fwrite(near_data, 1, length, io_ptr); + } + + 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 */ + err = fwrite(buf, 1, written, io_ptr); + + 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 PNGCBAPI +png_default_flush(png_structp png_ptr) +{ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + fflush(io_ptr); +} +# 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, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } +} + +#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/plugins/FreeImage/src/LibPNG/pngwrite.c b/plugins/FreeImage/src/LibPNG/pngwrite.c new file mode 100644 index 0000000000..dc12a20481 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngwrite.c @@ -0,0 +1,1655 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.5.7 [December 15, 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 + */ + +#include "pngpriv.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) + png_write_gAMA_fixed(png_ptr, info_ptr->gamma); +#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, + (png_charp)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) + png_write_cHRM_fixed(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); +#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->location & PNG_AFTER_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_alpha[j] = + (png_byte)(255 - info_ptr->trans_alpha[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), + 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_WRITE_sCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_sCAL) + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#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, PNG_CONST 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_FUNCTION(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),PNG_ALLOCATED) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */ + +PNG_FUNCTION(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),PNG_ALLOCATED) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + volatile int png_cleanup_needed = 0; +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf tmp_jmpbuf; +#endif +#endif + + 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 +/* 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(tmp_jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */ +#endif +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); +#endif + PNG_ABORT(); +#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 (!png_user_version_check(png_ptr, user_png_ver)) + png_cleanup_needed = 1; + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + + if (!png_cleanup_needed) + { + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, + png_ptr->zbuf_size); + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + 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); + } + + png_set_write_fn(png_ptr, NULL, NULL, NULL); + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_reset_filter_heuristics(png_ptr); +#endif + + return (png_ptr); +} + + +/* 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_const_bytep row) +{ + /* 1.5.6: moved from png_struct to be a local structure: */ + png_row_info row_info; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_write_row (row %u, 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; + + default: /* error: ignore it */ + break; + } + } +#endif + + /* Set up row info for transformations */ + row_info.color_type = png_ptr->color_type; + row_info.width = png_ptr->usr_width; + row_info.channels = png_ptr->usr_channels; + row_info.bit_depth = png_ptr->usr_bit_depth; + row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels); + row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); + + png_debug1(3, "row_info->color_type = %d", row_info.color_type); + png_debug1(3, "row_info->width = %u", row_info.width); + png_debug1(3, "row_info->channels = %d", row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy(png_ptr->row_buf + 1, row, 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(&row_info, png_ptr->row_buf + 1, png_ptr->pass); + /* This should always get caught above, but still ... */ + if (!(row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED + /* Handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr, &row_info); +#endif + + /* At this point the row_info pixel depth must match the 'transformed' depth, + * which is also the output depth. + */ + if (row_info.pixel_depth != png_ptr->pixel_depth || + row_info.pixel_depth != png_ptr->transformed_pixel_depth) + png_error(png_ptr, "internal write transform logic error"); + +#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(&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, &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); + 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->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 + 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->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; +#ifdef PNG_WARNINGS_SUPPORTED + png_error_ptr warning_fn; +#endif + 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 */ + if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED) + 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_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Use this to save a little code space, it doesn't free the filter_costs */ + png_reset_filter_heuristics(png_ptr); + 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->longjmp_buffer, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; +#ifdef PNG_WARNINGS_SUPPORTED + warning_fn = png_ptr->warning_fn; +#endif + 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; +#ifdef PNG_WARNINGS_SUPPORTED + png_ptr->warning_fn = warning_fn; +#endif + 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->longjmp_buffer, 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_byte)(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_byte)(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 */ +/* Convenience reset API. */ +static void +png_reset_filter_heuristics(png_structp png_ptr) +{ + /* Clear out any old values in the 'weights' - this must be done because if + * the app calls set_filter_heuristics multiple times with different + * 'num_weights' values we would otherwise potentially have wrong sized + * arrays. + */ + png_ptr->num_prev_filters = 0; + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + if (png_ptr->prev_filters != NULL) + { + png_bytep old = png_ptr->prev_filters; + png_ptr->prev_filters = NULL; + png_free(png_ptr, old); + } + if (png_ptr->filter_weights != NULL) + { + png_uint_16p old = png_ptr->filter_weights; + png_ptr->filter_weights = NULL; + png_free(png_ptr, old); + } + + if (png_ptr->inv_filter_weights != NULL) + { + png_uint_16p old = png_ptr->inv_filter_weights; + png_ptr->inv_filter_weights = NULL; + png_free(png_ptr, old); + } + + /* Leave the filter_costs - this array is fixed size. */ +} + +static int +png_init_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights) +{ + if (png_ptr == NULL) + return 0; + + /* Clear out the arrays */ + png_reset_filter_heuristics(png_ptr); + + /* Check arguments; the 'reset' function makes the correct settings for the + * unweighted case, but we must handle the weight case by initializing the + * arrays for the caller. + */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + + if (num_weights > 0) + { + 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; + } + + 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; + } + + /* Safe to set this now */ + png_ptr->num_prev_filters = (png_byte)num_weights; + } + + /* 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; + } + + /* All the arrays are inited, safe to set this: */ + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED; + + /* Return the 'ok' code. */ + return 1; + } + else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + return 1; + } + else + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return 0; + } +} + +/* Provide floating and fixed point APIs */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + 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)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5); + + png_ptr->filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5); + } + } + + /* 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[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5); + + png_ptr->filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5); + } + } +} +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method, + int num_weights, png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics_fixed"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 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) + ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1); + + png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR* + PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]); + } + } + + /* 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[i] >= PNG_FP_1) + { + png_uint_32 tmp; + + /* Use a 32 bit unsigned temporary here because otherwise the + * intermediate value will be a 32 bit *signed* integer (ANSI rules) + * and this will get the wrong answer on division. + */ + tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2); + tmp /= filter_costs[i]; + + png_ptr->inv_filter_costs[i] = (png_uint_16)tmp; + + tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF; + tmp /= PNG_FP_1; + + png_ptr->filter_costs[i] = (png_uint_16)tmp; + } + } +} +#endif /* FIXED_POINT */ +#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; +} + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +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; +} + +/* The following were added to libpng-1.5.4 */ +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +void PNGAPI +png_set_text_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_text_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_LEVEL; + png_ptr->zlib_text_level = level; +} + +void PNGAPI +png_set_text_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_text_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL; + png_ptr->zlib_text_mem_level = mem_level; +} + +void PNGAPI +png_set_text_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_text_compression_strategy"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_STRATEGY; + png_ptr->zlib_text_strategy = strategy; +} + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +void PNGAPI +png_set_text_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, "Text compression window is being reset to 512"); + window_bits = 9; + } + +#endif + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS; + png_ptr->zlib_text_window_bits = window_bits; +} + +void PNGAPI +png_set_text_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_text_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_ZTXT_CUSTOM_METHOD; + png_ptr->zlib_text_method = method; +} +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ +/* end of API added to libpng-1.5.4 */ + +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); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibPNG/pngwtran.c b/plugins/FreeImage/src/LibPNG/pngwtran.c new file mode 100644 index 0000000000..b598149a96 --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngwtran.c @@ -0,0 +1,633 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * Last changed in libpng 1.5.6 [November 3, 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 + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_TRANSFORMS_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_row_infop row_info) +{ + 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 */ + row_info, /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t 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_channel(row_info, png_ptr->row_buf + 1, + !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_pack(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(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(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(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(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(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 && + 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; + } + + default: + 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_const_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift"); + + if (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_size_t i; + png_byte mask; + png_size_t 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"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from ARGB to RGBA */ + 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; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AARRGGBB to RRGGBBAA */ + 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]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from AG to GA */ + 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; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AAGG to GGAA */ + 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 /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#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"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + 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++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in RRGGBBAA */ + 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++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + 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++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + 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 /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#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 ((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); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + 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_WRITE_16BIT_SUPPORTED */ + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/plugins/FreeImage/src/LibPNG/pngwutil.c b/plugins/FreeImage/src/LibPNG/pngwutil.c new file mode 100644 index 0000000000..64888f7c6c --- /dev/null +++ b/plugins/FreeImage/src/LibPNG/pngwutil.c @@ -0,0 +1,3180 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.5.6 [November 3, 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 + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_INT_FUNCTIONS_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); +} + +#ifdef PNG_SAVE_INT_32_SUPPORTED +/* 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. Note that, + * the following works correctly even if png_int_32 has more than 32 bits + * (compare the more complex code required on read for sign extention.) + */ +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); +} +#endif + +/* 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); +} +#endif + +/* 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 PNGAPI +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the signature is being written */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; +#endif + + /* 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 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(). + */ +static void +png_write_chunk_header(png_structp png_ptr, png_uint_32 chunk_name, + png_uint_32 length) +{ + png_byte buf[8]; + +#if defined(PNG_DEBUG) && (PNG_DEBUG > 0) + PNG_CSTRING_FROM_CHUNK(buf, chunk_name); + png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length); +#endif + + if (png_ptr == NULL) + return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk header is being written. + * PNG_IO_CHUNK_HDR requires a single I/O call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; +#endif + + /* Write the length and the chunk name */ + png_save_uint_32(buf, length); + png_save_uint_32(buf + 4, chunk_name); + png_write_data(png_ptr, buf, 8); + + /* Put the chunk name into png_ptr->chunk_name */ + png_ptr->chunk_name = chunk_name; + + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + + png_calculate_crc(png_ptr, buf + 4, 4); + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that chunk data will (possibly) be written. + * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; +#endif +} + +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_string, + png_uint_32 length) +{ + png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); +} + +/* Write the data of a PNG chunk started with png_write_chunk_header(). + * 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_header(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_const_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_header(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + if (png_ptr == NULL) return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk CRC is being written. + * PNG_IO_CHUNK_CRC requires a single I/O function call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; +#endif + + /* 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); +} + +/* 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. + */ +static void +png_write_complete_chunk(png_structp png_ptr, png_uint_32 chunk_name, + png_const_bytep data, png_size_t length) +{ + if (png_ptr == NULL) + return; + + /* On 64 bit architectures 'length' may not fit in a png_uint_32. */ + if (length > PNG_UINT_32_MAX) + png_error(png_ptr, "length exceeds PNG maxima"); + + png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, length); + png_write_chunk_end(png_ptr); +} + +/* This is the API that calls the internal function above. */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_const_bytep chunk_string, + png_const_bytep data, png_size_t length) +{ + png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, + length); +} + +/* Initialize the compressor for the appropriate type of compression. */ +static void +png_zlib_claim(png_structp png_ptr, png_uint_32 state) +{ + if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE)) + { + /* If already initialized for 'state' do not re-init. */ + if (png_ptr->zlib_state != state) + { + int ret = Z_OK; + png_const_charp who = "-"; + + /* If actually initialized for another state do a deflateEnd. */ + if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED) + { + ret = deflateEnd(&png_ptr->zstream); + who = "end"; + png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED; + } + + /* zlib itself detects an incomplete state on deflateEnd */ + if (ret == Z_OK) switch (state) + { +# ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED + case PNG_ZLIB_FOR_TEXT: + ret = deflateInit2(&png_ptr->zstream, + png_ptr->zlib_text_level, png_ptr->zlib_text_method, + png_ptr->zlib_text_window_bits, + png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy); + who = "text"; + break; +# endif + + case PNG_ZLIB_FOR_IDAT: + 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); + who = "IDAT"; + break; + + default: + png_error(png_ptr, "invalid zlib state"); + } + + if (ret == Z_OK) + png_ptr->zlib_state = state; + + else /* an error in deflateEnd or deflateInit2 */ + { + size_t pos = 0; + char msg[64]; + + pos = png_safecat(msg, sizeof msg, pos, + "zlib failed to initialize compressor ("); + pos = png_safecat(msg, sizeof msg, pos, who); + + switch (ret) + { + case Z_VERSION_ERROR: + pos = png_safecat(msg, sizeof msg, pos, ") version error"); + break; + + case Z_STREAM_ERROR: + pos = png_safecat(msg, sizeof msg, pos, ") stream error"); + break; + + case Z_MEM_ERROR: + pos = png_safecat(msg, sizeof msg, pos, ") memory error"); + break; + + default: + pos = png_safecat(msg, sizeof msg, pos, ") unknown error"); + break; + } + + png_error(png_ptr, msg); + } + } + + /* Here on success, claim the zstream: */ + png_ptr->zlib_state |= PNG_ZLIB_IN_USE; + } + + else + png_error(png_ptr, "zstream already in use (internal error)"); +} + +/* The opposite: release the stream. It is also reset, this API will warn on + * error but will not fail. + */ +static void +png_zlib_release(png_structp png_ptr) +{ + if (png_ptr->zlib_state & PNG_ZLIB_IN_USE) + { + int ret = deflateReset(&png_ptr->zstream); + + png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE; + + if (ret != Z_OK) + { + png_const_charp err; + PNG_WARNING_PARAMETERS(p) + + switch (ret) + { + case Z_VERSION_ERROR: + err = "version"; + break; + + case Z_STREAM_ERROR: + err = "stream"; + break; + + case Z_MEM_ERROR: + err = "memory"; + break; + + default: + err = "unknown"; + break; + } + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret); + png_warning_parameter(p, 2, err); + + if (png_ptr->zstream.msg) + err = png_ptr->zstream.msg; + else + err = "[no zlib message]"; + + png_warning_parameter(p, 3, err); + + png_formatted_warning(png_ptr, p, + "zlib failed to reset compressor: @1(@2): @3"); + } + } + + else + png_warning(png_ptr, "zstream not in use (internal error)"); +} + +#ifdef PNG_WRITE_COMPRESSED_TEXT_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 +{ + png_const_bytep input; /* The uncompressed input data */ + png_size_t input_len; /* Its length */ + int num_output_ptr; /* Number of output pointers used */ + int max_output_ptr; /* Size of output_ptr */ + png_bytep *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_const_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 = text_len; + + /* We may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = (png_const_bytep)text; + return((int)text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, + compression); + png_formatted_warning(png_ptr, p, "Unknown compression type @1"); + } + + /* 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). + */ + png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT); + + /* Set up the compression buffers */ + /* TODO: the following cast hides a potential overflow problem. */ + png_ptr->zstream.avail_in = (uInt)text_len; + + /* NOTE: assume zlib doesn't overwrite the input */ + png_ptr->zstream.next_in = (Bytef *)text; + png_ptr->zstream.avail_out = png_ptr->zbuf_size; + png_ptr->zstream.next_out = 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_bytepp old_ptr; + + old_ptr = comp->output_ptr; + + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t) + (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_bytepp)png_malloc(png_ptr, + (png_alloc_size_t) + (comp->max_output_ptr * png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)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_bytepp old_ptr; + + old_ptr = comp->output_ptr; + + /* This could be optimized to realloc() */ + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t)(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_bytepp)png_malloc(png_ptr, + (png_alloc_size_t)(comp->max_output_ptr * + png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)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, comp->input, comp->input_len); + + return; + } + +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + /* The zbuf_size test is because the code below doesn't work if zbuf_size is + * '1'; simply skip it to avoid memory overwrite. + */ + if (comp->input_len >= 2 && comp->input_len < 16384 && png_ptr->zbuf_size > 1) + { + unsigned int z_cmf; /* zlib compression method and flags */ + + /* Optimize the CMF field in the zlib stream. This hack of the zlib + * stream is compliant to the stream specification. + */ + + if (comp->num_output_ptr) + z_cmf = comp->output_ptr[0][0]; + else + z_cmf = png_ptr->zbuf[0]; + + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + unsigned int z_cinfo; + unsigned int half_z_window_size; + png_size_t uncompressed_text_size = comp->input_len; + + z_cinfo = z_cmf >> 4; + half_z_window_size = 1 << (z_cinfo + 7); + + while (uncompressed_text_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 (comp->num_output_ptr) + { + + if (comp->output_ptr[0][0] != z_cmf) + { + int tmp; + + comp->output_ptr[0][0] = (png_byte)z_cmf; + tmp = comp->output_ptr[0][1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + comp->output_ptr[0][1] = (png_byte)tmp; + } + } + else + { + int tmp; + + png_ptr->zbuf[0] = (png_byte)z_cmf; + tmp = png_ptr->zbuf[1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + png_ptr->zbuf[1] = (png_byte)tmp; + } + } + + else + png_error(png_ptr, + "Invalid zlib compression method or flags in non-IDAT chunk"); + } +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ + + /* Write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr, comp->output_ptr[i], + (png_size_t)png_ptr->zbuf_size); + + png_free(png_ptr, comp->output_ptr[i]); + } + + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + + /* 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 */ + png_zlib_release(png_ptr); +} +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ + +/* 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) +{ + 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: +#ifdef PNG_WRITE_16BIT_SUPPORTED + case 16: +#endif + png_ptr->channels = 1; break; + + default: + png_error(png_ptr, + "Invalid bit depth for grayscale image"); + } + break; + + case PNG_COLOR_TYPE_RGB: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + 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: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + 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_complete_chunk(png_ptr, 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; + +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY)) + png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL)) + png_ptr->zlib_text_level = png_ptr->zlib_level; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD)) + png_ptr->zlib_text_method = png_ptr->zlib_method; +#else + png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; + png_ptr->zlib_text_level = png_ptr->zlib_level; + png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level; + png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits; + png_ptr->zlib_text_method = png_ptr->zlib_method; +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ + + /* Record that the compressor has not yet been initialized. */ + png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED; + + png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ +} + +/* 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_const_colorp palette, + png_uint_32 num_pal) +{ + png_uint_32 i; + png_const_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_header(png_ptr, 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) +{ + png_debug(1, "in png_write_IDAT"); + +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + { + /* Optimize the CMF field in the zlib stream. This hack of the zlib + * stream is compliant to the stream specification. + */ + 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) + { + /* Compute the maximum possible length of the datastream */ + + /* Number of pixels, plus for each row a filter byte + * and possibly a padding byte, so increase the maximum + * size to account for these. + */ + unsigned int z_cinfo; + unsigned int half_z_window_size; + png_uint_32 uncompressed_idat_size = png_ptr->height * + ((png_ptr->width * + png_ptr->channels * png_ptr->bit_depth + 15) >> 3); + + /* If it's interlaced, each block of 8 rows is sent as up to + * 14 rows, i.e., 6 additional rows, each with a filter byte + * and possibly a padding byte + */ + if (png_ptr->interlaced) + uncompressed_idat_size += ((png_ptr->height + 7)/8) * + (png_ptr->bit_depth < 8 ? 12 : 6); + + z_cinfo = z_cmf >> 4; + 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] != z_cmf) + { + int tmp; + data[0] = (png_byte)z_cmf; + tmp = data[1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + data[1] = (png_byte)tmp; + } + } + } + + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); + } +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ + + png_write_complete_chunk(png_ptr, png_IDAT, data, length); + png_ptr->mode |= PNG_HAVE_IDAT; + + /* Prior to 1.5.4 this code was replicated in every caller (except at the + * end, where it isn't technically necessary). Since this function has + * flushed the data we can safely reset the zlib output buffer here. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; +} + +/* Write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ + png_debug(1, "in png_write_IEND"); + + png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#ifdef PNG_WRITE_gAMA_SUPPORTED +/* Write a gAMA chunk */ +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ + 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_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); +} +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +/* Write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ + 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_complete_chunk(png_ptr, 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_const_charp name, int compression_type, + png_const_charp profile, int profile_len) +{ + 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_const_bytep)profile ))<<24) | + ((*( (png_const_bytep)profile + 1))<<16) | + ((*( (png_const_bytep)profile + 2))<< 8) | + ((*( (png_const_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_header(png_ptr, 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) + { + comp.input_len = 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_const_sPLT_tp spalette) +{ + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); + png_size_t 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_header(png_ptr, 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, &spalette->depth, (png_size_t)1); + + /* Loop through each palette entry, writing appropriately */ +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (ep = spalette->entries; epentries + 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_const_color_8p sbit, int color_type) +{ + 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_complete_chunk(png_ptr, png_sBIT, buf, size); +} +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +/* Write the cHRM chunk */ +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) +{ + 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_complete_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); + } +} +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +/* Write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha, + png_const_color_16p tran, int num_trans, int color_type) +{ + 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_complete_chunk(png_ptr, png_tRNS, trans_alpha, (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_complete_chunk(png_ptr, 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); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + + png_write_complete_chunk(png_ptr, 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_const_color_16p back, int color_type) +{ + 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_complete_chunk(png_ptr, 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); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + + return; + } + + png_write_complete_chunk(png_ptr, 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_complete_chunk(png_ptr, 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_const_uint_16p hist, int num_hist) +{ + 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_header(png_ptr, 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_const_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_const_charp ikp; + 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 (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++) + { + if ((png_byte)*ikp < 0x20 || + ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1)) + { + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x, + (png_byte)*ikp); + png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1"); + *dp = ' '; + } + + else + { + *dp = *ikp; + } + } + *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); + 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_const_charp key, png_const_charp text, + png_size_t text_len) +{ + 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_header(png_ptr, 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_const_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_const_charp key, png_const_charp text, + png_size_t text_len, int compression) +{ + png_size_t key_len; + png_byte buf; + 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_header(png_ptr, 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 = (png_byte)compression; + + /* Write compression */ + png_write_chunk_data(png_ptr, &buf, (png_size_t)1); + + /* Write the compressed data */ + comp.input_len = text_len; + 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_const_charp key, + png_const_charp lang, png_const_charp lang_key, png_const_charp text) +{ + 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_header(png_ptr, 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_const_bytep)new_lang : cbuf), + (png_size_t)(lang_len + 1)); + + png_write_chunk_data(png_ptr, (lang_key ? (png_const_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) +{ + 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_complete_chunk(png_ptr, 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_const_charp units, + png_charpp params) +{ + png_size_t purpose_len, units_len, total_len; + png_size_tp 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_size_tp)png_malloc(png_ptr, + (png_alloc_size_t)(nparams * png_sizeof(png_size_t))); + + /* 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 += params_len[i]; + } + + png_debug1(3, "pCAL total length = %d", (int)total_len); + png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, 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_const_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_const_bytep)params[i], 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 */ +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width, + png_const_charp height) +{ + 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_complete_chunk(png_ptr, png_sCAL, buf, total_len); +} +#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) +{ + 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_complete_chunk(png_ptr, 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_const_timep mod_time) +{ + 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_complete_chunk(png_ptr, 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 */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_alloc_size_t buf_size; + int usr_pixel_depth; + + png_debug(1, "in png_write_start_row"); + + usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; + buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; + + /* 1.5.6: added to allow checking in the row write code. */ + png_ptr->transformed_pixel_depth = png_ptr->pixel_depth; + png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; + + /* Set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, 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_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, buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + 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 = (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 = (png_bytep)png_malloc(png_ptr, + 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_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT); + 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 */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + static PNG_CONST png_byte 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); + } + + png_zlib_release(png_ptr); + 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 */ + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + static PNG_CONST png_byte 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) */ + if (pass < 6) + { + /* 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. + */ +static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row, + png_size_t row_bytes); + +#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_size_t row_bytes = row_info->rowbytes; +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + int num_p_filters = 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_size_t 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_size_t 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_size_t 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_size_t 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_size_t 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_size_t 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_size_t 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_size_t 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, row_info->rowbytes+1); + +#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. */ +static void +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row, + png_size_t avail/*includes filter byte*/) +{ + 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 = 0; + /* Repeat until we have compressed all the data */ + do + { + int ret; /* Return of zlib */ + + /* Record the number of bytes available - zlib supports at least 65535 + * bytes at one step, depending on the size of the zlib type 'uInt', the + * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h). + * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e. + * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a + * uInt. ZLIB_IO_MAX can be safely reduced to cause zlib to be called + * with smaller chunks of data. + */ + if (png_ptr->zstream.avail_in == 0) + { + if (avail > ZLIB_IO_MAX) + { + png_ptr->zstream.avail_in = ZLIB_IO_MAX; + avail -= ZLIB_IO_MAX; + } + + else + { + /* So this will fit in the available uInt space: */ + png_ptr->zstream.avail_in = (uInt)avail; + avail = 0; + } + } + + /* 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); + } + /* Repeat until all data has been compressed */ + } while (avail > 0 || png_ptr->zstream.avail_in > 0); + + /* 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/plugins/FreeImage/src/LibTIFF/ChangeLog b/plugins/FreeImage/src/LibTIFF/ChangeLog new file mode 100644 index 0000000000..f3dfe26b0b --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/ChangeLog @@ -0,0 +1,4849 @@ +2011-04-09 Bob Friesenhahn + + * libtiff 3.9.5 released. + +2011-04-09 Bob Friesenhahn + + * configure.ac: Should use AC_CANONICAL_HOST since host specifies + the run-time target whereas target is used to specify the final + output target if the package is a build tool (like a compiler), + which libtiff is not. Resolves libtiff bug 2307 "Use + AC_CANONICAL_HOST macro". + +2011-04-02 Bob Friesenhahn + + * tools/fax2ps.c (main): Use tmpfile() rather than mkstemp() since + it is much more portable. Tmpfile is included in ISO/IEC + 9899:1990 and the WIN32 CRT. + +2011-03-21 Frank Warmerdam + + * libtiff/tiffiop.h: avoid declaring int64/uint64 on AIX with XLC + where they are already available. (#2301) + + * libtiff/tif_thunder.c: Correct potential buffer overflow with + thunder encoded files with wrong bitspersample set. The libtiff + development team would like to thank Marin Barbella and TippingPoint's + Zero Day Initiative for reporting this vulnerability (ZDI-CAN-1004, + CVE-2011-1167). + http://bugzilla.maptools.org/show_bug.cgi?id=2300 + +2011-03-10 Frank Warmerdam + + * libtiff/tif_fax3.h: Fix to last change allowing zero length + runs at the start of a scanline - needed for legal cases. + +2011-03-02 Frank Warmerdam + + * libtiff/tif_fax3.h: Protect against a fax VL(n) codeword commanding + a move left. Without this, a malicious input file can generate an + indefinitely large series of runs without a0 ever reaching the right + margin, thus overrunning our buffer of run lengths. Per CVE-2011-0192. + This is a modified version of a patch proposed by Drew Yao of Apple + Product Security. It adds an unexpected() report, and disallows the + equality case, since emitting a run without increasing a0 still allows + buffer overrun. + +2011-02-25 Andrey Kiselev + + * libtiff/tif_dirwrite.c: Avoid undefined behaviour when casting from + float to unsigned integer in TIFFWriteRationalArray() as reported by + Kareem Shehata. + +2011-01-03 Lee Howard + + * libtiff/tif_jpeg.c: Fix regressions with 2 and 3 band images + caused by commit on 2010-12-14. Submitted by e-mail from + Even Rouault + +2010-12-31 Olivier Paquet + + * libtiff/tif_dirread.c: Allow reading directories where + TIFFTAG_SMINSAMPLEVALUE and TIFFTAG_SMAXSAMPLEVALUE values differ for each + channel. The min/max of all channels is used as appropriate. + +2010-12-14 Lee Howard + + * libtiff/tif_dirread.c: tolerate some cases where + FIELD_COLORMAP is missing + http://bugzilla.maptools.org/show_bug.cgi?id=2189 + +2010-12-14 Lee Howard + + * libtiff/tif_strip.c: use TIFFGetFieldDefaulted instead + of TIFFGetField when we assume that it will succeed + http://bugzilla.maptools.org/show_bug.cgi?id=2215 + +2010-12-14 Lee Howard + + * tools/gif2tiff.c: fix buffer overrun + http://bugzilla.maptools.org/show_bug.cgi?id=2270 + +2010-12-14 Lee Howard + + * libtiff/tif_jpeg.c: reduce usage of JCS_UNKNOWN in order + to improve compatibility with various viewers + submitted by e-mail from Dwight Kelly + +2010-12-13 Lee Howard + + * tools/fax2ps.c: be consistent with page-numbering + http://bugzilla.maptools.org/show_bug.cgi?id=2225 + +2010-12-13 Lee Howard + + * libtiff/tif_dirread.c: fix needless tag ordering warning + http://bugzilla.maptools.org/show_bug.cgi?id=2210 + +2010-12-13 Lee Howard + + * libtiff/tif_color.c: prevent crash in handling bad TIFFs + resolves CVE-2010-2595 + http://bugzilla.maptools.org/show_bug.cgi?id=2208 + +2010-12-13 Lee Howard + + * tools/tiffcrop.c: new release by Richard Nolde + http://bugzilla.maptools.org/show_bug.cgi?id=2004 + +2010-12-12 Lee Howard + + * tools/tiff2pdf.c: fix colors for images with RGBA + interleaved data + http://bugzilla.maptools.org/show_bug.cgi?id=2250 + +2010-12-11 Lee Howard + + * tools/tiff2pdf.c: remove invalid duplication for Lab + http://bugzilla.maptools.org/show_bug.cgi?id=2162 + +2010-12-11 Lee Howard + + * libtiff/tif_jpeg.c: fix use of clumplines calculation + http://bugzilla.maptools.org/show_bug.cgi?id=2149 + +2010-12-11 Lee Howard + + * tools/fax2ps.c: replace unsafe tmpfile() with mkstemp() + http://bugzilla.maptools.org/show_bug.cgi?id=2118 + +2010-12-11 Lee Howard + + * tools/tiff2pdf.c: add fill-page option + http://bugzilla.maptools.org/show_bug.cgi?id=2051 + +2010-12-11 Lee Howard + + * libtiff/tif_dirread.c: modify warnings + http://bugzilla.maptools.org/show_bug.cgi?id=2016 + +2010-12-11 Lee Howard + + * libtiff/tif_ojpeg.c: fix buffer overflow on problem data + http://bugzilla.maptools.org/show_bug.cgi?id=1999 + +2010-12-11 Lee Howard + + * libtiff/tif_ojpeg.c: fix crash when reading a TIFF with a zero + or missing byte-count tag + * tools/tiffsplit.c: abort when reading a TIFF without a byte-count + per http://bugzilla.maptools.org/show_bug.cgi?id=1996 + +2010-12-08 Lee Howard + + * libtiff/tif_dirread.c: fix crash when reading a badly-constructed + TIFF per http://bugzilla.maptools.org/show_bug.cgi?id=1994 + +2010-12-07 Lee Howard + + * libtiff/tif_jpeg.c, libtiff/tif_strip.c: apply patch for + CVE-2010-3087 per bug + http://bugzilla.maptools.org/show_bug.cgi?id=2140 + +2010-12-06 Lee Howard + + * libtiff/tif_open.c: Fix mode check before opening a file. + http://bugzilla.maptools.org/show_bug.cgi?id=1906 + +2010-09-25 Lee Howard + + * tools/tiff2ps.c: improvements and enhancements from Richard Nolde + with additional command line options for Document Title, + Document Creator, and Page Orientation + +2010-07-13 Bob Friesenhahn + + * tools/tiffcrop.c: Patch from Richard Nolde to avoid a + potentially unterminated buffer due to using an exceptionally long + file name. + +2010-07-08 Andrey Kiselev + + * tools/tiff2pdf.c: Fixed ID buffer filling in + t2p_write_pdf_trailer(), thanks to Dmitry V. Levin. + +2010-07-07 Andrey Kiselev + + * libtiff/tif_dirread.c: Really reset the tag count in CheckDirCount() + to expected value as the warning message suggests. As per bug + http://bugzilla.maptools.org/show_bug.cgi?id=1963 + + * tools/tiffdump.c: Avoid integer overflows computing the buffer size + for large directories. As per bug + http://bugzilla.maptools.org/show_bug.cgi?id=2218 + +2010-07-06 Andrey Kiselev + + * tools/tiffset.c: Properly handle TIFFTAG_PAGENUMBER, + TIFFTAG_HALFTONEHINTS, TIFFTAG_YCBCRSUBSAMPLING, TIFFTAG_DOTRANGE + which should be set by value. + + * libtiff/tif_dirinfo.c: Don't use assertions in _TIFFFieldWithTag() + and _TIFFFieldWithName() if the tag is not found in the tag table. + This should be normal situation and returned NULL value should be + properly handled by the caller. + + * libtiff/{tif_dirwrite.c, tif_print.c}: Properly handle "DotRange" + tag as it can be either byte or short size and should be set and read + by value, not as an array. As per bug + http://bugzilla.maptools.org/show_bug.cgi?id=2116 + +2010-07-02 Andrey Kiselev + + * libtiff/tif_getimage.c: Avoid wrong math du to the signed/unsigned + integer type conversions. As per bug + http://bugzilla.maptools.org/show_bug.cgi?id=2207 + + * tools/{tiff2bw.c, thumbnail.c, pal2rgb.c}: Fix the count for + WhitePoint tag as per bug + http://bugzilla.maptools.org/show_bug.cgi?id=2042 + + * tools/tiffdump.c: Use PrintData() function instead of + PrintByte/Short/Long(). Should fix an issue reported at + http://bugzilla.maptools.org/show_bug.cgi?id=2116 + + * libtiff/tif_getimage.c: Check the number of samples per pixel when + working with YCbCr image in PickContigCase(). As per bug + http://bugzilla.maptools.org/show_bug.cgi?id=2216 + + * libtiff/tif_dir.c: Set the bogus post-decoding hook when processing + TIFFTAG_BITSPERSAMPLE in _TIFFVSetField() for the case of 8 bit when + we don't need any post-processing. That helps to reset the hook if we + previously set this field to some other value and the hook was + initialized accordingly. As per bug + http://bugzilla.maptools.org/show_bug.cgi?id=2035 + +2010-06-30 Andrey Kiselev + + * tools/tiff2pdf.c: Better generation of ID field in + t2p_write_pdf_trailer(). Get rid of GCC aliasing warnings. + + * tools/tiff2pdf.c: Fixed computation of the tile buffer size when + converting JPEG encoded tiles. + + * tools/tiff2pdf.c: Better handling of string fields, use static + string buffers instead of dynamically allocated, use strncpy() instead + of strcpy(), control the string lengths. + +2010-06-25 Andrey Kiselev + + * tools/tiffcp.c: Initialize buffer arrays with zero to avoid + referencing to uninitialized memory in some cases (e.g. when tile size + set bigger than the image size). + +2010-06-15 Bob Friesenhahn + + * tools/tiffcrop.c: Patch from Richard Nolde. Reject YCbCr + subsampled data since tiffcrop currently doesn't support it. Fix + JPEG support. + +2010-06-15 Bob Friesenhahn + + * libtiff 3.9.4 released. + +2010-06-13 Frank Warmerdam + + * libtiff/tif_jpeg.c: avoid re-preparing jpeg tables unnecessarily + (gdal #3633, libtiff #2135). + + * libtiff/tif_dirread.c: Fixed bad handling of out of order tags + definated late by a codec (#2210) + + * libtiff/tif_dirread.c: Fixed inadequate validation of the + SubjectDistance field (#2212). + + * tiff2pdf.c: Fix assorted bugs in tiff2pdf: missing "return" + in t2p_read_tiff_size() causes t2p->tiff_datasize to be set entirely + wrong for COMPRESSION_JPEG case, resulting in memory stomp if actual + size is larger. Also, there are a bunch of places that try to + memset() a malloc'd buffer before checking for malloc failure, which + would result in core dump if there actually were a failure. (#2211) + +2010-06-11 Bob Friesenhahn + + * tools/tiff2rgba.c: Applied portion of patch (from Tom Lane) + which was left out in order to fully resolve "CVE-2009-2347 + libtiff: integer overflows in various inter-color space conversion + tools". http://bugzilla.maptools.org/show_bug.cgi?id=2079 + + * libtiff/tiffiop.h (TIFFSafeMultiply): Need more castings to + avoid compiler warnings if parameter types are not sign + consistent. + + * tools/tiffcrop.c: Applied patch from Richard Nolde: Corrected + European page size dimensions. Added an option to allow the user + to specify a custom page size on the command line. Fix the case + where a page size specified with a fractional part was being + coerced to an integer by retyping the variables that define the + paper size. + + * libtiff 3.9.3 released. + + * tools/tiffcp.c (tiffcp): Applied Tom Lane's patch to reject + YCbCr subsampled data since tiffcp currently doesn't support it. + http://bugzilla.maptools.org/show_bug.cgi?id=2097 + + * Update libtool to version 2.2.10. + +2010-06-10 Bob Friesenhahn + + * libtiff/tiffiop.h (TIFFSafeMultiply): Work properly if + multiplier is zero. + +2010-06-09 Bob Friesenhahn + + * libtiff/tif_dir.h: Restore ReferenceBlackWhite as a non-custom + field. This avoids a multi-thread reentrancy problem as well as + fixing output of wrong tag value due to redundant definitions for + the same tag in the tiffFieldInfo[] array. Resolves + http://bugzilla.maptools.org/show_bug.cgi?id=2185 + + * libtiff/tif_fax3.c (Fax3SetupState): Yesterday's fix for + CVE-2010-1411 was not complete. + + * libtiff/tiffiop.h (TIFFSafeMultiply): New macro to safely + multiply two integers. Returns zero if there is an integer + overflow. + + * tools/tiffcp.c (main): Fix more TIFF handle leaks. + + * libtiff/tif_read.c (TIFFReadBufferSetup): Skip allocating + tif_rawdata if tif_rawdatasize becomes zero. + +2010-06-08 Bob Friesenhahn + + * tools/tiffcrop.c: Removed duplicated macros such as + TIFFhowmany(). + + * Update libtool to version 2.2.8. + + * libtiff/tif_fax3.c (Fax3SetupState): Avoid under-allocation of + buffer due to integer overflow in TIFFroundup() and several other + potential overflows. In conjunction with the fix to TIFFhowmany(), + fixes CVE-2010-1411. + + * libtiff/tiffiop.h (TIFFhowmany): Return zero if parameters would + result in an integer overflow. This causes TIFFroundup() to also + return zero if there would be an integer overflow. + + * libtiff/tif_read.c (TIFFReadBufferSetup): Return an error if + tif_rawdatasize becomes zero due to an initial raw size of zero or + an overflow reported by TIFFroundup(). + + * libtiff/tif_ojpeg.c (OJPEGReadBufferFill): Report an error and + avoid a crash if the input file is so broken that the strip + offsets are not defined. + + * tools/tiffcp.c (main): tiffcp should not leak memory if an error + is reported when reading the input file. + + * libtiff/tif_aux.c (_TIFFCheckRealloc): Produce a fully detailed + error message string. + + * Add an emacs formatting mode footer to all source files so that + emacs can be effectively used. + +2010-06-03 Oliver Chen Feng + + * libtiff/tools/tiffcp.c: add a new option -x to force merged tiff + file PAGENUMBER value in sequence for users who care the page + sequence, this will also prevent tiff2pdf from creating pdf file from + the merged tiff file with wrong page sequence. + +2010-05-07 Frank Warmerdam + + * libtiff/tif_jpeg.c: Ensure that quality is always set in + JPEGPreEncode(), not just when we want to output local tables. + Otherwise the quality used during compression may not be right and + might not match the tables in the tables tag. This bug only occurs + when seeking between directories in the midst of writing blocks. + http://trac.osgeo.org/gdal/ticket/3539 + +2010-05-05 Olivier Paquet + + * libtiff/tif_print.c: Have TIFFTAG_REFERENCEBLACKWHITE always print 6 + floats instead of 2*SamplesPerPixel. + http://bugzilla.maptools.org/show_bug.cgi?id=2186 + * man/TIFFGetField.3tiff, man/TIFFSetField.3tiff: Fixed doc to reflect the + fact that libtiff considers TIFFTAG_REFERENCEBLACKWHITE to be 6 floats. + +2010-04-10 Bob Friesenhahn + + * tools/ppm2tiff.c (main): While case for parsing comment line + requires extra parenthesis to work as expected. Reported by + Thomas Sinclair. + +2010-02-22 Lee Howard + + * libtiff/tif_jpeg.c: Do not generate a JPEGTables tag when creating + the JPEG TIFF as is is not required in order to prevent it from + being unused and filled with invalid data. (Leave it to be + generated by later activity.) + http://bugzilla.maptools.org/show_bug.cgi?id=2135 + * tools/tiff2pdf.c: Write the JPEG SOI headers into the TIFF strip + data rather than skipping them. This fixes the ability to view in + Acrobat Reader, Evince, and Ghostscript. + http://bugzilla.maptools.org/show_bug.cgi?id=2135 + * libtiff/tif_fax3.c: Don't return error on badly-terminated MMR + strips. + http://bugzilla.maptools.org/show_bug.cgi?id=2029 + +2010-01-06 Frank Warmerdam + + * libtiff/tif_dir.c: Ensure tile and scanline sizes are reset + when moving to new directories. + http://bugzilla.maptools.org/show_bug.cgi?id=1936 + +2009-12-03 Frank Warmerdam + + * libtiff/tif_jpeg.c: Fix a couple of issues that trigger failures in + some cases when using TIFFReadScanline() with JPEG compressed + subsampled ycbcr images. + http://bugzilla.maptools.org/show_bug.cgi?id=1936 + +2009-11-04 Bob Friesenhahn + + * libtiff 3.9.2 released. + +2009-11-03 Bob Friesenhahn + + * tools/tiffcrop.c: Updated tiffcrop from Richard Nolde. This + version has undergone substantial testing with arbitrary sample + bit depths. Also eliminates GCC compilation warnings. + +2009-11-02 Bob Friesenhahn + + * port/libport.h: Added header file for porting prototypes and + extern declarations. + +2009-10-31 Bob Friesenhahn + + * libtiff/tif_dirwrite.c (TIFFWriteAnyArray): Add missing break + statement so writing an array of TIFF_DOUBLE works. + +2009-10-29 Bob Friesenhahn + + * libtiff/tif_dirread.c: Eliminate GCC "dereferencing type-punned + pointer" warnings. + +2009-10-28 Bob Friesenhahn + + * html/tools.html: Add manual page links, and a summary + description of tiffcrop. + +2009-10-07 Bob Friesenhahn + + * configure.ac: x86_64 should use the same fill order as i386. + +2009-09-24 Bob Friesenhahn + + * tools/tiffcrop.c, man/tiffcrop.1: New tiffcrop from Richard + Nolde. Major updates to add significant functionality for reading + and writing tile based images with bit depths not a multiple of 8 + which cannot be handled by tiffcp. + +2009-09-03 Bob Friesenhahn + + * libtiff/tif_ojpeg.c (OJPEGWriteHeaderInfo): IJG JPEG 7 needs + do_fancy_upsampling=FALSE in order to read raw data. Resolves + "Bug 2090 - OJPEG crash with libjpeg v7". + http://bugzilla.maptools.org/show_bug.cgi?id=2090 + +2009-08-30 Bob Friesenhahn + + * contrib/iptcutil/iptcutil.c, + libtiff/tif_getimage.c,libtiff/tif_jpeg.c,libtiff/tif_ojpeg.c,tools/tiffcrop.c,tools/tiffgt.c: + Applied patch from Oden Eriksson to allow building with GCC using + the "-Wformat -Werror=format-security" flags. + +2009-08-28 Bob Friesenhahn + + * libtiff 3.9.1 released. + +2009-08-28 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff/tif_lzw.c: Fix buffer underflow bug. + http://bugzilla.maptools.org/show_bug.cgi?id=2065 + +2009-06-03 Frank Warmerdam + + * 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 + + * libtiff/tif_luv.c: Fix handling of tiled logluv images. + http://bugzilla.maptools.org/show_bug.cgi?id=2005 + +2009-01-23 Frank Warmerdam + + * 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 + + * tools/tiffsplit.c: fix sampleformat to be shortv instead of longv. + +2009-01-12 Bob Friesenhahn + + * tools/tiff2ps.c: Remove spurious message printed to stderr. + +2009-01-11 Bob Friesenhahn + + * 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 + + * 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 + + * 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 + + * 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 + + * tools/tiffcrop.c, man/tiffcrop.1: A major update from Richard + Nolde. + +2008-12-21 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * libtiff/tif_jbig.c: Support the JBIG-KIT 2.0 (compatibility with + the older versions retained). + +2008-09-05 Andrey Kiselev + + * tools/tiffsplit.c: Use dynamically allocated array instead of static + when constructing output file names. + +2008-09-03 Andrey Kiselev + + * 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 + + * 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 + + * tif_fax3.c: Make find0span() and find1span() non-inline to + make MSVC 6.0 compiler happy. + +2007-11-26 Frank Warmerdam + + * tif_fax3.c: fix leak of FAXCS state (per bug 1603). + +2007-11-23 Andrey Kiselev + + * configure.com, libtiff/tif_vms.c: Better OpenVMS support. Patches + from Alexey Chupahin. + +2007-11-22 Frank Warmerdam + + * 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 + + * tools/tiff2pdf.c: Fixed setting of alpha value per report on list. + +2007-09-13 Frank Warmerdam + + * 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 + + * 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 + + * libtiff 3.9.0beta released. + +2007-07-12 Andrey Kiselev + + * tools/tiff2pdf.c: Added missed extern optind as per bug + + http://bugzilla.remotesensing.org/show_bug.cgi?id=1567 + +2007-07-03 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * contrib/addtiffo/tif_overview.c: Fix problems with odd sized output + blocks in TIFF_DownSample_Subsampled() (bug 1542). + +2007-04-06 Frank Warmerdam + + * 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 + + * 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 + + * libtiff/tif_fax3.c: "inline static" -> "static inline" for IRIC CC. + +2007-03-07 Joris Van Damme + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * tif_msdos.c: Avoid handle leak for failed opens. c/o Thierry Pierron + +2006-07-19 Frank Warmerdam + + * 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 + + * 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 + + * {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 + + * 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 + + * tools/tiff2pdf.c: Fix handling of -q values. + http://bugzilla.remotesensing.org/show_bug.cgi?id=587 + +2006-06-17 Frank Warmerdam + + * 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 + + * 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 + + * {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 + + * libtiff/{tif_dirinfo.c, tif_print.c} : Fix crash in + TIFFPrintDirectory(). Joris Van Damme authored the fix. + +2006-04-21 Andrey Kiselev + + * 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 + + * 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 + + * nmake.opt: use /EHsc for VS2005 compatibility. Also define + _CRT_SECURE_NO_DEPRECATE to avoid noise on VS2005. + +2006-04-12 Joris Van Damme + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * contrib/addtiffo/tif_ovrcache.c: bugfix to correctly pass size + of last truncated strip data to TIFFWriteEncodedStrip + +2006-03-25 Joris Van Damme + + * libtiff/{tif_jpeg.c, tif_strip.c}: bugfix of tif_jpeg decode raw + +2006-03-25 Joris Van Damme + + * 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 + + * libtiff 3.8.2 released. + + * tools/Makefile.am: Use runtime paths linker flags when rpath + option enabled. + +2006-03-21 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff 3.8.1 released. + +2006-03-07 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * tools/tiff2pdf.c: Fixed support for non-YCbCr encoded JPEG + compressed TIFF files, per submission from Dan Cobra. + +2006-02-07 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * libtool related stuff updated from the 2.1a branch. + +2006-01-11 Frank Warmerdam + + * 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 + + * configure.ac: Fix with_default_strip_size comparison as reported + by Norihiko Murase. + +2006-01-08 Bob Friesenhahn + + * 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 + + * 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 + + * 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 + + * libtiff 3.8.0 released. + +2005-12-28 Bob Friesenhahn + + * 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 + + * html/{index.html, support.hml, libtiff.html}: Cleaned up HTML + +2005-12-27 Andrey Kiselev + + * libtiff/tiffio.h: Added VC_EXTRALEAN definition before including + windows.h, to reduce the compile time. + +2005-12-26 Bob Friesenhahn + + * libtiff/tif_jpeg.c: Improve compilation under MinGW. + +2005-12-26 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff/{tif_dir.c, tif_dir.h, tif_print.c}: Make RichTIFFIPTC, + Photoshop and ICCProfile tags custom. + +2005-12-21 Joris Van Damme + + * 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 + + * 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 + + * contrib/addtiffo/*: Major upgrade by Joris to support subsampled + YCbCr images in jpeg compressed TIFF files. + +2005-12-14 Andrey Kiselev + + * tools/tiffcp.c: Return non-zero status when reading fails (again). + +2005-12-13 Andrey Kiselev + + * tools/tiffcp.c: Return non-zero status when reading fails. + +2005-12-12 Andrey Kiselev + + * libtiff/{tif_dir.h, tiff.h}: Added more EXIF tags. + +2005-12-09 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff/libtiff.def, tiffiop.h, tiffio.h: Made TIFFFreeDirectory + public. + +2005-10-31 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * tif_write.c: fixed setting of planarconfig as per bug report + on the mailing list from Joris. + +2005-10-07 Andrey Kiselev + + * 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 + + * html/support.html: Fixed link to documentation on Greg Ward's + LogLuv TIFF format. + +2005-09-28 Andrey Kiselev + + * tools/tiffdump.c: Fixed crash when reading malformed tags. + +2005-09-20 Andrey Kiselev + + * tools/tiff2pdf.c: Added missed 'break' statement as per bug + http://bugzilla.remotesensing.org/show_bug.cgi?id=932 + +2005-09-12 Andrey Kiselev + + * 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 + + * libtiff/tif_open.c: reintroduce seek to avoid problem on solaris. + +2005-09-05 Frank Warmerdam + + * 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 + + * libtiff/tif_print.c: avoid signed/unsigned warning. + + * libtiff/tif_dirread.c: removed unused variable. + +2005-07-30 Frank Warmerdam + + * 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 + + * 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 + + * libtiff/tif_dir.c: More improvements in the "pass by value" part of + the custom tags handling code. + +2005-07-26 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff 3.7.3 released. + + * configure, configure.ac: Do not use empty -R option when linking + with --enable-rpath. + +2005-07-01 Andrey Kiselev + + * 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 + + * 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 + + * libtiff/tif_dirinfo.c: Added support for ClipPath, XClipPathUnits + and YClipPathUnits tags. + +2005-06-07 Andrey Kiselev + + * contrib/addtiffo/tif_ovrcache.c: Properly extract tile/strip size; + use pixel sized shift in contigous case. + +2005-06-06 Andrey Kiselev + + * contrib/addtiffo/{tif_overview.c, tif_ovrcache.c, tif_ovrcache.h}: + Make overviews working for contiguos images. + +2005-06-03 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * tools/tiffsplit.c: Check for JPEGTables tag presence before copying. + +2005-05-06 Frank Warmerdam + + * 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 + * 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 + + * 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 + + * tools/tiffdither.c: Copy the PhotometricInterpretation tag from the + input file. + +2005-04-15 Andrey Kiselev + + * libtiff/tif_predict.c: Added ability to encode floating point + predictor, as per TIFF Technical Note 3. + +2005-04-14 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * configure.ac, libtiff/Makefile.am: Use libtool machinery to pass + rpath option. + +2005-03-21 Andrey Kiselev + + * libtiff/{tif_dir.c, tif_print.c}: Handle all data types in custom + tags. + +2005-03-18 Andrey Kiselev + + * 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 + + * 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 + + * libtiff 3.7.2 released. + +2005-03-09 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff/tiff.h (TIFFTAG_TILEWIDTH): Corrected description. + (TIFFTAG_TILELENGTH): Corrected description. + +2005-01-30 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff/tif_getimage.c: #define A1 bracketing for clean build on + SunPro compiler. + +2004-12-11 Bob Friesenhahn + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff/tif_unix.c: Make UNIX module compilable (and usable) + on Windows. + + * nmake.opt: Add missed DLLNAME variable. + +2004-11-26 Frank Warmerdam + + * libtiff/makefile.vc: make it easier to rename the libtiff DLL. + +2004-11-24 Andrey Kiselev + + * 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 + + * libtiff/tif_error.c: fixed TIFFerror call to be TIFFError. + +2004-11-21 Frank Warmerdam + + * html/document.html: Updated Adobe web links as per email from Joris. + +2004-11-21 Andrey Kiselev + + * 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 . + +2004-11-13 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * libtiff/tif_color.c: Division by zero fixed (Hans Petter Selasky). + +2004-11-07 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff/tif_next.c: avoid use of u_long and u_char types. Bug 653. + +2004-11-02 Frank Warmerdam + + * tools/tiff2rgba.c: removed extra newlines in usage message. + +2004-10-30 Andrey Kiselev + + * 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 + + * libtiff/tiffiop.h: added fallback definition of assert() if we + don't have assert.h. + +2004-10-29 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * configure, configure.ac: Added --enable-rpath option to embed linker + paths into library binary. + +2004-10-26 Andrey Kiselev + + * 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 + + * libtiff 3.7.0 released. + +2004-10-15 Bob Friesenhahn + + * 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 + + * man/bmp2tiff.1: Added manual page for bmp2tiff utility. + +2004-10-13 Bob Friesenhahn + + * 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 + + * 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 + + * 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 + + * libtiff/tif_dirinfo.c: Type of the TIFFTAG_SUBIFD field changed + to TIFF_IFD. + +2004-10-10 Andrey Kiselev + + * tools/bmp2tif.c: Check the space allocation results. + +2004-10-09 Andrey Kiselev + + * 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 + + * 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 + + * contrib/iptcutil/README: Added the missing README which goes + along with iptcutil. + +2004-10-03 Andrey Kiselev + + * libtiff/tif_compress.c: Improved error reporting in + TIFFGetConfiguredCODECs() (Dmitry V. Levin). + +2004-10-02 Andrey Kiselev + + * 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 + + * libtiff/tif_open.c: added a more informative message if a BigTIFF + file is opened. + +2004-09-30 Frank Warmerdam + + * 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 + + * 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 + + * libtiff/tif_getimage.c: Check for allocated buffers before clearing + (Dmitry V. Levin). + +2004-09-26 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * libtiff/tif_dirread.c: Applied patch from Dmitry V. Levin to fix + possible integer overflow in CheckMalloc() function. + +2004-09-22 Andrey Kiselev + + * libtiff/{tiffiop.h, tif_strip.c}: Use TIFFhowmany8() macro instead + of plain TIFFhowmany() where appropriate. + +2004-09-21 Andrey Kiselev + + * libtiff/tif_getimage.c: Initialize arrays after space allocation. + +2004-09-19 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * configure.ac, acinclude.m4, aclocal.m4: New macros to detect GLUT + libraries. + +2004-09-11 Bob Friesenhahn + + * 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 + + * html/internals.html: Split off a discussion of adding new tags + into addingtags.html. + +2004-09-10 Andrey Kiselev + + * 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 + + * 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 + + * libtiff/tif_dirread.c: Use memcpy() function instead of pointer + assigning magic in TIFFFetchFloat(). + +2004-09-01 Andrey Kiselev + + * 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 + + * 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 + + * tools/tiff2pdf.c: More fixes for bug + + http://bugzilla.remotesensing.org/show_bug.cgi?id=590 + + from Ross Finlayson. + +2004-08-23 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff/tiffio.h: Revert thandle_t back to void* type. + +2004-07-11 Andrey Kiselev + + * libtiff/{tif_read.c, tif_tile.c, tif_strip.c}: Fixes in error + messages, as suggested by Bernd Herd. + +2004-07-03 Andrey Kiselev + + * 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 + + * tools/bmp2tiff.c: Add missed RawsPerStrip setting. + +2004-06-08 Andrey Kiselev + + * tools/bmp2tiff.c: Added new utility to convert Windows BMP files + into TIFFs. + +2004-06-07 Andrey Kiselev + + * libtiff 3.7.0alpha released. + +2004-06-06 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * tools/tiffsplit.c: Don't forget to copy Photometric + Interpretation tag. + +2004-05-20 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * libtiff/tif_strip.c: Never return 0 from the + TIFFNumberOfStrips(). + +2004-04-29 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * libtiff/tif_open.c: close clientdata if TIFFClientOpen() fails + via bad2. + +2004-03-26 Andrey Kiselev + + * 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 + + * {many}: The first attempt to switch to autotools. + +2004-03-03 Andrey Kiselev + + * 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 + + * tools/ycbcr.c: fixed main() declaration as per: + http://bugzilla.remotesensing.org/show_bug.cgi?id=513 + +2004-02-26 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * libtiff/libtiff.def: Added TIFFCurrentDirOffset, TIFFWriteCheck, + TIFFRGBAImageOK, and TIFFNumberOfDirectories as suggested by + Scott Reynolds. + +2004-01-29 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * tools/tiffcp.c: Fixed problem with wrong Photometric setting for + non-RGB images. + +2003-12-31 Andrey Kiselev + + * 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 + + * libtiff 3.6.1 released. + +2003-12-24 Andrey Kiselev + + * config.guess, config.sub: Updated from the recent upstream. + +2003-12-22 Andrey Kiselev + + * 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 + + * 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 + + * libtiff/{tif_getimage.c, tiffio.h}: Avoid warnings. + + * libtiff/makefile.vc, tools/makefile.vc: Support for IJG JPEG + library. + +2003-12-06 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * tools/tiff2pdf.c: Some bugs fixed. + +2003-11-27 Andrey Kiselev + + * 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 + + * /man/tiff2pdf.1: File added to repository. + +2003-11-26 Andrey Kiselev + + * Makefile.in, /tools/{Makefile.in, makefile.vc}: + Added support fpr tiff2pdf utility. + +2003-11-25 Ross Finlayson + + * /tools/tiff2pdf.c: File added to repository. + +2003-11-22 Andrey Kiselev + + * /tools/raw2tiff.c: sqrtf() replaced with sqrt(). + +2003-11-21 Andrey Kiselev + + * /tools/raw2tiff.c: #include 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 + + * 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 + + * tif_dirread.c: do not mark all anonymously defined tags to be + IGNOREd. + +2003-11-17 Andrey Kiselev + + * contrib/pds/{tif_pdsdirread.c, tif_pdsdirwrite.c}: Use + TIFFDataWidth() function insted of tiffDataWidth array. + +2003-11-16 Andrey Kiselev + + * libtiff/{tiff.h, tif_dirinfo.c}: Added support for IFD (13) + datatype, intruduced in "Adobe PageMaker TIFF Tech. Notes". + +2003-11-15 Frank Warmerdam + + * Makefile.in: fixed missing backslash for tif_color.c in list. + +2003-11-13 Andrey Kiselev + + * 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 + + * 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 + + * tools/raw2tiff.c: Implemented image size guessing using + correlation coefficient calculation between two neighbour lines. + +2003-11-09 Frank Warmerdam + + * 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 + + * libtiff/tiffiop.h: New macros: TIFFmax, TIFFmin and TIFFrint. + +2003-11-07 Andrey Kiselev + + * libtiff/{tiffio.h, tif_strip.c}, man/{TIFFstrip.3t, libtiff.3t}: + Added TIFFRawStripSize() function as suggested by Chris Hanson. + +2003-11-03 Andrey Kiselev + + * 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 + + * libtiff/libtiff.def: Added TIFFReadRGBAImageOriented. + + * html/build.html: Added note about GNU make requirement. + +2003-10-25 Andrey Kiselev + + * 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 + + * /tools/tiff2ps.c: #include replaced with the + #include . + +2003-10-16 Andrey Kiselev + + * Makefile.in: Add an absolute path to the test_pics.sh call. + +2003-10-12 Andrey Kiselev + + * libtiff/tiffcomp.h: #define _BSDTYPES_DEFINED when defining BSD + typedefs. + +2003-10-09 Andrey Kiselev + + * 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 + + * Makefile.in: Added missed v3.6.0.html. + + * libtiff/tiffio.h: Typo fixed: ORIENTATION_BOTTOMLEFT replaced with + ORIENTATION_BOTLEFT. + +2003-10-04 Andrey Kiselev + + * 3.6.0 final release. + +2003-10-03 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * libtiff/tif_dirread.c: More fixes for EstimateStripByteCounts(). See + + http://bugzilla.remotesensing.org/show_bug.cgi?id=358 + +2003-08-21 Andrey Kiselev + + * 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 + + * libtiff/Makefile.in: Fixed problem with building in different + directory. + + * tools/tiff2ps.c: Added missing #include . + + * libtiff/tif_dirwrite.c: More fixes for custom tags code + from Ashley Dreier. + +2003-08-07 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * tools/thumbnail.c: Memory leak fixed as reported by Robert S. Kissel. + +2003-06-30 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * tools/fax2tiff.c: Page numbering fixed, as per bug + + http://bugzilla.remotesensing.org/show_bug.cgi?id=341 + +2003-05-20 Andrey Kiselev + + * 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 + + * libtiff/mkversion.c: Fixed problem with wrong string size when + reading RELEASE-DATE file. + +2003-05-07 Andrey Kiselev + + * tools/tiff2ps.c: Fixed bug in Ascii85EncodeBlock() function: array + index was out of range. + +2003-05-06 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * port/install.sh.in: Fixed problems with install producing paths + like ///usr/local/lib on cygwin. + +2003-02-27 Andrey Kiselev + + * 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 + + * 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 + + * tools/ppm2tiff.c: Fixed problem with too many arguments. + +2003-02-04 Andrey Kiselev + + * tools/raw2tiff.c: Memory leak fixed. + +2003-02-03 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * config.guess, config.sub: Updated to recent upstream versions. + +2003-01-15 Frank Warmerdam + + * cut 3.6.0 Beta release. + +2002-12-20 Andrey Kiselev + + * 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 + + * libtiff/tif_dirread.c: Allow wrong sized arrays in + TIFFFetchStripThing(). + + http://bugzilla.remotesensing.org/show_bug.cgi?id=49 + +2002-12-02 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + * 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 + + * 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 + + * libtiff/tiff.h: added COMPRESSION_JP2000. + +2002-10-02 Andrey Kiselev + + * 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 + + * configure, libtiff/Makefile.in: Added SCO OpenServer 5.0.6 support + from John H. DuBois III. + +2002-09-15 Andrey Kiselev + + * Makefile.in, /man/{raw2tiff.1, Makefile.in, libtiff.3}: Added + manual page for raw2tiff(1) tool. + +2002-09-12 Andrey Kiselev + + * /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 + + * 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 + + * /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 + + * /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 + + * /libtiff/{Makefile.vc, libtiff.def}: + Missed declarations added. + +2002-08-15 Frank Warmerdam + + * 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 + + * /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 + + * 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 + + * /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 + + * 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 . + +2002-06-11 Frank Warmerdam + + * 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 + + * 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 + + * libtiff/libtiff.def: Added missed declaration. + +2002-04-22 Andrey Kiselev + + * 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 + + * libtiff/tif_open.c: Pointers to custom procedures + in TIFFClientOpen() are checked to be not NULL-pointers. + +2002-04-18 Andrey Kiselev + + * libtiff/libtiff.def: Added missed declarations. + + * libtiff/tif_pixarlog.c: Updated for using tif_tagmethods structure. + +2002-04-16 Andrey Kiselev + + * 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 + + * tools/tiff2ps: Division by zero fixed. + Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=88 + +2002-04-09 Andrey Kiselev + + * 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 + + * 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 + + * 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 + + * 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 + + * tools/: tifcp.c: Added support for 'Orientation' tag in tiffcp + utility (at cpStripToTile routine). + +2002-03-27 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * man/TIFFGetField: fixed type of TIFFTAG_COPYRIGHT. + + * man/libtiff.3t: added copyright tag info. + +2002-02-11 Frank Warmerdam + + * 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 + + * config.site/configure: added support for OJPEG=yes option to enable + OJPEG support from config.site. + +2002-01-27 Frank Warmerdam + + * html/document.html: fixed links for TIFf 6 docs. + +2002-01-18 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * html/Makefile.in: added missing images per bug 92. + + * port/Makefile.in: fixed clean target per bug 92. + +2001-11-28 Frank Warmerdam + + * 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 + + * added html/v3.5.7.html, updated html/index.html. + + * Makefile.in: added contrib/addtiffo/tif_ovrcache.{c,h}. + +2001-11-15 Frank Warmerdam + + * configure: fixed test for -lm. + +2001-11-02 Frank Warmerdam + + * Added PHOTOMETRIC_ITULAB as per bug 90. + + http://bugzilla.remotesensing.org/show_bug.cgi?id=90 + +2001-10-10 Frank Warmerdam + + * 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 + + * libtiff/tif_dirwrite.c: added TIFFRewriteDirectory() function. + Updated TIFFWriteDirectory man page to include TIFFRewriteDirectory. + +2001-09-24 Frank Warmerdam + + * 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 + + * libtiff/tif_ojpeg.c: new update from Scott. + +2001-09-09 Frank Warmerdam + + * 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 + + * libtiff/tif_packbits.c: fixed memory overrun error. + + http://bugzilla.remotesensing.org/show_bug.cgi?id=77 + +2001-08-31 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * 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 + + * man/Makefile.in: add TIFFClientOpen link as per debian submitted + bug 66. + +2001-07-20 Frank Warmerdam + + * libtiff/tif_jpeg.c: Define HAVE_BOOLEAN on windows if RPCNDR.H + has been included. + +2001-07-19 Frank Warmerdam + + * libtiff/tif_open.c: Seek back to zero after failed read, + before writing header. + +2001-07-18 Frank Warmerdam + + * 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 + + * */Makefile.in: added DESTDIR support. + + http://bugzilla.remotesensing.org/show_bug.cgi?id=60 + +2001-07-16 Frank Warmerdam + + * configure, libtiff/Makefile.in: applied OpenBSD patches + as per: + + http://bugzilla.remotesensing.org/show_bug.cgi?id=61 + +2001-06-28 Frank Warmerdam + + * 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 + + * configure: Changes for DSO generation on AIX provided by + John Marquart . + + * 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 + + * tools/tiff2rgba.c: added -n flag to avoid emitting alpha component. + + * man/tiff2rgba.1: new + +2001-05-22 Frank Warmerdam + + * Added tiffset and tif_ojpeg to the dist lists in Makefile.in. + +2001-05-13 Frank Warmerdam + + * libtiff/tools/thumbnail.c: changed default output compression + to packbits from LZW since LZW isn't generally available. + +2001-05-12 Frank Warmerdam + + * libtiff/tif_ojpeg.c: New. + libtiff/tif_jpeg.c, tiffconf.h, tif_getimage.c: changes related + to OJPEG support. + + Scott Marovich supplied OJPEG support. + +2001-05-11 Frank Warmerdam + + * tiff.h: removed, it duplicates libtiff/tiff.h. + +2001-05-08 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * configure, Makefile.in, etc: added support for OPTIMIZER being + set from config.site. + +2001-03-28 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * tif_getimage.c: Added support for 16bit minisblack/miniswhite + images in RGBA interface. + +2001-03-02 Frank Warmerdam + + * Added TIFFTAG_COPYRIGHT support. + +2001-02-19 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * Makefile.in: Now cleaning up after itself after creating the .tar.gz and .zip + +2001-01-07 Frank Warmerdam + + * html/libtiff.html: Fixed arguments in example for TIFFRGBAImageGet() + as per bug report by Patrick Connor. + +2000-12-28 Frank Warmerdam + + * Added RELEASE-DATE file to release file list. + + * Fixed libtiff/makefile.vc to make tiffvers.h not version.h. + +2000-12-22 Mike Welles + * 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 + + * 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 + + * libtiff/tif_apple.c: Applied "Carbon" support patches supplied by + Leonard Rosenthol . May interfere + with correct building on older systems. If so, please let me know. + +2000-12-19 Mike Welles + + * 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 + + * Added patches for EOFB support in tif_fax3.c and tif_fax3.h. + Patches supplied by Frank Cringle + Example file at: ftp://ftp.remotesensing.org/pub/libtiff/eofb_396.tif + +2000-11-24 Frank Warmerdam + + * 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 + + * I have applied a patch from Steffen Moeller to + the configure script so that it now accepts the --prefix, and + --exec-prefix directives. + +2000-11-13 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + +2000-09-30 Frank Warmerdam + + * 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 + + * Added GNULDdso target an`d switched linux and freebsd to use it. + +2000-09-26 Frank Warmerdam + + * Applied patch for 0x0000 sequences in tif_fax3.h's definition + of EXPAND1D() as per bug 11 (from Roman). + +2000-09-25 Frank Warmerdam + * 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 for reporting the + bug and proving the patch. + +2000-09-18 Frank Warmerdam + + * Fixed tif_jpeg.c so avoid destroying the decompressor before + we are done access data thanks to bug report from: + Michael Eckstein . + + * Reverted tif_flush change. + +2000-09-14 Frank Warmerdam + + * 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 + + * 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 + + * Tentatively added support for SAMPLEFORMAT_COMPLEXIEEEFP, and + SAMPLEFORMAT_COMPLEXINT. + +2000-07-13 Mike Welles + + * index.html, bugs.html: added bugzilla info. + +2000-07-12 Frank Warmerdam + + * 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 + +2000-06-15 Frank Warmerdam + + * Modified tiffio.h logic with regard to including windows.h. It + won't include it when building with __CYGWIN__. + +2000-05-11 Frank Warmerdam + + * 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 . + +2000-04-21 Frank Warmerdam + + * 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 + + * contrib/addtiffo: Added "averaging" resampling option. + + * tools/tiffsplit.c: Copy TIFFTAG_SAMPLEFORMAT. + +Tue Apr 18 16:18:08 2000 Frank Warmerdam + + * tools/Makefile.in: Modified to install properly on SGI. + +2000-04-12 Mike Welles + * configure: Fixed stupid mistake in libc6 test on Linux + +2000-04-04 Mike Welles + * tif_win32.c: Applied patch to fix overreads and ovverwrites + caught by BoundsChecker. From Arvan Pritchard + (untested). + + * tif_getimage.c: Applied patch to silence VC6 warnings. From + Arvan Pritchard + + * tif_lzw.c: Applied patch to silence VC6 warnings. From + Arvan Pritchard + +2000-03-28 Frank Warmerdam + + * Added contrib/stream (stream io) code submitted by Avi Bleiweiss. + +2000-03-28 Frank Warmerdam *** 3.5.5 release *** + + * fax2ps: Fixed mixup of width and height in bounding box statement + as per submission by Nalin Dahyabhai . + +2000-03-27 Mike Welles + + * fax2ps: Modified printruns to take uint32 instead of uint16. + Patch courtesy of Bernt Herd + +2000-03-20 Mike Welles + + * configure: added test for libc6 for linux targets. Bug reported by + Stanislav Brabec + + * Added 3.5 docs to html/Makefile.in. + Thanks to Stanislav Brabec + + * configure: fixed bugs in sed scripts + (applied sed script s:/@:s;@:;s:/s;;:;: to configure). + fix submitted to Stanislav Brabec + + * tools/iptcutil was not in files list, and wasn't being + added to tar archive. Updated Makefile.in. + +2000-03-17 Frank Warmerdam + + * tif_fax3.c: Fixed serious bug introduced during the uint16->uint32 + conversion for the run arrays. + +2000-03-03 Frank Warmerdam + + * Set td_sampleformat default to SAMPLEFORMAT_UINT instead of + SAMPLEFORMAT_VOID in TIFFDefaultDirectory() in tif_dir.c. + +2000-03-02 Frank Warmerdam + + * 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 + + * Fixed tools/tiffcmp so that stopondiff testing works. + Patch care of Joseph Orost . + +2000-01-28 + + * 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 + + * 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 + + * Added TIFFmemory(3t) functions to libtiff.def. + +Tue Jan 4 13:39:00 2000 Frank Warmerdam + + * Added libtiff/libtiff.def to TIFFILES distribution list. + +Mon Dec 27 12:13:39 EST 1999 Mike Welles + + * 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 + + * Added fax3sm_winnt.c to distribution list in Makefile.in. + +Tue Dec 21 11:04:45 EST 1999 Mike Welles *** 3.5.4 release *** + + * Aadded Pixar tag support. Contributed by Phil Beffery + + * 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 + + * 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 + + * Added patch from Ivo Penzar , + supporting Adobe ZIP deflate. Untested. + +Sat Dec 4 15:47:11 1999 Frank Warmerdam + + * Made Packbits the default compression in tools/tiff2rgba.c instead + of LZW. + +Tue Nov 30 14:41:43 1999 Frank Warmerdam *** 3.5.3. release *** + + * Added tif_luv to contrib/djgpp/Makefile.lib. + +Tue Nov 30 14:15:32 EST 1999 Mike Welles + + * Added zip creation to relase makefile target + + * Added html for TIFFWriteTile.3t man page. + +Tue Nov 30 09:20:16 1999 Frank Warmerdam + + * 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 + + * Added TIFFWriteTile.3t man page. + +Sun Nov 28 20:36:18 1999 Frank Warmerdam + + * Added notes on use of makefile.vc in build.html, and fixed + email subscription address. + +199-11-28 Mike Welles + + * 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 -- modifications of + changes made by Frank (sun cc still complained on cast). + + * Added tiffconf.h to install target per request from Bill + Radcliffe : "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 + + * fixed various VC++ warnings as suggested by Gilles Vollant + . + +Wed Nov 24 12:08:16 1999 Frank Warmerdam + + * Modified TIFFquery.3t man pages info on TIFFIsByteSwapped() to + not imply applications are responsible for image data swapping. + +1999-11-22 Mike Welles + * HTML-ized the man pages, added to html/man + + * Removed LZW Compression to comply with Unisys patent extortion. + +1999-09-29 Mike Welles + * Corrected one remaining 16 -> 32 bit value in tif_fax3.c, + From Ivo Penzar + +1999-09-26 Mike Welles *** 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 + + * 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 + + * Applied Francois Dagand's patch to handle fax decompression bug. + (sizes >= 65536 were failing) + +Tue Sep 14 21:31:43 1999 Frank Warmerdam + + * Applied "a" mode fix to tif_win32.c/TIFFOpen() as suggested + by Christopher Lawton + +Wed Sep 8 08:19:18 1999 Frank Warmerdam + + * Added IRIX/gcc, and OSF/1 4.x support on behalf of + Albert Chin-A-Young + + * Added TIFFReassignTagToIgnore() API on behalf of + Bruce Cameron . Man page still pending. + +Wed Aug 25 11:39:07 1999 Frank Warmerdam + + * 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 + + * 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 + + * 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 + + * Updated html/index.html with anon CVS instructions. + +Mon Aug 16 13:18:41 1999 Frank Warmerdam + + * 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/plugins/FreeImage/src/LibTIFF/LibTIFF.dsp b/plugins/FreeImage/src/LibTIFF/LibTIFF.dsp new file mode 100644 index 0000000000..9dd04050be --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/LibTIFF.dsp @@ -0,0 +1,293 @@ +# Microsoft Developer Studio Project File - Name="LibTIFF" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=LibTIFF - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "LibTIFF.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "LibTIFF.mak" CFG="LibTIFF - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "LibTIFF - Win32 Release" (basierend auf "Win32 (x86) Static Library") +!MESSAGE "LibTIFF - Win32 Debug" (basierend auf "Win32 (x86) Static Library") +!MESSAGE "LibTIFF - Win32 Release Unicode" (basierend auf "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "LibTIFF - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "LibTIFF - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "LibTIFF - Win32 Release Unicode" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "LibTIFF___Win32_Release_Unicode" +# PROP BASE Intermediate_Dir "LibTIFF___Win32_Release_Unicode" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "LibTIFF___Win32_Release_Unicode" +# PROP Intermediate_Dir "LibTIFF___Win32_Release_Unicode" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "LibTIFF - Win32 Release" +# Name "LibTIFF - Win32 Debug" +# Name "LibTIFF - Win32 Release Unicode" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\tif_aux.c +# End Source File +# Begin Source File + +SOURCE=.\tif_close.c +# End Source File +# Begin Source File + +SOURCE=.\tif_codec.c +# End Source File +# Begin Source File + +SOURCE=.\tif_color.c +# End Source File +# Begin Source File + +SOURCE=.\tif_compress.c +# End Source File +# Begin Source File + +SOURCE=.\tif_dir.c +# End Source File +# Begin Source File + +SOURCE=.\tif_dirinfo.c +# End Source File +# Begin Source File + +SOURCE=.\tif_dirread.c +# End Source File +# Begin Source File + +SOURCE=.\tif_dirwrite.c +# End Source File +# Begin Source File + +SOURCE=.\tif_dumpmode.c +# End Source File +# Begin Source File + +SOURCE=.\tif_error.c +# End Source File +# Begin Source File + +SOURCE=.\tif_extension.c +# End Source File +# Begin Source File + +SOURCE=.\tif_fax3.c +# End Source File +# Begin Source File + +SOURCE=.\tif_fax3sm.c +# End Source File +# Begin Source File + +SOURCE=.\tif_flush.c +# End Source File +# Begin Source File + +SOURCE=.\tif_getimage.c +# End Source File +# Begin Source File + +SOURCE=.\tif_jpeg.c +# End Source File +# Begin Source File + +SOURCE=.\tif_luv.c +# End Source File +# Begin Source File + +SOURCE=.\tif_lzw.c +# End Source File +# Begin Source File + +SOURCE=.\tif_next.c +# End Source File +# Begin Source File + +SOURCE=.\tif_open.c +# End Source File +# Begin Source File + +SOURCE=.\tif_packbits.c +# End Source File +# Begin Source File + +SOURCE=.\tif_pixarlog.c +# End Source File +# Begin Source File + +SOURCE=.\tif_predict.c +# End Source File +# Begin Source File + +SOURCE=.\tif_print.c +# End Source File +# Begin Source File + +SOURCE=.\tif_read.c +# End Source File +# Begin Source File + +SOURCE=.\tif_strip.c +# End Source File +# Begin Source File + +SOURCE=.\tif_swab.c +# End Source File +# Begin Source File + +SOURCE=.\tif_thunder.c +# End Source File +# Begin Source File + +SOURCE=.\tif_tile.c +# End Source File +# Begin Source File + +SOURCE=.\tif_version.c +# End Source File +# Begin Source File + +SOURCE=.\tif_warning.c +# End Source File +# Begin Source File + +SOURCE=.\tif_write.c +# End Source File +# Begin Source File + +SOURCE=.\tif_zip.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\t4.h +# End Source File +# Begin Source File + +SOURCE=.\tif_config.h +# End Source File +# Begin Source File + +SOURCE=.\tif_dir.h +# End Source File +# Begin Source File + +SOURCE=.\tif_fax3.h +# End Source File +# Begin Source File + +SOURCE=.\tif_predict.h +# End Source File +# Begin Source File + +SOURCE=.\tiff.h +# End Source File +# Begin Source File + +SOURCE=.\tiffio.h +# End Source File +# Begin Source File + +SOURCE=.\tiffiop.h +# End Source File +# Begin Source File + +SOURCE=.\tiffvers.h +# End Source File +# Begin Source File + +SOURCE=.\uvcode.h +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/FreeImage/src/LibTIFF/SConstruct b/plugins/FreeImage/src/LibTIFF/SConstruct new file mode 100644 index 0000000000..d1a2620cf5 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/SConstruct @@ -0,0 +1,73 @@ +# $Id: SConstruct,v 1.29 2011/04/10 17:14:09 drolon Exp $ + +# Tag Image File Format (TIFF) Software +# +# Copyright (C) 2005, Andrey Kiselev +# +# 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/plugins/FreeImage/src/LibTIFF/mkg3states.c b/plugins/FreeImage/src/LibTIFF/mkg3states.c new file mode 100644 index 0000000000..46fac37a9c --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/mkg3states.c @@ -0,0 +1,451 @@ +/* "$Id: mkg3states.c,v 1.37 2011/04/10 17:14:09 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 +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/t4.h b/plugins/FreeImage/src/LibTIFF/t4.h new file mode 100644 index 0000000000..1457ebfabe --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/t4.h @@ -0,0 +1,292 @@ +/* $Id: t4.h,v 1.37 2011/04/10 17:14:09 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_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_acorn.c b/plugins/FreeImage/src/LibTIFF/tif_acorn.c new file mode 100644 index 0000000000..d2de42de53 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_acorn.c @@ -0,0 +1,526 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_acorn.c,v 1.37 2011/04/10 17:14:09 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 +#include + +/* +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; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_apple.c b/plugins/FreeImage/src/LibTIFF/tif_apple.c new file mode 100644 index 0000000000..0cd2948cb7 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_apple.c @@ -0,0 +1,281 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_apple.c,v 1.37 2011/04/10 17:14:09 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 +#include +#include +#include + +#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; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_atari.c b/plugins/FreeImage/src/LibTIFF/tif_atari.c new file mode 100644 index 0000000000..62453a1d93 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_atari.c @@ -0,0 +1,250 @@ +/* "$Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_atari.c,v 1.37 2011/04/10 17:14:09 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 +#include +#else +#include +#include +#endif + +#ifndef O_ACCMODE +#define O_ACCMODE 3 +#endif + +#include + +#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 + +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; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_aux.c b/plugins/FreeImage/src/LibTIFF/tif_aux.c new file mode 100644 index 0000000000..92df69bd1a --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_aux.c @@ -0,0 +1,290 @@ +/* $Id: tif_aux.c,v 1.37 2011/04/10 17:14:09 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 + +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, + "Failed to allocate memory for %s " + "(%ld elements of %ld bytes each)", + what,(long) nmemb, (long) elem_size); + + 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_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; +} + +static int +TIFFDefaultRefBlackWhite(TIFFDirectory* td) +{ + int i; + + if (!(td->td_refblackwhite = (float *)_TIFFmalloc(6*sizeof (float)))) + return 0; + if (td->td_photometric == PHOTOMETRIC_YCBCR) { + /* + * YCbCr (Class Y) images must have the ReferenceBlackWhite + * tag set. Fix the broken images, which lacks that tag. + */ + td->td_refblackwhite[0] = 0.0F; + td->td_refblackwhite[1] = td->td_refblackwhite[3] = + td->td_refblackwhite[5] = 255.0F; + td->td_refblackwhite[2] = td->td_refblackwhite[4] = 128.0F; + } else { + /* + * Assume RGB (Class R) + */ + for (i = 0; i < 3; i++) { + td->td_refblackwhite[2*i+0] = 0; + td->td_refblackwhite[2*i+1] = + (float)((1L<td_bitspersample)-1L); + } + } + return 1; +} + +/* + * 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_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: + if (!td->td_refblackwhite && !TIFFDefaultRefBlackWhite(td)) + return (0); + *va_arg(ap, float **) = td->td_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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_close.c b/plugins/FreeImage/src/LibTIFF/tif_close.c new file mode 100644 index 0000000000..03a8847e84 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_close.c @@ -0,0 +1,126 @@ +/* $Id: tif_close.c,v 1.37 2011/04/10 17:14:09 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); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_codec.c b/plugins/FreeImage/src/LibTIFF/tif_codec.c new file mode 100644 index 0000000000..7876a5fc63 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_codec.c @@ -0,0 +1,160 @@ +/* $Id: tif_codec.c,v 1.37 2011/04/10 17:14:09 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; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_color.c b/plugins/FreeImage/src/LibTIFF/tif_color.c new file mode 100644 index 0000000000..f0302e4bf2 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_color.c @@ -0,0 +1,287 @@ +/* $Id: tif_color.c,v 1.37 2011/04/10 17:14:09 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 + +/* + * 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<(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) +{ + int32 i; + + /* XXX: Only 8-bit YCbCr input supported for now */ + Y = HICLAMP(Y, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255); + + i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]; + *r = CLAMP(i, 0, 255); + i = ycbcr->Y_tab[Y] + + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT); + *g = CLAMP(i, 0, 255); + i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]; + *b = CLAMP(i, 0, 255); +} + +/* + * 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_compress.c b/plugins/FreeImage/src/LibTIFF/tif_compress.c new file mode 100644 index 0000000000..ac471b1e10 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_compress.c @@ -0,0 +1,295 @@ +/* $Id: tif_compress.c,v 1.37 2011/04/10 17:14:09 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 = ®isteredCODECS; (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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_config.h b/plugins/FreeImage/src/LibTIFF/tif_config.h new file mode 100644 index 0000000000..3e08176627 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_config.h @@ -0,0 +1,266 @@ +/* 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 compression (read-only) */ +#define OJPEG_SUPPORT 1 + +/* 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 header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the 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 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 header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the 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 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 header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the 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. */ +#include +#if (LONG_MAX == +9223372036854775807L) +#define SIZEOF_LONG 8 +#elif (LONG_MAX == +2147483647) +#define SIZEOF_LONG 4 +#else +#error "Cannot detect SIZEOF_LONG" +#endif + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your 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 */ + +/* 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 header file. */ +#define HAVE_SEARCH_H 1 +#endif // _MSC_VER + + +/* Define to `long' if does not define. */ +/* #undef off_t */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +#endif /* _TIFFCONF_ */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_config.h-vms b/plugins/FreeImage/src/LibTIFF/tif_config.h-vms new file mode 100644 index 0000000000..c2cae5752e --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_config.h-vms @@ -0,0 +1,46 @@ +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +//#define HAVE_IO_H 1 + +/* Define to 1 if you have the 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/plugins/FreeImage/src/LibTIFF/tif_config.h.in b/plugins/FreeImage/src/LibTIFF/tif_config.h.in new file mode 100644 index 0000000000..86c07e6a99 --- /dev/null +++ b/plugins/FreeImage/src/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 header file. */ +#undef HAVE_ASSERT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the 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 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 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 header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the 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 header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the 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 and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your 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 does not define. */ +#undef off_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/plugins/FreeImage/src/LibTIFF/tif_config.vc.h b/plugins/FreeImage/src/LibTIFF/tif_config.vc.h new file mode 100644 index 0000000000..2bb16d3322 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_config.vc.h @@ -0,0 +1,63 @@ +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define to 1 if you have the 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 +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_dir.c b/plugins/FreeImage/src/LibTIFF/tif_dir.c new file mode 100644 index 0000000000..081bb43c06 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_dir.c @@ -0,0 +1,1391 @@ +/* $Id: tif_dir.c,v 1.38 2011/04/10 17:14:09 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 == 8) + tif->tif_postdecode = _TIFFNoPostDecode; + else 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_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_bitspersample); + break; + case TIFFTAG_REFERENCEBLACKWHITE: + /* XXX should check for null range */ + _TIFFsetFloatArray(&td->td_refblackwhite, va_arg(ap, float*), 6); + 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_REFERENCEBLACKWHITE: + *va_arg(ap, float**) = td->td_refblackwhite; + 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_refblackwhite); + 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; + /* + * Clear other directory-specific fields. + */ + tif->tif_tilesize = -1; + tif->tif_scanlinesize = -1; + + 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 + * + * 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_dir.h b/plugins/FreeImage/src/LibTIFF/tif_dir.h new file mode 100644 index 0000000000..f642834c44 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_dir.h @@ -0,0 +1,211 @@ +/* $Id: tif_dir.h,v 1.37 2011/04/10 17:14:09 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 */ + float* td_refblackwhite; + 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_REFBLACKWHITE 41 +#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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_dirinfo.c b/plugins/FreeImage/src/LibTIFF/tif_dirinfo.c new file mode 100644 index 0000000000..7b7507a8cb --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_dirinfo.c @@ -0,0 +1,884 @@ +/* $Id: tif_dirinfo.c,v 1.38 2011/04/10 17:14:09 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 +#include + +/* + * 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_REFBLACKWHITE, + 1, 0, "ReferenceBlackWhite" }, +/* XXX temporarily accept LONG for backwards compatibility */ + { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_LONG, FIELD_REFBLACKWHITE, + 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); + } + 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); + } + 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_dirread.c b/plugins/FreeImage/src/LibTIFF/tif_dirread.c new file mode 100644 index 0000000000..3567b2ae51 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_dirread.c @@ -0,0 +1,2117 @@ +/* $Id: tif_dirread.c,v 1.38 2011/04/10 17:14:09 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*, 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; + uint16 previous_tag = 0; + int diroutoforderwarning = 0, compressionknown = 0; + int haveunknowntags = 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; + } + { + TIFFDirEntry* ma; + uint16 mb; + for (ma=dir, mb=0; mbtdir_tag==na->tdir_tag) + na->tdir_tag=IGNORE; + } + } + } + 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 (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 < previous_tag) { + if (!diroutoforderwarning) { + TIFFWarningExt(tif->tif_clientdata, module, + "%s: invalid TIFF directory; tags are not sorted in ascending order", + tif->tif_name); + diroutoforderwarning = 1; + } + } + previous_tag = dp->tdir_tag; + if (fix >= tif->tif_nfields || + dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) + 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) { + /* Unknown tag ... we'll deal with it below */ + haveunknowntags = 1; + continue; + } + /* + * 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; + } + } + + /* + * If we saw any unknown tags, make an extra pass over the directory + * to deal with them. This must be done separately because the tags + * could have become known when we registered a codec after finding + * the Compression tag. In a correctly-sorted directory there's + * no problem because Compression will come before any codec-private + * tags, but if the sorting is wrong that might not hold. + */ + if (haveunknowntags) { + fix = 0; + for (dp = dir, n = dircount; n > 0; n--, dp++) { + if (dp->tdir_tag == IGNORE) + continue; + if (fix >= tif->tif_nfields || + dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) + 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); + dp->tdir_tag = IGNORE; + continue; + } + fix = 0; + while (fix < tif->tif_nfields && + tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) + fix++; + } + /* + * 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); + 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: + { + double minv = 0.0, maxv = 0.0; + if (!TIFFFetchPerSampleAnys(tif, dp, &minv, &maxv) || + !TIFFSetField(tif, dp->tdir_tag, minv)) + goto bad; + } + break; + case TIFFTAG_SMAXSAMPLEVALUE: + { + double minv = 0.0, maxv = 0.0; + if (!TIFFFetchPerSampleAnys(tif, dp, &minv, &maxv) || + !TIFFSetField(tif, dp->tdir_tag, maxv)) + 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_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) + { + TIFFWarningExt(tif->tif_clientdata, + "TIFFReadDirectory", + "SamplesPerPixel tag is missing, " + "assuming correct SamplesPerPixel value is 3"); + if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) + goto bad; + } + if (td->td_photometric==PHOTOMETRIC_YCBCR) + { + TIFFWarningExt(tif->tif_clientdata, + "TIFFReadDirectory", + "SamplesPerPixel tag is missing, " + "applying correct SamplesPerPixel value of 3"); + if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3)) + goto bad; + } + else if ((td->td_photometric==PHOTOMETRIC_MINISWHITE) + || (td->td_photometric==PHOTOMETRIC_MINISBLACK)) + { + /* + * SamplesPerPixel tag is missing, but is not required + * by spec. Assume correct SamplesPerPixel value of 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)) { + if ( tif->tif_dir.td_bitspersample>=8 && tif->tif_dir.td_samplesperpixel==3) + tif->tif_dir.td_photometric = PHOTOMETRIC_RGB; + else if (tif->tif_dir.td_bitspersample>=8) + tif->tif_dir.td_photometric = PHOTOMETRIC_MINISBLACK; + else { + 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_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; ntdir_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); + 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) { + union + { + float f; + uint32 i; + } float_union; + + float_union.i=dir->tdir_offset; + v[0]=float_union.f; + 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 returns their min + * and max. + */ +static int +TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* minv, double* maxv) +{ + 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; + + *minv = *maxv = v[0]; + for (i = 1; i < check_count; i++) + { + if (v[i] < *minv) + *minv = v[i]; + if (v[i] > *maxv) + *maxv = v[i]; + } + status = 1; + } + 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 ( dir->tdir_count != 1 || dir->tdir_type != TIFF_RATIONAL ) + { + TIFFWarningExt(tif->tif_clientdata, tif->tif_name, + "incorrect count or type for SubjectDistance, tag ignored" ); + return (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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_dirwrite.c b/plugins/FreeImage/src/LibTIFF/tif_dirwrite.c new file mode 100644 index 0000000000..962937298e --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_dirwrite.c @@ -0,0 +1,1436 @@ +/* $Id: tif_dirwrite.c,v 1.37 2011/04/10 17:14:09 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 TIFFSetupBytePair(TIFF*, ttag_t, TIFFDirEntry*); +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_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 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. See comments + * related to these tags in tif_dir.c. + */ + if (fip->field_tag == TIFFTAG_PAGENUMBER + || fip->field_tag == TIFFTAG_HALFTONEHINTS + || fip->field_tag == TIFFTAG_YCBCRSUBSAMPLING + || fip->field_tag == TIFFTAG_DOTRANGE) { + if (fip->field_type == TIFF_BYTE) { + if (!TIFFSetupBytePair(tif, fip->field_tag, dir)) + goto bad; + } else if (fip->field_type == TIFF_SHORT) { + 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 bytes that are returned by + * value, rather than as a reference to an array. + */ +static int +TIFFSetupBytePair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir) +{ + char v[2]; + + TIFFGetField(tif, tag, &v[0], &v[1]); + + dir->tdir_tag = (uint16) tag; + dir->tdir_type = (uint16) TIFF_BYTE; + dir->tdir_count = 2; + return (TIFFWriteByteArray(tif, dir, v)); +} + +/* + * 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_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 * (int32)(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; + } + break; + 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_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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_dumpmode.c b/plugins/FreeImage/src/LibTIFF/tif_dumpmode.c new file mode 100644 index 0000000000..273614728d --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_dumpmode.c @@ -0,0 +1,126 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_dumpmode.c,v 1.37 2011/04/10 17:14:09 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); +} +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_error.c b/plugins/FreeImage/src/LibTIFF/tif_error.c new file mode 100644 index 0000000000..23f90648de --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_error.c @@ -0,0 +1,80 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_error.c,v 1.37 2011/04/10 17:14:09 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); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_extension.c b/plugins/FreeImage/src/LibTIFF/tif_extension.c new file mode 100644 index 0000000000..e8fb4a2cac --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_extension.c @@ -0,0 +1,118 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_extension.c,v 1.37 2011/04/10 17:14:09 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; +} +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_fax3.c b/plugins/FreeImage/src/LibTIFF/tif_fax3.c new file mode 100644 index 0000000000..2e74a37c69 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_fax3.c @@ -0,0 +1,1626 @@ +/* $Id: tif_fax3.c,v 1.37 2011/04/10 17:14:09 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 + +/* + * 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 + ); + + /* + Assure that allocation computations do not overflow. + + TIFFroundup and TIFFSafeMultiply return zero on integer overflow + */ + dsp->runs=(uint32*) NULL; + nruns = TIFFroundup(rowpixels,32); + if (needsRefLine) { + nruns = TIFFSafeMultiply(uint32,nruns,2); + } + if ((nruns == 0) || (TIFFSafeMultiply(uint32,nruns,2) == 0)) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "Row pixels integer overflow (rowpixels %u)", + rowpixels); + return (0); + } + dsp->runs = (uint32*) _TIFFCheckMalloc(tif, + TIFFSafeMultiply(uint32,nruns,2), + 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<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 EOFB\n", stderr ); +#endif + ClrBits( 13 ); + (*sp->fill)(buf, thisrun, pa, lastx); + UNCACHE_STATE(tif, sp); + return ( sp->line ? 1 : -1); /* don't error on badly-terminated strips */ + } + 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_fax3.h b/plugins/FreeImage/src/LibTIFF/tif_fax3.h new file mode 100644 index 0000000000..ec2811f660 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_fax3.h @@ -0,0 +1,538 @@ +/* $Id: tif_fax3.h,v 1.37 2011/04/10 17:14:09 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++])<>= (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; \ + if (b1 <= (int) (a0 + TabEnt->Param)) { \ + if (b1 < (int) (a0 + TabEnt->Param) || pa != thisrun) { \ + unexpected("VL", a0); \ + goto eol2d; \ + } \ + } \ + 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_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_fax3sm.c b/plugins/FreeImage/src/LibTIFF/tif_fax3sm.c new file mode 100644 index 0000000000..1e2fe42316 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_fax3sm.c @@ -0,0 +1,1260 @@ +/* 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} +}; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_flush.c b/plugins/FreeImage/src/LibTIFF/tif_flush.c new file mode 100644 index 0000000000..af7fdd9b2a --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_flush.c @@ -0,0 +1,74 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_flush.c,v 1.37 2011/04/10 17:14:09 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)); +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_getimage.c b/plugins/FreeImage/src/LibTIFF/tif_getimage.c new file mode 100644 index 0000000000..041e540cba --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_getimage.c @@ -0,0 +1,2678 @@ +/* $Id: tif_getimage.c,v 1.39 2011/04/10 17:14:09 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 + +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), "%s", 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; + int32 incr = 2*toskew+w; + (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 += incr; + cp2 += incr; + 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; + int32 incr = 2*toskew+w; + (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 += incr; + cp2 += incr; + 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<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<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<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) && (img->samplesperpixel==3)) + { + 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), "%s", 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), "%s", 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_jbig.c b/plugins/FreeImage/src/LibTIFF/tif_jbig.c new file mode 100644 index 0000000000..c779c9b0f6 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_jbig.c @@ -0,0 +1,385 @@ +/* $Id: tif_jbig.c,v 1.23 2011/04/10 17:14:09 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 + * + */ + +#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: */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_jpeg.c b/plugins/FreeImage/src/LibTIFF/tif_jpeg.c new file mode 100644 index 0000000000..ee7d886fa8 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_jpeg.c @@ -0,0 +1,2078 @@ +/* $Id: tif_jpeg.c,v 1.37 2011/04/10 17:14:09 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 . + */ +#include + +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", "%s", 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", "%s", 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; + + 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) { + /* 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; icinfo.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; + } 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 ( sp->jpegtables == NULL + || memcmp(sp->jpegtables,"\0\0\0\0\0\0\0\0\0",8) == 0 ) + { + if (!prepare_JPEGTables(tif)) + return (0); + /* Mark the field present */ + /* Can't use TIFFSetField since BEENWRITING is already set! */ + tif->tif_flags |= TIFF_DIRTYDIRECT; + TIFFSetFieldBit(tif, FIELD_JPEGTABLES); + } + } 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 { + if ((td->td_photometric == PHOTOMETRIC_MINISWHITE || td->td_photometric == PHOTOMETRIC_MINISBLACK) && td->td_samplesperpixel == 1) + sp->cinfo.c.in_color_space = JCS_GRAYSCALE; + else if (td->td_photometric == PHOTOMETRIC_RGB) + sp->cinfo.c.in_color_space = JCS_RGB; + else if (td->td_photometric == PHOTOMETRIC_SEPARATED && td->td_samplesperpixel == 4) + sp->cinfo.c.in_color_space = JCS_CMYK; + else + sp->cinfo.c.in_color_space = JCS_UNKNOWN; + if (!TIFFjpeg_set_colorspace(sp, sp->cinfo.c.in_color_space)) + 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 (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE)) + return (0); + if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) { + 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 += bytesperclumpline; + 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? + */ + if ( tif->tif_tilesize > 0 ) + tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; + + if(tif->tif_scanlinesize > 0 ) + tif->tif_scanlinesize = TIFFScanlineSize(tif); +} + +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 ); + + /* + ** We want to clear the loaded strip so the application has time + ** to set JPEGCOLORMODE or other behavior modifiers. This essentially + ** undoes the JPEGPreDecode triggers by TIFFFileStrip(). (#1936) + */ + tif->tif_curstrip = -1; + +#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 +/* +The following line assumes incorrectly that all JPEG-in-TIFF files will have +a JPEGTABLES tag generated and causes null-filled JPEGTABLES tags to be written +when the JPEG data is placed with TIFFWriteRawStrip. The field bit should be +set, anyway, later when actual JPEGTABLES header is generated, so removing it +here hopefully is harmless. + 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: */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_luv.c b/plugins/FreeImage/src/LibTIFF/tif_luv.c new file mode 100644 index 0000000000..5e72ca63ba --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_luv.c @@ -0,0 +1,1629 @@ +/* $Id: tif_luv.c,v 1.37 2011/04/10 17:14:09 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 +#include +#include + +/* + * 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_lzw.c b/plugins/FreeImage/src/LibTIFF/tif_lzw.c new file mode 100644 index 0000000000..16fcd7f9a7 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_lzw.c @@ -0,0 +1,1129 @@ +/* $Id: tif_lzw.c,v 1.38 2011/04/10 17:14:09 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 + +/* + * 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_msdos.c b/plugins/FreeImage/src/LibTIFF/tif_msdos.c new file mode 100644 index 0000000000..884981fa49 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_msdos.c @@ -0,0 +1,193 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_msdos.c,v 1.35 2011/04/10 17:14:09 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 /* for open, close, etc. function prototypes */ +#include +#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 + +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 +#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; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_next.c b/plugins/FreeImage/src/LibTIFF/tif_next.c new file mode 100644 index 0000000000..3fa6406e68 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_next.c @@ -0,0 +1,154 @@ +/* $Id: tif_next.c,v 1.37 2011/04/10 17:14:09 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 + * 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_ojpeg.c b/plugins/FreeImage/src/LibTIFF/tif_ojpeg.c new file mode 100644 index 0000000000..ad339afc1b --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_ojpeg.c @@ -0,0 +1,2448 @@ +/* $Id: tif_ojpeg.c,v 1.36 2011/04/10 17:14:09 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 . + + 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 + and from AWare Systems' TIFF section + . 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 + Copyright (c) AWare Systems + + 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 . +*/ + +/* 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 +#endif + +#include "../LibJPEG/jpeglib.h" +#include "../LibJPEG/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; nqtable_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; ndctable_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; nactable_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; mqtable_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; mdctable_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; mactable_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_curstrilelibjpeg_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; mlines_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; qsubsampling_convert_clinelenout; q++) + { + r=oy; + for (sy=0; sysubsampling_ver; sy++) + { + for (sx=0; sxsubsampling_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_horsubsampling_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_lengthimage_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_offsetplane_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; +#if JPEG_LIB_VERSION >= 70 + sp->libjpeg_jpeg_decompress_struct.do_fancy_upsampling=FALSE; +#endif + 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; nsubsampling_convert_ylines; n++) + *m++=sp->subsampling_convert_ybuf+n*sp->subsampling_convert_ylinelen; + for (n=0; nsubsampling_convert_clines; n++) + *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen; + for (n=0; nsubsampling_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; osamples_per_pixel; o++) + sp->sof_c[o]=o; + sp->sof_hv[0]=((sp->subsampling_hor<<4)|sp->subsampling_ver); + for (o=1; osamples_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; osamples_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 (3tif_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 (3tif_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 (3tif_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 + { + /* Y: Number of lines */ + if (OJPEGReadWord(sp,&p)==0) + return(0); + if ((pimage_length) && (pstrile_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 ((pimage_width) && (pstrile_width)) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected width"); + return(0); + } + if ((uint32)p>sp->strile_width) + { + TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data image width exceeds expected image 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; qsubsamplingcorrect==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; osamples_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; msamples_per_pixel; m++) + { + if ((sp->qtable_offset[m]!=0) && ((m==0) || (sp->qtable_offset[m]!=sp->qtable_offset[m-1]))) + { + for (n=0; nqtable_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; msamples_per_pixel; m++) + { + if ((sp->dctable_offset[m]!=0) && ((m==0) || (sp->dctable_offset[m]!=sp->dctable_offset[m-1]))) + { + for (n=0; ndctable_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; msamples_per_pixel; m++) + { + if ((sp->actable_offset[m]!=0) && ((m==0) || (sp->actable_offset[m]!=sp->actable_offset[m-1]))) + { + for (n=0; nactable_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 + { + if (sp->tif->tif_dir.td_stripoffset == 0) { + TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip offsets are missing"); + return(0); + } + 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 if (sp->tif->tif_dir.td_stripbytecount==NULL) + sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; + else + { + if (sp->tif->tif_dir.td_stripbytecount == 0) { + TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing"); + return(0); + } + 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; msamples_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; msamples_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_strilein_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", "%s", 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", "%s", 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 + + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_open.c b/plugins/FreeImage/src/LibTIFF/tif_open.c new file mode 100644 index 0000000000..c2a0412e90 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_open.c @@ -0,0 +1,695 @@ +/* $Id: tif_open.c,v 1.37 2011/04/10 17:14:09 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 ((m & 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_packbits.c b/plugins/FreeImage/src/LibTIFF/tif_packbits.c new file mode 100644 index 0000000000..1fc96d13a2 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_packbits.c @@ -0,0 +1,300 @@ +/* $Id: tif_packbits.c,v 1.37 2011/04/10 17:14:09 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 + +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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_pixarlog.c b/plugins/FreeImage/src/LibTIFF/tif_pixarlog.c new file mode 100644 index 0000000000..ef4faa4e45 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_pixarlog.c @@ -0,0 +1,1371 @@ +/* $Id: tif_pixarlog.c,v 1.37 2011/04/10 17:14:09 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/zlib.h" + +#include +#include +#include + +/* 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_predict.c b/plugins/FreeImage/src/LibTIFF/tif_predict.c new file mode 100644 index 0000000000..7f7dc636be --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_predict.c @@ -0,0 +1,736 @@ +/* $Id: tif_predict.c,v 1.37 2011/04/10 17:14:09 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_predict.h b/plugins/FreeImage/src/LibTIFF/tif_predict.h new file mode 100644 index 0000000000..6675d9b2a7 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_predict.h @@ -0,0 +1,77 @@ +/* $Id: tif_predict.h,v 1.37 2011/04/10 17:14:09 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_print.c b/plugins/FreeImage/src/LibTIFF/tif_print.c new file mode 100644 index 0000000000..50663396df --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_print.c @@ -0,0 +1,642 @@ +/* $Id: tif_print.c,v 1.37 2011/04/10 17:14:09 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 +#include +#include + +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, ""); + 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_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 < 3; 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: , %lu bytes\n", + (unsigned long) value_count * 4); + return 1; + case TIFFTAG_PHOTOSHOP: + fprintf(fd, " Photoshop Data: , %lu bytes\n", + (unsigned long) value_count); + return 1; + case TIFFTAG_ICCPROFILE: + fprintf(fd, " ICC Profile: , %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_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_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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_read.c b/plugins/FreeImage/src/LibTIFF/tif_read.c new file mode 100644 index 0000000000..351a1b058d --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_read.c @@ -0,0 +1,750 @@ +/* $Id: tif_read.c,v 1.37 2011/04/10 17:14:09 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 + + 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); + if (tif->tif_rawdatasize > 0) + tif->tif_rawdata = (tidata_t) _TIFFmalloc(tif->tif_rawdatasize); + tif->tif_flags |= TIFF_MYBUFFER; + } + if ((tif->tif_rawdata == NULL) || (tif->tif_rawdatasize == 0)) { + 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_stream.cxx b/plugins/FreeImage/src/LibTIFF/tif_stream.cxx new file mode 100644 index 0000000000..a3aaea19d7 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_stream.cxx @@ -0,0 +1,295 @@ +/* $Id: tif_stream.cxx,v 1.32 2011/04/10 17:14:09 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 + +#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/plugins/FreeImage/src/LibTIFF/tif_strip.c b/plugins/FreeImage/src/LibTIFF/tif_strip.c new file mode 100644 index 0000000000..8abf726a00 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_strip.c @@ -0,0 +1,366 @@ +/* $Id: tif_strip.c,v 1.37 2011/04/10 17:14:09 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; + + TIFFGetFieldDefaulted(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]; + + TIFFGetFieldDefaulted(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; + } + + /* number of sample clumps per line */ + scanline = TIFFhowmany(td->td_imagewidth, + ycbcrsubsampling[0]); + /* number of samples per line */ + scanline = multiply(tif, scanline, + ycbcrsubsampling[0]*ycbcrsubsampling[1] + 2, + "TIFFScanlineSize"); + } 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]; + + TIFFGetFieldDefaulted(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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_swab.c b/plugins/FreeImage/src/LibTIFF/tif_swab.c new file mode 100644 index 0000000000..5a42713d5c --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_swab.c @@ -0,0 +1,242 @@ +/* $Id: tif_swab.c,v 1.37 2011/04/10 17:14:09 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[] gives + * the bit reversed value of . 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_thunder.c b/plugins/FreeImage/src/LibTIFF/tif_thunder.c new file mode 100644 index 0000000000..b8c6cc93cc --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_thunder.c @@ -0,0 +1,189 @@ +/* $Id: tif_thunder.c,v 1.37 2011/04/10 17:14:09 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" +#include +#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 < maxpixels ) \ + { \ + if (npixels++ & 1) \ + *op++ |= lastpixel; \ + else \ + op[0] = (tidataval_t) (lastpixel << 4); \ + } \ +} + +static int +ThunderSetupDecode(TIFF* tif) +{ + static const char module[] = "ThunderSetupDecode"; + + if ( tif->tif_dir.td_bitspersample != 4 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Wrong bitspersample value (%d), Thunder decoder only supports 4bits per sample.", + (int) tif->tif_dir.td_bitspersample ); + return 0; + } + + + return (1); +} + +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; + tif->tif_setupdecode = ThunderSetupDecode; + return (1); +} +#endif /* THUNDER_SUPPORT */ + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ + diff --git a/plugins/FreeImage/src/LibTIFF/tif_tile.c b/plugins/FreeImage/src/LibTIFF/tif_tile.c new file mode 100644 index 0000000000..4659825aab --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_tile.c @@ -0,0 +1,280 @@ +/* $Id: tif_tile.c,v 1.37 2011/04/10 17:14:09 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_unix.c b/plugins/FreeImage/src/LibTIFF/tif_unix.c new file mode 100644 index 0000000000..7e294cb78b --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_unix.c @@ -0,0 +1,300 @@ +/* $Id: tif_unix.c,v 1.35 2011/04/10 17:14:09 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 +#endif + +#include +#include +#include + +#ifdef HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_FCNTL_H +# include +#endif + +#ifdef HAVE_IO_H +# include +#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 + +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 +/* + * 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 : "", + 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; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_version.c b/plugins/FreeImage/src/LibTIFF/tif_version.c new file mode 100644 index 0000000000..6badfcdb5f --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_version.c @@ -0,0 +1,40 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_version.c,v 1.37 2011/04/10 17:14:09 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); +} +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_vms.c b/plugins/FreeImage/src/LibTIFF/tif_vms.c new file mode 100644 index 0000000000..553f5072e3 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_vms.c @@ -0,0 +1,595 @@ +/* $Id: tif_vms.c,v 1.21 2011/04/10 17:14:09 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 +#include +#include "tiffiop.h" +#if !HAVE_IEEEFP +#include +#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 + +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 +#include +#include + +/* + * 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 +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_warning.c b/plugins/FreeImage/src/LibTIFF/tif_warning.c new file mode 100644 index 0000000000..a2dbbe7e2f --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_warning.c @@ -0,0 +1,81 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_warning.c,v 1.37 2011/04/10 17:14:09 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); +} + + +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_win3.c b/plugins/FreeImage/src/LibTIFF/tif_win3.c new file mode 100644 index 0000000000..aa21e3aef8 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_win3.c @@ -0,0 +1,232 @@ +/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_win3.c,v 1.35 2011/04/10 17:14:09 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 /* for open, close, etc. function prototypes */ +#endif + +#include +#include +#include + +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 + +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; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_win32.c b/plugins/FreeImage/src/LibTIFF/tif_win32.c new file mode 100644 index 0000000000..5b3875901d --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_win32.c @@ -0,0 +1,408 @@ +/* $Id: tif_win32.c,v 1.35 2011/04/10 17:14:09 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 + +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" : + * + * 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 : "", 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_write.c b/plugins/FreeImage/src/LibTIFF/tif_write.c new file mode 100644 index 0000000000..043e645b87 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_write.c @@ -0,0 +1,718 @@ +/* $Id: tif_write.c,v 1.37 2011/04/10 17:14:09 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 + +#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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tif_zip.c b/plugins/FreeImage/src/LibTIFF/tif_zip.c new file mode 100644 index 0000000000..74ee9c4b5a --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tif_zip.c @@ -0,0 +1,419 @@ +/* $Id: tif_zip.c,v 1.37 2011/04/10 17:14:09 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/zlib.h" + +#include + +/* + * 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tiff.h b/plugins/FreeImage/src/LibTIFF/tiff.h new file mode 100644 index 0000000000..b8912efb9d --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tiff.h @@ -0,0 +1,654 @@ +/* $Id: tiff.h,v 1.38 2011/04/10 17:14:09 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 */ +#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 */ +#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 */ +#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 */ +#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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tiffconf.h-vms b/plugins/FreeImage/src/LibTIFF/tiffconf.h-vms new file mode 100644 index 0000000000..de717ecb97 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/LibTIFF/tiffconf.vc.h b/plugins/FreeImage/src/LibTIFF/tiffconf.vc.h new file mode 100644 index 0000000000..5d73852c41 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tiffconf.vc.h @@ -0,0 +1,116 @@ +/* + 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_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tiffio.h b/plugins/FreeImage/src/LibTIFF/tiffio.h new file mode 100644 index 0000000000..2b94407acd --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tiffio.h @@ -0,0 +1,526 @@ +/* $Id: tiffio.h,v 1.37 2011/04/10 17:14:09 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 +# 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 +#include + +/* 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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tiffio.hxx b/plugins/FreeImage/src/LibTIFF/tiffio.hxx new file mode 100644 index 0000000000..fc20d725d2 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tiffio.hxx @@ -0,0 +1,49 @@ +/* $Id: tiffio.hxx,v 1.32 2011/04/10 17:14:09 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 +#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: */ +/* + * Local Variables: + * mode: c++ + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tiffiop.h b/plugins/FreeImage/src/LibTIFF/tiffiop.h new file mode 100644 index 0000000000..1a64862810 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tiffiop.h @@ -0,0 +1,353 @@ +/* $Id: tiffiop.h,v 1.37 2011/04/10 17:14:09 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 +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_ASSERT_H +# include +#else +# define assert(x) +#endif + +#ifdef HAVE_SEARCH_H +# include +#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. +*/ + +#if !defined(__xlC__) && !defined(__xlc__) // Already defined there (#2301) +#define TIFF_INT64_T signed long long +#define TIFF_UINT64_T unsigned long long +#endif + +#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 < (0xffffffff - (uint32)(y-1))) ? \ + ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \ + 0U) +#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3) +#define TIFFroundup(x, y) (TIFFhowmany(x,y)*(y)) + +/* Safe multiply which returns zero if there is an integer overflow */ +#define TIFFSafeMultiply(t,v,m) ((((t)m != (t)0) && (((t)((v*m)/m)) == (t)v)) ? (t)(v*m) : (t)0) + +#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: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/LibTIFF/tiffvers.h b/plugins/FreeImage/src/LibTIFF/tiffvers.h new file mode 100644 index 0000000000..594702b566 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/tiffvers.h @@ -0,0 +1,9 @@ +#define TIFFLIB_VERSION_STR "LIBTIFF, Version 3.9.5\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 20110409 diff --git a/plugins/FreeImage/src/LibTIFF/uvcode.h b/plugins/FreeImage/src/LibTIFF/uvcode.h new file mode 100644 index 0000000000..8f22325703 --- /dev/null +++ b/plugins/FreeImage/src/LibTIFF/uvcode.h @@ -0,0 +1,180 @@ +/* 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 }, +}; +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff --git a/plugins/FreeImage/src/Metadata/Exif.cpp b/plugins/FreeImage/src/Metadata/Exif.cpp new file mode 100644 index 0000000000..7d0955c5db --- /dev/null +++ b/plugins/FreeImage/src/Metadata/Exif.cpp @@ -0,0 +1,859 @@ +// ========================================================== +// Metadata functions implementation +// Exif metadata model +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// - Mihail Naydenov (mnaydenov@users.sourceforge.net) +// +// 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_MAKER_NOTE 0x927C // Maker note + +// CANON cameras have some funny bespoke fields that need further processing... +#define TAG_CANON_CAMERA_STATE_0x01 0x0001 // tags under tag 0x001 (CameraSettings) +#define TAG_CANON_CAMERA_STATE_0x02 0x0002 // tags under tag 0x002 (FocalLength) +#define TAG_CANON_CAMERA_STATE_0x04 0x0004 // tags under tag 0x004 (ShotInfo) +#define TAG_CANON_CAMERA_STATE_0x12 0x0012 // tags under tag 0x012 (AFInfo) +#define TAG_CANON_CAMERA_STATE_0xA0 0x00A0 // tags under tag 0x0A0 (ProcessingInfo) +#define TAG_CANON_CAMERA_STATE_0xE0 0x00E0 // tags under tag 0x0E0 (SensorInfo) + + +// ===================================================================== +// Reimplementation of strnicmp (it is not supported on some systems) +// ===================================================================== + +/** +Compare characters of two strings without regard to case. +@param s1 Null-terminated string to compare. +@param s2 Null-terminated string to compare. +@param len Number of characters to compare +@return Returns 0 if s1 substring identical to s2 substring +*/ +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, const 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, const 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, const 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 DWORD +ReadUint32(BOOL msb_order, const void *buffer) { + return ((DWORD) 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 ((memcmp("OLYMP\x00\x01", pval, 7) == 0) || (memcmp("OLYMP\x00\x02", pval, 7) == 0) || (memcmp("EPSON", pval, 5) == 0) || (memcmp("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(memcmp("OLYMPUS\x00\x49\x49\x03\x00", pval, 12) == 0) { + // Olympus Type 2 Makernote + // !!! NOT YET SUPPORTED !!! + *subdirOffset = 0; + *md_model = TagLib::UNKNOWN; + } + else if(memcmp("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 + *subdirOffset = 0; + *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(memcmp("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 ((memcmp("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\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\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("LEICA", Maker, 5) == 0)) { + // Leica maker note + if(memcmp("LEICA\x00\x00\x00", pval, 8) == 0) { + // not yet supported makernote data ignored + *subdirOffset = 0; + *md_model = TagLib::UNKNOWN; + } + } + else if(Maker && ((FreeImage_strnicmp("Pentax", Maker, 6) == 0) || (FreeImage_strnicmp("Asahi", Maker, 5) == 0))) { + // Pentax maker note + if(memcmp("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 ((memcmp("SONY CAM\x20\x00\x00\x00", pval, 12) == 0) || (memcmp("SONY DSC\x20\x00\x00\x00", pval, 12) == 0)) { + *md_model = TagLib::EXIF_MAKERNOTE_SONY; + *subdirOffset = 12; + } + else if ((memcmp("SIGMA\x00\x00\x00", pval, 8) == 0) || (memcmp("FOVEON\x00\x00", pval, 8) == 0)) { + FITAG *tagModel = NULL; + FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "Model", &tagModel); + const char *Model = (char*)FreeImage_GetTagValue(tagModel); + if(Model && (memcmp("SIGMA SD1\x00", Model, 10) == 0)) { + // Sigma SD1 maker note + *subdirOffset = 10; + *md_model = TagLib::EXIF_MAKERNOTE_SIGMA_SD1; + } else { + // Sigma / Foveon makernote + *subdirOffset = 10; + *md_model = TagLib::EXIF_MAKERNOTE_SIGMA_FOVEON; + } + } +} + +/** +Process a Canon maker note tag. +A single Canon tag may contain many other tags within. +*/ +static BOOL +processCanonMakerNoteTag(FIBITMAP *dib, FITAG *tag) { + char defaultKey[16]; + DWORD startIndex = 0; + TagLib& s = TagLib::instance(); + + WORD tag_id = FreeImage_GetTagID(tag); + + int subTagTypeBase = 0; + + switch(tag_id) { + case TAG_CANON_CAMERA_STATE_0x01: + subTagTypeBase = 0xC100; + startIndex = 1; + break; + case TAG_CANON_CAMERA_STATE_0x02: + subTagTypeBase = 0xC200; + startIndex = 0; + break; + case TAG_CANON_CAMERA_STATE_0x04: + subTagTypeBase = 0xC400; + startIndex = 1; + break; + case TAG_CANON_CAMERA_STATE_0x12: + subTagTypeBase = 0x1200; + startIndex = 0; + break; + case TAG_CANON_CAMERA_STATE_0xA0: + subTagTypeBase = 0xCA00; + startIndex = 1; + break; + case TAG_CANON_CAMERA_STATE_0xE0: + subTagTypeBase = 0xCE00; + startIndex = 1; + break; + + default: + { + // 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); + } + + return TRUE; + } + break; + + } + + WORD *pvalue = (WORD*)FreeImage_GetTagValue(tag); + + // create a tag + FITAG *canonTag = FreeImage_CreateTag(); + if (!canonTag) return FALSE; + + // we intentionally skip the first array member (if needed) + for (DWORD i = startIndex; i < FreeImage_GetTagCount(tag); i++) { + + 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); + + return TRUE; +} + +/** +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)); + if(NULL == exif_value) { + // out of memory ... + return; + } + 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 destack; // directory entries stack + std::stack ifdstack; // IFD stack + std::stack 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 visitedIFD; + + /* + "An Image File Directory (IFD) consists of a 2-byte count of the number of directory + entries (i.e. the number of fields), followed by a sequence of 12-byte field + entries, followed by a 4-byte offset of the next IFD (or 0 if none)." + The "next IFD" (1st IFD) is the thumbnail. + */ + #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 (0th IFD) and follow it were it leads. + + const BYTE *ifd0th = (BYTE*)tiffp + offset; + + const BYTE *ifdp = ifd0th; + + 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 and entry 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 type + 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)); + // check that tag length (size of the tag value in bytes) will fit in a DWORD + unsigned tag_data_width = FreeImage_TagDataWidth(FreeImage_GetTagType(tag)); + if (tag_data_width != 0 && FreeImage_GetTagCount(tag) > ~(DWORD)0 / tag_data_width) { + FreeImage_DeleteTag(tag); + // jump to next entry + continue; + } + FreeImage_SetTagLength(tag, FreeImage_GetTagCount(tag) * tag_data_width); + + 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 that length does not exceed the buffer size + if(FreeImage_GetTagLength(tag) > length - offset_value){ + // 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; + const 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 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()); + + // + // --- handle thumbnail data --- + // + + const WORD entriesCount0th = ReadUint16(msb_order, ifd0th); + + DWORD next_offset = ReadUint32(msb_order, DIR_ENTRY_ADDR(ifd0th, entriesCount0th)); + if ((next_offset == 0) || (next_offset >= length)) { + return TRUE; //< no thumbnail + } + + const BYTE* const ifd1st = (BYTE*)tiffp + next_offset; + const WORD entriesCount1st = ReadUint16(msb_order, ifd1st); + + unsigned thCompression = 0; + unsigned thOffset = 0; + unsigned thSize = 0; + + for(int e = 0; e < entriesCount1st; e++) { + + // point to the directory entry + const BYTE* base = DIR_ENTRY_ADDR(ifd1st, e); + + // check for buffer overflow + const size_t remaining = (size_t)base + 12 - (size_t)tiffp; + if(remaining >= length) { + // bad IFD1 directory, ignore it + return FALSE; + } + + // get the tag ID + WORD tag = ReadUint16(msb_order, base); + // get the tag type + WORD type = ReadUint16(msb_order, base + sizeof(WORD)); + // get number of components + DWORD count = ReadUint32(msb_order, base + sizeof(WORD) + sizeof(WORD)); + // get the tag value + DWORD offset = ReadUint32(msb_order, base + sizeof(WORD) + sizeof(WORD) + sizeof(DWORD)); + + switch(tag) { + case TAG_COMPRESSION: + // Tiff Compression Tag (should be COMPRESSION_OJPEG (6), but is not always respected) + thCompression = offset; + break; + case TAG_JPEG_INTERCHANGE_FORMAT: + // Tiff JPEGInterchangeFormat Tag + thOffset = offset; + break; + case TAG_JPEG_INTERCHANGE_FORMAT_LENGTH: + // Tiff JPEGInterchangeFormatLength Tag + thSize = offset; + break; + // ### X and Y Resolution ignored, orientation ignored + case TAG_X_RESOLUTION: // XResolution + case TAG_Y_RESOLUTION: // YResolution + case TAG_RESOLUTION_UNIT: // ResolutionUnit + case TAG_ORIENTATION: // Orientation + break; + default: + break; + } + } + + if (/*thCompression != 6 ||*/ thOffset == 0 || thSize == 0) { + return TRUE; + } + + if(thOffset + thSize > length) { + return TRUE; + } + + // load the thumbnail + + const BYTE *thLocation = tiffp + thOffset; + + FIMEMORY* hmem = FreeImage_OpenMemory(const_cast(thLocation), thSize); + FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem); + FreeImage_CloseMemory(hmem); + + // store the thumbnail + FreeImage_SetThumbnail(dib, thumbnail); + // then delete it + FreeImage_Unload(thumbnail); + + return TRUE; +} + +/** + Read and decode 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 - TIFF header with 2 IFDs. 0th - the image attributes, 1st - may be used for thumbnail + + profile += sizeof(exif_signature); + length -= sizeof(exif_signature); + + // read the TIFF header (8 bytes) + + // 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 (Image File Directory) + unsigned long first_offset = ReadUint32(bMotorolaOrder, profile + 4); + if (first_offset > length) { + // bad Exif data + return FALSE; + } + + /* + Note: as FreeImage 3.14.0, this test is no longer needed for images with similar suspicious offset + => tested with Pentax Optio 230, FujiFilm SP-2500 and Canon EOS 300D + 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/plugins/FreeImage/src/Metadata/FIRational.cpp b/plugins/FreeImage/src/Metadata/FIRational.cpp new file mode 100644 index 0000000000..d383c8d38f --- /dev/null +++ b/plugins/FreeImage/src/Metadata/FIRational.cpp @@ -0,0 +1,176 @@ +// ========================================================== +// Helper class for rational numbers +// +// 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 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/plugins/FreeImage/src/Metadata/FIRational.h b/plugins/FreeImage/src/Metadata/FIRational.h new file mode 100644 index 0000000000..bd3ee13e07 --- /dev/null +++ b/plugins/FreeImage/src/Metadata/FIRational.h @@ -0,0 +1,108 @@ +// ========================================================== +// Helper class for rational numbers +// +// 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 your own risk! +// ========================================================== + +#ifndef FIRATIONAL_H +#define FIRATIONAL_H + +/** +Helper class to deal with rational numbers. +NB: LONG data type is assumed to be a signed 32-bit number. +*/ +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/plugins/FreeImage/src/Metadata/FreeImageTag.cpp b/plugins/FreeImage/src/Metadata/FreeImageTag.cpp new file mode 100644 index 0000000000..84e15d0822 --- /dev/null +++ b/plugins/FreeImage/src/Metadata/FreeImageTag.cpp @@ -0,0 +1,318 @@ +// ========================================================== +// Tag manipulation functions +// +// 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 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; + + try { + // 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)); + if (!dst_tag->key) { + throw FI_MSG_ERROR_MEMORY; + } + 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)); + if (!dst_tag->description) { + throw FI_MSG_ERROR_MEMORY; + } + 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 + dst_tag->value = (BYTE*)malloc(src_tag->length * sizeof(BYTE)); + if (!dst_tag->value) { + throw FI_MSG_ERROR_MEMORY; + } + memcpy(dst_tag->value, src_tag->value, src_tag->length); + + return clone; + + } catch(const char *message) { + FreeImage_DeleteTag(clone); + FreeImage_OutputMessageProc(FIF_UNKNOWN, message); + return NULL; + } +} + +// -------------------------------------------------------------------------- +// 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 && value) { + FITAGHEADER *tag_header = (FITAGHEADER *)tag->data; + // first, check the tag + if(tag_header->count * FreeImage_TagDataWidth((FREE_IMAGE_MDTYPE)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: + { + tag_header->value = (char*)malloc((tag_header->length + 1) * sizeof(char)); + if (!tag_header->value) { + return FALSE; + } + char *src_data = (char*)value; + char *dst_data = (char*)tag_header->value; + for(DWORD i = 0; i < tag_header->length; i++) { + dst_data[i] = src_data[i]; + } + dst_data[tag_header->length] = '\0'; + } + break; + + default: + tag_header->value = malloc(tag_header->length * sizeof(BYTE)); + if (!tag_header->value) { + return FALSE; + } + memcpy(tag_header->value, value, tag_header->length); + break; + } + return TRUE; + } + return FALSE; +} + + +// -------------------------------------------------------------------------- +// FITAG internal helper functions +// -------------------------------------------------------------------------- + +/** +Given a FREE_IMAGE_MDTYPE, calculate the size of this type in bytes unit +@param type Input data type +@return Returns the size of the data type, in bytes unit +*/ +unsigned +FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE type) { + static const unsigned format_bytes[] = { + 0, // FIDT_NOTYPE = 0, // placeholder + 1, // FIDT_BYTE = 1, // 8-bit unsigned integer + 1, // FIDT_ASCII = 2, // 8-bit bytes w/ last byte null + 2, // FIDT_SHORT = 3, // 16-bit unsigned integer + 4, // FIDT_LONG = 4, // 32-bit unsigned integer + 8, // FIDT_RATIONAL = 5, // 64-bit unsigned fraction + 1, // FIDT_SBYTE = 6, // 8-bit signed integer + 1, // FIDT_UNDEFINED= 7, // 8-bit untyped data + 2, // FIDT_SSHORT = 8, // 16-bit signed integer + 4, // FIDT_SLONG = 9, // 32-bit signed integer + 8, // FIDT_SRATIONAL= 10, // 64-bit signed fraction + 4, // FIDT_FLOAT = 11, // 32-bit IEEE floating point + 8, // FIDT_DOUBLE = 12, // 64-bit IEEE floating point + 4, // FIDT_IFD = 13, // 32-bit unsigned integer (offset) + 4, // FIDT_PALETTE = 14 // 32-bit RGBQUAD + 0, // placeholder (15) + 8, // FIDT_LONG8 = 16, // 64-bit unsigned integer + 8, // FIDT_SLONG8 = 17, // 64-bit signed integer + 8 // FIDT_IFD8 = 18 // 64-bit unsigned integer (offset) + }; + + return (type < (sizeof(format_bytes)/sizeof(format_bytes[0]))) ? + format_bytes[type] : 0; +} + diff --git a/plugins/FreeImage/src/Metadata/FreeImageTag.h b/plugins/FreeImage/src/Metadata/FreeImageTag.h new file mode 100644 index 0000000000..f412603e8d --- /dev/null +++ b/plugins/FreeImage/src/Metadata/FreeImageTag.h @@ -0,0 +1,474 @@ +// ========================================================== +// Tag manipulation functions +// +// 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 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 + +// LibTIF compression modes + +#define TAG_COMPRESSION_NONE 1 /* dump mode */ +#define TAG_COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */ +#define TAG_COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */ +#define TAG_COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */ +#define TAG_COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */ +#define TAG_COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */ +#define TAG_COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */ +#define TAG_COMPRESSION_OJPEG 6 /* !6.0 JPEG */ +#define TAG_COMPRESSION_JPEG 7 /* %JPEG DCT compression */ +#define TAG_COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */ +#define TAG_COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */ +#define TAG_COMPRESSION_PACKBITS 32773 /* Macintosh RLE */ +#define TAG_COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */ +/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT */ +#define TAG_COMPRESSION_DCS 32947 /* Kodak DCS encoding */ +#define TAG_COMPRESSION_JBIG 34661 /* ISO JBIG */ +#define TAG_COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */ +#define TAG_COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */ +#define TAG_COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */ +#define TAG_COMPRESSION_LZMA 34925 /* LZMA2 */ + +// 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 +*/ +unsigned FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE 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).
+ + Sample usage :
+ + TagLib& s = TagLib::instance(); + TagInfo *tag_info = s.getTagInfo(EXIF_MAIN, 0x0100); + + +*/ + +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, + EXIF_MAKERNOTE_SIGMA_SD1, + EXIF_MAKERNOTE_SIGMA_FOVEON, + IPTC, + GEOTIFF, + ANIMATION + }; + +private: + + typedef std::map TAGINFO; + typedef std::map TABLEMAP; + + /// store hash tables for all known tag info tables + TABLEMAP _table_map; + +private: + /** + Constructor (private)
+ 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 const char *g_TagLib_XMPFieldName = "XMLPacket"; + +/// Name of the Exif raw field +static const char *g_TagLib_ExifRawFieldName = "ExifRaw"; + +// -------------------------------------------------------------------------- +// 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/plugins/FreeImage/src/Metadata/IPTC.cpp b/plugins/FreeImage/src/Metadata/IPTC.cpp new file mode 100644 index 0000000000..817beddf98 --- /dev/null +++ b/plugins/FreeImage/src/Metadata/IPTC.cpp @@ -0,0 +1,325 @@ +// ========================================================== +// 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; + + if (!dataptr || (datalen == 0)) { + return FALSE; + } + + // 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 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/plugins/FreeImage/src/Metadata/TagConversion.cpp b/plugins/FreeImage/src/Metadata/TagConversion.cpp new file mode 100644 index 0000000000..7b91598014 --- /dev/null +++ b/plugins/FreeImage/src/Metadata/TagConversion.cpp @@ -0,0 +1,1094 @@ +// ========================================================== +// Tag to string conversion functions +// +// 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 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 + { + DWORD *pvalue = (DWORD *)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) + { + DWORD *pvalue = (DWORD *)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_LONG8: // N x 64-bit unsigned integer + { + FIUINT64 *pvalue = (FIUINT64 *)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_IFD8: // N x 64-bit unsigned integer (offset) + { + FIUINT64 *pvalue = (FIUINT64 *)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_SLONG8: // N x 64-bit signed integer + { + FIINT64 *pvalue = (FIINT64 *)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_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: + { + const 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; + + case TAG_COMPRESSION: + { + WORD compression = *((WORD*)FreeImage_GetTagValue(tag)); + switch(compression) { + case TAG_COMPRESSION_NONE: + sprintf(format, "dump mode (%d)", compression); + break; + case TAG_COMPRESSION_CCITTRLE: + sprintf(format, "CCITT modified Huffman RLE (%d)", compression); + break; + case TAG_COMPRESSION_CCITTFAX3: + sprintf(format, "CCITT Group 3 fax encoding (%d)", compression); + break; + /* + case TAG_COMPRESSION_CCITT_T4: + sprintf(format, "CCITT T.4 (TIFF 6 name) (%d)", compression); + break; + */ + case TAG_COMPRESSION_CCITTFAX4: + sprintf(format, "CCITT Group 4 fax encoding (%d)", compression); + break; + /* + case TAG_COMPRESSION_CCITT_T6: + sprintf(format, "CCITT T.6 (TIFF 6 name) (%d)", compression); + break; + */ + case TAG_COMPRESSION_LZW: + sprintf(format, "LZW (%d)", compression); + break; + case TAG_COMPRESSION_OJPEG: + sprintf(format, "!6.0 JPEG (%d)", compression); + break; + case TAG_COMPRESSION_JPEG: + sprintf(format, "JPEG (%d)", compression); + break; + case TAG_COMPRESSION_NEXT: + sprintf(format, "NeXT 2-bit RLE (%d)", compression); + break; + case TAG_COMPRESSION_CCITTRLEW: + sprintf(format, "CCITTRLEW (%d)", compression); + break; + case TAG_COMPRESSION_PACKBITS: + sprintf(format, "PackBits Macintosh RLE (%d)", compression); + break; + case TAG_COMPRESSION_THUNDERSCAN: + sprintf(format, "ThunderScan RLE (%d)", compression); + break; + case TAG_COMPRESSION_PIXARFILM: + sprintf(format, "Pixar companded 10bit LZW (%d)", compression); + break; + case TAG_COMPRESSION_PIXARLOG: + sprintf(format, "Pixar companded 11bit ZIP (%d)", compression); + break; + case TAG_COMPRESSION_DEFLATE: + sprintf(format, "Deflate compression (%d)", compression); + break; + case TAG_COMPRESSION_ADOBE_DEFLATE: + sprintf(format, "Adobe Deflate compression (%d)", compression); + break; + case TAG_COMPRESSION_DCS: + sprintf(format, "Kodak DCS encoding (%d)", compression); + break; + case TAG_COMPRESSION_JBIG: + sprintf(format, "ISO JBIG (%d)", compression); + break; + case TAG_COMPRESSION_SGILOG: + sprintf(format, "SGI Log Luminance RLE (%d)", compression); + break; + case TAG_COMPRESSION_SGILOG24: + sprintf(format, "SGI Log 24-bit packed (%d)", compression); + break; + case TAG_COMPRESSION_JP2000: + sprintf(format, "Leadtools JPEG2000 (%d)", compression); + break; + case TAG_COMPRESSION_LZMA: + sprintf(format, "LZMA2 (%d)", compression); + break; + default: + sprintf(format, "Unknown type (%d)", compression); + break; + } + + buffer += format; + 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/plugins/FreeImage/src/Metadata/TagLib.cpp b/plugins/FreeImage/src/Metadata/TagLib.cpp new file mode 100644 index 0000000000..eff291beab --- /dev/null +++ b/plugins/FreeImage/src/Metadata/TagLib.cpp @@ -0,0 +1,1617 @@ +// ========================================================== +// Tag library +// +// 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 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 TagInfo 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"}, + { 0x011D, (char *) "PageName", (char *) "Name of the page"}, + { 0x011E, (char *) "XPosition", (char *) "X position of the image"}, + { 0x011F, (char *) "YPosition", (char *) "Y position of the image"}, + { 0x0128, (char *) "ResolutionUnit", (char *) "Unit of X and Y resolution"}, + { 0x0129, (char *) "PageNumber", (char *) "Page number"}, + { 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"}, + { 0x013C, (char *) "HostComputer", (char *) "Host computer used to generate 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"}, + { 0xA430, (char *) "CameraOwnerName", (char *) "Camera owner name"}, + { 0xA431, (char *) "BodySerialNumber", (char *) "Body serial number"}, + { 0xA432, (char *) "LensSpecification", (char *) "Lens specification"}, + { 0xA433, (char *) "LensMake", (char *) "Lens make"}, + { 0xA434, (char *) "LensModel", (char *) "Lens model"}, + { 0xA435, (char *) "LensSerialNumber", (char *) "Lens serial number"}, + + // These tags are not part of the Exiv v2.3 specifications but are often loaded by applications as Exif data + { 0x4746, (char *) "Rating", (char *) "Rating tag used by Windows"}, + { 0x4749, (char *) "RatingPercent", (char *) "Rating tag used by Windows, value in percent"}, + { 0x9C9B, (char *) "XPTitle", (char *) "Title tag used by Windows, encoded in UCS2"}, + { 0x9C9C, (char *) "XPComment", (char *) "Comment tag used by Windows, encoded in UCS2"}, + { 0x9C9D, (char *) "XPAuthor", (char *) "Author tag used by Windows, encoded in UCS2"}, + { 0x9C9E, (char *) "XPKeywords", (char *) "Keywords tag used by Windows, encoded in UCS2"}, + { 0x9C9F, (char *) "XPSubject", (char *) "Subject tag used by Windows, encoded in UCS2"}, + { 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 *) "UnknownD30", (char *) "Canon UnknownD30 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 *) "CanonAFInfo", (char *) "Canon AFInfo Tags"}, + { 0x0013, (char *) "ThumbnailImageValidArea", (char *) NULL}, + { 0x0015, (char *) "SerialNumberFormat", (char *) NULL}, + { 0x001A, (char *) "SuperMacro", (char *) NULL}, + { 0x001C, (char *) "DateStampMode", (char *) NULL}, + { 0x001D, (char *) "MyColors", (char *) NULL}, + { 0x001E, (char *) "FirmwareRevision", (char *) NULL}, + { 0x0023, (char *) "Categories", (char *) NULL}, + { 0x0024, (char *) "FaceDetect1", (char *) NULL}, + { 0x0025, (char *) "FaceDetect2", (char *) NULL}, + { 0x0026, (char *) "CanonAFInfo2", (char *) "Canon AFInfo2 Tags"}, + { 0x0028, (char *) "ImageUniqueID", (char *) NULL}, + { 0x0081, (char *) "RawDataOffset", (char *) NULL}, + { 0x0083, (char *) "OriginalDecisionDataOffset", (char *) NULL}, + { 0x0090, (char *) "CustomFunctions1D", (char *) "CanonCustom Functions1D Tags"}, + { 0x0091, (char *) "PersonalFunctions", (char *) "CanonCustom PersonalFuncs Tags"}, + { 0x0092, (char *) "PersonalFunctionValues", (char *) "CanonCustom PersonalFuncValues Tags"}, + { 0x0093, (char *) "CanonFileInfo", (char *) "Canon FileInfo Tags"}, + { 0x0094, (char *) "AFPointsInFocus1D", (char *) NULL}, + { 0x0095, (char *) "LensModel", (char *) NULL}, + { 0x0096, (char *) "SerialInfo", (char *) NULL}, + { 0x0097, (char *) "DustRemovalData", (char *) NULL}, + { 0x0098, (char *) "CropInfo", (char *) NULL}, + { 0x0099, (char *) "CustomFunctions2", (char *) NULL}, + { 0x009A, (char *) "AspectInfo", (char *) NULL}, + { 0x00A0, (char *) "ProcessingInfo", (char *) NULL}, + { 0x00A1, (char *) "ToneCurveTable", (char *) NULL}, + { 0x00A2, (char *) "SharpnessTable", (char *) NULL}, + { 0x00A3, (char *) "SharpnessFreqTable", (char *) NULL}, + { 0x00A4, (char *) "WhiteBalanceTable", (char *) NULL}, + { 0x00A9, (char *) "ColorBalance", (char *) NULL}, + { 0x00AA, (char *) "MeasuredColor", (char *) NULL}, + { 0x00AE, (char *) "ColorTemperature", (char *) NULL}, + { 0x00B0, (char *) "CanonFlags", (char *) NULL}, + { 0x00B1, (char *) "ModifiedInfo", (char *) NULL}, + { 0x00B2, (char *) "ToneCurveMatching", (char *) NULL}, + { 0x00B3, (char *) "WhiteBalanceMatching", (char *) NULL}, + { 0x00B4, (char *) "ColorSpace", (char *) NULL}, + { 0x00B6, (char *) "PreviewImageInfo", (char *) NULL}, + { 0x00D0, (char *) "VRDOffset", (char *) "Offset of VRD 'recipe data' if it exists"}, + { 0x00E0, (char *) "SensorInfo", (char *) NULL}, + { 0x4001, (char *) "ColorData", (char *) "Canon ColorData Tags"}, + { 0x4002, (char *) "CRWParam?", (char *) NULL}, + { 0x4003, (char *) "ColorInfo", (char *) NULL}, + { 0x4005, (char *) "Flavor?", (char *) NULL}, + { 0x4008, (char *) "BlackLevel?", (char *) NULL}, + { 0x4010, (char *) "CustomPictureStyleFileName", (char *) NULL}, + { 0x4013, (char *) "AFMicroAdj", (char *) NULL}, + { 0x4015, (char *) "VignettingCorr", (char *) NULL}, + { 0x4016, (char *) "VignettingCorr2", (char *) NULL}, + { 0x4018, (char *) "LightingOpt", (char *) NULL}, + { 0x4019, (char *) "LensInfo", (char *) NULL}, + { 0x4020, (char *) "AmbienceInfo", (char *) NULL}, + { 0x4024, (char *) "FilterInfo", (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) + { 0xC100 + 1, (char *) "CameraSettings:MacroMode", (char *) NULL}, + { 0xC100 + 2, (char *) "CameraSettings:SelfTimer", (char *) NULL}, + { 0xC100 + 3, (char *) "CameraSettings:Quality", (char *) NULL}, + { 0xC100 + 4, (char *) "CameraSettings:CanonFlashMode", (char *) NULL}, + { 0xC100 + 5, (char *) "CameraSettings:ContinuousDrive", (char *) NULL}, + { 0xC100 + 6, (char *) "CameraSettings:0x0006", (char *) NULL}, + { 0xC100 + 7, (char *) "CameraSettings:FocusMode", (char *) NULL}, + { 0xC100 + 8, (char *) "CameraSettings:0x0008", (char *) NULL}, + { 0xC100 + 9, (char *) "CameraSettings:RecordMode", (char *) NULL}, + { 0xC100 + 10, (char *) "CameraSettings:CanonImageSize", (char *) NULL}, + { 0xC100 + 11, (char *) "CameraSettings:EasyMode", (char *) NULL}, + { 0xC100 + 12, (char *) "CameraSettings:DigitalZoom", (char *) NULL}, + { 0xC100 + 13, (char *) "CameraSettings:Contrast", (char *) NULL}, + { 0xC100 + 14, (char *) "CameraSettings:Saturation", (char *) NULL}, + { 0xC100 + 15, (char *) "CameraSettings:Sharpness", (char *) NULL}, + { 0xC100 + 16, (char *) "CameraSettings:CameraISO", (char *) NULL}, + { 0xC100 + 17, (char *) "CameraSettings:MeteringMode", (char *) NULL}, + { 0xC100 + 18, (char *) "CameraSettings:FocusRange", (char *) NULL}, + { 0xC100 + 19, (char *) "CameraSettings:AFPoint", (char *) NULL}, + { 0xC100 + 20, (char *) "CameraSettings:CanonExposureMode", (char *) NULL}, + { 0xC100 + 21, (char *) "CameraSettings:0x0015", (char *) NULL}, + { 0xC100 + 22, (char *) "CameraSettings:LensType", (char *) NULL}, + { 0xC100 + 23, (char *) "CameraSettings:LongFocal", (char *) NULL}, + { 0xC100 + 24, (char *) "CameraSettings:ShortFocal", (char *) NULL}, + { 0xC100 + 25, (char *) "CameraSettings:FocalUnits", (char *) "Focal Units per mm"}, + { 0xC100 + 26, (char *) "CameraSettings:MaxAperture", (char *) NULL}, + { 0xC100 + 27, (char *) "CameraSettings:MinAperture", (char *) NULL}, + { 0xC100 + 28, (char *) "CameraSettings:FlashActivity", (char *) NULL}, + { 0xC100 + 29, (char *) "CameraSettings:FlashBits", (char *) NULL}, + { 0xC100 + 30, (char *) "CameraSettings:0x001E", (char *) NULL}, + { 0xC100 + 31, (char *) "CameraSettings:0x001F", (char *) NULL}, + { 0xC100 + 32, (char *) "CameraSettings:FocusContinuous", (char *) NULL}, + { 0xC100 + 33, (char *) "CameraSettings:AESetting", (char *) NULL}, + { 0xC100 + 34, (char *) "CameraSettings:ImageStabilization", (char *) NULL}, + { 0xC100 + 35, (char *) "CameraSettings:DisplayAperture", (char *) NULL}, + { 0xC100 + 36, (char *) "CameraSettings:ZoomSourceWidth", (char *) NULL}, + { 0xC100 + 37, (char *) "CameraSettings:ZoomTargetWidth", (char *) NULL}, + { 0xC100 + 38, (char *) "CameraSettings:0x0026", (char *) NULL}, + { 0xC100 + 39, (char *) "CameraSettings:SpotMeteringMode", (char *) NULL}, + { 0xC100 + 40, (char *) "CameraSettings:PhotoEffect", (char *) NULL}, + { 0xC100 + 41, (char *) "CameraSettings:ManualFlashOutput", (char *) NULL}, + { 0xC100 + 42, (char *) "CameraSettings:ColorTone", (char *) NULL}, + { 0xC100 + 43, (char *) "CameraSettings:0x002B", (char *) NULL}, + { 0xC100 + 44, (char *) "CameraSettings:0x002C", (char *) NULL}, + { 0xC100 + 45, (char *) "CameraSettings:0x002D", (char *) NULL}, + { 0xC100 + 46, (char *) "CameraSettings:SRAWQuality", (char *) NULL}, + { 0xC100 + 47, (char *) "CameraSettings:0x002F", (char *) NULL}, + { 0xC100 + 48, (char *) "CameraSettings:0x0030", (char *) NULL}, + + // Fields under tag 0x0002 (we add 0xC200 to make unique tag id) + { 0xC200 + 0, (char *) "FocalLength:FocalType", (char *) NULL}, + { 0xC200 + 1, (char *) "FocalLength:FocalLength", (char *) NULL}, + { 0xC200 + 2, (char *) "FocalLength:FocalPlaneXSize", (char *) NULL}, + { 0xC200 + 3, (char *) "FocalLength:FocalPlaneYSize", (char *) NULL}, + + // Fields under tag 0x0004 (we add 0xC400 to make unique tag id) + { 0xC400 + 1, (char *) "ShotInfo:AutoISO", (char *) NULL}, + { 0xC400 + 2, (char *) "ShotInfo:BaseISO", (char *) NULL}, + { 0xC400 + 3, (char *) "ShotInfo:MeasuredEV", (char *) NULL}, + { 0xC400 + 4, (char *) "ShotInfo:TargetAperture", (char *) NULL}, + { 0xC400 + 5, (char *) "ShotInfo:TargetExposureTime", (char *) NULL}, + { 0xC400 + 6, (char *) "ShotInfo:ExposureCompensation", (char *) NULL}, + { 0xC400 + 7, (char *) "ShotInfo:WhiteBalance", (char *) NULL}, + { 0xC400 + 8, (char *) "ShotInfo:SlowShutter", (char *) NULL}, + { 0xC400 + 9, (char *) "ShotInfo:SequenceNumber", (char *) NULL}, + { 0xC400 + 10, (char *) "ShotInfo:OpticalZoomCode", (char *) NULL}, + { 0xC400 + 11, (char *) "ShotInfo:0x000B", (char *) NULL}, + { 0xC400 + 12, (char *) "ShotInfo:CameraTemperature", (char *) NULL}, + { 0xC400 + 13, (char *) "ShotInfo:FlashGuideNumber", (char *) NULL}, + { 0xC400 + 14, (char *) "ShotInfo:AFPointsInFocus", (char *) NULL}, + { 0xC400 + 15, (char *) "ShotInfo:FlashExposureComp", (char *) NULL}, + { 0xC400 + 16, (char *) "ShotInfo:AutoExposureBracketing", (char *) NULL}, + { 0xC400 + 17, (char *) "ShotInfo:AEBBracketValue", (char *) NULL}, + { 0xC400 + 18, (char *) "ShotInfo:ControlMode", (char *) NULL}, + { 0xC400 + 19, (char *) "ShotInfo:FocusDistanceUpper", (char *) NULL}, + { 0xC400 + 20, (char *) "ShotInfo:FocusDistanceLower", (char *) NULL}, + { 0xC400 + 21, (char *) "ShotInfo:FNumber", (char *) NULL}, + { 0xC400 + 22, (char *) "ShotInfo:ExposureTime", (char *) NULL}, + { 0xC400 + 23, (char *) "ShotInfo:MeasuredEV2", (char *) NULL}, + { 0xC400 + 24, (char *) "ShotInfo:BulbDuration", (char *) NULL}, + { 0xC400 + 25, (char *) "ShotInfo:0x0019", (char *) NULL}, + { 0xC400 + 26, (char *) "ShotInfo:CameraType", (char *) NULL}, + { 0xC400 + 27, (char *) "ShotInfo:AutoRotate", (char *) NULL}, + { 0xC400 + 28, (char *) "ShotInfo:NDFilter", (char *) NULL}, + { 0xC400 + 29, (char *) "ShotInfo:SelfTimer2", (char *) NULL}, + { 0xC400 + 30, (char *) "ShotInfo:0x001E", (char *) NULL}, + { 0xC400 + 31, (char *) "ShotInfo:0x001F", (char *) NULL}, + { 0xC400 + 32, (char *) "ShotInfo:0x0020", (char *) NULL}, + { 0xC400 + 33, (char *) "ShotInfo:FlashOutput", (char *) NULL}, + + // Fields under tag 0x0012 (we add 0x1200 to make unique tag id) + { 0x1200 + 0, (char *) "AFInfo:NumAFPoints", (char *) NULL}, + { 0x1200 + 1, (char *) "AFInfo:ValidAFPoints", (char *) NULL}, + { 0x1200 + 2, (char *) "AFInfo:CanonImageWidth", (char *) NULL}, + { 0x1200 + 3, (char *) "AFInfo:CanonImageHeight", (char *) NULL}, + { 0x1200 + 4, (char *) "AFInfo:AFImageWidth", (char *) NULL}, + { 0x1200 + 5, (char *) "AFInfo:AFImageHeight", (char *) NULL}, + { 0x1200 + 6, (char *) "AFInfo:AFAreaWidth", (char *) NULL}, + { 0x1200 + 7, (char *) "AFInfo:AFAreaHeight", (char *) NULL}, + { 0x1200 + 8, (char *) "AFInfo:AFAreaXPositions", (char *) NULL}, + { 0x1200 + 9, (char *) "AFInfo:AFAreaYPositions", (char *) NULL}, + { 0x1200 + 10, (char *) "AFInfo:AFPointsInFocus", (char *) NULL}, + { 0x1200 + 11, (char *) "AFInfo:PrimaryAFPoint?", (char *) NULL}, + { 0x1200 + 12, (char *) "AFInfo:PrimaryAFPoint", (char *) NULL}, + { 0x1200 + 13, (char *) "AFInfo:0x000D", (char *) NULL}, + { 0x1200 + 14, (char *) "AFInfo:0x000E", (char *) NULL}, + { 0x1200 + 15, (char *) "AFInfo:0x000F", (char *) NULL}, + { 0x1200 + 16, (char *) "AFInfo:0x0010", (char *) NULL}, + { 0x1200 + 17, (char *) "AFInfo:0x0011", (char *) NULL}, + { 0x1200 + 18, (char *) "AFInfo:0x0012", (char *) NULL}, + { 0x1200 + 19, (char *) "AFInfo:0x0013", (char *) NULL}, + { 0x1200 + 20, (char *) "AFInfo:0x0014", (char *) NULL}, + { 0x1200 + 21, (char *) "AFInfo:0x0015", (char *) NULL}, + { 0x1200 + 22, (char *) "AFInfo:0x0016", (char *) NULL}, + { 0x1200 + 23, (char *) "AFInfo:0x0017", (char *) NULL}, + { 0x1200 + 24, (char *) "AFInfo:0x0018", (char *) NULL}, + { 0x1200 + 25, (char *) "AFInfo:0x0019", (char *) NULL}, + { 0x1200 + 26, (char *) "AFInfo:0x001A", (char *) NULL}, + { 0x1200 + 27, (char *) "AFInfo:0x001B", (char *) NULL}, + + // Fields under tag 0x00A0 (we add 0xCA00 to make unique tag id) + { 0xCA00 + 1, (char *) "ProcessingInfo:ToneCurve", (char *) NULL}, + { 0xCA00 + 2, (char *) "ProcessingInfo:Sharpness", (char *) NULL}, + { 0xCA00 + 3, (char *) "ProcessingInfo:SharpnessFrequency", (char *) NULL}, + { 0xCA00 + 4, (char *) "ProcessingInfo:SensorRedLevel", (char *) NULL}, + { 0xCA00 + 5, (char *) "ProcessingInfo:SensorBlueLevel", (char *) NULL}, + { 0xCA00 + 6, (char *) "ProcessingInfo:WhiteBalanceRed", (char *) NULL}, + { 0xCA00 + 7, (char *) "ProcessingInfo:WhiteBalanceBlue", (char *) NULL}, + { 0xCA00 + 8, (char *) "ProcessingInfo:WhiteBalance", (char *) NULL}, + { 0xCA00 + 9, (char *) "ProcessingInfo:ColorTemperature", (char *) NULL}, + { 0xCA00 + 10, (char *) "ProcessingInfo:PictureStyle", (char *) NULL}, + { 0xCA00 + 11, (char *) "ProcessingInfo:DigitalGain", (char *) NULL}, + { 0xCA00 + 12, (char *) "ProcessingInfo:WBShiftAB", (char *) NULL}, + { 0xCA00 + 13, (char *) "ProcessingInfo:WBShiftGM", (char *) NULL}, + + // Fields under tag 0x00E0 (we add 0xCE00 to make unique tag id) + { 0xCE00 + 1, (char *) "SensorInfo:SensorWidth", (char *) NULL}, + { 0xCE00 + 2, (char *) "SensorInfo:SensorHeight", (char *) NULL}, + { 0xCE00 + 3, (char *) "SensorInfo:0x0003", (char *) NULL}, + { 0xCE00 + 4, (char *) "SensorInfo:0x0004", (char *) NULL}, + { 0xCE00 + 5, (char *) "SensorInfo:SensorLeftBorder", (char *) NULL}, + { 0xCE00 + 6, (char *) "SensorInfo:SensorTopBorder", (char *) NULL}, + { 0xCE00 + 7, (char *) "SensorInfo:SensorRightBorder", (char *) NULL}, + { 0xCE00 + 8, (char *) "SensorInfo:SensorBottomBorder", (char *) NULL}, + { 0xCE00 + 9, (char *) "SensorInfo:BlackMaskLeftBorder", (char *) NULL}, + { 0xCE00 + 10, (char *) "SensorInfo:BlackMaskTopBorder", (char *) NULL}, + { 0xCE00 + 11, (char *) "SensorInfo:BlackMaskRightBorder", (char *) NULL}, + { 0xCE00 + 12, (char *) "SensorInfo:BlackMaskBottomBorder", (char *) NULL}, + { 0xCE00 + 13, (char *) "SensorInfo:0x000D", (char *) NULL}, + { 0xCE00 + 14, (char *) "SensorInfo:0x000E", (char *) NULL}, + { 0xCE00 + 15, (char *) "SensorInfo:0x000F", (char *) NULL}, + { 0xCE00 + 16, (char *) "SensorInfo:0x0010", (char *) NULL}, + + { 0x0000, (char *) NULL, (char *) NULL} + }; + +/** +Casio type 1 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 *) "ISO", (char *) NULL}, + { 0x0015, (char *) "FirmwareDate", (char *) NULL}, + { 0x0016, (char *) "Enhancement", (char *) NULL}, + { 0x0017, (char *) "ColorFilter", (char *) NULL}, + { 0x0018, (char *) "AFPoint", (char *) NULL}, + { 0x0019, (char *) "FlashIntensity", (char *) NULL}, + { 0x0E00, (char *) "PrintIM", (char *) NULL}, + { 0x0000, (char *) NULL, (char *) NULL} + }; + +/** +Casio type 2 maker note +*/ +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}, + { 0x2001, (char *) "FirmwareDate", (char *) NULL}, + { 0x2011, (char *) "WhiteBalanceBias", (char *) NULL}, + { 0x2012, (char *) "WhiteBalance", (char *) NULL}, + { 0x2021, (char *) "AFPointPosition", (char *) NULL}, + { 0x2022, (char *) "ObjectDistance", (char *) NULL}, + { 0x2034, (char *) "FlashDistance", (char *) NULL}, + { 0x2076, (char *) "SpecialEffectMode", (char *) NULL}, + { 0x3000, (char *) "RecordMode", (char *) NULL}, + { 0x3001, (char *) "ReleaseMode", (char *) NULL}, + { 0x3002, (char *) "Quality", (char *) NULL}, + { 0x3003, (char *) "FocusMode", (char *) NULL}, + { 0x3006, (char *) "HometownCity", (char *) NULL}, + { 0x3007, (char *) "BestShotMode", (char *) NULL}, + { 0x3008, (char *) "AutoISO", (char *) NULL}, + { 0x3009, (char *) "AFMode", (char *) NULL}, + { 0x3011, (char *) "Sharpness", (char *) NULL}, + { 0x3012, (char *) "Contrast", (char *) NULL}, + { 0x3013, (char *) "Saturation", (char *) NULL}, + { 0x3014, (char *) "ISO", (char *) NULL}, + { 0x3015, (char *) "ColorMode", (char *) NULL}, + { 0x3016, (char *) "Enhancement", (char *) NULL}, + { 0x3017, (char *) "ColorFilter", (char *) NULL}, + { 0x301C, (char *) "SequenceNumber", (char *) NULL}, + { 0x301D, (char *) "BracketSequence", (char *) NULL}, + { 0x3020, (char *) "ImageStabilization", (char *) NULL}, + { 0x302A, (char *) "LightingMode", (char *) NULL}, + { 0x302B, (char *) "PortraitRefiner", (char *) NULL}, + { 0x3030, (char *) "SpecialEffectLevel", (char *) NULL}, + { 0x3031, (char *) "SpecialEffectSetting", (char *) NULL}, + { 0x3103, (char *) "DriveMode", (char *) NULL}, + { 0x4001, (char *) "CaptureFrameRate", (char *) NULL}, + { 0x4003, (char *) "VideoQuality", (char *) NULL}, + { 0x0000, (char *) NULL, (char *) NULL} + }; + +/** +FujiFilm maker note +*/ +static TagInfo + exif_fujifilm_tag_table[] = + { + { 0x0000, (char *) "Version", (char *) NULL}, + { 0x0010, (char *) "InternalSerialNumber", (char *) NULL}, + { 0x1000, (char *) "Quality", (char *) NULL}, + { 0x1001, (char *) "Sharpness", (char *) NULL}, + { 0x1002, (char *) "WhiteBalance", (char *) NULL}, + { 0x1003, (char *) "Saturation", (char *) NULL}, + { 0x1004, (char *) "Contrast", (char *) NULL}, + { 0x1005, (char *) "ColorTemperature", (char *) NULL}, + { 0x100A, (char *) "WhiteBalanceFineTune", (char *) NULL}, + { 0x100B, (char *) "NoiseReduction", (char *) NULL}, + { 0x1010, (char *) "FujiFlashMode", (char *) NULL}, + { 0x1011, (char *) "FlashExposureComp", (char *) NULL}, + { 0x1020, (char *) "Macro", (char *) NULL}, + { 0x1021, (char *) "FocusMode", (char *) NULL}, + { 0x1023, (char *) "FocusPixel", (char *) NULL}, + { 0x1030, (char *) "SlowSync", (char *) NULL}, + { 0x1031, (char *) "PictureMode", (char *) NULL}, + { 0x1033, (char *) "EXRAuto", (char *) NULL}, + { 0x1034, (char *) "EXRMode", (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}, + { 0x1401, (char *) "FilmMode", (char *) NULL}, + { 0x1402, (char *) "DynamicRangeSetting", (char *) NULL}, + { 0x1403, (char *) "DevelopmentDynamicRange", (char *) NULL}, + { 0x1404, (char *) "MinFocalLength", (char *) NULL}, + { 0x1405, (char *) "MaxFocalLength", (char *) NULL}, + { 0x1406, (char *) "MaxApertureAtMinFocal", (char *) NULL}, + { 0x1407, (char *) "MaxApertureAtMaxFocal", (char *) NULL}, + { 0x4100, (char *) "FacesDetected", (char *) NULL}, + { 0x4103, (char *) "FacePositions", (char *) NULL}, + { 0x8000, (char *) "FileSource", (char *) NULL}, + { 0x8002, (char *) "OrderNumber", (char *) NULL}, + { 0x8003, (char *) "FrameNumber", (char *) NULL}, + { 0xB211, (char *) "Parallax", (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}, + { 0x0104, (char *) "BodyFirmwareVersion", (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}, + { 0x020B, (char *) "EpsonImageWidth", (char *) NULL}, + { 0x020C, (char *) "EpsonImageHeight", (char *) NULL}, + { 0x020D, (char *) "EpsonSoftware", (char *) NULL}, + { 0x0280, (char *) "PreviewImage", (char *) NULL}, + { 0x0300, (char *) "PreCaptureFrames", (char *) NULL}, + { 0x0301, (char *) "WhiteBoard", (char *) NULL}, + { 0x0302, (char *) "OneTouchWB", (char *) NULL}, + { 0x0303, (char *) "WhiteBalanceBracket", (char *) NULL}, + { 0x0304, (char *) "WhiteBalanceBias", (char *) NULL}, + { 0x0403, (char *) "SceneMode", (char *) NULL}, + { 0x0404, (char *) "SerialNumber", (char *) NULL}, + { 0x0405, (char *) "Firmware", (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}, + { 0x1009, (char *) "LightCondition", (char *) NULL}, + { 0x100A, (char *) "FocusRange", (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}, + { 0x1019, (char *) "ColorMatrixNumber", (char *) NULL}, + { 0x101A, (char *) "SerialNumber", (char *) NULL}, + { 0x1023, (char *) "FlashExposureComp", (char *) NULL}, + { 0x1024, (char *) "InternalFlashTable", (char *) NULL}, + { 0x1025, (char *) "ExternalFlashGValue", (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}, + { 0x1030, (char *) "SceneDetect", (char *) NULL}, + { 0x1031, (char *) "SceneArea?", (char *) NULL}, + { 0x1033, (char *) "SceneDetectData?", (char *) NULL}, + { 0x1034, (char *) "CompressionRatio", (char *) NULL}, + { 0x1035, (char *) "PreviewImageValid", (char *) NULL}, + { 0x1036, (char *) "PreviewImageStart", (char *) NULL}, + { 0x1037, (char *) "PreviewImageLength", (char *) NULL}, + { 0x1038, (char *) "AFResult", (char *) NULL}, + { 0x1039, (char *) "CCDScanMode", (char *) NULL}, + { 0x103A, (char *) "NoiseReduction", (char *) NULL}, + { 0x103B, (char *) "InfinityLensStep", (char *) NULL}, + { 0x103C, (char *) "NearLensStep", (char *) NULL}, + { 0x103D, (char *) "LightValueCenter", (char *) NULL}, + { 0x103E, (char *) "LightValuePeriphery", (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"}, + { 0x2100, (char *) "Olympus2100", (char *) "Olympus FE Tags"}, + { 0x2200, (char *) "Olympus2200", (char *) "Olympus FE Tags"}, + { 0x2300, (char *) "Olympus2300", (char *) "Olympus FE Tags"}, + { 0x2400, (char *) "Olympus2400", (char *) "Olympus FE Tags"}, + { 0x2500, (char *) "Olympus2500", (char *) "Olympus FE Tags"}, + { 0x2600, (char *) "Olympus2600", (char *) "Olympus FE Tags"}, + { 0x2700, (char *) "Olympus2700", (char *) "Olympus FE Tags"}, + { 0x2800, (char *) "Olympus2800", (char *) "Olympus FE Tags"}, + { 0x2900, (char *) "Olympus2900", (char *) "Olympus FE Tags"}, + { 0x3000, (char *) "RawInfo", (char *) "Olympus RawInfo Tags"}, + { 0x4000, (char *) "MainInfo", (char *) "Olympus MainInfo Tags"}, + { 0x0000, (char *) NULL, (char *) NULL} + }; + +/** +Minolta maker note +*/ +static TagInfo + exif_minolta_tag_table[] = + { + { 0x0000, (char *) "MakerNoteVersion", (char *) NULL}, + { 0x0001, (char *) "MinoltaCameraSettingsOld", (char *) NULL}, + { 0x0003, (char *) "MinoltaCameraSettings", (char *) NULL}, + { 0x0004, (char *) "MinoltaCameraSettings7D", (char *) NULL}, + { 0x0018, (char *) "ImageStabilization", (char *) NULL}, + { 0x0040, (char *) "CompressedImageSize", (char *) NULL}, + { 0x0081, (char *) "PreviewImage", (char *) NULL}, + { 0x0088, (char *) "PreviewImageStart", (char *) NULL}, + { 0x0089, (char *) "PreviewImageLength", (char *) NULL}, + { 0x0100, (char *) "SceneMode", (char *) NULL}, + { 0x0101, (char *) "ColorMode", (char *) NULL}, + { 0x0102, (char *) "MinoltaQuality", (char *) NULL}, + { 0x0103, (char *) "MinoltaImageSize", (char *) NULL}, + { 0x0104, (char *) "FlashExposureComp", (char *) NULL}, + { 0x0105, (char *) "Teleconverter", (char *) NULL}, + { 0x0107, (char *) "ImageStabilization", (char *) NULL}, + { 0x0109, (char *) "RawAndJpgRecording", (char *) NULL}, + { 0x010A, (char *) "ZoneMatching", (char *) NULL}, + { 0x010B, (char *) "ColorTemperature", (char *) NULL}, + { 0x010C, (char *) "LensType", (char *) NULL}, + { 0x0111, (char *) "ColorCompensationFilter", (char *) NULL}, + { 0x0112, (char *) "WhiteBalanceFineTune", (char *) NULL}, + { 0x0113, (char *) "ImageStabilization", (char *) NULL}, + { 0x0114, (char *) "MinoltaCameraSettings5D", (char *) NULL}, + { 0x0115, (char *) "WhiteBalance", (char *) NULL}, + { 0x0E00, (char *) "PrintIM", (char *) NULL}, + { 0x0F00, (char *) "MinoltaCameraSettings2", (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} + }; + +/** +Nikon type 2 maker note +*/ +static TagInfo + exif_nikon_type2_tag_table[] = + { + { 0x0001, (char *) "MakerNoteVersion", (char *) NULL}, + { 0x0002, (char *) "ISO", (char *) NULL}, + { 0x0003, (char *) "ColorMode", (char *) NULL}, + { 0x0004, (char *) "Quality", (char *) NULL}, + { 0x0005, (char *) "WhiteBalance", (char *) NULL}, + { 0x0006, (char *) "Sharpness", (char *) NULL}, + { 0x0007, (char *) "FocusMode", (char *) NULL}, + { 0x0008, (char *) "FlashSetting", (char *) NULL}, + { 0x0009, (char *) "FlashType", (char *) NULL}, + { 0x000B, (char *) "WhiteBalanceFineTune", (char *) NULL}, + { 0x000F, (char *) "ISOSelection", (char *) NULL}, + { 0x0010, (char *) "DataDump", (char *) NULL}, + { 0x0080, (char *) "ImageAdjustment", (char *) NULL}, + { 0x0082, (char *) "AuxiliaryLens", (char *) NULL}, + { 0x0085, (char *) "ManualFocusDistance", (char *) NULL}, + { 0x0086, (char *) "DigitalZoom", (char *) NULL}, + { 0x0088, (char *) "AFInfo", (char *) NULL}, + { 0x0089, (char *) "ShootingMode", (char *) NULL}, + { 0x008D, (char *) "ColorMode", (char *) NULL}, + { 0x008F, (char *) "SceneMode", (char *) NULL}, + { 0x0092, (char *) "HueAdjustment", (char *) NULL}, + { 0x0094, (char *) "Saturation", (char *) NULL}, + { 0x0095, (char *) "NoiseReduction", (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 *) "MakerNoteVersion", (char *) NULL}, + { 0x0002, (char *) "ISO", (char *) NULL}, + { 0x0003, (char *) "ColorMode", (char *) NULL}, + { 0x0004, (char *) "Quality", (char *) NULL}, + { 0x0005, (char *) "WhiteBalance", (char *) NULL}, + { 0x0006, (char *) "Sharpness", (char *) NULL}, + { 0x0007, (char *) "FocusMode", (char *) NULL}, + { 0x0008, (char *) "FlashSetting", (char *) NULL}, + { 0x0009, (char *) "FlashType", (char *) NULL}, + { 0x000B, (char *) "WhiteBalanceFineTune", (char *) NULL}, + { 0x000C, (char *) "WB_RBLevels", (char *) NULL}, + { 0x000D, (char *) "ProgramShift", (char *) NULL}, + { 0x000E, (char *) "ExposureDifference", (char *) NULL}, + { 0x000F, (char *) "ISOSelection", (char *) NULL}, + { 0x0010, (char *) "DataDump", (char *) NULL}, + { 0x0011, (char *) "PreviewIFD", (char *) NULL}, + { 0x0012, (char *) "FlashExposureComp", (char *) NULL}, + { 0x0013, (char *) "ISOSetting", (char *) NULL}, + { 0x0014, (char *) "ColorBalanceA", (char *) NULL}, + { 0x0016, (char *) "ImageBoundary", (char *) NULL}, + { 0x0017, (char *) "FlashExposureComp", (char *) NULL}, + { 0x0018, (char *) "FlashExposureBracketValue", (char *) NULL}, + { 0x0019, (char *) "ExposureBracketValue", (char *) NULL}, + { 0x001A, (char *) "ImageProcessing", (char *) NULL}, + { 0x001B, (char *) "CropHiSpeed", (char *) NULL}, + { 0x001C, (char *) "ExposureTuning", (char *) NULL}, + { 0x001D, (char *) "SerialNumber", (char *) NULL}, + { 0x001E, (char *) "ColorSpace", (char *) NULL}, + { 0x001F, (char *) "VRInfo", (char *) NULL}, + { 0x0020, (char *) "ImageAuthentication", (char *) NULL}, + { 0x0022, (char *) "ActiveD-Lighting", (char *) NULL}, + { 0x0023, (char *) "PictureControl", (char *) NULL}, + { 0x0024, (char *) "WorldTime", (char *) NULL}, + { 0x0025, (char *) "ISOInfo", (char *) NULL}, + { 0x002A, (char *) "VignetteControl", (char *) NULL}, + { 0x002B, (char *) "DistortInfo", (char *) NULL}, + { 0x0080, (char *) "ImageAdjustment", (char *) NULL}, + { 0x0081, (char *) "ToneComp", (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}, + { 0x008B, (char *) "LensFStops", (char *) NULL}, + { 0x008C, (char *) "ContrastCurve", (char *) NULL}, + { 0x008D, (char *) "ColorHue", (char *) NULL}, + { 0x008F, (char *) "SceneMode", (char *) NULL}, + { 0x0090, (char *) "LightSource", (char *) NULL}, + { 0x0091, (char *) "ShotInfo", (char *) NULL}, + { 0x0092, (char *) "HueAdjustment", (char *) NULL}, + { 0x0093, (char *) "NEFCompression", (char *) NULL}, + { 0x0094, (char *) "Saturation", (char *) NULL}, + { 0x0095, (char *) "NoiseReduction", (char *) NULL}, + { 0x0096, (char *) "LinearizationTable", (char *) NULL}, + { 0x0097, (char *) "ColorBalance", (char *) NULL}, + { 0x0098, (char *) "LensData", (char *) NULL}, + { 0x0099, (char *) "RawImageCenter", (char *) NULL}, + { 0x009A, (char *) "SensorPixelSize", (char *) NULL}, + { 0x009C, (char *) "SceneAssist", (char *) NULL}, + { 0x009E, (char *) "RetouchHistory", (char *) NULL}, + { 0x00A0, (char *) "SerialNumber", (char *) NULL}, + { 0x00A2, (char *) "ImageDataSize", (char *) NULL}, + { 0x00A5, (char *) "ImageCount", (char *) NULL}, + { 0x00A6, (char *) "DeletedImageCount", (char *) NULL}, + { 0x00A7, (char *) "ShutterCount", (char *) NULL}, + { 0x00A8, (char *) "FlashInfo", (char *) NULL}, + { 0x00A9, (char *) "ImageOptimization", (char *) NULL}, + { 0x00AA, (char *) "Saturation", (char *) NULL}, + { 0x00AB, (char *) "VariProgram", (char *) NULL}, + { 0x00AC, (char *) "ImageStabilization", (char *) NULL}, + { 0x00AD, (char *) "AFResponse", (char *) NULL}, + { 0x00B0, (char *) "MultiExposure", (char *) NULL}, + { 0x00B1, (char *) "HighISONoiseReduction", (char *) NULL}, + { 0x00B3, (char *) "ToningEffect", (char *) NULL}, + { 0x00B6, (char *) "PowerUpTime", (char *) NULL}, + { 0x00B7, (char *) "AFInfo2", (char *) NULL}, + { 0x00B8, (char *) "FileInfo", (char *) NULL}, + { 0x00B9, (char *) "AFTune", (char *) NULL}, + { 0x00BD, (char *) "PictureControl", (char *) NULL}, + { 0x0E00, (char *) "PrintIM", (char *) NULL}, + { 0x0E01, (char *) "NikonCaptureData", (char *) NULL}, + { 0x0E09, (char *) "NikonCaptureVersion", (char *) NULL}, + { 0x0E0E, (char *) "NikonCaptureOffsets", (char *) NULL}, + { 0x0E10, (char *) "NikonScanIFD", (char *) NULL}, + { 0x0E1D, (char *) "NikonICCProfile", (char *) NULL}, + { 0x0E1E, (char *) "NikonCaptureOutput", (char *) NULL}, + { 0x0E22, (char *) "NEFBitDepth", (char *) NULL}, + { 0x0000, (char *) NULL, (char *) NULL} + }; + +/** +Panasonic / Leica 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 *) "AFAreaMode", (char *) NULL}, + { 0x001A, (char *) "ImageStabilization", (char *) NULL}, + { 0x001C, (char *) "MacroMode", (char *) NULL}, + { 0x001F, (char *) "ShootingMode", (char *) NULL}, + { 0x0020, (char *) "Audio", (char *) NULL}, + { 0x0021, (char *) "DataDump", (char *) NULL}, + { 0x0022, (char *) "EasyMode", (char *) NULL}, + { 0x0023, (char *) "WhiteBalanceBias", (char *) NULL}, + { 0x0024, (char *) "FlashBias", (char *) NULL}, + { 0x0025, (char *) "InternalSerialNumber", (char *) NULL}, + { 0x0026, (char *) "PanasonicExifVersion", (char *) NULL}, + { 0x0028, (char *) "ColorEffect", (char *) NULL}, + { 0x0029, (char *) "TimeSincePowerOn", (char *) NULL}, + { 0x002A, (char *) "BurstMode", (char *) NULL}, + { 0x002B, (char *) "SequenceNumber", (char *) NULL}, + { 0x002C, (char *) "ContrastMode", (char *) NULL}, + { 0x002D, (char *) "NoiseReduction", (char *) NULL}, + { 0x002E, (char *) "SelfTimer", (char *) NULL}, + { 0x0030, (char *) "Rotation", (char *) NULL}, + { 0x0031, (char *) "AFAssistLamp", (char *) NULL}, + { 0x0032, (char *) "ColorMode", (char *) NULL}, + { 0x0033, (char *) "BabyAge_0x0033", (char *) NULL}, + { 0x0034, (char *) "OpticalZoomMode", (char *) NULL}, + { 0x0035, (char *) "ConversionLens", (char *) NULL}, + { 0x0036, (char *) "TravelDay", (char *) NULL}, + { 0x0039, (char *) "Contrast", (char *) NULL}, + { 0x003A, (char *) "WorldTimeLocation", (char *) NULL}, + { 0x003B, (char *) "TextStamp_0x003B", (char *) NULL}, + { 0x003C, (char *) "ProgramISO", (char *) NULL}, + { 0x003D, (char *) "AdvancedSceneMode", (char *) NULL}, + { 0x003E, (char *) "TextStamp_0x003E", (char *) NULL}, + { 0x003F, (char *) "FacesDetected", (char *) NULL}, + { 0x0040, (char *) "Saturation", (char *) NULL}, + { 0x0041, (char *) "Sharpness", (char *) NULL}, + { 0x0042, (char *) "FilmMode", (char *) NULL}, + { 0x0046, (char *) "WBAdjustAB", (char *) NULL}, + { 0x0047, (char *) "WBAdjustGM", (char *) NULL}, + { 0x004B, (char *) "PanasonicImageWidth", (char *) NULL}, + { 0x004C, (char *) "PanasonicImageHeight", (char *) NULL}, + { 0x004D, (char *) "AFPointPosition", (char *) NULL}, + { 0x004E, (char *) "FaceDetInfo", (char *) "Panasonic FaceDetInfo Tags"}, + { 0x0051, (char *) "LensType", (char *) NULL}, + { 0x0052, (char *) "LensSerialNumber", (char *) NULL}, + { 0x0053, (char *) "AccessoryType", (char *) NULL}, + { 0x0059, (char *) "Transform", (char *) NULL}, + { 0x005D, (char *) "IntelligentExposure", (char *) NULL}, + { 0x0061, (char *) "FaceRecInfo", (char *) "Panasonic FaceRecInfo Tags"}, + { 0x0062, (char *) "FlashWarning", (char *) NULL}, + { 0x0063, (char *) "RecognizedFaceFlags?", (char *) NULL}, + { 0x0065, (char *) "Title", (char *) NULL}, + { 0x0066, (char *) "BabyName", (char *) NULL}, + { 0x0067, (char *) "Location", (char *) NULL}, + { 0x0069, (char *) "Country", (char *) NULL}, + { 0x006B, (char *) "State", (char *) NULL}, + { 0x006D, (char *) "City", (char *) NULL}, + { 0x006F, (char *) "Landmark", (char *) NULL}, + { 0x0070, (char *) "IntelligentResolution", (char *) NULL}, + { 0x0079, (char *) "IntelligentD-Range", (char *) NULL}, + { 0x0E00, (char *) "PrintIM", (char *) NULL}, + { 0x8000, (char *) "MakerNoteVersion", (char *) NULL}, + { 0x8001, (char *) "SceneMode", (char *) NULL}, + { 0x8004, (char *) "WBRedLevel", (char *) NULL}, + { 0x8005, (char *) "WBGreenLevel", (char *) NULL}, + { 0x8006, (char *) "WBBlueLevel", (char *) NULL}, + { 0x8007, (char *) "FlashFired", (char *) NULL}, + { 0x8008, (char *) "TextStamp_0x8008", (char *) NULL}, + { 0x8009, (char *) "TextStamp_0x8009", (char *) NULL}, + { 0x8010, (char *) "BabyAge_0x8010", (char *) NULL}, + { 0x8012, (char *) "Transform", (char *) NULL}, + { 0x0000, (char *) NULL, (char *) NULL} + }; + +/** +Pentax (Asahi) maker note type 1 +*/ +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} + }; + +/** +Pentax maker note type 2 +*/ +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 *) "Pentax PentaxModelID Values"}, + { 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}, + { 0x0015, (char *) "LightReading", (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 *) "Pentax City Values"}, + { 0x0024, (char *) "DestinationCity", (char *) "Pentax City Values"}, + { 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}, + { 0x0035, (char *) "SensorSize", (char *) NULL}, + { 0x0037, (char *) "ColorSpace", (char *) NULL}, + { 0x0039, (char *) "RawImageSize", (char *) NULL}, + { 0x003C, (char *) "AFPointsInFocus", (char *) NULL}, + { 0x003E, (char *) "PreviewImageBorders", (char *) NULL}, + { 0x003F, (char *) "LensType", (char *) "Pentax LensType Values"}, + { 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 *) "Pentax SRInfo Tags"}, + { 0x005D, (char *) "ShutterCount", (char *) NULL}, + { 0x0060, (char *) "FaceInfo", (char *) "Pentax FaceInfo Tags"}, + { 0x0067, (char *) "Hue", (char *) NULL}, + { 0x0068, (char *) "AWBInfo", (char *) "Pentax AWBInfo Tags"}, + { 0x0069, (char *) "DynamicRangeExpansion", (char *) NULL}, + { 0x006B, (char *) "TimeInfo", (char *) "Pentax TimeInfo Tags"}, + { 0x006C, (char *) "HighLowKeyAdj", (char *) NULL}, + { 0x006D, (char *) "ContrastHighlight", (char *) NULL}, + { 0x006E, (char *) "ContrastShadow", (char *) NULL}, + { 0x006F, (char *) "ContrastHighlightShadowAdj", (char *) NULL}, + { 0x0070, (char *) "FineSharpness", (char *) NULL}, + { 0x0071, (char *) "HighISONoiseReduction", (char *) NULL}, + { 0x0072, (char *) "AFAdjustment", (char *) NULL}, + { 0x0073, (char *) "MonochromeFilterEffect", (char *) NULL}, + { 0x0074, (char *) "MonochromeToning", (char *) NULL}, + { 0x0076, (char *) "FaceDetect", (char *) NULL}, + { 0x0077, (char *) "FaceDetectFrameSize", (char *) NULL}, + { 0x0079, (char *) "ShadowCompensation", (char *) NULL}, + { 0x007A, (char *) "ISOAutoParameters", (char *) NULL}, + { 0x007B, (char *) "CrossProcess", (char *) NULL}, + { 0x007D, (char *) "LensCorr", (char *) "Pentax LensCorr Tags"}, + { 0x007F, (char *) "BleachBypassToning", (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 *) "Pentax CameraSettings Tags"}, + { 0x0206, (char *) "AEInfo", (char *) "Pentax AEInfo Tags"}, + { 0x0207, (char *) "LensInfo", (char *) "Pentax LensInfo Tags"}, + { 0x0208, (char *) "FlashInfo", (char *) "Pentax FlashInfo Tags"}, + { 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 *) "Pentax CameraInfo Tags"}, + { 0x0216, (char *) "BatteryInfo", (char *) "Pentax BatteryInfo Tags"}, + { 0x021B, (char *) "SaturationInfo", (char *) NULL}, + { 0x021F, (char *) "AFInfo", (char *) "Pentax AFInfo Tags"}, + { 0x0222, (char *) "ColorInfo", (char *) "Pentax ColorInfo Tags"}, + { 0x0224, (char *) "EVStepInfo", (char *) "Pentax EVStepInfo Tags"}, + { 0x0226, (char *) "ShotInfo", (char *) "Pentax ShotInfo Tags"}, + { 0x0227, (char *) "FacePos", (char *) "Pentax FacePos Tags"}, + { 0x0228, (char *) "FaceSize", (char *) "Pentax FaceSize Tags"}, + { 0x0229, (char *) "SerialNumber", (char *) NULL}, + { 0x022A, (char *) "FilterInfo", (char *) "Pentax FilterInfo Tags"}, + { 0x022B, (char *) "LevelInfo", (char *) "Pentax LevelInfo Tags"}, + { 0x022E, (char *) "Artist", (char *) NULL}, + { 0x022F, (char *) "Copyright", (char *) NULL}, + { 0x0230, (char *) "FirmwareVersion", (char *) NULL}, + { 0x0231, (char *) "ContrastDetectAFArea", (char *) NULL}, + { 0x0235, (char *) "CrossProcessParams", (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[] = + { + { 0x0102, (char *) "Quality", (char *) NULL}, + { 0x0104, (char *) "FlashExposureComp", (char *) NULL}, + { 0x0105, (char *) "Teleconverter", (char *) NULL}, + { 0x0112, (char *) "WhiteBalanceFineTune", (char *) NULL}, + { 0x0114, (char *) "CameraSettings", (char *) NULL}, + { 0x0115, (char *) "WhiteBalance", (char *) NULL}, + { 0x0E00, (char *) "PrintIM", (char *) NULL}, + { 0x1000, (char *) "MultiBurstMode", (char *) NULL}, + { 0x1001, (char *) "MultiBurstImageWidth", (char *) NULL}, + { 0x1002, (char *) "MultiBurstImageHeight", (char *) NULL}, + { 0x1003, (char *) "Panorama", (char *) NULL}, + { 0x2001, (char *) "PreviewImage", (char *) NULL}, + { 0x2004, (char *) "Contrast", (char *) NULL}, + { 0x2005, (char *) "Saturation", (char *) NULL}, + { 0x2006, (char *) "Sharpness", (char *) NULL}, + { 0x2007, (char *) "Brightness", (char *) NULL}, + { 0x2008, (char *) "LongExposureNoiseReduction", (char *) NULL}, + { 0x2009, (char *) "HighISONoiseReduction", (char *) NULL}, + { 0x200A, (char *) "HDR", (char *) NULL}, + { 0x200B, (char *) "MultiFrameNoiseReduction", (char *) NULL}, + { 0x3000, (char *) "ShotInfo", (char *) NULL}, + { 0xB000, (char *) "FileFormat", (char *) NULL}, + { 0xB001, (char *) "SonyModelID", (char *) NULL}, + { 0xB020, (char *) "ColorReproduction", (char *) NULL}, + { 0xB021, (char *) "ColorTemperature", (char *) NULL}, + { 0xB022, (char *) "ColorCompensationFilter", (char *) NULL}, + { 0xB023, (char *) "SceneMode", (char *) NULL}, + { 0xB024, (char *) "ZoneMatching", (char *) NULL}, + { 0xB025, (char *) "DynamicRangeOptimizer", (char *) NULL}, + { 0xB026, (char *) "ImageStabilization", (char *) NULL}, + { 0xB027, (char *) "LensType", (char *) NULL}, + { 0xB028, (char *) "MinoltaMakerNote", (char *) NULL}, + { 0xB029, (char *) "ColorMode", (char *) NULL}, + { 0xB02B, (char *) "FullImageSize", (char *) NULL}, + { 0xB02C, (char *) "PreviewImageSize", (char *) NULL}, + { 0xB040, (char *) "Macro", (char *) NULL}, + { 0xB041, (char *) "ExposureMode", (char *) NULL}, + { 0xB042, (char *) "FocusMode", (char *) NULL}, + { 0xB043, (char *) "AFMode", (char *) NULL}, + { 0xB044, (char *) "AFIlluminator", (char *) NULL}, + { 0xB047, (char *) "Quality2", (char *) NULL}, + { 0xB048, (char *) "FlashLevel", (char *) NULL}, + { 0xB049, (char *) "ReleaseMode", (char *) NULL}, + { 0xB04A, (char *) "SequenceNumber", (char *) NULL}, + { 0xB04B, (char *) "Anti-Blur", (char *) NULL}, + { 0xB04E, (char *) "LongExposureNoiseReduction", (char *) NULL}, + { 0xB04F, (char *) "DynamicRangeOptimizer", (char *) NULL}, + { 0xB052, (char *) "IntelligentAuto", (char *) NULL}, + { 0xB054, (char *) "WhiteBalance2", (char *) NULL}, + { 0x0000, (char *) NULL, (char *) NULL} + }; + +/** +Sigma SD1 maker note +*/ +static TagInfo + exif_sigma_sd1_tag_table[] = + { + { 0x0002, (char *) "SerialNumber", (char *) NULL}, + { 0x0003, (char *) "DriveMode", (char *) NULL}, + { 0x0004, (char *) "ResolutionMode", (char *) NULL}, + { 0x0005, (char *) "AFMode", (char *) NULL}, + { 0x0006, (char *) "FocusSetting", (char *) NULL}, + { 0x0007, (char *) "WhiteBalance", (char *) NULL}, + { 0x0008, (char *) "ExposureMode", (char *) NULL}, + { 0x0009, (char *) "MeteringMode", (char *) NULL}, + { 0x000A, (char *) "LensFocalRange", (char *) NULL}, + { 0x000B, (char *) "ColorSpace", (char *) NULL}, + { 0x000C, (char *) "ExposureCompensation", (char *) NULL}, + { 0x000D, (char *) "Contrast", (char *) NULL}, + { 0x000E, (char *) "Shadow", (char *) NULL}, + { 0x000F, (char *) "Highlight", (char *) NULL}, + { 0x0010, (char *) "Saturation", (char *) NULL}, + { 0x0011, (char *) "Sharpness", (char *) NULL}, + { 0x0012, (char *) "X3FillLight", (char *) NULL}, + { 0x0014, (char *) "ColorAdjustment", (char *) NULL}, + { 0x0015, (char *) "AdjustmentMode", (char *) NULL}, + { 0x0016, (char *) "Quality", (char *) NULL}, + { 0x0017, (char *) "Firmware", (char *) NULL}, + { 0x0018, (char *) "Software", (char *) NULL}, + { 0x0019, (char *) "AutoBracket", (char *) NULL}, + { 0x001A, (char *) "ChrominanceNoiseReduction", (char *) NULL}, + { 0x001B, (char *) "LuminanceNoiseReduction", (char *) NULL}, + { 0x001C, (char *) "PreviewImageStart", (char *) NULL}, + { 0x001D, (char *) "PreviewImageLength", (char *) NULL}, + { 0x001F, (char *) "MakerNoteVersion", (char *) NULL}, + { 0x0026, (char *) "FileFormat", (char *) NULL}, + { 0x002C, (char *) "ColorMode", (char *) NULL}, + { 0x0030, (char *) "Calibration", (char *) NULL}, + { 0x0048, (char *) "LensApertureRange", (char *) NULL}, + { 0x0049, (char *) "FNumber", (char *) NULL}, + { 0x004A, (char *) "ExposureTime", (char *) NULL}, + { 0x004B, (char *) "ExposureTime2", (char *) NULL}, + { 0x004D, (char *) "ExposureCompensation_SD1", (char *) NULL}, + { 0x0055, (char *) "SensorTemperature", (char *) NULL}, + { 0x0056, (char *) "FlashExposureComp", (char *) NULL}, + { 0x0057, (char *) "Firmware_SD1", (char *) NULL}, + { 0x0058, (char *) "WhiteBalance", (char *) NULL}, + { 0x0000, (char *) NULL, (char *) NULL} + }; + +/** +Sigma / Foveon maker note (others than SD1 models) +NB: many tags are not consistent between different models +*/ +static TagInfo + exif_sigma_foveon_tag_table[] = + { + { 0x0002, (char *) "SerialNumber", (char *) NULL}, + { 0x0003, (char *) "DriveMode", (char *) NULL}, + { 0x0004, (char *) "ResolutionMode", (char *) NULL}, + { 0x0005, (char *) "AFMode", (char *) NULL}, + { 0x0006, (char *) "FocusSetting", (char *) NULL}, + { 0x0007, (char *) "WhiteBalance", (char *) NULL}, + { 0x0008, (char *) "ExposureMode", (char *) NULL}, + { 0x0009, (char *) "MeteringMode", (char *) NULL}, + { 0x000A, (char *) "LensFocalRange", (char *) NULL}, + { 0x000B, (char *) "ColorSpace", (char *) NULL}, + { 0x000C, (char *) "ExposureCompensation", (char *) NULL}, + { 0x000D, (char *) "Contrast", (char *) NULL}, + { 0x000E, (char *) "Shadow", (char *) NULL}, + { 0x000F, (char *) "Highlight", (char *) NULL}, + { 0x0010, (char *) "Saturation", (char *) NULL}, + { 0x0011, (char *) "Sharpness", (char *) NULL}, + { 0x0012, (char *) "X3FillLight", (char *) NULL}, + { 0x0014, (char *) "ColorAdjustment", (char *) NULL}, + { 0x0015, (char *) "AdjustmentMode", (char *) NULL}, + { 0x0016, (char *) "Quality", (char *) NULL}, + { 0x0017, (char *) "Firmware", (char *) NULL}, + { 0x0018, (char *) "Software", (char *) NULL}, + { 0x0019, (char *) "AutoBracket", (char *) NULL}, + { 0x001A, (char *) "PreviewImageStart", (char *) NULL}, + { 0x001B, (char *) "PreviewImageLength", (char *) NULL}, + { 0x001C, (char *) "PreviewImageSize", (char *) NULL}, + { 0x001D, (char *) "MakerNoteVersion", (char *) NULL}, + { 0x001F, (char *) "AFPoint", (char *) NULL}, + { 0x0022, (char *) "FileFormat", (char *) NULL}, + { 0x0024, (char *) "Calibration", (char *) NULL}, + { 0x002C, (char *) "ColorMode", (char *) NULL}, + { 0x0030, (char *) "LensApertureRange", (char *) NULL}, + { 0x0031, (char *) "FNumber", (char *) NULL}, + { 0x0032, (char *) "ExposureTime", (char *) NULL}, + { 0x0033, (char *) "ExposureTime2", (char *) NULL}, + { 0x0034, (char *) "BurstShot", (char *) NULL}, + { 0x0035, (char *) "ExposureCompensation", (char *) NULL}, + { 0x0039, (char *) "SensorTemperature", (char *) NULL}, + { 0x003A, (char *) "FlashExposureComp", (char *) NULL}, + { 0x003B, (char *) "Firmware", (char *) NULL}, + { 0x003C, (char *) "WhiteBalance", (char *) NULL}, + { 0x003D, (char *) "PictureMode", (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); + addMetadataModel(TagLib::EXIF_MAKERNOTE_SIGMA_SD1, exif_sigma_sd1_tag_table); + addMetadataModel(TagLib::EXIF_MAKERNOTE_SIGMA_FOVEON, exif_sigma_foveon_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 + if ((_table_map.find(md_model) == _table_map.end()) && (tag_table != NULL)) { + + // add the tag description table + TAGINFO *info_map = new(std::nothrow) TAGINFO(); + if (!info_map) return FALSE; + + 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) { + + if(_table_map.find(md_model) != _table_map.end()) { + + TAGINFO *info_map = (TAGINFO*)_table_map[md_model]; + if(info_map->find(tagID) != info_map->end()) { + 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) { + + if(_table_map.find(md_model) != _table_map.end()) { + + TAGINFO *info_map = (TAGINFO*)_table_map[md_model]; + 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: + case EXIF_MAKERNOTE_SIGMA_SD1: + case EXIF_MAKERNOTE_SIGMA_FOVEON: + 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/plugins/FreeImage/src/Metadata/XTIFF.cpp b/plugins/FreeImage/src/Metadata/XTIFF.cpp new file mode 100644 index 0000000000..bc63cf38b2 --- /dev/null +++ b/plugins/FreeImage/src/Metadata/XTIFF.cpp @@ -0,0 +1,661 @@ +// ========================================================== +// Metadata functions implementation +// Extended TIFF Directory GEO Tag Support +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// - Thorsten Radde (support@IdealSoftware.com) +// - Berend Engelbrecht (softwarecave@users.sourceforge.net) +// - Mihail Naydenov (mnaydenov@users.sourceforge.net) +// +// 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 "../LibTIFF4/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, ¶ms)) { + // 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(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 & writing +// ---------------------------------------------------------- + +/** +Read a single exif tag +*/ +static BOOL +tiff_read_exif_tag(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib, TagLib& tagLib, TIFFDirectory *td, uint32 tag) { + const TIFFField *fip; + uint32 value_count; + int mem_alloc = 0; + void *raw_data = NULL; + + if(tag == TIFFTAG_EXIFIFD) { + return TRUE; + } + + // get the tag key - use NULL to avoid reading GeoTIFF tags + const char *key = tagLib.getTagFieldName(md_model, (WORD)tag, NULL); + if(key == NULL) { + return TRUE; + } + + fip = TIFFFieldWithTag(tif, tag); + if(fip == NULL) { + return TRUE; + } + + if(fip->field_passcount) { //<- "passcount" means "returns count" + if (fip->field_readcount != TIFF_VARIABLE2) { //<- TIFF_VARIABLE2 means "uses LONG count" + + // assume TIFF_VARIABLE (uses SHORT count) + uint16 value_count16; + if(TIFFGetField(tif, tag, &value_count16, &raw_data) != 1) { + return TRUE; + } + value_count = value_count16; + } else { + if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) { + return TRUE; + } + } + } else { + + // determine count + + 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; + } + + // access fields as pointers to data + // (### determining this is NOT robust... and hardly can be. It is implemented looking the _TIFFVGetField code) + + if(fip->field_tag == TIFFTAG_TRANSFERFUNCTION) { + // reading this tag cause a bug probably located somewhere inside libtiff + return TRUE; + } + + 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 + + && fip->field_tag != TIFFTAG_BITSPERSAMPLE //<- these two are tricky - + && fip->field_tag != TIFFTAG_COMPRESSION //<- they are defined as TIFF_VARIABLE but in reality return a single value + ) { + if(TIFFGetField(tif, tag, &raw_data) != 1) { + return TRUE; + } + } else { + + // access fields as values + + const int value_size = _TIFFDataSize(fip->field_type); + raw_data = _TIFFmalloc(value_size * value_count); + mem_alloc = 1; + int ok = FALSE; + + // ### if value_count > 1, tag is PAGENUMBER or HALFTONEHINTS or YCBCRSUBSAMPLING or DOTRANGE, + // all off which are value_count == 2 (see tif_dirinfo.c) + switch(value_count) + { + case 1: + ok = TIFFGetField(tif, tag, raw_data); + break; + case 2: + ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1); + break; +/* # we might need more in the future: + case 3: + ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1, (BYTE*)(raw_data) + value_size*2); + break; +*/ + default: + FreeImage_OutputMessageProc(FIF_TIFF, "Unimplemented variable number of parameters for Tiff Tag %s", fip->field_name); + break; + } + if(ok != 1) { + _TIFFfree(raw_data); + return TRUE; + } + } + } + + // build FreeImage tag from Tiff Tag data we collected + + 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; + + case TIFF_LONG8: // BigTIFF 64-bit unsigned integer + FreeImage_SetTagType(fitag, FIDT_LONG8); + FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); + FreeImage_SetTagCount(fitag, value_count); + FreeImage_SetTagValue(fitag, raw_data); + break; + + case TIFF_IFD8: // BigTIFF 64-bit unsigned integer (offset) + FreeImage_SetTagType(fitag, FIDT_IFD8); + FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count); + FreeImage_SetTagCount(fitag, value_count); + FreeImage_SetTagValue(fitag, raw_data); + break; + + case TIFF_SLONG8: // BigTIFF 64-bit signed integer + FreeImage_SetTagType(fitag, FIDT_SLONG8); + 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; +} + +/** +Read all known exif tags +*/ +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++) { + uint32 tag = TIFFGetTagListEntry(tif, i); + // read the tag + if (!tiff_read_exif_tag(tif, md_model, dib, tagLib, td, tag)) + return FALSE; + } + + // we want to know values of standard tags too!! + + // loop over all Core Directory Tags + // ### uses private data, but there is no other way + if(md_model == TagLib::EXIF_MAIN) { + + uint32 lastTag = 0; //<- used to prevent reading some tags twice (as stored in tif_fieldinfo) + + for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) { + const TIFFField *fld = tif->tif_fields[fi]; + + if(fld->field_tag == lastTag) + continue; + + // test if tag value is set + // (lifted directly form LibTiff _TIFFWriteDirectory) + + if ( fld->field_bit == FIELD_CUSTOM ) { + int ci, is_set = FALSE; + + for ( ci = 0; ci < td->td_customValueCount; ci++ ) { + is_set |= (td->td_customValues[ci].info == fld); + } + + if ( !is_set ) { + continue; + } + + } else if (!TIFFFieldSet(tif, fld->field_bit)) { + continue; + } + + // process *all* other tags (some will be ignored) + + tiff_read_exif_tag(tif, md_model, dib, tagLib, td, fld->field_tag); + + + lastTag = fld->field_tag; + } + + } + + return TRUE; + +} + + +/** +Skip tags that are already handled by the LibTIFF writing process +*/ +static BOOL +skip_write_field(TIFF* tif, uint32 tag) { + switch (tag) { + case TIFFTAG_SAMPLEFORMAT: + case TIFFTAG_IMAGEWIDTH: + case TIFFTAG_IMAGELENGTH: + case TIFFTAG_SAMPLESPERPIXEL: + case TIFFTAG_BITSPERSAMPLE: + case TIFFTAG_PHOTOMETRIC: + case TIFFTAG_PLANARCONFIG: + case TIFFTAG_ROWSPERSTRIP: + case TIFFTAG_RESOLUTIONUNIT: + case TIFFTAG_XRESOLUTION: + case TIFFTAG_YRESOLUTION: + case TIFFTAG_SUBFILETYPE: + case TIFFTAG_PAGENUMBER: + case TIFFTAG_COLORMAP: + case TIFFTAG_ORIENTATION: + case TIFFTAG_COMPRESSION: + case TIFFTAG_PREDICTOR: + case TIFFTAG_GROUP3OPTIONS: + case TIFFTAG_FILLORDER: + // skip always, values have been set in SaveOneTIFF() + return TRUE; + break; + + case TIFFTAG_RICHTIFFIPTC: + // skip always, IPTC metadata model is set in tiff_write_iptc_profile() + return TRUE; + break; + + case TIFFTAG_YCBCRCOEFFICIENTS: + case TIFFTAG_REFERENCEBLACKWHITE: + case TIFFTAG_YCBCRSUBSAMPLING: + // skip as they cannot be filled yet + return TRUE; + break; + + case TIFFTAG_PAGENAME: + { + char *value = NULL; + TIFFGetField(tif, TIFFTAG_PAGENAME, &value); + // only skip if no value has been set + if(value == NULL) { + return FALSE; + } else { + return TRUE; + } + } + default: + return FALSE; + break; + } +} + +/** +Write all known exif tags +*/ +BOOL +tiff_write_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) { + char defaultKey[16]; + + // only EXIF_MAIN so far + if(md_model != TagLib::EXIF_MAIN) { + return FALSE; + } + + if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib) == 0) { + return FALSE; + } + + TagLib& tag_lib = TagLib::instance(); + + for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) { + const TIFFField *fld = tif->tif_fields[fi]; + + if(skip_write_field(tif, fld->field_tag)) { + // skip tags that are already handled by the LibTIFF writing process + continue; + } + + FITAG *tag = NULL; + // get the tag key + const char *key = tag_lib.getTagFieldName(TagLib::EXIF_MAIN, (WORD)fld->field_tag, defaultKey); + + if(FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, key, &tag)) { + FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag); + TIFFDataType tif_tag_type = fld->field_type; + + // check for identical formats + + // (enum value are the sames between FREE_IMAGE_MDTYPE and TIFFDataType types) + if ((int)tif_tag_type != (int)tag_type) { + // skip tag or _TIFFmemcpy will fail + continue; + } + // type of storage may differ (e.g. rationnal array vs float array type) + if(_TIFFDataSize(tif_tag_type) != FreeImage_TagDataWidth(tag_type)) { + // skip tag or _TIFFmemcpy will fail + continue; + } + + if(tag_type == FIDT_ASCII) { + TIFFSetField(tif, fld->field_tag, FreeImage_GetTagValue(tag)); + } else { + TIFFSetField(tif, fld->field_tag, FreeImage_GetTagCount(tag), FreeImage_GetTagValue(tag)); + } + } + } + + return TRUE; +} diff --git a/plugins/FreeImage/src/Plugin.h b/plugins/FreeImage/src/Plugin.h new file mode 100644 index 0000000000..dbb4540ef5 --- /dev/null +++ b/plugins/FreeImage/src/Plugin.h @@ -0,0 +1,142 @@ +// ========================================================== +// 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" + +// ========================================================== + +struct Plugin; + +// ===================================================================== +// Plugin Node +// ===================================================================== + +FI_STRUCT (PluginNode) { + /** FREE_IMAGE_FORMAT attached to this plugin */ + int m_id; + /** Handle to a user plugin DLL (NULL for standard plugins) */ + void *m_instance; + /** The actual plugin, holding the function pointers */ + Plugin *m_plugin; + /** Enable/Disable switch */ + BOOL m_enabled; + + /** Unique format string for the plugin */ + const char *m_format; + /** Description string for the plugin */ + const char *m_description; + /** Comma separated list of file extensions indicating what files this plugin can open */ + const char *m_extension; + /** optional regular expression to help software identifying a bitmap type */ + 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 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); +void DLL_CALLCONV InitEXR(Plugin *plugin, int format_id); +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); +void DLL_CALLCONV InitJNG(Plugin *plugin, int format_id); + +#endif //!PLUGIN_H diff --git a/plugins/FreeImage/src/Quantizers.h b/plugins/FreeImage/src/Quantizers.h new file mode 100644 index 0000000000..2a671fad1c --- /dev/null +++ b/plugins/FreeImage/src/Quantizers.h @@ -0,0 +1,225 @@ +// ============================================================= +// Quantizer objects and functions +// +// 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 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/plugins/FreeImage/src/ToneMapping.h b/plugins/FreeImage/src/ToneMapping.h new file mode 100644 index 0000000000..0519933c68 --- /dev/null +++ b/plugins/FreeImage/src/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/plugins/FreeImage/src/Utilities.h b/plugins/FreeImage/src/Utilities.h new file mode 100644 index 0000000000..b743325129 --- /dev/null +++ b/plugins/FreeImage/src/Utilities.h @@ -0,0 +1,484 @@ +// ========================================================== +// Utility functions +// +// Design and implementation by +// - Floris van den Berg (flvdberg@wxs.nl) +// - Hervé Drolon +// - 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ========================================================== +// 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); + +#if defined(__cplusplus) +extern "C" { +#endif + +/** +Allocate a FIBITMAP with possibly no pixel data +(i.e. only header data and some or all metadata) +@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP +@param type Image type +@param width +@param height +@param bpp +@param red_mask +@param green_mask +@param blue_mask +@see FreeImage_AllocateT +*/ +DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeaderT(BOOL header_only, 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)); + +/** +Allocate a FIBITMAP of type FIT_BITMAP, with possibly no pixel data +(i.e. only header data and some or all metadata) +@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP +@param width +@param height +@param bpp +@param red_mask +@param green_mask +@param blue_mask +@see FreeImage_Allocate +*/ +DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeader(BOOL header_only, int width, int height, int bpp, unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0)); + +#if defined(__cplusplus) +} +#endif + + +// ========================================================== +// 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 + +// ========================================================== +// Template utility functions +// ========================================================== + +/// Max function +template T MAX(const T &a, const T &b) { + return (a > b) ? a: b; +} + +/// Min function +template T MIN(const T &a, const T &b) { + return (a < b) ? a: b; +} + +/// INPLACESWAP adopted from codeguru.com +template void INPLACESWAP(T& a, T& b) { + a ^= b; b ^= a; a ^= b; +} + +/// Clamp function +template T CLAMP(const T &value, const T &min_value, const T &max_value) { + return ((value < min_value) ? min_value : (value > max_value) ? max_value : value); +} + +/** 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 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; + } + } +} + +// ========================================================== +// 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 unsigned +CalculateLine(unsigned width, unsigned bitdepth) { + return (unsigned)( ((unsigned __int64)width * bitdepth + 7) / 8 ); +} + +inline unsigned +CalculatePitch(unsigned line) { + return line + 3 & ~3; +} + +inline unsigned +CalculateUsedPaletteEntries(unsigned 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)); +} + +// ---------------------------------------------------------- + +/** +Fast generic assign (faster than for loop) +@param dst Destination pixel +@param src Source pixel +@param bytesperpixel # of bytes per pixel +*/ +inline void +AssignPixel(BYTE* dst, const BYTE* src, unsigned bytesperpixel) { + switch (bytesperpixel) { + case 1: // FIT_BITMAP (8-bit) + *dst = *src; + break; + + case 2: // FIT_UINT16 / FIT_INT16 / 16-bit + *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); + break; + + case 3: // FIT_BITMAP (24-bit) + *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); + dst[2] = src[2]; + break; + + case 4: // FIT_BITMAP (32-bit) / FIT_UINT32 / FIT_INT32 / FIT_FLOAT + *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); + break; + + case 6: // FIT_RGB16 (3 x 16-bit) + *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); + *(reinterpret_cast(dst + 4)) = *(reinterpret_cast (src + 4)); + break; + + // the rest can be speeded up with int64 + + case 8: // FIT_RGBA16 (4 x 16-bit) + *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); + *(reinterpret_cast(dst + 4)) = *(reinterpret_cast (src + 4)); + break; + + case 12: // FIT_RGBF (3 x 32-bit IEEE floating point) + *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); + *(reinterpret_cast(dst + 4)) = *(reinterpret_cast (src + 4)); + *(reinterpret_cast(dst + 8)) = *(reinterpret_cast (src + 8)); + break; + + case 16: // FIT_RGBAF (4 x 32-bit IEEE floating point) + *(reinterpret_cast(dst)) = *(reinterpret_cast (src)); + *(reinterpret_cast(dst + 4)) = *(reinterpret_cast (src + 4)); + *(reinterpret_cast(dst + 8)) = *(reinterpret_cast (src + 8)); + *(reinterpret_cast(dst + 12)) = *(reinterpret_cast (src + 12)); + break; + + default: + assert(FALSE); + } +} + +/** +Swap red and blue channels in a 24- or 32-bit dib. +@return Returns TRUE if successful, returns FALSE otherwise +@see See definition in Conversion.cpp +*/ +BOOL SwapRedBlue32(FIBITMAP* dib); + +/** +Inplace convert CMYK to RGBA.(8- and 16-bit). +Alpha is filled with the first extra channel if any or white otherwise. +@return Returns TRUE if successful, returns FALSE otherwise +@see See definition in Conversion.cpp +*/ +BOOL ConvertCMYKtoRGBA(FIBITMAP* dib); + +/** +Inplace convert CIELab to RGBA (8- and 16-bit). +@return Returns TRUE if successful, returns FALSE otherwise +@see See definition in Conversion.cpp +*/ +BOOL ConvertLABtoRGB(FIBITMAP* dib); + +/** +RGBA to RGB conversion +@see See definition in Conversion.cpp +*/ +FIBITMAP* RemoveAlphaChannel(FIBITMAP* dib); + + +// ========================================================== +// 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 +// ========================================================== + +/** +Extract the luminance channel L from a RGBF image. +Luminance is calculated from the sRGB model using a D65 white point, using the Rec.709 formula : +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 +*/ +#define LUMA_REC709(r, g, b) (0.2126F * r + 0.7152F * g + 0.0722F * b) + +#define GREY(r, g, b) (BYTE)LUMA_REC709(r, g, b) +/* +#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; \ + } + +// ========================================================== +// Generic error messages +// ========================================================== + +static const char *FI_MSG_ERROR_MEMORY = "Memory allocation failed"; +static const char *FI_MSG_ERROR_DIB_MEMORY = "DIB allocation failed, maybe caused by an invalid image size or by a lack of memory"; +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"; +static const char *FI_MSG_WARNING_INVALID_THUMBNAIL = "Warning: attached thumbnail cannot be written to output file (invalid format) - Thumbnail saving aborted"; + +#endif // UTILITIES_H diff --git a/plugins/FreeImage/src/Zlib/zconf.h b/plugins/FreeImage/src/Zlib/zconf.h new file mode 100644 index 0000000000..93c1bb27e3 --- /dev/null +++ b/plugins/FreeImage/src/Zlib/zconf.h @@ -0,0 +1,468 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2011 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.8 2012/02/05 18:10:25 drolon Exp $ */ + +#ifndef ZCONF_H +#define ZCONF_H +/* #undef Z_PREFIX */ +/* #undef Z_HAVE_UNISTD_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. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflags z_gzflags +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# endif +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# ifndef Z_SOLO +# define gz_header_s z_gz_header_s +# endif +# define internal_state z_internal_state + +#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 + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#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 + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(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 + /* 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 /*#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define Z_LARGE +#endif + +#if (defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE)) && !defined(Z_SOLO) +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# 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(_WIN32) && (defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0) +# define z_off64_t off64_t +#else +# if defined(_WIN32) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +#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/plugins/FreeImage/src/Zlib/zlib.h b/plugins/FreeImage/src/Zlib/zlib.h new file mode 100644 index 0000000000..79142d1172 --- /dev/null +++ b/plugins/FreeImage/src/Zlib/zlib.h @@ -0,0 +1,1732 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.6, January 29th, 2012 + + Copyright (C) 1995-2012 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://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.6" +#define ZLIB_VERNUM 0x1260 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 6 +#define ZLIB_VER_SUBREVISION 0 + +/* + 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, + 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 { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number 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 number of bytes output so far */ + + z_const 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 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* 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, or + 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 accumulate 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. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + 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). Then deflate is guaranteed to + return Z_STREAM_END. If not enough output space is provided, deflate will + not return Z_STREAM_END, and 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 Z_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, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +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, + Z_BLOCK, or Z_TREES. 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. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + 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 not required to perform an + inflation in one step. However it may be used to inform inflate that a + faster approach can be used for the single inflate() call. Z_FINISH also + informs inflate to not maintain a sliding window if the stream completes, + which reduces inflate's memory footprint. + + 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 effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 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() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). 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. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + producted so far. The CRC-32 is checked against the gzip 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 + next_in or next_out was Z_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_STRATEGY 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 any parameter is invalid (such as an invalid + method), or 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. 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. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. 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 + provided in deflateInit or deflateInit2. 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 (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). 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 Z_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 Z_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(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +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, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, 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 zero to request that inflate use the window size in + the zlib header of the compressed stream. + + 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_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +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 at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. 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 (e.g. dictionary being Z_NULL) 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 possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible 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 Z_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 Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +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. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + 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 or Z_TREES 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 parameters 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_in 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) + */ + +#ifndef Z_SOLO + + /* 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 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. + + 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 uncompressed buffer. + + 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. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + + /* gzip file access functions */ + +/* + This library 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. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +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", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + 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. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +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 (if 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 fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +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 is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -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 written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will 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. This can be determined using + zlibCompileFlags(). +*/ + +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. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +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. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + 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 is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +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, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +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. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +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. +*/ + +#endif /* !Z_SOLO */ + + /* 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 Z_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. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +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 Z_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, (int)sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); +#define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc_(g)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#ifndef Z_SOLO + ZEXTERN unsigned long ZEXPORT gzflags OF((void)); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/plugins/FreeImage/src/Zlib/zutil.h b/plugins/FreeImage/src/Zlib/zutil.h new file mode 100644 index 0000000000..8f33fd3e7d --- /dev/null +++ b/plugins/FreeImage/src/Zlib/zutil.h @@ -0,0 +1,248 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2011 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.8 2012/02/05 18:10:25 drolon Exp $ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#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 +# ifndef Z_SOLO +# 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 +# endif +# else /* MSC or DJGPP */ +# include +# endif +# 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 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# 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)) && !defined __INTERIX +# 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 + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#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(pyr) || defined(Z_SOLO) +# 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 + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL 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 + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#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/plugins/FreeImage/src/main.cpp b/plugins/FreeImage/src/main.cpp new file mode 100644 index 0000000000..a2ae903485 --- /dev/null +++ b/plugins/FreeImage/src/main.cpp @@ -0,0 +1,1255 @@ +/* +Plugin of Miranda IM for reading/writing PNG images. +Copyright (c) 2004-6 George Hazan (ghazan@postman.ru) + +Portions of this code are gotten from the libpng codebase. +Copyright 2000, Willem van Schaik. For conditions of distribution and +use, see the copyright/license/disclaimer notice in png.h + +Miranda IM: the free icq client for MS Windows +Copyright (C) 2000-2002 Richard Hughes, Roland Rabien & Tristan Van de Vreede + +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. + +File name : $Source: /cvsroot/miranda/miranda/plugins/png2dib/png2dib.c,v $ +Revision : $Revision: 5041 $ +Last change on : $Date: 2007-03-06 22:13:28 +0100 (Di, 06 Mär 2007) $ +Last change by : $Author: rainwater $ + +*/ + +#include + +#include +#include + +#include +#include + +#include + +#include "newpluginapi.h" +#include "version.h" + +#include "libpng/png.h" + +static const PLUGININFOEX pluginInfoEx = { + sizeof(PLUGININFOEX), + __PLUGIN_NAME, + PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), + __DESCRIPTION, + __AUTHOR, + __AUTHOREMAIL, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, + // {7C070F7C-459E-46b7-8E6D-BC6EFAA22F78} + { 0x7c070f7c, 0x459e, 0x46b7, { 0x8e, 0x6d, 0xbc, 0x6e, 0xfa, 0xa2, 0x2f, 0x78 } } +}; + +/* +* freeimage helper functions +*/ + +// Correct alpha from bitmaps loaded without it (it cames with 0 and should be 255) +// originally in loadavatars... + +static void FI_CorrectBitmap32Alpha(HBITMAP hBitmap, BOOL force) +{ + BITMAP bmp; + DWORD dwLen; + BYTE *p; + int x, y; + BOOL fixIt; + + GetObject(hBitmap, sizeof(bmp), &bmp); + + if (bmp.bmBitsPixel != 32) + return; + + dwLen = bmp.bmWidth * bmp.bmHeight * (bmp.bmBitsPixel / 8); + p = (BYTE *)malloc(dwLen); + if (p == NULL) + return; + memset(p, 0, dwLen); + + GetBitmapBits(hBitmap, dwLen, p); + + fixIt = TRUE; + for (y = 0; fixIt && y < bmp.bmHeight; ++y) { + BYTE *px = p + bmp.bmWidth * 4 * y; + + for (x = 0; fixIt && x < bmp.bmWidth; ++x) + { + if (px[3] != 0 && !force) + { + fixIt = FALSE; + } + else + { + px[3] = 255; + } + + px += 4; + } + } + + if (fixIt) + SetBitmapBits(hBitmap, dwLen, p); + + free(p); +} + +/* +* needed for per pixel transparent images. Such images should then be rendered by +* using AlphaBlend() with AC_SRC_ALPHA +* dwFlags will be set to AVS_PREMULTIPLIED +* return TRUE if the image has at least one pixel with transparency +*/ +static BOOL FreeImage_PreMultiply(HBITMAP hBitmap) +{ + BYTE *p = NULL; + DWORD dwLen; + int width, height, x, y; + BITMAP bmp; + BYTE alpha; + BOOL transp = FALSE; + + GetObject(hBitmap, sizeof(bmp), &bmp); + width = bmp.bmWidth; + height = bmp.bmHeight; + dwLen = width * height * 4; + p = (BYTE *)malloc(dwLen); + if (p != NULL) + { + GetBitmapBits(hBitmap, dwLen, p); + + for (y = 0; y < height; ++y) + { + BYTE *px = p + width * 4 * y; + + for (x = 0; x < width; ++x) + { + alpha = px[3]; + + if (alpha < 255) + { + transp = TRUE; + + px[0] = px[0] * alpha/255; + px[1] = px[1] * alpha/255; + px[2] = px[2] * alpha/255; + } + + px += 4; + } + } + + if (transp) + dwLen = SetBitmapBits(hBitmap, dwLen, p); + free(p); + } + + return transp; +} + +static HBITMAP FreeImage_CreateHBITMAPFromDIB(FIBITMAP *in) +{ + FIBITMAP *dib = NULL; + int bpp = FreeImage_GetBPP(in); + + if (bpp == 48) + dib = FreeImage_ConvertTo24Bits(in); + else if (FreeImage_GetBPP(in) > 32) + dib = FreeImage_ConvertTo32Bits(in); + else + dib = in; + + BYTE *ptPixels; + BITMAPINFO *info = FreeImage_GetInfo(dib); + HBITMAP hBmp = CreateDIBSection(NULL, info, DIB_RGB_COLORS, (void **)&ptPixels, NULL, 0); + if (ptPixels != NULL) + memmove(ptPixels, FreeImage_GetBits(dib), FreeImage_GetPitch(dib) * FreeImage_GetHeight(dib)); + + if (dib != in) + FreeImage_Unload(dib); + + return hBmp; +} + +static FIBITMAP *FreeImage_CreateDIBFromHBITMAP(HBITMAP hBmp) +{ + BITMAP bm; + + if(hBmp) { + GetObject(hBmp, sizeof(BITMAP), (LPSTR) &bm); + FIBITMAP *dib = FreeImage_Allocate(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel,0,0,0); + // 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); + HDC dc = GetDC(NULL); + int Success = GetDIBits(dc, hBmp, 0, FreeImage_GetHeight(dib), + FreeImage_GetBits(dib), FreeImage_GetInfo(dib), DIB_RGB_COLORS); + ReleaseDC(NULL, dc); + // restore BITMAPINFO members + FreeImage_GetInfoHeader(dib)->biClrUsed = nColors; + FreeImage_GetInfoHeader(dib)->biClrImportant = nColors; + return dib; + } + return NULL; +} + + +// Resize ///////////////////////////////////////////////////////////////////////////////////////// + + +// Returns a copy of the bitmap with the size especified +// !! the caller is responsible for destroying the original bitmap when it is no longer needed !! +// wParam = ResizeBitmap * +// lParam = NULL +// return NULL on error, ResizeBitmap->hBmp if don't need to resize or a new HBITMAP if resized + +static INT_PTR serviceBmpFilterResizeBitmap(WPARAM wParam,LPARAM lParam) +{ + BITMAP bminfo; + int width, height; + int xOrig, yOrig, widthOrig, heightOrig; + ResizeBitmap *info = (ResizeBitmap *) wParam; + + if (info == NULL || info->size != sizeof(ResizeBitmap) + || info->hBmp == NULL || info->max_width <= 0 + || info->max_height <= 0 + || (info->fit & ~RESIZEBITMAP_FLAG_DONT_GROW) < RESIZEBITMAP_STRETCH + || (info->fit & ~RESIZEBITMAP_FLAG_DONT_GROW) > RESIZEBITMAP_MAKE_SQUARE) + return 0; + + // Well, lets do it + + // Calc final size + GetObject(info->hBmp, sizeof(bminfo), &bminfo); + + width = info->max_width; + height = info->max_height; + + xOrig = 0; + yOrig = 0; + widthOrig = bminfo.bmWidth; + heightOrig = bminfo.bmHeight; + + if (widthOrig == 0 || heightOrig == 0) + return 0; + + switch(info->fit & ~RESIZEBITMAP_FLAG_DONT_GROW) + { + case RESIZEBITMAP_STRETCH: + { + // Do nothing + break; + } + case RESIZEBITMAP_KEEP_PROPORTIONS: + { + if (height * widthOrig / heightOrig <= width) + { + if (info->fit & RESIZEBITMAP_FLAG_DONT_GROW) + height = min(height, bminfo.bmHeight); + width = height * widthOrig / heightOrig; + } + else + { + if (info->fit & RESIZEBITMAP_FLAG_DONT_GROW) + width = min(width, bminfo.bmWidth); + height = width * heightOrig / widthOrig; + } + + break; + } + case RESIZEBITMAP_MAKE_SQUARE: + { + if (info->fit & RESIZEBITMAP_FLAG_DONT_GROW) + { + width = min(width, bminfo.bmWidth); + height = min(height, bminfo.bmHeight); + } + + width = height = min(width, height); + // Do not break. Use crop calcs to make size + } + case RESIZEBITMAP_CROP: + { + if (heightOrig * width / height >= widthOrig) + { + heightOrig = widthOrig * height / width; + yOrig = (bminfo.bmHeight - heightOrig) / 2; + } + else + { + widthOrig = heightOrig * width / height; + xOrig = (bminfo.bmWidth - widthOrig) / 2; + } + + break; + } + } + + if ((width == bminfo.bmWidth && height == bminfo.bmHeight) + || ((info->fit & RESIZEBITMAP_FLAG_DONT_GROW) + && !(info->fit & RESIZEBITMAP_MAKE_SQUARE) + && width > bminfo.bmWidth && height > bminfo.bmHeight)) + { + // Do nothing + return (int) info->hBmp; + } + else + { + FIBITMAP *dib = FreeImage_CreateDIBFromHBITMAP(info->hBmp); + if (dib == NULL) + return NULL; + + FIBITMAP *dib_tmp; + if (xOrig > 0 || yOrig > 0) + dib_tmp = FreeImage_Copy(dib, xOrig, yOrig, xOrig + widthOrig, yOrig + heightOrig); + else + dib_tmp = dib; + + if (dib_tmp == NULL) + { + FreeImage_Unload(dib); + return NULL; + } + + FIBITMAP *dib_new = FreeImage_Rescale(dib_tmp, width, height, FILTER_CATMULLROM); + + HBITMAP bitmap_new = FreeImage_CreateHBITMAPFromDIB(dib_new); + + if (dib_new != dib_tmp) + FreeImage_Unload(dib_new); + if (dib_tmp != dib) + FreeImage_Unload(dib_tmp); + FreeImage_Unload(dib); + + return (INT_PTR)bitmap_new; + } +} + + +FIBITMAP * +FreeImage_LoadFromMem(FREE_IMAGE_FORMAT fif, fiio_mem_handle *handle, int flags) { + //FreeImageIO io; + //SetMemIO(&io); + + if (handle && handle->data) { + FIMEMORY *hmem = FreeImage_OpenMemory((BYTE *)handle->data, handle->datalen); + FREE_IMAGE_FORMAT _fif = (fif != FIF_UNKNOWN) ? fif : FreeImage_GetFileTypeFromMemory(hmem, 0); + FIBITMAP *dib = FreeImage_LoadFromMemory(_fif, hmem, flags); + FreeImage_CloseMemory(hmem); + //handle->curpos = 0; + //return FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags); + } + + return NULL; +} + +FIMEMORY +*FreeImage_SaveToMem(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, fiio_mem_handle *handle, int flags) { + //FreeImageIO io; + //SetMemIO(&io); + + if (handle) { + FIMEMORY *hmem = FreeImage_OpenMemory(NULL, 0); + if(fif == FIF_UNKNOWN) + fif = FIF_BMP; + handle->curpos = 0; + FreeImage_SaveToMemory(fif, dib, hmem, flags); + FreeImage_AcquireMemory(hmem, (BYTE **)&handle->data, (DWORD *)&handle->datalen); + return hmem; + //handle->filelen = 0; + //handle->curpos = 0; + //return FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags); + } + return NULL; +} + +// ---------------------------------------------------------- + +/* +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 __stdcall fiio_mem_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) { + unsigned x; + for ( x=0; x= 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 __stdcall 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 __stdcall fiio_mem_TellProc(fi_handle handle) { + return FIIOMEM(curpos); +} + +*/ + +// PNG image handler functions + +typedef struct { + char* mBuffer; + png_size_t mBufSize; + png_size_t mBufPtr; +} +HMemBufInfo; + +static void png_read_data( png_structp png_ptr, png_bytep data, png_size_t length ) +{ + HMemBufInfo* io = ( HMemBufInfo* )png_get_io_ptr(png_ptr); + if ( length + io->mBufPtr > io->mBufSize ) + length = io->mBufSize - io->mBufPtr; + + if ( length > 0 ) { + memcpy( data, io->mBuffer + io->mBufPtr, length ); + io->mBufPtr += length; + } + else png_error(png_ptr, "Read Error"); +} + +static void png_write_data( png_structp png_ptr, png_bytep data, png_size_t length ) +{ + HMemBufInfo* io = ( HMemBufInfo* )png_get_io_ptr(png_ptr); + if ( io->mBuffer != NULL ) + memcpy( io->mBuffer + io->mBufPtr, data, length ); + + io->mBufPtr += length; +} + +static void png_flush( png_structp png_ptr ) +{ +} + +/* +* Converting a *in memory* png image into a bitmap +*/ + +extern "C" BOOL __declspec(dllexport) mempng2dib(BYTE* pSource, DWORD cbSourceSize, BITMAPINFOHEADER** ppDibData ) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + HMemBufInfo sBuffer = { (char*)pSource, cbSourceSize, 8 }; + + BOOL bResult = FALSE; + png_uint_32 iWidth; + png_uint_32 iHeight; + png_color pBkgColor; + int iBitDepth; + int iColorType; + double dGamma; + png_color_16* pBackground; + png_byte ulChannels; + png_size_t ulRowBytes; + png_byte* pbImageData; + png_byte** ppbRowPointers = NULL; + int i; + png_uint_32 j; + int wDIRowBytes; + BYTE* pImageData; + + *ppDibData = NULL; + + if ( pSource == NULL || cbSourceSize == 0 ) + return FALSE; + + if ( !png_check_sig( pSource, 8 )) + return FALSE; + + // create the two png(-info) structures + png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); + if (!png_ptr) + return FALSE; + + info_ptr = png_create_info_struct(png_ptr); + if ( !info_ptr ) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return FALSE; + } + + // initialize the png structure + png_set_read_fn(png_ptr, (png_voidp)&sBuffer, png_read_data); + png_set_sig_bytes(png_ptr, 8); + + // read all PNG info up to image data + png_read_info(png_ptr, info_ptr); + + // get width, height, bit-depth and color-type + + png_get_IHDR(png_ptr, info_ptr, &iWidth, &iHeight, &iBitDepth, &iColorType, NULL, NULL, NULL); + + // expand images of all color-type and bit-depth to 3x8 bit RGB images + // let the library process things like alpha, transparency, background + + if ( iBitDepth == 16 ) + png_set_strip_16( png_ptr ); + if ( iColorType == PNG_COLOR_TYPE_PALETTE ) + png_set_expand( png_ptr ); + if ( iBitDepth < 8 ) + png_set_expand( png_ptr ); + if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS )) + png_set_expand( png_ptr ); + if ( iColorType == PNG_COLOR_TYPE_GRAY || iColorType == PNG_COLOR_TYPE_GRAY_ALPHA ) + png_set_gray_to_rgb( png_ptr ); + + // set the background color to draw transparent and alpha images over. + if (png_get_bKGD( png_ptr, info_ptr, &pBackground )) { + png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + pBkgColor.red = (byte) pBackground->red; + pBkgColor.green = (byte) pBackground->green; + pBkgColor.blue = (byte) pBackground->blue; + } + + // if required set gamma conversion + if ( png_get_gAMA( png_ptr, info_ptr, &dGamma )) + png_set_gamma( png_ptr, (double) 2.2, dGamma ); + + // after the transformations have been registered update info_ptr data + png_read_update_info(png_ptr, info_ptr); + + // get again width, height and the new bit-depth and color-type + png_get_IHDR(png_ptr, info_ptr, &iWidth, &iHeight, &iBitDepth, &iColorType, NULL, NULL, NULL); + + // row_bytes is the width x number of channels + ulRowBytes = png_get_rowbytes(png_ptr, info_ptr); + ulChannels = png_get_channels(png_ptr, info_ptr); + wDIRowBytes = (WORD) (( ulChannels * iWidth + 3L) >> 2) << 2; + + // now we can allocate memory to store the image + { DWORD cbMemSize = sizeof( BITMAPINFOHEADER ); + cbMemSize += wDIRowBytes * iHeight; + if (( pbImageData = ( png_byte* )GlobalAlloc( LPTR, cbMemSize )) == NULL ) { + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return FALSE; + } } + + // initialize the dib-structure + { BITMAPINFOHEADER* pbmih = ( BITMAPINFOHEADER* )pbImageData; + *ppDibData = pbmih; + + pbmih->biSize = sizeof( BITMAPINFOHEADER ); + pbmih->biWidth = iWidth; + pbmih->biHeight = iHeight; + pbmih->biPlanes = 1; + pbmih->biBitCount = ( WORD )( ulChannels * 8 ); + pbmih->biCompression = 0; + pbmih->biSizeImage = iWidth * iHeight * ulChannels; + + pbImageData += sizeof( BITMAPINFOHEADER ); + } + + pImageData = (BYTE*)malloc( ulRowBytes * iHeight ); + if ( pImageData == NULL ) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return FALSE; + } + + // and allocate memory for an array of row-pointers + ppbRowPointers = ( png_bytepp )alloca( iHeight * sizeof( png_bytep )); + + // set the individual row-pointers to point at the correct offsets + for ( j = 0; j < iHeight; j++ ) + ppbRowPointers[j] = ( png_bytep )&pImageData[ j*ulRowBytes ]; + + // now we can go ahead and just read the whole image + png_read_image( png_ptr, ppbRowPointers ); + png_read_end(png_ptr, NULL); + + // repack bytes to fill the bitmap + for ( i = iHeight-1; i >= 0; i-- ) + { + png_byte a; + png_bytep s = ppbRowPointers[i]; + BYTE* dest = pbImageData; pbImageData += wDIRowBytes; + + for ( j = 0; j < iWidth; j++ ) { + png_byte r = *s++; + png_byte g = *s++; + png_byte b = *s++; + if ( ulChannels == 4 ) + a = *s++; + + *dest++ = b; + *dest++ = g; + *dest++ = r; + if ( ulChannels == 4 ) + *dest++ = a; + } } + + free( pImageData ); + png_destroy_read_struct( &png_ptr, &info_ptr, NULL ); + return TRUE; +} + +/* +* Converting a bitmap into a png image +*/ + +static BOOL sttCheckAlphaIsValid( BITMAPINFO* pbmi, png_byte* pDiData ) +{ + int ciChannels = pbmi->bmiHeader.biBitCount / 8, i, j; + int ulSrcRowBytes = ((( pbmi->bmiHeader.biWidth * ciChannels + 3 ) >> 2 ) << 2 ); + byte value = pDiData[ 3 ]; + + if ( ciChannels < 4 ) + return FALSE; + + if ( value != 0 && value != 0xFF ) + return TRUE; + + for ( i=0; i < pbmi->bmiHeader.biHeight; i++ ) { + png_byte* p = pDiData; pDiData += ulSrcRowBytes; + + for ( j=0; j < pbmi->bmiHeader.biWidth; j++, p += 4 ) + if ( p[3] != value ) + return TRUE; + } + + return FALSE; +} + +extern "C" BOOL __declspec(dllexport) dib2mempng( BITMAPINFO* pbmi, png_byte* pDiData, BYTE* pResult, long* pResultLen ) +{ + int ciBitDepth = 8; + int ciChannels = pbmi->bmiHeader.biBitCount / 8; + + png_uint_32 ulSrcRowBytes, ulDstRowBytes; + int i; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_bytepp ppbRowPointers; + png_bytep pTempBuffer; + BOOL bIsAlphaValid; + + HMemBufInfo sBuffer = { (char *)pResult, 0, 0 }; + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); + if (!png_ptr) + return FALSE; + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + return FALSE; + } + + // initialize the png structure + bIsAlphaValid = sttCheckAlphaIsValid( pbmi, pDiData ); + png_set_write_fn(png_ptr, (png_voidp)&sBuffer, png_write_data, png_flush); + + png_set_IHDR(png_ptr, info_ptr, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight, ciBitDepth, + ( bIsAlphaValid ) ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + // write the file header information + png_write_info(png_ptr, info_ptr); + + // swap the BGR pixels in the DiData structure to RGB + png_set_bgr(png_ptr); + + // row_bytes is the width x number of channels + ulSrcRowBytes = ((( pbmi->bmiHeader.biWidth * ciChannels + 3 ) >> 2 ) << 2 ); + ulDstRowBytes = ((( pbmi->bmiHeader.biWidth * ( ciChannels == 4 && bIsAlphaValid ? 4 : 3 ) + 3 ) >> 2 ) << 2 ); + + ppbRowPointers = (png_bytepp)alloca( pbmi->bmiHeader.biHeight * sizeof(png_bytep)); + + pTempBuffer = ( png_bytep )malloc( pbmi->bmiHeader.biHeight * ulDstRowBytes ); + if ( pTempBuffer != NULL ) { + png_bytep pDest = pTempBuffer; + for ( i = pbmi->bmiHeader.biHeight-1; i >= 0; i--) { + BYTE *s, *d; + int j; + s = pDiData; pDiData += ulSrcRowBytes; + d = ppbRowPointers[i] = pDest; pDest += ulDstRowBytes; + + if ( ciChannels >= 3 ) { + for ( j = 0; j < pbmi->bmiHeader.biWidth; j++ ) { + png_byte b = *s++; + png_byte g = *s++; + png_byte r = *s++; + png_byte a = 0; + + if ( ciChannels == 4 ) + a = *s++; + + *d++ = b; + *d++ = g; + *d++ = r; + if ( ciChannels == 4 && bIsAlphaValid ) + *d++ = a; + } } + else { + for ( j = 0; j < pbmi->bmiHeader.biWidth; j++ ) { + DWORD point; + if ( ciChannels == 1 ) { + *d++ = ( BYTE )( point & 0x03 ) << 6; + *d++ = ( BYTE )(( point & 0x0C ) >> 2 ) << 6; + *d++ = ( BYTE )(( point & 0x30 ) >> 4 ) << 6; + point = *s++; + } + else { + point = *( WORD* )s; + s += sizeof( WORD ); + *d++ = ( BYTE )(( point & 0x001F ) << 3 ); + *d++ = ( BYTE )((( point & 0x07e0 ) >> 6 ) << 3 ); + *d++ = ( BYTE )((( point & 0xF800 ) >> 11 ) << 3 ); + } } } } + + png_write_image (png_ptr, ppbRowPointers); + png_write_end(png_ptr, info_ptr); + + if ( pResultLen != NULL ) + *pResultLen = (long)sBuffer.mBufPtr; + + free( pTempBuffer ); + } + + png_destroy_write_struct(&png_ptr, &info_ptr ); + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Standard Miranda structures & functions + +static HANDLE hDib2mempng = NULL; +static HANDLE hMempng2Dib = NULL; + +/////////////////////////////////////////////////////////////////////////////// +// Load - initializes the plugin instance + +static INT_PTR serviceDib2Png( WPARAM wParam, LPARAM lParam ) +{ + DIB2PNG* param = ( DIB2PNG* )lParam; + return dib2mempng( param->pbmi, param->pDiData, param->pResult, param->pResultLen ); +} + +static INT_PTR servicePng2Dib( WPARAM wParam, LPARAM lParam ) +{ + PNG2DIB* param = ( PNG2DIB* )lParam; + return mempng2dib( param->pSource, param->cbSourceSize, param->pResult ); +} + +FI_INTERFACE feif = {0}; + +/* +* caller MUST supply the desired version in wParam +* if it doesn't match, error will be returned +*/ + +static INT_PTR serviceGetInterface(WPARAM wParam, LPARAM lParam) +{ + FI_INTERFACE **ppfe = (FI_INTERFACE **)lParam; + + if ((DWORD)wParam != FI_IF_VERSION) + return CALLSERVICE_NOTFOUND; + + if(ppfe) { + *ppfe = &feif; + return S_OK; + } + else + return CALLSERVICE_NOTFOUND; +} + +static INT_PTR serviceLoad(WPARAM wParam, LPARAM lParam) +{ + char *lpszFilename = (char *)wParam; + if(lpszFilename==NULL) return 0; + FREE_IMAGE_FORMAT fif = FIF_UNKNOWN; + + if(lParam & IMGL_WCHAR) + fif = FreeImage_GetFileTypeU((wchar_t *)lpszFilename, 0); + else + fif = FreeImage_GetFileType(lpszFilename, 0); + + if(fif == FIF_UNKNOWN) { + if(lParam & IMGL_WCHAR) + fif = FreeImage_GetFIFFromFilenameU((wchar_t *)lpszFilename); + else + fif = FreeImage_GetFIFFromFilename(lpszFilename); + } + // check that the plugin has reading capabilities ... + + if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) { + // ok, let's load the file + FIBITMAP *dib; + + if(lParam & IMGL_WCHAR) + dib = FreeImage_LoadU(fif, (wchar_t *)lpszFilename, 0); + else + dib = FreeImage_Load(fif, lpszFilename, 0); + + if(dib == NULL || (lParam & IMGL_RETURNDIB)) + return (int)dib; + + HBITMAP hbm = FreeImage_CreateHBITMAPFromDIB(dib); + FreeImage_Unload(dib); + FI_CorrectBitmap32Alpha(hbm, FALSE); + return((INT_PTR)hbm); + } + return NULL; +} + +static INT_PTR serviceLoadFromMem(WPARAM wParam, LPARAM lParam) +{ + IMGSRVC_MEMIO *mio = (IMGSRVC_MEMIO *)wParam; + //fiio_mem_handle fiio; + + if(mio->iLen == 0 || mio->pBuf == NULL) + return 0; + + //fiio.curpos = 0; + //fiio.data = mio->pBuf; + //fiio.datalen = fiio.filelen = mio->iLen; + + FIMEMORY *hmem = FreeImage_OpenMemory((BYTE *)mio->pBuf, mio->iLen); + FREE_IMAGE_FORMAT fif = (mio->fif != FIF_UNKNOWN) ? mio->fif : mio->fif = FreeImage_GetFileTypeFromMemory(hmem, 0); + FIBITMAP *dib = FreeImage_LoadFromMemory(fif, hmem, mio->flags); + FreeImage_CloseMemory(hmem); + + //FIBITMAP *dib = FreeImage_LoadFromMem(mio->fif, &fiio, mio->flags); + + if(dib == NULL || (lParam & IMGL_RETURNDIB)) + return (INT_PTR)dib; + + HBITMAP hbm = FreeImage_CreateHBITMAPFromDIB(dib); + + FreeImage_Unload(dib); + return (INT_PTR)hbm; +} + +static INT_PTR serviceUnload(WPARAM wParam, LPARAM lParam) +{ + FIBITMAP *dib = (FIBITMAP *)wParam; + + if(dib) + FreeImage_Unload(dib); + + return 0; +} + +static INT_PTR serviceSave(WPARAM wParam, LPARAM lParam) +{ + IMGSRVC_INFO *isi = (IMGSRVC_INFO *)wParam; + FREE_IMAGE_FORMAT fif; + BOOL fUnload = FALSE; + FIBITMAP *dib = NULL; + + if(isi) { + if(isi->cbSize != sizeof(IMGSRVC_INFO)) + return 0; + + if(isi->szName || isi->wszName) { + if(isi->fif == FIF_UNKNOWN) { + if(lParam & IMGL_WCHAR) + fif = FreeImage_GetFIFFromFilenameU(isi->wszName); + else + fif = FreeImage_GetFIFFromFilename(isi->szName); + } + else + fif = isi->fif; + + if(fif == FIF_UNKNOWN) + fif = FIF_BMP; // default, save as bmp + + if(isi->hbm != 0 && (isi->dwMask & IMGI_HBITMAP) && !(isi->dwMask & IMGI_FBITMAP)) { + // create temporary dib, because we got a HBTIMAP passed + fUnload = TRUE; + FI_CorrectBitmap32Alpha(isi->hbm, FALSE); + dib = FreeImage_CreateDIBFromHBITMAP(isi->hbm); + } + else if(isi->dib != NULL && (isi->dwMask & IMGI_FBITMAP) && !(isi->dwMask & IMGI_HBITMAP)) + dib = isi->dib; + + int ret = 0; + if(dib) { + int flags = HIWORD(lParam); + + if(fif == FIF_PNG || fif == FIF_BMP || fif == FIF_JNG) + { + if(lParam & IMGL_WCHAR) + ret = FreeImage_SaveU(fif, dib, isi->wszName, flags); + else + ret = FreeImage_Save(fif, dib, isi->szName, flags); + } + else + { + FIBITMAP *dib_new = FreeImage_ConvertTo24Bits(dib); + if(lParam & IMGL_WCHAR) + ret = FreeImage_SaveU(fif, dib_new, isi->wszName, flags); + else + ret = FreeImage_Save(fif, dib_new, isi->szName, flags); + FreeImage_Unload(dib_new); + } + + if(fUnload) + FreeImage_Unload(dib); + return ret; + } + return 0; + } + + } + return 0; +} + +static INT_PTR serviceGetVersion(WPARAM wParam, LPARAM lParam) +{ + return FI_IF_VERSION; +} + +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateClassic(FIBITMAP *dib, double angle) +{ + return FreeImage_Rotate(dib, angle, NULL); +} + +void FI_Populate(void) +{ + /* + * populate the interface + */ + + feif.version = FI_IF_VERSION; + + feif.FI__AllocateT = FreeImage_AllocateT; + feif.FI_Allocate = FreeImage_Allocate; + feif.FI_Clone = FreeImage_Clone; + feif.FI_Unload = FreeImage_Unload; + + feif.FI_Load = FreeImage_Load; + feif.FI_LoadFromHandle = FreeImage_LoadFromHandle; + feif.FI_LoadU = FreeImage_LoadU; + feif.FI_Save = FreeImage_Save; + feif.FI_SaveToHandle = FreeImage_SaveToHandle; + feif.FI_SaveU = FreeImage_SaveU; + + feif.FI_OpenMemory = FreeImage_OpenMemory; + feif.FI_CloseMemory = FreeImage_CloseMemory; + feif.FI_LoadFromMemory = FreeImage_LoadFromMemory; + feif.FI_SaveToMemory = FreeImage_SaveToMemory; + feif.FI_TellMemory = FreeImage_TellMemory; + feif.FI_SeekMemory = FreeImage_SeekMemory; + feif.FI_AcquireMemory = FreeImage_AcquireMemory; + feif.FI_ReadMemory = FreeImage_ReadMemory; + feif.FI_WriteMemory = FreeImage_WriteMemory; + feif.FI_LoadMultiBitmapFromMemory = FreeImage_LoadMultiBitmapFromMemory; + + feif.FI_OpenMultiBitmap = FreeImage_OpenMultiBitmap; + feif.FI_OpenMultiBitmapU = FreeImage_OpenMultiBitmapU; + feif.FI_CloseMultiBitmap = FreeImage_CloseMultiBitmap; + feif.FI_GetPageCount = FreeImage_GetPageCount; + feif.FI_AppendPage = FreeImage_AppendPage; + feif.FI_InsertPage = FreeImage_InsertPage; + feif.FI_DeletePage = FreeImage_DeletePage; + feif.FI_LockPage = FreeImage_LockPage; + feif.FI_UnlockPage = FreeImage_UnlockPage; + feif.FI_MovePage = FreeImage_MovePage; + feif.FI_GetLockedPageNumbers = FreeImage_GetLockedPageNumbers; + + feif.FI_GetFileType = FreeImage_GetFileType; + feif.FI_GetFileTypeU = FreeImage_GetFileTypeU; + feif.FI_GetFileTypeFromHandle = FreeImage_GetFileTypeFromHandle; + feif.FI_GetFileTypeFromMemory = FreeImage_GetFileTypeFromMemory; + feif.FI_GetImageType = FreeImage_GetImageType; + + feif.FI_GetBits = FreeImage_GetBits; + feif.FI_GetScanLine = FreeImage_GetScanLine; + feif.FI_GetPixelIndex = FreeImage_GetPixelIndex; + feif.FI_GetPixelColor = FreeImage_GetPixelColor; + feif.FI_SetPixelColor = FreeImage_SetPixelColor; + feif.FI_SetPixelIndex = FreeImage_SetPixelIndex; + + feif.FI_GetColorsUsed = FreeImage_GetColorsUsed; + feif.FI_GetBPP = FreeImage_GetBPP; + feif.FI_GetWidth = FreeImage_GetWidth; + feif.FI_GetHeight = FreeImage_GetHeight; + feif.FI_GetLine = FreeImage_GetLine; + feif.FI_GetPitch = FreeImage_GetPitch; + feif.FI_GetDIBSize = FreeImage_GetDIBSize; + feif.FI_GetPalette = FreeImage_GetPalette; + feif.FI_GetDotsPerMeterX = FreeImage_GetDotsPerMeterX; + feif.FI_GetDotsPerMeterY = FreeImage_GetDotsPerMeterY; + feif.FI_SetDotsPerMeterX = FreeImage_SetDotsPerMeterX; + feif.FI_SetDotsPerMeterY = FreeImage_SetDotsPerMeterY; + feif.FI_GetInfoHeader = FreeImage_GetInfoHeader; + feif.FI_GetInfo = FreeImage_GetInfo; + feif.FI_GetColorType = FreeImage_GetColorType; + feif.FI_GetRedMask = FreeImage_GetRedMask; + feif.FI_GetGreenMask = FreeImage_GetGreenMask; + feif.FI_GetBlueMask = FreeImage_GetBlueMask; + feif.FI_GetTransparencyCount = FreeImage_GetTransparencyCount; + feif.FI_GetTransparencyTable = FreeImage_GetTransparencyTable; + feif.FI_SetTransparent = FreeImage_SetTransparent; + feif.FI_SetTransparencyTable = FreeImage_SetTransparencyTable; + feif.FI_IsTransparent = FreeImage_IsTransparent; + feif.FI_HasBackgroundColor = FreeImage_HasBackgroundColor; + feif.FI_GetBackgroundColor = FreeImage_GetBackgroundColor; + feif.FI_SetBackgroundColor = FreeImage_SetBackgroundColor; + + feif.FI_ConvertTo4Bits = FreeImage_ConvertTo4Bits; + feif.FI_ConvertTo8Bits = FreeImage_ConvertTo8Bits; + feif.FI_ConvertToGreyscale = FreeImage_ConvertToGreyscale; + feif.FI_ConvertTo16Bits555 = FreeImage_ConvertTo16Bits555; + feif.FI_ConvertTo16Bits565 = FreeImage_ConvertTo16Bits565; + feif.FI_ConvertTo24Bits = FreeImage_ConvertTo24Bits; + feif.FI_ConvertTo32Bits = FreeImage_ConvertTo32Bits; + feif.FI_ColorQuantize = FreeImage_ColorQuantize; + feif.FI_ColorQuantizeEx = FreeImage_ColorQuantizeEx; + feif.FI_Threshold = FreeImage_Threshold; + feif.FI_Dither = FreeImage_Dither; + feif.FI_ConvertFromRawBits = FreeImage_ConvertFromRawBits; + feif.FI_ConvertToRawBits = FreeImage_ConvertToRawBits; + feif.FI_ConvertToRGBF = FreeImage_ConvertToRGBF; + feif.FI_ConvertToStandardType = FreeImage_ConvertToStandardType; + feif.FI_ConvertToType = FreeImage_ConvertToType; + + feif.FI_RegisterLocalPlugin = FreeImage_RegisterLocalPlugin; + feif.FI_RegisterExternalPlugin = FreeImage_RegisterExternalPlugin; + feif.FI_GetFIFCount = FreeImage_GetFIFCount; + feif.FI_SetPluginEnabled = FreeImage_SetPluginEnabled; + feif.FI_IsPluginEnabled = FreeImage_IsPluginEnabled; + feif.FI_GetFIFFromFormat = FreeImage_GetFIFFromFormat; + feif.FI_GetFIFFromMime = FreeImage_GetFIFFromMime; + feif.FI_GetFormatFromFIF = FreeImage_GetFormatFromFIF; + feif.FI_GetFIFExtensionList = FreeImage_GetFIFExtensionList; + feif.FI_GetFIFDescription = FreeImage_GetFIFDescription; + feif.FI_GetFIFRegExpr = FreeImage_GetFIFRegExpr; + feif.FI_GetFIFMimeType = FreeImage_GetFIFMimeType; + feif.FI_GetFIFFromFilename = FreeImage_GetFIFFromFilename; + feif.FI_GetFIFFromFilenameU = FreeImage_GetFIFFromFilenameU; + feif.FI_FIFSupportsReading = FreeImage_FIFSupportsReading; + feif.FI_FIFSupportsWriting = FreeImage_FIFSupportsWriting; + feif.FI_FIFSupportsExportBPP = FreeImage_FIFSupportsExportBPP; + feif.FI_FIFSupportsExportType = FreeImage_FIFSupportsExportType; + feif.FI_FIFSupportsICCProfiles = FreeImage_FIFSupportsICCProfiles; + + feif.FI_RotateClassic = FreeImage_RotateClassic; + feif.FI_RotateEx = FreeImage_RotateEx; + feif.FI_FlipHorizontal = FreeImage_FlipHorizontal; + feif.FI_FlipVertical = FreeImage_FlipVertical; + feif.FI_JPEGTransform = FreeImage_JPEGTransform; + + feif.FI_Rescale = FreeImage_Rescale; + feif.FI_MakeThumbnail = FreeImage_MakeThumbnail; + + feif.FI_AdjustCurve = FreeImage_AdjustCurve; + feif.FI_AdjustGamma = FreeImage_AdjustGamma; + feif.FI_AdjustBrightness = FreeImage_AdjustBrightness; + feif.FI_AdjustContrast = FreeImage_AdjustContrast; + feif.FI_Invert = FreeImage_Invert; + feif.FI_GetHistogram = FreeImage_GetHistogram; + + feif.FI_GetChannel = FreeImage_GetChannel; + feif.FI_SetChannel = FreeImage_SetChannel; + feif.FI_GetComplexChannel = FreeImage_GetComplexChannel; + feif.FI_SetComplexChannel = FreeImage_SetComplexChannel; + + feif.FI_Copy = FreeImage_Copy; + feif.FI_Paste = FreeImage_Paste; + feif.FI_Composite = FreeImage_Composite; + feif.FI_JPEGCrop = FreeImage_JPEGCrop; + + feif.FI_LoadFromMem = FreeImage_LoadFromMem; + feif.FI_SaveToMem = FreeImage_SaveToMem; + + feif.FI_CreateDIBFromHBITMAP = FreeImage_CreateDIBFromHBITMAP; + feif.FI_CreateHBITMAPFromDIB = FreeImage_CreateHBITMAPFromDIB; + + feif.FI_Premultiply = FreeImage_PreMultiply; + feif.FI_BmpFilterResizeBitmap = serviceBmpFilterResizeBitmap; + + feif.FI_IsLittleEndian = FreeImage_IsLittleEndian; + feif.FI_LookupX11Color = FreeImage_LookupX11Color; + feif.FI_LookupSVGColor = FreeImage_LookupSVGColor; + + feif.FI_GetICCProfile = FreeImage_GetICCProfile; + feif.FI_CreateICCProfile = FreeImage_CreateICCProfile; + feif.FI_DestroyICCProfile = FreeImage_DestroyICCProfile; + + feif.FI_ToneMapping = FreeImage_ToneMapping; + feif.FI_TmoDrago03 = FreeImage_TmoDrago03; + feif.FI_TmoReinhard05 = FreeImage_TmoReinhard05; + + feif.FI_ZLibCompress = FreeImage_ZLibCompress; + feif.FI_ZLibUncompress = FreeImage_ZLibUncompress; + feif.FI_ZLibGZip = FreeImage_ZLibGZip; + feif.FI_ZLibGUnzip = FreeImage_ZLibGUnzip; + feif.FI_ZLibCRC32 = FreeImage_ZLibCRC32; + + feif.FI_CreateTag = FreeImage_CreateTag; + feif.FI_DeleteTag = FreeImage_DeleteTag; + feif.FI_CloneTag = FreeImage_CloneTag; + + feif.FI_GetTagKey = FreeImage_GetTagKey; + feif.FI_GetTagDescription = FreeImage_GetTagDescription; + feif.FI_GetTagID = FreeImage_GetTagID; + feif.FI_GetTagType = FreeImage_GetTagType; + feif.FI_GetTagCount = FreeImage_GetTagCount; + feif.FI_GetTagLength = FreeImage_GetTagLength; + feif.FI_GetTagValue = FreeImage_GetTagValue; + + feif.FI_SetTagKey = FreeImage_SetTagKey; + feif.FI_SetTagDescription = FreeImage_SetTagDescription; + feif.FI_SetTagID = FreeImage_SetTagID; + feif.FI_SetTagType = FreeImage_SetTagType; + feif.FI_SetTagCount = FreeImage_SetTagCount; + feif.FI_SetTagLength = FreeImage_SetTagLength; + feif.FI_SetTagValue = FreeImage_SetTagValue; + + feif.FI_FindFirstMetadata = FreeImage_FindFirstMetadata; + feif.FI_FindNextMetadata = FreeImage_FindNextMetadata; + feif.FI_FindCloseMetadata = FreeImage_FindCloseMetadata; + feif.FI_SetMetadata = FreeImage_SetMetadata; + feif.FI_GetMetadata = FreeImage_GetMetadata; + + feif.FI_GetMetadataCount = FreeImage_GetMetadataCount; + feif.FI_TagToString = FreeImage_TagToString; + + feif.FI_CorrectBitmap32Alpha = FI_CorrectBitmap32Alpha; +} + +static HANDLE hGetIF, hLoad, hLoadFromMem, hSave, hUnload, hResize, hGetVersion; + +static int IMGSERVICE_Load() +{ + FI_Populate(); + + hDib2mempng = CreateServiceFunction( MS_DIB2PNG, serviceDib2Png ); + hMempng2Dib = CreateServiceFunction( MS_PNG2DIB, servicePng2Dib ); + hGetIF = CreateServiceFunction(MS_IMG_GETINTERFACE, serviceGetInterface); + hLoad = CreateServiceFunction(MS_IMG_LOAD, serviceLoad); + hLoadFromMem = CreateServiceFunction(MS_IMG_LOADFROMMEM, serviceLoadFromMem); + hSave = CreateServiceFunction(MS_IMG_SAVE, serviceSave); + hUnload = CreateServiceFunction(MS_IMG_UNLOAD, serviceUnload); + hResize = CreateServiceFunction(MS_IMG_RESIZE, serviceBmpFilterResizeBitmap); + hGetVersion = CreateServiceFunction(MS_IMG_GETIFVERSION, serviceGetVersion); + return 0; +} + +extern "C" int __declspec(dllexport) Load(void) +{ + return IMGSERVICE_Load(); +} + +/////////////////////////////////////////////////////////////////////////////// +// Unload - destroys the plugin instance + +static int IMGSERVICE_Unload( void ) +{ + DestroyServiceFunction( hDib2mempng ); + DestroyServiceFunction( hMempng2Dib ); + DestroyServiceFunction( hGetIF ); + DestroyServiceFunction( hLoad ); + DestroyServiceFunction( hLoadFromMem ); + DestroyServiceFunction( hSave ); + DestroyServiceFunction( hUnload ); + DestroyServiceFunction( hResize ); + DestroyServiceFunction( hGetVersion ); + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + return IMGSERVICE_Unload(); +} + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { { 0xece29554, 0x1cf0, 0x41da, { 0x85, 0x82, 0xfb, 0xe8, 0x45, 0x5c, 0x6b, 0xec } }, MIID_LAST}; + +extern "C" __declspec(dllexport) const PLUGININFOEX * MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfoEx; +} diff --git a/plugins/FreeImage/src/version.h b/plugins/FreeImage/src/version.h new file mode 100644 index 0000000000..fb6dca1759 --- /dev/null +++ b/plugins/FreeImage/src/version.h @@ -0,0 +1,20 @@ +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 11 +#define __RELEASE_NUM 0 +#define __BUILD_NUM 1 + +#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM +#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM + +#define __STRINGIFY_IMPL(x) #x +#define __STRINGIFY(x) __STRINGIFY_IMPL(x) +#define __VERSION_STRING __STRINGIFY(__FILEVERSION_DOTS) + +#define __PLUGIN_NAME "Miranda Image services" +#define __INTERNAL_NAME "AdvaImg" +#define __FILENAME "AdvaImg.dll" +#define __DESCRIPTION "Generic image services for Miranda NG." +#define __AUTHOR "Nightwish, The FreeImage project (http://freeimage.sourceforge.net/)" +#define __AUTHOREMAIL "" +#define __AUTHORWEB "http://miranda-ng.org/" +#define __COPYRIGHT "© 2000-2012 Miranda-IM project, 2012 Miranda-NG project uses the FreeImage distribution" diff --git a/plugins/FreeImage/version.rc b/plugins/FreeImage/version.rc deleted file mode 100644 index 171ae6576c..0000000000 --- a/plugins/FreeImage/version.rc +++ /dev/null @@ -1,115 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#ifdef APSTUDIO_INVOKED -#error this file is not editable by Microsoft Visual C++ -#endif //APSTUDIO_INVOKED - -#include "Miranda\version.h" -#include "afxres.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#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 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "\r\n" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// German (Austria) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEA) -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION __FILEVERSION_STRING - PRODUCTVERSION __FILEVERSION_STRING - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x0L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "FileDescription", __DESCRIPTION - VALUE "InternalName", __PLUGIN_NAME - VALUE "LegalCopyright", __COPYRIGHT - VALUE "OriginalFilename", __FILENAME - VALUE "ProductName", __PLUGIN_NAME - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - -#endif // German (Austria) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - - -- cgit v1.2.3