diff options
Diffstat (limited to 'plugins/AdvaImg')
120 files changed, 19204 insertions, 14658 deletions
diff --git a/plugins/AdvaImg/Docs/Whatsnew.txt b/plugins/AdvaImg/Docs/Whatsnew.txt new file mode 100644 index 0000000000..d761069a64 --- /dev/null +++ b/plugins/AdvaImg/Docs/Whatsnew.txt @@ -0,0 +1,1209 @@ +What's New for FreeImage
+
+* : fixed
+- : removed
+! : changed
++ : added
+
+March 23rd, 2014 - 3.16.0
+! FreeImage now uses LibJPEG 9a
+! FreeImage now uses LibPNG 1.6.10
+! FreeImage now uses LibTIFF 4.0.3 (CVS patch 2013-11-30)
+! FreeImage now uses LibRaw 0.16.0
+! FreeImage now uses OpenJPEG 2.1.0 (SVN patch 2748)
+! FreeImage now uses ZLib 1.2.8
+! FreeImage now uses LibWebP 0.4.0 (GIT patch 2014-03-21)
+! FreeImage now uses LibJXR 1.1 (GIT patch 2014-01-31)
++ [Herve Drolon] added loading & writing support for the JPEG-XR image format (also support the FIF_LOAD_NOPIXELS flag)
++ [Herve Drolon] added loading & writing support for the WebP image format (also support the FIF_LOAD_NOPIXELS flag)
++ [Herve Drolon] added support for FIF_LOAD_NOPIXELS flag to JP2/J2K plugins
++ [Gaël Zimmermann] added basic support for BMP v4, v5 in BMP plugin (useful for drag and drop from another application such as Firefox)
++ [Mihail Naydenov] FreeImage_GetFIFFromFilename[U] : added support for *rgb,*rgba,*.bw extensions to the SGI plugin
++ [Mihail Naydenov] improved FreeImage_Rescale speed & spatial accuracy
++ [Mihail Naydenov] improved JPEG transform functions and added new functions (see below) :
+ added FreeImage_JPEGTransformFromHandle
+ added FreeImage_JPEGTransformCombined
+ added FreeImage_JPEGTransformCombinedU
+ added FreeImage_JPEGTransformCombinedFromMemory
+* [Herve Drolon] fixed FreeImage_CloneTag behavior with ASCII data handling (regression that appeared in 3.15.2, affect metadata writing)
+* [Carsten Klein] ICO plugin: avoid using the AND mask when loading a 32-bit (already transparent) icon
+* [Andreas Baumann] HDR plugin: removed a comma at end of an enumerator list
+* [mark] added missing <string.h> in OpenEXR (needed with mingw)
+* [Herve Drolon] added support for FIC_MINISWHITE color type inside FreeImage_GetColorType for FIT_UINT16 images
+* [Takamasa Mitsuji] FreeImage_Rescale : fixed a NULL-pointer access bug occurring for transparent images with a linear palette
+* [Herve Drolon] fixed PSD parser when reading PSD files with corrupted resources
+* [Herve Drolon] fixed TIFF plugin truncating metadata tag on loading if type is ASCII and it's value is of variable size (TIFF_VARIABLE)
+* [Herve Drolon] fixed loading of TGA 8-bit files with a palette size greater that 256
+* [Anton Kukoba] TIFF parser didn't initialize the memory with zeros in stripped mode. This caused random bitmap data if the tiff file was corrupted/invalid.
+* [Herve Drolon] improved TGA file detection when the format version is < 2.0
+* [Christian Heimes] fixed compiler errors on 64bit Linux (INT64 / UINT64 type mismatches and missing prototype for memset)
+* [Christian Heimes] fixed FreeImage_Get*Mask() returning 0 on 24-, -32-bit FIT_BITMAP images
+* [Mihail Naydenov] fixed GIF plugin LZW decoder failing on some images
+* [Herve Drolon] fixed the TIFF plugin against race condition when used simultaneously in multiple threads
+* [Herve Drolon] fixed float <--> rgb[a]f conversions when pixels are out of [0..1] range
+
+October 27th, 2012 - 3.15.4
+! FreeImage now uses LibPNG 1.5.13
+! FreeImage now uses LibRaw 0.14.7
+! FreeImage now uses ZLib 1.2.7
+! FreeImage now uses LibTIFF 4.0.3
+! FreeImage now uses OpenJPEG 1.5.1
+! FreeImage now uses OpenEXR 1.7.1
++ [Herve Drolon] improved the speed of RAW files detection in FreeImage_GetFileType* functions
++ [Herve Drolon] added JPEG_GREYSCALE load flag to the JPEG plugin (force to load as 8-bit greyscale)
++ [Herve Drolon] added 64-bit RGBA to 24-bit conversion support in FreeImage_ConvertTo24Bits
++ [Carsten Klein] improved the speed of FreeImage_Rescale for FIT_BITMAP & UINT16, RGB[A]16 types
++ [Carsten Klein] improved the speed of FreeImage_ConvertToGreyscale
+* [Carsten Klein] updated makefile for building FreeImage with MinGW
+* [Herve Drolon] fixed BigTIFF signature validation in FreeImage_GetFileType* functions
+* [Carsten Klein] fixed handling of RGB-565 16-bit images (needed for conversion from HBITMAP to FIBITMAP)
+* [Herve Drolon] fixed loading of JPEG with invalid IPTC marker
+* [Herve Drolon] changed default TIF RowsPerStrips to image height when saving as TIF G3 or TIF G4 (improved compression)
+* [Herve Drolon] improved the memory behavior of the RAW plugin (do not allocate huge variables on the stack)
+* [Herve Drolon] fixed FreeImage_AllocateT so that it returns NULL with images with a zero width and/or height
+* [Herve Drolon] replaced FIUINT64/FIINT64 with standard types UINT64/INT64
+* [Rustam Abdullaev] fixed PNG plugin with saving of transparent monochrome images
+* [Floris van den Berg] improved plugin registering when replacing an existing internal plugin with a new equivalent plugin
+* [Herve Drolon] fixed a crash when calling FreeImage_GetColorType on a 32-bit RGBA images loaded with the FIF_LOAD_NOPIXELS flag
+* [Herve Drolon] fixed FreeImage_SetTransparencyTable falsely setting a dib to 'transparent' when called with a count of 0
+* [Carsten Klein] fixed storing of RGB masks for 16-bit RGB standard images in order to be in a MSDN compatible way
+* [Herve Drolon] added an error handling message inside HDR plugin when trying to save an unsupported format
+* [Corey Taylor] fixed DDS plugin color channel swapping for RGB color order, when using FREEIMAGE_COLORORDER_RGB color order
+* [Herve Drolon] fixed internal TagLib singleton initialization against double-checked locking so that it is multi-thread safe
+
+March 17th, 2012 - 3.15.3
+! FreeImage now uses LibPNG 1.5.9
+! FreeImage now uses LibTIFF 4.0.1
++ [Herve Drolon] added new 64-bit data types FIINT64, FIUINT64
++ [Herve Drolon] added new 64-bit metadata types to FREE_IMAGE_MDTYPE (FIDT_LONG8, FIDT_SLONG8, FIDT_IFD8)
++ [Herve Drolon] added support for 64-bit metadata types to FreeImage_TagToString
+* [Herve Drolon] fixed a regression with Fax3/Fax4 TIFF images on 64-bit OS (introduced with FI 3.15.2)
+* [Herve Drolon] fixed some gcc 4.4.6 warnings
+* [Petr Pytelka] refactored FreeImage_InsertPage and FreeImage_AppendPage
+* [Herve Drolon] fixed JP2/J2K plugins with saving of 32-bit dib with a fully opaque layer
+* [Herve Drolon] fixed loading of CMYK JPEG when using JPEG_CMYK load flag (need to invert pixels)
+* [Herve Drolon] fixed loading of CMYK PSD when using PSD_CMYK load flag
+
+February 20th, 2012 - 3.15.2
+! FreeImage now uses LibRaw 0.14.5
+! FreeImage now uses LibPNG 1.5.8
+! FreeImage now uses LibJPEG 8d
+! FreeImage now uses ZLib 1.2.6
+! FreeImage now uses OpenJPEG 1.5.0 (released version)
+! FreeImage now uses LibTIFF 4.0.0
+- [Herve Drolon] removed dependency on LibMNG 1.0.10 (MNG and JNG files are now handled internally)
++ [Herve Drolon] replaced the MNG plugin with a new MNG internal FreeImage plugin (with read support)
++ [Herve Drolon] added a new JNG internal FreeImage plugin (with read/write support)
++ [Christian Heimes] added write support to the TIFF plugin for EXIF_MAIN tags
++ [Herve Drolon] added new Exif maker note tags
++ [Herve Drolon] added TAG_COMPRESSION conversion to FreeImage_TagToString
+* [Mylek Grey] enabled the use of multi-component transforms (MCT) in J2K and JP2 saving
+* [Herve Drolon] refactored PluginICO in order to correctly support Windows Vista 256x256 icons
+* [Herve Drolon] added minor speed improvements to FreeImage_Rescale
+* [Herve Drolon] fixed dib allocation failing with very large images (i.e. more than 4GB)
+* [Herve Drolon] fixed FreeImage_CloneTag behavior with ASCII data handling
+* [Herve Drolon] improved JPEG plugin behavior with very big images
+* [Herve Drolon] improved JPEG plugin behavior with C++ exceptions
+* [Herve Drolon] fixed loading of palettized PNG with more that 256 palette entries
+* [Herve Drolon] fixed a bug inside IFF plugin occuring when loading a 24-bit dib with a palette
+* [Herve Drolon] fixed a bug with loading of PNG images containing a cHRM chunk (regression introduced by LibPNG 1.5.4 and fixed by LibPNG 1.5.5)
+* [Herve Drolon] allowed loading of PNG with benign errors (such as images with too many IDATs)
+* [Mihail Naydenov] fixed some incorrect MIME types returned by FreeImage_GetFIFMimeType
+* [Herve Drolon] fixed loading of Exif with bad thumbnail data or with a bad first offset size
+
+July 25th, 2011 - 3.15.1
+! FreeImage now uses LibRaw 0.13.7
+! FreeImage now uses LibPNG 1.5.4
+! FreeImage now uses LibTIFF 3.9.5
+! FreeImage now uses OpenJPEG 1.5.0 (SVN patch 2011-07-23)
++ [Herve Drolon] added FreeImage_ConvertToRGB16 and updated FreeImage_ConvertToType
++ [Herve Drolon] added RAW_HALFSIZE flag to RAW plugin
+* [Herve Drolon] fixed a memory leak in JPEG plugin occuring when loading some corrupted images
+* [Eberhard Mattes] improved thread safety behavior inside internal TagLib class
+* [Hew How Chee] fixed a bug in FreeImage_EnlargeCanvas when called with negative left and right parameters and bpp <= 4
+* [Herve Drolon] improved memory allocation checking in FreeImage_ConvertTo[Float/RGBF/UINT16]
+* [Herve Drolon] allowed loading of TIF with missing bitspersample/samplesperpixel/photometric tags
+* [Herve Drolon] fixed FreeImage_AllocateHeaderT against possible malloc overflow
+* [Herve Drolon] fixed CUT plugin against heap corruption vulnerability
+* [Herve Drolon] fixed BMP plugin for images with a truncated input data stream
+* [Herve Drolon] improved PCX format detection in FreeImage_GetFileType* functions
+* [Christian Heimes] fixed a TIFF G4 compression bug occuring with gcc-Version 4.1.2 20080704 (Red Hat 4.1.2-50)
+
+January 24th, 2011 - 3.15.0
+! FreeImage now uses LibRaw 0.13-Beta3
+! FreeImage now uses LibPNG 1.4.5
+! FreeImage now uses LibTIFF 3.9.4 (CVS patch 2011-01-03)
+! FreeImage now uses LibJPEG 8c
+! FreeImage now uses OpenJPEG 1.4.0 (SVN patch 2011-01-18)
+! [Herve Drolon] FreeImage_CloneMetadata now clone resolution info returned by FreeImage_GetDotsPerMeter(X / Y)
++ [Herve Drolon] added loading support for "half float" format to TIF plugin
++ [Herve Drolon] FreeImage_IsTransparent is now independant of FREE_IMAGE_TYPE
++ [Herve Drolon] added FIT_UINT16 to FIT_RGBF conversion to FreeImage_ConvertToRGBF & FreeImage_ConvertToType
++ [Herve Drolon] added FreeImage_ConvertToUINT16 and updated FreeImage_ConvertToType
++ [Mihail Naydenov] added FreeImage_GetThumbnail / FreeImage_SetThumbnail
++ [Mihail Naydenov] added thumbnail support to Exif, JPEG, EXR, PSD, TGA, TIF formats
++ [Mihail Naydenov] added JPEG_BASELINE save flag to the JPEG plugin
++ [Herve Drolon] added new Exif-TIFF tags (PageName, PageNumber, XPosition, YPosition) and Exif WinXP tags
++ [Herve Drolon] added support for 256x256 icon size to PluginICO:Save
+* [Domingo Stephan] fixed a compilation error in TARGA plugin when using a big endian OS (OS X 10.6)
+* [Christian Heimes] fixed a compilation error with gcc 4.3.x and OpenEXR
+* [Eric Fruhinsholz] fixed a crash in JPEG plugin when reading a JPEG with corrupted XMP data
+* [Herve Drolon] improved FreeImage_MultigridPoissonSolver for images whose size is a power-of-two
+* [Herve Drolon] fixed a crash in PSD plugin when loading a PSD with a CMYK embedded thumbnail
+* [Herve Drolon] fixed loading of JPEG images with a not null but zero length IPTC segment (bad files produced by Picasa)
+* [Carsten Klein] fixed a bug in FreeImage_ColorQuantizeEx when using FIQ_WUQUANT quantizer
+* [Herve Drolon] added support for RGBA[16][F] to FreeImage_IsTransparent
+* [Herve Drolon] fixed loading of resolution info in TIFF CMYK images (bug introduced with 3.14.0)
+* [Tom May] fixed JPEG plugin crashing on some Exif files containing tags with an invalid tag length
+* [Herve Drolon] fixed a crash when loading TIFF images with a TIFFTAG_TRANSFERFUNCTION Exif tag
+* [Tom May] removed assertions in PSD plugin, causing crashes on some malformed images in debug mode
+* [Mihail Naydenov] fixed a crash in TIFF plugin when reading an uncommon 24-bit palettized file
+* [Carsten Klein] fixed a bug in FreeImage_EnlargeCanvas when using the function as a FreeImage_Copy function
+* [Herve Drolon] fixed a bug in PluginBMP with loading of OS/2 2.x palettized BMP
+* [luispedro] fixed a bug in PluginBMP when reading malformed 16-bit RGB-555 BMP
+
+August 12th, 2010 - 3.14.1
++ [Mihail Naydenov] added support for FIF_LOAD_NOPIXELS flag to EXR plugin
++ [Herve Drolon] added support for FIF_LOAD_NOPIXELS flag to CUT, HDR, RAS, ICO, PNM, RAW, BMP, PFM, XPM plugins
+* [Eberhard Mattes] fixed memory allocation checking in multipage API
+* [Herve Drolon] (compiler options) removed Win32 OpenMP support introduced in 3.14.0
+
+August 9th, 2010 - 3.14.0
+! FreeImage now uses OpenEXR 1.7.0
+! FreeImage now uses ZLib 1.2.5
+! FreeImage now uses LibPNG 1.4.3
+! FreeImage now uses LibJPEG 8b
+! FreeImage now uses LibTIFF 3.9.4 (CVS patch 2010-07-13)
+! FreeImage now uses LibRaw 0.10-Beta3
+! FreeImage now uses OpenJPEG 1.4.0 (SVN patch 2010-04-16)
+! [Herve Drolon] FreeImage_AllocateT now builds a default greyscale palette for 8-bit images
+! [Volodymyr Goncharov] FreeImage_LoadMultiBitmapFromMemory now supports read/write operations
+! [Herve Drolon] FreeImage_OpenMultiBitmapFromHandle now supports read/write operations
+! [Herve Drolon] greyscale conversions now use the Rec. 709 formula
+! [Mihail Naydenov] saving RGBF images to TIFF no longer use LogLuv encoding (unless you use the TIFF_LOGLUV save flag)
++ [Herve Drolon] added FIT_FLOAT to FIT_RGBF conversion to FreeImage_ConvertToRGBF & FreeImage_ConvertToType
++ [Herve Drolon] added VS 2008 project files
++ [Herve Drolon] added FreeImage_ConvertToFloat
++ [Mihail Naydenov] added RLE saving to the Targa plugin (see flag TARGA_SAVE_RLE)
++ [Volodymyr Goncharov] added FreeImage_SaveMultiBitmapToHandle
++ [Herve Drolon] added FreeImage_SaveMultiBitmapToMemory
++ [Herve Drolon] added new Exif maker note tags
++ [Lucian Sabo] added JPEG_OPTIMIZE to PluginJPEG:Save
++ [Mihail Naydenov] improved support for Exif tag reading in TIFF plugin
++ [Mihail Naydenov] allowed dataWindow with minimal bounds different from zero in OpenEXR plugin
++ [Herve Drolon] added FIMD_EXIF_RAW metadata model
++ [Herve Drolon] JPEG plugin can load & save raw Exif data (see FIMD_EXIF_RAW)
++ [Herve Drolon] added FIF_LOAD_NOPIXELS load flag constant - used to load header & metadata only
++ [Herve Drolon] added FreeImage_HasPixels
++ [Herve Drolon] added FreeImage_FIFSupportsNoPixels
++ [Herve Drolon] added support for FIF_LOAD_NOPIXELS flag to JPEG, PNG, PCD, PCX plugins
++ [Mihail Naydenov] added support for FIF_LOAD_NOPIXELS flag to TGA, PSD, TIFF plugins
++ [Mihail Naydenov] added support for 16-bit image types to FreeImage_Invert
++ [Mihail Naydenov] improved PSD plugin (faster code, added support for CMYK and LAB loading) + added load flags PSD_CMYK & PSD_LAB
++ [Mihail Naydenov] improved TIFF plugin (CMYK 16-bit loading and saving / RGBAF saving) + added TIFF_LOGLUV save flag
+* [Herve Drolon] fixed FreeImage_GetFileType behavior with ANI file formats
+* [Herve Drolon] fixed loading of JNG with progressive-JPEG formats
+* [Mihail Naydenov] fixed loading of TGA with a corrupted rle count
+* [Herve Drolon] fixed conversion formula in FreeImage_PreMultiplyWithAlpha
+* [Christoph Brill] removed the use of libmng_data.h private API in MNG Plugin
+* [phe02sf] fixed handling of bad Exif-GPS data in a Nikon D5000 image
+* [Atsuhiro Igarashi] fixed handling of last data block in PluginGIF::Save (sometimes it saves corrupted images)
+* [Christian Heimes] fixed saving of G3 & G4 compressed TIFF with 1bpp on 64bit Linux
+* [Herve Drolon] fixed long data type being 64-bit on Unix/Linux platforms (use LONG/DWORD instead of long/unsigned long)
+* [Herve Drolon] fixed a memory leak in FreeImage_DeletePage
+* [Herve Drolon] fixed the loading of RGBZ images in OpenEXR plugin
+* [Lucian Sabo] improved conversion from 1-, 4-, 8-bpp transparent images to 32-bpp
+* [Roy F.] fixed a bug in FreeImage_EnlargeCanvas (unable to crop an image on the right)
+* [Herve Drolon] fixed the loading of Exif with unusual IFD offset value
+* [Eberhard Mattes] fixed page numbering info when saving multipage TIFF
+* [Herve Drolon] fixed PluginPICT causing an infinite loop on a malformed PICT image
+* [Eberhard Mattes] improved memory allocation checking when using the new operator
+* [Herve Drolon] (multipage internals) fixed a potential buffer overflow in ReplaceExtension
+* [Eberhard Mattes] improved error checking in FreeImage_CloseMultiBitmap
+
+December 22, 2009 - 3.13.1
+! FreeImage now uses libTIFF 3.9.2
+! FreeImage now uses OpenJPEG 1.3.0 (SVN patch 2009-11-05)
+! FreeImage now uses libPNG 1.2.41
++ [Berend Engelbrecht] added loading of Exif orientation tag in TIFF plugin
++ [Herve Drolon] added decoding support for the old and outdated JPEG-in-TIFF 6.0 format in TIFF plugin
++ [Herve Drolon] added new 'non standard' Exif tags
++ [Herve Drolon] added new Exif makernote tags
+* [Herve Drolon] fixed TIF plugin crashing on a malformed TIFF-JPEG compressed image
+* [Herve Drolon] fixed MNG plugin crashing on some old mng images
+* [Herve Drolon] fixed handling of 2-bit grayscale transparent PNG
+* [Herve Drolon] fixed a bug with the compression rate of JP2 and J2K encoders
+* [zestony] fixed TIF plugin with the '65535 bytes' pitch size limitation on saving
+* [Herve Drolon] fixed handling of PSD files with a non zero file header reserved member
+* [Lucian Sabo] PNG plugin now keep transparency when saving 1- or 4-bit transparent images
+
+September 28th, 2009 - 3.13.0
+! FreeImage now uses LibJPEG 7
+! FreeImage now uses LibRaw-Lite 0.7.2
+! FreeImage now uses libPNG 1.2.40
+! FreeImage now uses libTIFF 3.9.1
+! FreeImage_RotateClassic is deprecated (use FreeImage_Rotate instead)
++ [Herve Drolon] added support for all Photoshop supported color modes to PSD plugin
++ [Herve Drolon] added support for 32-bit to JNG/MNG plugin
++ [Amir Ebrahimi] added loading support for the PICT format
++ [Herve Drolon] added loading support for camera RAW formats (using LibRawLite wrapper for dcraw)
++ [Mihail Naydenov] added UNICODE functions FreeImage_JPEGTransformU and FreeImage_JPEGCropU
++ [Carsten Klein] added FreeImage_OpenMultiBitmapFromHandle
++ [Carsten Klein] added FreeImage_FillBackground
++ [Carsten Klein] added FreeImage_EnlargeCanvas
++ [Carsten Klein] added FreeImage_AllocateEx / FreeImage_AllocateExT
++ [Mihail Naydenov/Herve Drolon] added FreeImage_TmoReinhard05Ex
++ [Herve Drolon] added FIT_RGBA16 to FIT_RGBF conversion to FreeImage_ConvertToRGBF
++ [Herve Drolon] added FreeImage_Rotate (support for most image types, support background color)
+* [Christian Heimes] fixed function prototypes to use a void argument when no argument exist
+* [Herve Drolon] fixed RGB color ordering on Intel macs
+* [Herve Drolon] FreeImage_RotateClassic now keep transparency when applied to 8-bit images
+* [Herve Drolon] fixed handling of transparency info in FreeImage_Copy
+* [Herve Drolon] fixed a normalization error in FreeImage_GetAdjustColorsLookupTable
+* [Herve Drolon] fixed invalid Exif rotation in PluginJPEG for orientation cases 2 and 4
+* [Mihail Naydenov / Carsten Klein] fixed compilation issues with MinGW32
+* [Mihail Naydenov] improved the loading speed of all targa images
+* [Herve Drolon] FreeImage_TagToString now handles the Exif UserComment tag
+
+April 14th, 2009 - 3.12.0
+! FreeImage now uses libPNG 1.2.35
+! FreeImage now uses libTIFF 3.9.0beta (CVS patch 2009-02-12)
+! FreeImage now uses OpenJPEG 1.3.0 (SVN patch 2008-08-21)
+! [Herve Drolon] FreeImage_CloneMetadata no longer clone the FIMD_ANIMATION metadata (this was causing problems when saving to GIF format)
++ [Herve Drolon] added full support for the PFM format
++ [Herve Drolon] added JPEG_EXIFROTATE load flag to the JPEG plugin
++ [Herve Drolon] added 16-bit RGB(A) and float RGB(A)F support to FreeImage_GetChannel / FreeImage_SetChannel
++ [Herve Drolon] added src FIT_RGBA16 to dst 32-bit FIT_BITMAP conversion to FreeImage_ConvertToType
+* [Carsten Klein] FreeImage_Copy now copies transparency info, resolution info, ICC profile and metadata
+* [Carsten Klein] check for negative top/left values in FreeImage_Paste
+* [Christian Heimes] changed exceptions with a "catch(char *text)" to a "catch(const char *text)" to make GCC 4.1 happy
+* [Deif Lou] fixed a bug in FreeImage_SetTransparentIndex
+* [Thomas Maiwald] BMP plugin: on saving, fixed correct setting of bfSize BMP file header for palettized images
+* [Timothy Lee] fixed handling of frame disposal in GIF_PLAYBACK mode (GIF plugin)
+* [Herve Drolon] fixed handling of Exif Olympus Type 2 maker notes (not yet supported but now safely ignored)
+* [Rich Geldreich] fixed DXT1 color endpoint precision problem in DDS plugin
+* [Mihail Naydenov] improved loading speed of 24-bit targa images
+* [Eugene Golushkov] improved big endian / little endian swapping functions
+* [Carsten Klein/Jean-Philippe Goerke] improved FreeImage_SetMetadata / FreeImage_GetMetadata accessors
+* [Christian Ruppert] improved Linux Makefiles
+* [Eugene Golushkov] fixed PluginBMP alignment bug while saving 16 or 24bit BMP on big endian or Apple machines
+
+July 28th, 2008 - 3.11.0
+! FreeImage now uses libTIFF 3.9.0beta (CVS patch 2008-05-24)
+! FreeImage now uses OpenJPEG 1.3.0 (SVN patch 2008-05-22)
+! FreeImage now uses libMNG 1.0.10
+! FreeImage now uses libPNG 1.2.29
++ [Yves Schmid] added 48-bit RGB to 32-bit conversion support in FreeImage_ConvertTo32Bits
++ [Aaron Shumate] added RGB16-to-BITMAP and All-to-RGBF conversion support in FreeImage_ConvertToType
++ [Benjamin English] added a new OpenGL sample to FreeImage/Examples
++ [Lucian Sabo] added new compression flags to the PNG plugin
++ [Lucian Sabo] added new compression flags to the JPEG plugin (chroma subsampling options)
++ [Noam Gat] added support for SGI grayscale + alpha pics to SGI plugin
++ [Herve Drolon] added FreeImage_CloneMetadata
++ [Herve Drolon] added loading support for Windows Vista icons in ICO Plugin
++ [Herve Drolon] added loading and saving support for RGBF images to the TIF plugin (using the LogLuv codec)
+* [Will Bryant] fixed makefile for MacOSX Tiger and Leopard
+* [Maria Gullickson] fixed a 'divide by 0' error in PNM plugin and FreeImage_Rescale function
+* [Yves Schmid] fixed a bug with Exif metadata reading in TIFF images
+* [Herve Drolon] fixed some possible 64-bit portability issues with pointer calculations
+* [wangyn] fixed a bug with transparency handling of indexed images in PNG plugin
+* [Martin Dyring-Andersen] fixed a bug with GIFinfo structure initialization in GIF plugin
+* [Noam Gat] fixed a bug in SGI plugin: when the file reports as two-dimensional, the height factor does not get loaded
+* [Herve Drolon] added error messages in FreeImage_Load(U) / FreeImage_Save(U) in case of bad filenames
+* [Scott Smith/Herve Drolon] added missing IPTC tags and renamed some tag names to be compatible with ExifTool naming convention
+* [Martin Dyring-Andersen] fixed a crash problem with images containing exif data emitted by Picassa
+* [Herve Drolon] removed RGBA to RGB transparent conversion in EXR plugin
+* [Glenn Pierce] improved the speed of FreeImage_FlipHorizontal
+* [Carsten Klein] fixed 65535 pixels width/height limitation in FreeImage_Paste
+
+November 19th, 2007 - 3.10.0
+! FreeImage now uses libTIFF 3.9.0beta (CVS patch 2007-10-05)
+! FreeImage now uses OpenJPEG 1.2.0 (SVN patch 2007-07-13)
+! FreeImage now uses OpenEXR 1.6.1
+! FreeImage now uses libPNG 1.2.23
+! FreeImage now hides its internal functions and internal libraries when compiled with gcc
+- [Herve Drolon] removed VS C+ 6.0 project files : this IDE is no longer supported because of OpenEXR
++ [Herve Drolon] added VS 2005 project files
++ [Herve Drolon] added full support for the OpenEXR format
++ [Herve Drolon] added full support for the JPEG-2000 format
++ [Herve Drolon] added FreeImage_TmoFattal02 tone mapping operator
++ [Ryan Rubley] added support for RGB vs BGR regardless of endian
++ [Herve Drolon] added FreeImage_MultigridPoissonSolver
++ [Carsten Klein] added FreeImage_PreMultiplyWithAlpha
++ [Carsten Klein] added __stdcall version of FreeImage_OutputMessage
++ [Carsten Klein] added new palette and color manipulation functions (see below) :
+ added FreeImage_SetTransparentIndex
+ added FreeImage_GetTransparentIndex
+ added FreeImage_GetAdjustColorsLookupTable
+ added FreeImage_AdjustColors
+ added FreeImage_ApplyColorMapping
+ added FreeImage_SwapColors
+ added FreeImage_ApplyPaletteIndexMapping
+ added FreeImage_SwapPaletteIndices
+* [Herve Drolon] fixed a bug in TIFF plugin when reading 8-bit + 8-bit alpha images
+* [Herve Drolon] fixed a bug in TIFF plugin when reading images with uncommon bitdepths
+* [rodrigo] fixed FreeImage exception handling under gcc (added -fexceptions to gcc compiler flags)
+* [Martin Dyring-Andersen] fixed GIF plugin crashing on some corrupted files
+* [Herve Drolon] fixed a bug with RLE encoding for 8-bit BMP images
+* [Herve Drolon] fixed GPS metadata being skipped when reading metadata in Exif images
+* [Herve Drolon] fixed a bug when reading OS/2 BMP images with a negative height
+* [Ryan Rubley] fixed a bug with loading of GIFs with large amounts of solid color areas
+* [Ryan Rubley] fixed OS X compile error in BitmapAccess.cpp
+* [Herve Drolon] fixed a bug in FreeImage_Paste when pasting non-standard image types
+* [Herve Drolon] saving 1-bit TIF with the TIFF_CCITTFAX3 flag is now compliant with the TIFF Class F specification
+* [Carsten Klein] fixed topdown parameter in FreeImage_ConvertFromRawBits and FreeImage_ConvertToRawBits being handled in reverse
+* [Herve Drolon] fixed a bug when reading some RLE-4 encoded BMP data
+* [Carsten Klein] conversion from 1-bit to 32-bit now keep possibly present transparency
+
+February 11th, 2007 - 3.9.3
+! FreeImage now uses libPNG 1.2.16
+! [Ryan Rubley/Ryan Davis] reworked the MacOSX makefile in order to fully support Universal Binary builds of FreeImage
+! [Herve Drolon] makefiles are now generated from VS2003 project files instead of VS6 project files
+! [Herve Drolon] changed JPEG load/save flag option values
++ [Herve Drolon] added support for RGBAF images to FreeImage_ConvertToRGBF
++ [Herve Drolon] FreeImage_Paste now works with any bitmap type
++ [Herve Drolon] added full support for 64-bit RGBA images to the PNG and TIFF plugins
++ [Jascha Wetzel] added JPEG downsampling feature to PluginJPEG:Load
+* [Thomas Chmielewski] fixed a bug in FreeImage_Dither and Bayer dithering, added FID_BAYER16x16
+* [Raphael Gaquer] greatly improved the speed of the GIF encoder
+* [Herve Drolon] fixed saving of metadata in the PNG plugin
+* [rampelstinskin] fixed transparency table to alpha channel conversion for 4-bit images in FreeImage_ConvertTo32Bits
+* [Scott Smith] added missing IPTC tag named "Country/PrimaryLocationCode"
+* [Herve Drolon] changed #include <stdint.h> by #include <inttypes.h> in FreeImage.h (needed by Solaris 9)
+* [Pierre Arnaud] fixed the use of FreeImage in low memory condition by checking some returned values of the malloc function
+* [Pierre Arnaud] fixed TagLib::getTagFieldName not being thread safe
+
+October 30th, 2006 - 3.9.2
+! FreeImage now uses libTIFF 3.8.2 (with patch 2006-10-13)
++ [Herve Drolon] added full support for 16-bit greyscale and 48-bit RGB to the PNM plugin
++ [Herve Drolon] added IPTC writing support to JPEG & TIFF plugins
++ [Herve Drolon] added new Exif maker note tags
++ [Herve Drolon] added FreeImage_JPEGCrop
++ [Thorsten Radde] added support for 8-bit palettized bitmaps in FreeImage_RotateClassic
++ [Matt Rice] added automatic call to FreeImage_Initialise / FreeImage_DeInitialise when using FreeImage as a .so
++ [Martin Dyring-Andersen] added FreeImage_LoadMultiBitmapFromMemory to the multi-page API
++ [Herve Drolon] added support for tiled TIFF images
+* [Carsten Klein] fixed a bug in FreeImage_SetMetadata occuring when deleting a tag
+* [Herve Drolon] fixed a bug in PNG plugin when reading Macromedia 'false' PNG files
+* [Thorsten Radde] added resolution support to PluginPSD
+* [Ryan Rubley] fixed a bug in PluginGIF occuring with interlaced GIF
+* [Ryan Rubley] fixed a bug in the multipage cache mechanism (internal FreeImage_FindBlock function)
+* [Thorsten Radde] fixed a stack corruption in TIFF plugin occuring when reading exif tags
+* [checkered] fixed a bug in the multipage cache mechanism causing VS2005 to crash on multipage files
+* [Herve Drolon] fixed a bug with transparency support of 1- and 4-bit images
+* [Roar Flolo] fixed a bug in PSD plugin when reading non compressed RGB images (alpha channel initialization)
+* [Nicolas Hatier] fixed a bug in PluginGIF when using the GIF_PLAYBACK flag
+* [Herve Drolon] fixed a bug in TIFF plugin when saving 8-bit images using LZW with differenciation
+* [Herve Drolon] fixed 64-bit compilation issue with LibPNG and assembler code
+
+July 16th, 2006 - 3.9.1
+* [Ryan Rubley] fixed a bug in PluginGIF plugin causing FreeImage to crash on malformed GIF files
+
+July 6th, 2006 - 3.9.0
+! FreeImage now uses libPNG 1.2.12
+! FreeImage now uses libTIFF 3.8.2 (with patch 2006-06-24)
+! FreeImage_Allocate/FreeImage_Allocate now set the resolution to 72 dpi instead of 0
++ [Herve Drolon/Petr Pytelka] added a raw FAX G3 format loader
++ [Herve Drolon] added support for most image types to FreeImage_Rescale
++ [Herve Drolon] added FreeImage_MakeThumbnail
++ [Herve Drolon] added support for 64-bit images to FreeImage_ConvertTo32Bits
++ [Herve Drolon] added support for Exif tags to TIF plugin (read only)
++ [Herve Drolon] added FreeImage_ReadMemory
++ [Herve Drolon] added FreeImage_WriteMemory
++ [Herve Drolon] added new Exif maker note tags
++ [Sherman Wilcox] added a SGI file format loader
++ [Herve Drolon] added support for separated images to PluginTIFF
++ [Herve Drolon] added support for progressive-JPEG saving to PluginJPEG
+* [Carsten Klein] FreeImage_Dither and FreeImage_Threshold now work with palettized 8-bit dib
+* [Christophe Petit] fixed a bug in FreeImage_GetFIFFromFilenameU occuring with files without extension
+* [Leigh Brasington] fixed a bug in PluginGIF causing FreeImage not working on Win/98/ME
+* [Herve Drolon] fixed a bug in PluginTIFF with writing of JPEG-in-TIFF files
+* [Jojakim Stahl] fixed a bug occuring with 4-bit PCX files
+* [Sandor Szalacsi] fixed a bug in FreeImage_SetBackgroundColor (bkgnd clearing)
+* [Petr Pytelka] fixed PluginTIFF::_tiffSizeProc failing on some images
+* [Sherman Wilcox] fixed a bug in DDS plugin when loading images whose size is not a multiple of 4
+* [Sherman Wilcox] fixed a memory leak in PluginDDS::LoadDXT_Helper
+* [Sherman Wilcox] fixed DDS plugin bad behavior with invalid DDS files (such as files with zero length)
+* [Floris van den Berg] fixed a memory leak in the MultiPage cache mechanism
+* [Herve Drolon] replaced WIN32 #define by _WIN32 #define as this is needed by VS2005
+* [Herve Drolon] fixed a VS2005 error in FreeImage_DeletePage
+* [Petr Supina] fixed a pow(long,long) function not being standard ANSI C/C++
+* [Petr Supina] fixed FreeImage_FindBlock function not being standard ANSI C/C++
+* [Olaf Stoyke] added support for 64-bit Linux OS
+* [Craig Stark] fixed FreeImage support on Intel based Mac OS
+* [Herve Drolon] fixed PluginTIFF failing on bad fax tiff images (bad images are now loaded 'as is')
+* [Zack Simpson] fixed a bug occuring in rare situations with FreeImage_Aligned_Malloc
+
+September 5, 2005 - 3.8.0
+! FreeImage now uses libTIFF 3.7.3
+! FreeImage now uses ZLib 1.2.3
++ [Herve Drolon] added support for 48-bit images to FreeImage_ConvertTo24Bits
++ [Herve Drolon] added FreeImage_ConvertToGreyscale
++ [Herve Drolon] added support for 16-bit greyscale images to FreeImage_ConvertTo8Bits
++ [Petr Pytelka] added UNICODE functions (see below)
+ added FreeImage_LoadU
+ added FreeImage_SaveU
+ added FreeImage_GetFIFFromFilenameU
+ added FreeImage_GetFileTypeU
++ [Herve Drolon] FreeImage_Copy now works with any bitmap type
++ [Herve Drolon] added support for 1-bit images to FreeImage_Paste
+* [Ryan Rubley] fixed PluginGIF failing to link on some broken gcc versions
+* [Karl-Heinz Bussian] fixed a bug in LookupX11Color/LookupSVGColor with handling of grey color names
+* [Herve Drolon] FreeImage_Dither now uses FreeImage_ConvertToGreyscale and handles 4/8-bit palletized images
+* [Herve Drolon] FreeImage_Threshold now uses FreeImage_ConvertToGreyscale and handles 4/8-bit palletized images
+* [Craig Hockenberry] fixed PluginGIF::Save swapping the byte order for the height on big endian machines (e.g. PPC on Mac OS X.)
+* [Herve Drolon] fixed a bug in JPEG plugin when reading Exif maker notes from images produced by Nikon Editor
+* [Herve Drolon] fixed a bug in BMP plugin when reading some malformed RLE8 bmp
+* [Herve Drolon] fixed a bug in RAS plugin when loading 8-bit palettized images with less than 256 colors
+* [Herve Drolon] fixed a bug in FreeImage_Rescale with 16-,48-,64-bit images
+* [Herve Drolon] fixed a bug in the ICC profiles API when loading profile-less CMYK TIFF
+* [Herve Drolon] 4-bit PNG are now loaded as 4-bit and no longer converted to 8-bit
+* [Greg Ng] fixed a bug in FreeImage_ConvertToRGBF (FIT_BITMAP -> FIT_RGBF conversion)
+
+May 7, 2005 - 3.7.0
+! FreeImage now uses libTIFF 3.7.2
+! [Ryan Rubley] improved FreeImage_OpenMultiBitmap
++ [Detlev Vendt] added FreeImage_ZLibGUnzip
++ [Herve Drolon] added new image data types FIT_RGB16, FIT_RGBA16, FIT_RGBF, FIT_RGBAF
++ [Herve Drolon] FreeImage_FlipHorizontal & FreeImage_FlipVertical now work with any bitmap type
++ [Herve Drolon] added conversions to float and double in FreeImage_ConvertToType
++ [Herve Drolon] added FreeImage_ConvertToRGBF
++ [Herve Drolon] added support for 16-, 48- and 96-bit images to FreeImage_Rescale
++ [Ryan Rubley] added FreeImage_ColorQuantizeEx
++ [Ryan Rubley] added FIMD_ANIMATION and FIDT_PALETTE
++ [Ryan Rubley] added brand new PluginGIF with full animation multipage and metadata support
++ [Herve Drolon] added support for FIC_MINISWHITE 8-bit images to FreeImage_Rescale
++ [Herve Drolon] added HDR (High Dynamic Range) format (loader & writer)
++ [Herve Drolon] added support for 48-bit images in TIFF plugin
++ [Herve Drolon] added support for 48-bit images in PNG plugin
++ [Herve Drolon] added tone mapping operators (see below)
++ added FreeImage_ToneMapping
++ added FreeImage_TmoDrago03
++ added FreeImage_TmoReinhard05
++ [Petr Pytelka] added FreeImage_JPEGTransform
+* [Herve Drolon] allowed loading of corrupted JPEG with a premature end of file
+* [Herve Drolon] fixed a memory leak with loading of exif JPEG images
+* [Detlev Vendt] changed some 'pointer-to-int' casts to 'pointer-to-long' for 64bit machines
+* [Ryan Rubley] fixed a memory leak in the multipage API
+* [Ryan Rubley] updated VB6 wrapper generation for new functions
+* [Herve Drolon] fixed incorrect behavior when reading JPEG comments containing special characters
+* [Herve Drolon] fixed incorrect behavior when reading JPEG ICC profiles with a size greater than 64 KB
+* [Herve Drolon] fixed a bug in TIFF plugin when loading malformed multipage TIFF
+* [Herve Drolon] fixed PluginTIFF not being thread safe
+
+February 20, 2005 - 3.6.1
+* [Ryan Rubley] fixed a memory leak in the metadata API
+* [luedi] improved the robustness of FIBITMAP allocations
+
+February 13, 2005 - 3.6.0
+! FreeImage now uses libMNG 1.0.9
+! [Herve Drolon] improved the speed of FreeImage_Rescale
+! [Herve Drolon] improved FreeImage_RotateClassic (more compact code, a little faster)
+! [Herve Drolon] improved the metadata API using tag accessors
++ [Detlev Vendt] added LZW support to PluginGIF:Save
++ [Herve Drolon] added VS.Net 2003 project files
++ [Herve Drolon] added VERSIONINFO resource to the DLL
++ [Herve Drolon] added support for CMYK JPEG on loading
++ [Petr Supina] added 16-bytes alignment to FIBITMAP palette and pixels starting address
++ [Petr Supina] added support for MMX/SSE2 code in LibJPEG (based on Mozilla/Firefox code)
++ [Herve Drolon] added TIFF_JPEG compression flag to the TIFF plugin
++ [Detlev Vendt] added FreeImage_ZLibGZip
++ [Detlev Vendt] added FreeImage_ZLibCRC32
+* [Detlev Vendt] fixed PluginPNG not being thread safe
+* [Herve Drolon] fixed compiler warning C4018 occuring with VS.Net 2003
+
+December 29, 2004 - 3.5.3
+! FreeImage now uses ZLib 1.2.2
+! FreeImage now uses libPNG 1.2.8
+! FreeImage now uses libTIFF 3.7.1
+! [Herve Drolon] improved FreeImage_RotateClassic
+! [Detlev Vendt] improved FreeImage_Rescale (more compact code, preserving 8-bpp colors)
++ [Herve Drolon] added support for transparency saving in ICO plugin
++ [Herve Drolon] added support for 1-bit images to FreeImage_RotateClassic
++ [Herve Drolon] added FreeImage_SetDotsPerMeterX and FreeImage_SetDotsPerMeterY
+* [Nan Feng] fixed memory leak in FreeImage_DeleteTag (internal stuff)
+* [Nigel Stewart] added conditional #pragma with #ifdef _MSC_VER / #endif
+* [Herve Drolon] fixed the '65536 lines' limit on loading in PNM plugin
+
+November 27th, 2004 - 3.5.2
+* [Herve Drolon] fixed a second bug in FreeImage_Clone function
+
+November 26th, 2004 - 3.5.1
++ [Riley McNiff] added FreeImage_ConvertTo4Bits
+* [Herve Drolon] fixed a buffer overrun with some ILBM images
+* [Riley McNiff] fixed a potential problem when reading TIFF resolution info
+* [Dimitar Atanasov] fixed a bug in FreeImage_Clone function
+* [Dimitar Atanasov] fixed several bugs in TIFF plugin
+
+November 1st, 2004 - 3.5.0
+! FreeImage now uses libPNG 1.2.7
+! FreeImage now uses libTIFF 3.7.0
+! FreeImage now uses libMNG 1.0.8
+! [Herve Drolon] improved TIFF LZW compression using a predictor
+! [Detlev Vendt] FreeImagesPlus: corrected references to FreeImage.h and FreeImage.lib
++ [Herve Drolon] added support for loading/saving of 8-bit transparent TIFF
++ [Riley McNiff] added support for 4-bit dib in FreeImage_Paste
++ [Herve Drolon] added support for memory IO streams (see below)
++ added FreeImage_OpenMemory
++ added FreeImage_CloseMemory
++ added FreeImage_LoadFromMemory
++ added FreeImage_SaveToMemory
++ added FreeImage_TellMemory
++ added FreeImage_SeekMemory
++ added FreeImage_AcquireMemory
++ added FreeImage_GetFileTypeFromMemory
++ [Petr Pytelka] added FreeImage_GetFIFMimeType to the plugins function list
++ [Herve Drolon] added ICC profile support to JPEG plugin
++ [Herve Drolon] added support for metadata (see below)
++ added FreeImage_SetMetadata
++ added FreeImage_GetMetadata
++ added FreeImage_GetMetadataCount
++ added FreeImage_TagToString
++ added FreeImage_FindFirstMetadata
++ added FreeImage_FindNextMetadata
++ added FreeImage_FindCloseMetadata
+* [Riley McNiff] fixed a bug with FreeImage_SetPixelIndex and 4-bit images
+* [Petr Pytelka] fixed returned value in FreeImage_CloseMultiBitmap
+* [Petr Pytelka] fixed index of new page in FreeImage_InsertPage
+* [Aaron Shumate] fixed a minor bug in PNG plugin
+* [Aaron Shumate] fixed a bug in IFF plugin (odd-length chunks)
+* [Rupert Hewitt] fixed FreeImage not compiling on National Instruments Cvi Ccompiler
+* [Herve Drolon] fixed a bug in IFF plugin (ILBM data)
+* [Fred Harju] added a Makefile for Solaris 9
+* [Roddy Pratt] fixed FreeImage not linking under Borland C++ Builder
+* [Vadim Alexandrov] fixed a memory leak in the multipage API
+* [Herve Drolon] fixed a bug with DDS plugin behaviour on Big Endian OS
+* [Herve Drolon] fixed a bug with conversion of JPEG resolution info on saving
+
+July 8th, 2004 - 3.4.0
+! [Jim Keir] improved FreeImage_FlipVertical function
+! [Herve Drolon] LZW compression is now enabled in FreeImage
++ [Karl-Heinz Bussian] added constants to FreeImage.h to get at compile time the library version
++ [Karl-Heinz Bussian] added color lookup functions for X11 and SVG
++ [Herve Drolon] added TIFF tags TIFF_CCITTFAX3, TIFF_CCITTFAX4 and TIFF_LZW
++ [Detlev Vendt] added support for CMYK TIFF files with alpha channel
++ [Detlev Vendt] added (re-introduction of) PluginGIF
+* [Herve Drolon] fixed a bug with loading of FAX TIFF images (introduced with LibTIFF 3.6.1)
+* [Herve Drolon] fixed a bug in Floyd-Steinberg dithering algorithm
+* [Herve Drolon] fixed a bug in Targa plugin save function
+* [Herve Drolon] fixed a bug in FreeImage_AdjustCurve function
+* [Ryan Rubley] fixed a bug with FreeImage_Rescale's filters accuracy
+* [Ryan Rubley] fixed a bug in NN quantizer
+* [Herve Drolon] fixed a bug with TIFF files containing additional Photoshop alpha channels
+* [James Rossfeld] fixed a memory leak with some PSD images
+* [Herve Drolon] fixed a bug with saving of 32-bit non transparent PNG images
+* [Alexandr Zamaraev] fixed FreeImage not compiling with mingw32
+* [Herve Drolon] fixed FreeImage not compiling with VC.NET (pow function needs casts)
+
+May 2, 2004 - 3.3.0
+! [Ryan Rubley] FreeImage has been ported to MacOSX and should also work on other big endian processors
++ [Ryan Rubley] rewrote XPM plugin (better load support) and added save support
++ [Ryan Rubley] added ICO_MAKEALPHA flag to ICO plugin
++ [Ryan Rubley] Set/GetPixelColor now works with 16-bit pixels (555 or 565)
++ [Herve Drolon] PNG plugin now supports loading and saving of unsigned 16-bit greyscale images
+* [Herve Drolon] fixed a bug with loading of 8-bit and 16-bit PNG with a 8-bit alpha channel
+* [Herve Drolon] fixed a bug in NN quantizer algorithm with handling of 4-byte boundary alignment.
+* [Herve Drolon] fixed a bug in PluginIFF Validate function
+* [Herve Drolon] fixed a minor design issue in FreeImage_GetFIFFromFormat
+* [Brad Schick] fixed some compiler warnings with VC++ 7.1
+* [Herve Drolon] fixed a bug with saving of 8-bit palettized images to 24-bit JPEG (channel inversion)
+
+March 16, 2004 - 3.2.1
+! [Volker Gärtner] improved the DDS plugin
+! [Herve Drolon] FreeImage_Rescale now works on 8-, 24- and 32-bit images
+! [Herve Drolon] FreeImage_Copy now works on 1-, 4-, 8-, 16-, 24- and 32-bit images
+* [Floris van den Berg] fixed a bug in the MultiPage cache mechanism
+* [Herve Drolon] fixed a bug with loading/saving of 8-bit transparent tga images
+* [Herve Drolon] fixed a bug with loading of 1-bit TIFF (introduced with LibTIFF 3.6.1)
+
+February 18, 2004 - 3.2.0
+! FreeImage now uses libTIFF 3.6.1
++ [Herve Drolon] added FreeImage_HasBackgroundColor
++ [Herve Drolon] added FreeImage_GetBackgroundColor
++ [Herve Drolon] added FreeImage_SetBackgroundColor
++ [Herve Drolon] added FreeImage_Composite
++ [Herve Drolon] added ICC profile support to PNG plugin
++ [Herve Drolon] added background color support to PNG plugin
++ [Volker Gärtner] added support for DDS format (loader)
+* [Steve Johnson] improved FreeImage_OpenMultiBitmap/FreeImage_CloseMultiBitmap
+* [Steve Johnson] fixed a bug in FreeImage_InsertPage
+* [Herve Drolon] fixed a bug with JPEG compressed TIFF (red/blue swapping)
+* [Herve Drolon] fixed a bug in PluginTarga where 8-bit images were saved incorrectly
+
+January 26, 2004 - 3.1.0
+! FreeImage now uses ZLib 1.2.1
++ [Herve Drolon] added support for integer, real and complex image types (see below)
++ added FREE_IMAGE_TYPE enum
++ added FreeImage_AllocateT
++ added FreeImage_GetImageType
++ added FreeImage_FIFSupportsExportType
++ added FreeImage_ConvertToStandardType
++ added FreeImage_ConvertToType
++ added load/save support of all image types to TIFF plugin
++ [Peter Lemmens] added a Validate function to TARGA plugin
++ [Herve Drolon] added FreeImage_GetPixelIndex / FreeImage_SetPixelIndex
++ [Herve Drolon] added FreeImage_GetPixelColor / FreeImage_SetPixelColor
++ [Herve Drolon] added FreeImage_GetComplexChannel / FreeImage_SetComplexChannel
+* [Serge Ivanchenko] TIFF_DEFLATE compression is now enabled in TIFF plugin
+* [Herve Drolon] fixed a bug in NeuQuant color reduction algorithm
+
+November 16, 2003 - 3.0.4
+* [Tobias Persson] fixed FreeImage_GetChannel not working with FICC_ALPHA channel
+* [Detlev Vendt] fixed a minor bug with PNG plugin and PNG_IGNOREGAMMA flag
+* [Detlev Vendt] fixed a memory leak in PNG plugin save routine
+* [Detlev Vendt] fixed JPEG validation problem with .jpe files
+* [Ryan Rubley] added Source/LibTIFF/tif_extension.c to LibTIFF (needed for MacOSX)
+* [Herve Drolon] improved error handling in TIFF plugin
++ [Karl-Heinz Bussian] added FreeImage_IsLittleEndian
++ [Karl-Heinz Bussian] added JPEG save support for 8-bit miniswhite bitmaps (transparent conversion to minisblack)
++ [Karl-Heinz Bussian] FreeImage_GetColorType now recognizes 8-bit FIC_MINISWHITE images
+! [Herve Drolon] FreeImage_Rescale now supports rescaling of 32-bit images with alpha channel
+! [Herve Drolon] FreeImage_Invert now supports inversion of 32-bit images with alpha channel
+! [Herve Drolon] FreeImage_AdjustCurve now supports working with FICC_ALPHA channel
+
+November 2, 2003 - 3.0.3
+* [Ryan Rubley] improved makefile for Linux
+* [Ryan Rubley] fixed FreeImage not compiling under MacOSX
+* [Detlev Vendt] fixed still present inconsistancy with 32bpp transparency handling
+* [Herve Drolon] fixed incorrect loading of 4-bit greyscale images in TIFF plugin
+
+October 27, 2003 - 3.0.2
+! FreeImage now uses libMNG 1.0.6
+* [Herve Drolon] fixed a boolean test in PluginCUT returning always false
+* [Herve Drolon] fixed a warning in PluginIFF generated with g++
+* [Linus Tan] fixed a bug in FreeImage_Copy
+* [Herve Drolon] fixed FreeImage not compiling under Linux (thanks to Michal)
+
+October 20, 2003 - 3.0.1
+
+! FreeImage now uses libTIFF 3.6.0
+* [Detlev Vendt] fixed incorrect definition of the FREE_IMAGE_FORMAT enum
+* [Detlev Vendt] fixed a potential crash problem with Load / Save routines
+* [Herve Drolon] fixed incorrect loading of 16-bit greyscale images in TIFF plugin
+* [Dennis Lim] fixed a memory leak in Floyd & Steinberg dithering routine
+* [Herve Drolon] fixed a bug in BMP loader (incorrect loading of RLE4 bmp)
+* [Detlev Vendt] fixed some inconsistancy with 32bpp transparency handling
++ [David Boland] added a C# wrapper
+// Linux compatibility issues
+- [Michal Novotny] removed the round function in Utilities.h
+! [Herve Drolon] replaced the round routine by the clamp routine in PluginPCD
++ [Herve Drolon] added _itoa version in Utilities.h
+* [Michal Novotny] fixed untyped consts not accepted by g++ in PluginBMP
+
+September 8, 2003 - 3.0.0
+- [Herve Drolon] removed deprecated functions
+- [Herve Drolon] removed deprecated flags (TARGA_LOAD_RGB555, ICO_*, except ICO_DEFAULT)
+- [Herve Drolon] removed the FreeImage pointer table (internal stuff)
++ [Herve Drolon] added a C++ wrapper
++ [Herve Drolon] added the FreeImage Toolkit (see below)
++ added FreeImage_Rescale
++ added FreeImage_RotateClassic
++ added FreeImage_RotateEx
++ added FreeImage_FlipHorizontal
++ added FreeImage_FlipVertical
++ added FreeImage_Invert
++ added FreeImage_AdjustCurve
++ added FreeImage_AdjustGamma
++ added FreeImage_AdjustBrightness
++ added FreeImage_AdjustContrast
++ added FreeImage_GetHistogram
++ added FreeImage_GetChannel
++ added FreeImage_SetChannel
++ added FreeImage_Copy
++ added FreeImage_Paste
++ [Karl-Heinz Bussian] added XPM loader
++ [Karl-Heinz Bussian] added flags parameter to FreeImage_CloseMultiBitmap
++ [Karl-Heinz Bussian] added JPEG save support for 8-bit palettized bitmaps (transparent conversion to 24-bit)
++ [Herve Drolon] added interface to ZLib compression functions
++ [Herve Drolon] added ICO format to the multipage API (loader & writer)
++ [Herve Drolon] added a MIME type to all plugins
+* [Karl-Heinz Bussian] fixed incorrect conversion from 1-bit FIC_MINISWHITE bitmaps to 8-bit
+* [Herve Drolon] fixed a bug in FreeImage_CloseMultiBitmap
+* [Herve Drolon] fixed a potential memory leak in conversion functions (8-, 24-, 32-bit)
+* [Robert Walker] fixed incorrect conversion from 16-bit to 24-bit and 16-bit to 32-bit
+* [blurble] fixed TIFF validate signature problem (3DS files were recognized as TIFF)
+* [Kurt Jankowski-Tepe] fixed FreeImage not compiling on MinGW / LCC WIN32
+* [Jani Peltonen] fixed bug in PluginTARGA where 32-bit bitmaps are not always correctly flipped
+* [Detlev Vendt] fixed a bug with TIFF (memory leak with ICC profiles)
+
+May 25, 2003 - 2.6.1
++ [Detlev Vendt] added FIC_CMYK to FREE_IMAGE_COLOR_TYPE
++ [Detlev Vendt] added ICC profile support to the library (see below)
++ added FreeImage_GetICCProfile
++ added FreeImage_CreateICCProfile
++ added FreeImage_DestroyICCProfile
++ added FIICCPROFILE & FIICCPROFILE flags
++ added plugin function FreeImage_FIFSupportsICCProfiles
++ [Detlev Vendt] added ICC profile support for TIFF
++ [Herve Drolon] added XBM (X11 Bitmap Format) support : loading
+* [Herve Drolon] fixed incorrect IFF file detection (thanks Floris)
+* [Herve Drolon] fixed incorrect conversion from 1/4-bit greyscale bitmaps to 8-bit
+* [Herve Drolon] fixed a bug in TIFF writer when saving 1,4,8 bit dib (introduced in 2.6.0, sorry)
+* [Herve Drolon] fixed a palette problem in TIFF loader when loading 1-bit b & w images
+* [Herve Drolon] improved FreeImage_Dither to handle any bitdepth
+
+May 5th, 2003 - 2.6.0
+! FreeImage now uses libPNG 1.2.5
+! FreeImage now uses libMNG 1.0.5
+! [Markus Loibl] ActiveX wrapper is now distributed in a separate release (since 2.5.5)
+! [Herve Drolon] the function FreeImage_Free is now deprecated : use FreeImage_Unload instead
+! [Herve Drolon] updated the generic samples and removed deprecated functions
++ [Detlev Vendt] added CMYK support to TIFF save function
++ [Detlev Vendt] added TIFF_SAVE_CMYK flag constant
++ [Detlev Vendt] added 32-bit support (with transparency handling) to TIFF plugin
++ [Herve Drolon] added FreeImage_Threshold
++ [Herve Drolon] added FreeImage_Dither
++ [Herve Drolon] added FREE_IMAGE_DITHER parameter to FreeImage_Dither
+* [Herve Drolon] improved error handling in PluginMNG
+* [Herve Drolon] improved TIFF flags handling in TIFF save function
+* [Herve Drolon] fixed a potential crash-problem in FreeImage_OutputMessage (in case of a null message)
+* [Detlev Vendt] fixed a bug with the deprecated FreeImage_GetBitsRowCol (trailling backslash behind the DEPRECATE macro)
+
+July 24th, 2002 - 2.5.5
+! FreeImage now uses libPNG 1.2.4
+! FreeImage now uses libMNG 1.0.4
++ [Markus Loibl] added ActiveX wrapper
+
+June 22th, 2002 - 2.5.4
+* [Timothy Roughton] fixed FreeImage not compiling on LCC WIN32
+* [Markus Loibl] fixed PluginTIFF sometimes saving with wrong X/Y resolution
+* fixed crashbug when loading some RLE4 BMPs
+! FreeImage now uses LibPNG 1.2.3
+! [Markus Loibl] improved startup plugin locate handling code
+! [Gerhard Gruber] made some changes so that FreeImage compiles on VC5
++ [Markus Loibl] added flags TIFF_PACKBITS, TIFF_DEFLATE, TIFF_ADOBE_DEFLATE and TIFF_NONE
+
+May 21th, 2002 - 2.5.3
+* fixed wrong colors when loading 16-bit grayscale TIFF
+* fixed crash-problem with FreeImageQt
+* fixed PluginTIFF saving some bitmaps flipped vertically
+* [Laurent Rocher] fixed bug in FreeImage_GetLockedPageNumbers
+* [Laurent Rocher] fixed bug in FreeImage_UnlockPage
+! FreeImage now uses libpng 1.2.2
++ added TARGA save support
++ added BMP RLE8 save support
+
+March 30th, 2002 - 2.5.2
+* fixed bug in PluginTARGA where 32-bit bitmaps are not always correctly flipped
+* fixed FreeImage_GetLockedPageNumber being mentioned in FreeImage.h
+* fixed crash bug when handling read-only multipage bitmaps
+- removed internal function FreeImage_GetExtraDataPointer
+! FreeImage now uses zlib 1.1.4
++ added function FreeImage_GetLockedPageNumbers
+
+March 2nd 2002 - 2.5.1
+* fixed pluginTIFF not being able to save 32-bit bitmaps
+* fixed not being able to save PNM bitmaps through the LoadXXX wrappers
+* fixed a webcam generated BMP image being loaded with wrong colors
+! FI_ReadProc, FI_WriteProc, etc. do now carry the DLL_CALLCONV flag
+! the function FreeImage_GetBitsRowCol is now deprecated
+! FreeImage_SetTransparencyTable now taken an integer as count parameter
+! FreeImage_IsTransparent now always returns true for 32-bit bitmaps
+! PluginPNG::Save now ignores the result of FreeImage_IsTransparent
+! PluginTIFF now converts all 32-bit bitmaps to 24-bit, until our patch
+ to fully support alpha in TIFF is applied in libtiff
++ added full multi-paging support
++ added octal and hexadecimal number support to FreeImage_OutputMessage
+
+January 3rd 2002 - 2.5.0
+* fixed bug in FreeImage_SaveJPEG
+* fixed bug in FreeImage_LoadMNG
+* fixed bug in FreeImage_LoadPNG
+* fixed small Visual C++ 5.0 compiler issue in PluginMNG.cpp
+* fixed FreeImage crashing on JPEG 6.0 encoded TIFFs
+! FreeImage now uses libTIFF 3.5.7
+! FreeImage now uses libPNG 1.2.1
+! all the FreeImage_LoadXXX and FreeImage_SaveXXX functions are now deprecated
++ added Dr. Halo (*.cut) support
++ added printf-like format string support to SetOutputMessage
++ added basic multi-paging support: open, close, counting and grabbing
++ added deprecation manager
++ added FreeImage_Clone function
+
+October 3rd 2001 - 2.4.2
+* fixed missing BI_BITFIELDS support for 32-bit BMPs
+* fixed bug in FreeImage_ConvertLine16_555_To16_565 and vice versa
+* fixed bug in FreeImage_ConvertToRawBits
+* fixed PluginTIFF behaving incorrectly on PHOTOMETRIC_MASK images
+* fixed 16 bit TIFFs not loading correctly
+* fixed incorrect handling of CCITTFAX3 and CCITTFAX4 TIFFs
+* fixed JPEG encoded TIFFs not being supported
+! [Yours Detlev] patched libTIFF to handle EXTRASAMPLE_UNSPECIFIED
+! [Juergen Riecker] improved speed of PCX loading a lot
+! rewrote parts of FreeImage to improve support for c
+! the internal RGB555 and RGB565 macros now read BGR instead of RGB
+! FreeImage now uses libMNG 1.0.3
+! FreeImage now uses libPNG 1.2.0
+! FreeImage_Save now opens files with the "w+b" flag
+! renamed internal macro CalculateUsedColors to CalculateUsedPaletteEntries
+! enabling/disabling plugins no longer has effect on FIFSupportsReading
+! enabling/disabling plugins no longer has effect on FIFSupportsWriting
++ added flag PNG_IGNOREGAMMA
++ added function FreeImage_FIFSupportsExportBPP
+
+July 30th 2001 - 2.4.1
+* [Jan Nauta] fixed some plugin ids not being passed to plugins
+* [Jan Nauta] fixed some functions being natively called instead of indirect
+* [Jan Nauta] fixed BMPs with signature BA not being regognised
+* [Remo Eichenberger] fixed memory leak in the plugin system
+* fixed seek bug in PluginIFF's Validate
+* fixed transparency issue in PluginPNG
+* fixed uncaught exceptions in WUQuantizer and NNQuantizer
+* fixed some problems with PluginTARGA
+* fixed some problems with PluginICO
+* fixed some problems with PluginBMP
+! improved FreeImageQt's load function a little
+! tell/seek control for validation is now handled inside the plugin framework
+
+July 22th 2001 - 2.4.0
+* (Yours Detlev) fixed memory leak in FreeImage_GetFIFFromFilename
+* (Yours Detlev) fixed memory leak in the ICO plugin
+* (Yours Detlev) fixed memory leak in the PNG plugin
+* fixed potential NULL-pointer access bug in Plugin::AddNode
+* fixed problems with linking the static lib
+- removed LBM plugin. Its functionality is placed in the IFF plugin now
+- removed FreeImage_GetFIFByIndex
+! FreeImage now uses LibMNG 1.0.2
+! FreeImage_SetTransparent now only enables alpha when the bitmap is 8 or 32 bit
+! FreeImage_SetTransparencyTable now only enables alpha when the bitmap is 8 bit
+! FreeImage_LoadLBM now uses Mark Sibly's IFF plugin
+! FreeImage_SaveBMP now converts to 24-bit when bpp is 32 and transparency is off
+! FreeImage_SaveJPEG now converts to 24-bit when bpp is 32 and transparency is off
+! FreeImage_SavePNM now converts to 24-bit when bpp is 32 and transparency is off
+! FreeImage_SaveTIFF now converts to 24-bit when bpp is 32 and transparency is off
++ [Mark Sibly] added IFF (ILBM) support
++ added basic support for Photoshop files
++ added mime type support (FreeImage_GetFIFFromMime)
++ added functions FreeImage_SetPluginEnabled and FreeImage_IsPluginEnabled
+ Disabling plugins modifies the behaviour of the following functions:
+ * FreeImage_LoadFromHandle
+ * FreeImage_SaveToHandle
+ * FreeImage_FIFSupportsReading
+ * FreeImage_FIFSupportsWriting
+ * FreeImage_GetFIFFromFormat
+ * FreeImage_GetFIFFromFilename
+ * FreeImage_GetFIFFromMime
+ * FreeImage_Validate
+
+June 30th 2001 - 2.3.2
+* fixed missing "targa" extension in targa extension list
+* fixed small memory leak in PluginList::AddNode
+* fixed 32 bit PNG saving suddenly disappeared from the distro?
+* fixed 'black line' bug in LoadTARGA
+- removed project FreeImageM2
+- removed FreeImage_Combine
+! FreeImage_RegisterLocalPlugin now receives a FI_InitProc as first parameter
+! FreeImage_GetFIFFromFilename now also takes the format id into account
+! cleanup up the code a little for PluginPCD and PluginPCX
++ added static lib project
+
+June 11th 2001 - 2.3.1
+* [Machiel ten Brinke] fixed the loading of some 'ancient' TARGAs
+* [Rui Lopes] fixed some bugs in the external plugin registration
+* fixed the plugin system crashing when the init function isn't called
+- removed project FreeImagePy
+- removed 32 to 24 bit conversion while saving PNG in FreeImageQt
+! the scanline convert functions are now accessable in plugins
+! FreeImage now uses an STL map to store the plugin list
+! PluginSDK.h is now integrated into FreeImage.h
+! FreeImage_Register now receives the boolean parameter 'load_local_plugins_only'
+! FreeImage now uses LibPNG 1.0.12
++ [Rui Lopes] added plugin for GIF reading/writing support
++ added function FreeImage_SetTransparencyCount
++ added support for 32 bit PNG saving
++ added FreeImage_RegisterLocalPlugin to allow plugins inside apps
++ added FreeImage_RegisterExternalPlugin to manually load DLLs
++ added plugin for JBIG reading/writing support
+
+May 4th 2001 - 2.3.0
+* [Martin Weber] fixed some small bugs in the TARGA and BMP plugins
+* [Martin Weber] fixed tiny bug in new 16 bit conversions
+* [Martin Weber] fixed load flag inconsistency in the TARGA plugin
+* [Martin Weber] fixed plugin id / load reference inconsistency for PNM
+* [Jan Nauta] fixed bug in conversion 16 -> 16
+* [Herve Drolon] fixed small bug in 4-bit PCX loader
+- removed code that loads BMPs renamed to ICO in PluginICO
+! the flag TARGA_LOAD_RGB555 is now obsolete
+! the plugin list is now sorted internally
+! ConvertTo32Bits now stores the transparency table as alpha mask
+! FreeImage now uses LibMNG 1.0,1
+! FreeImage now uses LibPNG 1.0.11
++ added external plugin support via DLLs
++ added function FreeImage_GetFIFByIndex
++ added internal function CalculateScanLine
++ added transparency support for high-color PNGs
++ added transparency support for high-color TIFFs
++ added functions FreeImage_SetTransparent and FreeImage_IsTransparent
++ added constant FIC_RGBALPHA to FREE_IMAGE_COLOR_TYPE
+
+April 5th 2001 - 2.2.0
+* [Remo Eichenberger] fixed small bug concerning DLLMain and static LIB generation
+* fixed 1-bit bitmaps not properly loading in FreeImageQt
+* fixed bug in conversion 16->16
+* FreeImage now uses LibPNG 1.0.10
+! [Martin Weber] improved loading of BMP files
+! [Martin Weber] improved loading of TARGA files
+! [Dave Larson] improved visual appearance after 16 conversions
+! FreeImageQt now converts 32-bit bitmaps to 24-bit when saving PNGs and JPEGs
++ added functions FreeImage_Initialise and FreeImage_DeInitialise
++ added internal plugins
++ re-added combine/alphablend functions
+
+March 8th 2001 - 2.1.0
+* [Martin Hemming] fixed bug in 16-bit TARGA loading code
+* fixed PNG's with alpha masks not loading correctly
+! FreeImage is now dual-licensed: the FI-License and the GPL license
+! FreeImage now uses LibPNG 1.0.9
+! FreeImage now uses LibTIFF 3.5.6 Beta
+! FreeImage now uses LiBMNG 1.0.0
+! changed the ordering of the FREE_IMAGE_FORMAT table
+! improved linux support
+! improved test script
++ added transparency table support to SavePNG
++ added BI_BITFIELDS support to LoadBMP and SaveBMP
++ added reading support for OS/2 2.x BMPs
++ added support for MNG and JNG reading using LibMNG
++ added support for Deluxe Paint reading
++ added 'hot swap' support to the Core DLL
++ added 'hot swap' support to FreeImage Qt
++ added functions GetFIFFromFormat and GetFIFFromFilename
++ added functions FIFSupportsReading and FIFSupportsWriting
++ added function GetFIFRegExpr
+
+January 14th 2001 - 2.0.0
+* [Herve Drolon] fixed a bug in the conversion 4->8
+* [Herve Drolon] fixed a bug in metrics handling in SaveJPEG
+* [Herve Drolon] fixed a bug in the return value of the function SaveTIFF
+* fixed the presence of two WuQuantizer.cpp files in the distribution
+* fixed bug where a BMP renamed to ICO isn't loaded
+- removed FreeImage_ConvertToGreyScale. Use FreeImage_ConvertTo8Bits instead.
+- removed the boolean parameters from all conversion routines
+- removed page handling in LoadTIFF. A new range of functions will be added.
+! The void pointers used in FreeImage are now typed
+! LoadBMP now takes palettes in 24/32 bit images in respect
+! All effects and MMX functions are now stored in a new library (FreeEffects)
+! [Herve Drolon] fixed bug in FreeImage_GetColorType
+! [Herve Drolon] improved PCX loader. It can now read 1, 4, 8 and 24-bit images
+! [Manfred Tausch] improved FreeImage_Rotate
+! [Luca Piergentili] fixed crash bug when saving some 1-bit TIFFs
+! rewrote all bitdepth conversion routines making use of the new scanline converters
+! rewrote bitdepth conversion in FreeImageQt (uses less memory)
+! FreeImage is now compiled __stdcall
++ [Herve Drolon] added WBMP (Wireless Bitmap Format) support: loading and saving
++ [Herve Drolon] added 4, 16 and 32 bitdepth handling in GetColorType
++ [Herve Drolon] added handling of 8-bit greyscale bitmaps in SaveJPEG
++ [Herve Drolon] added NeuQuant color reduction algorithm to ColorQuantize
++ added DLL_CALLCONV (calling convention) flag
++ added bitmask support to all bitmaps
++ added a series of functions converting scanlines from one bitdepth to another
++ added functions ConvertFromRawBits and ConvertToRawBits
++ added project FreeImageM2: Magenta II MMT bindings for FreeImage
++ added basic foundation for linux support
+
+December 2th 2000 - 1.4.4
+* fixed small bug related to TIFFSetDirectory in FreeImage_LoadTIFF
+* fixed FreeImage_Rotate sometimes clipping too much pixels
+* fixed other small bug in FreeImage_Rotate
+* fixed FreeImage_Clone not taking the FREEIMAGEHEADER in account
+* fixed bug in FreeImageQt where 1-bit images are not correctly allocated
+* fixed FreeImage_Crop not copying the palette
+* fixed message function pointer crash bug
+* fixed bug where the palette wasn't copied when saving in FreeImageQt
+* fixed FreeImage_Clone not copying the transparency table
+- removed FreeImage_WritePaletteEntry
+! [Adam Gates] rewrote parts of FreeImage so that c compilers can handle it better
+! FreeImageQt doesn't statically link with the FreeImage lib anymore
+! FreeImageQt now uses atexit() to automatically unregister
+! rewrote parts of FreeImage_LoadBMP to increase speed
++ [Markus Loibl] added metrics handling code to LoadBMP, LoadJPEG, LoadTIFF and LoadPCX
++ added metrics handling code to FreeImageQt
++ added functions FIQT_IsLoaded, FIQT_GetVersion and FIQT_GetCopyrightMessage
++ added conversion 1 -> 16
++ added FreeImage_SaveJPEG and JPEG quality settings
++ added FreeImage_GetBitsRowCol
++ added function FIQT_SetOutputMessage to FreeImageQt
++ added FreeImage_GetFileTypeFromExtension and FIQT_GetFileTypeFromFormat
++ added project FreeImagePy: python bindings for FreeImage
+
+November 7th 2000 - 1.4.3
+* fixed FreeImage_SavePNG crash bug
+* fixed slighly corrupt size filter in FreeImage_Combine
+* fixed FreeImage_SaveTIFF not saving 4-bit images
+* [Herve Drolon] fixed bug in FreeImage_LoadTIFF
+* [Herve Drolon] fixed bug in FreeImage_GetColorType
+- removed fclose from FreeImage_SavePNM (who put it there?)
+! rewrote FreeImage_Rotate
+! FreeImageQt now automatically detects which formats are supported by Qt and which not
+! FreeImage_Allocate now returns a void pointer
+! FreeImage_Unload is now called FreeImage_Free
++ added 16-bit 5-5-5 support to FreeImage_LoadBMP
++ added RLE_DELTA support to FreeImage_LoadBMP
++ added directory support to FreeImage_LoadTIFF
++ added functions dealing with transparency
++ added transparency support to 8-bit PNG's in Qt
++ added FREE_IMAGE_QUANTIZE parameter to FreeImage_ColorQuantize
++ added custom FREEIMAGEHEADER header prepended to internal bitmaps
++ added new documentation
+
+October 18th 2000 - 1.4.2
+* fixed FreeImage_SaveBMP storing an incorrect bfSize value in the BITMAPFILEHEADER
+* fixed bug where JPEG and PNG wouldn't load in FreeImageQt
+* fixed FreeImage_Mirror mirroring one pixel less than needed
+! FreeImage_MaskedCombine24 is now called FreeImage_MaskedCombine24Ex
+! FreeImage_MaskedCombine32 is now called FreeImage_MaskedCombine32Ex
++ added 16-bit bitmap support to FreeImage_Mirror
++ added 16-bit bitmap support to FreeImage_ConvertTo8Bits
++ added simple version of FreeImage_MaskedCombine24
++ added simple version of FreeImage_MaskedCombine32
+
+October 17th 2000 - 1.4.1
+* [Herve Drolon] fixed bug in FreeImage_ConvertTo8Bits
+* fixed bug in conversion with 16 -> 24 and 16 -> 32
+- removed static library support
+- removed all unnecessary files from LibTIFF, LibPNG, LibJPEG and ZLib
+- removed all absolute seeks from the library
+! FreeImageQt now makes use of the DLL distro
+! rebuilt the entire directory structure
+! improved handling of BMP
+! renamed FreeImage_MaskedCombine to FreeImage_MaskedCombine32
++ [Alexander Dymerets] added 24-bit masked alpha blending with a seperate alpha mask
++ added FreeImage_Rotate (known bug in degrees 76 to 106)
++ added 4-bit bitmap support to FreeImage_ConvertTo16Bits
++ added 8-bit bitmap support to FreeImage_ConvertTo16Bits
++ added 32-bit bitmap support to FreeImage_ConvertTo16Bits
++ added 32-bit bitmap support to FreeImage_Mirror
++ added 16-bit 5-5-5 support to FreeImage_ConvertTo24Bits
++ added 16-bit 5-5-5 support to FreeImage_ConvertTo32Bits
+
+October 2th 2000 - 1.4.0
+* [Jani Kajala] fixed bug in conversion with 4 -> 24 and 8 -> 32
+* [Jani Kajala] fixed bug in FreeImage_Flip
+* [Jani Kajala] fixed minor bug in FreeImage_LoadBMP
+- [Herve Drolon] removed PBMFlags, PGMFlags and PPMFlags
+- [Herve Drolon] removed FI_LoadGeneric
+- removed FreeImage_Win32.h
+! [Herve Drolon] changed FI_GetFileType
+! [Herve Drolon] replaced FI_LoadPBM, FI_LoadPGM and FI_LoadPPM with FI_LoadPNM
+! [Herve Drolon] improved FreeImage_LoadPNG
+! FreeImage_WritePaletteEntry is now exported
++ [Herve Drolon] added FreeImage_SavePNG
++ [Herve Drolon] added FreeImage_SavePNM and PNMFlags
++ [Herve Drolon] added XXXFlags parameter to save functions
++ [Herve Drolon] added FreeImage_LoadRAS and FIF_RAS
++ added FreeImage_GetFileTypeFromExt
+
+September 7th 2000 - 1.3.5
++ added conversion 4 -> 8 to FI_ConvertTo8Bits
++ added simple version of FI_GetFileType
++ added project FreeImageQt; a port of the library to the TrollTech library
+
+August 31th 2000 - 1.3.4
+* fixed 'ice effect' bug in new 24 bit PCX code
+* fixed some bugs with the conversion 16 -> 24 and 16 -> 32
+! FI_Blur now returns void
+! A debug build of the library now produces FreeImaged.dll and FreeImaged.lib
+! TARGA_LOAD_ARGB8888 is now called TARGA_LOAD_RGB888
+! Alpha channels are now automatically loaded unless TARGA_LOAD_RGB888 is specified
+! cleaned up the code a lot
++ added 32-bit bitmap support to FreeImage_ConvertToGreyscale
++ added support for 32-bit bottom-left TARGA images
++ added internal functions FreeImage_WritePaletteEntry() and FreeImage_GetScanLine()
++ added FreeImage_Win32.h, containing Windows functions needed to create DIBs
++ added documentation through Doxygen
+
+July 30th 2000 - 1.3.3
+* [Jani Kajala] fixed some bugs with the conversion 4 -> 24 and 8 -> 24
+* [Jani Kajala] fixed some bugs with the conversion 4 -> 32 and 8 -> 32
+* fixed bug in FI_LoadPNM's ASCII number loader
+! [Herve Drolon] improved FI_LoadPNG
+! [Herve Drolon] changed FI_ConvertToGreyScale (added changeable macro for conversion)
+! improved FI_ConvertTo24Bits
+! improved FI_ConvertTo32Bits
+! freeImage now uses LibPNG 1.0.8
++ [Herve Drolon] added FI_ColorQuantize, based on Wu's color quantizer
++ added the conversion 1 -> 24
++ added the conversion 1 -> 32
++ added FI_ConvertTo8Bits
++ added FI_Invert (very useful for image processing)
++ added FI_GetColorType and 'enum FREE_IMAGE_COLOR_TYPE'
+
+June 30th 2000 - 1.3.2
+- removed color reduction functions from the project
+! [Herve Drolon] Improved FI_LoadTIFF code
+! renamed FI_ToGrayscale to FI_ConvertToGreyScale
+! renamed FI_IncreaseColors to FI_ConvertTo24Bits
+! LoadBMP now supports 32-bit bitmaps
+! [Jani Kajala] Improved FI_LoadTARGA and FI_LoadPCX code
++ added FI_ConvertTo32Bits to convert a bitmap to 32-bit
++ added FI_MaskCombine to combine two 32-bit bitmaps using a alpha mask
++ added FI_AddAlphaMask to enrich a 32-bit bitmap with an alpha mask
++ added FI_SaveTIFF
++ added 16-bit bitmap (565) support to the ConvertToXXX functions.
++ added FI_ConvertTo16Bits (555 and 565)
+
+June 1th 2000 - 1.3.1
+- removed Standard Template Library (STL) code
+* [Jani Kajala] fixed minor bug in FI_LoadTARGA
+* [Jani Kajala] fixed some minor bugs in FI_LoadPCX
+! streamlined FI_LoadJPEG a little
+! FreeImage now uses LibPNG 1.0.6
+! FreeImage now uses LibTIFF 3.5.5
+! FreeImage now uses malloc and free instead of new and delete
++ introduced compiler flags to disable certain features in the DLL
++ added experimental nearest color reduction (FI_ReduceColorsNearestColor)
+
+April 13th 2000 - 1.3.0
+* fixed some 8 bit PCX files loading incorrectly
+* fixed tiny bug in internally used CalculateUsedColors function
+- removed FI_SaveXPM. Only BMP is supported now.
+- removed Windows dependencies for easier porting
+! optimized FI_LoadKOALA a little
+! optimized FI_Combine using MMX technology
+! FI_Combine now receives an 'unsigned integer' as alpha blend parameter
+! FI_InCreaseColors and FI_ReduceColors don't dispose the old bitmap anymore
++ added PNM support (PGM, PPM and PBM; both binary and ascii)
++ [Alexander Dymerets] added FI_EnableMMX and FI_DisableMMX
++ added various effect functions (FI_Blur, FI_Brighten and FI_Crop)
+
+March 1st 2000 - 1.2.1
+* fixed some 24 bit PCX files loading incorrectly
+
+February 8th 2000 - 1.2.0
+* fixed last bitmap data block in JPEG files being truncated
+* fixed 4/8 bit BMP's incorrectly loading when the palette is smaller than the bitcount predicts
+- removed FI_Load. There is no reliable way to identify all image formats
+- removed FI_SetJpegDecodeMode.
+ Mode selection is now done using the 'DataEnum data' parameter of FI_LoadJPEG
+! read_proc/write_proc/tell_proc in FreeImageIO now are same as fread/fwrite/ftell
++ added a 'DataEnum data' parameter to all FI_LoadXXX functions.
++ added 16 bit TARGA support
++ added RLE support for TARGA images
++ added FI_GetDIBSize to get the size of a DIB in bytes
++ added Kodak PhotoCD support (Base, Base/4 and Base/16 encoding)
++ added KOALA support
++ added FI_GetFileType. Note: there is no reliable way to identify TARGA, ICO and PCD. Therefore they have been excluded
+In KOALA files only the files converted by a C64 emulator can be identified.
++ added FI_Combine to combine two 24-bit bitmaps with (optional) alpha blending
+
+January 15th 2000 - 1.1.1
+! FI_Copy is now called FI_Clone
++ added FI_ToGrayscale to convert a color bitmap to grayscale
++ added 32 bit TARGA support
++ added FI_IncreaseColors to increase the bitmap bitdepth from 4/8 bit to 24 bit
+
+January 14th 2000 - 1.1.0
+* FI_MIRROR: fixed nibbles not being mirrored in 4 bit images
+* FI_MIRROR: fixed bits not being mirrored in 1 bit images
+* fixed improper loading of 1, 4 and 8 bit OS/2 BMP's
+* fixed some inconsistensies in the calculation of lines and pitches
+* fixed incorrectly loading of Huffman and FAX encoded TIFFs
+* fixed LoadTGA accepting 16 bit TGA's and returning corrupt DIB's
+- removed LZW support for TIFFs
+! FreeImage now uses LibTIFF 3.5.4
++ added ICO support
++ added overridable file I/O support in the form of FreeImageIO and fi_handle
++ added FI_Load for generic image loading
++ added FI_ReduceColors for color reduction
++ added FI_Copy to copy a bitmap in memory
+
+January 5th 2000 - 1.0.0
diff --git a/plugins/AdvaImg/Docs/license-gpl.txt b/plugins/AdvaImg/Docs/license-gpl.txt deleted file mode 100644 index 7d1f8605f8..0000000000 --- a/plugins/AdvaImg/Docs/license-gpl.txt +++ /dev/null @@ -1,342 +0,0 @@ - GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
-
diff --git a/plugins/AdvaImg/src/FreeImage/CacheFile.h b/plugins/AdvaImg/src/CacheFile.h index a1e5e782c9..a1e5e782c9 100644 --- a/plugins/AdvaImg/src/FreeImage/CacheFile.h +++ b/plugins/AdvaImg/src/CacheFile.h diff --git a/plugins/AdvaImg/src/FreeImage.h b/plugins/AdvaImg/src/FreeImage.h index 2ee842ae0e..80a5d07514 100644 --- a/plugins/AdvaImg/src/FreeImage.h +++ b/plugins/AdvaImg/src/FreeImage.h @@ -1,1104 +1,1123 @@ -// ==========================================================
-// 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 4
-
-// Compiler options ---------------------------------------------------------
-
-#include <wchar.h> // needed for UNICODE functions
-
-#if defined(FREEIMAGE_LIB)
- #define DLL_API
- #define DLL_CALLCONV
-#else
- #if defined(_WIN32) || defined(__WIN32__)
- #define DLL_CALLCONV __stdcall
- // The following ifdef block is the standard way of creating macros which make exporting
- // from a DLL simpler. All files within this DLL are compiled with the FREEIMAGE_EXPORTS
- // symbol defined on the command line. this symbol should not be defined on any project
- // that uses this DLL. This way any other project whose source files include this file see
- // DLL_API functions as being imported from a DLL, wheras this DLL sees symbols
- // defined with this macro as being exported.
- #ifdef FREEIMAGE_EXPORTS
- #define DLL_API __declspec(dllexport)
- #else
- #define DLL_API __declspec(dllimport)
- #endif // FREEIMAGE_EXPORTS
- #else
- // try the gcc visibility support (see http://gcc.gnu.org/wiki/Visibility)
- #if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
- #ifndef GCC_HASCLASSVISIBILITY
- #define GCC_HASCLASSVISIBILITY
- #endif
- #endif // __GNUC__
- #define DLL_CALLCONV
- #if defined(GCC_HASCLASSVISIBILITY)
- #define DLL_API __attribute__ ((visibility("default")))
- #else
- #define DLL_API
- #endif
- #endif // WIN32 / !WIN32
-#endif // FREEIMAGE_LIB
-
-// Some versions of gcc may have BYTE_ORDER or __BYTE_ORDER defined
-// If your big endian system isn't being detected, add an OS specific check
-#if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || \
- (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || \
- defined(__BIG_ENDIAN__)
-#define FREEIMAGE_BIGENDIAN
-#endif // BYTE_ORDER
-
-// This really only affects 24 and 32 bit formats, the rest are always RGB order.
-#define FREEIMAGE_COLORORDER_BGR 0
-#define FREEIMAGE_COLORORDER_RGB 1
-#if defined(FREEIMAGE_BIGENDIAN)
-#define FREEIMAGE_COLORORDER FREEIMAGE_COLORORDER_RGB
-#else
-#define FREEIMAGE_COLORORDER FREEIMAGE_COLORORDER_BGR
-#endif
-
-// Ensure 4-byte enums if we're using Borland C++ compilers
-#if defined(__BORLANDC__)
-#pragma option push -b
-#endif
-
-// For C compatibility --------------------------------------------------------
-
-#ifdef __cplusplus
-#define FI_DEFAULT(x) = x
-#define FI_ENUM(x) enum x
-#define FI_STRUCT(x) struct x
-#else
-#define FI_DEFAULT(x)
-#define FI_ENUM(x) typedef int x; enum x
-#define FI_STRUCT(x) typedef struct x x; struct x
-#endif
-
-// Bitmap types -------------------------------------------------------------
-
-FI_STRUCT (FIBITMAP) { void *data; };
-FI_STRUCT (FIMULTIBITMAP) { void *data; };
-
-// Types used in the library (directly copied from Windows) -----------------
-
-#if defined(__MINGW32__) && defined(_WINDOWS_H)
-#define _WINDOWS_ // prevent a bug in MinGW32
-#endif // __MINGW32__
-
-#ifndef _WINDOWS_
-#define _WINDOWS_
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#define SEEK_CUR 1
-#define SEEK_END 2
-#endif
-
-#ifndef _MSC_VER
-// define portable types for 32-bit / 64-bit OS
-#include <inttypes.h>
-typedef int32_t BOOL;
-typedef uint8_t BYTE;
-typedef uint16_t WORD;
-typedef uint32_t DWORD;
-typedef int32_t LONG;
-typedef int64_t INT64;
-typedef uint64_t UINT64;
-#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 INT64;
-typedef unsigned __int64 UINT64;
-#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, default to full loading)
-
-#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_GREYSCALE 0x0010 // load and convert to a 8-bit greyscale image
-#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_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
+// ========================================================== +// 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 16 +#define FREEIMAGE_RELEASE_SERIAL 0 + +// Compiler options --------------------------------------------------------- + +#include <wchar.h> // needed for UNICODE functions + +#if defined(FREEIMAGE_LIB) + #define DLL_API + #define DLL_CALLCONV +#else + #if defined(_WIN32) || defined(__WIN32__) + #define DLL_CALLCONV __stdcall + // The following ifdef block is the standard way of creating macros which make exporting + // from a DLL simpler. All files within this DLL are compiled with the FREEIMAGE_EXPORTS + // symbol defined on the command line. this symbol should not be defined on any project + // that uses this DLL. This way any other project whose source files include this file see + // DLL_API functions as being imported from a DLL, wheras this DLL sees symbols + // defined with this macro as being exported. + #ifdef FREEIMAGE_EXPORTS + #define DLL_API __declspec(dllexport) + #else + #define DLL_API __declspec(dllimport) + #endif // FREEIMAGE_EXPORTS + #else + // try the gcc visibility support (see http://gcc.gnu.org/wiki/Visibility) + #if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) + #ifndef GCC_HASCLASSVISIBILITY + #define GCC_HASCLASSVISIBILITY + #endif + #endif // __GNUC__ + #define DLL_CALLCONV + #if defined(GCC_HASCLASSVISIBILITY) + #define DLL_API __attribute__ ((visibility("default"))) + #else + #define DLL_API + #endif + #endif // WIN32 / !WIN32 +#endif // FREEIMAGE_LIB + +// Some versions of gcc may have BYTE_ORDER or __BYTE_ORDER defined +// If your big endian system isn't being detected, add an OS specific check +#if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || \ + (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || \ + defined(__BIG_ENDIAN__) +#define FREEIMAGE_BIGENDIAN +#endif // BYTE_ORDER + +// This really only affects 24 and 32 bit formats, the rest are always RGB order. +#define FREEIMAGE_COLORORDER_BGR 0 +#define FREEIMAGE_COLORORDER_RGB 1 +#if defined(FREEIMAGE_BIGENDIAN) +#define FREEIMAGE_COLORORDER FREEIMAGE_COLORORDER_RGB +#else +#define FREEIMAGE_COLORORDER FREEIMAGE_COLORORDER_BGR +#endif + +// Ensure 4-byte enums if we're using Borland C++ compilers +#if defined(__BORLANDC__) +#pragma option push -b +#endif + +// For C compatibility -------------------------------------------------------- + +#ifdef __cplusplus +#define FI_DEFAULT(x) = x +#define FI_ENUM(x) enum x +#define FI_STRUCT(x) struct x +#else +#define FI_DEFAULT(x) +#define FI_ENUM(x) typedef int x; enum x +#define FI_STRUCT(x) typedef struct x x; struct x +#endif + +// Bitmap types ------------------------------------------------------------- + +FI_STRUCT (FIBITMAP) { void *data; }; +FI_STRUCT (FIMULTIBITMAP) { void *data; }; + +// Types used in the library (directly copied from Windows) ----------------- + +#if defined(__MINGW32__) && defined(_WINDOWS_H) +#define _WINDOWS_ // prevent a bug in MinGW32 +#endif // __MINGW32__ + +#ifndef _WINDOWS_ +#define _WINDOWS_ + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef NULL +#define NULL 0 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + +#ifndef _MSC_VER +// define portable types for 32-bit / 64-bit OS +#include <inttypes.h> +typedef int32_t BOOL; +typedef uint8_t BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef int32_t LONG; +typedef int64_t INT64; +typedef uint64_t UINT64; +#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 INT64; +typedef unsigned __int64 UINT64; +#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, + FIF_WEBP = 35, + FIF_JXR = 36 +}; + +/** 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, default to full loading) + +#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_GREYSCALE 0x0010 //! load and convert to a 8-bit greyscale image +#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 +#define WEBP_DEFAULT 0 //! save with good quality (75:1) +#define WEBP_LOSSLESS 0x100 //! save in lossless mode +#define JXR_DEFAULT 0 //! save with quality 80 and no chroma subsampling (4:4:4) +#define JXR_LOSSLESS 0x0064 //! save lossless +#define JXR_PROGRESSIVE 0x2000 //! save as a progressive-JXR (use | to combine with other save flags) + +// 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)); + +// -------------------------------------------------------------------------- +// JPEG lossless transformation routines +// -------------------------------------------------------------------------- + +DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransform(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect FI_DEFAULT(TRUE)); +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(TRUE)); +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_JPEGTransformFromHandle(FreeImageIO* src_io, fi_handle src_handle, FreeImageIO* dst_io, fi_handle dst_handle, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, BOOL perfect FI_DEFAULT(TRUE));
+DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransformCombined(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, BOOL perfect FI_DEFAULT(TRUE));
+DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransformCombinedU(const wchar_t *src_file, const wchar_t *dst_file, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, BOOL perfect FI_DEFAULT(TRUE));
+DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransformCombinedFromMemory(FIMEMORY* src_stream, FIMEMORY* dst_stream, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, BOOL perfect FI_DEFAULT(TRUE));
+
+ +// -------------------------------------------------------------------------- +// 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); + +// upsampling / downsampling +DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Rescale(FIBITMAP *dib, int dst_width, int dst_height, FREE_IMAGE_FILTER filter FI_DEFAULT(FILTER_CATMULLROM)); +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_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/AdvaImg/src/FreeImage/BitmapAccess.cpp b/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp index 5b90ed8607..2ba5539d4c 100644 --- a/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp +++ b/plugins/AdvaImg/src/FreeImage/BitmapAccess.cpp @@ -1,1269 +1,1306 @@ -// ==========================================================
-// 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 <stdlib.h>
-#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__)
-#include <malloc.h>
-#endif // _WIN32 || _WIN64 || __MINGW32__
-
-#include "FreeImage.h"
-#include "FreeImageIO.h"
-#include "Utilities.h"
-
-#include "../Metadata/FreeImageTag.h"
-
-/** Constants for the BITMAPINFOHEADER::biCompression field */
-#ifndef _WINGDI_
-#define BI_RGB 0L
-#define BI_BITFIELDS 3L
-#endif // _WINGDI_
-
-// ----------------------------------------------------------
-// Metadata definitions
-// ----------------------------------------------------------
-
-// helper for map<key, value> where value is a pointer to a FreeImage tag
-typedef std::map<std::string, FITAG*> TAGMAP;
-
-// helper for map<FREE_IMAGE_MDMODEL, TAGMAP*>
-typedef std::map<int, TAGMAP*> METADATAMAP;
-
-// helper for metadata iterator
-FI_STRUCT (METADATAHEADER) {
- long pos; // current position when iterating the map
- TAGMAP *tagmap; // pointer to the tag map
-};
-
-// ----------------------------------------------------------
-// FIBITMAP definition
-// ----------------------------------------------------------
-
-FI_STRUCT (FREEIMAGEHEADER) {
- FREE_IMAGE_TYPE type; // data type - bitmap, array of long, double, complex, etc
-
- 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
-};
-
-// ----------------------------------------------------------
-// FREEIMAGERGBMASKS definition
-// ----------------------------------------------------------
-
-FI_STRUCT (FREEIMAGERGBMASKS) {
- 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
-};
-
-// ----------------------------------------------------------
-// Memory allocation on a specified alignment boundary
-// ----------------------------------------------------------
-
-#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
-
-void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
- assert(alignment == FIBITMAP_ALIGNMENT);
- return _aligned_malloc(amount, alignment);
-}
-
-void FreeImage_Aligned_Free(void* mem) {
- _aligned_free(mem);
-}
-
-#elif defined (__MINGW32__)
-
-void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
- assert(alignment == FIBITMAP_ALIGNMENT);
- return __mingw_aligned_malloc (amount, alignment);
-}
-
-void FreeImage_Aligned_Free(void* mem) {
- __mingw_aligned_free (mem);
-}
-
-#else
-
-void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
- assert(alignment == FIBITMAP_ALIGNMENT);
- /*
- In some rare situations, the malloc routines can return misaligned memory.
- The routine FreeImage_Aligned_Malloc allocates a bit more memory to do
- aligned writes. Normally, it *should* allocate "alignment" extra memory and then writes
- one dword back the true pointer. But if the memory manager returns a
- misaligned block that is less than a dword from the next alignment,
- then the writing back one dword will corrupt memory.
-
- For example, suppose that alignment is 16 and malloc returns the address 0xFFFF.
-
- 16 - 0xFFFF % 16 + 0xFFFF = 16 - 15 + 0xFFFF = 0x10000.
-
- Now, you subtract one dword from that and write and that will corrupt memory.
-
- That's why the code below allocates *two* alignments instead of one.
- */
- void* mem_real = malloc(amount + 2 * alignment);
- if(!mem_real) return NULL;
- char* mem_align = (char*)((unsigned long)(2 * alignment - (unsigned long)mem_real % (unsigned long)alignment) + (unsigned long)mem_real);
- *((long*)mem_align - 1) = (long)mem_real;
- return mem_align;
-}
-
-void FreeImage_Aligned_Free(void* mem) {
- free((void*)*((long*)mem - 1));
-}
-
-#endif // _WIN32 || _WIN64
-
-// ----------------------------------------------------------
-// DIB information functions
-// ----------------------------------------------------------
-
-/**
-Calculate the size of a FreeImage image.
-Align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary.
-
-@param header_only If TRUE, calculate a 'header only' FIBITMAP size, otherwise calculate a full FIBITMAP size
-@param width
-@param height
-@param bpp
-@param need_masks
-@see FreeImage_AllocateHeaderT
-*/
-static size_t
-FreeImage_GetImageSizeHeader(BOOL header_only, unsigned width, unsigned height, unsigned bpp, BOOL need_masks) {
- 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);
- // we both add palette size and masks size if need_masks is true, since CalculateUsedPaletteEntries
- // always returns 0 if need_masks is true (which is only true for 16 bit images).
- dib_size += need_masks ? sizeof(DWORD) * 3 : 0;
- 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;
-}
-
-/**
+// ========================================================== +// 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 <stdlib.h> +#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__) +#include <malloc.h> +#endif // _WIN32 || _WIN64 || __MINGW32__ + +#include "FreeImage.h" +#include "FreeImageIO.h" +#include "Utilities.h" + +#include "../Metadata/FreeImageTag.h" + +/** Constants for the BITMAPINFOHEADER::biCompression field */ +#ifndef _WINGDI_ +#define BI_RGB 0L +#define BI_BITFIELDS 3L +#endif // _WINGDI_ + +// ---------------------------------------------------------- +// Metadata definitions +// ---------------------------------------------------------- + +// helper for map<key, value> where value is a pointer to a FreeImage tag +typedef std::map<std::string, FITAG*> TAGMAP; + +// helper for map<FREE_IMAGE_MDMODEL, TAGMAP*> +typedef std::map<int, TAGMAP*> METADATAMAP; + +// helper for metadata iterator +FI_STRUCT (METADATAHEADER) { + long pos; // current position when iterating the map + TAGMAP *tagmap; // pointer to the tag map +}; + +// ---------------------------------------------------------- +// FIBITMAP definition +// ---------------------------------------------------------- + +FI_STRUCT (FREEIMAGEHEADER) { + FREE_IMAGE_TYPE type; // data type - bitmap, array of long, double, complex, etc + + 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 +}; + +// ---------------------------------------------------------- +// FREEIMAGERGBMASKS definition +// ---------------------------------------------------------- + +FI_STRUCT (FREEIMAGERGBMASKS) { + 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 +}; + +// ---------------------------------------------------------- +// Memory allocation on a specified alignment boundary +// ---------------------------------------------------------- + +#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) + +void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) { + assert(alignment == FIBITMAP_ALIGNMENT); + return _aligned_malloc(amount, alignment); +} + +void FreeImage_Aligned_Free(void* mem) { + _aligned_free(mem); +} + +#elif defined (__MINGW32__) + +void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) { + assert(alignment == FIBITMAP_ALIGNMENT); + return __mingw_aligned_malloc (amount, alignment); +} + +void FreeImage_Aligned_Free(void* mem) { + __mingw_aligned_free (mem); +} + +#else + +void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) { + assert(alignment == FIBITMAP_ALIGNMENT); + /* + In some rare situations, the malloc routines can return misaligned memory. + The routine FreeImage_Aligned_Malloc allocates a bit more memory to do + aligned writes. Normally, it *should* allocate "alignment" extra memory and then writes + one dword back the true pointer. But if the memory manager returns a + misaligned block that is less than a dword from the next alignment, + then the writing back one dword will corrupt memory. + + For example, suppose that alignment is 16 and malloc returns the address 0xFFFF. + + 16 - 0xFFFF % 16 + 0xFFFF = 16 - 15 + 0xFFFF = 0x10000. + + Now, you subtract one dword from that and write and that will corrupt memory. + + That's why the code below allocates *two* alignments instead of one. + */ + void* mem_real = malloc(amount + 2 * alignment); + if(!mem_real) return NULL; + char* mem_align = (char*)((unsigned long)(2 * alignment - (unsigned long)mem_real % (unsigned long)alignment) + (unsigned long)mem_real); + *((long*)mem_align - 1) = (long)mem_real; + return mem_align; +} + +void FreeImage_Aligned_Free(void* mem) { + free((void*)*((long*)mem - 1)); +} + +#endif // _WIN32 || _WIN64 + +// ---------------------------------------------------------- +// DIB information functions +// ---------------------------------------------------------- + +/** +Calculate the size of a FreeImage image. +Align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary. + +@param header_only If TRUE, calculate a 'header only' FIBITMAP size, otherwise calculate a full FIBITMAP size +@param width +@param height +@param bpp +@param need_masks +@see FreeImage_AllocateHeaderT +*/ +static size_t +FreeImage_GetImageSizeHeader(BOOL header_only, unsigned width, unsigned height, unsigned bpp, BOOL need_masks) { + 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); + // we both add palette size and masks size if need_masks is true, since CalculateUsedPaletteEntries + // always returns 0 if need_masks is true (which is only true for 16 bit images). + dib_size += need_masks ? sizeof(DWORD) * 3 : 0; + 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; +} + +/** Helper for 16-bit FIT_BITMAP -Returns a pointer to the bitmap's red-, green- and blue masks.
-@param dib The bitmap to obtain masks from.
-@return Returns a pointer to the bitmap's red-, green- and blue masks
-or NULL, if no masks are present (e.g. for 24 bit images).
-*/
-static FREEIMAGERGBMASKS *
-FreeImage_GetRGBMasks(FIBITMAP *dib) {
- return FreeImage_HasRGBMasks(dib) ? (FREEIMAGERGBMASKS *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL;
-}
-
-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) {
-
- // check input variables
- width = abs(width);
- height = abs(height);
- if(!((width > 0) && (height > 0))) {
- return NULL;
- }
-
- // we only store the masks (and allocate memory for
- // them) for 16 images of type FIT_BITMAP
- BOOL need_masks = FALSE;
-
- // check pixel bit depth
- switch(type) {
- case FIT_BITMAP:
- switch(bpp) {
- case 1:
- case 4:
- case 8:
- break;
- case 16:
- need_masks = TRUE;
- break;
- 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:
- return NULL;
- }
-
- FIBITMAP *bitmap = (FIBITMAP *)malloc(sizeof(FIBITMAP));
-
- if (bitmap != 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, need_masks);
-
- 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;
-
- 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 = need_masks ? BI_BITFIELDS : BI_RGB;
- 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;
- }
- }
-
- // just setting the masks (only if needed) just like the palette.
- if (need_masks) {
- FREEIMAGERGBMASKS *masks = FreeImage_GetRGBMasks(bitmap);
- masks->red_mask = red_mask;
- masks->green_mask = green_mask;
- masks->blue_mask = blue_mask;
- }
-
- 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;
-
- FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib);
- 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;
- // check whether this image has masks defined ...
- BOOL need_masks = (bpp == 16 && type == FIT_BITMAP) ? TRUE : FALSE;
-
- // allocate a new dib
- FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, type, 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, need_masks);
-
- // 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;
-
- if( FreeImage_HasPixels(dib) ) {
- // check for fully opaque alpha layer
- 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;
- }
-
- return FIC_RGBALPHA;
- }
-
- 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;
-}
-
-// ----------------------------------------------------------
-
-BOOL DLL_CALLCONV
-FreeImage_HasRGBMasks(FIBITMAP *dib) {
- return dib && FreeImage_GetInfoHeader(dib)->biCompression == BI_BITFIELDS;
-}
-
-unsigned DLL_CALLCONV
-FreeImage_GetRedMask(FIBITMAP *dib) {
- FREEIMAGERGBMASKS *masks = FreeImage_GetRGBMasks(dib);
- return masks ? masks->red_mask : 0;
-}
-
-unsigned DLL_CALLCONV
-FreeImage_GetGreenMask(FIBITMAP *dib) {
- FREEIMAGERGBMASKS *masks = FreeImage_GetRGBMasks(dib);
- return masks ? masks->green_mask : 0;
-}
-
-unsigned DLL_CALLCONV
-FreeImage_GetBlueMask(FIBITMAP *dib) {
- FREEIMAGERGBMASKS *masks = FreeImage_GetRGBMasks(dib);
- return masks ? masks->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 = MAX(0, MIN(count, 256));
- if (FreeImage_GetBPP(dib) <= 8) {
- ((FREEIMAGEHEADER *)dib->data)->transparent = (count > 0) ? TRUE : FALSE;
- ((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();
-}
-
-// ----------------------------------------------------------
-
-
+Returns a pointer to the bitmap's red-, green- and blue masks. +@param dib The bitmap to obtain masks from. +@return Returns a pointer to the bitmap's red-, green- and blue masks +or NULL, if no masks are present (e.g. for 24 bit images). +*/ +static FREEIMAGERGBMASKS * +FreeImage_GetRGBMasks(FIBITMAP *dib) { + return FreeImage_HasRGBMasks(dib) ? (FREEIMAGERGBMASKS *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL; +} + +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) { + + // check input variables + width = abs(width); + height = abs(height); + if(!((width > 0) && (height > 0))) { + return NULL; + } + + // we only store the masks (and allocate memory for them) for 16-bit images of type FIT_BITMAP + BOOL need_masks = FALSE; + + // check pixel bit depth + switch(type) { + case FIT_BITMAP: + switch(bpp) { + case 1: + case 4: + case 8: + break; + case 16: + need_masks = TRUE; + break; + 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: + return NULL; + } + + FIBITMAP *bitmap = (FIBITMAP *)malloc(sizeof(FIBITMAP)); + + if (bitmap != 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, need_masks); + + 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; + + 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 = need_masks ? BI_BITFIELDS : BI_RGB; + 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; + } + } + + // just setting the masks (only if needed) just like the palette. + if (need_masks) { + FREEIMAGERGBMASKS *masks = FreeImage_GetRGBMasks(bitmap); + masks->red_mask = red_mask; + masks->green_mask = green_mask; + masks->blue_mask = blue_mask; + } + + 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; + + FREE_IMAGE_TYPE type = FreeImage_GetImageType(dib); + 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; + // check whether this image has masks defined ... + BOOL need_masks = (bpp == 16 && type == FIT_BITMAP) ? TRUE : FALSE; + + // allocate a new dib + FIBITMAP *new_dib = FreeImage_AllocateHeaderT(header_only, type, 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, need_masks); + + // 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_UINT16: + { + // 16-bit greyscale TIF can be either FIC_MINISBLACK (the most common case) or FIC_MINISWHITE + // you can check this using EXIF_MAIN metadata + FITAG *photometricTag = NULL; + if(FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "PhotometricInterpretation", &photometricTag)) { + const short *value = (short*)FreeImage_GetTagValue(photometricTag); + // PHOTOMETRIC_MINISWHITE = 0 => min value is white + // PHOTOMETRIC_MINISBLACK = 1 => min value is black + return (*value == 0) ? FIC_MINISWHITE : FIC_MINISBLACK; + } + return FIC_MINISBLACK; + } + break; + 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; + + if( FreeImage_HasPixels(dib) ) { + // check for fully opaque alpha layer + 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; + } + + return FIC_RGBALPHA; + } + + 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; +} + +// ---------------------------------------------------------- + +BOOL DLL_CALLCONV +FreeImage_HasRGBMasks(FIBITMAP *dib) { + return dib && FreeImage_GetInfoHeader(dib)->biCompression == BI_BITFIELDS; +} + +unsigned DLL_CALLCONV +FreeImage_GetRedMask(FIBITMAP *dib) { + FREEIMAGERGBMASKS *masks = NULL; + FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + switch(image_type) { + case FIT_BITMAP: + // check for 16-bit RGB (565 or 555) + masks = FreeImage_GetRGBMasks(dib); + return masks ? masks->red_mask : FI_RGBA_RED_MASK; + default: + return 0; + } +} + +unsigned DLL_CALLCONV +FreeImage_GetGreenMask(FIBITMAP *dib) { + FREEIMAGERGBMASKS *masks = NULL; + FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + switch(image_type) { + case FIT_BITMAP: + // check for 16-bit RGB (565 or 555) + masks = FreeImage_GetRGBMasks(dib); + return masks ? masks->green_mask : FI_RGBA_GREEN_MASK; + default: + return 0; + } +} + +unsigned DLL_CALLCONV +FreeImage_GetBlueMask(FIBITMAP *dib) { + FREEIMAGERGBMASKS *masks = NULL; + FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + switch(image_type) { + case FIT_BITMAP: + // check for 16-bit RGB (565 or 555) + masks = FreeImage_GetRGBMasks(dib); + return masks ? masks->blue_mask : FI_RGBA_BLUE_MASK; + default: + return 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 = MAX(0, MIN(count, 256)); + if (FreeImage_GetBPP(dib) <= 8) { + ((FREEIMAGEHEADER *)dib->data)->transparent = (count > 0) ? TRUE : FALSE; + ((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/AdvaImg/src/FreeImage/Conversion24.cpp b/plugins/AdvaImg/src/FreeImage/Conversion24.cpp index 1d5bba7f02..3b7a800696 100644 --- a/plugins/AdvaImg/src/FreeImage/Conversion24.cpp +++ b/plugins/AdvaImg/src/FreeImage/Conversion24.cpp @@ -1,252 +1,252 @@ -// ==========================================================
-// 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) && (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 == 24) {
- return FreeImage_Clone(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;
- }
- }
-
- } else if(image_type == FIT_RGB16) {
- 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);
-
- 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;
-
- } else if(image_type == FIT_RGBA16) {
- 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);
-
- 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;
- 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 NULL;
-}
+// ========================================================== +// 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) && (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 == 24) { + return FreeImage_Clone(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; + } + } + + } else if(image_type == FIT_RGB16) { + 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); + + 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; + + } else if(image_type == FIT_RGBA16) { + 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); + + 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; + 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 NULL; +} diff --git a/plugins/AdvaImg/src/FreeImage/Conversion32.cpp b/plugins/AdvaImg/src/FreeImage/Conversion32.cpp index b8bd518471..4874dcfaca 100644 --- a/plugins/AdvaImg/src/FreeImage/Conversion32.cpp +++ b/plugins/AdvaImg/src/FreeImage/Conversion32.cpp @@ -1,345 +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;
-}
+// ========================================================== +// 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/AdvaImg/src/FreeImage/Conversion8.cpp b/plugins/AdvaImg/src/FreeImage/Conversion8.cpp index 1c331a6552..c4f9b22441 100644 --- a/plugins/AdvaImg/src/FreeImage/Conversion8.cpp +++ b/plugins/AdvaImg/src/FreeImage/Conversion8.cpp @@ -1,305 +1,305 @@ -// ==========================================================
-// 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)
-// - Carsten Klein (cklein05@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"
-
-// ----------------------------------------------------------
-// internal conversions X to 8 bits
-// ----------------------------------------------------------
-
-void DLL_CALLCONV
-FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels) {
- for (unsigned cols = 0; cols < (unsigned)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) {
- unsigned count_new = 0;
- unsigned count_org = 0;
- BOOL hinibble = TRUE;
-
- while (count_new < (unsigned)width_in_pixels) {
- if (hinibble) {
- target[count_new] = (source[count_org] >> 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) {
- const WORD *const bits = (WORD *)source;
- for (unsigned cols = 0; cols < (unsigned)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) {
- const WORD *const bits = (WORD *)source;
- for (unsigned cols = 0; cols < (unsigned)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 (unsigned cols = 0; cols < (unsigned)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 (unsigned cols = 0; cols < (unsigned)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 FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
- if (image_type != FIT_BITMAP && image_type != FIT_UINT16) {
- return NULL;
- }
-
- const unsigned bpp = FreeImage_GetBPP(dib);
-
- if (bpp != 8) {
-
- const unsigned width = FreeImage_GetWidth(dib);
- const unsigned height = FreeImage_GetHeight(dib);
-
- // Allocate a destination image
- 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);
-
- // Palette of destination image has already been initialized
- RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
-
- const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
-
- if (image_type == FIT_BITMAP) {
-
- switch(bpp) {
- case 1:
- {
- if (color_type == FIC_PALETTE) {
- // Copy the palette
- RGBQUAD *old_pal = FreeImage_GetPalette(dib);
- new_pal[0] = old_pal[0];
- new_pal[255] = old_pal[1];
-
- } else if (color_type == FIC_MINISWHITE) {
- // Create a reverse grayscale palette
- CREATE_GREYSCALE_PALETTE_REVERSE(new_pal, 256);
- }
-
- // Expand and copy the bitmap data
- for (unsigned rows = 0; rows < height; rows++) {
- FreeImage_ConvertLine1To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
- }
- return new_dib;
- }
-
- case 4 :
- {
- if (color_type == FIC_PALETTE) {
- // Copy the palette
- memcpy(new_pal, FreeImage_GetPalette(dib), 16 * sizeof(RGBQUAD));
- }
-
- // Expand and copy the bitmap data
- for (unsigned 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
- if (IS_FORMAT_RGB565(dib)) {
- for (unsigned rows = 0; rows < height; rows++) {
- FreeImage_ConvertLine16To8_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
- }
- } else {
- for (unsigned rows = 0; rows < height; rows++) {
- 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 (unsigned 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 (unsigned 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 (unsigned rows = 0; rows < height; rows++) {
- const WORD *const src_pixel = (WORD*)src_bits;
- BYTE *dst_pixel = (BYTE*)dst_bits;
- for(unsigned 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);
-
- if (color_type == FIC_PALETTE || color_type == FIC_MINISWHITE) {
-
- const unsigned bpp = FreeImage_GetBPP(dib);
- const unsigned width = FreeImage_GetWidth(dib);
- const unsigned 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);
-
- // Create a greyscale palette
- BYTE grey_pal[256];
- const RGBQUAD *pal = FreeImage_GetPalette(dib);
- const unsigned size = CalculateUsedPaletteEntries(bpp);
- for (unsigned i = 0; i < size; i++) {
- grey_pal[i] = GREY(pal->rgbRed, pal->rgbGreen, pal->rgbBlue);
- pal++;
- }
-
- const BYTE *src_bits = FreeImage_GetBits(dib);
- BYTE *dst_bits = FreeImage_GetBits(new_dib);
-
- const unsigned src_pitch = FreeImage_GetPitch(dib);
- const unsigned dst_pitch = FreeImage_GetPitch(new_dib);
-
- switch(bpp) {
- case 1:
- {
- for (unsigned y = 0; y < height; y++) {
- for (unsigned x = 0; x < width; x++) {
- const unsigned pixel = (src_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
- dst_bits[x] = grey_pal[pixel];
- }
- src_bits += src_pitch;
- dst_bits += dst_pitch;
- }
- }
- break;
-
- case 4:
- {
- for (unsigned y = 0; y < height; y++) {
- for (unsigned x = 0; x < width; x++) {
- const unsigned pixel = x & 0x01 ? src_bits[x >> 1] & 0x0F : src_bits[x >> 1] >> 4;
- dst_bits[x] = grey_pal[pixel];
- }
- src_bits += src_pitch;
- dst_bits += dst_pitch;
- }
- }
- break;
-
- case 8:
- {
- for (unsigned y = 0; y < height; y++) {
- for (unsigned x = 0; x < width; x++) {
- dst_bits[x] = grey_pal[src_bits[x]];
- }
- src_bits += src_pitch;
- dst_bits += dst_pitch;
- }
- }
- break;
- }
- return new_dib;
- }
-
- // Convert the bitmap to 8-bit greyscale
- return FreeImage_ConvertTo8Bits(dib);
-}
+// ========================================================== +// 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) +// - Carsten Klein (cklein05@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" + +// ---------------------------------------------------------- +// internal conversions X to 8 bits +// ---------------------------------------------------------- + +void DLL_CALLCONV +FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels) { + for (unsigned cols = 0; cols < (unsigned)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) { + unsigned count_new = 0; + unsigned count_org = 0; + BOOL hinibble = TRUE; + + while (count_new < (unsigned)width_in_pixels) { + if (hinibble) { + target[count_new] = (source[count_org] >> 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) { + const WORD *const bits = (WORD *)source; + for (unsigned cols = 0; cols < (unsigned)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) { + const WORD *const bits = (WORD *)source; + for (unsigned cols = 0; cols < (unsigned)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 (unsigned cols = 0; cols < (unsigned)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 (unsigned cols = 0; cols < (unsigned)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 FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + if (image_type != FIT_BITMAP && image_type != FIT_UINT16) { + return NULL; + } + + const unsigned bpp = FreeImage_GetBPP(dib); + + if (bpp != 8) { + + const unsigned width = FreeImage_GetWidth(dib); + const unsigned height = FreeImage_GetHeight(dib); + + // Allocate a destination image + 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); + + // Palette of destination image has already been initialized + RGBQUAD *new_pal = FreeImage_GetPalette(new_dib); + + const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); + + if (image_type == FIT_BITMAP) { + + switch(bpp) { + case 1: + { + if (color_type == FIC_PALETTE) { + // Copy the palette + RGBQUAD *old_pal = FreeImage_GetPalette(dib); + new_pal[0] = old_pal[0]; + new_pal[255] = old_pal[1]; + + } else if (color_type == FIC_MINISWHITE) { + // Create a reverse grayscale palette + CREATE_GREYSCALE_PALETTE_REVERSE(new_pal, 256); + } + + // Expand and copy the bitmap data + for (unsigned rows = 0; rows < height; rows++) { + FreeImage_ConvertLine1To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); + } + return new_dib; + } + + case 4 : + { + if (color_type == FIC_PALETTE) { + // Copy the palette + memcpy(new_pal, FreeImage_GetPalette(dib), 16 * sizeof(RGBQUAD)); + } + + // Expand and copy the bitmap data + for (unsigned 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 + if (IS_FORMAT_RGB565(dib)) { + for (unsigned rows = 0; rows < height; rows++) { + FreeImage_ConvertLine16To8_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width); + } + } else { + for (unsigned rows = 0; rows < height; rows++) { + 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 (unsigned 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 (unsigned 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 (unsigned rows = 0; rows < height; rows++) { + const WORD *const src_pixel = (WORD*)src_bits; + BYTE *dst_pixel = (BYTE*)dst_bits; + for(unsigned 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); + + if (color_type == FIC_PALETTE || color_type == FIC_MINISWHITE) { + + const unsigned bpp = FreeImage_GetBPP(dib); + const unsigned width = FreeImage_GetWidth(dib); + const unsigned 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); + + // Create a greyscale palette + BYTE grey_pal[256]; + const RGBQUAD *pal = FreeImage_GetPalette(dib); + const unsigned size = CalculateUsedPaletteEntries(bpp); + for (unsigned i = 0; i < size; i++) { + grey_pal[i] = GREY(pal->rgbRed, pal->rgbGreen, pal->rgbBlue); + pal++; + } + + const BYTE *src_bits = FreeImage_GetBits(dib); + BYTE *dst_bits = FreeImage_GetBits(new_dib); + + const unsigned src_pitch = FreeImage_GetPitch(dib); + const unsigned dst_pitch = FreeImage_GetPitch(new_dib); + + switch(bpp) { + case 1: + { + for (unsigned y = 0; y < height; y++) { + for (unsigned x = 0; x < width; x++) { + const unsigned pixel = (src_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0; + dst_bits[x] = grey_pal[pixel]; + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + + case 4: + { + for (unsigned y = 0; y < height; y++) { + for (unsigned x = 0; x < width; x++) { + const unsigned pixel = x & 0x01 ? src_bits[x >> 1] & 0x0F : src_bits[x >> 1] >> 4; + dst_bits[x] = grey_pal[pixel]; + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + + case 8: + { + for (unsigned y = 0; y < height; y++) { + for (unsigned x = 0; x < width; x++) { + dst_bits[x] = grey_pal[src_bits[x]]; + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + } + return new_dib; + } + + // Convert the bitmap to 8-bit greyscale + return FreeImage_ConvertTo8Bits(dib); +} diff --git a/plugins/AdvaImg/src/FreeImage/ConversionFloat.cpp b/plugins/AdvaImg/src/FreeImage/ConversionFloat.cpp index e72d14cb83..a36a6d423f 100644 --- a/plugins/AdvaImg/src/FreeImage/ConversionFloat.cpp +++ b/plugins/AdvaImg/src/FreeImage/ConversionFloat.cpp @@ -1,192 +1,194 @@ -// ==========================================================
-// 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;
-}
-
+// ========================================================== +// 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); + dst_pixel[x] = CLAMP(dst_pixel[x], 0.0F, 1.0F); + } + 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); + dst_pixel[x] = CLAMP(dst_pixel[x], 0.0F, 1.0F); + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + } + + if(src != dib) { + FreeImage_Unload(src); + } + + return dst; +} + diff --git a/plugins/AdvaImg/src/FreeImage/ConversionRGB16.cpp b/plugins/AdvaImg/src/FreeImage/ConversionRGB16.cpp index bd38504a1e..9e28205688 100644 --- a/plugins/AdvaImg/src/FreeImage/ConversionRGB16.cpp +++ b/plugins/AdvaImg/src/FreeImage/ConversionRGB16.cpp @@ -1,144 +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;
-}
-
+// ========================================================== +// 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/AdvaImg/src/FreeImage/ConversionRGBF.cpp b/plugins/AdvaImg/src/FreeImage/ConversionRGBF.cpp index b5161d566d..230dd7b11b 100644 --- a/plugins/AdvaImg/src/FreeImage/ConversionRGBF.cpp +++ b/plugins/AdvaImg/src/FreeImage/ConversionRGBF.cpp @@ -1,241 +1,243 @@ -// ==========================================================
-// 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;
-}
-
+// ========================================================== +// 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 + // assume float values are in [0..1] + const float value = CLAMP(src_pixel[x], 0.0F, 1.0F); + dst_pixel[x].red = value; + dst_pixel[x].green = value; + dst_pixel[x].blue = value; + } + 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 = CLAMP(src_pixel[x].red, 0.0F, 1.0F); + dst_pixel[x].green = CLAMP(src_pixel[x].green, 0.0F, 1.0F); + dst_pixel[x].blue = CLAMP(src_pixel[x].blue, 0.0F, 1.0F); + } + src_bits += src_pitch; + dst_bits += dst_pitch; + } + } + break; + } + + if(src != dib) { + FreeImage_Unload(src); + } + + return dst; +} + diff --git a/plugins/AdvaImg/src/FreeImage/ConversionUINT16.cpp b/plugins/AdvaImg/src/FreeImage/ConversionUINT16.cpp index ed4691f3a2..e6492aacd2 100644 --- a/plugins/AdvaImg/src/FreeImage/ConversionUINT16.cpp +++ b/plugins/AdvaImg/src/FreeImage/ConversionUINT16.cpp @@ -1,134 +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;
-}
-
+// ========================================================== +// 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/AdvaImg/src/FreeImage/J2KHelper.cpp b/plugins/AdvaImg/src/FreeImage/J2KHelper.cpp index c9f8fa57af..1776c3bfd2 100644 --- a/plugins/AdvaImg/src/FreeImage/J2KHelper.cpp +++ b/plugins/AdvaImg/src/FreeImage/J2KHelper.cpp @@ -1,500 +1,591 @@ -// ==========================================================
-// 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;
- }
-}
+// ========================================================== +// 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" +#include "J2KHelper.h" + +// -------------------------------------------------------------------------- + +static OPJ_UINT64 +_LengthProc(J2KFIO_t *fio) { + long start_pos = fio->io->tell_proc(fio->handle); + fio->io->seek_proc(fio->handle, 0, SEEK_END); + unsigned file_length = fio->io->tell_proc(fio->handle) - start_pos; + fio->io->seek_proc(fio->handle, start_pos, SEEK_SET); + return (OPJ_UINT64)file_length; +} + +static OPJ_SIZE_T +_ReadProc(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) { + J2KFIO_t *fio = (J2KFIO_t*)p_user_data; + OPJ_SIZE_T l_nb_read = fio->io->read_proc(p_buffer, 1, (unsigned)p_nb_bytes, fio->handle); + return l_nb_read ? l_nb_read : (OPJ_SIZE_T)-1; +} + +static OPJ_SIZE_T +_WriteProc(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data) { + J2KFIO_t *fio = (J2KFIO_t*)p_user_data; + return fio->io->write_proc(p_buffer, 1, (unsigned)p_nb_bytes, fio->handle); +} + +static OPJ_OFF_T +_SkipProc(OPJ_OFF_T p_nb_bytes, void *p_user_data) { + J2KFIO_t *fio = (J2KFIO_t*)p_user_data; + if( fio->io->seek_proc(fio->handle, (long)p_nb_bytes, SEEK_CUR) ) { + return -1; + } + return p_nb_bytes; +} + +static OPJ_BOOL +_SeekProc(OPJ_OFF_T p_nb_bytes, FILE * p_user_data) { + J2KFIO_t *fio = (J2KFIO_t*)p_user_data; + if( fio->io->seek_proc(fio->handle, (long)p_nb_bytes, SEEK_SET) ) { + return OPJ_FALSE; + } + return OPJ_TRUE; +} + +// -------------------------------------------------------------------------- + +J2KFIO_t* +opj_freeimage_stream_create(FreeImageIO *io, fi_handle handle, BOOL bRead) { + if(!handle) { + return NULL; + } + J2KFIO_t *fio = (J2KFIO_t*)malloc(sizeof(J2KFIO_t)); + if(fio) { + fio->io = io; + fio->handle = handle; + + opj_stream_t *l_stream = opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, bRead ? OPJ_TRUE : OPJ_FALSE); + if (l_stream) { + opj_stream_set_user_data(l_stream, fio, NULL); + opj_stream_set_user_data_length(l_stream, _LengthProc(fio)); + opj_stream_set_read_function(l_stream, (opj_stream_read_fn)_ReadProc); + opj_stream_set_write_function(l_stream, (opj_stream_write_fn)_WriteProc); + opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn)_SkipProc); + opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn)_SeekProc); + fio->stream = l_stream; + return fio; + } else { + free(fio); + } + } + + return NULL; +} + +void +opj_freeimage_stream_destroy(J2KFIO_t* fio) { + if(fio) { + if(fio->stream) { + opj_stream_destroy(fio->stream); + } + free(fio); + } +} + +// -------------------------------------------------------------------------- + +/** +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 +@param header_only If TRUE, allocate a 'header only' FIBITMAP, otherwise allocate a full FIBITMAP +@return Returns the converted image if successful, returns NULL otherwise +*/ +FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image, BOOL header_only) { + 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_AllocateHeader(header_only, wrr, hrr, 8); + break; + case 3: + dib = FreeImage_AllocateHeader(header_only, wrr, hrr, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + break; + case 4: + dib = FreeImage_AllocateHeader(header_only, 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_AllocateHeaderT(header_only, FIT_UINT16, wrr, hrr); + break; + case 3: + dib = FreeImage_AllocateHeaderT(header_only, FIT_RGB16, wrr, hrr); + break; + case 4: + dib = FreeImage_AllocateHeaderT(header_only, FIT_RGBA16, wrr, hrr); + break; + } + } else { + throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; + } + if(!dib) { + throw FI_MSG_ERROR_DIB_MEMORY; + } + + // "header only" FIBITMAP ? + if(header_only) { + return dib; + } + + 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++) { + WORD *bits = (WORD*)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] = (WORD)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 = OPJ_CLRSPC_GRAY; + break; + case FIC_RGB: + if(FreeImage_GetBPP(dib) == 32) { + // 32-bit image with a fully opaque layer + numcomps = 4; + color_space = OPJ_CLRSPC_SRGB; + } else { + // 24-bit image + numcomps = 3; + color_space = OPJ_CLRSPC_SRGB; + } + break; + case FIC_RGBALPHA: + numcomps = 4; + color_space = OPJ_CLRSPC_SRGB; + break; + default: + return NULL; + } + } else { + // HDR image ... + prec = 16; + switch(image_type) { + case FIT_UINT16: + numcomps = 1; + color_space = OPJ_CLRSPC_GRAY; + break; + case FIT_RGB16: + numcomps = 3; + color_space = OPJ_CLRSPC_SRGB; + break; + case FIT_RGBA16: + numcomps = 4; + color_space = OPJ_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/AdvaImg/src/FreeImage/J2KHelper.h b/plugins/AdvaImg/src/FreeImage/J2KHelper.h new file mode 100644 index 0000000000..a8121f164e --- /dev/null +++ b/plugins/AdvaImg/src/FreeImage/J2KHelper.h @@ -0,0 +1,36 @@ +#ifndef J2K_HELPER_H +#define J2K_HELPER_H + +// ========================================================== +// Helper functions (see J2KHelper.cpp) +// ========================================================== + +/** +FreeImageIO wrapper +*/ +typedef struct tagJ2KFIO_t { + FreeImageIO *io; //! FreeImage IO + fi_handle handle; //! FreeImage handle + opj_stream_t *stream; //! OpenJPEG stream +} J2KFIO_t; + +/** +Stream constructor +*/ +J2KFIO_t* opj_freeimage_stream_create(FreeImageIO *io, fi_handle handle, BOOL bRead); + +/** +Stream destructor +*/ +void opj_freeimage_stream_destroy(J2KFIO_t* fio); + +/** +Conversion opj_image_t => FIBITMAP +*/ +FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image, BOOL header_only); +/** +Conversion FIBITMAP => opj_image_t +*/ +opj_image_t* FIBITMAPToJ2KImage(int format_id, FIBITMAP *dib, const opj_cparameters_t *parameters); + +#endif // J2K_HELPER_H
\ No newline at end of file diff --git a/plugins/AdvaImg/src/FreeImage/MultiPage.cpp b/plugins/AdvaImg/src/FreeImage/MultiPage.cpp index 60ce85eb10..d48e11be94 100644 --- a/plugins/AdvaImg/src/FreeImage/MultiPage.cpp +++ b/plugins/AdvaImg/src/FreeImage/MultiPage.cpp @@ -1,990 +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<BlockTypeS *> BlockList;
-typedef std::list<BlockTypeS *>::iterator BlockListIterator;
-
-// ----------------------------------------------------------
-
-FI_STRUCT (MULTIBITMAPHEADER) {
- PluginNode *node;
- FREE_IMAGE_FORMAT fif;
- FreeImageIO *io;
- fi_handle handle;
- CacheFile *m_cachefile;
- std::map<FIBITMAP *, int> locked_pages;
- BOOL changed;
- int page_count;
- BlockList m_blocks;
- char *m_filename;
- BOOL read_only;
- FREE_IMAGE_FORMAT cache_fif;
- int load_flags;
-};
-
-// =====================================================================
-// 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<FreeImageIO> io (new FreeImageIO);
-
- SetDefaultIO(io.get());
-
- if (!create_new) {
- handle = fopen(filename, "rb");
- if (handle == NULL) {
- return NULL;
- }
- }
-
- std::auto_ptr<FIMULTIBITMAP> bitmap (new FIMULTIBITMAP);
- std::auto_ptr<MULTIBITMAPHEADER> header (new MULTIBITMAPHEADER);
- header->m_filename = new char[strlen(filename) + 1];
- strcpy(header->m_filename, filename);
- header->node = node;
- header->fif = fif;
- header->io = io.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<CacheFile> 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<FIMULTIBITMAP> bitmap (new FIMULTIBITMAP);
- std::auto_ptr<MULTIBITMAPHEADER> header (new MULTIBITMAPHEADER);
- std::auto_ptr<FreeImageIO> 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<CacheFile> 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<FIBITMAP *, int>::iterator i = header->locked_pages.begin(); i != header->locked_pages.end(); ++i) {
- if (i->second == page) {
- return NULL;
- }
- }
-
- // open the bitmap
-
- header->io->seek_proc(header->handle, 0, SEEK_SET);
-
- void *data = FreeImage_Open(header->node, header->io, header->handle, TRUE);
-
- // load the bitmap data
-
- if (data != NULL) {
- FIBITMAP *dib = (header->node->m_plugin->load_proc != NULL) ? header->node->m_plugin->load_proc(header->io, header->handle, page, header->load_flags, data) : NULL;
-
- // close the file
-
- FreeImage_Close(header->node, header->io, header->handle, data);
-
- // if there was still another bitmap open, get rid of it
-
- if (dib) {
- header->locked_pages[dib] = page;
-
- return dib;
- }
-
- return NULL;
- }
- }
-
- return NULL;
-}
-
-void DLL_CALLCONV
-FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *page, BOOL changed) {
- if ((bitmap) && (page)) {
- MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
-
- // find out if the page we try to unlock is actually locked...
-
- if (header->locked_pages.find(page) != header->locked_pages.end()) {
- // store the bitmap compressed in the cache for later writing
-
- if (changed && !header->read_only) {
- header->changed = TRUE;
-
- // cut loose the block from the rest
-
- BlockListIterator i = FreeImage_FindBlock(bitmap, header->locked_pages[page]);
-
- // compress the data
-
- DWORD compressed_size = 0;
- BYTE *compressed_data = NULL;
-
- // open a memory handle
- FIMEMORY *hmem = FreeImage_OpenMemory();
- // save the page to memory
- FreeImage_SaveToMemory(header->cache_fif, page, hmem, 0);
- // get the buffer from the memory stream
- FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size);
-
- // write the data to the cache
-
- switch ((*i)->m_type) {
- case BLOCK_CONTINUEUS :
- {
- int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size);
-
- delete (*i);
-
- *i = (BlockTypeS *)new BlockReference(iPage, compressed_size);
-
- break;
- }
-
- case BLOCK_REFERENCE :
- {
- BlockReference *reference = (BlockReference *)(*i);
-
- header->m_cachefile->deleteFile(reference->m_reference);
-
- delete (*i);
-
- int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size);
-
- *i = (BlockTypeS *)new BlockReference(iPage, compressed_size);
-
- break;
- }
- }
-
- // get rid of the compressed data
-
- FreeImage_CloseMemory(hmem);
- }
-
- // reset the locked page so that another page can be locked
-
- FreeImage_Unload(page);
-
- header->locked_pages.erase(page);
- }
- }
-}
-
-BOOL DLL_CALLCONV
-FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source) {
- if (bitmap) {
- MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
-
- if ((!header->read_only) && (header->locked_pages.empty())) {
- if ((target != source) && ((target >= 0) && (target < FreeImage_GetPageCount(bitmap))) && ((source >= 0) && (source < FreeImage_GetPageCount(bitmap)))) {
- BlockListIterator block_source = FreeImage_FindBlock(bitmap, target);
- BlockListIterator block_target = FreeImage_FindBlock(bitmap, source);
-
- header->m_blocks.insert(block_target, *block_source);
- header->m_blocks.erase(block_source);
-
- header->changed = TRUE;
-
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-BOOL DLL_CALLCONV
-FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count) {
- if ((bitmap) && (count)) {
- MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
-
- if ((pages == NULL) || (*count == 0)) {
- *count = (int)header->locked_pages.size();
- } else {
- int c = 0;
-
- for (std::map<FIBITMAP *, int>::iterator i = header->locked_pages.begin(); i != header->locked_pages.end(); ++i) {
- pages[c] = i->second;
-
- c++;
-
- if (c == *count)
- break;
- }
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-// =====================================================================
-// 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;
-}
+// ========================================================== +// 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<BlockTypeS *> BlockList; +typedef std::list<BlockTypeS *>::iterator BlockListIterator; + +// ---------------------------------------------------------- + +FI_STRUCT (MULTIBITMAPHEADER) { + PluginNode *node; + FREE_IMAGE_FORMAT fif; + FreeImageIO *io; + fi_handle handle; + CacheFile *m_cachefile; + std::map<FIBITMAP *, int> locked_pages; + BOOL changed; + int page_count; + BlockList m_blocks; + char *m_filename; + BOOL read_only; + FREE_IMAGE_FORMAT cache_fif; + int load_flags; +}; + +// ===================================================================== +// 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<FreeImageIO> io (new FreeImageIO); + + SetDefaultIO(io.get()); + + if (!create_new) { + handle = fopen(filename, "rb"); + if (handle == NULL) { + return NULL; + } + } + + std::auto_ptr<FIMULTIBITMAP> bitmap (new FIMULTIBITMAP); + std::auto_ptr<MULTIBITMAPHEADER> header (new MULTIBITMAPHEADER); + header->m_filename = new char[strlen(filename) + 1]; + strcpy(header->m_filename, filename); + header->node = node; + header->fif = fif; + header->io = io.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<CacheFile> 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<FIMULTIBITMAP> bitmap (new FIMULTIBITMAP); + std::auto_ptr<MULTIBITMAPHEADER> header (new MULTIBITMAPHEADER); + std::auto_ptr<FreeImageIO> 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<CacheFile> 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<FIBITMAP *, int>::iterator i = header->locked_pages.begin(); i != header->locked_pages.end(); ++i) { + if (i->second == page) { + return NULL; + } + } + + // open the bitmap + + header->io->seek_proc(header->handle, 0, SEEK_SET); + + void *data = FreeImage_Open(header->node, header->io, header->handle, TRUE); + + // load the bitmap data + + if (data != NULL) { + FIBITMAP *dib = (header->node->m_plugin->load_proc != NULL) ? header->node->m_plugin->load_proc(header->io, header->handle, page, header->load_flags, data) : NULL; + + // close the file + + FreeImage_Close(header->node, header->io, header->handle, data); + + // if there was still another bitmap open, get rid of it + + if (dib) { + header->locked_pages[dib] = page; + + return dib; + } + + return NULL; + } + } + + return NULL; +} + +void DLL_CALLCONV +FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *page, BOOL changed) { + if ((bitmap) && (page)) { + MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); + + // find out if the page we try to unlock is actually locked... + + if (header->locked_pages.find(page) != header->locked_pages.end()) { + // store the bitmap compressed in the cache for later writing + + if (changed && !header->read_only) { + header->changed = TRUE; + + // cut loose the block from the rest + + BlockListIterator i = FreeImage_FindBlock(bitmap, header->locked_pages[page]); + + // compress the data + + DWORD compressed_size = 0; + BYTE *compressed_data = NULL; + + // open a memory handle + FIMEMORY *hmem = FreeImage_OpenMemory(); + // save the page to memory + FreeImage_SaveToMemory(header->cache_fif, page, hmem, 0); + // get the buffer from the memory stream + FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size); + + // write the data to the cache + + switch ((*i)->m_type) { + case BLOCK_CONTINUEUS : + { + int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size); + + delete (*i); + + *i = (BlockTypeS *)new BlockReference(iPage, compressed_size); + + break; + } + + case BLOCK_REFERENCE : + { + BlockReference *reference = (BlockReference *)(*i); + + header->m_cachefile->deleteFile(reference->m_reference); + + delete (*i); + + int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size); + + *i = (BlockTypeS *)new BlockReference(iPage, compressed_size); + + break; + } + } + + // get rid of the compressed data + + FreeImage_CloseMemory(hmem); + } + + // reset the locked page so that another page can be locked + + FreeImage_Unload(page); + + header->locked_pages.erase(page); + } + } +} + +BOOL DLL_CALLCONV +FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source) { + if (bitmap) { + MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); + + if ((!header->read_only) && (header->locked_pages.empty())) { + if ((target != source) && ((target >= 0) && (target < FreeImage_GetPageCount(bitmap))) && ((source >= 0) && (source < FreeImage_GetPageCount(bitmap)))) { + BlockListIterator block_source = FreeImage_FindBlock(bitmap, target); + BlockListIterator block_target = FreeImage_FindBlock(bitmap, source); + + header->m_blocks.insert(block_target, *block_source); + header->m_blocks.erase(block_source); + + header->changed = TRUE; + + return TRUE; + } + } + } + + return FALSE; +} + +BOOL DLL_CALLCONV +FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count) { + if ((bitmap) && (count)) { + MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap); + + if ((pages == NULL) || (*count == 0)) { + *count = (int)header->locked_pages.size(); + } else { + int c = 0; + + for (std::map<FIBITMAP *, int>::iterator i = header->locked_pages.begin(); i != header->locked_pages.end(); ++i) { + pages[c] = i->second; + + c++; + + if (c == *count) + break; + } + } + + return TRUE; + } + + return FALSE; +} + +// ===================================================================== +// 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/AdvaImg/src/FreeImage/PSDParser.cpp b/plugins/AdvaImg/src/FreeImage/PSDParser.cpp index 57c703a06f..fba54c2421 100644 --- a/plugins/AdvaImg/src/FreeImage/PSDParser.cpp +++ b/plugins/AdvaImg/src/FreeImage/PSDParser.cpp @@ -506,6 +506,10 @@ bool psdParser::ReadImageResources(FreeImageIO *io, fi_handle handle, LONG lengt oResource.Reset(); n = (int)io->read_proc(&oResource._OSType, sizeof(oResource._OSType), 1, handle); + if(n != 1) { + FreeImage_OutputMessageProc(_fi_format_id, "This file contains damaged data causing an unexpected end-of-file - stop reading resources"); + return false; + } nBytes += n * sizeof(oResource._OSType); if( (nBytes % 2) != 0 ) { diff --git a/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp b/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp index e3dccfe1c9..c69463c316 100644 --- a/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp +++ b/plugins/AdvaImg/src/FreeImage/PixelAccess.cpp @@ -1,210 +1,210 @@ -// ==========================================================
-// 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 += FreeImage_HasRGBMasks(dib) ? sizeof(DWORD) * 3 : 0;
- 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;
-}
-
+// ========================================================== +// 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 += FreeImage_HasRGBMasks(dib) ? sizeof(DWORD) * 3 : 0; + 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/AdvaImg/src/FreeImage/Plugin.cpp b/plugins/AdvaImg/src/FreeImage/Plugin.cpp index 7ded36ebc2..6f88e47e68 100644 --- a/plugins/AdvaImg/src/FreeImage/Plugin.cpp +++ b/plugins/AdvaImg/src/FreeImage/Plugin.cpp @@ -218,7 +218,12 @@ FreeImage_GetPluginList() { void DLL_CALLCONV FreeImage_Initialise(BOOL load_local_plugins_only) { if (s_plugin_reference_count++ == 0) { - + + /* + Note: initialize all singletons here + in order to avoid race conditions with multi-threading + */ + // initialise the TagLib singleton TagLib& s = TagLib::instance(); @@ -257,7 +262,7 @@ FreeImage_Initialise(BOOL load_local_plugins_only) { //s_plugins->AddNode(InitXPM); //s_plugins->AddNode(InitDDS); s_plugins->AddNode(InitGIF); - //s_plugins->AddNode(InitHDR); + //s_plugins->AddNode(InitHDR); //s_plugins->AddNode(InitG3); //s_plugins->AddNode(InitSGI); //s_plugins->AddNode(InitEXR); @@ -266,6 +271,74 @@ FreeImage_Initialise(BOOL load_local_plugins_only) { //s_plugins->AddNode(InitPFM); //s_plugins->AddNode(InitPICT); //s_plugins->AddNode(InitRAW); + //s_plugins->AddNode(InitWEBP); +//#if !(defined(_MSC_VER) && (_MSC_VER <= 1310)) + //s_plugins->AddNode(InitJXR); +//#endif // unsupported by MS Visual Studio 2003 !!! + + // external plugin initialization + +#ifdef _WIN32 + if (!load_local_plugins_only) { + int count = 0; + char buffer[MAX_PATH + 200]; + char current_dir[2 * _MAX_PATH], module[2 * _MAX_PATH]; + BOOL bOk = FALSE; + + // store the current directory. then set the directory to the application location + + if (GetCurrentDirectoryA(2 * _MAX_PATH, current_dir) != 0) { + if (GetModuleFileNameA(NULL, module, 2 * _MAX_PATH) != 0) { + char *last_point = strrchr(module, '\\'); + + if (last_point) { + *last_point = '\0'; + + bOk = SetCurrentDirectoryA(module); + } + } + } + + // search for plugins + + while (count < s_search_list_size) { + _finddata_t find_data; + long find_handle; + + strcpy(buffer, s_search_list[count]); + strcat(buffer, "*.fip"); + + if ((find_handle = (long)_findfirst(buffer, &find_data)) != -1L) { + do { + strcpy(buffer, s_search_list[count]); + strncat(buffer, find_data.name, MAX_PATH + 200); + + HINSTANCE instance = LoadLibraryA(buffer); + + if (instance != NULL) { + FARPROC proc_address = GetProcAddress(instance, "_Init@8"); + + if (proc_address != NULL) { + s_plugins->AddNode((FI_InitProc)proc_address, (void *)instance); + } else { + FreeLibrary(instance); + } + } + } while (_findnext(find_handle, &find_data) != -1L); + + _findclose(find_handle); + } + + count++; + } + + // restore the current directory + + if (bOk) { + SetCurrentDirectoryA(current_dir); + } + } +#endif // _WIN32 } } } diff --git a/plugins/AdvaImg/src/FreeImage/PluginBMP.cpp b/plugins/AdvaImg/src/FreeImage/PluginBMP.cpp index 4041d859fa..0ee1c5db30 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginBMP.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginBMP.cpp @@ -35,10 +35,13 @@ 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; +static const BYTE BI_RGB = 0; // compression: none +static const BYTE BI_RLE8 = 1; // compression: RLE 8-bit/pixel +static const BYTE BI_RLE4 = 2; // compression: RLE 4-bit/pixel +static const BYTE BI_BITFIELDS = 3; // compression: Bit field or Huffman 1D compression for BITMAPCOREHEADER2 +static const BYTE BI_JPEG = 4; // compression: JPEG or RLE-24 compression for BITMAPCOREHEADER2 +static const BYTE BI_PNG = 5; // compression: PNG +static const BYTE BI_ALPHABITFIELDS = 6; // compression: Bit field (this value is valid in Windows CE .NET 4.0 and later) // ---------------------------------------------------------- @@ -65,11 +68,11 @@ typedef struct tagBITMAPINFOOS2_1X_HEADER { } BITMAPINFOOS2_1X_HEADER, *PBITMAPINFOOS2_1X_HEADER; typedef struct tagBITMAPFILEHEADER { - WORD bfType; - DWORD bfSize; - WORD bfReserved1; - WORD bfReserved2; - DWORD bfOffBits; + WORD bfType; //! The file type + DWORD bfSize; //! The size, in bytes, of the bitmap file + WORD bfReserved1; //! Reserved; must be zero + WORD bfReserved2; //! Reserved; must be zero + DWORD bfOffBits; //! The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits } BITMAPFILEHEADER, *PBITMAPFILEHEADER; #ifdef _WIN32 @@ -452,7 +455,7 @@ LoadPixelDataRLE8(FreeImageIO *io, fi_handle handle, int width, int height, FIBI // -------------------------------------------------------------------------- static FIBITMAP * -LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) { +LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset, int type) { FIBITMAP *dib = NULL; try { @@ -481,8 +484,9 @@ LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bit case 4 : case 8 : { - if ((used_colors == 0) || (used_colors > CalculateUsedPaletteEntries(bit_count))) + 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 @@ -494,6 +498,19 @@ LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bit // set resolution information FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter); FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter); + + // seek to the end of the header (depending on the BMP header version) + // type == sizeof(BITMAPVxINFOHEADER) + switch(type) { + case 40: // sizeof(BITMAPINFOHEADER) - all Windows versions since Windows 3.0 + break; + case 52: // sizeof(BITMAPV2INFOHEADER) (undocumented) + case 56: // sizeof(BITMAPV3INFOHEADER) (undocumented) + case 108: // sizeof(BITMAPV4HEADER) - all Windows versions since Windows 95/NT4 (not supported) + case 124: // sizeof(BITMAPV5HEADER) - Windows 98/2000 and newer (not supported) + io->seek_proc(handle, (long)(type - sizeof(BITMAPINFOHEADER)), SEEK_CUR); + break; + } // load the palette @@ -512,10 +529,8 @@ LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bit // seek to the actual pixel data. // this is needed because sometimes the palette is larger than the entries it contains predicts + io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); - 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) { @@ -551,11 +566,15 @@ LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bit case 16 : { - if (bih.biCompression == BI_BITFIELDS) { - DWORD bitfields[3]; - - io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle); - + int use_bitfields = 0; + if (bih.biCompression == BI_BITFIELDS) use_bitfields = 3; + else if (bih.biCompression == BI_ALPHABITFIELDS) use_bitfields = 4; + else if (type == 52) use_bitfields = 3; + else if (type >= 56) use_bitfields = 4; + + if (use_bitfields > 0) { + DWORD bitfields[4]; + io->read_proc(bitfields, use_bitfields * 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); @@ -573,14 +592,11 @@ LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bit // header only mode return dib; } + + // seek to the actual pixel data + io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); // 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; @@ -590,11 +606,15 @@ LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bit case 24 : case 32 : { - if (bih.biCompression == BI_BITFIELDS) { - DWORD bitfields[3]; - - io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle); - + int use_bitfields = 0; + if (bih.biCompression == BI_BITFIELDS) use_bitfields = 3; + else if (bih.biCompression == BI_ALPHABITFIELDS) use_bitfields = 4; + else if (type == 52) use_bitfields = 3; + else if (type >= 56) use_bitfields = 4; + + if (use_bitfields > 0) { + DWORD bitfields[4]; + io->read_proc(bitfields, use_bitfields * sizeof(DWORD), 1, handle); dib = FreeImage_AllocateHeader(header_only, width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]); } else { if( bit_count == 32 ) { @@ -619,12 +639,10 @@ LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bit // Skip over the optional palette // A 24 or 32 bit DIB may contain a palette for faster color reduction + // i.e. you can have (FreeImage_GetColorsUsed(dib) > 0) - 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); - } + // seek to the actual pixel data + 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 @@ -735,8 +753,9 @@ LoadOS22XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_ // 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))) + if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3))) { io->seek_proc(handle, bitmap_bits_offset, SEEK_SET); + } // read the pixel data @@ -827,8 +846,9 @@ LoadOS22XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_ // 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))) + 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 @@ -1101,24 +1121,18 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { 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; + + case 40: // BITMAPINFOHEADER - all Windows versions since Windows 3.0 + case 52: // BITMAPV2INFOHEADER (undocumented, partially supported) + case 56: // BITMAPV3INFOHEADER (undocumented, partially supported) + case 108: // BITMAPV4HEADER - all Windows versions since Windows 95/NT4 (partially supported) + case 124: // BITMAPV5HEADER - Windows 98/2000 and newer (partially supported) + return LoadWindowsBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits, type); + default: break; } diff --git a/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp b/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp index e8d84afac4..87c0185865 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginGIF.cpp @@ -376,7 +376,7 @@ bool StringTable::Decompress(BYTE *buf, int *len) m_partial >>= m_codeSize; m_partialSize -= m_codeSize; - if( code > m_nextCode || (m_nextCode == MAX_LZW_CODE && code != m_clearCode) || code == m_endCode ) { + if( code > m_nextCode || /*(m_nextCode == MAX_LZW_CODE && code != m_clearCode) || */code == m_endCode ) { m_done = true; *len = (int)(bufpos - buf); return true; @@ -387,7 +387,7 @@ bool StringTable::Decompress(BYTE *buf, int *len) } //add new string to string table, if not the first pass since a clear code - if( m_oldCode != MAX_LZW_CODE ) { + if( m_oldCode != MAX_LZW_CODE && m_nextCode < MAX_LZW_CODE) { m_strings[m_nextCode] = m_strings[m_oldCode] + m_strings[code == m_nextCode ? m_oldCode : code][0]; } diff --git a/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp b/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp index d8c24adc31..0cde6139db 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginHDR.cpp @@ -73,7 +73,7 @@ typedef enum { rgbe_read_error, rgbe_write_error, rgbe_format_error, - rgbe_memory_error, + rgbe_memory_error } rgbe_error_code; // ---------------------------------------------------------- diff --git a/plugins/AdvaImg/src/FreeImage/PluginICO.cpp b/plugins/AdvaImg/src/FreeImage/PluginICO.cpp index 7f41a0d841..df5ecee91d 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginICO.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginICO.cpp @@ -339,7 +339,8 @@ LoadStandardIcon(FreeImageIO *io, fi_handle handle, int flags, BOOL header_only) // bitmap has been loaded successfully! // convert to 32bpp and generate an alpha channel - if((flags & ICO_MAKEALPHA) == ICO_MAKEALPHA) { + // apply the AND mask only if the image is not 32 bpp + if(((flags & ICO_MAKEALPHA) == ICO_MAKEALPHA) && (bit_count < 32)) { FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(dib); FreeImage_Unload(dib); diff --git a/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp b/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp index ae8a6ae88a..5c23a7c6e1 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginJ2K.cpp @@ -1,339 +1,327 @@ -// ==========================================================
-// 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;
-}
+// ========================================================== +// 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" +#include "J2KHelper.h" + +// ========================================================== +// Plugin Interface +// ========================================================== + +static int s_format_id; + +// ========================================================== +// 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) { + // create the stream wrapper + J2KFIO_t *fio = opj_freeimage_stream_create(io, handle, read); + return fio; +} + +static void DLL_CALLCONV +Close(FreeImageIO *io, fi_handle handle, void *data) { + // destroy the stream wrapper + J2KFIO_t *fio = (J2KFIO_t*)data; + opj_freeimage_stream_destroy(fio); +} + +// ---------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + J2KFIO_t *fio = (J2KFIO_t*)data; + if (handle && fio) { + opj_codec_t *d_codec = NULL; // handle to a decompressor + opj_dparameters_t parameters; // decompression parameters + opj_image_t *image = NULL; // decoded image + + FIBITMAP *dib = NULL; + + // check the file format + if(!Validate(io, handle)) { + return NULL; + } + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // get the OpenJPEG stream + opj_stream_t *d_stream = fio->stream; + + // set decoding parameters to default values + opj_set_default_decoder_parameters(¶meters); + + try { + // decode the JPEG-2000 codestream + + // get a decoder handle + d_codec = opj_create_decompress(OPJ_CODEC_J2K); + + // configure the event callbacks + // catch events using our callbacks (no local context needed here) + opj_set_info_handler(d_codec, NULL, NULL); + opj_set_warning_handler(d_codec, j2k_warning_callback, NULL); + opj_set_error_handler(d_codec, j2k_error_callback, NULL); + + // setup the decoder decoding parameters using user parameters + if( !opj_setup_decoder(d_codec, ¶meters) ) { + throw "Failed to setup the decoder\n"; + } + + // read the main header of the codestream and if necessary the JP2 boxes + if( !opj_read_header(d_stream, d_codec, &image)) { + throw "Failed to read the header\n"; + } + + // --- header only mode + + if (header_only) { + // create output image + dib = J2KImageToFIBITMAP(s_format_id, image, header_only); + if(!dib) throw "Failed to import JPEG2000 image"; + // clean-up and return header data + opj_destroy_codec(d_codec); + opj_image_destroy(image); + return dib; + } + + // decode the stream and fill the image structure + if( !( opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream) ) ) { + throw "Failed to decode image!\n"; + } + + // free the codec context + opj_destroy_codec(d_codec); + d_codec = NULL; + + // create output image + dib = J2KImageToFIBITMAP(s_format_id, image, header_only); + if(!dib) throw "Failed to import JPEG2000 image"; + + // free image data structure + opj_image_destroy(image); + + return dib; + + } catch (const char *text) { + if(dib) FreeImage_Unload(dib); + // free remaining structures + opj_destroy_codec(d_codec); + opj_image_destroy(image); + + 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) { + J2KFIO_t *fio = (J2KFIO_t*)data; + if (dib && handle && fio) { + BOOL bSuccess; + opj_codec_t *c_codec = NULL; // handle to a compressor + opj_cparameters_t parameters; // compression parameters + opj_image_t *image = NULL; // image to encode + + // get the OpenJPEG stream + opj_stream_t *c_stream = fio->stream; + + // set encoding parameters to default values + opj_set_default_encoder_parameters(¶meters); + + try { + parameters.numresolution = 1; + // check the resolution (i.e. parameters.numresolution) + int min_size = MIN(FreeImage_GetWidth(dib), FreeImage_GetHeight(dib)); + if(min_size < (1 << parameters.numresolution)) { + throw "Invalid image size - image is too small"; + } + + 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; + + // 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 + c_codec = opj_create_compress(OPJ_CODEC_J2K); + + // configure the event callbacks + // catch events using our callbacks (no local context needed here) + opj_set_info_handler(c_codec, NULL, NULL); + opj_set_warning_handler(c_codec, j2k_warning_callback, NULL); + opj_set_error_handler(c_codec, j2k_error_callback, NULL); + + // setup the encoder parameters using the current image and using user parameters + opj_setup_encoder(c_codec, ¶meters, image); + + // encode the image + bSuccess = opj_start_compress(c_codec, image, c_stream); + if(bSuccess) { + bSuccess = bSuccess && opj_encode(c_codec, c_stream); + if(bSuccess) { + bSuccess = bSuccess && opj_end_compress(c_codec, c_stream); + } + } + if (!bSuccess) { + throw "Failed to encode image"; + } + + // free remaining compression structures + opj_destroy_codec(c_codec); + + // free image data + opj_image_destroy(image); + + return TRUE; + + } catch (const char *text) { + if(c_codec) opj_destroy_codec(c_codec); + 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/AdvaImg/src/FreeImage/PluginJP2.cpp b/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp index 261697fb5c..edf5b396c3 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginJP2.cpp @@ -1,339 +1,327 @@ -// ==========================================================
-// 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;
-}
+// ========================================================== +// 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" +#include "J2KHelper.h" + +// ========================================================== +// Plugin Interface +// ========================================================== + +static int s_format_id; + +// ========================================================== +// 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) { + // create the stream wrapper + J2KFIO_t *fio = opj_freeimage_stream_create(io, handle, read); + return fio; +} + +static void DLL_CALLCONV +Close(FreeImageIO *io, fi_handle handle, void *data) { + // destroy the stream wrapper + J2KFIO_t *fio = (J2KFIO_t*)data; + opj_freeimage_stream_destroy(fio); +} + +// ---------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + J2KFIO_t *fio = (J2KFIO_t*)data; + if (handle && fio) { + opj_codec_t *d_codec = NULL; // handle to a decompressor + opj_dparameters_t parameters; // decompression parameters + opj_image_t *image = NULL; // decoded image + + FIBITMAP *dib = NULL; + + // check the file format + if(!Validate(io, handle)) { + return NULL; + } + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // get the OpenJPEG stream + opj_stream_t *d_stream = fio->stream; + + // set decoding parameters to default values + opj_set_default_decoder_parameters(¶meters); + + try { + // decode the JPEG-2000 file + + // get a decoder handle + d_codec = opj_create_decompress(OPJ_CODEC_JP2); + + // configure the event callbacks + // catch events using our callbacks (no local context needed here) + opj_set_info_handler(d_codec, NULL, NULL); + opj_set_warning_handler(d_codec, jp2_warning_callback, NULL); + opj_set_error_handler(d_codec, jp2_error_callback, NULL); + + // setup the decoder decoding parameters using user parameters + if( !opj_setup_decoder(d_codec, ¶meters) ) { + throw "Failed to setup the decoder\n"; + } + + // read the main header of the codestream and if necessary the JP2 boxes + if( !opj_read_header(d_stream, d_codec, &image)) { + throw "Failed to read the header\n"; + } + + // --- header only mode + + if (header_only) { + // create output image + dib = J2KImageToFIBITMAP(s_format_id, image, header_only); + if(!dib) throw "Failed to import JPEG2000 image"; + // clean-up and return header data + opj_destroy_codec(d_codec); + opj_image_destroy(image); + return dib; + } + + // decode the stream and fill the image structure + if( !( opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream) ) ) { + throw "Failed to decode image!\n"; + } + + // free the codec context + opj_destroy_codec(d_codec); + d_codec = NULL; + + // create output image + dib = J2KImageToFIBITMAP(s_format_id, image, header_only); + if(!dib) throw "Failed to import JPEG2000 image"; + + // free image data structure + opj_image_destroy(image); + + return dib; + + } catch (const char *text) { + if(dib) FreeImage_Unload(dib); + // free remaining structures + opj_destroy_codec(d_codec); + opj_image_destroy(image); + + 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) { + J2KFIO_t *fio = (J2KFIO_t*)data; + if (dib && handle && fio) { + BOOL bSuccess; + opj_codec_t *c_codec = NULL; // handle to a compressor + opj_cparameters_t parameters; // compression parameters + opj_image_t *image = NULL; // image to encode + + // get the OpenJPEG stream + opj_stream_t *c_stream = fio->stream; + + // set encoding parameters to default values + opj_set_default_encoder_parameters(¶meters); + + try { + parameters.numresolution = 1; + // check the resolution (i.e. parameters.numresolution) + int min_size = MIN(FreeImage_GetWidth(dib), FreeImage_GetHeight(dib)); + if(min_size < (1 << parameters.numresolution)) { + throw "Invalid image size - image is too small"; + } + + 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; + + // 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 JP2 compressor handle + c_codec = opj_create_compress(OPJ_CODEC_JP2); + + // configure the event callbacks + // catch events using our callbacks (no local context needed here) + opj_set_info_handler(c_codec, NULL, NULL); + opj_set_warning_handler(c_codec, jp2_warning_callback, NULL); + opj_set_error_handler(c_codec, jp2_error_callback, NULL); + + // setup the encoder parameters using the current image and using user parameters + opj_setup_encoder(c_codec, ¶meters, image); + + // encode the image + bSuccess = opj_start_compress(c_codec, image, c_stream); + if(bSuccess) { + bSuccess = bSuccess && opj_encode(c_codec, c_stream); + if(bSuccess) { + bSuccess = bSuccess && opj_end_compress(c_codec, c_stream); + } + } + if (!bSuccess) { + throw "Failed to encode image"; + } + + // free remaining compression structures + opj_destroy_codec(c_codec); + + // free image data + opj_image_destroy(image); + + return TRUE; + + } catch (const char *text) { + if(c_codec) opj_destroy_codec(c_codec); + 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/AdvaImg/src/FreeImage/PluginJPEG.cpp b/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp index 1e0237d115..c1b45e6347 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginJPEG.cpp @@ -656,46 +656,6 @@ jpeg_read_xmp_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) } /** - 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 @@ -976,14 +936,14 @@ jpeg_write_exif_profile_raw(j_compress_ptr cinfo, FIBITMAP *dib) { 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 TRUE; } return FALSE; @@ -1126,66 +1086,6 @@ store_size_info(FIBITMAP *dib, JDIMENSION width, JDIMENSION height) { } } -// ------------------------------------------------------------ -// 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 // ========================================================== @@ -1473,7 +1373,7 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { // check for automatic Exif rotation if(!header_only && ((flags & JPEG_EXIFROTATE) == JPEG_EXIFROTATE)) { - rotate_exif(&dib); + RotateExif(&dib); } // everything went well. return the loaded dib diff --git a/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp b/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp new file mode 100644 index 0000000000..f5e4878c1d --- /dev/null +++ b/plugins/AdvaImg/src/FreeImage/PluginJXR.cpp @@ -0,0 +1,1309 @@ +// ========================================================== +// JPEG XR Loader & Writer +// +// 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" +#include "../Metadata/FreeImageTag.h" + +#include "../LibJXR/jxrgluelib/JXRGlue.h" + +// ========================================================== +// Plugin Interface +// ========================================================== + +static int s_format_id; + +// ========================================================== +// FreeImageIO interface (I/O streaming functions) +// ========================================================== + +/** +JXR wrapper for FreeImage I/O handle +*/ +typedef struct tagFreeImageJXRIO { + FreeImageIO *io; + fi_handle handle; +} FreeImageJXRIO; + +static ERR +_jxr_io_Read(WMPStream* pWS, void* pv, size_t cb) { + FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; + return (fio->io->read_proc(pv, (unsigned)cb, 1, fio->handle) == 1) ? WMP_errSuccess : WMP_errFileIO; +} + +static ERR +_jxr_io_Write(WMPStream* pWS, const void* pv, size_t cb) { + FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; + if(0 != cb) { + return (fio->io->write_proc((void*)pv, (unsigned)cb, 1, fio->handle) == 1) ? WMP_errSuccess : WMP_errFileIO; + } + return WMP_errFileIO; +} + +static ERR +_jxr_io_SetPos(WMPStream* pWS, size_t offPos) { + FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; + return (fio->io->seek_proc(fio->handle, (long)offPos, SEEK_SET) == 0) ? WMP_errSuccess : WMP_errFileIO; +} + +static ERR +_jxr_io_GetPos(WMPStream* pWS, size_t* poffPos) { + FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; + long lOff = fio->io->tell_proc(fio->handle); + if(lOff == -1) { + return WMP_errFileIO; + } + *poffPos = (size_t)lOff; + return WMP_errSuccess; +} + +static Bool +_jxr_io_EOS(WMPStream* pWS) { + FreeImageJXRIO *fio = (FreeImageJXRIO*)pWS->state.pvObj; + long currentPos = fio->io->tell_proc(fio->handle); + fio->io->seek_proc(fio->handle, 0, SEEK_END); + long fileRemaining = fio->io->tell_proc(fio->handle) - currentPos; + fio->io->seek_proc(fio->handle, currentPos, SEEK_SET); + return (fileRemaining > 0); +} + +static ERR +_jxr_io_Close(WMPStream** ppWS) { + WMPStream *pWS = *ppWS; + // HACK : we use fMem to avoid a stream destruction by the library + // because FreeImage MUST HAVE the ownership of the stream + // see _jxr_io_Create + if(pWS && pWS->fMem) { + free(pWS); + *ppWS = NULL; + } + return WMP_errSuccess; +} + +static ERR +_jxr_io_Create(WMPStream **ppWS, FreeImageJXRIO *jxr_io) { + *ppWS = (WMPStream*)calloc(1, sizeof(**ppWS)); + if(*ppWS) { + WMPStream *pWS = *ppWS; + + pWS->state.pvObj = jxr_io; + pWS->Close = _jxr_io_Close; + pWS->EOS = _jxr_io_EOS; + pWS->Read = _jxr_io_Read; + pWS->Write = _jxr_io_Write; + pWS->SetPos = _jxr_io_SetPos; + pWS->GetPos = _jxr_io_GetPos; + + // HACK : we use fMem to avoid a stream destruction by the library + // because FreeImage MUST HAVE the ownership of the stream + // see _jxr_io_Close + pWS->fMem = FALSE; + + return WMP_errSuccess; + } + return WMP_errOutOfMemory; +} + +// ========================================================== +// JPEG XR Error handling +// ========================================================== + +static const char* +JXR_ErrorMessage(const int error) { + switch(error) { + case WMP_errNotYetImplemented: + case WMP_errAbstractMethod: + return "Not yet implemented"; + case WMP_errOutOfMemory: + return "Out of memory"; + case WMP_errFileIO: + return "File I/O error"; + case WMP_errBufferOverflow: + return "Buffer overflow"; + case WMP_errInvalidParameter: + return "Invalid parameter"; + case WMP_errInvalidArgument: + return "Invalid argument"; + case WMP_errUnsupportedFormat: + return "Unsupported format"; + case WMP_errIncorrectCodecVersion: + return "Incorrect codec version"; + case WMP_errIndexNotFound: + return "Format converter: Index not found"; + case WMP_errOutOfSequence: + return "Metadata: Out of sequence"; + case WMP_errMustBeMultipleOf16LinesUntilLastCall: + return "Must be multiple of 16 lines until last call"; + case WMP_errPlanarAlphaBandedEncRequiresTempFile: + return "Planar alpha banded encoder requires temp files"; + case WMP_errAlphaModeCannotBeTranscoded: + return "Alpha mode cannot be transcoded"; + case WMP_errIncorrectCodecSubVersion: + return "Incorrect codec subversion"; + case WMP_errFail: + case WMP_errNotInitialized: + default: + return "Invalid instruction - please contact the FreeImage team"; + } + + return NULL; +} + +// ========================================================== +// Helper functions & macro +// ========================================================== + +#define JXR_CHECK(error_code) \ + if(error_code < 0) { \ + const char *error_message = JXR_ErrorMessage(error_code); \ + throw error_message; \ + } + +// -------------------------------------------------------------------------- + +/** +Input conversions natively understood by FreeImage +@see GetNativePixelFormat +*/ +typedef struct tagJXRInputConversion { + BITDEPTH_BITS bdBitDepth; + U32 cbitUnit; + FREE_IMAGE_TYPE image_type; + unsigned red_mask; + unsigned green_mask; + unsigned blue_mask; +} JXRInputConversion; + +/** +Conversion table for native FreeImage formats +@see GetNativePixelFormat +*/ +static JXRInputConversion s_FreeImagePixelInfo[] = { + // 1-bit bitmap + { BD_1, 1, FIT_BITMAP, 0, 0, 0 }, + // 8-, 24-, 32-bit bitmap + { BD_8, 8, FIT_BITMAP, 0, 0, 0 }, + { BD_8, 24, FIT_BITMAP, 0, 0, 0 }, + { BD_8, 32, FIT_BITMAP, 0, 0, 0 }, + // 16-bit RGB 565 + { BD_565, 16, FIT_BITMAP, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK }, + // 16-bit RGB 555 + { BD_5, 16, FIT_BITMAP, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK }, + // 16-bit greyscale, RGB16, RGBA16 bitmap + { BD_16, 16, FIT_UINT16, 0, 0, 0 }, + { BD_16, 48, FIT_RGB16, 0, 0, 0 }, + { BD_16, 64, FIT_RGBA16, 0, 0, 0 }, + // 32-bit float, RGBF, RGBAF bitmap + { BD_32F, 32, FIT_FLOAT, 0, 0, 0 }, + { BD_32F, 96, FIT_RGBF, 0, 0, 0 }, + { BD_32F, 128, FIT_RGBAF, 0, 0, 0 } +}; + +/** +Scan input pixelInfo specifications and return the equivalent FreeImage info for loading +@param pixelInfo Image specifications +@param out_guid_format (returned value) output pixel format +@param image_type (returned value) Image type +@param bpp (returned value) Image bit depth +@param red_mask (returned value) RGB mask +@param green_mask (returned value) RGB mask +@param blue_mask (returned value) RGB mask +@return Returns WMP_errSuccess if successful, returns WMP_errFail otherwise +@see GetInputPixelFormat +*/ +static ERR +GetNativePixelFormat(const PKPixelInfo *pixelInfo, PKPixelFormatGUID *out_guid_format, FREE_IMAGE_TYPE *image_type, unsigned *bpp, unsigned *red_mask, unsigned *green_mask, unsigned *blue_mask) { + const unsigned s_FreeImagePixelInfoSize = (unsigned)sizeof(s_FreeImagePixelInfo) / sizeof(*(s_FreeImagePixelInfo)); + + for(unsigned i = 0; i < s_FreeImagePixelInfoSize; i++) { + if(pixelInfo->bdBitDepth == s_FreeImagePixelInfo[i].bdBitDepth) { + if(pixelInfo->cbitUnit == s_FreeImagePixelInfo[i].cbitUnit) { + // found ! now get dst image format specifications + memcpy(out_guid_format, pixelInfo->pGUIDPixFmt, sizeof(PKPixelFormatGUID)); + *image_type = s_FreeImagePixelInfo[i].image_type; + *bpp = s_FreeImagePixelInfo[i].cbitUnit; + *red_mask = s_FreeImagePixelInfo[i].red_mask; + *green_mask = s_FreeImagePixelInfo[i].green_mask; + *blue_mask = s_FreeImagePixelInfo[i].blue_mask; + return WMP_errSuccess; + } + } + } + + // not found : need pixel format conversion + return WMP_errFail; +} + +/** +Scan input file guid format and return the equivalent FreeImage info & target guid format for loading +@param pDecoder Decoder handle +@param guid_format (returned value) Output pixel format +@param image_type (returned value) Image type +@param bpp (returned value) Image bit depth +@param red_mask (returned value) RGB mask +@param green_mask (returned value) RGB mask +@param blue_mask (returned value) RGB mask +@return Returns TRUE if successful, returns FALSE otherwise +*/ +static ERR +GetInputPixelFormat(PKImageDecode *pDecoder, PKPixelFormatGUID *guid_format, FREE_IMAGE_TYPE *image_type, unsigned *bpp, unsigned *red_mask, unsigned *green_mask, unsigned *blue_mask) { + ERR error_code = 0; // error code as returned by the interface + PKPixelInfo pixelInfo; // image specifications + + try { + // get input file pixel format ... + PKPixelFormatGUID pguidSourcePF; + error_code = pDecoder->GetPixelFormat(pDecoder, &pguidSourcePF); + JXR_CHECK(error_code); + pixelInfo.pGUIDPixFmt = &pguidSourcePF; + // ... check for a supported format and get the format specifications + error_code = PixelFormatLookup(&pixelInfo, LOOKUP_FORWARD); + JXR_CHECK(error_code); + + // search for an equivalent native FreeImage format + error_code = GetNativePixelFormat(&pixelInfo, guid_format, image_type, bpp, red_mask, green_mask, blue_mask); + + if(error_code != WMP_errSuccess) { + // try to find a suitable conversion function ... + const PKPixelFormatGUID *ppguidTargetPF = NULL; // target pixel format + unsigned iIndex = 0; // first available conversion function + do { + error_code = PKFormatConverter_EnumConversions(&pguidSourcePF, iIndex, &ppguidTargetPF); + if(error_code == WMP_errSuccess) { + // found a conversion function, is the converted format a native FreeImage format ? + pixelInfo.pGUIDPixFmt = ppguidTargetPF; + error_code = PixelFormatLookup(&pixelInfo, LOOKUP_FORWARD); + JXR_CHECK(error_code); + error_code = GetNativePixelFormat(&pixelInfo, guid_format, image_type, bpp, red_mask, green_mask, blue_mask); + if(error_code == WMP_errSuccess) { + break; + } + } + // try next conversion function + iIndex++; + } while(error_code != WMP_errIndexNotFound); + + } + + return (error_code == WMP_errSuccess) ? WMP_errSuccess : WMP_errUnsupportedFormat; + + } catch(...) { + return error_code; + } +} + +// -------------------------------------------------------------------------- + +/** +Scan input dib format and return the equivalent PKPixelFormatGUID format for saving +@param dib Image to be saved +@param guid_format (returned value) GUID format +@param bHasAlpha (returned value) TRUE if an alpha layer is present +@return Returns TRUE if successful, returns FALSE otherwise +*/ +static ERR +GetOutputPixelFormat(FIBITMAP *dib, PKPixelFormatGUID *guid_format, BOOL *bHasAlpha) { + const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + const unsigned bpp = FreeImage_GetBPP(dib); + const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib); + + *guid_format = GUID_PKPixelFormatDontCare; + *bHasAlpha = FALSE; + + switch(image_type) { + case FIT_BITMAP: // standard image : 1-, 4-, 8-, 16-, 24-, 32-bit + switch(bpp) { + case 1: + // assume FIC_MINISBLACK + if(color_type == FIC_MINISBLACK) { + *guid_format = GUID_PKPixelFormatBlackWhite; + } + break; + case 8: + // assume FIC_MINISBLACK + if(color_type == FIC_MINISBLACK) { + *guid_format = GUID_PKPixelFormat8bppGray; + } + break; + case 16: + if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) { + *guid_format = GUID_PKPixelFormat16bppRGB565; + } else { + // includes case where all the masks are 0 + *guid_format = GUID_PKPixelFormat16bppRGB555; + } + break; +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + case 24: + *guid_format = GUID_PKPixelFormat24bppBGR; + break; + case 32: + *guid_format = GUID_PKPixelFormat32bppBGRA; + *bHasAlpha = TRUE; + break; +#elif FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB + case 24: + *guid_format = GUID_PKPixelFormat24bppRGB; + break; + case 32: + *guid_format = GUID_PKPixelFormat32bppRGBA; + *bHasAlpha = TRUE; + break; +#endif + case 4: + default: + // not supported + break; + } + break; + case FIT_UINT16: // array of unsigned short : unsigned 16-bit + *guid_format = GUID_PKPixelFormat16bppGray; + break; + case FIT_FLOAT: // array of float : 32-bit IEEE floating point + *guid_format = GUID_PKPixelFormat32bppGrayFloat; + break; + case FIT_RGB16: // 48-bit RGB image : 3 x 16-bit + *guid_format = GUID_PKPixelFormat48bppRGB; + break; + case FIT_RGBA16: // 64-bit RGBA image : 4 x 16-bit + *guid_format = GUID_PKPixelFormat64bppRGBA; + *bHasAlpha = TRUE; + break; + case FIT_RGBF: // 96-bit RGB float image : 3 x 32-bit IEEE floating point + *guid_format = GUID_PKPixelFormat96bppRGBFloat; + break; + case FIT_RGBAF: // 128-bit RGBA float image : 4 x 32-bit IEEE floating point + *guid_format = GUID_PKPixelFormat128bppRGBAFloat; + *bHasAlpha = TRUE; + break; + + case FIT_INT16: // array of short : signed 16-bit + case FIT_UINT32: // array of unsigned long : unsigned 32-bit + case FIT_INT32: // array of long : signed 32-bit + case FIT_DOUBLE: // array of double : 64-bit IEEE floating point + case FIT_COMPLEX: // array of FICOMPLEX : 2 x 64-bit IEEE floating point + + default: + // unsupported format + break; + } + + return (*guid_format != GUID_PKPixelFormatDontCare) ? WMP_errSuccess : WMP_errUnsupportedFormat; +} + +// ========================================================== +// Metadata loading & saving +// ========================================================== + +/** +Read a JPEG-XR IFD as a buffer +*/ +static ERR +ReadProfile(WMPStream* pStream, unsigned cbByteCount, unsigned uOffset, BYTE **ppbProfile) { + // (re-)allocate profile buffer + BYTE *pbProfile = *ppbProfile; + pbProfile = (BYTE*)realloc(pbProfile, cbByteCount); + if(!pbProfile) { + return WMP_errOutOfMemory; + } + // read the profile + if(WMP_errSuccess == pStream->SetPos(pStream, uOffset)) { + if(WMP_errSuccess == pStream->Read(pStream, pbProfile, cbByteCount)) { + *ppbProfile = pbProfile; + return WMP_errSuccess; + } + } + return WMP_errFileIO; +} + +/** +Convert a DPKPROPVARIANT to a FITAG, then store the tag as FIMD_EXIF_MAIN +*/ +static BOOL +ReadPropVariant(WORD tag_id, const DPKPROPVARIANT & varSrc, FIBITMAP *dib) { + DWORD dwSize; + + if(varSrc.vt == DPKVT_EMPTY) { + return FALSE; + } + + // get the tag key + TagLib& s = TagLib::instance(); + const char *key = s.getTagFieldName(TagLib::EXIF_MAIN, tag_id, NULL); + if(!key) { + return FALSE; + } + + // create a tag + FITAG *tag = FreeImage_CreateTag(); + if(tag) { + // set tag ID + FreeImage_SetTagID(tag, tag_id); + // set tag type, count, length and value + switch (varSrc.vt) { + case DPKVT_LPSTR: + FreeImage_SetTagType(tag, FIDT_ASCII); + dwSize = (DWORD)strlen(varSrc.VT.pszVal) + 1; + FreeImage_SetTagCount(tag, dwSize); + FreeImage_SetTagLength(tag, dwSize); + FreeImage_SetTagValue(tag, varSrc.VT.pszVal); + break; + + case DPKVT_LPWSTR: + FreeImage_SetTagType(tag, FIDT_UNDEFINED); + dwSize = (DWORD)(sizeof(U16) * (wcslen((wchar_t *) varSrc.VT.pwszVal) + 1)); // +1 for NULL term + FreeImage_SetTagCount(tag, dwSize / 2); + FreeImage_SetTagLength(tag, dwSize); + FreeImage_SetTagValue(tag, varSrc.VT.pwszVal); + break; + + case DPKVT_UI2: + FreeImage_SetTagType(tag, FIDT_SHORT); + FreeImage_SetTagCount(tag, 1); + FreeImage_SetTagLength(tag, 2); + FreeImage_SetTagValue(tag, &varSrc.VT.uiVal); + break; + + case DPKVT_UI4: + FreeImage_SetTagType(tag, FIDT_LONG); + FreeImage_SetTagCount(tag, 1); + FreeImage_SetTagLength(tag, 4); + FreeImage_SetTagValue(tag, &varSrc.VT.ulVal); + break; + + default: + assert(FALSE); // This case is not handled + break; + } + // get the tag desctiption + const char *description = s.getTagDescription(TagLib::EXIF_MAIN, tag_id); + FreeImage_SetTagDescription(tag, description); + + // store the tag + FreeImage_SetMetadata(FIMD_EXIF_MAIN, dib, key, tag); + + FreeImage_DeleteTag(tag); + } + return TRUE; +} + +/** +Read JPEG-XR descriptive metadata and store as EXIF_MAIN metadata +@see ReadPropVariant +*/ +static ERR +ReadDescriptiveMetadata(PKImageDecode *pID, FIBITMAP *dib) { + // get Exif TIFF metadata + const DESCRIPTIVEMETADATA *pDescMetadata = &pID->WMP.sDescMetadata; + // convert metadata to FITAG and store into the EXIF_MAIN metadata model + ReadPropVariant(WMP_tagImageDescription, pDescMetadata->pvarImageDescription, dib); + ReadPropVariant(WMP_tagCameraMake, pDescMetadata->pvarCameraMake, dib); + ReadPropVariant(WMP_tagCameraModel, pDescMetadata->pvarCameraModel, dib); + ReadPropVariant(WMP_tagSoftware, pDescMetadata->pvarSoftware, dib); + ReadPropVariant(WMP_tagDateTime, pDescMetadata->pvarDateTime, dib); + ReadPropVariant(WMP_tagArtist, pDescMetadata->pvarArtist, dib); + ReadPropVariant(WMP_tagCopyright, pDescMetadata->pvarCopyright, dib); + ReadPropVariant(WMP_tagRatingStars, pDescMetadata->pvarRatingStars, dib); + ReadPropVariant(WMP_tagRatingValue, pDescMetadata->pvarRatingValue, dib); + ReadPropVariant(WMP_tagCaption, pDescMetadata->pvarCaption, dib); + ReadPropVariant(WMP_tagDocumentName, pDescMetadata->pvarDocumentName, dib); + ReadPropVariant(WMP_tagPageName, pDescMetadata->pvarPageName, dib); + ReadPropVariant(WMP_tagPageNumber, pDescMetadata->pvarPageNumber, dib); + ReadPropVariant(WMP_tagHostComputer, pDescMetadata->pvarHostComputer, dib); + return WMP_errSuccess; +} + +/** +Read ICC, XMP, Exif, Exif-GPS, IPTC, descriptive (i.e. Exif-TIFF) metadata +*/ +static ERR +ReadMetadata(PKImageDecode *pID, FIBITMAP *dib) { + ERR error_code = 0; // error code as returned by the interface + size_t currentPos = 0; // current stream position + + WMPStream *pStream = pID->pStream; + WmpDEMisc *wmiDEMisc = &pID->WMP.wmiDEMisc; + BYTE *pbProfile = NULL; + + try { + // save current position + error_code = pStream->GetPos(pStream, ¤tPos); + JXR_CHECK(error_code); + + // ICC profile + if(0 != wmiDEMisc->uColorProfileByteCount) { + unsigned cbByteCount = wmiDEMisc->uColorProfileByteCount; + unsigned uOffset = wmiDEMisc->uColorProfileOffset; + error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); + JXR_CHECK(error_code); + FreeImage_CreateICCProfile(dib, pbProfile, cbByteCount); + } + + // XMP metadata + if(0 != wmiDEMisc->uXMPMetadataByteCount) { + unsigned cbByteCount = wmiDEMisc->uXMPMetadataByteCount; + unsigned uOffset = wmiDEMisc->uXMPMetadataOffset; + error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); + JXR_CHECK(error_code); + // store the tag as XMP + FITAG *tag = FreeImage_CreateTag(); + if(tag) { + FreeImage_SetTagLength(tag, cbByteCount); + FreeImage_SetTagCount(tag, cbByteCount); + FreeImage_SetTagType(tag, FIDT_ASCII); + FreeImage_SetTagValue(tag, pbProfile); + FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName); + FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag); + FreeImage_DeleteTag(tag); + } + } + + // IPTC metadata + if(0 != wmiDEMisc->uIPTCNAAMetadataByteCount) { + unsigned cbByteCount = wmiDEMisc->uIPTCNAAMetadataByteCount; + unsigned uOffset = wmiDEMisc->uIPTCNAAMetadataOffset; + error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); + JXR_CHECK(error_code); + // decode the IPTC profile + read_iptc_profile(dib, pbProfile, cbByteCount); + } + + // Exif metadata + if(0 != wmiDEMisc->uEXIFMetadataByteCount) { + unsigned cbByteCount = wmiDEMisc->uEXIFMetadataByteCount; + unsigned uOffset = wmiDEMisc->uEXIFMetadataOffset; + error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); + JXR_CHECK(error_code); + // decode the Exif profile + jpegxr_read_exif_profile(dib, pbProfile, cbByteCount); + } + + // Exif-GPS metadata + if(0 != wmiDEMisc->uGPSInfoMetadataByteCount) { + unsigned cbByteCount = wmiDEMisc->uGPSInfoMetadataByteCount; + unsigned uOffset = wmiDEMisc->uGPSInfoMetadataOffset; + error_code = ReadProfile(pStream, cbByteCount, uOffset, &pbProfile); + JXR_CHECK(error_code); + // decode the Exif-GPS profile + jpegxr_read_exif_gps_profile(dib, pbProfile, cbByteCount); + } + + // free profile buffer + free(pbProfile); + // restore initial position + error_code = pID->pStream->SetPos(pID->pStream, currentPos); + JXR_CHECK(error_code); + + // as a LAST STEP, read descriptive metadata + // these metadata overwrite possible identical Exif-TIFF metadata + // that could have been read inside the Exif IFD + + return ReadDescriptiveMetadata(pID, dib); + + } catch(...) { + // free profile buffer + free(pbProfile); + if(currentPos) { + // restore initial position + pStream->SetPos(pStream, currentPos); + } + return error_code; + } +} + +// ========================================================== +// Quantization tables (Y, U, V, YHP, UHP, VHP), +// optimized for PSNR +// ========================================================== + +static const int DPK_QPS_420[11][6] = { // for 8 bit only + { 66, 65, 70, 72, 72, 77 }, + { 59, 58, 63, 64, 63, 68 }, + { 52, 51, 57, 56, 56, 61 }, + { 48, 48, 54, 51, 50, 55 }, + { 43, 44, 48, 46, 46, 49 }, + { 37, 37, 42, 38, 38, 43 }, + { 26, 28, 31, 27, 28, 31 }, + { 16, 17, 22, 16, 17, 21 }, + { 10, 11, 13, 10, 10, 13 }, + { 5, 5, 6, 5, 5, 6 }, + { 2, 2, 3, 2, 2, 2 } +}; + +static const int DPK_QPS_8[12][6] = { + { 67, 79, 86, 72, 90, 98 }, + { 59, 74, 80, 64, 83, 89 }, + { 53, 68, 75, 57, 76, 83 }, + { 49, 64, 71, 53, 70, 77 }, + { 45, 60, 67, 48, 67, 74 }, + { 40, 56, 62, 42, 59, 66 }, + { 33, 49, 55, 35, 51, 58 }, + { 27, 44, 49, 28, 45, 50 }, + { 20, 36, 42, 20, 38, 44 }, + { 13, 27, 34, 13, 28, 34 }, + { 7, 17, 21, 8, 17, 21 }, // Photoshop 100% + { 2, 5, 6, 2, 5, 6 } +}; + +static const int DPK_QPS_16[11][6] = { + { 197, 203, 210, 202, 207, 213 }, + { 174, 188, 193, 180, 189, 196 }, + { 152, 167, 173, 156, 169, 174 }, + { 135, 152, 157, 137, 153, 158 }, + { 119, 137, 141, 119, 138, 142 }, + { 102, 120, 125, 100, 120, 124 }, + { 82, 98, 104, 79, 98, 103 }, + { 60, 76, 81, 58, 76, 81 }, + { 39, 52, 58, 36, 52, 58 }, + { 16, 27, 33, 14, 27, 33 }, + { 5, 8, 9, 4, 7, 8 } +}; + +static const int DPK_QPS_16f[11][6] = { + { 148, 177, 171, 165, 187, 191 }, + { 133, 155, 153, 147, 172, 181 }, + { 114, 133, 138, 130, 157, 167 }, + { 97, 118, 120, 109, 137, 144 }, + { 76, 98, 103, 85, 115, 121 }, + { 63, 86, 91, 62, 96, 99 }, + { 46, 68, 71, 43, 73, 75 }, + { 29, 48, 52, 27, 48, 51 }, + { 16, 30, 35, 14, 29, 34 }, + { 8, 14, 17, 7, 13, 17 }, + { 3, 5, 7, 3, 5, 6 } +}; + +static const int DPK_QPS_32f[11][6] = { + { 194, 206, 209, 204, 211, 217 }, + { 175, 187, 196, 186, 193, 205 }, + { 157, 170, 177, 167, 180, 190 }, + { 133, 152, 156, 144, 163, 168 }, + { 116, 138, 142, 117, 143, 148 }, + { 98, 120, 123, 96, 123, 126 }, + { 80, 99, 102, 78, 99, 102 }, + { 65, 79, 84, 63, 79, 84 }, + { 48, 61, 67, 45, 60, 66 }, + { 27, 41, 46, 24, 40, 45 }, + { 3, 22, 24, 2, 21, 22 } +}; + +// ========================================================== +// Plugin Implementation +// ========================================================== + +static const char * DLL_CALLCONV +Format() { + return "JPEG-XR"; +} + +static const char * DLL_CALLCONV +Description() { + return "JPEG XR image format"; +} + +static const char * DLL_CALLCONV +Extension() { + return "jxr,wdp,hdp"; +} + +static const char * DLL_CALLCONV +RegExpr() { + return NULL; +} + +static const char * DLL_CALLCONV +MimeType() { + return "image/vnd.ms-photo"; +} + +static BOOL DLL_CALLCONV +Validate(FreeImageIO *io, fi_handle handle) { + BYTE jxr_signature[3] = { 0x49, 0x49, 0xBC }; + BYTE signature[3] = { 0, 0, 0 }; + + io->read_proc(&signature, 1, 3, handle); + + return (memcmp(jxr_signature, signature, 3) == 0); +} + +static BOOL DLL_CALLCONV +SupportsExportDepth(int depth) { + return ( + (depth == 1) || + (depth == 8) || + (depth == 16) || + (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) || + (type == FIT_FLOAT) || + (type == FIT_RGBF) || + (type == FIT_RGBAF) + ); +} + +static BOOL DLL_CALLCONV +SupportsICCProfiles() { + return TRUE; +} + +static BOOL DLL_CALLCONV +SupportsNoPixels() { + return TRUE; +} + +// ========================================================== +// Open & Close +// ========================================================== + +static void * DLL_CALLCONV +Open(FreeImageIO *io, fi_handle handle, BOOL read) { + WMPStream *pStream = NULL; // stream interface + if(io && handle) { + // allocate the FreeImageIO stream wrapper + FreeImageJXRIO *jxr_io = (FreeImageJXRIO*)malloc(sizeof(FreeImageJXRIO)); + if(jxr_io) { + jxr_io->io = io; + jxr_io->handle = handle; + // create a JXR stream wrapper + if(_jxr_io_Create(&pStream, jxr_io) != WMP_errSuccess) { + free(jxr_io); + return NULL; + } + } + } + return pStream; +} + +static void DLL_CALLCONV +Close(FreeImageIO *io, fi_handle handle, void *data) { + WMPStream *pStream = (WMPStream*)data; + if(pStream) { + // free the FreeImageIO stream wrapper + FreeImageJXRIO *jxr_io = (FreeImageJXRIO*)pStream->state.pvObj; + free(jxr_io); + // free the JXR stream wrapper + pStream->fMem = TRUE; + _jxr_io_Close(&pStream); + } +} + +// ========================================================== +// Load +// ========================================================== + +/** +Set decoder parameters +@param pDecoder Decoder handle +@param flags FreeImage load flags +*/ +static void +SetDecoderParameters(PKImageDecode *pDecoder, int flags) { + // load image & alpha for formats with alpha + pDecoder->WMP.wmiSCP.uAlphaMode = 2; + // more options to come ... +} + +/** +Copy or convert & copy decoded pixels into the dib +@param pDecoder Decoder handle +@param out_guid_format Target guid format +@param dib Output dib +@param width Image width +@param height Image height +@return Returns 0 if successful, returns ERR otherwise +*/ +static ERR +CopyPixels(PKImageDecode *pDecoder, PKPixelFormatGUID out_guid_format, FIBITMAP *dib, int width, int height) { + PKFormatConverter *pConverter = NULL; // pixel format converter + ERR error_code = 0; // error code as returned by the interface + BYTE *pb = NULL; // local buffer used for pixel format conversion + + // image dimensions + const PKRect rect = {0, 0, width, height}; + + try { + // get input file pixel format ... + PKPixelFormatGUID in_guid_format; + error_code = pDecoder->GetPixelFormat(pDecoder, &in_guid_format); + JXR_CHECK(error_code); + + // is a format conversion needed ? + + if(IsEqualGUID(out_guid_format, in_guid_format)) { + // no conversion, load bytes "as is" ... + + // get a pointer to dst pixel data + BYTE *dib_bits = FreeImage_GetBits(dib); + + // get dst pitch (count of BYTE for stride) + const unsigned cbStride = FreeImage_GetPitch(dib); + + // decode and copy bits to dst array + error_code = pDecoder->Copy(pDecoder, &rect, dib_bits, cbStride); + JXR_CHECK(error_code); + } + else { + // we need to use the conversion API ... + + // allocate the pixel format converter + error_code = PKCodecFactory_CreateFormatConverter(&pConverter); + JXR_CHECK(error_code); + + // set the conversion function + error_code = pConverter->Initialize(pConverter, pDecoder, NULL, out_guid_format); + JXR_CHECK(error_code); + + // get the maximum stride + unsigned cbStride = 0; + { + PKPixelInfo pPIFrom; + PKPixelInfo pPITo; + + pPIFrom.pGUIDPixFmt = &in_guid_format; + error_code = PixelFormatLookup(&pPIFrom, LOOKUP_FORWARD); + JXR_CHECK(error_code); + + pPITo.pGUIDPixFmt = &out_guid_format; + error_code = PixelFormatLookup(&pPITo, LOOKUP_FORWARD); + JXR_CHECK(error_code); + + unsigned cbStrideFrom = ((pPIFrom.cbitUnit + 7) >> 3) * width; + unsigned cbStrideTo = ((pPITo.cbitUnit + 7) >> 3) * width; + cbStride = MAX(cbStrideFrom, cbStrideTo); + } + + // allocate a local decoder / encoder buffer + error_code = PKAllocAligned((void **) &pb, cbStride * height, 128); + JXR_CHECK(error_code); + + // copy / convert pixels + error_code = pConverter->Copy(pConverter, &rect, pb, cbStride); + JXR_CHECK(error_code); + + // now copy pixels into the dib + const size_t line_size = FreeImage_GetLine(dib); + for(int y = 0; y < height; y++) { + BYTE *src_bits = (BYTE*)(pb + y * cbStride); + BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, y); + memcpy(dst_bits, src_bits, line_size); + } + + // free the local buffer + PKFreeAligned((void **) &pb); + + // free the pixel format converter + PKFormatConverter_Release(&pConverter); + } + + // FreeImage DIB are upside-down relative to usual graphic conventions + FreeImage_FlipVertical(dib); + + // post-processing ... + // ------------------- + + // swap RGB as needed + +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + if(IsEqualGUID(out_guid_format, GUID_PKPixelFormat24bppRGB) || IsEqualGUID(out_guid_format, GUID_PKPixelFormat32bppRGB)) { + SwapRedBlue32(dib); + } +#elif FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB + if(IsEqualGUID(out_guid_format, GUID_PKPixelFormat24bppBGR) || IsEqualGUID(out_guid_format, GUID_PKPixelFormat32bppBGR)) { + SwapRedBlue32(dib); + } +#endif + + return WMP_errSuccess; + + } catch(...) { + // free the local buffer + PKFreeAligned((void **) &pb); + // free the pixel format converter + PKFormatConverter_Release(&pConverter); + + return error_code; + } +} + +// -------------------------------------------------------------------------- + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + PKImageDecode *pDecoder = NULL; // decoder interface + ERR error_code = 0; // error code as returned by the interface + PKPixelFormatGUID guid_format; // loaded pixel format (== input file pixel format if no conversion needed) + + FREE_IMAGE_TYPE image_type = FIT_UNKNOWN; // input image type + unsigned bpp = 0; // input image bit depth + FIBITMAP *dib = NULL; + + // get the I/O stream wrapper + WMPStream *pDecodeStream = (WMPStream*)data; + + if(!handle || !pDecodeStream) { + return NULL; + } + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + try { + int width, height; // image dimensions (in pixels) + + // create a JXR decoder interface and initialize function pointers with *_WMP functions + error_code = PKImageDecode_Create_WMP(&pDecoder); + JXR_CHECK(error_code); + + // attach the stream to the decoder ... + // ... then read the image container and the metadata + error_code = pDecoder->Initialize(pDecoder, pDecodeStream); + JXR_CHECK(error_code); + + // set decoder parameters + SetDecoderParameters(pDecoder, flags); + + // get dst image format specifications + unsigned red_mask = 0, green_mask = 0, blue_mask = 0; + error_code = GetInputPixelFormat(pDecoder, &guid_format, &image_type, &bpp, &red_mask, &green_mask, &blue_mask); + JXR_CHECK(error_code); + + // get image dimensions + pDecoder->GetSize(pDecoder, &width, &height); + + // allocate dst image + { + dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, bpp, red_mask, green_mask, blue_mask); + if(!dib) { + throw FI_MSG_ERROR_DIB_MEMORY; + } + if(FreeImage_GetBPP(dib) == 1) { + // BD_1 - build a FIC_MINISBLACK palette + 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; + } + } + + // get image resolution + { + float resX, resY; // image resolution (in dots per inch) + // convert from English units, i.e. dots per inch to universal units, i.e. dots per meter + pDecoder->GetResolution(pDecoder, &resX, &resY); + FreeImage_SetDotsPerMeterX(dib, (unsigned)(resX / 0.0254F + 0.5F)); + FreeImage_SetDotsPerMeterY(dib, (unsigned)(resY / 0.0254F + 0.5F)); + } + + // get metadata & ICC profile + error_code = ReadMetadata(pDecoder, dib); + JXR_CHECK(error_code); + + if(header_only) { + // header only mode ... + + // free the decoder + pDecoder->Release(&pDecoder); + assert(pDecoder == NULL); + + return dib; + } + + // copy pixels into the dib, perform pixel conversion if needed + error_code = CopyPixels(pDecoder, guid_format, dib, width, height); + JXR_CHECK(error_code); + + // free the decoder + pDecoder->Release(&pDecoder); + assert(pDecoder == NULL); + + return dib; + + } catch (const char *message) { + // unload the dib + FreeImage_Unload(dib); + // free the decoder + pDecoder->Release(&pDecoder); + + if(NULL != message) { + FreeImage_OutputMessageProc(s_format_id, message); + } + } + + return NULL; +} + +// ========================================================== +// Save +// ========================================================== + +/** +Configure compression parameters + +ImageQuality Q (BD==1) Q (BD==8) Q (BD==16) Q (BD==32F) Subsample Overlap +[0.0, 0.4] 8-IQ*5 (see table) (see table) (see table) 4:4:4 2 +(0.4, 0.8) 8-IQ*5 (see table) (see table) (see table) 4:4:4 1 +[0.8, 1.0) 8-IQ*5 (see table) (see table) (see table) 4:4:4 1 +[1.0, 1.0] 1 1 1 1 4:4:4 0 + +@param wmiSCP Encoder parameters +@param pixelInfo Image specifications +@param fltImageQuality Image output quality in [0..1), 1 means lossless +*/ +static void +SetCompression(CWMIStrCodecParam *wmiSCP, const PKPixelInfo *pixelInfo, float fltImageQuality) { + if(fltImageQuality < 1.0F) { + // overlap + if(fltImageQuality >= 0.5F) { + wmiSCP->olOverlap = OL_ONE; + } else { + wmiSCP->olOverlap = OL_TWO; + } + // chroma sub-sampling + if(fltImageQuality >= 0.5F || pixelInfo->uBitsPerSample > 8) { + wmiSCP->cfColorFormat = YUV_444; + } else { + wmiSCP->cfColorFormat = YUV_420; + } + + // bit depth + if(pixelInfo->bdBitDepth == BD_1) { + wmiSCP->uiDefaultQPIndex = (U8)(8 - 5.0F * fltImageQuality + 0.5F); + } + else { + // remap [0.8, 0.866, 0.933, 1.0] to [0.8, 0.9, 1.0, 1.1] + // to use 8-bit DPK QP table (0.933 == Photoshop JPEG 100) + if(fltImageQuality > 0.8F && pixelInfo->bdBitDepth == BD_8 && wmiSCP->cfColorFormat != YUV_420 && wmiSCP->cfColorFormat != YUV_422) { + fltImageQuality = 0.8F + (fltImageQuality - 0.8F) * 1.5F; + } + + const int qi = (int) (10.0F * fltImageQuality); + const float qf = 10.0F * fltImageQuality - (float)qi; + + const int *pQPs = + (wmiSCP->cfColorFormat == YUV_420 || wmiSCP->cfColorFormat == YUV_422) ? + DPK_QPS_420[qi] : + (pixelInfo->bdBitDepth == BD_8 ? DPK_QPS_8[qi] : + (pixelInfo->bdBitDepth == BD_16 ? DPK_QPS_16[qi] : + (pixelInfo->bdBitDepth == BD_16F ? DPK_QPS_16f[qi] : + DPK_QPS_32f[qi]))); + + wmiSCP->uiDefaultQPIndex = (U8) (0.5F + (float) pQPs[0] * (1.0F - qf) + (float) (pQPs + 6)[0] * qf); + wmiSCP->uiDefaultQPIndexU = (U8) (0.5F + (float) pQPs[1] * (1.0F - qf) + (float) (pQPs + 6)[1] * qf); + wmiSCP->uiDefaultQPIndexV = (U8) (0.5F + (float) pQPs[2] * (1.0F - qf) + (float) (pQPs + 6)[2] * qf); + wmiSCP->uiDefaultQPIndexYHP = (U8) (0.5F + (float) pQPs[3] * (1.0F - qf) + (float) (pQPs + 6)[3] * qf); + wmiSCP->uiDefaultQPIndexUHP = (U8) (0.5F + (float) pQPs[4] * (1.0F - qf) + (float) (pQPs + 6)[4] * qf); + wmiSCP->uiDefaultQPIndexVHP = (U8) (0.5F + (float) pQPs[5] * (1.0F - qf) + (float) (pQPs + 6)[5] * qf); + } + } // fltImageQuality < 1.0F + else { + // lossless mode + wmiSCP->uiDefaultQPIndex = 1; + } +} + +/** +Set encoder parameters +@param wmiSCP Encoder parameters +@param pixelInfo Image specifications +@param flags FreeImage save flags +@param bHasAlpha TRUE if an alpha layer is present +*/ +static void +SetEncoderParameters(CWMIStrCodecParam *wmiSCP, const PKPixelInfo *pixelInfo, int flags, BOOL bHasAlpha) { + float fltImageQuality = 1.0F; + + // all values have been set to zero by the API + // update default values for some attributes + wmiSCP->cfColorFormat = YUV_444; // color format + wmiSCP->bdBitDepth = BD_LONG; // internal bit depth + wmiSCP->bfBitstreamFormat = SPATIAL; // compressed image data in spatial order + wmiSCP->bProgressiveMode = FALSE; // sequential mode + wmiSCP->olOverlap = OL_ONE; // single level overlap processing + wmiSCP->cNumOfSliceMinus1H = 0; // # of horizontal slices + wmiSCP->cNumOfSliceMinus1V = 0; // # of vertical slices + wmiSCP->sbSubband = SB_ALL; // keep all subbands + wmiSCP->uAlphaMode = 0; // 0:no alpha 1: alpha only else: something + alpha + wmiSCP->uiDefaultQPIndex = 1; // quantization for grey or rgb layer(s), 1: lossless + wmiSCP->uiDefaultQPIndexAlpha = 1; // quantization for alpha layer, 1: lossless + + // process the flags + // ----------------- + + // progressive mode + if((flags & JXR_PROGRESSIVE) == JXR_PROGRESSIVE) { + // turn on progressive mode (instead of sequential mode) + wmiSCP->bProgressiveMode = TRUE; + } + + // quality in [0.01 - 1.0), 1.0 means lossless - default is 0.80 + int quality = flags & 0x7F; + if(quality == 0) { + // defaut to 0.80 + fltImageQuality = 0.8F; + } else if((flags & JXR_LOSSLESS) == JXR_LOSSLESS) { + fltImageQuality = 1.0F; + } else { + quality = (quality >= 100) ? 100 : quality; + fltImageQuality = quality / 100.0F; + } + SetCompression(wmiSCP, pixelInfo, fltImageQuality); + + // alpha compression + if(bHasAlpha) { + wmiSCP->uAlphaMode = 2; // encode with a planar alpha channel + } +} + +// -------------------------------------------------------------------------- + +static BOOL DLL_CALLCONV +Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) { + BOOL bIsFlipped = FALSE; // FreeImage DIB are upside-down relative to usual graphic conventions + PKPixelFormatGUID guid_format; // image format + PKPixelInfo pixelInfo; // image specifications + BOOL bHasAlpha = FALSE; // is alpha layer present ? + + PKImageEncode *pEncoder = NULL; // encoder interface + ERR error_code = 0; // error code as returned by the interface + + // get the I/O stream wrapper + WMPStream *pEncodeStream = (WMPStream*)data; + + if(!dib || !handle || !pEncodeStream) { + return FALSE; + } + + try { + // get image dimensions + unsigned width = FreeImage_GetWidth(dib); + unsigned height = FreeImage_GetHeight(dib); + + // check JPEG-XR limits + if((width < MB_WIDTH_PIXEL) || (height < MB_HEIGHT_PIXEL)) { + FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height); + throw (const char*)NULL; + } + + // get output pixel format + error_code = GetOutputPixelFormat(dib, &guid_format, &bHasAlpha); + JXR_CHECK(error_code); + pixelInfo.pGUIDPixFmt = &guid_format; + error_code = PixelFormatLookup(&pixelInfo, LOOKUP_FORWARD); + JXR_CHECK(error_code); + + // create a JXR encoder interface and initialize function pointers with *_WMP functions + error_code = PKImageEncode_Create_WMP(&pEncoder); + JXR_CHECK(error_code); + + // attach the stream to the encoder and set all encoder parameters to zero ... + error_code = pEncoder->Initialize(pEncoder, pEncodeStream, &pEncoder->WMP.wmiSCP, sizeof(CWMIStrCodecParam)); + JXR_CHECK(error_code); + + // ... then configure the encoder + SetEncoderParameters(&pEncoder->WMP.wmiSCP, &pixelInfo, flags, bHasAlpha); + + // set pixel format + pEncoder->SetPixelFormat(pEncoder, guid_format); + + // set image size + pEncoder->SetSize(pEncoder, width, height); + + // set resolution (convert from universal units to English units) + float resX = (float)(unsigned)(0.5F + 0.0254F * FreeImage_GetDotsPerMeterX(dib)); + float resY = (float)(unsigned)(0.5F + 0.0254F * FreeImage_GetDotsPerMeterY(dib)); + pEncoder->SetResolution(pEncoder, resX, resY); + + // write pixels + // -------------- + + // dib coordinates are upside-down relative to usual conventions + bIsFlipped = FreeImage_FlipVertical(dib); + + // get a pointer to dst pixel data + BYTE *dib_bits = FreeImage_GetBits(dib); + + // get dst pitch (count of BYTE for stride) + const unsigned cbStride = FreeImage_GetPitch(dib); + + // write pixels on output + error_code = pEncoder->WritePixels(pEncoder, height, dib_bits, cbStride); + JXR_CHECK(error_code); + + // recover dib coordinates + FreeImage_FlipVertical(dib); + + // free the encoder + pEncoder->Release(&pEncoder); + assert(pEncoder == NULL); + + return TRUE; + + } catch (const char *message) { + if(bIsFlipped) { + // recover dib coordinates + FreeImage_FlipVertical(dib); + } + if(pEncoder) { + // free the encoder + pEncoder->Release(&pEncoder); + assert(pEncoder == NULL); + } + if(NULL != message) { + FreeImage_OutputMessageProc(s_format_id, message); + } + } + + return FALSE; +} + +// ========================================================== +// Init +// ========================================================== + +void DLL_CALLCONV +InitJXR(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 = SupportsICCProfiles; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} + diff --git a/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp b/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp index 7a74fe5e81..f6b59e299b 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginPNG.cpp @@ -35,6 +35,8 @@ #define PNG_BYTES_TO_CHECK 8 +#undef PNG_Z_DEFAULT_COMPRESSION // already used in ../LibPNG/pnglibconf.h + // ---------------------------------------------------------- #include "zlib.h" diff --git a/plugins/AdvaImg/src/FreeImage/PluginSGI.cpp b/plugins/AdvaImg/src/FreeImage/PluginSGI.cpp index 0fd162b1d4..35fd2ec611 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginSGI.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginSGI.cpp @@ -178,7 +178,7 @@ Description() { static const char * DLL_CALLCONV Extension() { - return "sgi"; + return "sgi,rgb,rgba,bw"; } static const char * DLL_CALLCONV diff --git a/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp b/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp index 5fb1f53ee0..f12d7286ce 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginTARGA.cpp @@ -358,6 +358,7 @@ MimeType() { static BOOL isTARGA20(FreeImageIO *io, fi_handle handle) { const unsigned sizeofSig = 18; + BYTE signature[sizeofSig]; // 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 @@ -366,13 +367,10 @@ isTARGA20(FreeImageIO *io, fi_handle handle) { 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); + io->read_proc(&signature, 1, sizeofSig, handle); + // rewind + io->seek_proc(handle, start_offset, SEEK_SET); return (memcmp(tga_signature, signature, sizeofSig) == 0); } @@ -384,41 +382,61 @@ Validate(FreeImageIO *io, fi_handle handle) { } // 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); + { + const long start_offset = io->tell_proc(handle); + + // get the header + TGAHEADER header; + io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle); +#ifdef FREEIMAGE_BIGENDIAN + SwapHeader(&header); +#endif + // 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; + // the color map type should be a 0 or a 1... + if(header.color_map_type != 0 && header.color_map_type != 1) { + return FALSE; + } + // if the color map type is 1 then we validate the map entry information... + if(header.color_map_type > 0) { + // It doesn't make any sense if the first entry is larger than the color map table + if(header.cm_first_entry >= header.cm_length) { + return FALSE; } - break; - default: - bResult = FALSE; - break; + } + // check header.cm_size, don't allow 0 or anything bigger than 32 + if(header.cm_size == 0 || header.cm_size > 32) { + return FALSE; + } + // the width/height shouldn't be 0, right ? + if(header.is_width == 0 || header.is_height == 0) { + return FALSE; + } + // let's now verify all the types that are supported by FreeImage (this is our final verification) + 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: + return TRUE; + default: + return FALSE; + } + break; + default: + return FALSE; + } } - - return bResult; + + return FALSE; } static BOOL DLL_CALLCONV @@ -731,8 +749,12 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { // calculate the color map size csize = header.cm_length * header.cm_size / 8; + + // read the color map BYTE *cmap = (BYTE*)malloc(csize * sizeof(BYTE)); - + if (cmap == NULL) { + throw FI_MSG_ERROR_DIB_MEMORY; + } io->read_proc(cmap, sizeof(BYTE), csize, handle); // build the palette @@ -740,8 +762,10 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { switch (header.cm_size) { case 16: { WORD *rgb555 = (WORD*)&cmap[0]; + unsigned start = (unsigned)header.cm_first_entry; + unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length); - for (count = header.cm_first_entry; count < header.cm_length; count++) { + for (count = start; count < stop; 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); @@ -752,8 +776,10 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { case 24: { FILE_BGR *bgr = (FILE_BGR*)&cmap[0]; + unsigned start = (unsigned)header.cm_first_entry; + unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length); - for (count = header.cm_first_entry; count < header.cm_length; count++) { + for (count = start; count < stop; count++) { palette[count].rgbBlue = bgr->b; palette[count].rgbGreen = bgr->g; palette[count].rgbRed = bgr->r; @@ -769,8 +795,10 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { memset(trns, 0xFF, 256); FILE_BGRA *bgra = (FILE_BGRA*)&cmap[0]; + unsigned start = (unsigned)header.cm_first_entry; + unsigned stop = MIN((unsigned)256, (unsigned)header.cm_length); - for (count = header.cm_first_entry; count < header.cm_length; count++) { + for (count = start; count < stop; count++) { palette[count].rgbBlue = bgra->b; palette[count].rgbGreen = bgra->g; palette[count].rgbRed = bgra->r; diff --git a/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp b/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp index 72218a2564..4e502c56e8 100644 --- a/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp +++ b/plugins/AdvaImg/src/FreeImage/PluginTIFF.cpp @@ -193,9 +193,6 @@ 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, @@ -1894,6 +1891,7 @@ Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { if(buf == NULL) { throw FI_MSG_ERROR_MEMORY; } + memset(buf, 0, TIFFStripSize(tif) * sizeof(BYTE)); BOOL bThrowMessage = FALSE; @@ -2622,6 +2620,10 @@ void DLL_CALLCONV InitTIFF(Plugin *plugin, int format_id) { s_format_id = format_id; + // Set up the callback for extended TIFF directory tag support (see XTIFF.cpp) + // Must be called before using libtiff + XTIFFInitialize(); + plugin->format_proc = Format; plugin->description_proc = Description; plugin->extension_proc = Extension; diff --git a/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp b/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp new file mode 100644 index 0000000000..9fb0b69447 --- /dev/null +++ b/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp @@ -0,0 +1,698 @@ +// ========================================================== +// Google WebP Loader & Writer +// +// 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" + +#include "../Metadata/FreeImageTag.h" + +#include "../LibWebP/src/webp/decode.h" +#include "../LibWebP/src/webp/encode.h" +#include "../LibWebP/src/enc/vp8enci.h" +#include "../LibWebP/src/webp/mux.h" + +// ========================================================== +// Plugin Interface +// ========================================================== + +static int s_format_id; + +// ---------------------------------------------------------- +// Helpers for the load function +// ---------------------------------------------------------- + +/** +Read the whole file into memory +*/ +static BOOL +ReadFileToWebPData(FreeImageIO *io, fi_handle handle, WebPData * const bitstream) { + uint8_t *raw_data = NULL; + + try { + // Read the input file and put it in memory + long start_pos = io->tell_proc(handle); + io->seek_proc(handle, 0, SEEK_END); + size_t file_length = (size_t)(io->tell_proc(handle) - start_pos); + io->seek_proc(handle, start_pos, SEEK_SET); + raw_data = (uint8_t*)malloc(file_length * sizeof(uint8_t)); + if(!raw_data) { + throw FI_MSG_ERROR_MEMORY; + } + if(io->read_proc(raw_data, 1, (unsigned)file_length, handle) != file_length) { + throw "Error while reading input stream"; + } + + // copy pointers (must be released later using free) + bitstream->bytes = raw_data; + bitstream->size = file_length; + + return TRUE; + + } catch(const char *text) { + if(raw_data) { + free(raw_data); + } + memset(bitstream, 0, sizeof(WebPData)); + if(NULL != text) { + FreeImage_OutputMessageProc(s_format_id, text); + } + return FALSE; + } +} + +// ---------------------------------------------------------- +// Helpers for the save function +// ---------------------------------------------------------- + +/** +Output function. Should return 1 if writing was successful. +data/data_size is the segment of data to write, and 'picture' is for +reference (and so one can make use of picture->custom_ptr). +*/ +static int +WebP_MemoryWriter(const BYTE *data, size_t data_size, const WebPPicture* const picture) { + FIMEMORY *hmem = (FIMEMORY*)picture->custom_ptr; + return data_size ? (FreeImage_WriteMemory(data, 1, (unsigned)data_size, hmem) == data_size) : 0; +} + +// ========================================================== +// Plugin Implementation +// ========================================================== + +static const char * DLL_CALLCONV +Format() { + return "WebP"; +} + +static const char * DLL_CALLCONV +Description() { + return "Google WebP image format"; +} + +static const char * DLL_CALLCONV +Extension() { + return "webp"; +} + +static const char * DLL_CALLCONV +RegExpr() { + return NULL; +} + +static const char * DLL_CALLCONV +MimeType() { + return "image/webp"; +} + +static BOOL DLL_CALLCONV +Validate(FreeImageIO *io, fi_handle handle) { + BYTE riff_signature[4] = { 0x52, 0x49, 0x46, 0x46 }; + BYTE webp_signature[4] = { 0x57, 0x45, 0x42, 0x50 }; + BYTE signature[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + io->read_proc(signature, 1, 12, handle); + + if(memcmp(riff_signature, signature, 4) == 0) { + if(memcmp(webp_signature, signature + 8, 4) == 0) { + return TRUE; + } + } + + return FALSE; +} + +static BOOL DLL_CALLCONV +SupportsExportDepth(int depth) { + return ( + (depth == 24) || + (depth == 32) + ); +} + +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 void * DLL_CALLCONV +Open(FreeImageIO *io, fi_handle handle, BOOL read) { + WebPMux *mux = NULL; + int copy_data = 1; // 1 : copy data into the mux, 0 : keep a link to local data + + if(read) { + // create the MUX object from the input stream + WebPData bitstream; + // read the input file and put it in memory + if(!ReadFileToWebPData(io, handle, &bitstream)) { + return NULL; + } + // create the MUX object + mux = WebPMuxCreate(&bitstream, copy_data); + // no longer needed since copy_data == 1 + free((void*)bitstream.bytes); + if(mux == NULL) { + FreeImage_OutputMessageProc(s_format_id, "Failed to create mux object from file"); + return NULL; + } + } else { + // creates an empty mux object + mux = WebPMuxNew(); + if(mux == NULL) { + FreeImage_OutputMessageProc(s_format_id, "Failed to create empty mux object"); + return NULL; + } + } + + return mux; +} + +static void DLL_CALLCONV +Close(FreeImageIO *io, fi_handle handle, void *data) { + WebPMux *mux = (WebPMux*)data; + if(mux != NULL) { + // free the MUX object + WebPMuxDelete(mux); + } +} + +// ---------------------------------------------------------- + +/** +Decode a WebP image and returns a FIBITMAP image +@param webp_image Raw WebP image +@param flags FreeImage load flags +@return Returns a dib if successfull, returns NULL otherwise +*/ +static FIBITMAP * +DecodeImage(WebPData *webp_image, int flags) { + FIBITMAP *dib = NULL; + + const uint8_t* data = webp_image->bytes; // raw image data + const size_t data_size = webp_image->size; // raw image size + + VP8StatusCode webp_status = VP8_STATUS_OK; + + BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; + + // Main object storing the configuration for advanced decoding + WebPDecoderConfig decoder_config; + // Output buffer + WebPDecBuffer* const output_buffer = &decoder_config.output; + // Features gathered from the bitstream + WebPBitstreamFeatures* const bitstream = &decoder_config.input; + + try { + // Initialize the configuration as empty + // This function must always be called first, unless WebPGetFeatures() is to be called + if(!WebPInitDecoderConfig(&decoder_config)) { + throw "Library version mismatch"; + } + + // Retrieve features from the bitstream + // The bitstream structure is filled with information gathered from the bitstream + webp_status = WebPGetFeatures(data, data_size, bitstream); + if(webp_status != VP8_STATUS_OK) { + throw FI_MSG_ERROR_PARSING; + } + + // Allocate output dib + + unsigned bpp = bitstream->has_alpha ? 32 : 24; + unsigned width = (unsigned)bitstream->width; + unsigned height = (unsigned)bitstream->height; + + 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) { + WebPFreeDecBuffer(output_buffer); + return dib; + } + + // --- Set decoding options --- + + // use multi-threaded decoding + decoder_config.options.use_threads = 1; + // set output color space + output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR; + + // --- + + // decode the input stream, taking 'config' into account. + + webp_status = WebPDecode(data, data_size, &decoder_config); + if(webp_status != VP8_STATUS_OK) { + throw FI_MSG_ERROR_PARSING; + } + + // fill the dib with the decoded data + + const BYTE *src_bitmap = output_buffer->u.RGBA.rgba; + const unsigned src_pitch = (unsigned)output_buffer->u.RGBA.stride; + + switch(bpp) { + case 24: + for(unsigned y = 0; y < height; y++) { + const BYTE *src_bits = src_bitmap + y * src_pitch; + BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, height-1-y); + for(unsigned x = 0; x < width; x++) { + dst_bits[FI_RGBA_BLUE] = src_bits[0]; // B + dst_bits[FI_RGBA_GREEN] = src_bits[1]; // G + dst_bits[FI_RGBA_RED] = src_bits[2]; // R + src_bits += 3; + dst_bits += 3; + } + } + break; + case 32: + for(unsigned y = 0; y < height; y++) { + const BYTE *src_bits = src_bitmap + y * src_pitch; + BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, height-1-y); + for(unsigned x = 0; x < width; x++) { + dst_bits[FI_RGBA_BLUE] = src_bits[0]; // B + dst_bits[FI_RGBA_GREEN] = src_bits[1]; // G + dst_bits[FI_RGBA_RED] = src_bits[2]; // R + dst_bits[FI_RGBA_ALPHA] = src_bits[3]; // A + src_bits += 4; + dst_bits += 4; + } + } + break; + } + + // Free the decoder + WebPFreeDecBuffer(output_buffer); + + return dib; + + } catch (const char *text) { + if(dib) { + FreeImage_Unload(dib); + } + WebPFreeDecBuffer(output_buffer); + + if(NULL != text) { + FreeImage_OutputMessageProc(s_format_id, text); + } + + return NULL; + } +} + +static FIBITMAP * DLL_CALLCONV +Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { + WebPMux *mux = NULL; + WebPMuxFrameInfo webp_frame = { 0 }; // raw image + WebPData color_profile; // ICC raw data + WebPData xmp_metadata; // XMP raw data + WebPData exif_metadata; // EXIF raw data + FIBITMAP *dib = NULL; + WebPMuxError error_status; + + if(!handle) { + return NULL; + } + + try { + // get the MUX object + mux = (WebPMux*)data; + if(!mux) { + throw (1); + } + + // gets the feature flags from the mux object + uint32_t webp_flags = 0; + error_status = WebPMuxGetFeatures(mux, &webp_flags); + if(error_status != WEBP_MUX_OK) { + throw (1); + } + + // get image data + error_status = WebPMuxGetFrame(mux, 1, &webp_frame); + + if(error_status == WEBP_MUX_OK) { + // decode the data (can be limited to the header if flags uses FIF_LOAD_NOPIXELS) + dib = DecodeImage(&webp_frame.bitstream, flags); + if(!dib) { + throw (1); + } + + // get ICC profile + if(webp_flags & ICCP_FLAG) { + error_status = WebPMuxGetChunk(mux, "ICCP", &color_profile); + if(error_status == WEBP_MUX_OK) { + FreeImage_CreateICCProfile(dib, (void*)color_profile.bytes, (long)color_profile.size); + } + } + + // get XMP metadata + if(webp_flags & XMP_FLAG) { + error_status = WebPMuxGetChunk(mux, "XMP ", &xmp_metadata); + if(error_status == WEBP_MUX_OK) { + // create a tag + FITAG *tag = FreeImage_CreateTag(); + if(tag) { + FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName); + FreeImage_SetTagLength(tag, (DWORD)xmp_metadata.size); + FreeImage_SetTagCount(tag, (DWORD)xmp_metadata.size); + FreeImage_SetTagType(tag, FIDT_ASCII); + FreeImage_SetTagValue(tag, xmp_metadata.bytes); + + // store the tag + FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag); + + // destroy the tag + FreeImage_DeleteTag(tag); + } + } + } + + // get Exif metadata + if(webp_flags & EXIF_FLAG) { + error_status = WebPMuxGetChunk(mux, "EXIF", &exif_metadata); + if(error_status == WEBP_MUX_OK) { + // read the Exif raw data as a blob + jpeg_read_exif_profile_raw(dib, exif_metadata.bytes, (unsigned)exif_metadata.size); + // read and decode the Exif data + jpeg_read_exif_profile(dib, exif_metadata.bytes, (unsigned)exif_metadata.size); + } + } + } + + WebPDataClear(&webp_frame.bitstream); + + return dib; + + } catch(int) { + WebPDataClear(&webp_frame.bitstream); + return NULL; + } +} + +// -------------------------------------------------------------------------- + +/** +Encode a FIBITMAP to a WebP image +@param hmem Memory output stream, containing on return the encoded image +@param dib The FIBITMAP to encode +@param flags FreeImage save flags +@return Returns TRUE if successfull, returns FALSE otherwise +*/ +static BOOL +EncodeImage(FIMEMORY *hmem, FIBITMAP *dib, int flags) { + WebPPicture picture; // Input buffer + WebPConfig config; // Coding parameters + + BOOL bIsFlipped = FALSE; + + try { + const unsigned width = FreeImage_GetWidth(dib); + const unsigned height = FreeImage_GetHeight(dib); + const unsigned bpp = FreeImage_GetBPP(dib); + const unsigned pitch = FreeImage_GetPitch(dib); + + // check image type + FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); + + if( !((image_type == FIT_BITMAP) && ((bpp == 24) || (bpp == 32))) ) { + throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; + } + + // check format limits + if(MAX(width, height) > WEBP_MAX_DIMENSION) { + FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height); + return FALSE; + } + + // Initialize output I/O + if(WebPPictureInit(&picture) == 1) { + picture.writer = WebP_MemoryWriter; + picture.custom_ptr = hmem; + picture.width = (int)width; + picture.height = (int)height; + } else { + throw "Couldn't initialize WebPPicture"; + } + + // --- Set encoding parameters --- + + // Initialize encoding parameters to default values + WebPConfigInit(&config); + + // quality/speed trade-off (0=fast, 6=slower-better) + config.method = 6; + + if((flags & WEBP_LOSSLESS) == WEBP_LOSSLESS) { + // lossless encoding + config.lossless = 1; + picture.use_argb = 1; + } else if((flags & 0x7F) > 0) { + // lossy encoding + config.lossless = 0; + // quality is between 1 (smallest file) and 100 (biggest) - default to 75 + config.quality = (float)(flags & 0x7F); + if(config.quality > 100) { + config.quality = 100; + } + } + + // validate encoding parameters + if(WebPValidateConfig(&config) == 0) { + throw "Failed to initialize encoder"; + } + + // --- Perform encoding --- + + // Invert dib scanlines + bIsFlipped = FreeImage_FlipVertical(dib); + + + // convert dib buffer to output stream + + const BYTE *bits = FreeImage_GetBits(dib); + +#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + switch(bpp) { + case 24: + WebPPictureImportBGR(&picture, bits, pitch); + break; + case 32: + WebPPictureImportBGRA(&picture, bits, pitch); + break; + } +#else + switch(bpp) { + case 24: + WebPPictureImportRGB(&picture, bits, pitch); + break; + case 32: + WebPPictureImportRGBA(&picture, bits, pitch); + break; + } + +#endif // FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR + + if(!WebPEncode(&config, &picture)) { + throw "Failed to encode image"; + } + + WebPPictureFree(&picture); + + if(bIsFlipped) { + // invert dib scanlines + FreeImage_FlipVertical(dib); + } + + return TRUE; + + } catch (const char* text) { + + WebPPictureFree(&picture); + + if(bIsFlipped) { + // invert dib scanlines + FreeImage_FlipVertical(dib); + } + + if(NULL != 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) { + WebPMux *mux = NULL; + FIMEMORY *hmem = NULL; + WebPData webp_image; + WebPData output_data = { 0 }; + WebPMuxError error_status; + + int copy_data = 1; // 1 : copy data into the mux, 0 : keep a link to local data + + if(!dib || !handle || !data) { + return FALSE; + } + + try { + + // get the MUX object + mux = (WebPMux*)data; + if(!mux) { + return FALSE; + } + + // --- prepare image data --- + + // encode image as a WebP blob + hmem = FreeImage_OpenMemory(); + if(!hmem || !EncodeImage(hmem, dib, flags)) { + throw (1); + } + // store the blob into the mux + BYTE *data = NULL; + DWORD data_size = 0; + FreeImage_AcquireMemory(hmem, &data, &data_size); + webp_image.bytes = data; + webp_image.size = data_size; + error_status = WebPMuxSetImage(mux, &webp_image, copy_data); + // no longer needed since copy_data == 1 + FreeImage_CloseMemory(hmem); + hmem = NULL; + if(error_status != WEBP_MUX_OK) { + throw (1); + } + + // --- set metadata --- + + // set ICC color profile + { + FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib); + if (iccProfile->size && iccProfile->data) { + WebPData icc_profile; + icc_profile.bytes = (uint8_t*)iccProfile->data; + icc_profile.size = (size_t)iccProfile->size; + error_status = WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data); + if(error_status != WEBP_MUX_OK) { + throw (1); + } + } + } + + // set XMP metadata + { + FITAG *tag = NULL; + if(FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag)) { + WebPData xmp_profile; + xmp_profile.bytes = (uint8_t*)FreeImage_GetTagValue(tag); + xmp_profile.size = (size_t)FreeImage_GetTagLength(tag); + error_status = WebPMuxSetChunk(mux, "XMP ", &xmp_profile, copy_data); + if(error_status != WEBP_MUX_OK) { + throw (1); + } + } + } + + // set Exif metadata + { + FITAG *tag = NULL; + if(FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag)) { + WebPData exif_profile; + exif_profile.bytes = (uint8_t*)FreeImage_GetTagValue(tag); + exif_profile.size = (size_t)FreeImage_GetTagLength(tag); + error_status = WebPMuxSetChunk(mux, "EXIF", &exif_profile, copy_data); + if(error_status != WEBP_MUX_OK) { + throw (1); + } + } + } + + // get data from mux in WebP RIFF format + error_status = WebPMuxAssemble(mux, &output_data); + if(error_status != WEBP_MUX_OK) { + FreeImage_OutputMessageProc(s_format_id, "Failed to create webp output file"); + throw (1); + } + + // write the file to the output stream + if(io->write_proc((void*)output_data.bytes, 1, (unsigned)output_data.size, handle) != output_data.size) { + FreeImage_OutputMessageProc(s_format_id, "Failed to write webp output file"); + throw (1); + } + + // free WebP output file + WebPDataClear(&output_data); + + return TRUE; + + } catch(int) { + if(hmem) { + FreeImage_CloseMemory(hmem); + } + + WebPDataClear(&output_data); + + return FALSE; + } +} + +// ========================================================== +// Init +// ========================================================== + +void DLL_CALLCONV +InitWEBP(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 = SupportsICCProfiles; + plugin->supports_no_pixels_proc = SupportsNoPixels; +} + diff --git a/plugins/AdvaImg/src/FreeImage/tmoColorConvert.cpp b/plugins/AdvaImg/src/FreeImage/tmoColorConvert.cpp index 66869b2806..6b103a08c1 100644 --- a/plugins/AdvaImg/src/FreeImage/tmoColorConvert.cpp +++ b/plugins/AdvaImg/src/FreeImage/tmoColorConvert.cpp @@ -1,479 +1,479 @@ -// ==========================================================
-// High Dynamic Range bitmap conversion routines
-//
-// Design and implementation by
-// - Hervé Drolon (drolon@infonie.fr)
-// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#include "FreeImage.h"
-#include "Utilities.h"
-#include "ToneMapping.h"
-
-// ----------------------------------------------------------
-// Convert RGB to and from Yxy, same as in Reinhard et al. SIGGRAPH 2002
-// References :
-// [1] Radiance Home Page [Online] http://radsite.lbl.gov/radiance/HOME.html
-// [2] E. Reinhard, M. Stark, P. Shirley, and J. Ferwerda,
-// Photographic Tone Reproduction for Digital Images, ACM Transactions on Graphics,
-// 21(3):267-276, 2002 (Proceedings of SIGGRAPH 2002).
-// [3] J. Tumblin and H.E. Rushmeier,
-// Tone Reproduction for Realistic Images. IEEE Computer Graphics and Applications,
-// 13(6):42-48, 1993.
-// ----------------------------------------------------------
-
-/**
-nominal CRT primaries
-*/
-/*
-static const float CIE_x_r = 0.640F;
-static const float CIE_y_r = 0.330F;
-static const float CIE_x_g = 0.290F;
-static const float CIE_y_g = 0.600F;
-static const float CIE_x_b = 0.150F;
-static const float CIE_y_b = 0.060F;
-static const float CIE_x_w = 0.3333F; // use true white
-static const float CIE_y_w = 0.3333F;
-*/
-/**
-sRGB primaries
-*/
-static const float CIE_x_r = 0.640F;
-static const float CIE_y_r = 0.330F;
-static const float CIE_x_g = 0.300F;
-static const float CIE_y_g = 0.600F;
-static const float CIE_x_b = 0.150F;
-static const float CIE_y_b = 0.060F;
-static const float CIE_x_w = 0.3127F; // Illuminant D65
-static const float CIE_y_w = 0.3290F;
-
-static const float CIE_D = ( CIE_x_r*(CIE_y_g - CIE_y_b) + CIE_x_g*(CIE_y_b - CIE_y_r) + CIE_x_b*(CIE_y_r - CIE_y_g) );
-static const float CIE_C_rD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_g - CIE_y_b) - CIE_y_w*(CIE_x_g - CIE_x_b) + CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g) );
-static const float CIE_C_gD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_b - CIE_y_r) - CIE_y_w*(CIE_x_b - CIE_x_r) - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r) );
-static const float CIE_C_bD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_r - CIE_y_g) - CIE_y_w*(CIE_x_r - CIE_x_g) + CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r) );
-
-/**
-RGB to XYZ (no white balance)
-*/
-static const float RGB2XYZ[3][3] = {
- { CIE_x_r*CIE_C_rD / CIE_D,
- CIE_x_g*CIE_C_gD / CIE_D,
- CIE_x_b*CIE_C_bD / CIE_D
- },
- { CIE_y_r*CIE_C_rD / CIE_D,
- CIE_y_g*CIE_C_gD / CIE_D,
- CIE_y_b*CIE_C_bD / CIE_D
- },
- { (1 - CIE_x_r-CIE_y_r)*CIE_C_rD / CIE_D,
- (1 - CIE_x_g-CIE_y_g)*CIE_C_gD / CIE_D,
- (1 - CIE_x_b-CIE_y_b)*CIE_C_bD / CIE_D
- }
-};
-
-/**
-XYZ to RGB (no white balance)
-*/
-static const float XYZ2RGB[3][3] = {
- {(CIE_y_g - CIE_y_b - CIE_x_b*CIE_y_g + CIE_y_b*CIE_x_g) / CIE_C_rD,
- (CIE_x_b - CIE_x_g - CIE_x_b*CIE_y_g + CIE_x_g*CIE_y_b) / CIE_C_rD,
- (CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g) / CIE_C_rD
- },
- {(CIE_y_b - CIE_y_r - CIE_y_b*CIE_x_r + CIE_y_r*CIE_x_b) / CIE_C_gD,
- (CIE_x_r - CIE_x_b - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r) / CIE_C_gD,
- (CIE_x_b*CIE_y_r - CIE_x_r*CIE_y_b) / CIE_C_gD
- },
- {(CIE_y_r - CIE_y_g - CIE_y_r*CIE_x_g + CIE_y_g*CIE_x_r) / CIE_C_bD,
- (CIE_x_g - CIE_x_r - CIE_x_g*CIE_y_r + CIE_x_r*CIE_y_g) / CIE_C_bD,
- (CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r) / CIE_C_bD
- }
-};
-
-/**
-This gives approximately the following matrices :
-
-static const float RGB2XYZ[3][3] = {
- { 0.41239083F, 0.35758433F, 0.18048081F },
- { 0.21263903F, 0.71516865F, 0.072192319F },
- { 0.019330820F, 0.11919473F, 0.95053220F }
-};
-static const float XYZ2RGB[3][3] = {
- { 3.2409699F, -1.5373832F, -0.49861079F },
- { -0.96924376F, 1.8759676F, 0.041555084F },
- { 0.055630036F, -0.20397687F, 1.0569715F }
-};
-*/
-
-// ----------------------------------------------------------
-
-static const float EPSILON = 1e-06F;
-static const float INF = 1e+10F;
-
-/**
-Convert in-place floating point RGB data to Yxy.<br>
-On output, pixel->red == Y, pixel->green == x, pixel->blue == y
-@param dib Input RGBF / Output Yxy image
-@return Returns TRUE if successful, returns FALSE otherwise
-*/
-BOOL
-ConvertInPlaceRGBFToYxy(FIBITMAP *dib) {
- float result[3];
-
- if(FreeImage_GetImageType(dib) != FIT_RGBF)
- return FALSE;
-
- 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.<br>
-On input, pixel->red == Y, pixel->green == x, pixel->blue == y
-@param dib Input Yxy / Output RGBF image
-@return Returns TRUE if successful, returns FALSE otherwise
-*/
-BOOL
-ConvertInPlaceYxyToRGBF(FIBITMAP *dib) {
- float result[3];
- float X, Y, Z;
-
- if(FreeImage_GetImageType(dib) != FIT_RGBF)
- return FALSE;
-
- 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.<br>
-On input, pixel->red == Y, pixel->green == x, pixel->blue == y
-@param Yxy Source Yxy image to analyze
-@param maxLum Maximum luminance
-@param minLum Minimum luminance
-@param worldLum Average luminance (world adaptation luminance)
-@return Returns TRUE if successful, returns FALSE otherwise
-*/
-BOOL
-LuminanceFromYxy(FIBITMAP *Yxy, float *maxLum, float *minLum, float *worldLum) {
- if(FreeImage_GetImageType(Yxy) != FIT_RGBF)
- return FALSE;
-
- 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<float> vY(width * height);
-
- BYTE *bits = (BYTE*)FreeImage_GetBits(Y);
- for(y = 0; y < height; y++) {
- float *pixel = (float*)bits;
- for(x = 0; x < width; x++) {
- if(pixel[x] != 0) {
- vY.push_back(pixel[x]);
- }
- }
- bits += pitch;
- }
-
- std::sort(vY.begin(), vY.end());
-
- *minLum = vY.at( int(minPrct * vY.size()) );
- *maxLum = vY.at( int(maxPrct * vY.size()) );
-}
-
-/**
-Clipping function<br>
-Remove any extremely bright and/or extremely dark pixels
-and normalize between 0 and 1.
-@param Y Input/Output image
-@param minPrct Minimum percentile
-@param maxPrct Maximum percentile
-*/
-void
-NormalizeY(FIBITMAP *Y, float minPrct, float maxPrct) {
- int x, y;
- float maxLum, minLum;
-
- if(minPrct > maxPrct) {
- // swap values
- float t = minPrct; minPrct = maxPrct; maxPrct = t;
- }
- if(minPrct < 0) minPrct = 0;
- if(maxPrct > 1) maxPrct = 1;
-
- int width = FreeImage_GetWidth(Y);
- int height = FreeImage_GetHeight(Y);
- int pitch = FreeImage_GetPitch(Y);
-
- // find max & min luminance values
- if((minPrct > 0) || (maxPrct < 1)) {
- maxLum = 0, minLum = 0;
- findMaxMinPercentile(Y, minPrct, &minLum, maxPrct, &maxLum);
- } else {
- maxLum = -1e20F, minLum = 1e20F;
- BYTE *bits = (BYTE*)FreeImage_GetBits(Y);
- for(y = 0; y < height; y++) {
- const float *pixel = (float*)bits;
- for(x = 0; x < width; x++) {
- const float value = pixel[x];
- maxLum = (maxLum < value) ? value : maxLum; // max Luminance in the scene
- minLum = (minLum < value) ? minLum : value; // min Luminance in the scene
- }
- // next line
- bits += pitch;
- }
- }
- if(maxLum == minLum) return;
-
- // normalize to range 0..1
- const float divider = maxLum - minLum;
- BYTE *bits = (BYTE*)FreeImage_GetBits(Y);
- for(y = 0; y < height; y++) {
- float *pixel = (float*)bits;
- for(x = 0; x < width; x++) {
- pixel[x] = (pixel[x] - minLum) / divider;
- if(pixel[x] <= 0) pixel[x] = EPSILON;
- if(pixel[x] > 1) pixel[x] = 1;
- }
- // next line
- bits += pitch;
- }
-}
+// ========================================================== +// High Dynamic Range bitmap conversion routines +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// - Mihail Naydenov (mnaydenov@users.sourceforge.net) +// +// This file is part of FreeImage 3 +// +// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY +// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES +// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE +// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED +// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT +// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY +// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL +// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER +// THIS DISCLAIMER. +// +// Use at your own risk! +// ========================================================== + +#include "FreeImage.h" +#include "Utilities.h" +#include "ToneMapping.h" + +// ---------------------------------------------------------- +// Convert RGB to and from Yxy, same as in Reinhard et al. SIGGRAPH 2002 +// References : +// [1] Radiance Home Page [Online] http://radsite.lbl.gov/radiance/HOME.html +// [2] E. Reinhard, M. Stark, P. Shirley, and J. Ferwerda, +// Photographic Tone Reproduction for Digital Images, ACM Transactions on Graphics, +// 21(3):267-276, 2002 (Proceedings of SIGGRAPH 2002). +// [3] J. Tumblin and H.E. Rushmeier, +// Tone Reproduction for Realistic Images. IEEE Computer Graphics and Applications, +// 13(6):42-48, 1993. +// ---------------------------------------------------------- + +/** +nominal CRT primaries +*/ +/* +static const float CIE_x_r = 0.640F; +static const float CIE_y_r = 0.330F; +static const float CIE_x_g = 0.290F; +static const float CIE_y_g = 0.600F; +static const float CIE_x_b = 0.150F; +static const float CIE_y_b = 0.060F; +static const float CIE_x_w = 0.3333F; // use true white +static const float CIE_y_w = 0.3333F; +*/ +/** +sRGB primaries +*/ +static const float CIE_x_r = 0.640F; +static const float CIE_y_r = 0.330F; +static const float CIE_x_g = 0.300F; +static const float CIE_y_g = 0.600F; +static const float CIE_x_b = 0.150F; +static const float CIE_y_b = 0.060F; +static const float CIE_x_w = 0.3127F; // Illuminant D65 +static const float CIE_y_w = 0.3290F; + +static const float CIE_D = ( CIE_x_r*(CIE_y_g - CIE_y_b) + CIE_x_g*(CIE_y_b - CIE_y_r) + CIE_x_b*(CIE_y_r - CIE_y_g) ); +static const float CIE_C_rD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_g - CIE_y_b) - CIE_y_w*(CIE_x_g - CIE_x_b) + CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g) ); +static const float CIE_C_gD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_b - CIE_y_r) - CIE_y_w*(CIE_x_b - CIE_x_r) - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r) ); +static const float CIE_C_bD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_r - CIE_y_g) - CIE_y_w*(CIE_x_r - CIE_x_g) + CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r) ); + +/** +RGB to XYZ (no white balance) +*/ +static const float RGB2XYZ[3][3] = { + { CIE_x_r*CIE_C_rD / CIE_D, + CIE_x_g*CIE_C_gD / CIE_D, + CIE_x_b*CIE_C_bD / CIE_D + }, + { CIE_y_r*CIE_C_rD / CIE_D, + CIE_y_g*CIE_C_gD / CIE_D, + CIE_y_b*CIE_C_bD / CIE_D + }, + { (1 - CIE_x_r-CIE_y_r)*CIE_C_rD / CIE_D, + (1 - CIE_x_g-CIE_y_g)*CIE_C_gD / CIE_D, + (1 - CIE_x_b-CIE_y_b)*CIE_C_bD / CIE_D + } +}; + +/** +XYZ to RGB (no white balance) +*/ +static const float XYZ2RGB[3][3] = { + {(CIE_y_g - CIE_y_b - CIE_x_b*CIE_y_g + CIE_y_b*CIE_x_g) / CIE_C_rD, + (CIE_x_b - CIE_x_g - CIE_x_b*CIE_y_g + CIE_x_g*CIE_y_b) / CIE_C_rD, + (CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g) / CIE_C_rD + }, + {(CIE_y_b - CIE_y_r - CIE_y_b*CIE_x_r + CIE_y_r*CIE_x_b) / CIE_C_gD, + (CIE_x_r - CIE_x_b - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r) / CIE_C_gD, + (CIE_x_b*CIE_y_r - CIE_x_r*CIE_y_b) / CIE_C_gD + }, + {(CIE_y_r - CIE_y_g - CIE_y_r*CIE_x_g + CIE_y_g*CIE_x_r) / CIE_C_bD, + (CIE_x_g - CIE_x_r - CIE_x_g*CIE_y_r + CIE_x_r*CIE_y_g) / CIE_C_bD, + (CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r) / CIE_C_bD + } +}; + +/** +This gives approximately the following matrices : + +static const float RGB2XYZ[3][3] = { + { 0.41239083F, 0.35758433F, 0.18048081F }, + { 0.21263903F, 0.71516865F, 0.072192319F }, + { 0.019330820F, 0.11919473F, 0.95053220F } +}; +static const float XYZ2RGB[3][3] = { + { 3.2409699F, -1.5373832F, -0.49861079F }, + { -0.96924376F, 1.8759676F, 0.041555084F }, + { 0.055630036F, -0.20397687F, 1.0569715F } +}; +*/ + +// ---------------------------------------------------------- + +static const float EPSILON = 1e-06F; +static const float INF = 1e+10F; + +/** +Convert in-place floating point RGB data to Yxy.<br> +On output, pixel->red == Y, pixel->green == x, pixel->blue == y +@param dib Input RGBF / Output Yxy image +@return Returns TRUE if successful, returns FALSE otherwise +*/ +BOOL +ConvertInPlaceRGBFToYxy(FIBITMAP *dib) { + float result[3]; + + if(FreeImage_GetImageType(dib) != FIT_RGBF) + return FALSE; + + 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.<br> +On input, pixel->red == Y, pixel->green == x, pixel->blue == y +@param dib Input Yxy / Output RGBF image +@return Returns TRUE if successful, returns FALSE otherwise +*/ +BOOL +ConvertInPlaceYxyToRGBF(FIBITMAP *dib) { + float result[3]; + float X, Y, Z; + + if(FreeImage_GetImageType(dib) != FIT_RGBF) + return FALSE; + + 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.<br> +On input, pixel->red == Y, pixel->green == x, pixel->blue == y +@param Yxy Source Yxy image to analyze +@param maxLum Maximum luminance +@param minLum Minimum luminance +@param worldLum Average luminance (world adaptation luminance) +@return Returns TRUE if successful, returns FALSE otherwise +*/ +BOOL +LuminanceFromYxy(FIBITMAP *Yxy, float *maxLum, float *minLum, float *worldLum) { + if(FreeImage_GetImageType(Yxy) != FIT_RGBF) + return FALSE; + + 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 = MAX(0.0F, pixel[x].red);// avoid negative values + 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<float> vY(width * height); + + BYTE *bits = (BYTE*)FreeImage_GetBits(Y); + for(y = 0; y < height; y++) { + float *pixel = (float*)bits; + for(x = 0; x < width; x++) { + if(pixel[x] != 0) { + vY.push_back(pixel[x]); + } + } + bits += pitch; + } + + std::sort(vY.begin(), vY.end()); + + *minLum = vY.at( int(minPrct * vY.size()) ); + *maxLum = vY.at( int(maxPrct * vY.size()) ); +} + +/** +Clipping function<br> +Remove any extremely bright and/or extremely dark pixels +and normalize between 0 and 1. +@param Y Input/Output image +@param minPrct Minimum percentile +@param maxPrct Maximum percentile +*/ +void +NormalizeY(FIBITMAP *Y, float minPrct, float maxPrct) { + int x, y; + float maxLum, minLum; + + if(minPrct > maxPrct) { + // swap values + float t = minPrct; minPrct = maxPrct; maxPrct = t; + } + if(minPrct < 0) minPrct = 0; + if(maxPrct > 1) maxPrct = 1; + + int width = FreeImage_GetWidth(Y); + int height = FreeImage_GetHeight(Y); + int pitch = FreeImage_GetPitch(Y); + + // find max & min luminance values + if((minPrct > 0) || (maxPrct < 1)) { + maxLum = 0, minLum = 0; + findMaxMinPercentile(Y, minPrct, &minLum, maxPrct, &maxLum); + } else { + maxLum = -1e20F, minLum = 1e20F; + BYTE *bits = (BYTE*)FreeImage_GetBits(Y); + for(y = 0; y < height; y++) { + const float *pixel = (float*)bits; + for(x = 0; x < width; x++) { + const float value = pixel[x]; + maxLum = (maxLum < value) ? value : maxLum; // max Luminance in the scene + minLum = (minLum < value) ? minLum : value; // min Luminance in the scene + } + // next line + bits += pitch; + } + } + if(maxLum == minLum) return; + + // normalize to range 0..1 + const float divider = maxLum - minLum; + BYTE *bits = (BYTE*)FreeImage_GetBits(Y); + for(y = 0; y < height; y++) { + float *pixel = (float*)bits; + for(x = 0; x < width; x++) { + pixel[x] = (pixel[x] - minLum) / divider; + if(pixel[x] <= 0) pixel[x] = EPSILON; + if(pixel[x] > 1) pixel[x] = 1; + } + // next line + bits += pitch; + } +} diff --git a/plugins/AdvaImg/src/FreeImage/tmoDrago03.cpp b/plugins/AdvaImg/src/FreeImage/tmoDrago03.cpp index a61534474d..d46a8c8426 100644 --- a/plugins/AdvaImg/src/FreeImage/tmoDrago03.cpp +++ b/plugins/AdvaImg/src/FreeImage/tmoDrago03.cpp @@ -1,295 +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;
-}
+// ========================================================== +// 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/AdvaImg/src/FreeImage/tmoFattal02.cpp b/plugins/AdvaImg/src/FreeImage/tmoFattal02.cpp index 88f054412a..c63f91f762 100644 --- a/plugins/AdvaImg/src/FreeImage/tmoFattal02.cpp +++ b/plugins/AdvaImg/src/FreeImage/tmoFattal02.cpp @@ -1,689 +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 y = 0; y < height; y++) {
- 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 = y*pitch + x;
- divg[index] = gx[index] + gy[index];
- if(x > 0) divg[index] -= gx[index-1];
- if(y > 0) divg[index] -= gy[index-pitch];
- }
- }
-
- // no longer needed ...
- FreeImage_Unload(Gx);
- FreeImage_Unload(Gy);
-
- // return the divergence
- return divG;
-
- } catch(int) {
- if(Gx) FreeImage_Unload(Gx);
- if(Gy) FreeImage_Unload(Gy);
- if(divG) FreeImage_Unload(divG);
- return NULL;
- }
-}
-
-/**
-Given the luminance channel, find max & min luminance values,
-normalize to range 0..100 and take the logarithm.
-@param Y Image luminance
-@return Returns the normalized luminance H if successful, returns NULL otherwise
-*/
-static FIBITMAP* LogLuminance(FIBITMAP *Y) {
- 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 y = 0; y < height; y++) {
- 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;
- }
-}
+// ========================================================== +// 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 y = 0; y < height; y++) { + 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 = y*pitch + x; + divg[index] = gx[index] + gy[index]; + if(x > 0) divg[index] -= gx[index-1]; + if(y > 0) divg[index] -= gy[index-pitch]; + } + } + + // no longer needed ... + FreeImage_Unload(Gx); + FreeImage_Unload(Gy); + + // return the divergence + return divG; + + } catch(int) { + if(Gx) FreeImage_Unload(Gx); + if(Gy) FreeImage_Unload(Gy); + if(divG) FreeImage_Unload(divG); + return NULL; + } +} + +/** +Given the luminance channel, find max & min luminance values, +normalize to range 0..100 and take the logarithm. +@param Y Image luminance +@return Returns the normalized luminance H if successful, returns NULL otherwise +*/ +static FIBITMAP* LogLuminance(FIBITMAP *Y) { + 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 y = 0; y < height; y++) { + 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/AdvaImg/src/FreeImageToolkit/Background.cpp b/plugins/AdvaImg/src/FreeImageToolkit/Background.cpp index fc18667b21..08cdd4473b 100644 --- a/plugins/AdvaImg/src/FreeImageToolkit/Background.cpp +++ b/plugins/AdvaImg/src/FreeImageToolkit/Background.cpp @@ -251,7 +251,7 @@ FillBackgroundBitmap(FIBITMAP *dib, const RGBQUAD *color, int options) { // release, just assume to have an unicolor background and fill // all with an 'alpha-blended' color. if (color->rgbReserved < 255) { - + // If we will draw on an unicolor background, it's // faster to draw opaque with an alpha blended color. // So, first get the color from the first pixel in the @@ -259,7 +259,7 @@ FillBackgroundBitmap(FIBITMAP *dib, const RGBQUAD *color, int options) { RGBQUAD bgcolor; if (bpp == 8) { bgcolor = FreeImage_GetPalette(dib)[*src_bits]; - } else { + } else { bgcolor.rgbBlue = src_bits[FI_RGBA_BLUE]; bgcolor.rgbGreen = src_bits[FI_RGBA_GREEN]; bgcolor.rgbRed = src_bits[FI_RGBA_RED]; @@ -269,14 +269,14 @@ FillBackgroundBitmap(FIBITMAP *dib, const RGBQUAD *color, int options) { color_intl = &blend; } } - + int index = (bpp <= 8) ? GetPaletteIndex(dib, color_intl, options, &color_type) : 0; if (index == -1) { // No palette index found for a palletized // image. This should never happen... return FALSE; } - + // first, build the first scanline (line 0) switch (bpp) { case 1: { diff --git a/plugins/AdvaImg/src/FreeImageToolkit/JPEGTransform.cpp b/plugins/AdvaImg/src/FreeImageToolkit/JPEGTransform.cpp index 5822f748a6..132fef7e85 100644 --- a/plugins/AdvaImg/src/FreeImageToolkit/JPEGTransform.cpp +++ b/plugins/AdvaImg/src/FreeImageToolkit/JPEGTransform.cpp @@ -1,410 +1,623 @@ -// ========================================================== -// JPEG lossless transformations -// -// Design and implementation by -// - Petr Pytelka (pyta@lightcomp.com) -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -extern "C" { -#define XMD_H -#undef FAR -#include <setjmp.h> - -#include "../LibJPEG/jinclude.h" -#include "../LibJPEG/jpeglib.h" -#include "../LibJPEG/jerror.h" -#include "../LibJPEG/transupp.h" -} - -#include "FreeImage.h" -#include "Utilities.h" - +// ==========================================================
+// JPEG lossless transformations
+//
+// Design and implementation by
+// - Petr Pytelka (pyta@lightcomp.com)
+// - 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!
+// ==========================================================
+
+extern "C" {
+#define XMD_H
+#undef FAR
+#include <setjmp.h>
+
+#include "../LibJPEG/jinclude.h"
+#include "../LibJPEG/jpeglib.h"
+#include "../LibJPEG/jerror.h"
+#include "../LibJPEG/transupp.h"
+}
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageIO.h"
+
// ---------------------------------------------------------- -// IO filename handling +// Source manager & Destination manager setup +// (see PluginJPEG.cpp) // ---------------------------------------------------------- - -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; -} +
+void jpeg_freeimage_src(j_decompress_ptr cinfo, fi_handle infile, FreeImageIO *io); +void jpeg_freeimage_dst(j_compress_ptr cinfo, fi_handle outfile, FreeImageIO *io); +
+// ----------------------------------------------------------
+// Error handling
+// (see also PluginJPEG.cpp) +// ----------------------------------------------------------
+
+/**
+ 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
+// ----------------------------------------------------------
+
+/**
+Build a crop string.
+
+@param crop Output crop string
+@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
+@param width Image width
+@param height Image height
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL
+getCropString(char* crop, int* left, int* top, int* right, int* bottom, int width, int height) {
+ if(!left || !top || !right || !bottom) {
+ return FALSE;
+ }
+
+ *left = CLAMP(*left, 0, width);
+ *top = CLAMP(*top, 0, height);
+
+ // negative/zero right and bottom count from the edges inwards
+
+ if(*right <= 0) {
+ *right = width + *right;
+ }
+ if(*bottom <= 0) {
+ *bottom = height + *bottom;
+ }
+
+ *right = CLAMP(*right, 0, width);
+ *bottom = CLAMP(*bottom, 0, height);
+
+ // test for empty rect
+
+ if(((*left - *right) == 0) || ((*top - *bottom) == 0)) {
+ return FALSE;
+ }
+
+ // normalize the rectangle
+
+ if(*right < *left) {
+ INPLACESWAP(*left, *right);
+ }
+ if(*bottom < *top) {
+ INPLACESWAP(*top, *bottom);
+ }
+
+ // test for "noop" rect
+
+ if(*left == 0 && *right == width && *top == 0 && *bottom == height) {
+ return FALSE;
+ }
+
+ // build the crop option
+ sprintf(crop, "%dx%d+%d+%d", *right - *left, *bottom - *top, *left, *top);
+
+ return TRUE;
+}
+
+static BOOL
+JPEGTransformFromHandle(FreeImageIO* src_io, fi_handle src_handle, FreeImageIO* dst_io, fi_handle dst_handle, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, BOOL perfect) {
+ const BOOL onlyReturnCropRect = (dst_io == NULL) || (dst_handle == NULL);
+ const long stream_start = onlyReturnCropRect ? 0 : dst_io->tell_proc(dst_handle);
+ BOOL swappedDim = FALSE;
+ BOOL trimH = FALSE;
+ BOOL trimV = FALSE;
+
+ // 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;
+ trimH = TRUE;
+ break;
+ case FIJPEG_OP_FLIP_V: // vertical flip
+ transfoptions.transform = JXFORM_FLIP_V;
+ trimV = TRUE;
+ break;
+ case FIJPEG_OP_TRANSPOSE: // transpose across UL-to-LR axis
+ transfoptions.transform = JXFORM_TRANSPOSE;
+ swappedDim = TRUE;
+ break;
+ case FIJPEG_OP_TRANSVERSE: // transpose across UR-to-LL axis
+ transfoptions.transform = JXFORM_TRANSVERSE;
+ trimH = TRUE;
+ trimV = TRUE;
+ swappedDim = TRUE;
+ break;
+ case FIJPEG_OP_ROTATE_90: // 90-degree clockwise rotation
+ transfoptions.transform = JXFORM_ROT_90;
+ trimH = TRUE;
+ swappedDim = TRUE;
+ break;
+ case FIJPEG_OP_ROTATE_180: // 180-degree rotation
+ trimH = TRUE;
+ trimV = TRUE;
+ transfoptions.transform = JXFORM_ROT_180;
+ break;
+ case FIJPEG_OP_ROTATE_270: // 270-degree clockwise (or 90 ccw)
+ transfoptions.transform = JXFORM_ROT_270;
+ trimV = TRUE;
+ swappedDim = TRUE;
+ 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);
+
+ // Specify data source for decompression
+ jpeg_freeimage_src(&srcinfo, src_handle, src_io);
+
+ // Enable saving of extra markers that we want to copy
+ jcopy_markers_setup(&srcinfo, copyoption);
+
+ // Read the file header
+ jpeg_read_header(&srcinfo, TRUE);
+
+ // crop option
+ char crop[64];
+ const BOOL hasCrop = getCropString(crop, left, top, right, bottom, swappedDim ? srcinfo.image_height : srcinfo.image_width, swappedDim ? srcinfo.image_width : srcinfo.image_height);
+
+ if(hasCrop) {
+ if(!jtransform_parse_crop_spec(&transfoptions, crop)) {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Bogus crop argument %s", crop);
+ throw(1);
+ }
+ }
+
+ // 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);
+ }
+
+ if(left || top) {
+ // compute left and top offsets, it's a bit tricky, taking into account both
+ // transform, which might have trimed the image,
+ // and crop itself, which is adjusted to lie on a iMCU boundary
+
+ const int fullWidth = swappedDim ? srcinfo.image_height : srcinfo.image_width;
+ const int fullHeight = swappedDim ? srcinfo.image_width : srcinfo.image_height;
+
+ int transformedFullWidth = fullWidth;
+ int transformedFullHeight = fullHeight;
+
+ if(trimH && transformedFullWidth/transfoptions.iMCU_sample_width > 0) {
+ transformedFullWidth = (transformedFullWidth/transfoptions.iMCU_sample_width) * transfoptions.iMCU_sample_width;
+ }
+ if(trimV && transformedFullHeight/transfoptions.iMCU_sample_height > 0) {
+ transformedFullHeight = (transformedFullHeight/transfoptions.iMCU_sample_height) * transfoptions.iMCU_sample_height;
+ }
+
+ const int trimmedWidth = fullWidth - transformedFullWidth;
+ const int trimmedHeight = fullHeight - transformedFullHeight;
+
+ if(left) {
+ *left = trimmedWidth + transfoptions.x_crop_offset * transfoptions.iMCU_sample_width;
+ }
+ if(top) {
+ *top = trimmedHeight + transfoptions.y_crop_offset * transfoptions.iMCU_sample_height;
+ }
+ }
+
+ if(right) {
+ *right = (left ? *left : 0) + transfoptions.output_width;
+ }
+ if(bottom) {
+ *bottom = (top ? *top : 0) + transfoptions.output_height;
+ }
+
+ // if only the crop rect is requested, we are done
+
+ if(onlyReturnCropRect) {
+ jpeg_destroy_compress(&dstinfo);
+ jpeg_destroy_decompress(&srcinfo);
+ return TRUE;
+ }
+
+ // 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);
+
+ // 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(src_handle == dst_handle) {
+ dst_io->seek_proc(dst_handle, stream_start, SEEK_SET);
+ }
+
+ // Specify data destination for compression
+ jpeg_freeimage_dst(&dstinfo, dst_handle, dst_io);
+
+ // 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);
+
+ }
+ catch(...) {
+ jpeg_destroy_compress(&dstinfo);
+ jpeg_destroy_decompress(&srcinfo);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// FreeImage interface
+// ----------------------------------------------------------
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGTransformFromHandle(FreeImageIO* src_io, fi_handle src_handle, FreeImageIO* dst_io, fi_handle dst_handle, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, BOOL perfect) {
+ return JPEGTransformFromHandle(src_io, src_handle, dst_io, dst_handle, operation, left, top, right, bottom, perfect);
+}
+
+static void
+closeStdIO(fi_handle src_handle, fi_handle dst_handle) {
+ if(src_handle) {
+ fclose((FILE*)src_handle);
+ }
+ if(dst_handle) {
+ fclose((FILE*)dst_handle);
+ }
+}
+
+static BOOL
+openStdIO(const char* src_file, const char* dst_file, FreeImageIO* dst_io, fi_handle* src_handle, fi_handle* dst_handle) {
+ *src_handle = NULL;
+ *dst_handle = NULL;
+
+ FreeImageIO io;
+ SetDefaultIO (&io);
+
+ const BOOL isSameFile = (dst_file && (strcmp(src_file, dst_file) == 0)) ? TRUE : FALSE;
+
+ FILE* srcp = NULL;
+ FILE* dstp = NULL;
+
+ if(isSameFile) {
+ srcp = fopen(src_file, "r+b");
+ dstp = srcp;
+ }
+ else {
+ srcp = fopen(src_file, "rb");
+ if(dst_file) {
+ dstp = fopen(dst_file, "wb");
+ }
+ }
+
+ if(!srcp || (dst_file && !dstp)) {
+ if(!srcp) {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open \"%s\" for reading", src_file);
+ } else {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open \"%s\" for writing", dst_file);
+ }
+ closeStdIO(srcp, dstp);
+ return FALSE;
+ }
+
+ if(FreeImage_GetFileTypeFromHandle(&io, srcp) != FIF_JPEG) {
+ FreeImage_OutputMessageProc(FIF_JPEG, " Source file \"%s\" is not jpeg", src_file);
+ closeStdIO(srcp, dstp);
+ return FALSE;
+ }
+
+ *dst_io = io;
+ *src_handle = srcp;
+ *dst_handle = dstp;
+
+ return TRUE;
+}
+
+static BOOL
+openStdIOU(const wchar_t* src_file, const wchar_t* dst_file, FreeImageIO* dst_io, fi_handle* src_handle, fi_handle* dst_handle) {
+#ifdef _WIN32
+
+ *src_handle = NULL;
+ *dst_handle = NULL;
+
+ FreeImageIO io;
+ SetDefaultIO (&io);
+
+ const BOOL isSameFile = (dst_file && (wcscmp(src_file, dst_file) == 0)) ? TRUE : FALSE;
+
+ FILE* srcp = NULL;
+ FILE* dstp = NULL;
+
+ if(isSameFile) {
+ srcp = _wfopen(src_file, L"r+b");
+ dstp = srcp;
+ } else {
+ srcp = _wfopen(src_file, L"rb");
+ if(dst_file) {
+ dstp = _wfopen(dst_file, L"wb");
+ }
+ }
+
+ if(!srcp || (dst_file && !dstp)) {
+ if(!srcp) {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open source file for reading");
+ } else {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open destination file for writing");
+ }
+ closeStdIO(srcp, dstp);
+ return FALSE;
+ }
+
+ if(FreeImage_GetFileTypeFromHandle(&io, srcp) != FIF_JPEG) {
+ FreeImage_OutputMessageProc(FIF_JPEG, " Source file is not jpeg");
+ closeStdIO(srcp, dstp);
+ return FALSE;
+ }
+
+ *dst_io = io;
+ *src_handle = srcp;
+ *dst_handle = dstp;
+
+ return TRUE;
+
+#else
+ return FALSE;
+#endif // _WIN32
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGTransform(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect) {
+ FreeImageIO io;
+ fi_handle src;
+ fi_handle dst;
+
+ if(!openStdIO(src_file, dst_file, &io, &src, &dst)) {
+ return FALSE;
+ }
+
+ BOOL ret = JPEGTransformFromHandle(&io, src, &io, dst, operation, NULL, NULL, NULL, NULL, perfect);
+
+ closeStdIO(src, dst);
+
+ return ret;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGCrop(const char *src_file, const char *dst_file, int left, int top, int right, int bottom) {
+ FreeImageIO io;
+ fi_handle src;
+ fi_handle dst;
+
+ if(!openStdIO(src_file, dst_file, &io, &src, &dst)) {
+ return FALSE;
+ }
+
+ BOOL ret = FreeImage_JPEGTransformFromHandle(&io, src, &io, dst, FIJPEG_OP_NONE, &left, &top, &right, &bottom, FALSE);
+
+ closeStdIO(src, dst);
+
+ return ret;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGTransformU(const wchar_t *src_file, const wchar_t *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect) {
+ FreeImageIO io;
+ fi_handle src;
+ fi_handle dst;
+
+ if(!openStdIOU(src_file, dst_file, &io, &src, &dst)) {
+ return FALSE;
+ }
+
+ BOOL ret = JPEGTransformFromHandle(&io, src, &io, dst, operation, NULL, NULL, NULL, NULL, perfect);
+
+ closeStdIO(src, dst);
+
+ return ret;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGCropU(const wchar_t *src_file, const wchar_t *dst_file, int left, int top, int right, int bottom) {
+ FreeImageIO io;
+ fi_handle src;
+ fi_handle dst;
+
+ if(!openStdIOU(src_file, dst_file, &io, &src, &dst)) {
+ return FALSE;
+ }
+
+ BOOL ret = FreeImage_JPEGTransformFromHandle(&io, src, &io, dst, FIJPEG_OP_NONE, &left, &top, &right, &bottom, FALSE);
+
+ closeStdIO(src, dst);
+
+ return ret;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGTransformCombined(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, BOOL perfect) {
+ FreeImageIO io;
+ fi_handle src;
+ fi_handle dst;
+
+ if(!openStdIO(src_file, dst_file, &io, &src, &dst)) {
+ return FALSE;
+ }
+
+ BOOL ret = FreeImage_JPEGTransformFromHandle(&io, src, &io, dst, operation, left, top, right, bottom, perfect);
+
+ closeStdIO(src, dst);
+
+ return ret;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGTransformCombinedU(const wchar_t *src_file, const wchar_t *dst_file, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, BOOL perfect) {
+ FreeImageIO io;
+ fi_handle src;
+ fi_handle dst;
+
+ if(!openStdIOU(src_file, dst_file, &io, &src, &dst)) {
+ return FALSE;
+ }
+
+ BOOL ret = FreeImage_JPEGTransformFromHandle(&io, src, &io, dst, operation, left, top, right, bottom, perfect);
+
+ closeStdIO(src, dst);
+
+ return ret;
+}
+
+// --------------------------------------------------------------------------
+
+static BOOL
+getMemIO(FIMEMORY* src_stream, FIMEMORY* dst_stream, FreeImageIO* dst_io, fi_handle* src_handle, fi_handle* dst_handle) {
+ *src_handle = NULL;
+ *dst_handle = NULL;
+
+ FreeImageIO io;
+ SetMemoryIO (&io);
+
+ if(dst_stream) {
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(dst_stream->data);
+ if(mem_header->delete_me != TRUE) {
+ // do not save in a user buffer
+ FreeImage_OutputMessageProc(FIF_JPEG, "Destination memory buffer is read only");
+ return FALSE;
+ }
+ }
+
+ *dst_io = io;
+ *src_handle = src_stream;
+ *dst_handle = dst_stream;
+
+ return TRUE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGTransformCombinedFromMemory(FIMEMORY* src_stream, FIMEMORY* dst_stream, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, BOOL perfect) {
+ FreeImageIO io;
+ fi_handle src;
+ fi_handle dst;
+
+ if(!getMemIO(src_stream, dst_stream, &io, &src, &dst)) {
+ return FALSE;
+ }
+
+ return FreeImage_JPEGTransformFromHandle(&io, src, &io, dst, operation, left, top, right, bottom, perfect);
+}
+
diff --git a/plugins/AdvaImg/src/FreeImageToolkit/Rescale.cpp b/plugins/AdvaImg/src/FreeImageToolkit/Rescale.cpp index ffe667e7d4..0c8bbc2787 100644 --- a/plugins/AdvaImg/src/FreeImageToolkit/Rescale.cpp +++ b/plugins/AdvaImg/src/FreeImageToolkit/Rescale.cpp @@ -1,169 +1,169 @@ -// ==========================================================
-// Upsampling / downsampling routine
-//
-// Design and implementation by
-// - Hervé Drolon (drolon@infonie.fr)
-// - Carsten Klein (cklein05@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 "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);
-
- dst = Engine.scale(src, dst_width, dst_height, 0, 0,
- FreeImage_GetWidth(src), FreeImage_GetHeight(src));
-
- 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;
-}
+// ========================================================== +// Upsampling / downsampling routine +// +// Design and implementation by +// - Hervé Drolon (drolon@infonie.fr) +// - Carsten Klein (cklein05@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 "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); + + dst = Engine.scale(src, dst_width, dst_height, 0, 0, + FreeImage_GetWidth(src), FreeImage_GetHeight(src)); + + 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/AdvaImg/src/FreeImageToolkit/Resize.cpp b/plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp index f342bb794e..283a91e830 100644 --- a/plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp +++ b/plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp @@ -139,9 +139,8 @@ GetRGBAPalette(FIBITMAP *dib, RGBQUAD * const buffer) { // --------------------------------------------------------------------------
CWeightsTable::CWeightsTable(CGenericFilter *pFilter, unsigned uDstSize, unsigned uSrcSize) {
- unsigned u;
double dWidth;
- double dFScale = 1.0;
+ double dFScale;
const double dFilterWidth = pFilter->GetWidth();
// scale factor
@@ -153,69 +152,70 @@ CWeightsTable::CWeightsTable(CGenericFilter *pFilter, unsigned uDstSize, unsigne dFScale = dScale;
} else {
// magnification
- dWidth= dFilterWidth;
+ dWidth = dFilterWidth;
+ dFScale = 1.0;
}
// allocate a new line contributions structure
//
// window size is the number of sampled pixels
m_WindowSize = 2 * (int)ceil(dWidth) + 1;
+ // length of dst line (no. of rows / cols)
m_LineLength = uDstSize;
+
// allocate list of contributions
m_WeightTable = (Contribution*)malloc(m_LineLength * sizeof(Contribution));
- for(u = 0 ; u < m_LineLength ; u++) {
+ for(unsigned 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;
+ const double dOffset = (0.5 / dScale);
- for(u = 0; u < m_LineLength; u++) {
+ for(unsigned 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--;
- }
- }
+ // inverse mapping (discrete dst 'u' to continous src 'dCenter')
+ const double dCenter = (double)u / dScale + dOffset;
+
+ // find the significant edge points that affect the pixel
+ const int iLeft = MAX(0, (int)(dCenter - dWidth + 0.5));
+ const int iRight = MIN((int)(dCenter + dWidth + 0.5), int(uSrcSize));
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++) {
+ double dTotalWeight = 0; // sum of weights (initialized to zero)
+ for(int iSrc = iLeft; iSrc < iRight; iSrc++) {
// calculate weights
- const double weight = dFScale * pFilter->Filter(dFScale * (dCenter - (double)iSrc));
+ const double weight = dFScale * pFilter->Filter(dFScale * ((double)iSrc + 0.5 - dCenter));
+ // assert((iSrc-iLeft) < m_WindowSize);
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++) {
+ for(int 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) {
+ }
+
+ // simplify the filter, discarding null weights at the right
+ {
+ int iTrailing = iRight - iLeft - 1;
+ while(m_WeightTable[u].Weights[iTrailing] == 0) {
m_WeightTable[u].Right--;
- iSrc--;
+ iTrailing--;
if(m_WeightTable[u].Right == m_WeightTable[u].Left) {
break;
}
}
-
+
}
- }
+
+ } // next dst pixel
}
CWeightsTable::~CWeightsTable() {
@@ -253,6 +253,12 @@ FIBITMAP* CResizeEngine::scale(FIBITMAP *src, unsigned dst_width, unsigned dst_h // greyscale images require an 8-bit destination image
// (or a 32-bit image if the image is transparent)
dst_bpp = FreeImage_IsTransparent(src) ? 32 : 8;
+ if (dst_bpp == 32) {
+ // additionally, for transparent images we always need a
+ // palette including transparency information (an RGBA palette)
+ // so, set color_type accordingly.
+ color_type = FIC_PALETTE;
+ }
} else if (src_bpp == 16 && image_type == FIT_BITMAP) {
// 16-bit 555 and 565 RGB images require a high-color destination image
// (fixed to 24 bits, since 16-bit RGBs don't support transparency in FreeImage)
@@ -303,7 +309,7 @@ FIBITMAP* CResizeEngine::scale(FIBITMAP *src, unsigned dst_width, unsigned dst_h // provide the source image's palette to the rescaler for
// FIC_PALETTE type images (this includes palletized greyscale
- // images with an unordered palette)
+ // images with an unordered palette as well as transparent images)
if (color_type == FIC_PALETTE) {
if (dst_bpp == 32) {
// a 32 bit destination image signals transparency, so
@@ -522,7 +528,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
double value = 0;
- for (unsigned i = iLeft; i <= iRight; i++) {
+ for (unsigned i = iLeft; i < iRight; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const unsigned pixel = (src_bits[i >> 3] & (0x80 >> (i & 0x07))) != 0;
@@ -546,7 +552,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
double value = 0;
- for (unsigned i = iLeft; i <= iRight; i++) {
+ for (unsigned i = iLeft; i < iRight; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const unsigned pixel = (src_bits[i >> 3] & (0x80 >> (i & 0x07))) != 0;
@@ -579,7 +585,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
double r = 0, g = 0, b = 0;
- for (unsigned i = iLeft; i <= iRight; i++) {
+ 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);
@@ -617,7 +623,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
double r = 0, g = 0, b = 0, a = 0;
- for (unsigned i = iLeft; i <= iRight; i++) {
+ 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);
@@ -663,7 +669,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
double value = 0;
- for (unsigned i = iLeft; i <= iRight; i++) {
+ for (unsigned i = iLeft; i < iRight; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const unsigned pixel = i & 0x01 ? src_bits[i >> 1] & 0x0F : src_bits[i >> 1] >> 4;
@@ -695,7 +701,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
double r = 0, g = 0, b = 0;
- for (unsigned i = iLeft; i <= iRight; i++) {
+ 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);
@@ -733,7 +739,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
double r = 0, g = 0, b = 0, a = 0;
- for (unsigned i = iLeft; i <= iRight; i++) {
+ 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);
@@ -781,7 +787,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double value = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
value += (weightsTable.getWeight(x, i)
@@ -807,7 +813,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double value = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
value += (weightsTable.getWeight(x, i) * (double)pixel[i]);
@@ -838,7 +844,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double r = 0, g = 0, b = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(x, i);
@@ -875,7 +881,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double r = 0, g = 0, b = 0, a = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(x, i);
@@ -919,7 +925,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double r = 0, g = 0, b = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(x, i);
@@ -951,7 +957,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double r = 0, g = 0, b = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(x, i);
@@ -989,7 +995,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double r = 0, g = 0, b = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(x, i);
@@ -1026,7 +1032,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double r = 0, g = 0, b = 0, a = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(x, i);
@@ -1069,7 +1075,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double value = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(x, i);
@@ -1103,7 +1109,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double r = 0, g = 0, b = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(x, i);
@@ -1141,7 +1147,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig double r = 0, g = 0, b = 0, a = 0;
// for(i = iLeft to iRight)
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(x, i);
@@ -1181,7 +1187,7 @@ void CResizeEngine::horizontalFilter(FIBITMAP *const src, unsigned height, unsig const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
double value[4] = {0, 0, 0, 0}; // 4 = 128 bpp max
- for(unsigned i = iLeft; i <= iRight; i++) {
+ 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);
@@ -1246,7 +1252,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + index;
double value = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const unsigned pixel = (*src_bits & mask) != 0;
@@ -1277,7 +1283,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + index;
double value = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
value += (weightsTable.getWeight(y, i)
@@ -1313,7 +1319,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + index;
double r = 0, g = 0, b = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1353,7 +1359,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + index;
double r = 0, g = 0, b = 0, a = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1403,7 +1409,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + index;
double value = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const unsigned pixel = x & 0x01 ? *src_bits & 0x0F : *src_bits >> 4;
@@ -1437,7 +1443,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + index;
double r = 0, g = 0, b = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1476,7 +1482,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + index;
double r = 0, g = 0, b = 0, a = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1527,7 +1533,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + x;
double value = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
value += (weightsTable.getWeight(y, i)
@@ -1554,7 +1560,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + x;
double value = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
value += (weightsTable.getWeight(y, i)
@@ -1587,7 +1593,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + x;
double r = 0, g = 0, b = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1624,7 +1630,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + x;
double r = 0, g = 0, b = 0, a = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1671,7 +1677,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const WORD *src_bits = src_base + iLeft * src_pitch + x;
double r = 0, g = 0, b = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1702,7 +1708,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const WORD *src_bits = src_base + iLeft * src_pitch + x;
double r = 0, g = 0, b = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1743,7 +1749,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + index;
double r = 0, g = 0, b = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1783,7 +1789,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const BYTE *src_bits = src_base + iLeft * src_pitch + index;
double r = 0, g = 0, b = 0, a = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1832,7 +1838,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const WORD *src_bits = src_base + iLeft * src_pitch + index;
double value = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1873,7 +1879,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const WORD *src_bits = src_base + iLeft * src_pitch + index;
double r = 0, g = 0, b = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1919,7 +1925,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const WORD *src_bits = src_base + iLeft * src_pitch + index;
double r = 0, g = 0, b = 0, a = 0;
- for (unsigned i = 0; i <= iLimit; i++) {
+ for (unsigned i = 0; i < iLimit; i++) {
// scan between boundaries
// accumulate weighted effect of each neighboring pixel
const double weight = weightsTable.getWeight(y, i);
@@ -1969,7 +1975,7 @@ void CResizeEngine::verticalFilter(FIBITMAP *const src, unsigned width, unsigned const float *src_bits = src_base + iLeft * src_pitch + index;
double value[4] = {0, 0, 0, 0}; // 4 = 128 bpp max
- for (unsigned i = iLeft; i <= iRight; i++) {
+ 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);
diff --git a/plugins/AdvaImg/src/FreeImageToolkit/Resize.h b/plugins/AdvaImg/src/FreeImageToolkit/Resize.h index 7fe1cdb112..ca382efa60 100644 --- a/plugins/AdvaImg/src/FreeImageToolkit/Resize.h +++ b/plugins/AdvaImg/src/FreeImageToolkit/Resize.h @@ -163,14 +163,15 @@ private: /**
Performs horizontal image filtering
- @param src
- @param height
- @param src_width
+
+ @param src Source image
+ @param height Source / Destination image height
+ @param src_width Source image width
@param src_offset_x
@param src_offset_y
@param src_pal
- @param dst
- @param dst_width
+ @param dst Destination image
+ @param dst_width Destination image width
*/
void horizontalFilter(FIBITMAP * const src, const unsigned height, const unsigned src_width,
const unsigned src_offset_x, const unsigned src_offset_y, const RGBQUAD * const src_pal,
@@ -178,14 +179,14 @@ private: /**
Performs vertical image filtering
- @param src
- @param width
- @param src_height
+ @param src Source image
+ @param width Source / Destination image width
+ @param src_height Source image height
@param src_offset_x
@param src_offset_y
@param src_pal
- @param dst
- @param dst_height
+ @param dst Destination image
+ @param dst_height Destination image height
*/
void verticalFilter(FIBITMAP * const src, const unsigned width, const unsigned src_height,
const unsigned src_offset_x, const unsigned src_offset_y, const RGBQUAD * const src_pal,
diff --git a/plugins/AdvaImg/src/LibJPEG/README b/plugins/AdvaImg/src/LibJPEG/README index 4f2645397a..a28ead34ee 100644 --- a/plugins/AdvaImg/src/LibJPEG/README +++ b/plugins/AdvaImg/src/LibJPEG/README @@ -1,8 +1,8 @@ The Independent JPEG Group's JPEG software
==========================================
-README for release 9 of 13-Jan-2013
-===================================
+README for release 9a of 19-Jan-2014
+====================================
This distribution contains the ninth public release of the Independent JPEG
Group's free JPEG software. You are welcome to redistribute this software and
@@ -14,7 +14,7 @@ Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers, and other members of the Independent JPEG Group.
IJG is not affiliated with the ISO/IEC JTC1/SC29/WG1 standards committee
-(also known as JPEG, together with ITU-T SG16).
+(previously known as JPEG, together with ITU-T SG16).
DOCUMENTATION ROADMAP
@@ -115,7 +115,7 @@ with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you,
its user, assume the entire risk as to its quality and accuracy.
-This software is copyright (C) 1991-2013, Thomas G. Lane, Guido Vollbeding.
+This software is copyright (C) 1991-2014, Thomas G. Lane, Guido Vollbeding.
All Rights Reserved except as specified below.
Permission is hereby granted to use, copy, modify, and distribute this
@@ -153,11 +153,11 @@ ltmain.sh). Another support script, install-sh, is copyright by X Consortium but is also freely distributable.
The IJG distribution formerly included code to read and write GIF files.
-To avoid entanglement with the Unisys LZW patent, GIF reading support has
-been removed altogether, and the GIF writer has been simplified to produce
-"uncompressed GIFs". This technique does not use the LZW algorithm; the
-resulting GIF files are larger than usual, but are readable by all standard
-GIF decoders.
+To avoid entanglement with the Unisys LZW patent (now expired), GIF reading
+support has been removed altogether, and the GIF writer has been simplified
+to produce "uncompressed GIFs". This technique does not use the LZW
+algorithm; the resulting GIF files are larger than usual, but are readable
+by all standard GIF decoders.
We are required to state that
"The Graphics Interchange Format(c) is the Copyright property of
@@ -252,8 +252,8 @@ ARCHIVE LOCATIONS The "official" archive site for this software is www.ijg.org.
The most recent released version can always be found there in
directory "files". This particular version will be archived as
-http://www.ijg.org/files/jpegsrc.v9.tar.gz, and in Windows-compatible
-"zip" archive format as http://www.ijg.org/files/jpegsr9.zip.
+http://www.ijg.org/files/jpegsrc.v9a.tar.gz, and in Windows-compatible
+"zip" archive format as http://www.ijg.org/files/jpegsr9a.zip.
The JPEG FAQ (Frequently Asked Questions) article is a source of some
general information about JPEG.
@@ -280,7 +280,7 @@ Thank to Thomas Wiegand and Gary Sullivan for inviting me to the Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland.
Thank to Thomas Richter and Daniel Lee for inviting me to the
-ISO/IEC JTC1/SC29/WG1 (also known as JPEG, together with ITU-T SG16)
+ISO/IEC JTC1/SC29/WG1 (previously known as JPEG, together with ITU-T SG16)
meeting in Berlin, Germany.
Thank to John Korejwa and Massimo Ballerini for inviting me to
@@ -306,10 +306,10 @@ design and development of this singular software package. FILE FORMAT WARS
================
-The ISO/IEC JTC1/SC29/WG1 standards committee (also known as JPEG, together
-with ITU-T SG16) currently promotes different formats containing the name
-"JPEG" which is misleading because these formats are incompatible with
-original DCT-based JPEG and are based on faulty technologies.
+The ISO/IEC JTC1/SC29/WG1 standards committee (previously known as JPEG,
+together with ITU-T SG16) currently promotes different formats containing
+the name "JPEG" which is misleading because these formats are incompatible
+with original DCT-based JPEG and are based on faulty technologies.
IJG therefore does not and will not support such momentary mistakes
(see REFERENCES).
There exist also distributions under the name "OpenJPEG" promoting such
@@ -322,9 +322,13 @@ Don't use an incompatible file format! (In any case, our decoder will remain capable of reading existing JPEG
image files indefinitely.)
-Furthermore, the ISO committee pretends to be "responsible for the popular
-JPEG" in their public reports which is not true because they don't respond to
-actual requirements for the maintenance of the original JPEG specification.
+The ISO committee pretends to be "responsible for the popular JPEG" in their
+public reports which is not true because they don't respond to actual
+requirements for the maintenance of the original JPEG specification.
+Furthermore, the ISO committee pretends to "ensure interoperability" with
+their standards which is not true because their "standards" support only
+application-specific and proprietary use cases and contain mathematically
+incorrect code.
There are currently different distributions in circulation containing the
name "libjpeg" which is misleading because they don't have the features and
@@ -332,19 +336,46 @@ are incompatible with formats supported by actual IJG libjpeg distributions. One of those fakes is released by members of the ISO committee and just uses
the name of libjpeg for misdirection of people, similar to the abuse of the
name JPEG as described above, while having nothing in common with actual IJG
-libjpeg distributions.
-The other one claims to be a "derivative" or "fork" of the original libjpeg
-and violates the license conditions as described under LEGAL ISSUES above.
-We have no sympathy for the release of misleading and illegal distributions
-derived from obsolete code bases.
+libjpeg distributions and containing mathematically incorrect code.
+The other one claims to be a "derivative" or "fork" of the original libjpeg,
+but violates the license conditions as described under LEGAL ISSUES above
+and violates basic C programming properties.
+We have no sympathy for the release of misleading, incorrect and illegal
+distributions derived from obsolete code bases.
Don't use an obsolete code base!
+According to the UCC (Uniform Commercial Code) law, IJG has the lawful and
+legal right to foreclose on certain standardization bodies and other
+institutions or corporations that knowingly perform substantial and
+systematic deceptive acts and practices, fraud, theft, and damaging of the
+value of the people of this planet without their knowing, willing and
+intentional consent.
+The titles, ownership, and rights of these institutions and all their assets
+are now duly secured and held in trust for the free people of this planet.
+People of the planet, on every country, may have a financial interest in
+the assets of these former principals, agents, and beneficiaries of the
+foreclosed institutions and corporations.
+IJG asserts what is: that each man, woman, and child has unalienable value
+and rights granted and deposited in them by the Creator and not any one of
+the people is subordinate to any artificial principality, corporate fiction
+or the special interest of another without their appropriate knowing,
+willing and intentional consent made by contract or accommodation agreement.
+IJG expresses that which already was.
+The people have already determined and demanded that public administration
+entities, national governments, and their supporting judicial systems must
+be fully transparent, accountable, and liable.
+IJG has secured the value for all concerned free people of the planet.
+
+A partial list of foreclosed institutions and corporations ("Hall of Shame")
+is currently prepared and will be published later.
+
TO DO
=====
Version 9 is the second release of a new generation JPEG standard
-to overcome the limitations of the original JPEG specification.
+to overcome the limitations of the original JPEG specification,
+and is the first true source reference JPEG codec.
More features are being prepared for coming releases...
Please send bug reports, offers of help, etc. to jpeg-info@jpegclub.org.
diff --git a/plugins/AdvaImg/src/LibJPEG/ansi2knr.c b/plugins/AdvaImg/src/LibJPEG/ansi2knr.c new file mode 100644 index 0000000000..dcfb5d9255 --- /dev/null +++ b/plugins/AdvaImg/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, <<arbitrary>>)
+ * will not be considered a function definition.
+ * ansi2knr will recognize a multi-line header provided that no intervening
+ * line ends with a left or right brace or a semicolon. These algorithms
+ * ignore whitespace, comments, and preprocessor directives, except that
+ * the function name must be the first thing on the line. The following
+ * constructs will confuse it:
+ * - Any other construct that starts at the left margin and
+ * follows the above syntax (such as a macro or function call).
+ * - Some macros that tinker with the syntax of function headers.
+ */
+
+/*
+ * The original and principal author of ansi2knr is L. Peter Deutsch
+ * <ghost@aladdin.com>. Other authors are noted in the change history
+ * that follows (in reverse chronological order):
+
+ lpd 2000-04-12 backs out Eggert's changes because of bugs:
+ - concatlits didn't declare the type of its bufend argument;
+ - concatlits didn't recognize when it was inside a comment;
+ - scanstring could scan backward past the beginning of the string; when
+ - the check for \ + newline in scanstring was unnecessary.
+
+ 2000-03-05 Paul Eggert <eggert@twinsun.com>
+
+ Add support for concatenated string literals.
+ * ansi2knr.c (concatlits): New decl.
+ (main): Invoke concatlits to concatenate string literals.
+ (scanstring): Handle backslash-newline correctly. Work with
+ character constants. Fix bug when scanning backwards through
+ backslash-quote. Check for unterminated strings.
+ (convert1): Parse character constants, too.
+ (appendline, concatlits): New functions.
+ * ansi2knr.1: Document this.
+
+ lpd 1999-08-17 added code to allow preprocessor directives
+ wherever comments are allowed
+ lpd 1999-04-12 added minor fixes from Pavel Roskin
+ <pavel_roskin@geocities.com> for clean compilation with
+ gcc -W -Wall
+ lpd 1999-03-22 added hack to recognize lines consisting of
+ identifier1(identifier2, xxx) as *not* being procedures
+ lpd 1999-02-03 made indentation of preprocessor commands consistent
+ lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
+ endless loop; quoted strings within an argument list
+ confused the parser
+ lpd 1999-01-24 added a check for write errors on the output,
+ suggested by Jim Meyering <meyering@ascend.com>
+ lpd 1998-11-09 added further hack to recognize identifier(void)
+ as being a procedure
+ lpd 1998-10-23 added hack to recognize lines consisting of
+ identifier1(identifier2) as *not* being procedures
+ lpd 1997-12-08 made input_file optional; only closes input and/or
+ output file if not stdin or stdout respectively; prints
+ usage message on stderr rather than stdout; adds
+ --filename switch (changes suggested by
+ <ceder@lysator.liu.se>)
+ lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
+ compilers that don't understand void, as suggested by
+ Tom Lane
+ lpd 1996-01-15 changed to require that the first non-comment token
+ on the line following a function header be a left brace,
+ to reduce sensitivity to macros, as suggested by Tom Lane
+ <tgl@sss.pgh.pa.us>
+ lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
+ undefined preprocessor symbols as 0; changed all #ifdefs
+ for configuration symbols to #ifs
+ lpd 1995-04-05 changed copyright notice to make it clear that
+ including ansi2knr in a program does not bring the entire
+ program under the GPL
+ lpd 1994-12-18 added conditionals for systems where ctype macros
+ don't handle 8-bit characters properly, suggested by
+ Francois Pinard <pinard@iro.umontreal.ca>;
+ removed --varargs switch (this is now the default)
+ lpd 1994-10-10 removed CONFIG_BROKETS conditional
+ lpd 1994-07-16 added some conditionals to help GNU `configure',
+ suggested by Francois Pinard <pinard@iro.umontreal.ca>;
+ properly erase prototype args in function parameters,
+ contributed by Jim Avera <jima@netcom.com>;
+ correct error in writeblanks (it shouldn't erase EOLs)
+ lpd 1989-xx-xx original version
+ */
+
+/* Most of the conditionals here are to make ansi2knr work with */
+/* or without the GNU configure machinery. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+#if HAVE_CONFIG_H
+
+/*
+ For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
+ This will define HAVE_CONFIG_H and so, activate the following lines.
+ */
+
+# if STDC_HEADERS || HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+#else /* not HAVE_CONFIG_H */
+
+/* Otherwise do it the hard way */
+
+# ifdef BSD
+# include <strings.h>
+# else
+# ifdef VMS
+ extern int strlen(), strncmp();
+# else
+# include <string.h>
+# endif
+# endif
+
+#endif /* not HAVE_CONFIG_H */
+
+#if STDC_HEADERS
+# include <stdlib.h>
+#else
+/*
+ malloc and free should be declared in stdlib.h,
+ but if you've got a K&R compiler, they probably aren't.
+ */
+# ifdef MSDOS
+# include <malloc.h>
+# else
+# ifdef VMS
+ extern char *malloc();
+ extern void free();
+# else
+ extern char *malloc();
+ extern int free();
+# endif
+# endif
+
+#endif
+
+/* Define NULL (for *very* old compilers). */
+#ifndef NULL
+# define NULL (0)
+#endif
+
+/*
+ * The ctype macros don't always handle 8-bit characters correctly.
+ * Compensate for this here.
+ */
+#ifdef isascii
+# undef HAVE_ISASCII /* just in case */
+# define HAVE_ISASCII 1
+#else
+#endif
+#if STDC_HEADERS || !HAVE_ISASCII
+# define is_ascii(c) 1
+#else
+# define is_ascii(c) isascii(c)
+#endif
+
+#define is_space(c) (is_ascii(c) && isspace(c))
+#define is_alpha(c) (is_ascii(c) && isalpha(c))
+#define is_alnum(c) (is_ascii(c) && isalnum(c))
+
+/* Scanning macros */
+#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
+#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
+
+/* Forward references */
+char *ppdirforward();
+char *ppdirbackward();
+char *skipspace();
+char *scanstring();
+int writeblanks();
+int test1();
+int convert1();
+
+/* The main program */
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{ FILE *in = stdin;
+ FILE *out = stdout;
+ char *filename = 0;
+ char *program_name = argv[0];
+ char *output_name = 0;
+#define bufsize 5000 /* arbitrary size */
+ char *buf;
+ char *line;
+ char *more;
+ char *usage =
+ "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
+ /*
+ * In previous versions, ansi2knr recognized a --varargs switch.
+ * If this switch was supplied, ansi2knr would attempt to convert
+ * a ... argument to va_alist and va_dcl; if this switch was not
+ * supplied, ansi2knr would simply drop any such arguments.
+ * Now, ansi2knr always does this conversion, and we only
+ * check for this switch for backward compatibility.
+ */
+ int convert_varargs = 1;
+ int output_error;
+
+ while ( argc > 1 && argv[1][0] == '-' ) {
+ if ( !strcmp(argv[1], "--varargs") ) {
+ convert_varargs = 1;
+ argc--;
+ argv++;
+ continue;
+ }
+ if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
+ filename = argv[2];
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+ fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
+ argv[1]);
+ fprintf(stderr, usage);
+ exit(1);
+ }
+ switch ( argc )
+ {
+ default:
+ fprintf(stderr, usage);
+ exit(0);
+ case 3:
+ output_name = argv[2];
+ out = fopen(output_name, "w");
+ if ( out == NULL ) {
+ fprintf(stderr, "%s: Cannot open output file %s\n",
+ program_name, output_name);
+ exit(1);
+ }
+ /* falls through */
+ case 2:
+ in = fopen(argv[1], "r");
+ if ( in == NULL ) {
+ fprintf(stderr, "%s: Cannot open input file %s\n",
+ program_name, argv[1]);
+ exit(1);
+ }
+ if ( filename == 0 )
+ filename = argv[1];
+ /* falls through */
+ case 1:
+ break;
+ }
+ if ( filename )
+ fprintf(out, "#line 1 \"%s\"\n", filename);
+ buf = malloc(bufsize);
+ if ( buf == NULL )
+ {
+ fprintf(stderr, "Unable to allocate read buffer!\n");
+ exit(1);
+ }
+ line = buf;
+ while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
+ {
+test: line += strlen(line);
+ switch ( test1(buf) )
+ {
+ case 2: /* a function header */
+ convert1(buf, out, 1, convert_varargs);
+ break;
+ case 1: /* a function */
+ /* Check for a { at the start of the next line. */
+ more = ++line;
+f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
+ goto wl;
+ if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
+ goto wl;
+ switch ( *skipspace(ppdirforward(more), 1) )
+ {
+ case '{':
+ /* Definitely a function header. */
+ convert1(buf, out, 0, convert_varargs);
+ fputs(more, out);
+ break;
+ case 0:
+ /* The next line was blank or a comment: */
+ /* keep scanning for a non-comment. */
+ line += strlen(line);
+ goto f;
+ default:
+ /* buf isn't a function header, but */
+ /* more might be. */
+ fputs(buf, out);
+ strcpy(buf, more);
+ line = buf;
+ goto test;
+ }
+ break;
+ case -1: /* maybe the start of a function */
+ if ( line != buf + (bufsize - 1) ) /* overflow check */
+ continue;
+ /* falls through */
+ default: /* not a function */
+wl: fputs(buf, out);
+ break;
+ }
+ line = buf;
+ }
+ if ( line != buf )
+ fputs(buf, out);
+ free(buf);
+ if ( output_name ) {
+ output_error = ferror(out);
+ output_error |= fclose(out);
+ } else { /* out == stdout */
+ fflush(out);
+ output_error = ferror(out);
+ }
+ if ( output_error ) {
+ fprintf(stderr, "%s: error writing to %s\n", program_name,
+ (output_name ? output_name : "stdout"));
+ exit(1);
+ }
+ if ( in != stdin )
+ fclose(in);
+ return 0;
+}
+
+/*
+ * Skip forward or backward over one or more preprocessor directives.
+ */
+char *
+ppdirforward(p)
+ char *p;
+{
+ for (; *p == '#'; ++p) {
+ for (; *p != '\r' && *p != '\n'; ++p)
+ if (*p == 0)
+ return p;
+ if (*p == '\r' && p[1] == '\n')
+ ++p;
+ }
+ return p;
+}
+char *
+ppdirbackward(p, limit)
+ char *p;
+ char *limit;
+{
+ char *np = p;
+
+ for (;; p = --np) {
+ if (*np == '\n' && np[-1] == '\r')
+ --np;
+ for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
+ if (np[-1] == 0)
+ return np;
+ if (*np != '#')
+ return p;
+ }
+}
+
+/*
+ * Skip over whitespace, comments, and preprocessor directives,
+ * in either direction.
+ */
+char *
+skipspace(p, dir)
+ char *p;
+ int dir; /* 1 for forward, -1 for backward */
+{
+ for ( ; ; ) {
+ while ( is_space(*p) )
+ p += dir;
+ if ( !(*p == '/' && p[dir] == '*') )
+ break;
+ p += dir; p += dir;
+ while ( !(*p == '*' && p[dir] == '/') ) {
+ if ( *p == 0 )
+ return p; /* multi-line comment?? */
+ p += dir;
+ }
+ p += dir; p += dir;
+ }
+ return p;
+}
+
+/* Scan over a quoted string, in either direction. */
+char *
+scanstring(p, dir)
+ char *p;
+ int dir;
+{
+ for (p += dir; ; p += dir)
+ if (*p == '"' && p[-dir] != '\\')
+ return p + dir;
+}
+
+/*
+ * Write blanks over part of a string.
+ * Don't overwrite end-of-line characters.
+ */
+int
+writeblanks(start, end)
+ char *start;
+ char *end;
+{ char *p;
+ for ( p = start; p < end; p++ )
+ if ( *p != '\r' && *p != '\n' )
+ *p = ' ';
+ return 0;
+}
+
+/*
+ * Test whether the string in buf is a function definition.
+ * The string may contain and/or end with a newline.
+ * Return as follows:
+ * 0 - definitely not a function definition;
+ * 1 - definitely a function definition;
+ * 2 - definitely a function prototype (NOT USED);
+ * -1 - may be the beginning of a function definition,
+ * append another line and look again.
+ * The reason we don't attempt to convert function prototypes is that
+ * Ghostscript's declaration-generating macros look too much like
+ * prototypes, and confuse the algorithms.
+ */
+int
+test1(buf)
+ char *buf;
+{ char *p = buf;
+ char *bend;
+ char *endfn;
+ int contin;
+
+ if ( !isidfirstchar(*p) )
+ return 0; /* no name at left margin */
+ bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
+ switch ( *bend )
+ {
+ case ';': contin = 0 /*2*/; break;
+ case ')': contin = 1; break;
+ case '{': return 0; /* not a function */
+ case '}': return 0; /* not a function */
+ default: contin = -1;
+ }
+ while ( isidchar(*p) )
+ p++;
+ endfn = p;
+ p = skipspace(p, 1);
+ if ( *p++ != '(' )
+ return 0; /* not a function */
+ p = skipspace(p, 1);
+ if ( *p == ')' )
+ return 0; /* no parameters */
+ /* Check that the apparent function name isn't a keyword. */
+ /* We only need to check for keywords that could be followed */
+ /* by a left parenthesis (which, unfortunately, is most of them). */
+ { static char *words[] =
+ { "asm", "auto", "case", "char", "const", "double",
+ "extern", "float", "for", "if", "int", "long",
+ "register", "return", "short", "signed", "sizeof",
+ "static", "switch", "typedef", "unsigned",
+ "void", "volatile", "while", 0
+ };
+ char **key = words;
+ char *kp;
+ unsigned len = endfn - buf;
+
+ while ( (kp = *key) != 0 )
+ { if ( strlen(kp) == len && !strncmp(kp, buf, len) )
+ return 0; /* name is a keyword */
+ key++;
+ }
+ }
+ {
+ char *id = p;
+ int len;
+ /*
+ * Check for identifier1(identifier2) and not
+ * identifier1(void), or identifier1(identifier2, xxxx).
+ */
+
+ while ( isidchar(*p) )
+ p++;
+ len = p - id;
+ p = skipspace(p, 1);
+ if (*p == ',' ||
+ (*p == ')' && (len != 4 || strncmp(id, "void", 4)))
+ )
+ return 0; /* not a function */
+ }
+ /*
+ * If the last significant character was a ), we need to count
+ * parentheses, because it might be part of a formal parameter
+ * that is a procedure.
+ */
+ if (contin > 0) {
+ int level = 0;
+
+ for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
+ level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
+ if (level > 0)
+ contin = -1;
+ }
+ return contin;
+}
+
+/* Convert a recognized function definition or header to K&R syntax. */
+int
+convert1(buf, out, header, convert_varargs)
+ char *buf;
+ FILE *out;
+ int header; /* Boolean */
+ int convert_varargs; /* Boolean */
+{ char *endfn;
+ char *p;
+ /*
+ * The breaks table contains pointers to the beginning and end
+ * of each argument.
+ */
+ char **breaks;
+ unsigned num_breaks = 2; /* for testing */
+ char **btop;
+ char **bp;
+ char **ap;
+ char *vararg = 0;
+
+ /* Pre-ANSI implementations don't agree on whether strchr */
+ /* is called strchr or index, so we open-code it here. */
+ for ( endfn = buf; *(endfn++) != '('; )
+ ;
+top: p = endfn;
+ breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
+ if ( breaks == NULL )
+ { /* Couldn't allocate break table, give up */
+ fprintf(stderr, "Unable to allocate break table!\n");
+ fputs(buf, out);
+ return -1;
+ }
+ btop = breaks + num_breaks * 2 - 2;
+ bp = breaks;
+ /* Parse the argument list */
+ do
+ { int level = 0;
+ char *lp = NULL;
+ char *rp = NULL;
+ char *end = NULL;
+
+ if ( bp >= btop )
+ { /* Filled up break table. */
+ /* Allocate a bigger one and start over. */
+ free((char *)breaks);
+ num_breaks <<= 1;
+ goto top;
+ }
+ *bp++ = p;
+ /* Find the end of the argument */
+ for ( ; end == NULL; p++ )
+ { switch(*p)
+ {
+ case ',':
+ if ( !level ) end = p;
+ break;
+ case '(':
+ if ( !level ) lp = p;
+ level++;
+ break;
+ case ')':
+ if ( --level < 0 ) end = p;
+ else rp = p;
+ break;
+ case '/':
+ if (p[1] == '*')
+ p = skipspace(p, 1) - 1;
+ break;
+ case '"':
+ p = scanstring(p, 1) - 1;
+ break;
+ default:
+ ;
+ }
+ }
+ /* Erase any embedded prototype parameters. */
+ if ( lp && rp )
+ writeblanks(lp + 1, rp);
+ p--; /* back up over terminator */
+ /* Find the name being declared. */
+ /* This is complicated because of procedure and */
+ /* array modifiers. */
+ for ( ; ; )
+ { p = skipspace(p - 1, -1);
+ switch ( *p )
+ {
+ case ']': /* skip array dimension(s) */
+ case ')': /* skip procedure args OR name */
+ { int level = 1;
+ while ( level )
+ switch ( *--p )
+ {
+ case ']': case ')':
+ level++;
+ break;
+ case '[': case '(':
+ level--;
+ break;
+ case '/':
+ if (p > buf && p[-1] == '*')
+ p = skipspace(p, -1) + 1;
+ break;
+ case '"':
+ p = scanstring(p, -1) + 1;
+ break;
+ default: ;
+ }
+ }
+ if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
+ { /* We found the name being declared */
+ while ( !isidfirstchar(*p) )
+ p = skipspace(p, 1) + 1;
+ goto found;
+ }
+ break;
+ default:
+ goto found;
+ }
+ }
+found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
+ { if ( convert_varargs )
+ { *bp++ = "va_alist";
+ vararg = p-2;
+ }
+ else
+ { p++;
+ if ( bp == breaks + 1 ) /* sole argument */
+ writeblanks(breaks[0], p);
+ else
+ writeblanks(bp[-1] - 1, p);
+ bp--;
+ }
+ }
+ else
+ { while ( isidchar(*p) ) p--;
+ *bp++ = p+1;
+ }
+ p = end;
+ }
+ while ( *p++ == ',' );
+ *bp = p;
+ /* Make a special check for 'void' arglist */
+ if ( bp == breaks+2 )
+ { p = skipspace(breaks[0], 1);
+ if ( !strncmp(p, "void", 4) )
+ { p = skipspace(p+4, 1);
+ if ( p == breaks[2] - 1 )
+ { bp = breaks; /* yup, pretend arglist is empty */
+ writeblanks(breaks[0], p + 1);
+ }
+ }
+ }
+ /* Put out the function name and left parenthesis. */
+ p = buf;
+ while ( p != endfn ) putc(*p, out), p++;
+ /* Put out the declaration. */
+ if ( header )
+ { fputs(");", out);
+ for ( p = breaks[0]; *p; p++ )
+ if ( *p == '\r' || *p == '\n' )
+ putc(*p, out);
+ }
+ else
+ { for ( ap = breaks+1; ap < bp; ap += 2 )
+ { p = *ap;
+ while ( isidchar(*p) )
+ putc(*p, out), p++;
+ if ( ap < bp - 1 )
+ fputs(", ", out);
+ }
+ fputs(") ", out);
+ /* Put out the argument declarations */
+ for ( ap = breaks+2; ap <= bp; ap += 2 )
+ (*ap)[-1] = ';';
+ if ( vararg != 0 )
+ { *vararg = 0;
+ fputs(breaks[0], out); /* any prior args */
+ fputs("va_dcl", out); /* the final arg */
+ fputs(bp[0], out);
+ }
+ else
+ fputs(breaks[0], out);
+ }
+ free((char *)breaks);
+ return 0;
+}
diff --git a/plugins/AdvaImg/src/LibJPEG/change.log b/plugins/AdvaImg/src/LibJPEG/change.log index be1b8870e7..26b628bb86 100644 --- a/plugins/AdvaImg/src/LibJPEG/change.log +++ b/plugins/AdvaImg/src/LibJPEG/change.log @@ -1,6 +1,33 @@ CHANGE LOG for Independent JPEG Group's JPEG software
+Version 9a 19-Jan-2014
+-----------------------
+
+Add support for wide gamut color spaces (JFIF version 2).
+Improve clarity and accuracy in color conversion modules.
+Note: Requires rebuild of test images.
+
+Extend the bit depth support to all values from 8 to 12
+(BITS_IN_JSAMPLE configuration option in jmorecfg.h).
+jpegtran now supports N bits sample data precision with all N from 8 to 12
+in a single instance. Thank to Roland Fassauer for inspiration.
+
+Try to resolve issues with new boolean type definition.
+Thank also to v4hn for suggestion.
+
+Enable option to use default Huffman tables for lossless compression
+(for hardware solution), and in this case improve lossless RGB compression
+with reversible color transform. Thank to Benny Alexandar for hint.
+
+Extend the entropy decoding structure, so that extraneous bytes between
+compressed scan data and following marker can be reported correctly.
+Thank to Nigel Tao for hint.
+
+Add jpegtran -wipe option and extension for -crop.
+Thank to Andrew Senior, David Clunie, and Josef Schmid for suggestion.
+
+
Version 9 13-Jan-2013
----------------------
diff --git a/plugins/AdvaImg/src/LibJPEG/cjpeg.c b/plugins/AdvaImg/src/LibJPEG/cjpeg.c index 6d6b772b7a..b9b65b8839 100644 --- a/plugins/AdvaImg/src/LibJPEG/cjpeg.c +++ b/plugins/AdvaImg/src/LibJPEG/cjpeg.c @@ -174,6 +174,7 @@ usage (void) #endif
#if JPEG_LIB_VERSION_MAJOR >= 9
fprintf(stderr, " -rgb1 Create RGB JPEG file with reversible color transform\n");
+ fprintf(stderr, " -bgycc Create big gamut YCC JPEG file\n");
#endif
#ifdef DCT_ISLOW_SUPPORTED
fprintf(stderr, " -dct int Use integer DCT method%s\n",
@@ -323,6 +324,17 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, #endif
jpeg_set_colorspace(cinfo, JCS_RGB);
+ } else if (keymatch(arg, "bgycc", 5)) {
+ /* Force a big gamut YCC JPEG file to be generated. */
+#if JPEG_LIB_VERSION_MAJOR >= 9 && \
+ (JPEG_LIB_VERSION_MAJOR > 9 || JPEG_LIB_VERSION_MINOR >= 1)
+ jpeg_set_colorspace(cinfo, JCS_BG_YCC);
+#else
+ fprintf(stderr, "%s: sorry, BG_YCC colorspace not supported\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
} else if (keymatch(arg, "maxmemory", 3)) {
/* Maximum memory in Kb (or Mb with 'm'). */
long lval;
diff --git a/plugins/AdvaImg/src/LibJPEG/filelist.txt b/plugins/AdvaImg/src/LibJPEG/filelist.txt index a0761fae7d..62aba52552 100644 --- a/plugins/AdvaImg/src/LibJPEG/filelist.txt +++ b/plugins/AdvaImg/src/LibJPEG/filelist.txt @@ -1,6 +1,6 @@ IJG JPEG LIBRARY: FILE LIST
-Copyright (C) 1994-2012, Thomas G. Lane, Guido Vollbeding.
+Copyright (C) 1994-2013, 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.
@@ -198,6 +198,7 @@ config.sub depcomp
missing
ar-lib
+compile
install-sh Install shell script for those Unix systems lacking one.
Makefile.in Makefile input for configure.
Makefile.am Source file for use with Automake to generate Makefile.in.
diff --git a/plugins/AdvaImg/src/LibJPEG/install.txt b/plugins/AdvaImg/src/LibJPEG/install.txt index d73a05761f..8e6b721ba5 100644 --- a/plugins/AdvaImg/src/LibJPEG/install.txt +++ b/plugins/AdvaImg/src/LibJPEG/install.txt @@ -1,6 +1,6 @@ INSTALLATION INSTRUCTIONS for the Independent JPEG Group's JPEG software
-Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
+Copyright (C) 1991-2013, 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.
@@ -418,54 +418,58 @@ support as follows: the directory containing the URT "librle.a" file (typically the
"lib" subdirectory of the URT distribution).
-Support for 12-bit-deep pixel data:
+Support for 9-bit to 12-bit deep pixel data:
-The JPEG standard allows either 8-bit or 12-bit data precision. (For color,
-this means 8 or 12 bits per channel, of course.) If you need to work with
-deeper than 8-bit data, you can compile the IJG code for 12-bit operation.
+The IJG code currently allows 8, 9, 10, 11, or 12 bits sample data precision.
+(For color, this means 8 to 12 bits per channel, of course.) If you need to
+work with deeper than 8-bit data, you can compile the IJG code for 9-bit to
+12-bit operation.
To do so:
- 1. In jmorecfg.h, define BITS_IN_JSAMPLE as 12 rather than 8.
+ 1. In jmorecfg.h, define BITS_IN_JSAMPLE as 9, 10, 11, or 12 rather than 8.
2. In jconfig.h, undefine BMP_SUPPORTED, RLE_SUPPORTED, and TARGA_SUPPORTED,
- because the code for those formats doesn't handle 12-bit data and won't
- even compile. (The PPM code does work, as explained below. The GIF
- code works too; it scales 8-bit GIF data to and from 12-bit depth
- automatically.)
+ because the code for those formats doesn't handle deeper than 8-bit data
+ and won't even compile. (The PPM code does work, as explained below.
+ The GIF code works too; it scales 8-bit GIF data to and from 12-bit
+ depth automatically.)
3. Compile. Don't expect "make test" to pass, since the supplied test
files are for 8-bit data.
-Currently, 12-bit support does not work on 16-bit-int machines.
+Currently, 9-bit to 12-bit support does not work on 16-bit-int machines.
-Note that a 12-bit version will not read 8-bit JPEG files, nor vice versa;
-so you'll want to keep around a regular 8-bit compilation as well.
-(Run-time selection of data depth, to allow a single copy that does both,
-is possible but would probably slow things down considerably; it's very low
-on our to-do list.)
+Run-time selection and conversion of data precision are currently not
+supported and may be added later.
+Exception: The transcoding part (jpegtran) supports all settings in a
+single instance, since it operates on the level of DCT coefficients and
+not sample values.
-The PPM reader (rdppm.c) can read 12-bit data from either text-format or
-binary-format PPM and PGM files. Binary-format PPM/PGM files which have a
-maxval greater than 255 are assumed to use 2 bytes per sample, MSB first
-(big-endian order). As of early 1995, 2-byte binary format is not
+The PPM reader (rdppm.c) can read deeper than 8-bit data from either
+text-format or binary-format PPM and PGM files. Binary-format PPM/PGM files
+which have a maxval greater than 255 are assumed to use 2 bytes per sample,
+MSB first (big-endian order). As of early 1995, 2-byte binary format is not
officially supported by the PBMPLUS library, but it is expected that a
future release of PBMPLUS will support it. Note that the PPM reader will
read files of any maxval regardless of the BITS_IN_JSAMPLE setting; incoming
-data is automatically rescaled to either maxval=255 or maxval=4095 as
-appropriate for the cjpeg bit depth.
+data is automatically rescaled to maxval=MAXJSAMPLE as appropriate for the
+cjpeg bit depth.
The PPM writer (wrppm.c) will normally write 2-byte binary PPM or PGM
-format, maxval 4095, when compiled with BITS_IN_JSAMPLE=12. Since this
+format, maxval=MAXJSAMPLE, when compiled with BITS_IN_JSAMPLE>8. Since this
format is not yet widely supported, you can disable it by compiling wrppm.c
with PPM_NORAWWORD defined; then the data is scaled down to 8 bits to make a
standard 1-byte/sample PPM or PGM file. (Yes, this means still another copy
of djpeg to keep around. But hopefully you won't need it for very long.
Poskanzer's supposed to get that new PBMPLUS release out Real Soon Now.)
-Of course, if you are working with 12-bit data, you probably have it stored
-in some other, nonstandard format. In that case you'll probably want to
-write your own I/O modules to read and write your format.
+Of course, if you are working with 9-bit to 12-bit data, you probably have
+it stored in some other, nonstandard format. In that case you'll probably
+want to write your own I/O modules to read and write your format.
-Note that a 12-bit version of cjpeg always runs in "-optimize" mode, in
-order to generate valid Huffman tables. This is necessary because our
-default Huffman tables only cover 8-bit data.
+Note:
+The standard Huffman tables are only valid for 8-bit data precision. If
+you selected more than 8-bit data precision, cjpeg uses arithmetic coding
+by default. The Huffman encoder normally uses entropy optimization to
+compute usable tables for higher precision. Otherwise, you'll have to
+supply different default Huffman tables.
Removing code:
@@ -859,6 +863,12 @@ add something like this to your jconfig.h file: #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
typedef unsigned char boolean;
#endif
+ #ifndef FALSE /* in case these macros already exist */
+ #define FALSE 0 /* values of boolean */
+ #endif
+ #ifndef TRUE
+ #define TRUE 1
+ #endif
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
(This is already in jconfig.vc, by the way.)
diff --git a/plugins/AdvaImg/src/LibJPEG/jcapistd.c b/plugins/AdvaImg/src/LibJPEG/jcapistd.c index fed66caf17..8892bfaac8 100644 --- a/plugins/AdvaImg/src/LibJPEG/jcapistd.c +++ b/plugins/AdvaImg/src/LibJPEG/jcapistd.c @@ -2,6 +2,7 @@ * jcapistd.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
+ * Modified 2013 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.
*
@@ -145,7 +146,7 @@ jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, (*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;
+ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size;
if (num_lines < lines_per_iMCU_row)
ERREXIT(cinfo, JERR_BUFFER_SIZE);
diff --git a/plugins/AdvaImg/src/LibJPEG/jcarith.c b/plugins/AdvaImg/src/LibJPEG/jcarith.c index 78edcd353c..3bc0a5b8db 100644 --- a/plugins/AdvaImg/src/LibJPEG/jcarith.c +++ b/plugins/AdvaImg/src/LibJPEG/jcarith.c @@ -1,7 +1,7 @@ /*
* jcarith.c
*
- * Developed 1997-2012 by Guido Vollbeding.
+ * Developed 1997-2013 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.
*
@@ -362,7 +362,6 @@ 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;
@@ -381,14 +380,13 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* 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);
+ m = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->Al);
/* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */
@@ -453,11 +451,11 @@ METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ const int * natural_order;
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) {
@@ -552,6 +550,8 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /*
* 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)
@@ -593,11 +593,11 @@ METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ const int * natural_order;
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) {
@@ -692,12 +692,13 @@ METHODDEF(boolean) encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
- jpeg_component_info * compptr;
+ const int * natural_order;
JBLOCKROW block;
unsigned char *st;
- int blkn, ci, tbl, k, ke;
+ int tbl, k, ke;
int v, v2, m;
- const int * natural_order;
+ int blkn, ci;
+ jpeg_component_info * compptr;
/* Emit restart marker if needed */
if (cinfo->restart_interval) {
diff --git a/plugins/AdvaImg/src/LibJPEG/jccolor.c b/plugins/AdvaImg/src/LibJPEG/jccolor.c index daf66010df..aac5802e92 100644 --- a/plugins/AdvaImg/src/LibJPEG/jccolor.c +++ b/plugins/AdvaImg/src/LibJPEG/jccolor.c @@ -2,7 +2,7 @@ * jccolor.c
*
* Copyright (C) 1991-1996, Thomas G. Lane.
- * Modified 2011-2012 by Guido Vollbeding.
+ * Modified 2011-2013 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.
*
@@ -29,13 +29,25 @@ 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.)
+ * YCbCr is defined per Recommendation ITU-R BT.601-7 (03/2011),
+ * previously known as Recommendation CCIR 601-1, except that Cb and Cr
+ * are normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * sRGB (standard RGB color space) is defined per IEC 61966-2-1:1999.
+ * sYCC (standard luma-chroma-chroma color space with extended gamut)
+ * is defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex F.
+ * bg-sRGB and bg-sYCC (big gamut standard color spaces)
+ * are defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex G.
+ * Note that the derived conversion coefficients given in some of these
+ * documents are imprecise. The general conversion equations are
+ * Y = Kr * R + (1 - Kr - Kb) * G + Kb * B
+ * Cb = 0.5 * (B - Y) / (1 - Kb)
+ * Cr = 0.5 * (R - Y) / (1 - Kr)
+ * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993
+ * from the 1953 FCC NTSC primaries and CIE Illuminant C),
+ * the conversion equations to be implemented are therefore
+ * Y = 0.299 * R + 0.587 * G + 0.114 * B
+ * Cb = -0.168735892 * R - 0.331264108 * G + 0.5 * B + CENTERJSAMPLE
+ * Cr = 0.5 * R - 0.418687589 * G - 0.081312411 * B + CENTERJSAMPLE
* 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)
@@ -49,9 +61,9 @@ typedef my_color_converter * my_cconvert_ptr; * 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.
+ * for 9-bit to 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.
*/
@@ -96,21 +108,21 @@ rgb_ycc_start (j_compress_ptr cinfo) (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;
+ rgb_ycc_tab[i+R_Y_OFF] = FIX(0.299) * i;
+ rgb_ycc_tab[i+G_Y_OFF] = FIX(0.587) * i;
+ rgb_ycc_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF;
+ rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.168735892)) * i;
+ rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.331264108)) * 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;
+ rgb_ycc_tab[i+B_CB_OFF] = FIX(0.5) * 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+R_CR_OFF] = FIX(0.5) * 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;
+ rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.418687589)) * i;
+ rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.081312411)) * i;
}
}
@@ -274,6 +286,9 @@ cmyk_ycck_convert (j_compress_ptr cinfo, * Convert some rows of samples to the JPEG colorspace.
* [R,G,B] to [R-G,G,B-G] conversion with modulo calculation
* (forward reversible color transform).
+ * This can be seen as an adaption of the general RGB->YCbCr
+ * conversion equation with Kr = Kb = 0, while replacing the
+ * normalization by modulo calculation.
*/
METHODDEF(void)
@@ -312,7 +327,7 @@ rgb_rgb1_convert (j_compress_ptr cinfo, /*
* 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).
+ * The source can be either plain grayscale or YCC (since Y == gray).
*/
METHODDEF(void)
@@ -439,11 +454,13 @@ jinit_color_converter (j_compress_ptr cinfo) break;
case JCS_RGB:
+ case JCS_BG_RGB:
if (cinfo->input_components != RGB_PIXELSIZE)
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
case JCS_YCbCr:
+ case JCS_BG_YCC:
if (cinfo->input_components != 3)
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
break;
@@ -460,8 +477,10 @@ jinit_color_converter (j_compress_ptr cinfo) break;
}
- /* Support color transform only for RGB colorspace */
- if (cinfo->color_transform && cinfo->jpeg_color_space != JCS_RGB)
+ /* Support color transform only for RGB colorspaces */
+ if (cinfo->color_transform &&
+ cinfo->jpeg_color_space != JCS_RGB &&
+ cinfo->jpeg_color_space != JCS_BG_RGB)
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
/* Check num_components, set conversion method based on requested space */
@@ -469,20 +488,26 @@ jinit_color_converter (j_compress_ptr cinfo) 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)
+ switch (cinfo->in_color_space) {
+ case JCS_GRAYSCALE:
+ case JCS_YCbCr:
+ case JCS_BG_YCC:
cconvert->pub.color_convert = grayscale_convert;
- else if (cinfo->in_color_space == JCS_RGB) {
+ break;
+ case JCS_RGB:
cconvert->pub.start_pass = rgb_ycc_start;
cconvert->pub.color_convert = rgb_gray_convert;
- } else
+ break;
+ default:
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ }
break;
case JCS_RGB:
+ case JCS_BG_RGB:
if (cinfo->num_components != 3)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
- if (cinfo->in_color_space == JCS_RGB) {
+ if (cinfo->in_color_space == cinfo->jpeg_color_space) {
switch (cinfo->color_transform) {
case JCT_NONE:
cconvert->pub.color_convert = rgb_convert;
@@ -492,7 +517,6 @@ jinit_color_converter (j_compress_ptr cinfo) break;
default:
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
- break;
}
} else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
@@ -501,13 +525,48 @@ jinit_color_converter (j_compress_ptr cinfo) case JCS_YCbCr:
if (cinfo->num_components != 3)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
- if (cinfo->in_color_space == JCS_RGB) {
+ switch (cinfo->in_color_space) {
+ case JCS_RGB:
cconvert->pub.start_pass = rgb_ycc_start;
cconvert->pub.color_convert = rgb_ycc_convert;
- } else if (cinfo->in_color_space == JCS_YCbCr)
+ break;
+ case JCS_YCbCr:
cconvert->pub.color_convert = null_convert;
- else
+ break;
+ default:
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ }
+ break;
+
+ case JCS_BG_YCC:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ switch (cinfo->in_color_space) {
+ case JCS_RGB:
+ /* For conversion from normal RGB input to BG_YCC representation,
+ * the Cb/Cr values are first computed as usual, and then
+ * quantized further after DCT processing by a factor of
+ * 2 in reference to the nominal quantization factor.
+ */
+ /* need quantization scale by factor of 2 after DCT */
+ cinfo->comp_info[1].component_needed = TRUE;
+ cinfo->comp_info[2].component_needed = TRUE;
+ /* compute normal YCC first */
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = rgb_ycc_convert;
+ break;
+ case JCS_YCbCr:
+ /* need quantization scale by factor of 2 after DCT */
+ cinfo->comp_info[1].component_needed = TRUE;
+ cinfo->comp_info[2].component_needed = TRUE;
+ /*FALLTHROUGH*/
+ case JCS_BG_YCC:
+ /* Pass through for BG_YCC input */
+ cconvert->pub.color_convert = null_convert;
+ break;
+ default:
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ }
break;
case JCS_CMYK:
@@ -522,13 +581,17 @@ jinit_color_converter (j_compress_ptr cinfo) case JCS_YCCK:
if (cinfo->num_components != 4)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
- if (cinfo->in_color_space == JCS_CMYK) {
+ switch (cinfo->in_color_space) {
+ case JCS_CMYK:
cconvert->pub.start_pass = rgb_ycc_start;
cconvert->pub.color_convert = cmyk_ycck_convert;
- } else if (cinfo->in_color_space == JCS_YCCK)
+ break;
+ case JCS_YCCK:
cconvert->pub.color_convert = null_convert;
- else
+ break;
+ default:
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ }
break;
default: /* allow null conversion of JCS_UNKNOWN */
diff --git a/plugins/AdvaImg/src/LibJPEG/jcdctmgr.c b/plugins/AdvaImg/src/LibJPEG/jcdctmgr.c index 550b1a6e7c..9daea85f62 100644 --- a/plugins/AdvaImg/src/LibJPEG/jcdctmgr.c +++ b/plugins/AdvaImg/src/LibJPEG/jcdctmgr.c @@ -2,6 +2,7 @@ * jcdctmgr.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
+ * Modified 2003-2013 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.
*
@@ -25,22 +26,30 @@ typedef struct { /* 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 allocated post-DCT divisor tables -- big enough for any
+ * supported variant and not identical to the quant table entries,
+ * because of scaling (especially for an unnormalized DCT) --
+ * are pointed to by dct_table in the per-component comp_info
+ * structures. Each table is given in normal array order.
+ */
+
+typedef union {
+ DCTELEM int_array[DCTSIZE2];
+#ifdef DCT_FLOAT_SUPPORTED
+ FAST_FLOAT float_array[DCTSIZE2];
+#endif
+} divisor_table;
+
+
/* The current scaled-DCT routines require ISLOW-style divisor tables,
* so be sure to compile that code if either ISLOW or SCALING is requested.
*/
@@ -71,7 +80,7 @@ forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, /* 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 * divisors = (DCTELEM *) compptr->dct_table;
DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */
JDIMENSION bi;
@@ -134,7 +143,7 @@ forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, /* 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 * divisors = (FAST_FLOAT *) compptr->dct_table;
FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */
JDIMENSION bi;
@@ -352,22 +361,17 @@ start_pass_fdctmgr (j_compress_ptr cinfo) 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 */
+ /* Create divisor table from quant table */
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];
+ dtbl = (DCTELEM *) compptr->dct_table;
for (i = 0; i < DCTSIZE2; i++) {
- dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
+ dtbl[i] =
+ ((DCTELEM) qtbl->quantval[i]) << (compptr->component_needed ? 4 : 3);
}
fdct->pub.forward_DCT[ci] = forward_DCT;
break;
@@ -395,17 +399,12 @@ start_pass_fdctmgr (j_compress_ptr cinfo) };
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];
+ dtbl = (DCTELEM *) compptr->dct_table;
for (i = 0; i < DCTSIZE2; i++) {
dtbl[i] = (DCTELEM)
DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
(INT32) aanscales[i]),
- CONST_BITS-3);
+ compptr->component_needed ? CONST_BITS-4 : CONST_BITS-3);
}
}
fdct->pub.forward_DCT[ci] = forward_DCT;
@@ -422,25 +421,20 @@ start_pass_fdctmgr (j_compress_ptr cinfo) * What's actually stored is 1/divisor so that the inner loop can
* use a multiplication rather than a division.
*/
- FAST_FLOAT * fdtbl;
+ FAST_FLOAT * fdtbl = (FAST_FLOAT *) 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
};
- 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)));
+ (1.0 / ((double) qtbl->quantval[i] *
+ aanscalefactor[row] * aanscalefactor[col] *
+ (compptr->component_needed ? 16.0 : 8.0)));
i++;
}
}
@@ -464,19 +458,20 @@ GLOBAL(void) jinit_forward_dct (j_compress_ptr cinfo)
{
my_fdct_ptr fdct;
- int i;
+ int ci;
+ jpeg_component_info *compptr;
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;
+ cinfo->fdct = &fdct->pub;
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
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Allocate a divisor table for each component */
+ compptr->dct_table =
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(divisor_table));
}
}
diff --git a/plugins/AdvaImg/src/LibJPEG/jchuff.c b/plugins/AdvaImg/src/LibJPEG/jchuff.c index 4cbab438d5..92fd974caf 100644 --- a/plugins/AdvaImg/src/LibJPEG/jchuff.c +++ b/plugins/AdvaImg/src/LibJPEG/jchuff.c @@ -2,7 +2,7 @@ * jchuff.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 2006-2009 by Guido Vollbeding.
+ * Modified 2006-2013 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.
*
@@ -308,24 +308,27 @@ 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;
+ register INT32 put_buffer;
+ register int put_bits;
/* if size is 0, caller used an invalid Huffman table entry */
if (size == 0)
ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
- put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
-
- put_bits += size; /* new number of bits in buffer */
-
+ /* mask off any extra bits in code */
+ put_buffer = ((INT32) code) & ((((INT32) 1) << size) - 1);
+
+ /* new number of bits in buffer */
+ put_bits = size + state->cur.put_bits;
+
put_buffer <<= 24 - put_bits; /* align incoming bits */
- put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
-
+ /* and merge with old buffer contents */
+ put_buffer |= state->cur.put_buffer;
+
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);
@@ -347,8 +350,8 @@ 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;
+ register INT32 put_buffer;
+ register int put_bits;
/* if size is 0, caller used an invalid Huffman table entry */
if (size == 0)
@@ -357,9 +360,11 @@ emit_bits_e (huff_entropy_ptr entropy, unsigned int code, int size) if (entropy->gather_statistics)
return; /* do nothing if we're only getting stats */
- put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
-
- put_bits += size; /* new number of bits in buffer */
+ /* mask off any extra bits in code */
+ put_buffer = ((INT32) code) & ((((INT32) 1) << size) - 1);
+
+ /* new number of bits in buffer */
+ put_bits = size + entropy->saved.put_bits;
put_buffer <<= 24 - put_bits; /* align incoming bits */
@@ -543,10 +548,7 @@ 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;
+ int blkn, ci, tbl;
ISHIFT_TEMPS
entropy->next_output_byte = cinfo->dest->next_output_byte;
@@ -559,28 +561,27 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /* 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];
+ 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.
*/
- temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
+ temp = IRIGHT_SHIFT((int) (MCU_data[blkn][0][0]), cinfo->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;
+ temp2 = temp - entropy->saved.last_dc_val[ci];
+ entropy->saved.last_dc_val[ci] = temp;
/* Encode the DC coefficient difference per section G.1.2.1 */
- temp2 = temp;
+ temp = temp2;
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) {
@@ -592,10 +593,10 @@ encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) */
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_dc_symbol(entropy, tbl, 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 */
@@ -628,12 +629,12 @@ METHODDEF(boolean) encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ const int * natural_order;
+ JBLOCKROW block;
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;
@@ -731,18 +732,15 @@ encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) /*
* 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.
+ * 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;
+ int Al, blkn;
entropy->next_output_byte = cinfo->dest->next_output_byte;
entropy->free_in_buffer = cinfo->dest->free_in_buffer;
@@ -752,13 +750,12 @@ encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) if (entropy->restarts_to_go == 0)
emit_restart_e(entropy, entropy->next_restart_num);
+ Al = cinfo->Al;
+
/* 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);
+ emit_bits_e(entropy, (unsigned int) (MCU_data[blkn][0][0] >> Al), 1);
}
cinfo->dest->next_output_byte = entropy->next_output_byte;
@@ -786,14 +783,14 @@ METHODDEF(boolean) encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
{
huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ const int * natural_order;
+ JBLOCKROW block;
register int temp;
register int r, k;
+ int Se, Al;
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;
@@ -918,7 +915,7 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, {
register int temp, temp2;
register int nbits;
- register int k, r, i;
+ register int r, k;
int Se = state->cinfo->lim_Se;
const int * natural_order = state->cinfo->natural_order;
@@ -960,7 +957,7 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, r = 0; /* r = run length of zeros */
for (k = 1; k <= Se; k++) {
- if ((temp = block[natural_order[k]]) == 0) {
+ if ((temp2 = block[natural_order[k]]) == 0) {
r++;
} else {
/* if run length > 15, must emit special run-length-16 codes (0xF0) */
@@ -970,7 +967,7 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, r -= 16;
}
- temp2 = temp;
+ temp = temp2;
if (temp < 0) {
temp = -temp; /* temp is abs value of input */
/* This code assumes we are on a two's complement machine */
@@ -986,8 +983,8 @@ encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, 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]))
+ temp = (r << 4) + nbits;
+ if (! emit_bits_s(state, actbl->ehufco[temp], actbl->ehufsi[temp]))
return FALSE;
/* Emit that number of bits of the value, if positive, */
@@ -1124,16 +1121,16 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, {
register int temp;
register int nbits;
- register int k, r;
+ register int r, k;
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) {
@@ -1148,11 +1145,11 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, /* 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++;
@@ -1162,11 +1159,11 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, 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))
@@ -1174,10 +1171,10 @@ htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, /* 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;
}
}
@@ -1562,7 +1559,7 @@ jinit_huff_encoder (j_compress_ptr cinfo) 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;
+ cinfo->entropy = &entropy->pub;
entropy->pub.start_pass = start_pass_huff;
/* Mark tables unallocated */
diff --git a/plugins/AdvaImg/src/LibJPEG/jcinit.c b/plugins/AdvaImg/src/LibJPEG/jcinit.c index f7aa89fdb3..397b488aee 100644 --- a/plugins/AdvaImg/src/LibJPEG/jcinit.c +++ b/plugins/AdvaImg/src/LibJPEG/jcinit.c @@ -2,6 +2,7 @@ * jcinit.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 2003-2013 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.
*
@@ -29,6 +30,24 @@ GLOBAL(void)
jinit_compress_master (j_compress_ptr cinfo)
{
+ long samplesperrow;
+ JDIMENSION jd_samplesperrow;
+
+ /* For now, precision must match compiled-in value... */
+ if (cinfo->data_precision != BITS_IN_JSAMPLE)
+ ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+
+ /* Sanity check on image dimensions */
+ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 ||
+ cinfo->input_components <= 0)
+ ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+ /* 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);
+
/* Initialize master control (includes parameter checking/processing) */
jinit_c_master_control(cinfo, FALSE /* full compression */);
diff --git a/plugins/AdvaImg/src/LibJPEG/jcmarker.c b/plugins/AdvaImg/src/LibJPEG/jcmarker.c index 84fd20db31..f2cd7a393a 100644 --- a/plugins/AdvaImg/src/LibJPEG/jcmarker.c +++ b/plugins/AdvaImg/src/LibJPEG/jcmarker.c @@ -2,7 +2,7 @@ * jcmarker.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
- * Modified 2003-2012 by Guido Vollbeding.
+ * Modified 2003-2013 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.
*
@@ -508,8 +508,8 @@ write_marker_byte (j_compress_ptr cinfo, int 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
+ * when using YCbCr or grayscale data. The JFIF marker is also used
+ * for other standard JPEG colorspaces. 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.
diff --git a/plugins/AdvaImg/src/LibJPEG/jcmaster.c b/plugins/AdvaImg/src/LibJPEG/jcmaster.c index ef73194b8b..431744ebe1 100644 --- a/plugins/AdvaImg/src/LibJPEG/jcmaster.c +++ b/plugins/AdvaImg/src/LibJPEG/jcmaster.c @@ -2,7 +2,7 @@ * jcmaster.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 2003-2011 by Guido Vollbeding.
+ * Modified 2003-2013 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.
*
@@ -222,8 +222,6 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) {
int ci, ssize;
jpeg_component_info *compptr;
- long samplesperrow;
- JDIMENSION jd_samplesperrow;
if (transcode_only)
jpeg_calc_trans_dimensions(cinfo);
@@ -251,7 +249,7 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) /* Sanity check on image dimensions */
if (cinfo->jpeg_height <= 0 || cinfo->jpeg_width <= 0 ||
- cinfo->num_components <= 0 || cinfo->input_components <= 0)
+ cinfo->num_components <= 0)
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
/* Make sure image isn't bigger than I can handle */
@@ -259,14 +257,8 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) (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)
+ /* Only 8 to 12 bits data precision are supported for DCT based JPEG */
+ if (cinfo->data_precision < 8 || cinfo->data_precision > 12)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
/* Check that number of components won't exceed internal array sizes */
@@ -339,8 +331,10 @@ initial_setup (j_compress_ptr cinfo, boolean transcode_only) 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;
+ /* Don't need quantization scale after DCT,
+ * until color conversion says otherwise.
+ */
+ compptr->component_needed = FALSE;
}
/* Compute number of fully interleaved MCU rows (number of times that
@@ -811,7 +805,7 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) 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;
+ cinfo->master = &master->pub;
master->pub.prepare_for_pass = prepare_for_pass;
master->pub.pass_startup = pass_startup;
master->pub.finish_pass = finish_pass_master;
@@ -833,10 +827,14 @@ jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) 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;
+ if (cinfo->optimize_coding)
+ cinfo->arith_code = FALSE; /* disable arithmetic coding */
+ else if (! cinfo->arith_code &&
+ (cinfo->progressive_mode ||
+ (cinfo->block_size > 1 && cinfo->block_size < DCTSIZE)))
+ /* TEMPORARY HACK ??? */
+ /* assume default tables no good for progressive or reduced AC mode */
+ cinfo->optimize_coding = TRUE; /* force Huffman optimization */
/* Initialize my private state */
if (transcode_only) {
diff --git a/plugins/AdvaImg/src/LibJPEG/jconfig.h b/plugins/AdvaImg/src/LibJPEG/jconfig.h index 4a321ed276..3d952e2e72 100644 --- a/plugins/AdvaImg/src/LibJPEG/jconfig.h +++ b/plugins/AdvaImg/src/LibJPEG/jconfig.h @@ -1,45 +1,161 @@ -/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */
-/* see jconfig.txt for explanations */
+/*
+ * jconfig.txt
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * Modified 2009-2013 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 documents the configuration options that are required to
+ * customize the JPEG software for a particular system.
+ *
+ * The actual configuration options for a particular installation are stored
+ * in jconfig.h. On many machines, jconfig.h can be generated automatically
+ * or copied from one of the "canned" jconfig files that we supply. But if
+ * you need to generate a jconfig.h file by hand, this file tells you how.
+ *
+ * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING.
+ * EDIT A COPY NAMED JCONFIG.H.
+ */
+
+/*
+ * These symbols indicate the properties of your machine or compiler.
+ * #define the symbol if yes, #undef it if no.
+ */
+
+/* Does your compiler support function prototypes?
+ * (If not, you also need to use ansi2knr, see install.txt)
+ */
#define HAVE_PROTOTYPES
+
+/* Does your compiler support the declaration "unsigned char" ?
+ * How about "unsigned short" ?
+ */
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
+
+/* Define "void" as "char" if your compiler doesn't know about type void.
+ * NOTE: be sure to define void such that "void *" represents the most general
+ * pointer type, e.g., that returned by malloc().
+ */
/* #define void char */
+
+/* Define "const" as empty if your compiler doesn't know the "const" keyword.
+ */
/* #define const */
+
+/* Define this if an ordinary "char" type is unsigned.
+ * If you're not sure, leaving it undefined will work at some cost in speed.
+ * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
+ */
#undef CHAR_IS_UNSIGNED
+
+/* Define this if your system has an ANSI-conforming <stddef.h> file.
+ */
#define HAVE_STDDEF_H
+
+/* Define this if your system has an ANSI-conforming <stdlib.h> file.
+ */
#define HAVE_STDLIB_H
+
+/* Define this if your system does not have an ANSI/SysV <string.h>,
+ * but does have a BSD-style <strings.h>.
+ */
#undef NEED_BSD_STRINGS
+
+/* Define this if your system does not provide typedef size_t in any of the
+ * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
+ * <sys/types.h> instead.
+ */
#undef NEED_SYS_TYPES_H
-#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */
+
+/* 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 enum, per Windows custom */
+/* 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 */
+/*
+ * 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 TWO_FILE_COMMANDLINE /* optional */
-#define USE_SETMODE /* Microsoft has setmode() */
+/* 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
-#undef PROGRESS_REPORT /* optional */
+
+/* Define this if you want percent-done progress reports from cjpeg/djpeg.
+ */
+#undef PROGRESS_REPORT
+
#endif /* JPEG_CJPEG_DJPEG */
diff --git a/plugins/AdvaImg/src/LibJPEG/jconfig.txt b/plugins/AdvaImg/src/LibJPEG/jconfig.txt index 27086a3644..6c92b82d39 100644 --- a/plugins/AdvaImg/src/LibJPEG/jconfig.txt +++ b/plugins/AdvaImg/src/LibJPEG/jconfig.txt @@ -2,6 +2,7 @@ * jconfig.txt
*
* Copyright (C) 1991-1994, Thomas G. Lane.
+ * Modified 2009-2013 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.
*
@@ -91,12 +92,18 @@ */
#undef INCOMPLETE_TYPES_BROKEN
-/* Define "boolean" as unsigned char, not int, on Windows systems.
+/* Define "boolean" as unsigned char, not enum, on Windows systems.
*/
#ifdef _WIN32
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
typedef unsigned char boolean;
#endif
+#ifndef FALSE /* in case these macros already exist */
+#define FALSE 0 /* values of boolean */
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
#endif
diff --git a/plugins/AdvaImg/src/LibJPEG/jcparam.c b/plugins/AdvaImg/src/LibJPEG/jcparam.c index f440bc9d0e..1680e39257 100644 --- a/plugins/AdvaImg/src/LibJPEG/jcparam.c +++ b/plugins/AdvaImg/src/LibJPEG/jcparam.c @@ -2,7 +2,7 @@ * jcparam.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
- * Modified 2003-2012 by Guido Vollbeding.
+ * Modified 2003-2013 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.
*
@@ -323,18 +323,17 @@ jpeg_set_defaults (j_compress_ptr cinfo) /* 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;
+ /* The standard Huffman tables are only valid for 8-bit data precision.
+ * If the precision is higher, use arithmetic coding.
+ * (Alternatively, using Huffman coding would be possible with forcing
+ * optimization on so that usable tables will be computed, or by
+ * supplying default tables that are valid for the desired precision.)
+ * Otherwise, use Huffman coding by default.
+ */
+ cinfo->arith_code = cinfo->data_precision > 8 ? TRUE : 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;
@@ -360,6 +359,9 @@ jpeg_set_defaults (j_compress_ptr cinfo) * 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.
+ *
+ * For wide gamut colorspaces (BG_RGB and BG_YCC), the major version will be
+ * overridden by jpeg_set_colorspace and set to 2.
*/
cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */
cinfo->JFIF_minor_version = 1;
@@ -384,6 +386,9 @@ GLOBAL(void) jpeg_default_colorspace (j_compress_ptr cinfo)
{
switch (cinfo->in_color_space) {
+ case JCS_UNKNOWN:
+ jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
+ break;
case JCS_GRAYSCALE:
jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
break;
@@ -399,8 +404,12 @@ jpeg_default_colorspace (j_compress_ptr cinfo) case JCS_YCCK:
jpeg_set_colorspace(cinfo, JCS_YCCK);
break;
- case JCS_UNKNOWN:
- jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
+ case JCS_BG_RGB:
+ /* No translation for now -- conversion to BG_YCC not yet supportet */
+ jpeg_set_colorspace(cinfo, JCS_BG_RGB);
+ break;
+ case JCS_BG_YCC:
+ jpeg_set_colorspace(cinfo, JCS_BG_YCC);
break;
default:
ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
@@ -441,29 +450,40 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */
switch (colorspace) {
+ 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;
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);
+ SET_COMP(0, 0x01, 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,
+ SET_COMP(0, 0x52 /* 'R' */, 1,1, 0,
+ cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0,
+ cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0);
+ SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
+ SET_COMP(2, 0x42 /* 'B' */, 1,1, 0,
cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0,
cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 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);
+ SET_COMP(0, 0x01, 2,2, 0, 0,0);
+ SET_COMP(1, 0x02, 1,1, 1, 1,1);
+ SET_COMP(2, 0x03, 1,1, 1, 1,1);
break;
case JCS_CMYK:
cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
@@ -476,19 +496,33 @@ jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) 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);
+ SET_COMP(0, 0x01, 2,2, 0, 0,0);
+ SET_COMP(1, 0x02, 1,1, 1, 1,1);
+ SET_COMP(2, 0x03, 1,1, 1, 1,1);
+ SET_COMP(3, 0x04, 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);
- }
+ case JCS_BG_RGB:
+ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+ cinfo->JFIF_major_version = 2; /* Set JFIF major version = 2 */
+ cinfo->num_components = 3;
+ /* Add offset 0x20 to the normal R/G/B component IDs */
+ SET_COMP(0, 0x72 /* 'r' */, 1,1, 0,
+ cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0,
+ cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0);
+ SET_COMP(1, 0x67 /* 'g' */, 1,1, 0, 0,0);
+ SET_COMP(2, 0x62 /* 'b' */, 1,1, 0,
+ cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0,
+ cinfo->color_transform == JCT_SUBTRACT_GREEN ? 1 : 0);
+ break;
+ case JCS_BG_YCC:
+ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+ cinfo->JFIF_major_version = 2; /* Set JFIF major version = 2 */
+ cinfo->num_components = 3;
+ /* Add offset 0x20 to the normal Cb/Cr component IDs */
+ /* We default to 2x2 subsamples of chrominance */
+ SET_COMP(0, 0x01, 2,2, 0, 0,0);
+ SET_COMP(1, 0x22, 1,1, 1, 1,1);
+ SET_COMP(2, 0x23, 1,1, 1, 1,1);
break;
default:
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
@@ -572,8 +606,10 @@ jpeg_simple_progression (j_compress_ptr cinfo) 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. */
+ if (ncomps == 3 &&
+ (cinfo->jpeg_color_space == JCS_YCbCr ||
+ cinfo->jpeg_color_space == JCS_BG_YCC)) {
+ /* Custom script for YCC color images. */
nscans = 10;
} else {
/* All-purpose script for other color spaces. */
@@ -588,7 +624,7 @@ jpeg_simple_progression (j_compress_ptr cinfo) * 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.
+ * enough space to handle YCC even if initially asked for grayscale.
*/
if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
cinfo->script_space_size = MAX(nscans, 10);
@@ -600,8 +636,10 @@ jpeg_simple_progression (j_compress_ptr cinfo) cinfo->scan_info = scanptr;
cinfo->num_scans = nscans;
- if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
- /* Custom script for YCbCr color images. */
+ if (ncomps == 3 &&
+ (cinfo->jpeg_color_space == JCS_YCbCr ||
+ cinfo->jpeg_color_space == JCS_BG_YCC)) {
+ /* Custom script for YCC color images. */
/* Initial DC scan */
scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
/* Initial AC scan: get some luma data out in a hurry */
diff --git a/plugins/AdvaImg/src/LibJPEG/jctrans.c b/plugins/AdvaImg/src/LibJPEG/jctrans.c index 9dc9e5f3a7..38f06e097c 100644 --- a/plugins/AdvaImg/src/LibJPEG/jctrans.c +++ b/plugins/AdvaImg/src/LibJPEG/jctrans.c @@ -2,7 +2,7 @@ * jctrans.c
*
* Copyright (C) 1995-1998, Thomas G. Lane.
- * Modified 2000-2012 by Guido Vollbeding.
+ * Modified 2000-2013 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.
*
@@ -143,10 +143,10 @@ jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, * 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) {
+ if (srcinfo->JFIF_major_version == 1 ||
+ srcinfo->JFIF_major_version == 2) {
dstinfo->JFIF_major_version = srcinfo->JFIF_major_version;
dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version;
}
diff --git a/plugins/AdvaImg/src/LibJPEG/jdapimin.c b/plugins/AdvaImg/src/LibJPEG/jdapimin.c index 65f8a491bd..c1b88f75ea 100644 --- a/plugins/AdvaImg/src/LibJPEG/jdapimin.c +++ b/plugins/AdvaImg/src/LibJPEG/jdapimin.c @@ -2,7 +2,7 @@ * jdapimin.c
*
* Copyright (C) 1994-1998, Thomas G. Lane.
- * Modified 2009 by Guido Vollbeding.
+ * Modified 2009-2013 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.
*
@@ -114,8 +114,9 @@ jpeg_abort_decompress (j_decompress_ptr cinfo) LOCAL(void)
default_decompress_parms (j_decompress_ptr cinfo)
{
+ int cid0, cid1, cid2;
+
/* 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:
@@ -124,9 +125,22 @@ default_decompress_parms (j_decompress_ptr cinfo) break;
case 3:
- if (cinfo->saw_JFIF_marker) {
- cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
- } else if (cinfo->saw_Adobe_marker) {
+ cid0 = cinfo->comp_info[0].component_id;
+ cid1 = cinfo->comp_info[1].component_id;
+ cid2 = cinfo->comp_info[2].component_id;
+
+ /* First try to guess from the component IDs */
+ if (cid0 == 0x01 && cid1 == 0x02 && cid2 == 0x03)
+ cinfo->jpeg_color_space = JCS_YCbCr;
+ else if (cid0 == 0x01 && cid1 == 0x22 && cid2 == 0x23)
+ cinfo->jpeg_color_space = JCS_BG_YCC;
+ else if (cid0 == 0x52 && cid1 == 0x47 && cid2 == 0x42)
+ cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
+ else if (cid0 == 0x72 && cid1 == 0x67 && cid2 == 0x62)
+ cinfo->jpeg_color_space = JCS_BG_RGB; /* ASCII 'r', 'g', 'b' */
+ else if (cinfo->saw_JFIF_marker)
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+ else if (cinfo->saw_Adobe_marker) {
switch (cinfo->Adobe_transform) {
case 0:
cinfo->jpeg_color_space = JCS_RGB;
@@ -136,23 +150,12 @@ default_decompress_parms (j_decompress_ptr cinfo) break;
default:
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
- cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+ 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 */
- }
+ 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;
@@ -169,7 +172,7 @@ default_decompress_parms (j_decompress_ptr cinfo) break;
default:
WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
- cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
+ cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
break;
}
} else {
diff --git a/plugins/AdvaImg/src/LibJPEG/jdapistd.c b/plugins/AdvaImg/src/LibJPEG/jdapistd.c index e81bd67dd7..6437dc562b 100644 --- a/plugins/AdvaImg/src/LibJPEG/jdapistd.c +++ b/plugins/AdvaImg/src/LibJPEG/jdapistd.c @@ -2,6 +2,7 @@ * jdapistd.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
+ * Modified 2002-2013 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.
*
diff --git a/plugins/AdvaImg/src/LibJPEG/jdarith.c b/plugins/AdvaImg/src/LibJPEG/jdarith.c index 5cd294260d..dac87a9948 100644 --- a/plugins/AdvaImg/src/LibJPEG/jdarith.c +++ b/plugins/AdvaImg/src/LibJPEG/jdarith.c @@ -1,7 +1,7 @@ /*
* jdarith.c
*
- * Developed 1997-2012 by Guido Vollbeding.
+ * Developed 1997-2013 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.
*
@@ -395,6 +395,8 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) /*
* 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)
@@ -744,6 +746,17 @@ start_pass (j_decompress_ptr cinfo) /*
+ * Finish up at the end of an arithmetic-compressed scan.
+ */
+
+METHODDEF(void)
+finish_pass (j_decompress_ptr cinfo)
+{
+ /* no work necessary here */
+}
+
+
+/*
* Module initialization routine for arithmetic entropy decoding.
*/
@@ -758,6 +771,7 @@ jinit_arith_decoder (j_decompress_ptr cinfo) SIZEOF(arith_entropy_decoder));
cinfo->entropy = &entropy->pub;
entropy->pub.start_pass = start_pass;
+ entropy->pub.finish_pass = finish_pass;
/* Mark tables unallocated */
for (i = 0; i < NUM_ARITH_TBLS; i++) {
diff --git a/plugins/AdvaImg/src/LibJPEG/jdcolor.c b/plugins/AdvaImg/src/LibJPEG/jdcolor.c index fe3f1d8d1f..b135776567 100644 --- a/plugins/AdvaImg/src/LibJPEG/jdcolor.c +++ b/plugins/AdvaImg/src/LibJPEG/jdcolor.c @@ -2,7 +2,7 @@ * jdcolor.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 2011-2012 by Guido Vollbeding.
+ * Modified 2011-2013 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.
*
@@ -19,12 +19,15 @@ typedef struct {
struct jpeg_color_deconverter pub; /* public fields */
- /* Private state for YCC->RGB conversion */
+ /* Private state for YCbCr->RGB and BG_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 */
+ JSAMPLE * range_limit; /* pointer to normal sample range limit table, */
+ /* or extended sample range limit table for BG_YCC */
+
/* Private state for RGB->Y conversion */
INT32 * rgb_y_tab; /* => table for RGB to Y conversion */
} my_color_deconverter;
@@ -32,22 +35,44 @@ typedef struct { typedef my_color_deconverter * my_cconvert_ptr;
-/**************** YCbCr -> RGB conversion: most common case **************/
-/**************** RGB -> Y conversion: less common case **************/
+/*************** YCbCr -> RGB conversion: most common case **************/
+/*************** BG_YCC -> RGB conversion: less 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
+ * YCbCr is defined per Recommendation ITU-R BT.601-7 (03/2011),
+ * previously known as Recommendation CCIR 601-1, except that Cb and Cr
+ * are normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * sRGB (standard RGB color space) is defined per IEC 61966-2-1:1999.
+ * sYCC (standard luma-chroma-chroma color space with extended gamut)
+ * is defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex F.
+ * bg-sRGB and bg-sYCC (big gamut standard color spaces)
+ * are defined per IEC 61966-2-1:1999 Amendment A1:2003 Annex G.
+ * Note that the derived conversion coefficients given in some of these
+ * documents are imprecise. The general conversion equations are
+ *
+ * R = Y + K * (1 - Kr) * Cr
+ * G = Y - K * (Kb * (1 - Kb) * Cb + Kr * (1 - Kr) * Cr) / (1 - Kr - Kb)
+ * B = Y + K * (1 - Kb) * Cb
+ *
+ * Y = Kr * R + (1 - Kr - Kb) * G + Kb * B
*
- * R = Y + 1.40200 * Cr
- * G = Y - 0.34414 * Cb - 0.71414 * Cr
- * B = Y + 1.77200 * Cb
+ * With Kr = 0.299 and Kb = 0.114 (derived according to SMPTE RP 177-1993
+ * from the 1953 FCC NTSC primaries and CIE Illuminant C), K = 2 for sYCC,
+ * the conversion equations to be implemented are therefore
*
- * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
+ * R = Y + 1.402 * Cr
+ * G = Y - 0.344136286 * Cb - 0.714136286 * Cr
+ * B = Y + 1.772 * Cb
+ *
+ * Y = 0.299 * R + 0.587 * G + 0.114 * 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.)
+ * For bg-sYCC, with K = 4, the equations are
+ *
+ * R = Y + 2.804 * Cr
+ * G = Y - 0.688272572 * Cb - 1.428272572 * Cr
+ * B = Y + 3.544 * Cb
*
* 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
@@ -58,9 +83,9 @@ typedef my_color_deconverter * my_cconvert_ptr; * 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.
+ * for 9-bit to 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.
@@ -84,11 +109,54 @@ typedef my_color_deconverter * my_cconvert_ptr; /*
- * Initialize tables for YCC->RGB colorspace conversion.
+ * Initialize tables for YCbCr->RGB and BG_YCC->RGB colorspace conversion.
*/
LOCAL(void)
build_ycc_rgb_table (j_decompress_ptr cinfo)
+/* Normal case, sYCC */
+{
+ 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));
+
+ cconvert->range_limit = cinfo->sample_range_limit;
+
+ 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.402 * x */
+ cconvert->Cr_r_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.402) * x + ONE_HALF, SCALEBITS);
+ /* Cb=>B value is nearest int to 1.772 * x */
+ cconvert->Cb_b_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.772) * x + ONE_HALF, SCALEBITS);
+ /* Cr=>G value is scaled-up -0.714136286 * x */
+ cconvert->Cr_g_tab[i] = (- FIX(0.714136286)) * x;
+ /* Cb=>G value is scaled-up -0.344136286 * x */
+ /* We also add in ONE_HALF so that need not do it in inner loop */
+ cconvert->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF;
+ }
+}
+
+
+LOCAL(void)
+build_bg_ycc_rgb_table (j_decompress_ptr cinfo)
+/* Wide gamut case, bg-sYCC */
{
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
int i;
@@ -108,21 +176,39 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
(MAXJSAMPLE+1) * SIZEOF(INT32));
+ cconvert->range_limit = (JSAMPLE *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 5 * (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
+
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 */
+ /* Cr=>R value is nearest int to 2.804 * 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 */
+ RIGHT_SHIFT(FIX(2.804) * x + ONE_HALF, SCALEBITS);
+ /* Cb=>B value is nearest int to 3.544 * 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 */
+ RIGHT_SHIFT(FIX(3.544) * x + ONE_HALF, SCALEBITS);
+ /* Cr=>G value is scaled-up -1.428272572 * x */
+ cconvert->Cr_g_tab[i] = (- FIX(1.428272572)) * x;
+ /* Cb=>G value is scaled-up -0.688272572 * 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;
+ cconvert->Cb_g_tab[i] = (- FIX(0.688272572)) * x + ONE_HALF;
}
+
+ /* Cb and Cr portions can extend to double range in wide gamut case,
+ * so we prepare an appropriate extended range limit table.
+ */
+
+ /* First segment of range limit table: limit[x] = 0 for x < 0 */
+ MEMZERO(cconvert->range_limit, 2 * (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
+ cconvert->range_limit += 2 * (MAXJSAMPLE+1);
+ /* Main part of range limit table: limit[x] = x */
+ for (i = 0; i <= MAXJSAMPLE; i++)
+ cconvert->range_limit[i] = (JSAMPLE) i;
+ /* End of range limit table: limit[x] = MAXJSAMPLE for x > MAXJSAMPLE */
+ for (; i < 3 * (MAXJSAMPLE+1); i++)
+ cconvert->range_limit[i] = MAXJSAMPLE;
}
@@ -149,7 +235,7 @@ ycc_rgb_convert (j_decompress_ptr cinfo, 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 JSAMPLE * range_limit = cconvert->range_limit;
register int * Crrtab = cconvert->Cr_r_tab;
register int * Cbbtab = cconvert->Cb_b_tab;
register INT32 * Crgtab = cconvert->Cr_g_tab;
@@ -166,19 +252,21 @@ ycc_rgb_convert (j_decompress_ptr cinfo, 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]];
+ /* Range-limiting is essential due to noise introduced by DCT losses,
+ * for extended gamut (sYCC) and wide gamut (bg-sYCC) encodings.
+ */
+ 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_BLUE] = range_limit[y + Cbbtab[cb]];
outptr += RGB_PIXELSIZE;
}
}
}
-/**************** Cases other than YCbCr -> RGB **************/
+/**************** Cases other than YCC -> RGB ****************/
/*
@@ -198,9 +286,9 @@ build_rgb_y_table (j_decompress_ptr cinfo) (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;
+ rgb_y_tab[i+R_Y_OFF] = FIX(0.299) * i;
+ rgb_y_tab[i+G_Y_OFF] = FIX(0.587) * i;
+ rgb_y_tab[i+B_Y_OFF] = FIX(0.114) * i + ONE_HALF;
}
}
@@ -244,6 +332,9 @@ rgb_gray_convert (j_decompress_ptr cinfo, /*
* [R-G,G,B-G] to [R,G,B] conversion with modulo calculation
* (inverse color transform).
+ * This can be seen as an adaption of the general YCbCr->RGB
+ * conversion equation with Kr = Kb = 0, while replacing the
+ * normalization by modulo calculation.
*/
METHODDEF(void)
@@ -387,7 +478,7 @@ null_convert (j_decompress_ptr cinfo, /*
* Color conversion for grayscale: just copy the data.
- * This also works for YCbCr -> grayscale conversion, in which
+ * This also works for YCC -> grayscale conversion, in which
* we just copy the Y (luminance) component and ignore chrominance.
*/
@@ -466,7 +557,9 @@ ycck_cmyk_convert (j_decompress_ptr cinfo, y = GETJSAMPLE(inptr0[col]);
cb = GETJSAMPLE(inptr1[col]);
cr = GETJSAMPLE(inptr2[col]);
- /* Range-limiting is essential due to noise introduced by DCT losses. */
+ /* Range-limiting is essential due to noise introduced by DCT losses,
+ * and for extended gamut encodings (sYCC).
+ */
outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
@@ -516,6 +609,8 @@ jinit_color_deconverter (j_decompress_ptr cinfo) case JCS_RGB:
case JCS_YCbCr:
+ case JCS_BG_RGB:
+ case JCS_BG_YCC:
if (cinfo->num_components != 3)
ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
break;
@@ -532,8 +627,10 @@ jinit_color_deconverter (j_decompress_ptr cinfo) break;
}
- /* Support color transform only for RGB colorspace */
- if (cinfo->color_transform && cinfo->jpeg_color_space != JCS_RGB)
+ /* Support color transform only for RGB colorspaces */
+ if (cinfo->color_transform &&
+ cinfo->jpeg_color_space != JCS_RGB &&
+ cinfo->jpeg_color_space != JCS_BG_RGB)
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
/* Set out_color_components and conversion method based on requested space.
@@ -544,13 +641,16 @@ jinit_color_deconverter (j_decompress_ptr cinfo) 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) {
+ switch (cinfo->jpeg_color_space) {
+ case JCS_GRAYSCALE:
+ case JCS_YCbCr:
+ case JCS_BG_YCC:
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) {
+ break;
+ case JCS_RGB:
switch (cinfo->color_transform) {
case JCT_NONE:
cconvert->pub.color_convert = rgb_gray_convert;
@@ -560,21 +660,29 @@ jinit_color_deconverter (j_decompress_ptr cinfo) break;
default:
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
- break;
}
build_rgb_y_table(cinfo);
- } else
+ break;
+ default:
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ }
break;
case JCS_RGB:
cinfo->out_color_components = RGB_PIXELSIZE;
- if (cinfo->jpeg_color_space == JCS_YCbCr) {
+ switch (cinfo->jpeg_color_space) {
+ case JCS_GRAYSCALE:
+ cconvert->pub.color_convert = gray_rgb_convert;
+ break;
+ case 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) {
+ break;
+ case JCS_BG_YCC:
+ cconvert->pub.color_convert = ycc_rgb_convert;
+ build_bg_ycc_rgb_table(cinfo);
+ break;
+ case JCS_RGB:
switch (cinfo->color_transform) {
case JCT_NONE:
cconvert->pub.color_convert = rgb_convert;
@@ -584,7 +692,25 @@ jinit_color_deconverter (j_decompress_ptr cinfo) break;
default:
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ }
+ break;
+ default:
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ }
+ break;
+
+ case JCS_BG_RGB:
+ cinfo->out_color_components = RGB_PIXELSIZE;
+ if (cinfo->jpeg_color_space == JCS_BG_RGB) {
+ switch (cinfo->color_transform) {
+ case JCT_NONE:
+ cconvert->pub.color_convert = rgb_convert;
+ break;
+ case JCT_SUBTRACT_GREEN:
+ cconvert->pub.color_convert = rgb1_rgb_convert;
break;
+ default:
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
}
} else
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
@@ -592,13 +718,17 @@ jinit_color_deconverter (j_decompress_ptr cinfo) case JCS_CMYK:
cinfo->out_color_components = 4;
- if (cinfo->jpeg_color_space == JCS_YCCK) {
+ switch (cinfo->jpeg_color_space) {
+ case JCS_YCCK:
cconvert->pub.color_convert = ycck_cmyk_convert;
build_ycc_rgb_table(cinfo);
- } else if (cinfo->jpeg_color_space == JCS_CMYK) {
+ break;
+ case JCS_CMYK:
cconvert->pub.color_convert = null_convert;
- } else
+ break;
+ default:
ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ }
break;
default:
diff --git a/plugins/AdvaImg/src/LibJPEG/jddctmgr.c b/plugins/AdvaImg/src/LibJPEG/jddctmgr.c index 5e4f1dc440..b2f5a36d96 100644 --- a/plugins/AdvaImg/src/LibJPEG/jddctmgr.c +++ b/plugins/AdvaImg/src/LibJPEG/jddctmgr.c @@ -2,7 +2,7 @@ * jddctmgr.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
- * Modified 2002-2010 by Guido Vollbeding.
+ * Modified 2002-2013 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.
*
@@ -368,7 +368,7 @@ jinit_inverse_dct (j_decompress_ptr cinfo) 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;
+ cinfo->idct = &idct->pub;
idct->pub.start_pass = start_pass;
for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
diff --git a/plugins/AdvaImg/src/LibJPEG/jdhuff.c b/plugins/AdvaImg/src/LibJPEG/jdhuff.c index b18ff7a20a..85a98bd3ef 100644 --- a/plugins/AdvaImg/src/LibJPEG/jdhuff.c +++ b/plugins/AdvaImg/src/LibJPEG/jdhuff.c @@ -2,7 +2,7 @@ * jdhuff.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 2006-2012 by Guido Vollbeding.
+ * Modified 2006-2013 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.
*
@@ -628,6 +628,22 @@ jpeg_huff_decode (bitread_working_state * state, /*
+ * Finish up at the end of a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+finish_pass_huff (j_decompress_ptr cinfo)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+
+ /* 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;
+}
+
+
+/*
* Check for a restart marker & resynchronize decoder.
* Returns FALSE if must suspend.
*/
@@ -638,10 +654,7 @@ 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;
+ finish_pass_huff(cinfo);
/* Advance past the RSTn marker */
if (! (*cinfo->marker->read_restart_marker) (cinfo))
@@ -846,17 +859,15 @@ decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) /*
* 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.
+ * 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;
+ int p1, blkn;
BITREAD_STATE_VARS;
/* Process restart marker if needed; may have to suspend */
@@ -873,15 +884,15 @@ decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) /* Load up working state */
BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ 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++) {
- 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;
+ MCU_data[blkn][0][0] |= p1;
/* Note: since we use |=, repeating the assignment later is safe */
}
@@ -1517,6 +1528,7 @@ jinit_huff_decoder (j_decompress_ptr cinfo) SIZEOF(huff_entropy_decoder));
cinfo->entropy = &entropy->pub;
entropy->pub.start_pass = start_pass_huff_decoder;
+ entropy->pub.finish_pass = finish_pass_huff;
if (cinfo->progressive_mode) {
/* Create progression status table */
diff --git a/plugins/AdvaImg/src/LibJPEG/jdinput.c b/plugins/AdvaImg/src/LibJPEG/jdinput.c index de6f7ed8e9..80bdef568a 100644 --- a/plugins/AdvaImg/src/LibJPEG/jdinput.c +++ b/plugins/AdvaImg/src/LibJPEG/jdinput.c @@ -2,7 +2,7 @@ * jdinput.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 2002-2009 by Guido Vollbeding.
+ * Modified 2002-2013 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.
*
@@ -196,7 +196,7 @@ jpeg_core_output_dimensions (j_decompress_ptr cinfo) /* 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,
+ /* initial_setup has already initialized DCT_scaled_size,
* and has computed unscaled downsampled_width and downsampled_height.
*/
@@ -216,8 +216,8 @@ initial_setup (j_decompress_ptr cinfo) (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)
+ /* Only 8 to 12 bits data precision are supported for DCT based JPEG */
+ if (cinfo->data_precision < 8 || cinfo->data_precision > 12)
ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
/* Check that number of components won't exceed internal array sizes */
@@ -537,6 +537,7 @@ start_input_pass (j_decompress_ptr cinfo) METHODDEF(void)
finish_input_pass (j_decompress_ptr cinfo)
{
+ (*cinfo->entropy->finish_pass) (cinfo);
cinfo->inputctl->consume_input = consume_markers;
}
@@ -646,7 +647,7 @@ jinit_input_controller (j_decompress_ptr cinfo) 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;
+ cinfo->inputctl = &inputctl->pub;
/* Initialize method pointers */
inputctl->pub.consume_input = consume_markers;
inputctl->pub.reset_input_controller = reset_input_controller;
diff --git a/plugins/AdvaImg/src/LibJPEG/jdmarker.c b/plugins/AdvaImg/src/LibJPEG/jdmarker.c index 47ebee9576..b1faf88fb7 100644 --- a/plugins/AdvaImg/src/LibJPEG/jdmarker.c +++ b/plugins/AdvaImg/src/LibJPEG/jdmarker.c @@ -2,7 +2,7 @@ * jdmarker.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
- * Modified 2009-2012 by Guido Vollbeding.
+ * Modified 2009-2013 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.
*
@@ -269,8 +269,8 @@ get_sof (j_decompress_ptr cinfo, boolean is_baseline, boolean is_prog, /* 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)
+ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 ||
+ cinfo->num_components <= 0)
ERREXIT(cinfo, JERR_EMPTY_IMAGE);
if (length != (cinfo->num_components * 3))
@@ -350,6 +350,9 @@ get_sos (j_decompress_ptr cinfo) /* Detect the case where component id's are not unique, and, if so, */
/* create a fake component id using the same logic as in get_sof. */
+ /* Note: This also ensures that all of the SOF components are */
+ /* referenced in the single scan case, which prevents access to */
+ /* uninitialized memory in later decoding stages. */
for (ci = 0; ci < i; ci++) {
if (c == cinfo->cur_comp_info[ci]->component_id) {
c = cinfo->cur_comp_info[0]->component_id;
@@ -493,6 +496,8 @@ get_dht (j_decompress_ptr cinfo) if (count > 256 || ((INT32) count) > length)
ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ MEMZERO(huffval, SIZEOF(huffval)); /* pre-zero array for later copy */
+
for (i = 0; i < count; i++)
INPUT_BYTE(cinfo, huffval[i], return FALSE);
@@ -735,12 +740,13 @@ examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data, 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.
+ * Major version must be 1 or 2, 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)
+ if (cinfo->JFIF_major_version != 1 && cinfo->JFIF_major_version != 2)
WARNMS2(cinfo, JWRN_JFIF_MAJOR,
cinfo->JFIF_major_version, cinfo->JFIF_minor_version);
/* Generate trace messages */
diff --git a/plugins/AdvaImg/src/LibJPEG/jdmaster.c b/plugins/AdvaImg/src/LibJPEG/jdmaster.c index 03d4dd08b8..ed6b499607 100644 --- a/plugins/AdvaImg/src/LibJPEG/jdmaster.c +++ b/plugins/AdvaImg/src/LibJPEG/jdmaster.c @@ -2,7 +2,7 @@ * jdmaster.c
*
* Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 2002-2011 by Guido Vollbeding.
+ * Modified 2002-2013 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.
*
@@ -51,7 +51,8 @@ use_merged_upsample (j_decompress_ptr cinfo) /* 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)
+ cinfo->out_color_components != RGB_PIXELSIZE ||
+ cinfo->color_transform)
return FALSE;
/* and it only handles 2h1v or 2h2v sampling ratios */
if (cinfo->comp_info[0].h_samp_factor != 2 ||
@@ -158,9 +159,11 @@ jpeg_calc_output_dimensions (j_decompress_ptr cinfo) cinfo->out_color_components = 1;
break;
case JCS_RGB:
+ case JCS_BG_RGB:
cinfo->out_color_components = RGB_PIXELSIZE;
break;
case JCS_YCbCr:
+ case JCS_BG_YCC:
cinfo->out_color_components = 3;
break;
case JCS_CMYK:
@@ -273,10 +276,19 @@ master_selection (j_decompress_ptr cinfo) long samplesperrow;
JDIMENSION jd_samplesperrow;
+ /* For now, precision must match compiled-in value... */
+ if (cinfo->data_precision != BITS_IN_JSAMPLE)
+ ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+
/* Initialize dimensions and other stuff */
jpeg_calc_output_dimensions(cinfo);
prepare_range_limit_table(cinfo);
+ /* Sanity check on image dimensions */
+ if (cinfo->output_height <= 0 || cinfo->output_width <= 0 ||
+ cinfo->out_color_components <= 0)
+ ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
/* Width of an output scanline must be representable as JDIMENSION. */
samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
jd_samplesperrow = (JDIMENSION) samplesperrow;
@@ -521,7 +533,7 @@ jinit_master_decompress (j_decompress_ptr cinfo) 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;
+ cinfo->master = &master->pub;
master->pub.prepare_for_output_pass = prepare_for_output_pass;
master->pub.finish_output_pass = finish_output_pass;
diff --git a/plugins/AdvaImg/src/LibJPEG/jdmerge.c b/plugins/AdvaImg/src/LibJPEG/jdmerge.c index 9e3a595de0..605e858cbd 100644 --- a/plugins/AdvaImg/src/LibJPEG/jdmerge.c +++ b/plugins/AdvaImg/src/LibJPEG/jdmerge.c @@ -2,6 +2,7 @@ * jdmerge.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
+ * Modified 2013 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.
*
@@ -103,17 +104,17 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) 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 */
+ /* Cr=>R value is nearest int to 1.402 * 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 */
+ RIGHT_SHIFT(FIX(1.402) * x + ONE_HALF, SCALEBITS);
+ /* Cb=>B value is nearest int to 1.772 * 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 */
+ RIGHT_SHIFT(FIX(1.772) * x + ONE_HALF, SCALEBITS);
+ /* Cr=>G value is scaled-up -0.714136286 * x */
+ upsample->Cr_g_tab[i] = (- FIX(0.714136286)) * x;
+ /* Cb=>G value is scaled-up -0.344136286 * 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;
+ upsample->Cb_g_tab[i] = (- FIX(0.344136286)) * x + ONE_HALF;
}
}
diff --git a/plugins/AdvaImg/src/LibJPEG/jfdctint.c b/plugins/AdvaImg/src/LibJPEG/jfdctint.c index 529eaf8670..4dd7cb9e6c 100644 --- a/plugins/AdvaImg/src/LibJPEG/jfdctint.c +++ b/plugins/AdvaImg/src/LibJPEG/jfdctint.c @@ -2,7 +2,7 @@ * jfdctint.c
*
* Copyright (C) 1991-1996, Thomas G. Lane.
- * Modification developed 2003-2009 by Guido Vollbeding.
+ * Modification developed 2003-2013 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.
*
@@ -165,16 +165,18 @@ jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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. */
+ /* 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/16).
+ */
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".
+ * rotator "c1" should be "c6".
*/
tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]);
@@ -196,47 +198,49 @@ jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS);
dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
- z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */
/* 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);
+
+ dataptr[2] = (DCTELEM)
+ RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM)
+ RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */
+ 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 */
+
+ 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 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */
+ 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);
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp0 += z1 + tmp12;
+ tmp3 += z1 + tmp13;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp1 += z1 + tmp13;
+ tmp2 += z1 + tmp12;
+
+ dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS-PASS1_BITS);
dataptr += DCTSIZE; /* advance pointer to next row */
}
@@ -244,12 +248,13 @@ jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pass 2: process columns.
* We remove the PASS1_BITS scaling, but leave the results scaled up
* by an overall factor of 8.
+ * cK represents sqrt(2) * cos(K*pi/16).
*/
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".
+ * rotator "c1" should be "c6".
*/
tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
@@ -271,47 +276,49 @@ jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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);
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */
/* 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);
+ RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*6] = (DCTELEM)
- RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS);
+ RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */
+ 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 */
+
+ 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 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */
+ 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);
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp0 += z1 + tmp12;
+ tmp3 += z1 + tmp13;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp1 += z1 + tmp13;
+ tmp2 += z1 + tmp12;
+
+ dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS+PASS1_BITS);
dataptr++; /* advance pointer to next column */
}
@@ -338,10 +345,11 @@ jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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++) {
@@ -472,10 +480,11 @@ jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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++) {
@@ -585,12 +594,13 @@ jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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++) {
@@ -695,11 +705,12 @@ jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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]. */
+ /* 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++) {
@@ -737,6 +748,7 @@ jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pass 2: process columns.
* We remove the PASS1_BITS scaling, but leave the results scaled up
* by an overall factor of 8.
+ * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT].
*/
dataptr = data;
@@ -787,12 +799,13 @@ jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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++) {
@@ -869,8 +882,9 @@ jpeg_fdct_2x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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. */
+ /* 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;
@@ -935,11 +949,12 @@ jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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). */
+ /* 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;
@@ -1084,11 +1099,12 @@ jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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). */
+ /* 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;
@@ -1248,11 +1264,12 @@ jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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). */
+ /* 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;
@@ -1430,9 +1447,10 @@ jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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). */
+ /* 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;
@@ -1596,9 +1614,10 @@ jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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). */
+ /* 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;
@@ -1794,9 +1813,10 @@ jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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). */
+ /* 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;
@@ -1995,9 +2015,10 @@ jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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). */
+ /* 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;
@@ -2173,10 +2194,11 @@ jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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). */
+ /* 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;
@@ -2275,6 +2297,7 @@ jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) * 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.
+ * cK represents sqrt(2) * cos(K*pi/32).
*/
dataptr = data;
@@ -2380,10 +2403,11 @@ jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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). */
+ /* 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;
@@ -2475,12 +2499,13 @@ jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) * 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.
+ * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
*/
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".
+ * rotator "c1" should be "c6".
*/
tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
@@ -2501,43 +2526,43 @@ jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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);
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */
+ 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 */
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */
+ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */
+ 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);
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp0 += z1 + tmp12;
+ tmp3 += z1 + tmp13;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp1 += z1 + tmp13;
+ tmp2 += z1 + tmp12;
+
+ 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[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+PASS1_BITS+1);
dataptr++; /* advance pointer to next column */
}
@@ -2564,10 +2589,11 @@ jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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++) {
@@ -2727,10 +2753,11 @@ jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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++) {
@@ -2866,10 +2893,11 @@ jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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++) {
@@ -2999,17 +3027,19 @@ jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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. */
+ /* 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.
+ * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ */
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".
+ * rotator "c1" should be "c6".
*/
tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]);
@@ -3032,47 +3062,49 @@ jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << (PASS1_BITS+1));
dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << (PASS1_BITS+1));
- z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */
/* 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);
+
+ dataptr[2] = (DCTELEM)
+ RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS-PASS1_BITS-1);
+ dataptr[6] = (DCTELEM)
+ RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */
+ 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 */
+
+ 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 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */
+ 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);
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp0 += z1 + tmp12;
+ tmp3 += z1 + tmp13;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp1 += z1 + tmp13;
+ tmp2 += z1 + tmp12;
+
+ dataptr[1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS-PASS1_BITS-1);
+ dataptr[3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS-PASS1_BITS-1);
+ dataptr[5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS-1);
+ dataptr[7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS-PASS1_BITS-1);
dataptr += DCTSIZE; /* advance pointer to next row */
}
@@ -3080,7 +3112,8 @@ jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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).
+ * 4-point FDCT kernel,
+ * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT].
*/
dataptr = data;
@@ -3099,7 +3132,7 @@ jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Odd part */
- tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */
+ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */
/* Add fudge factor here for final descale. */
tmp0 += ONE << (CONST_BITS+PASS1_BITS-1);
@@ -3134,12 +3167,13 @@ jpeg_fdct_6x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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++) {
@@ -3234,12 +3268,13 @@ jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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]. */
+ /* 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++) {
@@ -3323,10 +3358,12 @@ jpeg_fdct_2x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) */
/* Even part */
+
/* Apply unsigned->signed conversion */
data[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5);
/* Odd part */
+
data[1] = (DCTELEM) ((tmp0 - tmp1) << 5);
}
@@ -3350,9 +3387,11 @@ jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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. */
+ /* 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.
+ * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ */
dataptr = data;
ctr = 0;
@@ -3360,7 +3399,7 @@ jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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".
+ * rotator "c1" should be "c6".
*/
tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]);
@@ -3382,39 +3421,43 @@ jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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);
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */
+ dataptr[2] = (DCTELEM)
+ DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM)
+ DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */
+ 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 */
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */
+ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */
+ 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);
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp0 += z1 + tmp12;
+ tmp3 += z1 + tmp13;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp1 += z1 + tmp13;
+ tmp2 += z1 + tmp12;
+
+ 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[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS-PASS1_BITS);
ctr++;
@@ -3541,10 +3584,11 @@ jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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;
@@ -3721,10 +3765,11 @@ jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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;
@@ -3870,10 +3915,11 @@ jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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;
@@ -4015,11 +4061,13 @@ jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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) [refers to 8-point FDCT].
+ */
dataptr = data;
for (ctr = 0; ctr < DCTSIZE; ctr++) {
@@ -4057,12 +4105,13 @@ jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pass 2: process columns.
* We remove the PASS1_BITS scaling, but leave the results scaled up
* by an overall factor of 8.
+ * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
*/
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".
+ * rotator "c1" should be "c6".
*/
tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
@@ -4084,47 +4133,49 @@ jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) 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);
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); /* c6 */
/* 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);
+ RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS+PASS1_BITS);
dataptr[DCTSIZE*6] = (DCTELEM)
- RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS);
+ RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), /* c2+c6 */
+ 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 */
+
+ 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 = MULTIPLY(tmp12, - FIX_0_390180644); /* -c3+c5 */
+ 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);
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp0 += z1 + tmp12;
+ tmp3 += z1 + tmp13;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp1 += z1 + tmp13;
+ tmp2 += z1 + tmp12;
+
+ dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM) RIGHT_SHIFT(tmp1, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM) RIGHT_SHIFT(tmp2, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*7] = (DCTELEM) RIGHT_SHIFT(tmp3, CONST_BITS+PASS1_BITS);
dataptr++; /* advance pointer to next column */
}
@@ -4150,12 +4201,13 @@ jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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). */
+ /* 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++) {
@@ -4255,9 +4307,10 @@ jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* 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. */
+ /* 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++) {
@@ -4329,18 +4382,23 @@ jpeg_fdct_1x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col) /* Pre-zero output coefficient block. */
MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
- tmp0 = GETJSAMPLE(sample_data[0][start_col]);
- tmp1 = GETJSAMPLE(sample_data[1][start_col]);
+ /* Pass 1: empty. */
- /* We leave the results scaled up by an overall factor of 8.
+ /* Pass 2: process columns.
+ * 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 */
+
+ tmp0 = GETJSAMPLE(sample_data[0][start_col]);
+ tmp1 = GETJSAMPLE(sample_data[1][start_col]);
+
/* Apply unsigned->signed conversion */
data[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5);
/* Odd part */
+
data[DCTSIZE*1] = (DCTELEM) ((tmp0 - tmp1) << 5);
}
diff --git a/plugins/AdvaImg/src/LibJPEG/jidctint.c b/plugins/AdvaImg/src/LibJPEG/jidctint.c index 49ef79f560..6be271c6e7 100644 --- a/plugins/AdvaImg/src/LibJPEG/jidctint.c +++ b/plugins/AdvaImg/src/LibJPEG/jidctint.c @@ -2,7 +2,7 @@ * jidctint.c
*
* Copyright (C) 1991-1998, Thomas G. Lane.
- * Modification developed 2002-2009 by Guido Vollbeding.
+ * Modification developed 2002-2013 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.
*
@@ -165,6 +165,8 @@ /*
* Perform dequantization and inverse DCT on one block of coefficients.
+ *
+ * cK represents sqrt(2) * cos(K*pi/16).
*/
GLOBAL(void)
@@ -184,9 +186,10 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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. */
+ /* 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;
@@ -223,15 +226,16 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, continue;
}
- /* Even part: reverse the even part of the forward DCT. */
- /* The rotator is sqrt(2)*c(-6). */
-
+ /* Even part: reverse the even part of the forward DCT.
+ * The rotator is 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);
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
@@ -256,25 +260,25 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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) */
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */
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) */
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* 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) */
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */
tmp1 += z1 + z3;
tmp2 += z1 + z2;
@@ -288,15 +292,16 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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. */
+ /* 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++) {
@@ -330,15 +335,16 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, }
#endif
- /* Even part: reverse the even part of the forward DCT. */
- /* The rotator is sqrt(2)*c(-6). */
-
+ /* Even part: reverse the even part of the forward DCT.
+ * The rotator is 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);
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
/* Add fudge factor here for final descale. */
z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
@@ -346,7 +352,7 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp0 = (z2 + z3) << CONST_BITS;
tmp1 = (z2 - z3) << CONST_BITS;
-
+
tmp10 = tmp0 + tmp2;
tmp13 = tmp0 - tmp2;
tmp11 = tmp1 + tmp3;
@@ -364,21 +370,21 @@ jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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) */
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */
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) */
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* 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) */
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */
tmp1 += z1 + z3;
tmp2 += z1 + z2;
@@ -2835,9 +2841,11 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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. */
+ /* 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.
+ * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ */
inptr = coef_block;
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
@@ -2851,14 +2859,14 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, * 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;
@@ -2867,23 +2875,24 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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). */
-
+
+ /* Even part: reverse the even part of the forward DCT.
+ * The rotator is 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);
-
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
+
z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
z2 <<= CONST_BITS;
@@ -2893,44 +2902,44 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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) */
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */
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) */
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* 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) */
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* 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);
@@ -2939,7 +2948,7 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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++;
@@ -2948,6 +2957,7 @@ jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -3109,6 +3119,7 @@ jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -3164,6 +3175,7 @@ jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -3304,6 +3316,7 @@ jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -3346,6 +3359,7 @@ jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -3480,6 +3494,7 @@ jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -3520,6 +3535,7 @@ jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -3639,8 +3655,10 @@ jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, SHIFT_TEMPS
/* Pass 1: process columns from input, store into work array.
- * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ * 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;
@@ -3675,31 +3693,34 @@ jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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. */
+ /* 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.
+ * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ */
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). */
+ /* Even part: reverse the even part of the forward DCT.
+ * The rotator is 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);
-
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
+
/* 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;
@@ -3717,21 +3738,21 @@ jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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) */
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */
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) */
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* 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) */
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */
tmp1 += z1 + z3;
tmp2 += z1 + z2;
@@ -3793,6 +3814,7 @@ jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -3823,6 +3845,7 @@ jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -3924,6 +3947,7 @@ jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, * 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;
@@ -3979,7 +4003,7 @@ jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
- INT32 tmp0, tmp10;
+ INT32 tmp0, tmp1;
ISLOW_MULT_TYPE * quantptr;
JSAMPROW outptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
@@ -3994,18 +4018,18 @@ jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */
- tmp10 = DEQUANTIZE(coef_block[0], quantptr[0]);
+ tmp0 = DEQUANTIZE(coef_block[0], quantptr[0]);
/* Add fudge factor here for final descale. */
- tmp10 += ONE << 2;
+ tmp0 += ONE << 2;
/* Odd part */
- tmp0 = DEQUANTIZE(coef_block[1], quantptr[1]);
+ tmp1 = 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];
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK];
}
@@ -4036,6 +4060,7 @@ jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -4134,69 +4159,72 @@ jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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. */
+
+ /* 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.
+ * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ */
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). */
-
+
+ /* Even part: reverse the even part of the forward DCT.
+ * The rotator is 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);
-
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
+
/* 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) */
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */
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) */
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* 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) */
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* 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];
@@ -4221,7 +4249,7 @@ jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr, outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
-
+
wsptr += DCTSIZE; /* advance pointer to next row */
}
}
@@ -4254,6 +4282,7 @@ jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -4341,6 +4370,7 @@ jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -4437,6 +4467,7 @@ jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -4520,6 +4551,7 @@ jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -4601,6 +4633,7 @@ jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -4676,6 +4709,7 @@ jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -4750,9 +4784,11 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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. */
+ /* 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.
+ * 8-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ */
inptr = coef_block;
quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
@@ -4789,16 +4825,17 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, continue;
}
- /* Even part: reverse the even part of the forward DCT. */
- /* The rotator is sqrt(2)*c(-6). */
+ /* Even part: reverse the even part of the forward DCT.
+ * The rotator is 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);
-
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
+
z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
z2 <<= CONST_BITS;
@@ -4808,7 +4845,7 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, tmp0 = z2 + z3;
tmp1 = z2 - z3;
-
+
tmp10 = tmp0 + tmp2;
tmp13 = tmp0 - tmp2;
tmp11 = tmp1 + tmp3;
@@ -4826,21 +4863,21 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, 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) */
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* -c3-c5 */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* -c3+c5 */
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) */
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* -c3+c7 */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* 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) */
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* -c1-c3 */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* c1+c3+c5-c7 */
tmp1 += z1 + z3;
tmp2 += z1 + z2;
@@ -4861,8 +4898,10 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, }
/* Pass 2: process 8 rows from work array, store into output array.
- * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ * 4-point IDCT kernel,
+ * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT].
*/
+
wsptr = workspace;
for (ctr = 0; ctr < 8; ctr++) {
outptr = output_buf[ctr] + output_col;
@@ -4900,7 +4939,7 @@ jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr, outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
CONST_BITS+PASS1_BITS+3)
& RANGE_MASK];
-
+
wsptr += 4; /* advance pointer to next row */
}
}
@@ -4932,6 +4971,7 @@ jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -4974,6 +5014,7 @@ jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* 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;
@@ -5037,6 +5078,7 @@ jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr, * 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;
@@ -5106,7 +5148,7 @@ jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, JCOEFPTR coef_block,
JSAMPARRAY output_buf, JDIMENSION output_col)
{
- INT32 tmp0, tmp10;
+ INT32 tmp0, tmp1;
ISLOW_MULT_TYPE * quantptr;
JSAMPLE *range_limit = IDCT_range_limit(cinfo);
SHIFT_TEMPS
@@ -5117,19 +5159,19 @@ jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr, /* Even part */
- tmp10 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]);
/* Add fudge factor here for final descale. */
- tmp10 += ONE << 2;
+ tmp0 += ONE << 2;
/* Odd part */
- tmp0 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp1 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]);
/* Final output stage */
- output_buf[0][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, 3)
+ output_buf[0][output_col] = range_limit[(int) RIGHT_SHIFT(tmp0 + tmp1, 3)
& RANGE_MASK];
- output_buf[1][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, 3)
+ output_buf[1][output_col] = range_limit[(int) RIGHT_SHIFT(tmp0 - tmp1, 3)
& RANGE_MASK];
}
diff --git a/plugins/AdvaImg/src/LibJPEG/jmorecfg.h b/plugins/AdvaImg/src/LibJPEG/jmorecfg.h index f2600cc8ff..1f645d7ff4 100644 --- a/plugins/AdvaImg/src/LibJPEG/jmorecfg.h +++ b/plugins/AdvaImg/src/LibJPEG/jmorecfg.h @@ -2,7 +2,7 @@ * jmorecfg.h
*
* Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 1997-2012 by Guido Vollbeding.
+ * Modified 1997-2013 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.
*
@@ -15,13 +15,22 @@ /*
* Define BITS_IN_JSAMPLE as either
* 8 for 8-bit sample values (the usual setting)
+ * 9 for 9-bit sample values
+ * 10 for 10-bit sample values
+ * 11 for 11-bit sample values
* 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.
+ * Only 8, 9, 10, 11, and 12 bits sample data precision are supported for
+ * full-feature DCT processing. Further depths up to 16-bit may be added
+ * later for the lossless modes of operation.
+ * Run-time selection and conversion of data precision will be added later
+ * and are currently not supported, sorry.
+ * Exception: The transcoding part (jpegtran) supports all settings in a
+ * single instance, since it operates on the level of DCT coefficients and
+ * not sample values. The DCT coefficients are of the same type (16 bits)
+ * in all cases (see below).
*/
-#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
+#define BITS_IN_JSAMPLE 8 /* use 8, 9, 10, 11, or 12 */
/*
@@ -77,6 +86,48 @@ typedef char JSAMPLE; #endif /* BITS_IN_JSAMPLE == 8 */
+#if BITS_IN_JSAMPLE == 9
+/* JSAMPLE should be the smallest type that will hold the values 0..511.
+ * On nearly all machines "short" will do nicely.
+ */
+
+typedef short JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#define MAXJSAMPLE 511
+#define CENTERJSAMPLE 256
+
+#endif /* BITS_IN_JSAMPLE == 9 */
+
+
+#if BITS_IN_JSAMPLE == 10
+/* JSAMPLE should be the smallest type that will hold the values 0..1023.
+ * On nearly all machines "short" will do nicely.
+ */
+
+typedef short JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#define MAXJSAMPLE 1023
+#define CENTERJSAMPLE 512
+
+#endif /* BITS_IN_JSAMPLE == 10 */
+
+
+#if BITS_IN_JSAMPLE == 11
+/* JSAMPLE should be the smallest type that will hold the values 0..2047.
+ * On nearly all machines "short" will do nicely.
+ */
+
+typedef short JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#define MAXJSAMPLE 2047
+#define CENTERJSAMPLE 1024
+
+#endif /* BITS_IN_JSAMPLE == 11 */
+
+
#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.
@@ -299,11 +350,12 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean; #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.
+/* Note: if you selected more than 8-bit data precision, it is dangerous to
+ * turn off ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only
+ * good for 8-bit precision, so arithmetic coding is recommended for higher
+ * precision. The Huffman encoder normally uses entropy optimization to
+ * compute usable tables for higher precision. Otherwise, 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.)
*/
@@ -314,7 +366,7 @@ typedef enum { FALSE = 0, TRUE = 1 } boolean; #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 IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires DCT_ISLOW)*/
#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? */
diff --git a/plugins/AdvaImg/src/LibJPEG/jpegint.h b/plugins/AdvaImg/src/LibJPEG/jpegint.h index 18404efd00..ec14a1ebc8 100644 --- a/plugins/AdvaImg/src/LibJPEG/jpegint.h +++ b/plugins/AdvaImg/src/LibJPEG/jpegint.h @@ -2,7 +2,7 @@ * jpegint.h
*
* Copyright (C) 1991-1997, Thomas G. Lane.
- * Modified 1997-2011 by Guido Vollbeding.
+ * Modified 1997-2013 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.
*
@@ -211,8 +211,8 @@ struct jpeg_marker_reader { /* 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));
+ JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data));
+ JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
};
/* Inverse DCT (also performs dequantization) */
diff --git a/plugins/AdvaImg/src/LibJPEG/jpeglib.h b/plugins/AdvaImg/src/LibJPEG/jpeglib.h index b5e85d2d73..8eb0085e9a 100644 --- a/plugins/AdvaImg/src/LibJPEG/jpeglib.h +++ b/plugins/AdvaImg/src/LibJPEG/jpeglib.h @@ -2,7 +2,7 @@ * jpeglib.h
*
* Copyright (C) 1991-1998, Thomas G. Lane.
- * Modified 2002-2012 by Guido Vollbeding.
+ * Modified 2002-2013 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.
*
@@ -39,12 +39,12 @@ extern "C" { #define JPEG_LIB_VERSION 90 /* Compatibility version 9.0 */
#define JPEG_LIB_VERSION_MAJOR 9
-#define JPEG_LIB_VERSION_MINOR 0
+#define JPEG_LIB_VERSION_MINOR 1
/* 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.
+ * 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 */
@@ -157,16 +157,21 @@ typedef struct { /* 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)
+ * downsampled_width =
+ * ceil(image_width * Hi/Hmax * DCT_h_scaled_size/block_size)
* 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.
+ /* 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.
+ * For compression, some of the components will need further quantization
+ * scale by factor of 2 after DCT (eg BG_YCC output from normal RGB input).
+ * The field is first set TRUE for decompression, FALSE for compression
+ * in initial_setup, and then adapted in color conversion setup.
*/
- boolean component_needed; /* do we need the value of this component? */
+ boolean component_needed;
/* These values are computed before starting a scan of the component. */
/* The decompressor output side may not use these variables. */
@@ -215,10 +220,12 @@ struct jpeg_marker_struct { typedef enum {
JCS_UNKNOWN, /* error/unspecified */
JCS_GRAYSCALE, /* monochrome */
- JCS_RGB, /* red/green/blue */
- JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
+ JCS_RGB, /* red/green/blue, standard RGB (sRGB) */
+ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV), standard YCC */
JCS_CMYK, /* C/M/Y/K */
- JCS_YCCK /* Y/Cb/Cr/K */
+ JCS_YCCK, /* Y/Cb/Cr/K */
+ JCS_BG_RGB, /* big gamut red/green/blue, bg-sRGB */
+ JCS_BG_YCC /* big gamut Y/Cb/Cr, bg-sYCC */
} J_COLOR_SPACE;
/* Supported color transforms. */
diff --git a/plugins/AdvaImg/src/LibJPEG/jpegtran.c b/plugins/AdvaImg/src/LibJPEG/jpegtran.c index c15664a4f4..f3175aee24 100644 --- a/plugins/AdvaImg/src/LibJPEG/jpegtran.c +++ b/plugins/AdvaImg/src/LibJPEG/jpegtran.c @@ -1,7 +1,7 @@ /*
* jpegtran.c
*
- * Copyright (C) 1995-2012, Thomas G. Lane, Guido Vollbeding.
+ * Copyright (C) 1995-2013, 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.
*
@@ -66,8 +66,8 @@ usage (void) 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, " -grayscale Reduce to grayscale (omit color data)\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
@@ -76,6 +76,7 @@ usage (void) fprintf(stderr, " -transpose Transpose image\n");
fprintf(stderr, " -transverse Transverse transpose image\n");
fprintf(stderr, " -trim Drop non-transformable edge blocks\n");
+ fprintf(stderr, " -wipe WxH+X+Y Wipe (gray out) a rectangular subarea\n");
#endif
fprintf(stderr, "Switches for advanced users:\n");
#ifdef C_ARITH_CODING_SUPPORTED
@@ -187,7 +188,8 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, #if TRANSFORMS_SUPPORTED
if (++argn >= argc) /* advance to next argument */
usage();
- if (! jtransform_parse_crop_spec(&transformoption, argv[argn])) {
+ if (transformoption.crop /* reject multiple crop/wipe requests */ ||
+ ! jtransform_parse_crop_spec(&transformoption, argv[argn])) {
fprintf(stderr, "%s: bogus -crop argument '%s'\n",
progname, argv[argn]);
exit(EXIT_FAILURE);
@@ -336,6 +338,21 @@ parse_switches (j_compress_ptr cinfo, int argc, char **argv, /* Trim off any partial edge MCUs that the transform can't handle. */
transformoption.trim = TRUE;
+ } else if (keymatch(arg, "wipe", 1)) {
+#if TRANSFORMS_SUPPORTED
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (transformoption.crop /* reject multiple crop/wipe requests */ ||
+ ! jtransform_parse_crop_spec(&transformoption, argv[argn])) {
+ fprintf(stderr, "%s: bogus -wipe argument '%s'\n",
+ progname, argv[argn]);
+ exit(EXIT_FAILURE);
+ }
+ select_transform(JXFORM_WIPE);
+#else
+ select_transform(JXFORM_NONE); /* force an error */
+#endif
+
} else {
usage(); /* bogus switch */
}
diff --git a/plugins/AdvaImg/src/LibJPEG/jversion.h b/plugins/AdvaImg/src/LibJPEG/jversion.h index 41726ccbc2..8bd2b522ce 100644 --- a/plugins/AdvaImg/src/LibJPEG/jversion.h +++ b/plugins/AdvaImg/src/LibJPEG/jversion.h @@ -1,7 +1,7 @@ /*
* jversion.h
*
- * Copyright (C) 1991-2013, Thomas G. Lane, Guido Vollbeding.
+ * Copyright (C) 1991-2014, 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.
*
@@ -9,6 +9,6 @@ */
-#define JVERSION "9 13-Jan-2013"
+#define JVERSION "9a 19-Jan-2014"
-#define JCOPYRIGHT "Copyright (C) 2013, Thomas G. Lane, Guido Vollbeding"
+#define JCOPYRIGHT "Copyright (C) 2014, Thomas G. Lane, Guido Vollbeding"
diff --git a/plugins/AdvaImg/src/LibJPEG/libjpeg.txt b/plugins/AdvaImg/src/LibJPEG/libjpeg.txt index b4e1d886c6..b602ab3095 100644 --- a/plugins/AdvaImg/src/LibJPEG/libjpeg.txt +++ b/plugins/AdvaImg/src/LibJPEG/libjpeg.txt @@ -95,8 +95,8 @@ use.) Unsupported ISO options include: * Lossless JPEG
* DNL marker
* Nonintegral subsampling ratios
-We support both 8- and 12-bit data precision, but this is a compile-time
-choice rather than a run-time choice; hence it is difficult to use both
+We support 8-bit to 12-bit data precision, but this is a compile-time choice
+rather than a run-time choice; hence it is difficult to use different
precisions in a single application.
By itself, the library handles only interchange JPEG datastreams --- in
@@ -225,7 +225,7 @@ For best results, source data values should have the precision specified by BITS_IN_JSAMPLE (normally 8 bits). For instance, if you choose to compress
data that's only 6 bits/channel, you should left-justify each value in a
byte before passing it to the compressor. If you need to compress data
-that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 12.
+that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 9 to 12.
(See "Library compile-time options", later.)
@@ -1273,9 +1273,10 @@ Special color spaces The JPEG standard itself is "color blind" and doesn't specify any particular
color space. It is customary to convert color data to a luminance/chrominance
color space before compressing, since this permits greater compression. The
-existing de-facto JPEG file format standards specify YCbCr or grayscale data
-(JFIF), or grayscale, RGB, YCbCr, CMYK, or YCCK (Adobe). For special
-applications such as multispectral images, other color spaces can be used,
+existing JPEG file interchange format standards specify YCbCr or GRAYSCALE
+data (JFIF version 1), GRAYSCALE, RGB, YCbCr, CMYK, or YCCK (Adobe), or BG_RGB
+or BG_YCC (big gamut color spaces, JFIF version 2). For special applications
+such as multispectral images, other color spaces can be used,
but it must be understood that such files will be unportable.
The JPEG library can handle the most common colorspace conversions (namely
@@ -1292,22 +1293,25 @@ jpeg_set_colorspace(). Of course you must select a supported transformation. jccolor.c currently supports the following transformations:
RGB => YCbCr
RGB => GRAYSCALE
+ RGB => BG_YCC
YCbCr => GRAYSCALE
+ YCbCr => BG_YCC
CMYK => YCCK
plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB,
-YCbCr => YCbCr, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN.
-
-The de-facto file format standards (JFIF and Adobe) specify APPn markers that
-indicate the color space of the JPEG file. It is important to ensure that
-these are written correctly, or omitted if the JPEG file's color space is not
-one of the ones supported by the de-facto standards. jpeg_set_colorspace()
-will set the compression parameters to include or omit the APPn markers
-properly, so long as it is told the truth about the JPEG color space.
-For example, if you are writing some random 3-component color space without
-conversion, don't try to fake out the library by setting in_color_space and
-jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN. You may want to write an
-APPn marker of your own devising to identify the colorspace --- see "Special
-markers", below.
+BG_RGB => BG_RGB, YCbCr => YCbCr, BG_YCC => BG_YCC, CMYK => CMYK,
+YCCK => YCCK, and UNKNOWN => UNKNOWN.
+
+The file interchange format standards (JFIF and Adobe) specify APPn markers
+that indicate the color space of the JPEG file. It is important to ensure
+that these are written correctly, or omitted if the JPEG file's color space
+is not one of the ones supported by the interchange standards.
+jpeg_set_colorspace() will set the compression parameters to include or omit
+the APPn markers properly, so long as it is told the truth about the JPEG
+color space. For example, if you are writing some random 3-component color
+space without conversion, don't try to fake out the library by setting
+in_color_space and jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN.
+You may want to write an APPn marker of your own devising to identify
+the colorspace --- see "Special markers", below.
When told that the color space is UNKNOWN, the library will default to using
luminance-quality compression parameters for all color components. You may
@@ -1325,6 +1329,8 @@ set out_color_space to override this. Again, you must select a supported transformation. jdcolor.c currently supports
YCbCr => RGB
YCbCr => GRAYSCALE
+ BG_YCC => RGB
+ BG_YCC => GRAYSCALE
RGB => GRAYSCALE
GRAYSCALE => RGB
YCCK => CMYK
@@ -2585,10 +2591,10 @@ different sizes. If the image dimensions are not a multiple of the MCU size, you must also pad the data correctly (usually, this is done by replicating
the last column and/or row). The data must be padded to a multiple of a DCT
block in each component: that is, each downsampled row must contain a
-multiple of 8 valid samples, and there must be a multiple of 8 sample rows
-for each component. (For applications such as conversion of digital TV
-images, the standard image size is usually a multiple of the DCT block size,
-so that no padding need actually be done.)
+multiple of block_size valid samples, and there must be a multiple of
+block_size sample rows for each component. (For applications such as
+conversion of digital TV images, the standard image size is usually a
+multiple of the DCT block size, so that no padding need actually be done.)
The procedure for compression of raw data is basically the same as normal
compression, except that you call jpeg_write_raw_data() in place of
@@ -2614,22 +2620,22 @@ The scanlines count passed to and returned from jpeg_write_raw_data is measured in terms of the component with the largest v_samp_factor.
jpeg_write_raw_data() processes one MCU row per call, which is to say
-v_samp_factor*DCTSIZE sample rows of each component. The passed num_lines
-value must be at least max_v_samp_factor*DCTSIZE, and the return value will
-be exactly that amount (or possibly some multiple of that amount, in future
-library versions). This is true even on the last call at the bottom of the
-image; don't forget to pad your data as necessary.
+v_samp_factor*block_size sample rows of each component. The passed num_lines
+value must be at least max_v_samp_factor*block_size, and the return value
+will be exactly that amount (or possibly some multiple of that amount, in
+future library versions). This is true even on the last call at the bottom
+of the image; don't forget to pad your data as necessary.
The required dimensions of the supplied data can be computed for each
component as
- cinfo->comp_info[i].width_in_blocks*DCTSIZE samples per row
- cinfo->comp_info[i].height_in_blocks*DCTSIZE rows in image
+ cinfo->comp_info[i].width_in_blocks*block_size samples per row
+ cinfo->comp_info[i].height_in_blocks*block_size rows in image
after jpeg_start_compress() has initialized those fields. If the valid data
is smaller than this, it must be padded appropriately. For some sampling
factors and image sizes, additional dummy DCT blocks are inserted to make
the image a multiple of the MCU dimensions. The library creates such dummy
blocks itself; it does not read them from your supplied data. Therefore you
-need never pad by more than DCTSIZE samples. An example may help here.
+need never pad by more than block_size samples. An example may help here.
Assume 2h2v downsampling of YCbCr data, that is
cinfo->comp_info[0].h_samp_factor = 2 for Y
cinfo->comp_info[0].v_samp_factor = 2
@@ -2671,8 +2677,8 @@ Then call jpeg_read_raw_data() in place of jpeg_read_scanlines(). The decompression process is otherwise the same as usual.
jpeg_read_raw_data() returns one MCU row per call, and thus you must pass a
-buffer of at least max_v_samp_factor*DCTSIZE scanlines (scanline counting is
-the same as for raw-data compression). The buffer you pass must be large
+buffer of at least max_v_samp_factor*block_size scanlines (scanline counting
+is the same as for raw-data compression). The buffer you pass must be large
enough to hold the actual data plus padding to DCT-block boundaries. As with
compression, any entirely dummy DCT blocks are not processed so you need not
allocate space for them, but the total scanline count includes them. The
@@ -2928,10 +2934,10 @@ This does not count any memory allocated by the application, such as a buffer to hold the final output image.
The above figures are valid for 8-bit JPEG data precision and a machine with
-32-bit ints. For 12-bit JPEG data, double the size of the strip buffers and
-quantization pixel buffer. The "fixed-size" data will be somewhat smaller
-with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual
-color spaces will require different amounts of space.
+32-bit ints. For 9-bit to 12-bit JPEG data, double the size of the strip
+buffers and quantization pixel buffer. The "fixed-size" data will be
+somewhat smaller with 16-bit ints, larger with 64-bit ints. Also, CMYK
+or other unusual color spaces will require different amounts of space.
The full-image coefficient and pixel buffers, if needed at all, do not
have to be fully RAM resident; you can have the library use temporary
@@ -2953,27 +2959,34 @@ Library compile-time options A number of compile-time options are available by modifying jmorecfg.h.
-The JPEG standard provides for both the baseline 8-bit DCT process and
-a 12-bit DCT process. The IJG code supports 12-bit JPEG if you define
-BITS_IN_JSAMPLE as 12 rather than 8. Note that this causes JSAMPLE to be
-larger than a char, so it affects the surrounding application's image data.
-The sample applications cjpeg and djpeg can support 12-bit mode only for PPM
-and GIF file formats; you must disable the other file formats to compile a
-12-bit cjpeg or djpeg. (install.txt has more information about that.)
-At present, a 12-bit library can handle *only* 12-bit images, not both
-precisions. (If you need to include both 8- and 12-bit libraries in a single
-application, you could probably do it by defining NEED_SHORT_EXTERNAL_NAMES
-for just one of the copies. You'd have to access the 8-bit and 12-bit copies
-from separate application source files. This is untested ... if you try it,
-we'd like to hear whether it works!)
-
-Note that a 12-bit library always compresses in Huffman optimization mode,
-in order to generate valid Huffman tables. This is necessary because our
-default Huffman tables only cover 8-bit data. If you need to output 12-bit
-files in one pass, you'll have to supply suitable default Huffman tables.
-You may also want to supply your own DCT quantization tables; the existing
-quality-scaling code has been developed for 8-bit use, and probably doesn't
-generate especially good tables for 12-bit.
+The IJG code currently supports 8-bit to 12-bit sample data precision by
+defining BITS_IN_JSAMPLE as 8, 9, 10, 11, or 12.
+Note that a value larger than 8 causes JSAMPLE to be larger than a char,
+so it affects the surrounding application's image data.
+The sample applications cjpeg and djpeg can support deeper than 8-bit data
+only for PPM and GIF file formats; you must disable the other file formats
+to compile a 9-bit to 12-bit cjpeg or djpeg. (install.txt has more
+information about that.)
+Run-time selection and conversion of data precision are currently not
+supported and may be added later.
+Exception: The transcoding part (jpegtran) supports all settings in a
+single instance, since it operates on the level of DCT coefficients and
+not sample values.
+(If you need to include an 8-bit library and a 9-bit to 12-bit library for
+compression or decompression in a single application, you could probably do
+it by defining NEED_SHORT_EXTERNAL_NAMES for just one of the copies. You'd
+have to access the 8-bit and the 9-bit to 12-bit copies from separate
+application source files. This is untested ... if you try it, we'd like to
+hear whether it works!)
+
+Note that the standard Huffman tables are only valid for 8-bit data precision.
+If you selected more than 8-bit data precision, cjpeg uses arithmetic coding
+by default. The Huffman encoder normally uses entropy optimization to
+compute usable tables for higher precision. Otherwise, you'll have to
+supply different default Huffman tables. You may also want to supply your
+own DCT quantization tables; the existing quality-scaling code has been
+developed for 8-bit use, and probably doesn't generate especially good tables
+for 9-bit to 12-bit.
The maximum number of components (color channels) in the image is determined
by MAX_COMPONENTS. The JPEG standard allows up to 255 components, but we
diff --git a/plugins/AdvaImg/src/LibJPEG/structure.txt b/plugins/AdvaImg/src/LibJPEG/structure.txt index ae9f89f6df..04d957746e 100644 --- a/plugins/AdvaImg/src/LibJPEG/structure.txt +++ b/plugins/AdvaImg/src/LibJPEG/structure.txt @@ -1,6 +1,6 @@ IJG JPEG LIBRARY: SYSTEM ARCHITECTURE
-Copyright (C) 1991-2012, Thomas G. Lane, Guido Vollbeding.
+Copyright (C) 1991-2013, 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.
@@ -170,16 +170,16 @@ can be simplified a little if they work on padded data: it's not necessary to have special cases at the right and bottom edges. Therefore the interface
buffer is always an integral number of blocks wide and high, and we expect
compression preprocessing to pad the source data properly. Padding will occur
-only to the next block (N-sample) boundary. In an interleaved-scan situation,
-additional dummy blocks may be used to fill out MCUs, but the MCU assembly and
-disassembly logic will create or discard these blocks internally. (This is
-advantageous for speed reasons, since we avoid DCTing the dummy blocks.
-It also permits a small reduction in file size, because the compressor can
-choose dummy block contents so as to minimize their size in compressed form.
-Finally, it makes the interface buffer specification independent of whether
-the file is actually interleaved or not.) Applications that wish to deal
-directly with the downsampled data must provide similar buffering and padding
-for odd-sized images.
+only to the next block (block_size-sample) boundary. In an interleaved-scan
+situation, additional dummy blocks may be used to fill out MCUs, but the MCU
+assembly and disassembly logic will create or discard these blocks internally.
+(This is advantageous for speed reasons, since we avoid DCTing the dummy
+blocks. It also permits a small reduction in file size, because the
+compressor can choose dummy block contents so as to minimize their size
+in compressed form. Finally, it makes the interface buffer specification
+independent of whether the file is actually interleaved or not.)
+Applications that wish to deal directly with the downsampled data must
+provide similar buffering and padding for odd-sized images.
*** Poor man's object-oriented programming ***
@@ -345,9 +345,10 @@ The objects shown above are: require context rows above and below the current row group; the
preprocessing controller is responsible for supplying these rows via proper
buffering. The downsampler is responsible for edge expansion at the right
- edge (i.e., extending each sample row to a multiple of N samples); but the
- preprocessing controller is responsible for vertical edge expansion (i.e.,
- duplicating the bottom sample row as needed to make a multiple of N rows).
+ edge (i.e., extending each sample row to a multiple of block_size samples);
+ but the preprocessing controller is responsible for vertical edge expansion
+ (i.e., duplicating the bottom sample row as needed to make a multiple of
+ block_size rows).
* Coefficient controller: buffer controller for the DCT-coefficient data.
This controller handles MCU assembly, including insertion of dummy DCT
@@ -651,8 +652,8 @@ contain quantized coefficients everywhere outside the DCT/IDCT subsystems. quantization a la JPEG Part 3.)
Notice that the allocation unit is now a row of 8x8 coefficient blocks,
-corresponding to N rows of samples. Otherwise the structure is much the same
-as for samples, and for the same reasons.
+corresponding to block_size rows of samples. Otherwise the structure
+is much the same as for samples, and for the same reasons.
On machines where malloc() can't handle a request bigger than 64Kb, this data
structure limits us to rows of less than 512 JBLOCKs, or a picture width of
diff --git a/plugins/AdvaImg/src/LibJPEG/transupp.c b/plugins/AdvaImg/src/LibJPEG/transupp.c index e0af04cbd8..0524d1fc29 100644 --- a/plugins/AdvaImg/src/LibJPEG/transupp.c +++ b/plugins/AdvaImg/src/LibJPEG/transupp.c @@ -1,7 +1,7 @@ /*
* transupp.c
*
- * Copyright (C) 1997-2012, Thomas G. Lane, Guido Vollbeding.
+ * Copyright (C) 1997-2013, 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.
*
@@ -114,6 +114,116 @@ do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo, LOCAL(void)
+do_crop_ext (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.
+ * Extension: If the destination size is larger than the source, we fill in
+ * the extra area with zero (neutral gray). Note we also have to zero partial
+ * iMCUs at the right and bottom edge of the source image area in this case.
+ */
+{
+ JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
+ JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
+ int ci, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ 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 (dstinfo->jpeg_height > srcinfo->output_height) {
+ if (dst_blk_y < y_crop_blocks ||
+ dst_blk_y >= comp_height + y_crop_blocks) {
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ FMEMZERO(dst_buffer[offset_y],
+ compptr->width_in_blocks * SIZEOF(JBLOCK));
+ }
+ continue;
+ }
+ 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);
+ } else {
+ 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 (dstinfo->jpeg_width > srcinfo->output_width) {
+ if (x_crop_blocks > 0) {
+ FMEMZERO(dst_buffer[offset_y],
+ x_crop_blocks * SIZEOF(JBLOCK));
+ }
+ jcopy_block_row(src_buffer[offset_y],
+ dst_buffer[offset_y] + x_crop_blocks,
+ comp_width);
+ if (compptr->width_in_blocks > comp_width + x_crop_blocks) {
+ FMEMZERO(dst_buffer[offset_y] +
+ comp_width + x_crop_blocks,
+ (compptr->width_in_blocks -
+ comp_width - x_crop_blocks) * SIZEOF(JBLOCK));
+ }
+ } else {
+ jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
+ dst_buffer[offset_y],
+ compptr->width_in_blocks);
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_wipe (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays,
+ JDIMENSION drop_width, JDIMENSION drop_height)
+/* Wipe - drop content of specified area, fill with zero (neutral gray) */
+{
+ JDIMENSION comp_width, comp_height;
+ JDIMENSION blk_y, x_wipe_blocks, y_wipe_blocks;
+ int ci, offset_y;
+ JBLOCKARRAY buffer;
+ jpeg_component_info *compptr;
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = drop_width * compptr->h_samp_factor;
+ comp_height = drop_height * compptr->v_samp_factor;
+ x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
+ y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
+ for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) {
+ buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y + y_wipe_blocks,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ FMEMZERO(buffer[offset_y] + x_wipe_blocks,
+ comp_width * SIZEOF(JBLOCK));
+ }
+ }
+ }
+}
+
+
+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)
@@ -888,7 +998,8 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, /* Determine number of components in output image */
if (info->force_grayscale &&
- srcinfo->jpeg_color_space == JCS_YCbCr &&
+ (srcinfo->jpeg_color_space == JCS_YCbCr ||
+ srcinfo->jpeg_color_space == JCS_BG_YCC) &&
srcinfo->num_components == 3)
/* We'll only process the first component */
info->num_components = 1;
@@ -965,39 +1076,81 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, 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)
+ if (info->crop_width_set == JCROP_UNSET) {
+ if (info->crop_xoffset >= info->output_width)
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
info->crop_width = info->output_width - info->crop_xoffset;
- if (info->crop_height_set == JCROP_UNSET)
+ } else {
+ /* Check for crop extension */
+ if (info->crop_width > info->output_width) {
+ /* Crop extension does not work when transforming! */
+ if (info->transform != JXFORM_NONE ||
+ info->crop_xoffset >= info->crop_width ||
+ info->crop_xoffset > info->crop_width - info->output_width)
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
+ } else {
+ if (info->crop_xoffset >= info->output_width ||
+ info->crop_width <= 0 ||
+ info->crop_xoffset > info->output_width - info->crop_width)
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
+ }
+ }
+ if (info->crop_height_set == JCROP_UNSET) {
+ if (info->crop_yoffset >= info->output_height)
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
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);
+ } else {
+ /* Check for crop extension */
+ if (info->crop_height > info->output_height) {
+ /* Crop extension does not work when transforming! */
+ if (info->transform != JXFORM_NONE ||
+ info->crop_yoffset >= info->crop_height ||
+ info->crop_yoffset > info->crop_height - info->output_height)
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
+ } else {
+ if (info->crop_yoffset >= info->output_height ||
+ info->crop_height <= 0 ||
+ 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
+ if (info->crop_xoffset_set != JCROP_NEG)
xoffset = info->crop_xoffset;
- if (info->crop_yoffset_set == JCROP_NEG)
- yoffset = info->output_height - info->crop_height - info->crop_yoffset;
+ else if (info->crop_width > info->output_width) /* crop extension */
+ xoffset = info->crop_width - info->output_width - info->crop_xoffset;
else
+ xoffset = info->output_width - info->crop_width - info->crop_xoffset;
+ if (info->crop_yoffset_set != JCROP_NEG)
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 if (info->crop_height > info->output_height) /* crop extension */
+ yoffset = info->crop_height - info->output_height - info->crop_yoffset;
else
- info->output_height =
- info->crop_height + (yoffset % info->iMCU_sample_height);
+ yoffset = info->output_height - info->crop_height - info->crop_yoffset;
+ /* Now adjust so that upper left corner falls at an iMCU boundary */
+ if (info->transform == JXFORM_WIPE) {
+ /* Ensure the effective wipe region will cover the requested */
+ info->drop_width = (JDIMENSION) jdiv_round_up
+ ((long) (info->crop_width + (xoffset % info->iMCU_sample_width)),
+ (long) info->iMCU_sample_width);
+ info->drop_height = (JDIMENSION) jdiv_round_up
+ ((long) (info->crop_height + (yoffset % info->iMCU_sample_height)),
+ (long) info->iMCU_sample_height);
+ } else {
+ /* Ensure the effective crop region will cover the requested */
+ if (info->crop_width_set == JCROP_FORCE ||
+ info->crop_width > info->output_width)
+ 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->crop_height > info->output_height)
+ 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;
@@ -1013,7 +1166,9 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, transpose_it = FALSE;
switch (info->transform) {
case JXFORM_NONE:
- if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
+ if (info->x_crop_offset != 0 || info->y_crop_offset != 0 ||
+ info->output_width > srcinfo->output_width ||
+ info->output_height > srcinfo->output_height)
need_workspace = TRUE;
/* No workspace needed if neither cropping nor transforming */
break;
@@ -1067,6 +1222,8 @@ jtransform_request_workspace (j_decompress_ptr srcinfo, need_workspace = TRUE;
transpose_it = TRUE;
break;
+ case JXFORM_WIPE:
+ break;
}
/* Allocate workspace if needed.
@@ -1327,12 +1484,13 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo, {
/* 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
+ /* First, ensure we have YCC 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 &&
+ if ((((dstinfo->jpeg_color_space == JCS_YCbCr ||
+ dstinfo->jpeg_color_space == JCS_BG_YCC) &&
dstinfo->num_components == 3) ||
(dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
dstinfo->num_components == 1)) &&
@@ -1427,7 +1585,11 @@ jtransform_execute_transform (j_decompress_ptr srcinfo, */
switch (info->transform) {
case JXFORM_NONE:
- if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
+ if (info->output_width > srcinfo->output_width ||
+ info->output_height > srcinfo->output_height)
+ do_crop_ext(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, dst_coef_arrays);
+ else 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;
@@ -1463,6 +1625,10 @@ jtransform_execute_transform (j_decompress_ptr srcinfo, do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
src_coef_arrays, dst_coef_arrays);
break;
+ case JXFORM_WIPE:
+ do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, info->drop_width, info->drop_height);
+ break;
}
}
diff --git a/plugins/AdvaImg/src/LibJPEG/transupp.h b/plugins/AdvaImg/src/LibJPEG/transupp.h index 6e4d65afbe..28a1a9cb7a 100644 --- a/plugins/AdvaImg/src/LibJPEG/transupp.h +++ b/plugins/AdvaImg/src/LibJPEG/transupp.h @@ -1,7 +1,7 @@ /*
* transupp.h
*
- * Copyright (C) 1997-2011, Thomas G. Lane, Guido Vollbeding.
+ * Copyright (C) 1997-2013, 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.
*
@@ -51,14 +51,17 @@ *
* 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
+ * flip transforms, lossless crop is restricted by the current JPEG format: the
+ * upper left corner of the selected region must fall on an iMCU boundary. If
+ * this does not hold for the given crop parameters, we silently move the upper
+ * left corner up and/or left to make it so, simultaneously increasing the
+ * region dimensions to keep the lower right crop corner unchanged. (Thus, the
* output image covers at least the requested region, but may cover more.)
* The adjustment of the region dimensions may be optionally disabled.
*
+ * A complementary lossless-wipe option is provided to discard (gray out) data
+ * inside a given image region while losslessly preserving what is outside.
+ *
* 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
@@ -102,7 +105,8 @@ typedef enum { 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_ROT_270, /* 270-degree clockwise (or 90 ccw) */
+ JXFORM_WIPE /* wipe */
} JXFORM_CODE;
/*
@@ -130,7 +134,7 @@ typedef struct { 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 */
+ boolean crop; /* if TRUE, crop or wipe source image */
/* Crop parameters: application need not set these unless crop is TRUE.
* These can be filled in by jtransform_parse_crop_spec().
@@ -151,6 +155,8 @@ typedef struct { JDIMENSION output_height;
JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */
JDIMENSION y_crop_offset;
+ JDIMENSION drop_width; /* drop/wipe dimensions measured in iMCUs */
+ JDIMENSION drop_height;
int iMCU_sample_width; /* destination iMCU size */
int iMCU_sample_height;
} jpeg_transform_info;
diff --git a/plugins/AdvaImg/src/LibJPEG/usage.txt b/plugins/AdvaImg/src/LibJPEG/usage.txt index c8ea77cd26..ca9f7d74a4 100644 --- a/plugins/AdvaImg/src/LibJPEG/usage.txt +++ b/plugins/AdvaImg/src/LibJPEG/usage.txt @@ -158,10 +158,10 @@ file size is about the same --- often a little smaller. Switches for advanced users:
- -arithmetic Use arithmetic coding. CAUTION: arithmetic coded JPEG
- is not yet widely implemented, so many decoders will
- be unable to view an arithmetic coded JPEG file at
- all.
+ -arithmetic Use arithmetic coding.
+ CAUTION: arithmetic coded JPEG is not yet widely
+ implemented, so many decoders will be unable to
+ view an arithmetic coded JPEG file at all.
-block N Set DCT block size. All N from 1 to 16 are possible.
Default is 8 (baseline format).
@@ -188,6 +188,25 @@ Switches for advanced users: so many decoders will be unable to view a reversible
color transformed JPEG file at all.
+ -bgycc Create big gamut YCC JPEG file.
+ In this type of encoding the color difference
+ components are quantized further by a factor of 2
+ compared to the normal Cb/Cr values, thus creating
+ space to allow larger color values with higher
+ saturation than the normal gamut limits to be encoded.
+ In order to compensate for the loss of color fidelity
+ compared to a normal YCC encoded file, the color
+ quantization tables can be adjusted accordingly.
+ For example, cjpeg -bgycc -quality 80,90 will give
+ similar results as cjpeg -quality 80.
+ CAUTION: For correct decompression a decoder with big
+ gamut YCC support (JFIF version 2) is required.
+ An old decoder may or may not display a big gamut YCC
+ encoded JPEG file, depending on JFIF version check
+ and corresponding warning/error configuration.
+ In case of a granted decompression the old decoder
+ will display the image with half saturated colors.
+
-dct int Use integer DCT method (default).
-dct fast Use fast integer DCT (less accurate).
-dct float Use floating-point DCT method.
@@ -387,7 +406,8 @@ quality settings to make very small JPEG files; the percentage improvement is often a lot more than it is on larger files. (At present, -optimize
mode is always selected when generating progressive JPEG files.)
-GIF input files are no longer supported, to avoid the Unisys LZW patent.
+GIF input files are no longer supported, to avoid the Unisys LZW patent
+(now expired).
(Conversion of GIF files to JPEG is usually a bad idea anyway.)
@@ -415,8 +435,9 @@ it may run out of memory even with -maxmemory 0. In that case you can still decompress, with some loss of image quality, by specifying -onepass for
one-pass quantization.
-To avoid the Unisys LZW patent, djpeg produces uncompressed GIF files. These
-are larger than they should be, but are readable by standard GIF decoders.
+To avoid the Unisys LZW patent (now expired), djpeg produces uncompressed GIF
+files. These are larger than they should be, but are readable by standard GIF
+decoders.
HINTS FOR BOTH PROGRAMS
@@ -533,14 +554,20 @@ image region but losslessly preserves what is inside. Like the rotate and flip transforms, lossless crop is restricted by the current JPEG format: the
upper left corner of the selected region must fall on an iMCU boundary. If
this does not hold for the given crop parameters, we silently move the upper
-left corner up and/or left to make it so, simultaneously increasing the region
-dimensions to keep the lower right crop corner unchanged. (Thus, the output
-image covers at least the requested region, but may cover more.)
+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.
The image can be losslessly cropped by giving the switch:
-crop WxH+X+Y Crop to a rectangular subarea of width W, height H
starting at point X,Y.
+A complementary lossless-wipe option is provided to discard (gray out) data
+inside a given image region while losslessly preserving what is outside:
+ -wipe WxH+X+Y Wipe (gray out) a rectangular subarea of
+ width W, height H starting at point X,Y.
+
Other not-strictly-lossless transformation switches are:
-grayscale Force grayscale output.
diff --git a/plugins/AdvaImg/src/LibPNG/ANNOUNCE b/plugins/AdvaImg/src/LibPNG/ANNOUNCE index 6ea2c2abcc..bfd62d13c3 100644 --- a/plugins/AdvaImg/src/LibPNG/ANNOUNCE +++ b/plugins/AdvaImg/src/LibPNG/ANNOUNCE @@ -1,5 +1,5 @@ -Libpng 1.6.3 - July 18, 2013
+Libpng 1.6.10 - March 6, 2014
This is a public release of libpng, intended for use in production codes.
@@ -8,106 +8,80 @@ Files available for download: Source files with LF line endings (for Unix/Linux) and with a
"configure" script
- libpng-1.6.3.tar.xz (LZMA-compressed, recommended)
- libpng-1.6.3.tar.gz
+ libpng-1.6.10.tar.xz (LZMA-compressed, recommended)
+ libpng-1.6.10.tar.gz
Source files with CRLF line endings (for Windows), without the
"configure" script
- lpng163.7z (LZMA-compressed, recommended)
- lpng163.zip
+ lpng1610.7z (LZMA-compressed, recommended)
+ lpng1610.zip
Other information:
- libpng-1.6.3-README.txt
- libpng-1.6.3-LICENSE.txt
+ libpng-1.6.10-README.txt
+ libpng-1.6.10-LICENSE.txt
+ libpng-1.6.10-*.asc (armored detached GPG signatures)
-Changes since the last public release (1.6.2):
-
- Revised stack marking in arm/filter_neon.S and configure.ac.
- Ensure that NEON filter stuff is completely disabled when switched 'off'.
- Previously the ARM NEON specific files were still built if the option
- was switched 'off' as opposed to being explicitly disabled.
- Test for 'arm*' not just 'arm' in the host_cpu configure variable.
- Rebuilt the configure scripts.
- Expanded manual paragraph about writing private chunks, particularly
- the need to call png_set_keep_unknown_chunks() when writing them.
- Avoid dereferencing NULL pointer possibly returned from
- png_create_write_struct() (Andrew Church).
- Calculate our own zlib windowBits when decoding rather than trusting the
- CMF bytes in the PNG datastream.
- Added an option to force maximum window size for inflating, which was
- the behavior of libpng15 and earlier.
- Added png-fix-itxt and png-fix-too-far-back to the built programs and
- removed warnings from the source code and timepng that are revealed as
- a result.
- Detect wrong libpng versions linked to png-fix-too-far-back, which currently
- only works with libpng versions that can be made to reliably fail when
- the deflate data contains an out-of-window reference. This means only
- 1.6 and later.
- Fixed gnu issues: g++ needs a static_cast, gcc 4.4.7 has a broken warning
- message which it is easier to work round than ignore.
- Updated contrib/pngminus/pnm2png.c (Paul Stewart):
- Check for EOF
- Ignore "#" delimited comments in input file to pnm2png.c.
- Fixed whitespace handling
- Added a call to png_set_packing()
- Initialize dimension values so if sscanf fails at least we have known
- invalid values.
- Attempt to detect configuration issues with png-fix-too-far-back, which
- requires both the correct libpng and the correct zlib to function
- correctly.
- Check ZLIB_VERNUM for mismatches, enclose #error in quotes
- Added information in the documentation about problems with and fixes for
- the bad CRC and bad iTXt chunk situations.
- Allow contrib/pngminus/pnm2png.c to compile without WRITE_INVERT and
- WRITE_PACK supported (writes error message that it can't read P1 or
- Improved png-fix-too-far-back usage message, added --suffix option.
- Revised contrib/pngminim/*/makefile to generate pnglibconf.h with the
- right zlib header files.
- Separated CPPFLAGS and CFLAGS in contrib/pngminim/*/makefile
- Removed a redundant test in png_set_IHDR().
- Added set(CMAKE_CONFIGURATION_TYPES ...) to CMakeLists.txt (Andrew Hundt)
- Deleted set(CMAKE_BUILD_TYPE) block from CMakeLists.txt
- Enclose the prototypes for the simplified write API in
- #ifdef PNG_STDIO_SUPPORTED/#endif
- Make ARM NEON support work at compile time (not just configure time).
- This moves the test on __ARM_NEON__ into pngconf.h to avoid issues when
- using a compiler that compiles for multiple architectures at one time.
- Removed PNG_FILTER_OPTIMIZATIONS and PNG_ARM_NEON_SUPPORTED from
- pnglibconf.h, allowing more of the decisions to be made internally
- (pngpriv.h) during the compile. Without this, symbol prefixing is broken
- under certain circumstances on ARM platforms. Now only the API parts of
- the optimizations ('check' vs 'api') are exposed in the public header files
- except that the new setting PNG_ARM_NEON_OPT documents how libpng makes the
- decision about whether or not to use the optimizations.
- Protect symbol prefixing against CC/CPPFLAGS/CFLAGS useage.
- Previous iOS/Xcode fixes for the ARM NEON optimizations moved the test
- on __ARM_NEON__ from configure time to compile time. This breaks symbol
- prefixing because the definition of the special png_init_filter_functions
- call was hidden at configure time if the relevant compiler arguments are
- passed in CFLAGS as opposed to CC. This change attempts to avoid all
- the confusion that would result by declaring the init function even when
- it is not used, so that it will always get prefixed.
- Revised libpng.3 so that "doclifter" can process it.
- Revised example.c to illustrate use of PNG_DEFAULT_sRGB and PNG_GAMMA_MAC_18
- as parameters for png_set_gamma(). These have been available since
- libpng-1.5.4.
- Renamed contrib/tools/png-fix-too-far-back.c to pngfix.c and revised it
- to check all compressed chunks known to libpng.
- Updated documentation to show default behavior of benign errors correctly.
- Only compile ARM code when PNG_READ_SUPPORTED is defined.
- Fixed undefined behavior in contrib/tools/pngfix.c and added new strip
- option. pngfix relied on undefined behavior and even a simple change from
- gcc to g++ caused it to fail. The new strip option 'unsafe' has been
- implemented and is the default if --max is given. Option names have
- been clarified, with --strip=transform now stripping the bKGD chunk,
- which was stripped previously with --strip=unused.
- Added all documented chunk types to pngpriv.h
- Unified pngfix.c source with libpng17.
- Revised manual about changes in iTXt chunk handling made in libpng-1.6.0.
- Added "/* SAFE */" comments in pngrutil.c and pngrtran.c where warnings
- may be erroneously issued by code-checking applications.
+Changes since the last public release (1.6.9):
+ Backported changes from libpng-1.7.0beta30 and beta31:
+ Fixed a large number of instances where PNGCBAPI was omitted from
+ function definitions.
+ Added pngimage test program for png_read_png() and png_write_png()
+ with two new test scripts.
+ Removed dependence on !PNG_READ_EXPAND_SUPPORTED for calling
+ png_set_packing() in png_read_png().
+ Fixed combination of ~alpha with shift. On read invert alpha, processing
+ occurred after shift processing, which causes the final values to be
+ outside the range that should be produced by the shift. Reversing the
+ order on read makes the two transforms work together correctly and mirrors
+ the order used on write.
+ Do not read invalid sBIT chunks. Previously libpng only checked sBIT
+ values on write, so a malicious PNG writer could therefore cause
+ the read code to return an invalid sBIT chunk, which might lead to
+ application errors or crashes. Such chunks are now skipped (with
+ chunk_benign_error).
+ Make png_read_png() and png_write_png() prototypes in png.h depend
+ upon PNG_READ_SUPPORTED and PNG_WRITE_SUPPORTED.
+ Support builds with unsupported PNG_TRANSFORM_* values. All of the
+ PNG_TRANSFORM_* values are always defined in png.h and, because they
+ are used for both read and write in some cases, it is not reliable
+ to #if out ones that are totally unsupported. This change adds error
+ detection in png_read_image() and png_write_image() to do a
+ png_app_error() if the app requests something that cannot be done
+ and it adds corresponding code to pngimage.c to handle such options
+ by not attempting to test them.
+ Moved redefines of png_error(), png_warning(), png_chunk_error(),
+ and png_chunk_warning() from pngpriv.h to png.h to make them visible
+ to libpng-calling applications.
+ Moved OS dependent code from arm/arm_init.c, to allow the included
+ implementation of the ARM NEON discovery function to be set at
+ build-time and provide sample implementations from the current code in the
+ contrib/arm-neon subdirectory. The __linux__ code has also been changed to
+ compile and link on Android by using /proc/cpuinfo, and the old linux code
+ is in contrib/arm-neon/linux-auxv.c. The new code avoids POSIX and Linux
+ dependencies apart from opening /proc/cpuinfo and is C90 compliant.
+ Check for info_ptr == NULL early in png_read_end() so we don't need to
+ run all the png_handle_*() and depend on them to return if info_ptr == NULL.
+ This improves the performance of png_read_end(png_ptr, NULL) and makes
+ it more robust against future programming errors.
+ Check for __has_extension before using it in pngconf.h, to
+ support older Clang versions (Jeremy Sequoia).
+ Treat CRC error handling with png_set_crc_action(), instead of with
+ png_set_benign_errors(), which has been the case since libpng-1.6.0beta18.
+ Use a user warning handler in contrib/gregbook/readpng2.c instead of default,
+ so warnings will be put on stderr even if libpng has CONSOLE_IO disabled.
+ Added png_ptr->process_mode = PNG_READ_IDAT_MODE in png_push_read_chunk
+ after recognizing the IDAT chunk, which avoids an infinite loop while
+ reading a datastream whose first IDAT chunk is of zero-length.
+ This fixes CERT VU#684412 and CVE-2014-0333.
+ Don't recognize known sRGB profiles as sRGB if they have been hacked,
+ but don't reject them and don't issue a copyright violation warning.
+ Moved some documentation from png.h to libpng.3 and libpng-manual.txt
+ Minor editing of contrib/arm-neon/README and contrib/examples/*.c
+ Fixed typos in the manual and in scripts/pnglibconf.dfa (CFLAGS -> CPPFLAGS
+ and PNG_USR_CONFIG -> PNG_USER_CONFIG).
+ Un-deprecated png_data_freer().
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit
@@ -116,3 +90,4 @@ to subscribe) or to glennrp at users.sourceforge.net
Glenn R-P
+#endif
diff --git a/plugins/AdvaImg/src/LibPNG/CHANGES b/plugins/AdvaImg/src/LibPNG/CHANGES index 0d6e5feea3..8d9a4f3556 100644 --- a/plugins/AdvaImg/src/LibPNG/CHANGES +++ b/plugins/AdvaImg/src/LibPNG/CHANGES @@ -4618,6 +4618,262 @@ Version 1.6.3 [July 18, 2013] Added "/* SAFE */" comments in pngrutil.c and pngrtran.c where warnings
may be erroneously issued by code-checking applications.
+Version 1.6.4beta01 [August 21, 2013]
+ Added information about png_set_options() to the manual.
+ Delay calling png_init_filter_functions() until a row with nonzero filter
+ is found.
+
+Version 1.6.4beta02 [August 30, 2013]
+ Fixed inconsistent conditional compilation of png_chunk_unknown_handling()
+ prototype, definition, and usage. Made it depend on
+ PNG_HANDLE_AS_UNKNOWN_SUPPORTED everywhere.
+
+Version 1.6.4rc01 [September 5, 2013]
+ No changes.
+
+Version 1.6.4 [September 12, 2013]
+ No changes.
+
+Version 1.6.5 [September 14, 2013]
+ Removed two stray lines of code from arm/arm_init.c.
+
+Version 1.6.6 [September 16, 2013]
+ Removed two stray lines of code from arm/arm_init.c, again.
+
+Version 1.6.7beta01 [September 30, 2013]
+ Revised unknown chunk code to correct several bugs in the NO_SAVE_/NO_WRITE
+ combination
+ Allow HANDLE_AS_UNKNOWN to work when other options are configured off. Also
+ fixed the pngminim makefiles to work when $(MAKEFLAGS) contains stuff
+ which terminates the make options (as by default in recent versions of
+ Gentoo).
+ Avoid up-cast warnings in pngvalid.c. On ARM the alignment requirements of
+ png_modifier are greater than that of png_store and as a consequence
+ compilation of pngvalid.c results in a warning about increased alignment
+ requirements because of the bare cast to (png_modifier*). The code is safe,
+ because the pointer is known to point to a stack allocated png_modifier,
+ but this change avoids the warning.
+ Fixed default behavior of ARM_NEON_API. If the ARM NEON API option was
+ compiled without the CHECK option it defaulted to on, not off.
+ Check user callback behavior in pngunknown.c. Previous versions compiled
+ if SAVE_UNKNOWN was not available but did nothing since the callback
+ was never implemented.
+ Merged pngunknown.c with 1.7 version and back ported 1.7 improvements/fixes
+
+Version 1.6.7beta02 [October 12, 2013]
+ Made changes for compatibility with automake 1.14:
+ 1) Added the 'compile' program to the list of programs that must be cleaned
+ in autogen.sh
+ 2) Added 'subdir-objects' which causes .c files in sub-directories to be
+ compiled such that the corresponding .o files are also in the
+ sub-directory. This is because automake 1.14 warns that the
+ current behavior of compiling to the top level directory may be removed
+ in the future.
+ 3) Updated dependencies on pnglibconf.h to match the new .o locations and
+ added all the files in contrib/libtests and contrib/tools that depend
+ on pnglibconf.h
+ 4) Added 'BUILD_SOURCES = pnglibconf.h'; this is the automake recommended
+ way of handling the dependencies of sources that are machine generated;
+ unfortunately it only works if the user does 'make all' or 'make check',
+ so the dependencies (3) are still required.
+ Cleaned up (char*) casts of zlib messages. The latest version of the Intel C
+ compiler complains about casting a string literal as (char*), so copied the
+ treatment of z_const from the library code into pngfix.c
+ Simplified error message code in pngunknown. The simplification has the
+ useful side effect of avoiding a bogus warning generated by the latest
+ version of the Intel C compiler (it objects to
+ condition ? string-literal : string-literal).
+ Make autogen.sh work with automake 1.13 as well as 1.14. Do this by always
+ removing the 1.14 'compile' script but never checking for it.
+
+Version 1.6.7beta03 [October 19, 2013]
+ Added ARMv8 support (James Yu <james.yu at linaro.org>). Added file
+ arm/filter_neon_intrinsics.c; enable with -mfpu=neon.
+ Revised pngvalid to generate size images with as many filters as it can
+ manage, limited by the number of rows.
+ Cleaned up ARM NEON compilation handling. The tests are now in pngpriv.h
+ and detect the broken GCC compilers.
+
+Version 1.6.7beta04 [October 26, 2013]
+ Allow clang derived from older GCC versions to use ARM intrinsics. This
+ causes all clang builds that use -mfpu=neon to use the intrinsics code,
+ not the assembler code. This has only been tested on iOS 7. It may be
+ necessary to exclude some earlier clang versions but this seems unlikely.
+ Changed NEON implementation selection mechanism. This allows assembler
+ or intrinsics to be turned on at compile time during the build by defining
+ PNG_ARM_NEON_IMPLEMENTATION to the correct value (2 or 1). This macro
+ is undefined by default and the build type is selected in pngpriv.h.
+
+Version 1.6.7rc01 [November 2, 2013]
+ No changes.
+
+Version 1.6.7rc02 [November 7, 2013]
+ Fixed #include in filter_neon_intrinsics.c and ctype macros. The ctype char
+ checking macros take an unsigned char argument, not a signed char.
+
+Version 1.6.7 [November 14, 2013]
+ No changes.
+
+Version 1.6.8beta01 [November 24, 2013]
+ Moved prototype for png_handle_unknown() in pngpriv.h outside of
+ the #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED/#endif block.
+ Added "-Wall" to CFLAGS in contrib/pngminim/*/makefile
+ Conditionally compile some unused functions reported by -Wall in
+ pngminim.
+ Fixed 'minimal' builds. Various obviously useful minimal configurations
+ don't build because of missing contrib/libtests test programs and
+ overly complex dependencies in scripts/pnglibconf.dfa. This change
+ adds contrib/conftest/*.dfa files that can be used in automatic build
+ scripts to ensure that these configurations continue to build.
+ Enabled WRITE_INVERT and WRITE_PACK in contrib/pngminim/encoder.
+ Fixed pngvalid 'fail' function declaration on the Intel C Compiler.
+ This reverts to the previous 'static' implementation and works round
+ the 'unused static function' warning by using PNG_UNUSED().
+
+Version 1.6.8beta02 [November 30, 2013]
+ Removed or marked PNG_UNUSED some harmless "dead assignments" reported
+ by clang scan-build.
+ Changed tabs to 3 spaces in png_debug macros and changed '"%s"m'
+ to '"%s" m' to improve portability among compilers.
+ Changed png_free_default() to free() in pngtest.c
+
+Version 1.6.8rc01 [December 12, 2013]
+ Tidied up pngfix inits and fixed pngtest no-write builds.
+
+Version 1.6.8rc02 [December 14, 2013]
+ Handle zero-length PLTE chunk or NULL palette with png_error()
+ instead of png_chunk_report(), which by default issues a warning
+ rather than an error, leading to later reading from a NULL pointer
+ (png_ptr->palette) in png_do_expand_palette(). This is CVE-2013-6954
+ and VU#650142. Libpng-1.6.1 through 1.6.7 are vulnerable.
+ Libpng-1.6.0 and earlier do not have this bug.
+
+Version 1.6.8 [December 19, 2013]
+ No changes.
+
+Version 1.6.9beta01 [December 26, 2013]
+ Bookkeeping: Moved functions around (no changes). Moved transform
+ function definitions before the place where they are called so that
+ they can be made static. Move the intrapixel functions and the
+ grayscale palette builder out of the png?tran.c files. The latter
+ isn't a transform function and is no longer used internally, and the
+ former MNG specific functions are better placed in pngread/pngwrite.c
+ Made transform implementation functions static. This makes the internal
+ functions called by png_do_{read|write}_transformations static. On an
+ x86-64 DLL build (Gentoo Linux) this reduces the size of the text
+ segment of the DLL by 1208 bytes, about 0.6%. It also simplifies
+ maintenance by removing the declarations from pngpriv.h and allowing
+ easier changes to the internal interfaces.
+ Rebuilt configure scripts with automake-1.14.1 and autoconf-2.69
+ in the tar distributions.
+
+Version 1.6.9beta02 [January 1, 2014]
+ Added checks for libpng 1.5 to pngvalid.c. This supports the use of
+ this version of pngvalid in libpng 1.5
+ Merged with pngvalid.c from libpng-1.7 changes to create a single
+ pngvalid.c
+ Removed #error macro from contrib/tools/pngfix.c (Thomas Klausner).
+ Merged pngrio.c, pngtrans.c, pngwio.c, and pngerror.c with libpng-1.7.0
+ Merged libpng-1.7.0 changes to make no-interlace configurations work
+ with test programs.
+ Revised pngvalid.c to support libpng 1.5, which does not support the
+ PNG_MAXIMUM_INFLATE_WINDOW option, so #define it out when appropriate in
+ pngvalid.c
+ Allow unversioned links created on install to be disabled in configure.
+ In configure builds 'make install' changes/adds links like png.h
+ and libpng.a to point to the newly installed, versioned, files (e.g.
+ libpng17/png.h and libpng17.a). Three new configure options and some
+ rearrangement of Makefile.am allow creation of these links to be disabled.
+
+Version 1.6.9beta03 [January 10, 2014]
+ Removed potentially misleading warning from png_check_IHDR().
+
+Version 1.6.9beta04 [January 20, 2014]
+ Updated scripts/makefile.* to use CPPFLAGS (Cosmin).
+ Added clang attribute support (Cosmin).
+
+Version 1.6.9rc01 [January 28, 2014]
+ No changes.
+
+Version 1.6.9rc02 [January 30, 2014]
+ Quiet an uninitialized memory warning from VC2013 in png_get_png().
+
+Version 1.6.9 [February 6, 2014]
+
+Version 1.6.10beta01 [February 9, 2014]
+ Backported changes from libpng-1.7.0beta30 and beta31:
+ Fixed a large number of instances where PNGCBAPI was omitted from
+ function definitions.
+ Added pngimage test program for png_read_png() and png_write_png()
+ with two new test scripts.
+ Removed dependence on !PNG_READ_EXPAND_SUPPORTED for calling
+ png_set_packing() in png_read_png().
+ Fixed combination of ~alpha with shift. On read invert alpha, processing
+ occurred after shift processing, which causes the final values to be
+ outside the range that should be produced by the shift. Reversing the
+ order on read makes the two transforms work together correctly and mirrors
+ the order used on write.
+ Do not read invalid sBIT chunks. Previously libpng only checked sBIT
+ values on write, so a malicious PNG writer could therefore cause
+ the read code to return an invalid sBIT chunk, which might lead to
+ application errors or crashes. Such chunks are now skipped (with
+ chunk_benign_error).
+ Make png_read_png() and png_write_png() prototypes in png.h depend
+ upon PNG_READ_SUPPORTED and PNG_WRITE_SUPPORTED.
+ Support builds with unsupported PNG_TRANSFORM_* values. All of the
+ PNG_TRANSFORM_* values are always defined in png.h and, because they
+ are used for both read and write in some cases, it is not reliable
+ to #if out ones that are totally unsupported. This change adds error
+ detection in png_read_image() and png_write_image() to do a
+ png_app_error() if the app requests something that cannot be done
+ and it adds corresponding code to pngimage.c to handle such options
+ by not attempting to test them.
+
+Version 1.6.10beta02 [February 23, 2014]
+ Moved redefines of png_error(), png_warning(), png_chunk_error(),
+ and png_chunk_warning() from pngpriv.h to png.h to make them visible
+ to libpng-calling applications.
+ Moved OS dependent code from arm/arm_init.c, to allow the included
+ implementation of the ARM NEON discovery function to be set at
+ build-time and provide sample implementations from the current code in the
+ contrib/arm-neon subdirectory. The __linux__ code has also been changed to
+ compile and link on Android by using /proc/cpuinfo, and the old linux code
+ is in contrib/arm-neon/linux-auxv.c. The new code avoids POSIX and Linux
+ dependencies apart from opening /proc/cpuinfo and is C90 compliant.
+ Check for info_ptr == NULL early in png_read_end() so we don't need to
+ run all the png_handle_*() and depend on them to return if info_ptr == NULL.
+ This improves the performance of png_read_end(png_ptr, NULL) and makes
+ it more robust against future programming errors.
+ Check for __has_extension before using it in pngconf.h, to
+ support older Clang versions (Jeremy Sequoia).
+ Treat CRC error handling with png_set_crc_action(), instead of with
+ png_set_benign_errors(), which has been the case since libpng-1.6.0beta18.
+ Use a user warning handler in contrib/gregbook/readpng2.c instead of default,
+ so warnings will be put on stderr even if libpng has CONSOLE_IO disabled.
+ Added png_ptr->process_mode = PNG_READ_IDAT_MODE in png_push_read_chunk
+ after recognizing the IDAT chunk, which avoids an infinite loop while
+ reading a datastream whose first IDAT chunk is of zero-length.
+ This fixes CERT VU#684412 and CVE-2014-0333.
+ Don't recognize known sRGB profiles as sRGB if they have been hacked,
+ but don't reject them and don't issue a copyright violation warning.
+
+Version 1.6.10beta03 [February 25, 2014]
+ Moved some documentation from png.h to libpng.3 and libpng-manual.txt
+ Minor editing of contrib/arm-neon/README and contrib/examples/*.c
+
+Version 1.6.10rc01 [February 27, 2014]
+ Fixed typos in the manual and in scripts/pnglibconf.dfa (CFLAGS -> CPPFLAGS
+ and PNG_USR_CONFIG -> PNG_USER_CONFIG).
+
+Version 1.6.10rc02 [February 28, 2014]
+ Removed unreachable return statement after png_chunk_error()
+ in pngrutil.c
+
+Version 1.6.10rc03 [March 4, 2014]
+ Un-deprecated png_data_freer().
+
+Version 1.6.10 [March 6, 2014]
+
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/plugins/AdvaImg/src/LibPNG/LICENSE b/plugins/AdvaImg/src/LibPNG/LICENSE index 5b289d1a01..ea1841e479 100644 --- a/plugins/AdvaImg/src/LibPNG/LICENSE +++ b/plugins/AdvaImg/src/LibPNG/LICENSE @@ -10,8 +10,8 @@ this sentence. This code is released under the libpng license.
-libpng versions 1.2.6, August 15, 2004, through 1.6.3, July 18, 2013, are
-Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson, and are
+libpng versions 1.2.6, August 15, 2004, through 1.6.10, March 6, 2014, are
+Copyright (c) 2004, 2006-2014 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
@@ -108,4 +108,4 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson
glennrp at users.sourceforge.net
-July 18, 2013
+March 6, 2014
diff --git a/plugins/AdvaImg/src/LibPNG/README b/plugins/AdvaImg/src/LibPNG/README index a60e6b70fe..d7b19371f9 100644 --- a/plugins/AdvaImg/src/LibPNG/README +++ b/plugins/AdvaImg/src/LibPNG/README @@ -1,4 +1,4 @@ -README for libpng version 1.6.3 - July 18, 2013 (shared library 16.0)
+README for libpng version 1.6.10 - March 6, 2014 (shared library 16.0)
See the note about version numbers near the top of png.h
See INSTALL for instructions on how to install libpng.
@@ -121,7 +121,7 @@ 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 eighteen years now, and it is official and
+been discussing PNG for nineteen 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.
diff --git a/plugins/AdvaImg/src/LibPNG/TODO b/plugins/AdvaImg/src/LibPNG/TODO index b1660a413a..4659b70d81 100644 --- a/plugins/AdvaImg/src/LibPNG/TODO +++ b/plugins/AdvaImg/src/LibPNG/TODO @@ -10,6 +10,7 @@ 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).
+Make profile checking optional via a png_set_something() call.
Man pages for function calls.
Better documentation.
Better filter selection
diff --git a/plugins/AdvaImg/src/LibPNG/configure b/plugins/AdvaImg/src/LibPNG/configure index c654a18976..4dbd0267d7 100644 --- a/plugins/AdvaImg/src/LibPNG/configure +++ b/plugins/AdvaImg/src/LibPNG/configure @@ -1,14 +1,14 @@ echo "
There is no \"configure\" script in this distribution (*.zip or *.7z) of
- libpng-1.6.3.
+ libpng-1.6.10.
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.6.3.tar.gz, libpng-1.6.3.tar.xz, or libpng-1.6.3.tar.bz2
+ libpng-1.6.10.tar.gz, libpng-1.6.10.tar.xz, or libpng-1.6.10.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
diff --git a/plugins/AdvaImg/src/LibPNG/libpng-manual.txt b/plugins/AdvaImg/src/LibPNG/libpng-manual.txt index 326cebb2da..c8cd50393e 100644 --- a/plugins/AdvaImg/src/LibPNG/libpng-manual.txt +++ b/plugins/AdvaImg/src/LibPNG/libpng-manual.txt @@ -1,9 +1,9 @@ libpng-manual.txt - A description on how to use and modify libpng
- libpng version 1.6.3 - July 18, 2013
+ libpng version 1.6.10 - March 6, 2014
Updated and distributed by Glenn Randers-Pehrson
<glennrp at users.sourceforge.net>
- Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ Copyright (c) 1998-2014 Glenn Randers-Pehrson
This document is released under the libpng license.
For conditions of distribution and use, see the disclaimer
@@ -11,9 +11,9 @@ libpng-manual.txt - A description on how to use and modify libpng Based on:
- libpng versions 0.97, January 1998, through 1.6.3 - July 18, 2013
+ libpng versions 0.97, January 1998, through 1.6.10 - March 6, 2014
Updated and distributed by Glenn Randers-Pehrson
- Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ Copyright (c) 1998-2014 Glenn Randers-Pehrson
libpng 1.0 beta 6 version 0.96 May 28, 1997
Updated and distributed by Andreas Dilger
@@ -274,10 +274,10 @@ 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
+C. Configuration using PNG_USER_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
+If -DPNG_USER_CONFIG is added to the CPPFLAGS 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.
@@ -712,12 +712,12 @@ 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*/);
+ png_set_gamma(png_ptr, screen_gamma, output_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);
+ PNG_FP_1*output_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
@@ -740,11 +740,75 @@ situations: 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
+values further because this avoids the need to decode and re-encode 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 output_gamma value 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 values can be passed to either the fixed or floating
+point APIs, but the floating point API will also accept floating point
+values.
+
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
@@ -769,11 +833,11 @@ 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.
+ 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
@@ -790,11 +854,35 @@ 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.
+probably doesn't!). They '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. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
+described below (the latter being the two common names for associated alpha
+color channels). Note that PNG files always contain non-associated color
+channels; png_set_alpha_mode() with one of the modes causes the decoder to
+convert the pixels to an associated form before returning them to your
+application.
+
+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.
+
+ 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.
@@ -823,9 +911,8 @@ 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
+ 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.
@@ -844,18 +931,16 @@ 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.
+ PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD; however, all component
+values, including the alpha channel are gamma encoded. 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. 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():
@@ -886,6 +971,89 @@ 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.
+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.
+
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
@@ -1216,7 +1384,7 @@ png_set_rgb_to_gray()). png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
- file_srgb_intent - the rendering intent (PNG_INFO_sRGB)
+ 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
@@ -2166,10 +2334,15 @@ how pngvalid.c does it. 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
+low-level interface, you can finish reading the file.
+
+If you want to use a different crc action for handling CRC errors in
+chunks after the image data, you can call png_set_crc_action()
+again at this point.
+
+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);
@@ -2185,6 +2358,9 @@ separate. 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.
+If you do this, libpng will not process any chunks after IDAT other than
+skipping over them and perhaps (depending on whether you have called
+png_set_crc_action) checking their CRCs while looking for the IEND chunk.
png_read_end(png_ptr, (png_infop)NULL);
@@ -3535,7 +3711,7 @@ The simplified API, which became available in libpng-1.6.0, hides the details of both libpng and the PNG file format itself.
It allows PNG files to be read into a very limited number of
in-memory bitmap formats or to be written from the same formats. If these
-formats do not accomodate your needs then you can, and should, use the more
+formats do not accommodate your needs then you can, and should, use the more
sophisticated APIs above - these support a wide variety of in-memory formats
and a wide variety of sophisticated transformations to those formats as well
as a wide variety of APIs to manipulate ancilliary information.
@@ -4393,6 +4569,9 @@ 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.
+Support for the sCAL, iCCP, iTXt, and sPLT chunks was added at libpng-1.0.6;
+however, iTXt support was not enabled by default.
+
Starting with version 1.0.7, you can find out which version of the library
you are using at run-time:
@@ -4609,7 +4788,7 @@ 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
+was re-enabled, 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
@@ -4621,12 +4800,13 @@ XI. 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.
+The incorrect macro was removed from libpng-1.4.5.
-Checking for invalid palette index on read or write was added at libpng
-1.5.10. When an invalid index is found, libpng issues a benign error.
-This is enabled by default because this condition is an error according
-to the PNG specification, Clause 11.3.2, but the error can be ignored in
-each png_ptr with
+Checking for invalid palette index on write was added at libpng
+1.5.10. If a pixel contains an invalid (out-of-range) index libpng issues
+a benign error. This is enabled by default because this condition is an
+error according to the PNG specification, Clause 11.3.2, but the error can
+be ignored in each png_ptr with
png_set_check_for_invalid_index(png_ptr, allowed);
@@ -4725,7 +4905,10 @@ 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.
+internal floating point calculations. Starting with libpng-1.5.0, both
+of these functions are present when PNG_sCAL_SUPPORTED is defined. Prior
+to libpng-1.5.0, their presence also depended upon PNG_FIXED_POINT_SUPPORTED
+being defined and PNG_FLOATING_POINT_SUPPORTED not being defined.
Applications no longer need to include the optional distribution header
file pngusr.h or define the corresponding macros during application
@@ -4745,15 +4928,10 @@ 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
+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
@@ -4767,7 +4945,10 @@ 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.
+chopping. In libpng-1.5.4, the PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+macro became PNG_READ_SCALE_16_TO_8_SUPPORTED, and the PNG_READ_16_TO_8
+macro became PNG_READ_STRIP_16_TO_8_SUPPORTED, to enable the two
+png_set_*_16_to_8() functions separately.
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
@@ -4789,6 +4970,9 @@ limits are now png_user_chunk_cache_max 0 (unlimited) 128
png_user_chunk_malloc_max 0 (unlimited) 8,000,000
+The png_set_option() function (and the "options" member of the png struct) was
+added to libpng-1.5.15.
+
B. Changes to the build and configuration of libpng
Details of internal changes to the library code can be found in the CHANGES
@@ -4933,7 +5117,7 @@ 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
+CPPFLAGS 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.
@@ -4990,7 +5174,6 @@ The following API are now DEPRECATED: png_info_init_3()
png_convert_to_rfc1123() which has been replaced
with png_convert_to_rfc1123_buffer()
- png_data_freer()
png_malloc_default()
png_free_default()
png_reset_zstream()
@@ -5012,10 +5195,11 @@ where "rp" indicates a "restricted pointer". Error detection in some chunks has improved; in particular the iCCP chunk
reader now does pretty complete validation of the basic format. Some bad
-profiles that were previously accepted are now rejected, in particular the
-very old broken Microsoft/HP sRGB profile. The PNG spec requirement that
-only grayscale profiles may appear in images with color type 0 or 4 and that
-even if the image only contains gray pixels, only RGB profiles may appear
+profiles that were previously accepted are now accepted with a warning or
+rejected, depending upon the png_set_benign_errors() setting, in particular the
+very old broken Microsoft/HP 3144-byte sRGB profile. The PNG spec requirement
+that only grayscale profiles may appear in images with color type 0 or 4 and
+that even if the image only contains gray pixels, only RGB profiles may appear
in images with color type 2, 3, or 6, is now enforced. The sRGB chunk
is allowed to appear in images with any color type.
@@ -5024,7 +5208,9 @@ an empty language field or an empty translated keyword. Both of these are allowed by the PNG specification, so these warnings are no longer issued.
The library now issues an error if the application attempts to set a
-transform after it calls png_read_update_info().
+transform after it calls png_read_update_info() or if it attempts to call
+both png_read_update_info() and png_start_read_image() or to call either
+of them more than once.
The default condition for benign_errors is now to treat benign errors as
warnings while reading and as errors while writing.
@@ -5045,14 +5231,19 @@ The machine-generated configure files are no longer included in branches libpng16 and later of the GIT repository. They continue to be included
in the tarball releases, however.
-Libpng-1.6.0 and later use the CMF bytes at the beginning of the IDAT stream
-to set the size of the sliding window for reading instead of using the default
-32-kbyte sliding window size. It was discovered that there are hundreds of PNG
-files in the wild that have incorrect CMF bytes that cause libpng to now issue
-a "too far back" error and reject the file. Libpng-1.6.3 provides a way to
-revert to the libpng-1.5.x behavior (ignoring the CMF bytes and using a
-32-kbyte sliding window), and provides a tool
-(contrib/tools/png-fix-too-far-back) for optimizing the CMF bytes
+Libpng-1.6.0 through 1.6.2 used the CMF bytes at the beginning of the IDAT
+stream to set the size of the sliding window for reading instead of using the
+default 32-kbyte sliding window size. It was discovered that there are
+hundreds of PNG files in the wild that have incorrect CMF bytes that caused
+libpng to issue a "too far back" error and reject the file. Libpng-1.6.3 and
+later calculate their own safe CMF from the image dimensions, provide a way
+to revert to the libpng-1.5.x behavior (ignoring the CMF bytes and using a
+32-kbyte sliding window), by using
+
+ png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW,
+ PNG_OPTION_ON);
+
+and provide a tool (contrib/tools/pngfix) for optimizing the CMF bytes
correctly.
Libpng-1.6.0 and libpng-1.6.1 wrote uncompressed iTXt chunks with the wrong
@@ -5158,6 +5349,9 @@ exported functions are marked with PNGAPI: body;
}
+The return type and decorations are placed on a separate line
+ahead of the function name, as illustrated above.
+
The prototypes for all exported functions appear in png.h,
above the comment that says
@@ -5222,13 +5416,13 @@ Other rules can be inferred by inspecting the libpng source. XVI. Y2K Compliance in libpng
-July 18, 2013
+March 6, 2014
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.6.3 are Y2K compliant. It is my belief that earlier
+upward through 1.6.10 are Y2K compliant. It is my belief that earlier
versions were also Y2K compliant.
Libpng only has two year fields. One is a 2-byte unsigned integer
diff --git a/plugins/AdvaImg/src/LibPNG/libpng.3 b/plugins/AdvaImg/src/LibPNG/libpng.3 index 7f2f4cff20..a84c3b6b7e 100644 --- a/plugins/AdvaImg/src/LibPNG/libpng.3 +++ b/plugins/AdvaImg/src/LibPNG/libpng.3 @@ -1,6 +1,6 @@ -.TH LIBPNG 3 "July 18, 2013"
+.TH LIBPNG 3 "March 6, 2014"
.SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.3
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.10
.SH SYNOPSIS
\fB
#include <png.h>\fP
@@ -504,10 +504,10 @@ 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.6.3 - July 18, 2013
+ libpng version 1.6.10 - March 6, 2014
Updated and distributed by Glenn Randers-Pehrson
<glennrp at users.sourceforge.net>
- Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ Copyright (c) 1998-2014 Glenn Randers-Pehrson
This document is released under the libpng license.
For conditions of distribution and use, see the disclaimer
@@ -515,9 +515,9 @@ libpng-manual.txt - A description on how to use and modify libpng Based on:
- libpng versions 0.97, January 1998, through 1.6.3 - July 18, 2013
+ libpng versions 0.97, January 1998, through 1.6.10 - March 6, 2014
Updated and distributed by Glenn Randers-Pehrson
- Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ Copyright (c) 1998-2014 Glenn Randers-Pehrson
libpng 1.0 beta 6 version 0.96 May 28, 1997
Updated and distributed by Andreas Dilger
@@ -672,7 +672,7 @@ 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
+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.
@@ -713,7 +713,7 @@ 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
+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
@@ -721,7 +721,7 @@ 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
+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.
@@ -778,10 +778,10 @@ 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
+C. Configuration using PNG_USER_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
+If \-DPNG_USER_CONFIG is added to the CPPFLAGS 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.
@@ -1010,7 +1010,7 @@ input stream. You must supply the function unknown chunk structure, process it, and return one
of the following: */
- return (-n); /* chunk had an error */
+ return (\-n); /* chunk had an error */
return (0); /* did not recognize */
return (n); /* success */
}
@@ -1061,7 +1061,7 @@ 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
+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.
@@ -1151,7 +1151,7 @@ callback function: .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.
+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
@@ -1216,12 +1216,12 @@ 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*/);
+ png_set_gamma(png_ptr, screen_gamma, output_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);
+ PNG_FP_1*output_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
@@ -1244,11 +1244,75 @@ situations: 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
+values further because this avoids the need to decode and re-encode 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 output_gamma value 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 values can be passed to either the fixed or floating
+point APIs, but the floating point API will also accept floating point
+values.
+
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
@@ -1273,11 +1337,11 @@ 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.
+ 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
@@ -1294,11 +1358,35 @@ 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.
+probably doesn't!). They '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. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
+described below (the latter being the two common names for associated alpha
+color channels). Note that PNG files always contain non-associated color
+channels; png_set_alpha_mode() with one of the modes causes the decoder to
+convert the pixels to an associated form before returning them to your
+application.
+
+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.
+
+ 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.
@@ -1327,9 +1415,8 @@ 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
+ 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.
@@ -1348,18 +1435,16 @@ 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.
+ PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD; however, all component
+values, including the alpha channel are gamma encoded. 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. 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():
@@ -1390,6 +1475,89 @@ 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.
+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.
+
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
@@ -1720,7 +1888,7 @@ png_set_rgb_to_gray()). png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
- file_srgb_intent - the rendering intent (PNG_INFO_sRGB)
+ 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
@@ -2670,10 +2838,15 @@ 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
+low-level interface, you can finish reading the file.
+
+If you want to use a different crc action for handling CRC errors in
+chunks after the image data, you can call png_set_crc_action()
+again at this point.
+
+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);
@@ -2689,6 +2862,9 @@ separate. 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.
+If you do this, libpng will not process any chunks after IDAT other than
+skipping over them and perhaps (depending on whether you have called
+png_set_crc_action) checking their CRCs while looking for the IEND chunk.
png_read_end(png_ptr, (png_infop)NULL);
@@ -2723,13 +2899,13 @@ point to libpng-allocated storage with the following function: or simply PNG_FREE_ALL
seq - sequence number of item to be freed
- (-1 for all items)
+ (\-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
+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".
@@ -3130,7 +3306,7 @@ 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
+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.
@@ -3970,13 +4146,13 @@ point to libpng-allocated storage with the following function: or simply PNG_FREE_ALL
seq - sequence number of item to be freed
- (-1 for all items)
+ (\-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
+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".
@@ -4039,7 +4215,7 @@ The simplified API, which became available in libpng-1.6.0, hides the details of both libpng and the PNG file format itself.
It allows PNG files to be read into a very limited number of
in-memory bitmap formats or to be written from the same formats. If these
-formats do not accomodate your needs then you can, and should, use the more
+formats do not accommodate your needs then you can, and should, use the more
sophisticated APIs above - these support a wide variety of in-memory formats
and a wide variety of sophisticated transformations to those formats as well
as a wide variety of APIs to manipulate ancilliary information.
@@ -4829,7 +5005,7 @@ this version of libpng, but if you insert some they will be printed. Starting with libpng-1.6.0, you can configure libpng (when using the
"configure" script) to prefix all exported symbols by means of the
-configuration option "--with-libpng-prefix=FOO_", where FOO_ can be any
+configuration option "\-\-with\-libpng\-prefix=FOO_", where FOO_ can be any
string beginning with a letter and containing only uppercase
and lowercase letters, digits, and the underscore (i.e., a C language
identifier). This creates a set of macros in pnglibconf.h, so this is
@@ -4898,6 +5074,9 @@ 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.
+Support for the sCAL, iCCP, iTXt, and sPLT chunks was added at libpng-1.0.6;
+however, iTXt support was not enabled by default.
+
Starting with version 1.0.7, you can find out which version of the library
you are using at run-time:
@@ -5114,7 +5293,7 @@ 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
+was re-enabled, 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
@@ -5126,12 +5305,13 @@ We removed the trailing '.' from the warning and error messages. 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.
+The incorrect macro was removed from libpng-1.4.5.
-Checking for invalid palette index on read or write was added at libpng
-1.5.10. When an invalid index is found, libpng issues a benign error.
-This is enabled by default because this condition is an error according
-to the PNG specification, Clause 11.3.2, but the error can be ignored in
-each png_ptr with
+Checking for invalid palette index on write was added at libpng
+1.5.10. If a pixel contains an invalid (out-of-range) index libpng issues
+a benign error. This is enabled by default because this condition is an
+error according to the PNG specification, Clause 11.3.2, but the error can
+be ignored in each png_ptr with
png_set_check_for_invalid_index(png_ptr, allowed);
@@ -5152,7 +5332,7 @@ reading, and after png_write_png() or png_write_image() while writing. int max_palette = png_get_palette_max(png_ptr, info_ptr);
-This will return the maximum palette index found in the image, or "-1" if
+This will return the maximum palette index found in the image, or "\-1" if
the palette was not checked, or "0" if no palette was found. Note that this
does not account for any palette index used by ancillary chunks such as the
bKGD chunk; you must check those separately to determine the maximum
@@ -5230,7 +5410,10 @@ 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.
+internal floating point calculations. Starting with libpng-1.5.0, both
+of these functions are present when PNG_sCAL_SUPPORTED is defined. Prior
+to libpng-1.5.0, their presence also depended upon PNG_FIXED_POINT_SUPPORTED
+being defined and PNG_FLOATING_POINT_SUPPORTED not being defined.
Applications no longer need to include the optional distribution header
file pngusr.h or define the corresponding macros during application
@@ -5250,15 +5433,10 @@ 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
+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
@@ -5272,7 +5450,10 @@ 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.
+chopping. In libpng-1.5.4, the PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+macro became PNG_READ_SCALE_16_TO_8_SUPPORTED, and the PNG_READ_16_TO_8
+macro became PNG_READ_STRIP_16_TO_8_SUPPORTED, to enable the two
+png_set_*_16_to_8() functions separately.
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
@@ -5294,6 +5475,9 @@ limits are now png_user_chunk_cache_max 0 (unlimited) 128
png_user_chunk_malloc_max 0 (unlimited) 8,000,000
+The png_set_option() function (and the "options" member of the png struct) was
+added to libpng-1.5.15.
+
B. Changes to the build and configuration of libpng
Details of internal changes to the library code can be found in the CHANGES
@@ -5438,7 +5622,7 @@ 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
+CPPFLAGS 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.
@@ -5495,7 +5679,6 @@ The following API are now DEPRECATED: png_info_init_3()
png_convert_to_rfc1123() which has been replaced
with png_convert_to_rfc1123_buffer()
- png_data_freer()
png_malloc_default()
png_free_default()
png_reset_zstream()
@@ -5517,10 +5700,11 @@ where "rp" indicates a "restricted pointer". Error detection in some chunks has improved; in particular the iCCP chunk
reader now does pretty complete validation of the basic format. Some bad
-profiles that were previously accepted are now rejected, in particular the
-very old broken Microsoft/HP sRGB profile. The PNG spec requirement that
-only grayscale profiles may appear in images with color type 0 or 4 and that
-even if the image only contains gray pixels, only RGB profiles may appear
+profiles that were previously accepted are now accepted with a warning or
+rejected, depending upon the png_set_benign_errors() setting, in particular the
+very old broken Microsoft/HP 3144-byte sRGB profile. The PNG spec requirement
+that only grayscale profiles may appear in images with color type 0 or 4 and
+that even if the image only contains gray pixels, only RGB profiles may appear
in images with color type 2, 3, or 6, is now enforced. The sRGB chunk
is allowed to appear in images with any color type.
@@ -5529,7 +5713,9 @@ an empty language field or an empty translated keyword. Both of these are allowed by the PNG specification, so these warnings are no longer issued.
The library now issues an error if the application attempts to set a
-transform after it calls png_read_update_info().
+transform after it calls png_read_update_info() or if it attempts to call
+both png_read_update_info() and png_start_read_image() or to call either
+of them more than once.
The default condition for benign_errors is now to treat benign errors as
warnings while reading and as errors while writing.
@@ -5550,14 +5736,19 @@ The machine-generated configure files are no longer included in branches libpng16 and later of the GIT repository. They continue to be included
in the tarball releases, however.
-Libpng-1.6.0 and later use the CMF bytes at the beginning of the IDAT stream
-to set the size of the sliding window for reading instead of using the default
-32-kbyte sliding window size. It was discovered that there are hundreds of PNG
-files in the wild that have incorrect CMF bytes that cause libpng to now issue
-a "too far back" error and reject the file. Libpng-1.6.3 provides a way to
-revert to the libpng-1.5.x behavior (ignoring the CMF bytes and using a
-32-kbyte sliding window), and provides a tool
-(contrib/tools/png-fix-too-far-back) for optimizing the CMF bytes
+Libpng-1.6.0 through 1.6.2 used the CMF bytes at the beginning of the IDAT
+stream to set the size of the sliding window for reading instead of using the
+default 32-kbyte sliding window size. It was discovered that there are
+hundreds of PNG files in the wild that have incorrect CMF bytes that caused
+libpng to issue a "too far back" error and reject the file. Libpng-1.6.3 and
+later calculate their own safe CMF from the image dimensions, provide a way
+to revert to the libpng-1.5.x behavior (ignoring the CMF bytes and using a
+32-kbyte sliding window), by using
+
+ png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW,
+ PNG_OPTION_ON);
+
+and provide a tool (contrib/tools/pngfix) for optimizing the CMF bytes
correctly.
Libpng-1.6.0 and libpng-1.6.1 wrote uncompressed iTXt chunks with the wrong
@@ -5663,6 +5854,9 @@ exported functions are marked with PNGAPI: body;
}
+The return type and decorations are placed on a separate line
+ahead of the function name, as illustrated above.
+
The prototypes for all exported functions appear in png.h,
above the comment that says
@@ -5706,7 +5900,7 @@ C binary operator and after "for" or "while", and before being cast, nor do we put one between a function name and the
left parenthesis that follows it:
- for (i = 2; i > 0; --i)
+ for (i = 2; i > 0; \-\-i)
y[i] = a(x) + (int)b;
We prefer #ifdef and #ifndef to #if defined() and #if !defined()
@@ -5727,13 +5921,13 @@ Other rules can be inferred by inspecting the libpng source. .SH XVI. Y2K Compliance in libpng
-July 18, 2013
+March 6, 2014
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.6.3 are Y2K compliant. It is my belief that earlier
+upward through 1.6.10 are Y2K compliant. It is my belief that earlier
versions were also Y2K compliant.
Libpng only has two year fields. One is a 2-byte unsigned integer
@@ -5950,6 +6144,23 @@ the first widely used release: 1.6.3beta01-11 16 10603 16.so.16.3[.0]
1.6.3rc01 16 10603 16.so.16.3[.0]
1.6.3 16 10603 16.so.16.3[.0]
+ 1.6.4beta01-02 16 10604 16.so.16.4[.0]
+ 1.6.4rc01 16 10604 16.so.16.4[.0]
+ 1.6.4 16 10604 16.so.16.4[.0]
+ 1.6.5 16 10605 16.so.16.5[.0]
+ 1.6.6 16 10606 16.so.16.6[.0]
+ 1.6.7beta01-04 16 10607 16.so.16.7[.0]
+ 1.6.7rc01-02 16 10607 16.so.16.7[.0]
+ 1.6.7 16 10607 16.so.16.7[.0]
+ 1.6.8beta01-02 16 10608 16.so.16.8[.0]
+ 1.6.8rc01-02 16 10608 16.so.16.8[.0]
+ 1.6.8 16 10608 16.so.16.8[.0]
+ 1.6.9beta01-04 16 10609 16.so.16.9[.0]
+ 1.6.9rc01-02 16 10609 16.so.16.9[.0]
+ 1.6.9 16 10609 16.so.16.9[.0]
+ 1.6.10beta01-03 16 10610 16.so.16.10[.0]
+ 1.6.10rc01-04 16 10610 16.so.16.10[.0]
+ 1.6.10 16 10610 16.so.16.10[.0]
Henceforth the source version will match the shared-library minor
and patch numbers; the shared-library major version number will be
@@ -6006,7 +6217,7 @@ possible without all of you. Thanks to Frank J. T. Wojcik for helping with the documentation.
-Libpng version 1.6.3 - July 18, 2013:
+Libpng version 1.6.10 - March 6, 2014:
Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net).
@@ -6029,7 +6240,7 @@ this sentence. This code is released under the libpng license.
-libpng versions 1.2.6, August 15, 2004, through 1.6.3, July 18, 2013, are
+libpng versions 1.2.6, August 15, 2004, through 1.6.10, March 6, 2014, 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
@@ -6128,7 +6339,7 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson
glennrp at users.sourceforge.net
-July 18, 2013
+March 6, 2014
.\" end of man page
diff --git a/plugins/AdvaImg/src/LibPNG/libpngpf.3 b/plugins/AdvaImg/src/LibPNG/libpngpf.3 index 7b6e69f6dd..62caa67efa 100644 --- a/plugins/AdvaImg/src/LibPNG/libpngpf.3 +++ b/plugins/AdvaImg/src/LibPNG/libpngpf.3 @@ -1,6 +1,6 @@ -.TH LIBPNGPF 3 "July 18, 2013"
+.TH LIBPNGPF 3 "March 6, 2014"
.SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.3
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.10
(private functions)
.SH SYNOPSIS
\fB#include \fI"pngpriv.h"
diff --git a/plugins/AdvaImg/src/LibPNG/png.5 b/plugins/AdvaImg/src/LibPNG/png.5 index fbaee84e26..23e7c7f907 100644 --- a/plugins/AdvaImg/src/LibPNG/png.5 +++ b/plugins/AdvaImg/src/LibPNG/png.5 @@ -1,4 +1,4 @@ -.TH PNG 5 "July 18, 2013"
+.TH PNG 5 "March 6, 2014"
.SH NAME
png \- Portable Network Graphics (PNG) format
.SH DESCRIPTION
diff --git a/plugins/AdvaImg/src/LibPNG/png.c b/plugins/AdvaImg/src/LibPNG/png.c index 40db183bca..7a67bd3026 100644 --- a/plugins/AdvaImg/src/LibPNG/png.c +++ b/plugins/AdvaImg/src/LibPNG/png.c @@ -1,8 +1,8 @@ /* png.c - location for general purpose libpng functions
*
- * Last changed in libpng 1.6.2 [April 25, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -14,7 +14,7 @@ #include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_3 Your_png_h_is_not_version_1_6_3;
+typedef png_libpng_version_1_6_10 Your_png_h_is_not_version_1_6_10;
/* Tells libpng that we have already handled the first "num_bytes" bytes
* of the PNG file signature. If the PNG data is embedded into another
@@ -201,6 +201,7 @@ png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) 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_UNUSED(pos)
png_warning(png_ptr, m);
#endif
@@ -259,6 +260,10 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, */
# ifdef PNG_USER_MEM_SUPPORTED
png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);
+# else
+ PNG_UNUSED(mem_ptr)
+ PNG_UNUSED(malloc_fn)
+ PNG_UNUSED(free_fn)
# endif
/* (*error_fn) can return control to the caller after the error_ptr is set,
@@ -768,14 +773,14 @@ png_get_copyright(png_const_structrp png_ptr) #else
# ifdef __STDC__
return PNG_STRING_NEWLINE \
- "libpng version 1.6.3 - July 18, 2013" PNG_STRING_NEWLINE \
- "Copyright (c) 1998-2013 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+ "libpng version 1.6.10 - March 6, 2014" PNG_STRING_NEWLINE \
+ "Copyright (c) 1998-2014 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.6.3 - July 18, 2013\
- Copyright (c) 1998-2013 Glenn Randers-Pehrson\
+ return "libpng version 1.6.10 - March 6, 2014\
+ Copyright (c) 1998-2014 Glenn Randers-Pehrson\
Copyright (c) 1996-1997 Andreas Dilger\
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
# endif
@@ -821,6 +826,63 @@ png_get_header_version(png_const_structrp png_ptr) #endif
}
+#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
+/* NOTE: this routine is not used internally! */
+/* 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_SET_UNKNOWN_CHUNKS_SUPPORTED
int PNGAPI
png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)
@@ -855,7 +917,8 @@ png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) return PNG_HANDLE_CHUNK_AS_DEFAULT;
}
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
int /* PRIVATE */
png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name)
{
@@ -864,7 +927,7 @@ png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name) PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
return png_handle_as_unknown(png_ptr, chunk_string);
}
-#endif /* READ_UNKNOWN_CHUNKS */
+#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
#endif /* SET_UNKNOWN_CHUNKS */
#ifdef PNG_READ_SUPPORTED
@@ -1679,7 +1742,8 @@ is_ICC_signature_char(png_alloc_size_t it) (it >= 97 && it <= 122);
}
-static int is_ICC_signature(png_alloc_size_t it)
+static int
+is_ICC_signature(png_alloc_size_t it)
{
return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&
is_ICC_signature_char((it >> 16) & 0xff) &&
@@ -1721,6 +1785,7 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, # endif
/* The 'reason' is an arbitrary message, allow +79 maximum 195 */
pos = png_safecat(message, (sizeof message), pos, reason);
+ PNG_UNUSED(pos)
/* This is recoverable, but make it unconditionally an app_error on write to
* avoid writing invalid ICC profiles into PNG files. (I.e. we handle them
@@ -2231,15 +2296,16 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, }
}
-# if PNG_sRGB_PROFILE_CHECKS > 0
- /* The signature matched, but the profile had been changed in some
- * way. This is an apparent violation of the ICC terms of use and,
- * anyway, probably indicates a data error or uninformed hacking.
- */
- if (png_sRGB_checks[i].have_md5)
- png_benign_error(png_ptr,
- "copyright violation: edited ICC profile ignored");
-# endif
+# if PNG_sRGB_PROFILE_CHECKS > 0
+ /* The signature matched, but the profile had been changed in some
+ * way. This probably indicates a data error or uninformed hacking.
+ * Fall through to "no match".
+ */
+ png_chunk_report(png_ptr,
+ "Not recognizing known sRGB profile that has been edited",
+ PNG_CHUNK_WARNING);
+ break;
+# endif
}
}
@@ -2409,14 +2475,6 @@ png_check_IHDR(png_const_structrp png_ptr, 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)
@@ -3090,11 +3148,15 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) if (r > 2147483647. || r < -2147483648.)
png_fixed_error(png_ptr, text);
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(text)
+# endif
+
return (png_fixed_point)r;
}
#endif
-#if defined(PNG_READ_GAMMA_SUPPORTED) || \
+#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_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
@@ -3267,27 +3329,29 @@ png_gamma_significant(png_fixed_point gamma_val) #endif
#ifdef PNG_READ_GAMMA_SUPPORTED
+# ifdef PNG_16BIT_SUPPORTED
/* 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
+# 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
+# else
png_fixed_point res;
if (png_muldiv(&res, a, b, 100000))
return res;
-#endif
+# endif
return 0; /* overflow */
}
+# endif /* 16BIT */
/* The inverse of the above. */
png_fixed_point
@@ -3592,6 +3656,7 @@ png_exp8bit(png_fixed_point lg2) return (png_byte)((x + 0x7fffffU) >> 24);
}
+#ifdef PNG_16BIT_SUPPORTED
static png_uint_16
png_exp16bit(png_fixed_point lg2)
{
@@ -3602,6 +3667,7 @@ png_exp16bit(png_fixed_point lg2) x -= x >> 16;
return (png_uint_16)((x + 32767U) >> 16);
}
+#endif /* 16BIT */
#endif /* FLOATING_ARITHMETIC */
png_byte
@@ -3627,6 +3693,7 @@ png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) return (png_byte)value;
}
+#ifdef PNG_16BIT_SUPPORTED
png_uint_16
png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
{
@@ -3649,6 +3716,7 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) return (png_uint_16)value;
}
+#endif /* 16BIT */
/* 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
@@ -3662,10 +3730,16 @@ png_gamma_correct(png_structrp png_ptr, unsigned int value, if (png_ptr->bit_depth == 8)
return png_gamma_8bit_correct(value, gamma_val);
+#ifdef PNG_16BIT_SUPPORTED
else
return png_gamma_16bit_correct(value, gamma_val);
+#else
+ /* should not reach this */
+ return 0;
+#endif /* 16BIT */
}
+#ifdef PNG_16BIT_SUPPORTED
/* 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).
@@ -3804,6 +3878,7 @@ png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, last++;
}
}
+#endif /* 16BIT */
/* 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
@@ -3832,6 +3907,7 @@ png_destroy_gamma_table(png_structrp png_ptr) png_free(png_ptr, png_ptr->gamma_table);
png_ptr->gamma_table = NULL;
+#ifdef PNG_16BIT_SUPPORTED
if (png_ptr->gamma_16_table != NULL)
{
int i;
@@ -3843,6 +3919,7 @@ png_destroy_gamma_table(png_structrp png_ptr) png_free(png_ptr, png_ptr->gamma_16_table);
png_ptr->gamma_16_table = NULL;
}
+#endif /* 16BIT */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
@@ -3852,6 +3929,7 @@ png_destroy_gamma_table(png_structrp png_ptr) png_free(png_ptr, png_ptr->gamma_to_1);
png_ptr->gamma_to_1 = NULL;
+#ifdef PNG_16BIT_SUPPORTED
if (png_ptr->gamma_16_from_1 != NULL)
{
int i;
@@ -3874,6 +3952,7 @@ png_destroy_gamma_table(png_structrp png_ptr) png_free(png_ptr, png_ptr->gamma_16_to_1);
png_ptr->gamma_16_to_1 = NULL;
}
+#endif /* 16BIT */
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
}
@@ -3919,6 +3998,7 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth) }
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
}
+#ifdef PNG_16BIT_SUPPORTED
else
{
png_byte shift, sig_bit;
@@ -3975,24 +4055,20 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth) 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->colorspace.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->colorspace.gamma,
png_ptr->screen_gamma) : PNG_FP_1);
-#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
@@ -4012,6 +4088,7 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth) }
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
}
+#endif /* 16BIT */
}
#endif /* READ_GAMMA */
diff --git a/plugins/AdvaImg/src/LibPNG/png.h b/plugins/AdvaImg/src/LibPNG/png.h index 9fafb2435a..77bffe6b40 100644 --- a/plugins/AdvaImg/src/LibPNG/png.h +++ b/plugins/AdvaImg/src/LibPNG/png.h @@ -1,8 +1,8 @@ /* png.h - header file for PNG reference library
*
- * libpng version 1.6.3 - July 18, 2013
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * libpng version 1.6.10 - March 6, 2014
+ * Copyright (c) 1998-2014 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.)
*
@@ -11,7 +11,7 @@ * 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.6.3 - July 18, 2013: Glenn
+ * libpng versions 0.97, January 1998, through 1.6.10 - March 6, 2014: Glenn
* See also "Contributing Authors", below.
*
* Note about libpng version numbers:
@@ -178,6 +178,23 @@ * 1.6.3beta01-11 16 10603 16.so.16.3[.0]
* 1.6.3rc01 16 10603 16.so.16.3[.0]
* 1.6.3 16 10603 16.so.16.3[.0]
+ * 1.6.4beta01-02 16 10604 16.so.16.4[.0]
+ * 1.6.4rc01 16 10604 16.so.16.4[.0]
+ * 1.6.4 16 10604 16.so.16.4[.0]
+ * 1.6.5 16 10605 16.so.16.5[.0]
+ * 1.6.6 16 10606 16.so.16.6[.0]
+ * 1.6.7beta01-04 16 10607 16.so.16.7[.0]
+ * 1.6.7rc01-03 16 10607 16.so.16.7[.0]
+ * 1.6.7 16 10607 16.so.16.7[.0]
+ * 1.6.8beta01-02 16 10608 16.so.16.8[.0]
+ * 1.6.8rc01-02 16 10608 16.so.16.8[.0]
+ * 1.6.8 16 10608 16.so.16.8[.0]
+ * 1.6.9beta01-04 16 10609 16.so.16.9[.0]
+ * 1.6.9rc01-02 16 10609 16.so.16.9[.0]
+ * 1.6.9 16 10609 16.so.16.9[.0]
+ * 1.6.10beta01-03 16 10610 16.so.16.10[.0]
+ * 1.6.10betarc01-04 16 10610 16.so.16.10[.0]
+ * 1.6.10beta 16 10610 16.so.16.10[.0]
*
* Henceforth the source version will match the shared-library major
* and minor numbers; the shared-library major version number will be
@@ -209,7 +226,7 @@ *
* This code is released under the libpng license.
*
- * libpng versions 1.2.6, August 15, 2004, through 1.6.3, July 18, 2013, are
+ * libpng versions 1.2.6, August 15, 2004, through 1.6.10, March 6, 2014, are
* Copyright (c) 2004, 2006-2013 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:
@@ -321,13 +338,13 @@ * Y2K compliance in libpng:
* =========================
*
- * July 18, 2013
+ * March 6, 2014
*
* 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.6.3 are Y2K compliant. It is my belief that
+ * upward through 1.6.10 are Y2K compliant. It is my belief that
* earlier versions were also Y2K compliant.
*
* Libpng only has two year fields. One is a 2-byte unsigned integer
@@ -387,9 +404,9 @@ */
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.3"
+#define PNG_LIBPNG_VER_STRING "1.6.10"
#define PNG_HEADER_VERSION_STRING \
- " libpng version 1.6.3 - July 18, 2013\n"
+ " libpng version 1.6.10 - March 6, 2014\n"
#define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16
@@ -397,7 +414,7 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 3
+#define PNG_LIBPNG_VER_RELEASE 10
/* This should match the numeric part of the final component of
* PNG_LIBPNG_VER_STRING, omitting any leading zero:
@@ -428,7 +445,7 @@ * version 1.0.0 was mis-numbered 100 instead of 10000). From
* version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
*/
-#define PNG_LIBPNG_VER 10603 /* 1.6.3 */
+#define PNG_LIBPNG_VER 10610 /* 1.6.10 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -440,10 +457,6 @@ # include "pnglibconf.h"
#endif
-#define PNG_APNG_SUPPORTED
-#define PNG_READ_APNG_SUPPORTED
-#define PNG_WRITE_APNG_SUPPORTED
-
#ifndef PNG_VERSION_INFO_ONLY
/* Machine specific configuration. */
# include "pngconf.h"
@@ -534,21 +547,10 @@ extern "C" { * See pngconf.h for base types that vary by machine/system
*/
-#ifdef PNG_APNG_SUPPORTED
-/* dispose_op flags from inside fcTL */
-#define PNG_DISPOSE_OP_NONE 0x00
-#define PNG_DISPOSE_OP_BACKGROUND 0x01
-#define PNG_DISPOSE_OP_PREVIOUS 0x02
-
-/* blend_op flags from inside fcTL */
-#define PNG_BLEND_OP_SOURCE 0x00
-#define PNG_BLEND_OP_OVER 0x01
-#endif /* PNG_APNG_SUPPORTED */
-
/* 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_6_3;
+typedef char* png_libpng_version_1_6_10;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
@@ -730,7 +732,8 @@ typedef png_time * png_timep; typedef const png_time * png_const_timep;
typedef png_time * * png_timepp;
-#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\
+ defined(PNG_USER_CHUNKS_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
@@ -864,10 +867,6 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; #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 */
-#ifdef PNG_APNG_SUPPORTED
-#define PNG_INFO_acTL 0x10000
-#define PNG_INFO_fcTL 0x20000
-#endif
/* This is used for the transformation routines, as some of them
* change these values for the row. It also should enable using
@@ -905,10 +904,6 @@ typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, #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));
-#ifdef PNG_APNG_SUPPORTED
-typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp,
- png_uint_32));
-#endif
/* 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
@@ -1217,9 +1212,9 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, #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.
+/* How the alpha channel is interpreted - this affects how the color channels
+ * of a PNG file are returned to the calling application when an alpha channel,
+ * or a 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
@@ -1227,33 +1222,19 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, *
* 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
+ * corresponding composited pixel, and the color channels are unassociated
+ * (not premultiplied). 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.
+ * storing color channel values that have been scaled by the alpha.
+ * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
+ * (the latter being the two common names for associated alpha color channels).
+ *
+ * For the 'OPTIMIZED' 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
@@ -1280,68 +1261,7 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, #if defined(PNG_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.
+ * how to decode the output values, not how they are encoded.
*/
#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */
#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */
@@ -1964,8 +1884,8 @@ PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, * It is unlikely that this function works correctly as of 1.6.0 and using it
* may result either in memory leaks or double free of allocated data.
*/
-PNG_EXPORTA(99, void, png_data_freer, (png_const_structrp png_ptr,
- png_inforp info_ptr, int freer, png_uint_32 mask), PNG_DEPRECATED);
+PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int freer, png_uint_32 mask));
/* Assignments for png_data_freer */
#define PNG_DESTROY_WILL_FREE_DATA 1
@@ -2007,6 +1927,8 @@ PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, #else
/* Fatal error in PNG image of libpng - can't continue */
PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN);
+# define png_error(s1,s2) png_err(s1)
+# define png_chunk_error(s1,s2) png_err(s1)
#endif
#ifdef PNG_WARNINGS_SUPPORTED
@@ -2017,6 +1939,9 @@ PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, /* Non-fatal error in libpng, chunk name is prepended to message. */
PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr,
png_const_charp warning_message));
+#else
+# define png_warning(s1,s2) ((void)(s1))
+# define png_chunk_warning(s1,s2) ((void)(s1))
#endif
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
@@ -2527,11 +2452,15 @@ PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, #ifdef PNG_INFO_IMAGE_SUPPORTED
/* The "params" pointer is currently not used and is for future expansion. */
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr,
int transforms, png_voidp params));
+#endif
+#ifdef PNG_WRITE_SUPPORTED
PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr,
int transforms, png_voidp params));
#endif
+#endif
PNG_EXPORT(180, png_const_charp, png_get_copyright,
(png_const_structrp png_ptr));
@@ -3312,75 +3241,6 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, * END OF HARDWARE OPTIONS
******************************************************************************/
-#ifdef PNG_APNG_SUPPORTED
-PNG_EXPORT(245, png_uint_32, png_get_acTL, (png_structp png_ptr,
- png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
-
-PNG_EXPORT(246, png_uint_32, png_set_acTL, (png_structp png_ptr,
- png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays));
-
-PNG_EXPORT(247, png_uint_32, png_get_num_frames, (png_structp png_ptr,
- png_infop info_ptr));
-
-PNG_EXPORT(248, png_uint_32, png_get_num_plays, (png_structp png_ptr,
- png_infop info_ptr));
-
-PNG_EXPORT(249, png_uint_32, png_get_next_frame_fcTL,
- (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width,
- png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset,
- png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op,
- png_byte *blend_op));
-
-PNG_EXPORT(250, png_uint_32, png_set_next_frame_fcTL,
- (png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
- png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
- png_byte blend_op));
-
-PNG_EXPORT(251, png_uint_32, png_get_next_frame_width,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(252, png_uint_32, png_get_next_frame_height,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(253, png_uint_32, png_get_next_frame_x_offset,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(254, png_uint_32, png_get_next_frame_y_offset,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(255, png_uint_16, png_get_next_frame_delay_num,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(256, png_uint_16, png_get_next_frame_delay_den,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(257, png_byte, png_get_next_frame_dispose_op,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(258, png_byte, png_get_next_frame_blend_op,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(259, png_byte, png_get_first_frame_is_hidden,
- (png_structp png_ptr, png_infop info_ptr));
-PNG_EXPORT(260, png_uint_32, png_set_first_frame_is_hidden,
- (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden));
-
-#ifdef PNG_READ_APNG_SUPPORTED
-PNG_EXPORT(261, void, png_read_frame_head, (png_structp png_ptr,
- png_infop info_ptr));
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_EXPORT(262, void, png_set_progressive_frame_fn, (png_structp png_ptr,
- png_progressive_frame_ptr frame_info_fn,
- png_progressive_frame_ptr frame_end_fn));
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-#endif /* PNG_READ_APNG_SUPPORTED */
-
-#ifdef PNG_WRITE_APNG_SUPPORTED
-PNG_EXPORT(263, void, png_write_frame_head, (png_structp png_ptr,
- png_infop info_ptr, png_bytepp row_pointers,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
- png_byte blend_op));
-
-PNG_EXPORT(264, void, png_write_frame_tail, (png_structp png_ptr,
- png_infop info_ptr));
-#endif /* PNG_WRITE_APNG_SUPPORTED */
-#endif /* PNG_APNG_SUPPORTED */
-
/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
* defs, scripts/pnglibconf.h, and scripts/pnglibconf.h.prebuilt
*/
@@ -3390,11 +3250,7 @@ PNG_EXPORT(264, void, png_write_frame_tail, (png_structp png_ptr, * scripts/symbols.def as well.
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
-#ifdef PNG_APNG_SUPPORTED
- PNG_EXPORT_LAST_ORDINAL(264);
-#else
PNG_EXPORT_LAST_ORDINAL(244);
-#endif /* PNG_APNG_SUPPORTED */
#endif
#ifdef __cplusplus
diff --git a/plugins/AdvaImg/src/LibPNG/pngconf.h b/plugins/AdvaImg/src/LibPNG/pngconf.h index 02f74e2639..f11192fa70 100644 --- a/plugins/AdvaImg/src/LibPNG/pngconf.h +++ b/plugins/AdvaImg/src/LibPNG/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine configurable file for libpng
*
- * libpng version 1.6.3 - July 18, 2013
+ * libpng version 1.6.10 - March 6, 2014
*
* Copyright (c) 1998-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
@@ -361,7 +361,33 @@ * version 1.2.41. Disabling these removes the warnings but may also produce
* less efficient code.
*/
-# if defined(__GNUC__)
+# if defined(__clang__)
+ /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */
+# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__)
+# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
+# endif
+# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__)
+# define PNG_NORETURN __attribute__((__noreturn__))
+# endif
+# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__)
+# define PNG_ALLOCATED __attribute__((__malloc__))
+# endif
+# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__)
+# define PNG_DEPRECATED __attribute__((__deprecated__))
+# endif
+# if !defined(PNG_PRIVATE)
+# ifdef __has_extension
+# if __has_extension(attribute_unavailable_with_message)
+# define PNG_PRIVATE __attribute__((__unavailable__(\
+ "This function is not exported by libpng.")))
+# endif
+# endif
+# endif
+# ifndef PNG_RESTRICT
+# define PNG_RESTRICT __restrict
+# endif
+
+# elif defined(__GNUC__)
# ifndef PNG_USE_RESULT
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
# endif
@@ -384,12 +410,12 @@ __attribute__((__deprecated__))
# endif
# endif
-# if ((__GNUC__ != 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1))
+# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1))
# ifndef PNG_RESTRICT
# define PNG_RESTRICT __restrict
# endif
-# endif /* __GNUC__ == 3.0 */
-# endif /* __GNUC__ >= 3 */
+# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */
+# endif /* __GNUC__ >= 3 */
# elif defined(_MSC_VER) && (_MSC_VER >= 1300)
# ifndef PNG_USE_RESULT
@@ -419,7 +445,7 @@ # ifndef PNG_RESTRICT
# define PNG_RESTRICT __restrict
# endif
-# endif /* _MSC_VER */
+# endif
#endif /* PNG_PEDANTIC_WARNINGS */
#ifndef PNG_DEPRECATED
@@ -440,6 +466,7 @@ #ifndef PNG_RESTRICT
# define PNG_RESTRICT /* The C99 "restrict" feature */
#endif
+
#ifndef PNG_FP_EXPORT /* A floating point API. */
# ifdef PNG_FLOATING_POINT_SUPPORTED
# define PNG_FP_EXPORT(ordinal, type, name, args)\
diff --git a/plugins/AdvaImg/src/LibPNG/pngdebug.h b/plugins/AdvaImg/src/LibPNG/pngdebug.h index 96c1ea42b3..99a7aad44f 100644 --- a/plugins/AdvaImg/src/LibPNG/pngdebug.h +++ b/plugins/AdvaImg/src/LibPNG/pngdebug.h @@ -1,11 +1,11 @@ /* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2013 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]
+ * Last changed in libpng 1.6.8 [December 19, 2013]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -25,7 +25,7 @@ * (actually ((void)0)).
*
* level: level of detail of message, starting at 0. A level 'n'
- * message is preceded by 'n' tab characters (not implemented
+ * message is preceded by 'n' 3-space indentations (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
@@ -77,32 +77,29 @@ # 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":"")))); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : "")))); \
} 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); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),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); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1,p2);\
} while (0)
# endif
# else /* __STDC __ */
diff --git a/plugins/AdvaImg/src/LibPNG/pngerror.c b/plugins/AdvaImg/src/LibPNG/pngerror.c index c71e2ab559..7e155cf2d3 100644 --- a/plugins/AdvaImg/src/LibPNG/pngerror.c +++ b/plugins/AdvaImg/src/LibPNG/pngerror.c @@ -1,8 +1,8 @@ /* pngerror.c - stub functions for i/o and memory allocation
*
- * Last changed in libpng 1.6.1 [March 28, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -382,6 +382,10 @@ png_benign_error(png_const_structrp png_ptr, png_const_charp error_message) # endif
png_error(png_ptr, error_message);
}
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
}
void /* PRIVATE */
@@ -391,6 +395,10 @@ png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) png_warning(png_ptr, error_message);
else
png_error(png_ptr, error_message);
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
}
void /* PRIVATE */
@@ -400,6 +408,10 @@ png_app_error(png_const_structrp png_ptr, png_const_charp error_message) png_warning(png_ptr, error_message);
else
png_error(png_ptr, error_message);
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
}
#endif /* BENIGN_ERRORS */
@@ -416,7 +428,8 @@ static PNG_CONST char png_digit[16] = { };
#define PNG_MAX_ERROR_TEXT 196 /* Currently limited be profile_error in png.c */
-#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
+#if defined(PNG_WARNINGS_SUPPORTED) || \
+ (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED))
static void /* PRIVATE */
png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
error_message)
@@ -506,6 +519,10 @@ png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp else
png_chunk_error(png_ptr, error_message);
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
}
#endif
#endif /* PNG_READ_SUPPORTED */
@@ -513,6 +530,10 @@ png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp void /* PRIVATE */
png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
{
+# ifndef PNG_WARNINGS_SUPPORTED
+ PNG_UNUSED(message)
+# endif
+
/* This is always supported, but for just read or just write it
* unconditionally does the right thing.
*/
@@ -740,7 +761,12 @@ png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val);
#endif
- /* Here if not setjmp support or if png_ptr is null. */
+ /* If control reaches this point, png_longjmp() must not return. The only
+ * choice is to terminate the whole process (or maybe the thread); to do
+ * this the ANSI-C abort() function is used unless a different method is
+ * implemented by overriding the default configuration setting for
+ * PNG_ABORT().
+ */
PNG_ABORT();
}
@@ -850,8 +876,8 @@ png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) * possible to implement without setjmp support just so long as there is some
* way to handle the error return here:
*/
-PNG_FUNCTION(void /* PRIVATE */,
-png_safe_error,(png_structp png_nonconst_ptr, png_const_charp error_message),
+PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
+png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
PNG_NORETURN)
{
const png_const_structrp png_ptr = png_nonconst_ptr;
@@ -886,7 +912,7 @@ png_safe_error,(png_structp png_nonconst_ptr, png_const_charp error_message), }
#ifdef PNG_WARNINGS_SUPPORTED
-void /* PRIVATE */
+void /* PRIVATE */ PNGCBAPI
png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
{
const png_const_structrp png_ptr = png_nonconst_ptr;
diff --git a/plugins/AdvaImg/src/LibPNG/pngget.c b/plugins/AdvaImg/src/LibPNG/pngget.c index 6a3eef1873..80ab055dca 100644 --- a/plugins/AdvaImg/src/LibPNG/pngget.c +++ b/plugins/AdvaImg/src/LibPNG/pngget.c @@ -1174,166 +1174,4 @@ png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr) # endif
#endif
-#ifdef PNG_APNG_SUPPORTED
-png_uint_32 PNGAPI
-png_get_acTL(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 *num_frames, png_uint_32 *num_plays)
-{
- png_debug1(1, "in %s retrieval function", "acTL");
-
- if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_acTL) &&
- num_frames != NULL && num_plays != NULL)
- {
- *num_frames = info_ptr->num_frames;
- *num_plays = info_ptr->num_plays;
- return (1);
- }
-
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_num_frames(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_num_frames()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->num_frames);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_num_plays(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_num_plays()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->num_plays);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 *width, png_uint_32 *height,
- png_uint_32 *x_offset, png_uint_32 *y_offset,
- png_uint_16 *delay_num, png_uint_16 *delay_den,
- png_byte *dispose_op, png_byte *blend_op)
-{
- png_debug1(1, "in %s retrieval function", "fcTL");
-
- if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_fcTL) &&
- width != NULL && height != NULL &&
- x_offset != NULL && y_offset != NULL &&
- delay_num != NULL && delay_den != NULL &&
- dispose_op != NULL && blend_op != NULL)
- {
- *width = info_ptr->next_frame_width;
- *height = info_ptr->next_frame_height;
- *x_offset = info_ptr->next_frame_x_offset;
- *y_offset = info_ptr->next_frame_y_offset;
- *delay_num = info_ptr->next_frame_delay_num;
- *delay_den = info_ptr->next_frame_delay_den;
- *dispose_op = info_ptr->next_frame_dispose_op;
- *blend_op = info_ptr->next_frame_blend_op;
- return (1);
- }
-
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_width()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_width);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_height()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_height);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_x_offset()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_x_offset);
- return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_y_offset()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_y_offset);
- return (0);
-}
-
-png_uint_16 PNGAPI
-png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_delay_num()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_delay_num);
- return (0);
-}
-
-png_uint_16 PNGAPI
-png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_delay_den()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_delay_den);
- return (0);
-}
-
-png_byte PNGAPI
-png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_dispose_op()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_dispose_op);
- return (0);
-}
-
-png_byte PNGAPI
-png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_get_next_frame_blend_op()");
-
- if (png_ptr != NULL && info_ptr != NULL)
- return (info_ptr->next_frame_blend_op);
- return (0);
-}
-
-png_byte PNGAPI
-png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_first_frame_is_hidden()");
-
- if (png_ptr != NULL)
- return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN);
-
- PNG_UNUSED(info_ptr)
-
- return 0;
-}
-#endif /* PNG_APNG_SUPPORTED */
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/plugins/AdvaImg/src/LibPNG/pnginfo.h b/plugins/AdvaImg/src/LibPNG/pnginfo.h index 94db9ff31c..683b7ea177 100644 --- a/plugins/AdvaImg/src/LibPNG/pnginfo.h +++ b/plugins/AdvaImg/src/LibPNG/pnginfo.h @@ -256,18 +256,5 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) png_bytepp row_pointers; /* the image bits */
#endif
-#ifdef PNG_APNG_SUPPORTED
- png_uint_32 num_frames; /* including default image */
- png_uint_32 num_plays;
- png_uint_32 next_frame_width;
- png_uint_32 next_frame_height;
- png_uint_32 next_frame_x_offset;
- png_uint_32 next_frame_y_offset;
- png_uint_16 next_frame_delay_num;
- png_uint_16 next_frame_delay_den;
- png_byte next_frame_dispose_op;
- png_byte next_frame_blend_op;
-#endif
-
};
#endif /* PNGINFO_H */
diff --git a/plugins/AdvaImg/src/LibPNG/pnglibconf.h b/plugins/AdvaImg/src/LibPNG/pnglibconf.h index ececc38fc2..1894e2daeb 100644 --- a/plugins/AdvaImg/src/LibPNG/pnglibconf.h +++ b/plugins/AdvaImg/src/LibPNG/pnglibconf.h @@ -1,211 +1,211 @@ -/* libpng 1.6.3 STANDARD API DEFINITION */
-
-/* pnglibconf.h - library build configuration */
-
-/* Libpng version 1.6.3 - July 18, 2013 */
-
-/* Copyright (c) 1998-2013 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 */
-/* Machine generated file: DO NOT EDIT */
-/* Derived from: scripts/pnglibconf.dfa */
-#ifndef PNGLCONF_H
-#define PNGLCONF_H
-/* options */
-#define PNG_16BIT_SUPPORTED
-#define PNG_ALIGNED_MEMORY_SUPPORTED
-/*#undef PNG_ARM_NEON_API_SUPPORTED*/
-/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
-#define PNG_BENIGN_ERRORS_SUPPORTED
-#define PNG_BENIGN_READ_ERRORS_SUPPORTED
-/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
-#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
-#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
-#define PNG_COLORSPACE_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_FORMAT_AFIRST_SUPPORTED
-#define PNG_FORMAT_BGR_SUPPORTED
-#define PNG_GAMMA_SUPPORTED
-#define PNG_GET_PALETTE_MAX_SUPPORTED
-#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#define PNG_INCH_CONVERSIONS_SUPPORTED
-#define PNG_INFO_IMAGE_SUPPORTED
-#define PNG_IO_STATE_SUPPORTED
-#define PNG_MNG_FEATURES_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_CHECK_FOR_INVALID_INDEX_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_GAMMA_SUPPORTED
-#define PNG_READ_GET_PALETTE_MAX_SUPPORTED
-#define PNG_READ_GRAY_TO_RGB_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_OPT_PLTE_SUPPORTED
-#define PNG_READ_PACKSWAP_SUPPORTED
-#define PNG_READ_PACK_SUPPORTED
-#define PNG_READ_QUANTIZE_SUPPORTED
-#define PNG_READ_RGB_TO_GRAY_SUPPORTED
-#define PNG_READ_SCALE_16_TO_8_SUPPORTED
-#define PNG_READ_SHIFT_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_TRANSFORMS_SUPPORTED
-#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_READ_USER_CHUNKS_SUPPORTED
-#define PNG_READ_USER_TRANSFORM_SUPPORTED
-#define PNG_READ_bKGD_SUPPORTED
-#define PNG_READ_cHRM_SUPPORTED
-#define PNG_READ_gAMA_SUPPORTED
-#define PNG_READ_hIST_SUPPORTED
-#define PNG_READ_iCCP_SUPPORTED
-#define PNG_READ_iTXt_SUPPORTED
-#define PNG_READ_oFFs_SUPPORTED
-#define PNG_READ_pCAL_SUPPORTED
-#define PNG_READ_pHYs_SUPPORTED
-#define PNG_READ_sBIT_SUPPORTED
-#define PNG_READ_sCAL_SUPPORTED
-#define PNG_READ_sPLT_SUPPORTED
-#define PNG_READ_sRGB_SUPPORTED
-#define PNG_READ_tEXt_SUPPORTED
-#define PNG_READ_tIME_SUPPORTED
-#define PNG_READ_tRNS_SUPPORTED
-#define PNG_READ_zTXt_SUPPORTED
-/*#undef PNG_SAFE_LIMITS_SUPPORTED*/
-#define PNG_SAVE_INT_32_SUPPORTED
-#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_SEQUENTIAL_READ_SUPPORTED
-#define PNG_SETJMP_SUPPORTED
-#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
-#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
-#define PNG_SET_OPTION_SUPPORTED
-#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_SET_USER_LIMITS_SUPPORTED
-#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
-#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
-#define PNG_SIMPLIFIED_READ_SUPPORTED
-#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
-#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
-#define PNG_SIMPLIFIED_WRITE_SUPPORTED
-#define PNG_STDIO_SUPPORTED
-#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_TEXT_SUPPORTED
-#define PNG_TIME_RFC1123_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_CHECK_FOR_INVALID_INDEX_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_GET_PALETTE_MAX_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_OPTIMIZE_CMF_SUPPORTED
-#define PNG_WRITE_PACKSWAP_SUPPORTED
-#define PNG_WRITE_PACK_SUPPORTED
-#define PNG_WRITE_SHIFT_SUPPORTED
-#define PNG_WRITE_SUPPORTED
-#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
-#define PNG_WRITE_SWAP_SUPPORTED
-#define PNG_WRITE_TEXT_SUPPORTED
-#define PNG_WRITE_TRANSFORMS_SUPPORTED
-#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
-#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-#define PNG_WRITE_bKGD_SUPPORTED
-#define PNG_WRITE_cHRM_SUPPORTED
-#define PNG_WRITE_gAMA_SUPPORTED
-#define PNG_WRITE_hIST_SUPPORTED
-#define PNG_WRITE_iCCP_SUPPORTED
-#define PNG_WRITE_iTXt_SUPPORTED
-#define PNG_WRITE_oFFs_SUPPORTED
-#define PNG_WRITE_pCAL_SUPPORTED
-#define PNG_WRITE_pHYs_SUPPORTED
-#define PNG_WRITE_sBIT_SUPPORTED
-#define PNG_WRITE_sCAL_SUPPORTED
-#define PNG_WRITE_sPLT_SUPPORTED
-#define PNG_WRITE_sRGB_SUPPORTED
-#define PNG_WRITE_tEXt_SUPPORTED
-#define PNG_WRITE_tIME_SUPPORTED
-#define PNG_WRITE_tRNS_SUPPORTED
-#define PNG_WRITE_zTXt_SUPPORTED
-#define PNG_bKGD_SUPPORTED
-#define PNG_cHRM_SUPPORTED
-#define PNG_gAMA_SUPPORTED
-#define PNG_hIST_SUPPORTED
-#define PNG_iCCP_SUPPORTED
-#define PNG_iTXt_SUPPORTED
-#define PNG_oFFs_SUPPORTED
-#define PNG_pCAL_SUPPORTED
-#define PNG_pHYs_SUPPORTED
-#define PNG_sBIT_SUPPORTED
-#define PNG_sCAL_SUPPORTED
-#define PNG_sPLT_SUPPORTED
-#define PNG_sRGB_SUPPORTED
-#define PNG_tEXt_SUPPORTED
-#define PNG_tIME_SUPPORTED
-#define PNG_tRNS_SUPPORTED
-#define PNG_zTXt_SUPPORTED
-/* end of options */
-/* 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_IDAT_READ_SIZE PNG_ZBUF_SIZE
-#define PNG_INFLATE_BUF_SIZE 1024
-#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_TEXT_Z_DEFAULT_COMPRESSION (-1)
-#define PNG_TEXT_Z_DEFAULT_STRATEGY 0
-#define PNG_WEIGHT_SHIFT 8
-#define PNG_ZBUF_SIZE 8192
-#define PNG_ZLIB_VERNUM 0 /* unknown */
-#define PNG_Z_DEFAULT_COMPRESSION (-1)
-#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
-#define PNG_Z_DEFAULT_STRATEGY 1
-#define PNG_sCAL_PRECISION 5
-#define PNG_sRGB_PROFILE_CHECKS 2
-/* end of settings */
-#endif /* PNGLCONF_H */
+/* libpng 1.6.1 STANDARD API DEFINITION */ + +/* pnglibconf.h - library build configuration */ + +/* Libpng version 1.6.1 - March 28, 2013 */ + +/* Copyright (c) 1998-2013 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 */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_ALIGNED_MEMORY_SUPPORTED +/*#undef PNG_ARM_NEON_API_SUPPORTED*/ +/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +/*#undef PNG_ARM_NEON_SUPPORTED*/ +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_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_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_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_CHECK_FOR_INVALID_INDEX_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_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_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_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_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_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +/*#undef PNG_SAFE_LIMITS_SUPPORTED*/ +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +/*#undef PNG_SET_OPTION_SUPPORTED*/ +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_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_CHECK_FOR_INVALID_INDEX_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_GET_PALETTE_MAX_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_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* 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_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#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_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_WEIGHT_SHIFT 8 +#define PNG_ZBUF_SIZE 8192 +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/plugins/AdvaImg/src/LibPNG/pngmem.c b/plugins/AdvaImg/src/LibPNG/pngmem.c index adae736699..ba643a9fb1 100644 --- a/plugins/AdvaImg/src/LibPNG/pngmem.c +++ b/plugins/AdvaImg/src/LibPNG/pngmem.c @@ -1,7 +1,7 @@ /* pngmem.c - stub functions for memory allocation
*
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.8 [December 19, 2013]
* Copyright (c) 1998-2013 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.)
@@ -73,9 +73,10 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), * to implement a user memory handler. This checks to be sure it isn't
* called with big numbers.
*/
-#ifdef PNG_USER_MEM_SUPPORTED
+#ifndef PNG_USER_MEM_SUPPORTED
PNG_UNUSED(png_ptr)
#endif
+
if (size > 0 && size <= PNG_SIZE_MAX
# ifdef PNG_MAX_MALLOC_64K
&& size <= 65536U
@@ -95,6 +96,8 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), return NULL;
}
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
+ defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7
* that arises because of the checks in png_realloc_array that are repeated in
* png_malloc_array.
@@ -156,6 +159,7 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, return NULL; /* error */
}
+#endif /* TEXT || sPLT || STORE_UNKNOWN_CHUNKS */
/* Various functions that have different error handling are derived from this.
* png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
diff --git a/plugins/AdvaImg/src/LibPNG/pngpread.c b/plugins/AdvaImg/src/LibPNG/pngpread.c index 6c06d81ee9..eec5983833 100644 --- a/plugins/AdvaImg/src/LibPNG/pngpread.c +++ b/plugins/AdvaImg/src/LibPNG/pngpread.c @@ -1,8 +1,8 @@ /* pngpread.c - read a png file in push mode
*
- * Last changed in libpng 1.6.0 [February 14, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -217,109 +217,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) chunk_name = png_ptr->chunk_name;
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->num_frames_read > 0 &&
- png_ptr->num_frames_read < info_ptr->num_frames)
- {
- if (chunk_name == png_IDAT)
- {
- /* Discard trailing IDATs for the first frame */
- if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1)
- png_error(png_ptr, "out of place IDAT");
-
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_crc_skip(png_ptr, png_ptr->push_length);
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
- return;
- }
- else if (chunk_name == png_fdAT)
- {
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_ensure_sequence_number(png_ptr, 4);
-
- if (!(png_ptr->mode & PNG_HAVE_fcTL))
- {
- /* Discard trailing fdATs for frames other than the first */
- if (png_ptr->num_frames_read < 2)
- png_error(png_ptr, "out of place fdAT");
-
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_push_crc_skip(png_ptr, png_ptr->push_length);
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
- return;
- }
-
- else
- {
- /* frame data follows */
- png_ptr->idat_size = png_ptr->push_length - 4;
- png_ptr->mode |= PNG_HAVE_IDAT;
- png_ptr->process_mode = PNG_READ_IDAT_MODE;
-
- return;
- }
- }
-
- else if (chunk_name == png_fcTL)
- {
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_read_reset(png_ptr);
- png_ptr->mode &= ~PNG_HAVE_fcTL;
-
- png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
-
- if (!(png_ptr->mode & PNG_HAVE_fcTL))
- png_error(png_ptr, "missing required fcTL chunk");
-
- png_read_reinit(png_ptr, info_ptr);
- png_progressive_read_reset(png_ptr);
-
- if (png_ptr->frame_info_fn != NULL)
- (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
-
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
-
- return;
- }
-
- else
- {
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
- png_warning(png_ptr, "Skipped (ignored) a chunk "
- "between APNG chunks");
- png_push_crc_skip(png_ptr, png_ptr->push_length);
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
- return;
- }
-
- return;
- }
-#endif /* PNG_READ_APNG_SUPPORTED */
-
if (chunk_name == png_IDAT)
{
if (png_ptr->mode & PNG_AFTER_IDAT)
@@ -337,6 +234,7 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) png_error(png_ptr, "Missing PLTE before IDAT");
png_ptr->mode |= PNG_HAVE_IDAT;
+ png_ptr->process_mode = PNG_READ_IDAT_MODE;
if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
if (png_ptr->push_length == 0)
@@ -388,8 +286,8 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) if (chunk_name == png_PLTE)
png_ptr->mode |= PNG_HAVE_PLTE;
}
-
#endif
+
else if (chunk_name == png_PLTE)
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -402,9 +300,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) else if (chunk_name == png_IDAT)
{
-#ifdef PNG_READ_APNG_SUPPORTED
- png_have_info(png_ptr, info_ptr);
-#endif
png_ptr->idat_size = png_ptr->push_length;
png_ptr->process_mode = PNG_READ_IDAT_MODE;
png_push_have_info(png_ptr, info_ptr);
@@ -634,32 +529,8 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
}
-
#endif
-#ifdef PNG_READ_APNG_SUPPORTED
- else if (chunk_name == png_acTL)
- {
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
- }
- else if (chunk_name == png_fcTL)
- {
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
- }
-
-#endif /* PNG_READ_APNG_SUPPORTED */
else
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
@@ -861,11 +732,7 @@ png_push_read_IDAT(png_structrp png_ptr) png_byte chunk_tag[4];
/* TODO: this code can be commoned up with the same code in push_read */
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->buffer_size < 12)
-#else
if (png_ptr->buffer_size < 8)
-#endif
{
png_push_save_buffer(png_ptr);
return;
@@ -878,64 +745,17 @@ png_push_read_IDAT(png_structrp png_ptr) png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0)
- {
- if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)
- {
- png_ptr->process_mode = PNG_READ_CHUNK_MODE;
- if (png_ptr->frame_end_fn != NULL)
- (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
- png_ptr->num_frames_read++;
- return;
- }
- else
- {
- if (png_ptr->chunk_name == png_IEND)
- png_error(png_ptr, "Not enough image data");
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
- png_warning(png_ptr, "Skipping (ignoring) a chunk between "
- "APNG chunks");
- png_crc_finish(png_ptr, png_ptr->push_length);
- png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
- return;
- }
- }
- else
-#endif
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0)
-#else
if (png_ptr->chunk_name != png_IDAT)
-#endif
{
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
png_error(png_ptr, "Not enough compressed data");
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->frame_end_fn != NULL)
- (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
- png_ptr->num_frames_read++;
-#endif
-
return;
}
png_ptr->idat_size = png_ptr->push_length;
-
-#ifdef PNG_READ_APNG_SUPPORTED
- if (png_ptr->num_frames_read > 0)
- {
- png_ensure_sequence_number(png_ptr, 4);
- png_ptr->idat_size -= 4;
- }
-#endif
}
if (png_ptr->idat_size && png_ptr->save_buffer_size)
@@ -1013,15 +833,6 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, if (!(buffer_length > 0) || buffer == NULL)
png_error(png_ptr, "No IDAT data (internal error)");
-#ifdef PNG_READ_APNG_SUPPORTED
- /* If the app is not APNG-aware, decode only the first frame */
- if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0)
- {
- png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
- return;
- }
-#endif
-
/* This routine must process all the data it has been given
* before returning, calling the row callback as required to
* handle the uncompressed results.
@@ -1470,18 +1281,6 @@ png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr, png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
}
-#ifdef PNG_READ_APNG_SUPPORTED
-void PNGAPI
-png_set_progressive_frame_fn(png_structp png_ptr,
- png_progressive_frame_ptr frame_info_fn,
- png_progressive_frame_ptr frame_end_fn)
-{
- png_ptr->frame_info_fn = frame_info_fn;
- png_ptr->frame_end_fn = frame_end_fn;
- png_ptr->apng_flags |= PNG_APNG_APP;
-}
-#endif
-
png_voidp PNGAPI
png_get_progressive_ptr(png_const_structrp png_ptr)
{
diff --git a/plugins/AdvaImg/src/LibPNG/pngpriv.h b/plugins/AdvaImg/src/LibPNG/pngpriv.h index 9eb2fd229b..db8f33c37b 100644 --- a/plugins/AdvaImg/src/LibPNG/pngpriv.h +++ b/plugins/AdvaImg/src/LibPNG/pngpriv.h @@ -2,11 +2,11 @@ /* pngpriv.h - private declarations for use inside libpng
*
* For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2014 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.6.3 [July 18, 2013]
+ * Last changed in libpng 1.6.10 [March 6, 2014]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -112,9 +112,15 @@ * typically the target FPU. If the FPU has been set to NEON (-mfpu=neon
* with GCC) then the compiler will define __ARM_NEON__ and we can rely
* unconditionally on NEON instructions not crashing, otherwise we must
- * disable use of NEON instructions:
+ * disable use of NEON instructions.
+ *
+ * NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they
+ * can only be turned on automatically if that is supported too. If
+ * PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail
+ * to compile with an appropriate #error if ALIGNED_MEMORY has been turned
+ * off.
*/
-# ifdef __ARM_NEON__
+# if defined(__ARM_NEON__) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
# define PNG_ARM_NEON_OPT 2
# else
# define PNG_ARM_NEON_OPT 0
@@ -126,7 +132,49 @@ * callbacks to do this.
*/
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
-#endif
+
+ /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
+ * if possible - if __ARM_NEON__ is set and the compiler version is not known
+ * to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
+ * be:
+ *
+ * 1 The intrinsics code (the default with __ARM_NEON__)
+ * 2 The hand coded assembler (the default without __ARM_NEON__)
+ *
+ * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
+ * this is *NOT* supported and may cease to work even after a minor revision
+ * to libpng. It *is* valid to do this for testing purposes, e.g. speed
+ * testing or a new compiler, but the results should be communicated to the
+ * libpng implementation list for incorporation in the next minor release.
+ */
+# ifndef PNG_ARM_NEON_IMPLEMENTATION
+# ifdef __ARM_NEON__
+# if defined(__clang__)
+ /* At present it is unknown by the libpng developers which versions
+ * of clang support the intrinsics, however some or perhaps all
+ * versions do not work with the assembler so this may be
+ * irrelevant, so just use the default (do nothing here.)
+ */
+# elif defined(__GNUC__)
+ /* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to
+ * work, so if this *is* GCC, or G++, look for a version >4.5
+ */
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
+# define PNG_ARM_NEON_IMPLEMENTATION 2
+# endif /* no GNUC support */
+# endif /* __GNUC__ */
+# else /* !defined __ARM_NEON__ */
+ /* The 'intrinsics' code simply won't compile without this -mfpu=neon:
+ */
+# define PNG_ARM_NEON_IMPLEMENTATION 2
+# endif /* __ARM_NEON__ */
+# endif /* !defined PNG_ARM_NEON_IMPLEMENTATION */
+
+# ifndef PNG_ARM_NEON_IMPLEMENTATION
+ /* Use the intrinsics code by default. */
+# define PNG_ARM_NEON_IMPLEMENTATION 1
+# endif
+#endif /* PNG_ARM_NEON_OPT > 0 */
/* 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
@@ -206,6 +254,11 @@ extern PNG_FUNCTION(type, name, args, PNG_EMPTY attributes)
#endif
+#ifndef PNG_INTERNAL_CALLBACK
+# define PNG_INTERNAL_CALLBACK(type, name, args, attributes)\
+ extern PNG_FUNCTION(type, (PNGCBAPI name), args, PNG_EMPTY attributes)
+#endif
+
/* If floating or fixed point APIs are disabled they may still be compiled
* internally. To handle this make sure they are declared as the appropriate
* internal extern function (otherwise the symbol prefixing stuff won't work and
@@ -325,8 +378,6 @@ #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)
@@ -334,8 +385,6 @@ # 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
@@ -502,10 +551,6 @@ #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
/* 0x4000 (unused) */
#define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */
-#ifdef PNG_APNG_SUPPORTED
-#define PNG_HAVE_acTL 0x10000
-#define PNG_HAVE_fcTL 0x20000
-#endif
/* Flags for the transformations the PNG library does on the image data */
#define PNG_BGR 0x0001
@@ -727,16 +772,6 @@ #define png_tRNS PNG_U32(116, 82, 78, 83)
#define png_zTXt PNG_U32(122, 84, 88, 116)
-#ifdef PNG_APNG_SUPPORTED
-#define png_acTL PNG_U32( 97, 99, 84, 76)
-#define png_fcTL PNG_U32(102, 99, 84, 76)
-#define png_fdAT PNG_U32(102, 100, 65, 84)
-
-/* For png_struct.apng_flags: */
-#define PNG_FIRST_FRAME_HIDDEN 0x0001
-#define PNG_APNG_APP 0x0002
-#endif
-
/* 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.
*/
@@ -1190,7 +1225,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_finish_IDAT,(png_structrp png_ptr), PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr),
PNG_EMPTY);
/* Finish a row while reading, dealing with interlacing passes, etc. */
-#endif
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
/* Initialize the row buffers, etc. */
PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY);
@@ -1201,32 +1236,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr, png_inforp info_ptr),PNG_EMPTY);
#endif
-/* These are the functions that do the transformations */
-#ifdef PNG_READ_FILLER_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_read_filler,(png_row_infop row_info,
- png_bytep row, png_uint_32 filler, png_uint_32 flags),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_read_swap_alpha,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_write_swap_alpha,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_read_invert_alpha,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_write_invert_alpha,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
+/* Shared transform functions, defined in pngtran.c */
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
PNG_INTERNAL_FUNCTION(void,png_do_strip_channel,(png_row_infop row_info,
@@ -1246,96 +1256,16 @@ PNG_INTERNAL_FUNCTION(void,png_do_packswap,(png_row_infop row_info, png_bytep row),PNG_EMPTY);
#endif
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-PNG_INTERNAL_FUNCTION(int,png_do_rgb_to_gray,(png_structrp png_ptr,
- png_row_infop row_info, png_bytep row),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_gray_to_rgb,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_PACK_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_unpack,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_SHIFT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_unshift,(png_row_infop row_info,
- png_bytep row, png_const_color_8p sig_bits),PNG_EMPTY);
-#endif
-
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
PNG_INTERNAL_FUNCTION(void,png_do_invert,(png_row_infop row_info,
png_bytep row),PNG_EMPTY);
#endif
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_scale_16_to_8,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_chop,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_quantize,(png_row_infop row_info,
- png_bytep row, png_const_bytep palette_lookup,
- png_const_bytep quantize_lookup),PNG_EMPTY);
-
-# ifdef PNG_CORRECT_PALETTE_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_correct_palette,(png_structrp png_ptr,
- png_colorp palette, int num_palette),PNG_EMPTY);
-# endif
-#endif
-
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info,
png_bytep row),PNG_EMPTY);
#endif
-#ifdef PNG_WRITE_PACK_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_pack,(png_row_infop row_info,
- png_bytep row, png_uint_32 bit_depth),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_shift,(png_row_infop row_info,
- png_bytep row, png_const_color_8p bit_depth),PNG_EMPTY);
-#endif
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
- defined(PNG_READ_ALPHA_MODE_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_compose,(png_row_infop row_info,
- png_bytep row, png_structrp png_ptr),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_gamma,(png_row_infop row_info,
- png_bytep row, png_structrp png_ptr),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_encode_alpha,(png_row_infop row_info,
- png_bytep row, png_structrp png_ptr),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_expand_palette,(png_row_infop row_info,
- png_bytep row, png_const_colorp palette, png_const_bytep trans,
- int num_trans),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_do_expand,(png_row_infop row_info,
- png_bytep row, png_const_color_16p trans_color),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_expand_16,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
/* The following decodes the appropriate chunks, and does error correction,
* then calls the appropriate callback for the chunk if it is valid.
*/
@@ -1436,7 +1366,6 @@ PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr,
png_uint_32 chunk_name),PNG_EMPTY);
-#ifdef PNG_READ_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
/* This is the function that gets called for unknown chunks. The 'keep'
@@ -1445,16 +1374,14 @@ PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, * just skips the chunk or errors out if it is critical.
*/
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling,
(png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY);
/* Exactly as the API png_handle_as_unknown() except that the argument is a
* 32-bit chunk name, not a string.
*/
-#endif
-#endif /* PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
/* Handle the transformations for reading and writing */
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
@@ -1525,56 +1452,6 @@ PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr, #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_read_intrapixel,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_do_write_intrapixel,(png_row_infop row_info,
- png_bytep row),PNG_EMPTY);
-#endif
-
-#ifdef PNG_APNG_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den,
- png_byte dispose_op, png_byte blend_op),PNG_EMPTY);
-
-#ifdef PNG_READ_APNG_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr,
- png_infop info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr,
- png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr,
- png_infop info_ptr),PNG_EMPTY);
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr),
- PNG_EMPTY);
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-#endif /* PNG_READ_APNG_SUPPORTED */
-
-#ifdef PNG_WRITE_APNG_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr,
- png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_write_fcTL,(png_structp png_ptr,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den,
- png_byte dispose_op, png_byte blend_op),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr,
- png_const_bytep data, png_size_t length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr,
- png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY);
-#endif /* PNG_WRITE_APNG_SUPPORTED */
-#endif /* PNG_APNG_SUPPORTED */
-
/* Added at libpng version 1.6.0 */
#ifdef PNG_GAMMA_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr,
@@ -1916,7 +1793,7 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, png_size_t size),PNG_EMPTY);
#endif /* pCAL || sCAL */
-#if defined(PNG_READ_GAMMA_SUPPORTED) ||\
+#if defined(PNG_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
@@ -2007,11 +1884,11 @@ typedef struct png_control * errors that might occur. Returns true on success, false on failure (either
* of the function or as a result of a png_error.)
*/
-PNG_INTERNAL_FUNCTION(void,png_safe_error,(png_structp png_ptr,
+PNG_INTERNAL_CALLBACK(void,png_safe_error,(png_structp png_ptr,
png_const_charp error_message),PNG_NORETURN);
#ifdef PNG_WARNINGS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_safe_warning,(png_structp png_ptr,
+PNG_INTERNAL_CALLBACK(void,png_safe_warning,(png_structp png_ptr,
png_const_charp warning_message),PNG_EMPTY);
#else
# define png_safe_warning 0/*dummy argument*/
diff --git a/plugins/AdvaImg/src/LibPNG/pngread.c b/plugins/AdvaImg/src/LibPNG/pngread.c index 51ff8f3434..4b80ef2d46 100644 --- a/plugins/AdvaImg/src/LibPNG/pngread.c +++ b/plugins/AdvaImg/src/LibPNG/pngread.c @@ -1,8 +1,8 @@ /* pngread.c - read a PNG file
*
- * Last changed in libpng 1.6.1 [March 28, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -158,9 +158,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) else if (chunk_name == png_IDAT)
{
-#ifdef PNG_READ_APNG_SUPPORTED
- png_have_info(png_ptr, info_ptr);
-#endif
png_ptr->idat_size = length;
break;
}
@@ -250,17 +247,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) png_handle_iTXt(png_ptr, info_ptr, length);
#endif
-#ifdef PNG_READ_APNG_SUPPORTED
- else if (chunk_name == png_acTL)
- png_handle_acTL(png_ptr, info_ptr, length);
-
- else if (chunk_name == png_fcTL)
- png_handle_fcTL(png_ptr, info_ptr, length);
-
- else if (chunk_name == png_fdAT)
- png_handle_fdAT(png_ptr, info_ptr, length);
-#endif
-
else
png_handle_unknown(png_ptr, info_ptr, length,
PNG_HANDLE_CHUNK_AS_DEFAULT);
@@ -268,72 +254,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) }
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
-#ifdef PNG_READ_APNG_SUPPORTED
-void PNGAPI
-png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
-{
- png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
-
- png_debug(0, "Reading frame head");
-
- if (!(png_ptr->mode & PNG_HAVE_acTL))
- png_error(png_ptr, "attempt to png_read_frame_head() but "
- "no acTL present");
-
- /* do nothing for the main IDAT */
- if (png_ptr->num_frames_read == 0)
- return;
-
- png_read_reset(png_ptr);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
- png_ptr->mode &= ~PNG_HAVE_fcTL;
-
- have_chunk_after_DAT = 0;
- for (;;)
- {
- png_uint_32 length = png_read_chunk_header(png_ptr);
-
- if (png_ptr->chunk_name == png_IDAT)
- {
- /* discard trailing IDATs for the first frame */
- if (have_chunk_after_DAT || png_ptr->num_frames_read > 1)
- png_error(png_ptr, "png_read_frame_head(): out of place IDAT");
- png_crc_finish(png_ptr, length);
- }
-
- else if (png_ptr->chunk_name == png_fcTL)
- {
- png_handle_fcTL(png_ptr, info_ptr, length);
- have_chunk_after_DAT = 1;
- }
-
- else if (png_ptr->chunk_name == png_fdAT)
- {
- png_ensure_sequence_number(png_ptr, length);
-
- /* discard trailing fdATs for frames other than the first */
- if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1)
- png_crc_finish(png_ptr, length - 4);
- else if(png_ptr->mode & PNG_HAVE_fcTL)
- {
- png_ptr->idat_size = length - 4;
- png_ptr->mode |= PNG_HAVE_IDAT;
-
- break;
- }
- else
- png_error(png_ptr, "png_read_frame_head(): out of place fdAT");
- }
- else
- {
- png_warning(png_ptr, "Skipped (ignored) a chunk "
- "between APNG chunks");
- png_crc_finish(png_ptr, length);
- }
- }
-}
-#endif /* PNG_READ_APNG_SUPPORTED */
-
/* Optional call to update the users info_ptr structure */
void PNGAPI
png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
@@ -385,6 +305,72 @@ png_start_read_image(png_structrp png_ptr) #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Undoes intrapixel differencing,
+ * NOTE: this is apparently only supported in the 'sequential' reader.
+ */
+static void
+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 */
+
void PNGAPI
png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
{
@@ -569,7 +555,6 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) }
#endif
-
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
if (png_ptr->transformations)
png_do_read_transformations(png_ptr, &row_info);
@@ -796,11 +781,14 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_uint_32 length = png_read_chunk_header(png_ptr);
png_uint_32 chunk_name = png_ptr->chunk_name;
- if (chunk_name == png_IHDR)
+ if (chunk_name == png_IEND)
+ png_handle_IEND(png_ptr, info_ptr, length);
+
+ else 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);
+ else if (info_ptr == NULL)
+ png_crc_finish(png_ptr, length);
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
@@ -1016,8 +1004,6 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, int transforms,
voidp params)
{
- int row;
-
if (png_ptr == NULL || info_ptr == NULL)
return;
@@ -1029,126 +1015,149 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, png_error(png_ptr, "Image is too high to process with png_read_png()");
/* -------------- image transformations start here ------------------- */
+ /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM
+ * is not implemented. This will only happen in de-configured (non-default)
+ * libpng builds. The results can be unexpected - png_read_png may return
+ * short or mal-formed rows because the transform is skipped.
+ */
-#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.
*/
+#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
png_set_scale_16(png_ptr);
- }
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported");
#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)
+#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
png_set_strip_16(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported");
#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)
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
png_set_strip_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported");
#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)
+#ifdef PNG_READ_PACK_SUPPORTED
png_set_packing(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
#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)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
png_set_packswap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
#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);
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ png_set_expand(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported");
#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)
+#ifdef PNG_READ_INVERT_SUPPORTED
png_set_invert_mono(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
#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);
- }
+ if (transforms & PNG_TRANSFORM_SHIFT)
+#ifdef PNG_READ_SHIFT_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_sBIT)
+ png_set_shift(png_ptr, &info_ptr->sig_bit);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
#endif
-#ifdef PNG_READ_BGR_SUPPORTED
/* Flip the RGB pixels to BGR (or RGBA to BGRA) */
if (transforms & PNG_TRANSFORM_BGR)
+#ifdef PNG_READ_BGR_SUPPORTED
png_set_bgr(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
#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)
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
png_set_swap_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
#endif
-#ifdef PNG_READ_SWAP_SUPPORTED
/* Swap bytes of 16-bit files to least significant byte first */
if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+#ifdef PNG_READ_SWAP_SUPPORTED
png_set_swap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
#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)
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
png_set_invert_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
#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)
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
png_set_gray_to_rgb(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported");
#endif
/* Added at libpng-1.5.4 */
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
if (transforms & PNG_TRANSFORM_EXPAND_16)
+#ifdef PNG_READ_EXPAND_16_SUPPORTED
png_set_expand_16(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported");
#endif
/* We don't handle adding filler bytes */
@@ -1171,16 +1180,17 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, {
png_uint_32 iptr;
- info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
- info_ptr->height * (sizeof (png_bytep)));
+ info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr,
+ info_ptr->height * (sizeof (png_bytep))));
+
for (iptr=0; iptr<info_ptr->height; 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));
+ for (iptr = 0; iptr < info_ptr->height; iptr++)
+ info_ptr->row_pointers[iptr] = png_voidcast(png_bytep,
+ png_malloc(png_ptr, info_ptr->rowbytes));
}
png_read_image(png_ptr, info_ptr->row_pointers);
@@ -1189,9 +1199,7 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, /* 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 */
@@ -1205,12 +1213,11 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, /* Arguments to png_image_finish_read: */
/* Encoding of PNG data (used by the color-map code) */
-/* TODO: change these, dang, ANSI-C reserves the 'E' namespace. */
-# define E_NOTSET 0 /* File encoding not yet known */
-# define E_sRGB 1 /* 8-bit encoded to sRGB gamma */
-# define E_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */
-# define E_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */
-# define E_LINEAR8 4 /* 8-bit linear: only from a file value */
+# define P_NOTSET 0 /* File encoding not yet known */
+# define P_sRGB 1 /* 8-bit encoded to sRGB gamma */
+# define P_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */
+# define P_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */
+# define P_LINEAR8 4 /* 8-bit linear: only from a file value */
/* Color-map processing: after libpng has run on the PNG image further
* processing may be needed to conver the data to color-map indicies.
@@ -1241,7 +1248,7 @@ typedef struct png_voidp first_row;
ptrdiff_t row_bytes; /* step between rows */
int file_encoding; /* E_ values above */
- png_fixed_point gamma_to_linear; /* For E_FILE, reciprocal of gamma */
+ png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */
int colormap_processing; /* PNG_CMAP_ values above */
} png_image_read_control;
@@ -1373,7 +1380,7 @@ png_image_read_header(png_voidp argument) #ifdef PNG_COLORSPACE_SUPPORTED
/* Does the colorspace match sRGB? If there is no color endpoint
* (colorant) information assume yes, otherwise require the
- * 'ENDPOINTS_MATCHE_sRGB' colorspace flag to have been set. If the
+ * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set. If the
* colorspace has been determined to be invalid ignore it.
*/
if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags
@@ -1562,17 +1569,24 @@ png_image_skip_unused_chunks(png_structrp png_ptr) *
* Or image data handling:
*
- * tRNS, bKGD, gAMA, cHRM, sRGB, iCCP and sBIT.
+ * tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT.
*
* This provides a small performance improvement and eliminates any
* potential vulnerability to security problems in the unused chunks.
+ *
+ * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored
+ * too. This allows the simplified API to be compiled without iCCP support,
+ * however if the support is there the chunk is still checked to detect
+ * errors (which are unfortunately quite common.)
*/
{
static PNG_CONST png_byte chunks_to_process[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
103, 65, 77, 65, '\0', /* gAMA */
+# ifdef PNG_READ_iCCP_SUPPORTED
105, 67, 67, 80, '\0', /* iCCP */
+# endif
115, 66, 73, 84, '\0', /* sBIT */
115, 82, 71, 66, '\0', /* sRGB */
};
@@ -1609,25 +1623,25 @@ set_file_encoding(png_image_read_control *display) {
if (png_gamma_not_sRGB(g))
{
- display->file_encoding = E_FILE;
+ display->file_encoding = P_FILE;
display->gamma_to_linear = png_reciprocal(g);
}
else
- display->file_encoding = E_sRGB;
+ display->file_encoding = P_sRGB;
}
else
- display->file_encoding = E_LINEAR8;
+ display->file_encoding = P_LINEAR8;
}
static unsigned int
decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding)
{
- if (encoding == E_FILE) /* double check */
+ if (encoding == P_FILE) /* double check */
encoding = display->file_encoding;
- if (encoding == E_NOTSET) /* must be the file encoding */
+ if (encoding == P_NOTSET) /* must be the file encoding */
{
set_file_encoding(display);
encoding = display->file_encoding;
@@ -1635,18 +1649,18 @@ decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) switch (encoding)
{
- case E_FILE:
+ case P_FILE:
value = png_gamma_16bit_correct(value*257, display->gamma_to_linear);
break;
- case E_sRGB:
+ case P_sRGB:
value = png_sRGB_table[value];
break;
- case E_LINEAR:
+ case P_LINEAR:
break;
- case E_LINEAR8:
+ case P_LINEAR8:
value *= 257;
break;
@@ -1665,9 +1679,9 @@ png_colormap_compose(png_image_read_control *display, png_uint_32 background, int encoding)
{
/* The file value is composed on the background, the background has the given
- * encoding and so does the result, the file is encoded with E_FILE and the
+ * encoding and so does the result, the file is encoded with P_FILE and the
* file and alpha are 8-bit values. The (output) encoding will always be
- * E_LINEAR or E_sRGB.
+ * P_LINEAR or P_sRGB.
*/
png_uint_32 f = decode_gamma(display, foreground, foreground_encoding);
png_uint_32 b = decode_gamma(display, background, encoding);
@@ -1677,7 +1691,7 @@ png_colormap_compose(png_image_read_control *display, */
f = f * alpha + b * (255-alpha);
- if (encoding == E_LINEAR)
+ if (encoding == P_LINEAR)
{
/* Scale to 65535; divide by 255, approximately (in fact this is extremely
* accurate, it divides by 255.00000005937181414556, with no overflow.)
@@ -1687,13 +1701,13 @@ png_colormap_compose(png_image_read_control *display, f = (f+32768) >> 16;
}
- else /* E_sRGB */
+ else /* P_sRGB */
f = PNG_sRGB_FROM_LINEAR(f);
return f;
}
-/* NOTE: E_LINEAR values to this routine must be 16-bit, but E_FILE values must
+/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must
* be 8-bit.
*/
static void
@@ -1703,7 +1717,7 @@ png_create_colormap_entry(png_image_read_control *display, {
png_imagep image = display->image;
const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) ?
- E_LINEAR : E_sRGB;
+ P_LINEAR : P_sRGB;
const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
(red != green || green != blue);
@@ -1713,18 +1727,18 @@ png_create_colormap_entry(png_image_read_control *display, /* Update the cache with whether the file gamma is significantly different
* from sRGB.
*/
- if (encoding == E_FILE)
+ if (encoding == P_FILE)
{
- if (display->file_encoding == E_NOTSET)
+ if (display->file_encoding == P_NOTSET)
set_file_encoding(display);
- /* Note that the cached value may be E_FILE too, but if it is then the
+ /* Note that the cached value may be P_FILE too, but if it is then the
* gamma_to_linear member has been set.
*/
encoding = display->file_encoding;
}
- if (encoding == E_FILE)
+ if (encoding == P_FILE)
{
png_fixed_point g = display->gamma_to_linear;
@@ -1732,10 +1746,10 @@ png_create_colormap_entry(png_image_read_control *display, green = png_gamma_16bit_correct(green*257, g);
blue = png_gamma_16bit_correct(blue*257, g);
- if (convert_to_Y || output_encoding == E_LINEAR)
+ if (convert_to_Y || output_encoding == P_LINEAR)
{
alpha *= 257;
- encoding = E_LINEAR;
+ encoding = P_LINEAR;
}
else
@@ -1743,11 +1757,11 @@ png_create_colormap_entry(png_image_read_control *display, red = PNG_sRGB_FROM_LINEAR(red * 255);
green = PNG_sRGB_FROM_LINEAR(green * 255);
blue = PNG_sRGB_FROM_LINEAR(blue * 255);
- encoding = E_sRGB;
+ encoding = P_sRGB;
}
}
- else if (encoding == E_LINEAR8)
+ else if (encoding == P_LINEAR8)
{
/* This encoding occurs quite frequently in test cases because PngSuite
* includes a gAMA 1.0 chunk with most images.
@@ -1756,10 +1770,10 @@ png_create_colormap_entry(png_image_read_control *display, green *= 257;
blue *= 257;
alpha *= 257;
- encoding = E_LINEAR;
+ encoding = P_LINEAR;
}
- else if (encoding == E_sRGB && (convert_to_Y || output_encoding == E_LINEAR))
+ else if (encoding == P_sRGB && (convert_to_Y || output_encoding == P_LINEAR))
{
/* The values are 8-bit sRGB values, but must be converted to 16-bit
* linear.
@@ -1768,11 +1782,11 @@ png_create_colormap_entry(png_image_read_control *display, green = png_sRGB_table[green];
blue = png_sRGB_table[blue];
alpha *= 257;
- encoding = E_LINEAR;
+ encoding = P_LINEAR;
}
/* This is set if the color isn't gray but the output is. */
- if (encoding == E_LINEAR)
+ if (encoding == P_LINEAR)
{
if (convert_to_Y)
{
@@ -1780,7 +1794,7 @@ png_create_colormap_entry(png_image_read_control *display, png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green +
(png_uint_32)2366 * blue;
- if (output_encoding == E_LINEAR)
+ if (output_encoding == P_LINEAR)
y = (y + 16384) >> 15;
else
@@ -1789,19 +1803,19 @@ png_create_colormap_entry(png_image_read_control *display, y = (y + 128) >> 8;
y *= 255;
y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7);
- encoding = E_sRGB;
+ encoding = P_sRGB;
}
blue = red = green = y;
}
- else if (output_encoding == E_sRGB)
+ else if (output_encoding == P_sRGB)
{
red = PNG_sRGB_FROM_LINEAR(red * 255);
green = PNG_sRGB_FROM_LINEAR(green * 255);
blue = PNG_sRGB_FROM_LINEAR(blue * 255);
alpha = PNG_DIV257(alpha);
- encoding = E_sRGB;
+ encoding = P_sRGB;
}
}
@@ -1810,7 +1824,7 @@ png_create_colormap_entry(png_image_read_control *display, /* Store the value. */
{
-# ifdef PNG_FORMAT_BGR_SUPPORTED
+# ifdef PNG_FORMAT_AFIRST_SUPPORTED
const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else
@@ -1822,7 +1836,7 @@ png_create_colormap_entry(png_image_read_control *display, # define bgr 0
# endif
- if (output_encoding == E_LINEAR)
+ if (output_encoding == P_LINEAR)
{
png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap);
@@ -1877,7 +1891,7 @@ png_create_colormap_entry(png_image_read_control *display, }
}
- else /* output encoding is E_sRGB */
+ else /* output encoding is P_sRGB */
{
png_bytep entry = png_voidcast(png_bytep, display->colormap);
@@ -1919,7 +1933,7 @@ make_gray_file_colormap(png_image_read_control *display) unsigned int i;
for (i=0; i<256; ++i)
- png_create_colormap_entry(display, i, i, i, i, 255, E_FILE);
+ png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
return i;
}
@@ -1930,7 +1944,7 @@ make_gray_colormap(png_image_read_control *display) unsigned int i;
for (i=0; i<256; ++i)
- png_create_colormap_entry(display, i, i, i, i, 255, E_sRGB);
+ png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
return i;
}
@@ -1969,13 +1983,13 @@ make_ga_colormap(png_image_read_control *display) while (i < 231)
{
unsigned int gray = (i * 256 + 115) / 231;
- png_create_colormap_entry(display, i++, gray, gray, gray, 255, E_sRGB);
+ png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB);
}
/* 255 is used here for the component values for consistency with the code
* that undoes premultiplication in pngwrite.c.
*/
- png_create_colormap_entry(display, i++, 255, 255, 255, 0, E_sRGB);
+ png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB);
for (a=1; a<5; ++a)
{
@@ -1983,7 +1997,7 @@ make_ga_colormap(png_image_read_control *display) for (g=0; g<6; ++g)
png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,
- E_sRGB);
+ P_sRGB);
}
return i;
@@ -2007,7 +2021,7 @@ make_rgb_colormap(png_image_read_control *display) for (b=0; b<6; ++b)
png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,
- E_sRGB);
+ P_sRGB);
}
}
@@ -2030,11 +2044,11 @@ png_image_read_colormap(png_voidp argument) const png_structrp png_ptr = image->opaque->png_ptr;
const png_uint_32 output_format = image->format;
const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) ?
- E_LINEAR : E_sRGB;
+ P_LINEAR : P_sRGB;
unsigned int cmap_entries;
unsigned int output_processing; /* Output processing option */
- unsigned int data_encoding = E_NOTSET; /* Encoding libpng must produce */
+ unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */
/* Background information; the background color and the index of this color
* in the color-map if it exists (else 256).
@@ -2054,7 +2068,7 @@ png_image_read_colormap(png_voidp argument) png_ptr->num_trans > 0) /* alpha in input */ &&
((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */)
{
- if (output_encoding == E_LINEAR) /* compose on black */
+ if (output_encoding == P_LINEAR) /* compose on black */
back_b = back_g = back_r = 0;
else if (display->background == NULL /* no way to remove it */)
@@ -2078,7 +2092,7 @@ png_image_read_colormap(png_voidp argument) }
}
- else if (output_encoding == E_LINEAR)
+ else if (output_encoding == P_LINEAR)
back_b = back_r = back_g = 65535;
else
@@ -2136,7 +2150,7 @@ png_image_read_colormap(png_voidp argument) trans = png_ptr->trans_color.gray;
if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0)
- back_alpha = output_encoding == E_LINEAR ? 65535 : 255;
+ back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
}
/* png_create_colormap_entry just takes an RGBA and writes the
@@ -2154,7 +2168,7 @@ png_image_read_colormap(png_voidp argument) */
if (i != trans)
png_create_colormap_entry(display, i, val, val, val, 255,
- E_FILE/*8-bit with file gamma*/);
+ P_FILE/*8-bit with file gamma*/);
/* Else this entry is transparent. The colors don't matter if
* there is an alpha channel (back_alpha == 0), but it does no
@@ -2170,7 +2184,7 @@ png_image_read_colormap(png_voidp argument) }
/* We need libpng to preserve the original encoding. */
- data_encoding = E_FILE;
+ data_encoding = P_FILE;
/* The rows from libpng, while technically gray values, are now also
* color-map indicies; however, they may need to be expanded to 1
@@ -2199,7 +2213,7 @@ png_image_read_colormap(png_voidp argument) * ensuring that the corresponding gray level matches the background
* color exactly.
*/
- data_encoding = E_sRGB;
+ data_encoding = P_sRGB;
if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "gray[16] color-map: too few entries");
@@ -2223,7 +2237,7 @@ png_image_read_colormap(png_voidp argument) png_color_16 c;
png_uint_32 gray = back_g;
- if (output_encoding == E_LINEAR)
+ if (output_encoding == P_LINEAR)
{
gray = PNG_sRGB_FROM_LINEAR(gray * 255);
@@ -2231,7 +2245,7 @@ png_image_read_colormap(png_voidp argument) * matches.
*/
png_create_colormap_entry(display, gray, back_g, back_g,
- back_g, 65535, E_LINEAR);
+ back_g, 65535, P_LINEAR);
}
/* The background passed to libpng, however, must be the
@@ -2252,7 +2266,7 @@ png_image_read_colormap(png_voidp argument) break;
}
- back_alpha = output_encoding == E_LINEAR ? 65535 : 255;
+ back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
}
/* output_processing means that the libpng-processed row will be
@@ -2289,7 +2303,7 @@ png_image_read_colormap(png_voidp argument) * worry about tRNS matching - tRNS is ignored if there is an alpha
* channel.
*/
- data_encoding = E_sRGB;
+ data_encoding = P_sRGB;
if (output_format & PNG_FORMAT_FLAG_ALPHA)
{
@@ -2332,13 +2346,13 @@ png_image_read_colormap(png_voidp argument) cmap_entries = make_gray_colormap(display);
- if (output_encoding == E_LINEAR)
+ if (output_encoding == P_LINEAR)
{
gray = PNG_sRGB_FROM_LINEAR(gray * 255);
/* And make sure the corresponding palette entry matches. */
png_create_colormap_entry(display, gray, back_g, back_g,
- back_g, 65535, E_LINEAR);
+ back_g, 65535, P_LINEAR);
}
/* The background passed to libpng, however, must be the sRGB
@@ -2369,7 +2383,7 @@ png_image_read_colormap(png_voidp argument) {
png_uint_32 gray = (i * 256 + 115) / 231;
png_create_colormap_entry(display, i++, gray, gray, gray,
- 255, E_sRGB);
+ 255, P_sRGB);
}
/* NOTE: this preserves the full precision of the application
@@ -2377,7 +2391,7 @@ png_image_read_colormap(png_voidp argument) */
background_index = i;
png_create_colormap_entry(display, i++, back_r, back_g, back_b,
- output_encoding == E_LINEAR ? 65535U : 255U, output_encoding);
+ output_encoding == P_LINEAR ? 65535U : 255U, output_encoding);
/* For non-opaque input composite on the sRGB background - this
* requires inverting the encoding for each component. The input
@@ -2387,7 +2401,7 @@ png_image_read_colormap(png_voidp argument) * represents. Consequently 'G' is always sRGB encoded, while
* 'A' is linear. We need the linear background colors.
*/
- if (output_encoding == E_sRGB) /* else already linear */
+ if (output_encoding == P_sRGB) /* else already linear */
{
/* This may produce a value not exactly matching the
* background, but that's ok because these numbers are only
@@ -2417,7 +2431,7 @@ png_image_read_colormap(png_voidp argument) png_create_colormap_entry(display, i++,
PNG_sRGB_FROM_LINEAR(gray + back_rx),
PNG_sRGB_FROM_LINEAR(gray + back_gx),
- PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, E_sRGB);
+ PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
}
}
@@ -2444,7 +2458,7 @@ png_image_read_colormap(png_voidp argument) */
png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,
-1);
- data_encoding = E_sRGB;
+ data_encoding = P_sRGB;
/* The output will now be one or two 8-bit gray or gray+alpha
* channels. The more complex case arises when the input has alpha.
@@ -2489,7 +2503,7 @@ png_image_read_colormap(png_voidp argument) png_gamma_not_sRGB(png_ptr->colorspace.gamma))
{
cmap_entries = make_gray_file_colormap(display);
- data_encoding = E_FILE;
+ data_encoding = P_FILE;
}
else
@@ -2508,18 +2522,18 @@ png_image_read_colormap(png_voidp argument) * it. Achieve this simply by ensuring that the entry
* selected for the background really is the background color.
*/
- if (data_encoding == E_FILE) /* from the fixup above */
+ if (data_encoding == P_FILE) /* from the fixup above */
{
/* The app supplied a gray which is in output_encoding, we
- * need to convert it to a value of the input (E_FILE)
+ * need to convert it to a value of the input (P_FILE)
* encoding then set this palette entry to the required
* output encoding.
*/
- if (output_encoding == E_sRGB)
- gray = png_sRGB_table[gray]; /* now E_LINEAR */
+ if (output_encoding == P_sRGB)
+ gray = png_sRGB_table[gray]; /* now P_LINEAR */
gray = PNG_DIV257(png_gamma_16bit_correct(gray,
- png_ptr->colorspace.gamma)); /* now E_FILE */
+ png_ptr->colorspace.gamma)); /* now P_FILE */
/* And make sure the corresponding palette entry contains
* exactly the required sRGB value.
@@ -2528,14 +2542,14 @@ png_image_read_colormap(png_voidp argument) back_g, 0/*unused*/, output_encoding);
}
- else if (output_encoding == E_LINEAR)
+ else if (output_encoding == P_LINEAR)
{
gray = PNG_sRGB_FROM_LINEAR(gray * 255);
/* And make sure the corresponding palette entry matches.
*/
png_create_colormap_entry(display, gray, back_g, back_g,
- back_g, 0/*unused*/, E_LINEAR);
+ back_g, 0/*unused*/, P_LINEAR);
}
/* The background passed to libpng, however, must be the
@@ -2565,7 +2579,7 @@ png_image_read_colormap(png_voidp argument) * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube.
* Consequently we always want libpng to produce sRGB data.
*/
- data_encoding = E_sRGB;
+ data_encoding = P_sRGB;
/* Is there any transparency or alpha? */
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
@@ -2585,7 +2599,7 @@ png_image_read_colormap(png_voidp argument) /* Add a transparent entry. */
png_create_colormap_entry(display, cmap_entries, 255, 255,
- 255, 0, E_sRGB);
+ 255, 0, P_sRGB);
/* This is stored as the background index for the processing
* algorithm.
@@ -2606,7 +2620,7 @@ png_image_read_colormap(png_voidp argument) */
for (b=0; b<256; b = (b << 1) | 0x7f)
png_create_colormap_entry(display, cmap_entries++,
- r, g, b, 128, E_sRGB);
+ r, g, b, 128, P_sRGB);
}
}
@@ -2635,7 +2649,7 @@ png_image_read_colormap(png_voidp argument) png_create_colormap_entry(display, cmap_entries, back_r,
back_g, back_b, 0/*unused*/, output_encoding);
- if (output_encoding == E_LINEAR)
+ if (output_encoding == P_LINEAR)
{
r = PNG_sRGB_FROM_LINEAR(back_r * 255);
g = PNG_sRGB_FROM_LINEAR(back_g * 255);
@@ -2675,11 +2689,11 @@ png_image_read_colormap(png_voidp argument) */
for (b=0; b<256; b = (b << 1) | 0x7f)
png_create_colormap_entry(display, cmap_entries++,
- png_colormap_compose(display, r, E_sRGB, 128,
+ png_colormap_compose(display, r, P_sRGB, 128,
back_r, output_encoding),
- png_colormap_compose(display, g, E_sRGB, 128,
+ png_colormap_compose(display, g, P_sRGB, 128,
back_g, output_encoding),
- png_colormap_compose(display, b, E_sRGB, 128,
+ png_colormap_compose(display, b, P_sRGB, 128,
back_b, output_encoding),
0/*unused*/, output_encoding);
}
@@ -2738,7 +2752,7 @@ png_image_read_colormap(png_voidp argument) num_trans = 0;
output_processing = PNG_CMAP_NONE;
- data_encoding = E_FILE; /* Don't change from color-map indicies */
+ data_encoding = P_FILE; /* Don't change from color-map indicies */
cmap_entries = png_ptr->num_palette;
if (cmap_entries > 256)
cmap_entries = 256;
@@ -2760,13 +2774,13 @@ png_image_read_colormap(png_voidp argument) * on the sRGB color in 'back'.
*/
png_create_colormap_entry(display, i,
- png_colormap_compose(display, colormap[i].red, E_FILE,
+ png_colormap_compose(display, colormap[i].red, P_FILE,
trans[i], back_r, output_encoding),
- png_colormap_compose(display, colormap[i].green, E_FILE,
+ png_colormap_compose(display, colormap[i].green, P_FILE,
trans[i], back_g, output_encoding),
- png_colormap_compose(display, colormap[i].blue, E_FILE,
+ png_colormap_compose(display, colormap[i].blue, P_FILE,
trans[i], back_b, output_encoding),
- output_encoding == E_LINEAR ? trans[i] * 257U :
+ output_encoding == P_LINEAR ? trans[i] * 257U :
trans[i],
output_encoding);
}
@@ -2775,7 +2789,7 @@ png_image_read_colormap(png_voidp argument) else
png_create_colormap_entry(display, i, colormap[i].red,
colormap[i].green, colormap[i].blue,
- i < num_trans ? trans[i] : 255U, E_FILE/*8-bit*/);
+ i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);
}
/* The PNG data may have indicies packed in fewer than 8 bits, it
@@ -2803,12 +2817,12 @@ png_image_read_colormap(png_voidp argument) png_error(png_ptr, "bad data option (internal error)");
break;
- case E_sRGB:
+ case P_sRGB:
/* Change to 8-bit sRGB */
png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
/* FALL THROUGH */
- case E_FILE:
+ case P_FILE:
if (png_ptr->bit_depth > 8)
png_set_scale_16(png_ptr);
break;
@@ -2885,7 +2899,6 @@ png_image_read_and_map(png_voidp argument) break;
default:
- passes = 0;
png_error(png_ptr, "unknown interlace type");
}
@@ -3204,7 +3217,6 @@ png_image_read_composite(png_voidp argument) break;
default:
- passes = 0;
png_error(png_ptr, "unknown interlace type");
}
@@ -3353,11 +3365,15 @@ png_image_read_background(png_voidp argument) break;
default:
- passes = 0;
png_error(png_ptr, "unknown interlace type");
}
- switch (png_get_bit_depth(png_ptr, info_ptr))
+ /* Use direct access to info_ptr here because otherwise the simplified API
+ * would require PNG_EASY_ACCESS_SUPPORTED (just for this.) Note this is
+ * checking the value after libpng expansions, not the original value in the
+ * PNG.
+ */
+ switch (info_ptr->bit_depth)
{
default:
png_error(png_ptr, "unexpected bit depth");
@@ -3365,7 +3381,7 @@ png_image_read_background(png_voidp argument) case 8:
/* 8-bit sRGB gray values with an alpha channel; the alpha channel is
- * to be removed by composing on a backgroundi: either the row if
+ * to be removed by composing on a background: either the row if
* display->background is NULL or display->background->green if not.
* Unlike the code above ALPHA_OPTIMIZED has *not* been done.
*/
@@ -3505,8 +3521,10 @@ png_image_read_background(png_voidp argument) unsigned int outchannels = 1+preserve_alpha;
int swap_alpha = 0;
- if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST))
- swap_alpha = 1;
+# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
+ if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST))
+ swap_alpha = 1;
+# endif
for (pass = 0; pass < passes; ++pass)
{
diff --git a/plugins/AdvaImg/src/LibPNG/pngrio.c b/plugins/AdvaImg/src/LibPNG/pngrio.c index 2b9c103202..6c02457a0c 100644 --- a/plugins/AdvaImg/src/LibPNG/pngrio.c +++ b/plugins/AdvaImg/src/LibPNG/pngrio.c @@ -1,8 +1,8 @@ /* pngrio.c - functions for data input
*
- * Last changed in libpng 1.6.0 [February 14, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -102,6 +102,7 @@ png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, png_ptr->read_data_fn = read_data_fn;
#endif
+#ifdef PNG_WRITE_SUPPORTED
/* It is an error to write to a read device */
if (png_ptr->write_data_fn != NULL)
{
@@ -110,6 +111,7 @@ png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, "Can't set both read_data_fn and write_data_fn in the"
" same structure");
}
+#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_ptr->output_flush_fn = NULL;
diff --git a/plugins/AdvaImg/src/LibPNG/pngrtran.c b/plugins/AdvaImg/src/LibPNG/pngrtran.c index 90698c598f..ae5deaeacc 100644 --- a/plugins/AdvaImg/src/LibPNG/pngrtran.c +++ b/plugins/AdvaImg/src/LibPNG/pngrtran.c @@ -1,8 +1,8 @@ /* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.6.2 [April 25, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -1116,19 +1116,25 @@ png_init_palette_transformations(png_structrp png_ptr) /* Ignore if all the entries are opaque (unlikely!) */
for (i=0; i<png_ptr->num_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_transparency = 1;
input_has_alpha = 1;
+ break;
+ }
+ }
}
/* 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
+ * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
* and ENCODE_ALPHA are irrelevant.
*/
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
@@ -1193,7 +1199,7 @@ png_init_rgb_transformations(png_structrp png_ptr) 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
+ * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
* and ENCODE_ALPHA are irrelevant.
*/
# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
@@ -1357,12 +1363,12 @@ png_init_read_transformations(png_structrp png_ptr) * 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
+ * 15) PNG_INVERT_ALPHA
+ * 16) PNG_SHIFT
+ * 17) PNG_PACK
+ * 18) PNG_BGR
+ * 19) PNG_PACKSWAP
+ * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
* 21) PNG_SWAP_ALPHA
* 22) PNG_SWAP_BYTES
* 23) PNG_USER_TRANSFORM [must be last]
@@ -1878,31 +1884,34 @@ png_init_read_transformations(png_structrp png_ptr) * 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; i<istop; ++i)
- {
- int component = png_ptr->palette[i].red;
+ if (shift > 0 && shift < 8)
+ for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].red;
- component >>= shift;
- png_ptr->palette[i].red = (png_byte)component;
- }
+ 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; i<istop; ++i)
- {
- int component = png_ptr->palette[i].green;
+ if (shift > 0 && shift < 8)
+ for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].green;
- component >>= shift;
- png_ptr->palette[i].green = (png_byte)component;
- }
+ 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; i<istop; ++i)
- {
- int component = png_ptr->palette[i].blue;
+ if (shift > 0 && shift < 8)
+ for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].blue;
- component >>= shift;
- png_ptr->palette[i].blue = (png_byte)component;
- }
+ component >>= shift;
+ png_ptr->palette[i].blue = (png_byte)component;
+ }
}
#endif /* PNG_READ_SHIFT_SUPPORTED */
}
@@ -1933,6 +1942,9 @@ png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) info_ptr->bit_depth = 8;
info_ptr->num_trans = 0;
+
+ if (png_ptr->palette == NULL)
+ png_error (png_ptr, "Palette is NULL in indexed image");
}
else
{
@@ -2111,303 +2123,6 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED) #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_structrp 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.6 the new flag is set only for
- * all transformations, however in practice the ROW_INIT always gets done on
- * demand, if necessary.
- */
- 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_CHECK_FOR_INVALID_INDEX_SUPPORTED
- /* Added at libpng-1.5.10 */
- if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
- png_ptr->num_palette_max >= 0)
- png_do_check_palette_indexes(png_ptr, row_info);
-#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
@@ -2415,7 +2130,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) * the numbers 0 or 1. If you would rather they contain 0 and 255, use
* png_do_shift() after this.
*/
-void /* PRIVATE */
+static void
png_do_unpack(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_unpack");
@@ -2513,7 +2228,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row) * a row of bit depth 8, but only 5 are significant, this will shift
* the values back to 0 through 31.
*/
-void /* PRIVATE */
+static void
png_do_unshift(png_row_infop row_info, png_bytep row,
png_const_color_8p sig_bits)
{
@@ -2652,7 +2367,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row, #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
/* Scale rows of bit depth 16 down to 8 accurately */
-void /* PRIVATE */
+static void
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_scale_16_to_8");
@@ -2710,7 +2425,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) #endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-void /* PRIVATE */
+static void
/* Simply discard the low byte. This was the default behavior prior
* to libpng-1.5.4.
*/
@@ -2738,7 +2453,7 @@ png_do_chop(png_row_infop row_info, png_bytep row) #endif
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_read_swap_alpha");
@@ -2835,7 +2550,7 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) #endif
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
png_uint_32 row_width;
@@ -2937,7 +2652,7 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) #ifdef PNG_READ_FILLER_SUPPORTED
/* Add filler channel if we have RGB color */
-void /* PRIVATE */
+static void
png_do_read_filler(png_row_infop row_info, png_bytep row,
png_uint_32 filler, png_uint_32 flags)
{
@@ -3124,7 +2839,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Expand grayscale files to RGB, with or without alpha */
-void /* PRIVATE */
+static void
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
{
png_uint_32 i;
@@ -3263,7 +2978,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) * calculated to make the sum 32768. This will result in different rounding
* to that used above.
*/
-int /* PRIVATE */
+static int
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
{
@@ -3457,73 +3172,14 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) 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 */
+static void
png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
#ifdef PNG_READ_GAMMA_SUPPORTED
@@ -4263,7 +3919,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) * is 16, use gamma_16_table and gamma_shift. Build these with
* build_gamma_table().
*/
-void /* PRIVATE */
+static void
png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
png_const_bytep gamma_table = png_ptr->gamma_table;
@@ -4464,7 +4120,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr) * linear.) Called only with color types that have an alpha channel. Needs the
* from_1 tables.
*/
-void /* PRIVATE */
+static void
png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
png_uint_32 row_width = row_info->width;
@@ -4530,7 +4186,7 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) /* Expands a palette row to an RGB or RGBA row depending
* upon whether you supply trans and num_trans.
*/
-void /* PRIVATE */
+static void
png_do_expand_palette(png_row_infop row_info, png_bytep row,
png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
{
@@ -4683,7 +4339,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, /* 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 */
+static void
png_do_expand(png_row_infop row_info, png_bytep row,
png_const_color_16p trans_color)
{
@@ -4913,7 +4569,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, /* 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 */
+static void
png_do_expand_16(png_row_infop row_info, png_bytep row)
{
if (row_info->bit_depth == 8 &&
@@ -4941,7 +4597,7 @@ png_do_expand_16(png_row_infop row_info, png_bytep row) #endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
-void /* PRIVATE */
+static void
png_do_quantize(png_row_infop row_info, png_bytep row,
png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
{
@@ -5033,69 +4689,303 @@ png_do_quantize(png_row_infop row_info, png_bytep row, }
}
#endif /* PNG_READ_QUANTIZE_SUPPORTED */
-#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Undoes intrapixel differencing */
+/* 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_intrapixel(png_row_infop row_info, png_bytep row)
+png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
{
- png_debug(1, "in png_do_read_intrapixel");
+ png_debug(1, "in png_do_read_transformations");
- if (
- (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ if (png_ptr->row_buf == NULL)
{
- int bytes_per_pixel;
- png_uint_32 row_width = row_info->width;
+ /* 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");
+ }
- if (row_info->bit_depth == 8)
- {
- png_bytep rp;
- png_uint_32 i;
+ /* 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.6 the new flag is set only for
+ * all transformations, however in practice the ROW_INIT always gets done on
+ * demand, if necessary.
+ */
+ 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");
+ }
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 3;
+#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 (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 4;
+ 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
- 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);
- }
+ png_do_expand(row_info, png_ptr->row_buf + 1,
+ NULL);
}
- else if (row_info->bit_depth == 16)
- {
- png_bytep rp;
- png_uint_32 i;
+ }
+#endif
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 6;
+#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
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 8;
+#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);
- else
- return;
+ 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");
- 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);
- }
+ 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_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_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_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Added at libpng-1.5.10 */
+ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max >= 0)
+ png_do_check_palette_indexes(png_ptr, row_info);
+#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_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
}
-#endif /* PNG_MNG_FEATURES_SUPPORTED */
+
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
#endif /* PNG_READ_SUPPORTED */
diff --git a/plugins/AdvaImg/src/LibPNG/pngrutil.c b/plugins/AdvaImg/src/LibPNG/pngrutil.c index 1e7e0d6903..2079db54f7 100644 --- a/plugins/AdvaImg/src/LibPNG/pngrutil.c +++ b/plugins/AdvaImg/src/LibPNG/pngrutil.c @@ -1,8 +1,8 @@ /* pngrutil.c - utilities to read a PNG file
*
- * Last changed in libpng 1.6.3 [July 18, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -227,10 +227,7 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip) }
else
- {
- png_chunk_benign_error(png_ptr, "CRC error");
- return (0);
- }
+ png_chunk_error(png_ptr, "CRC error");
return (1);
}
@@ -278,6 +275,10 @@ png_crc_error(png_structrp png_ptr) return (0);
}
+#if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
+ defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\
+ defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\
+ defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED)
/* Manage the read buffer; this simply reallocates the buffer if it is not small
* enough (or if it is not allocated). The routine returns a pointer to the
* buffer; if an error occurs and 'warn' is set the routine returns NULL, else
@@ -310,21 +311,17 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) else if (warn < 2) /* else silent */
{
-#ifdef PNG_WARNINGS_SUPPORTED
if (warn)
png_chunk_warning(png_ptr, "insufficient memory to read chunk");
+
else
-#endif
- {
-#ifdef PNG_ERROR_TEXT_SUPPORTED
png_chunk_error(png_ptr, "insufficient memory to read chunk");
-#endif
- }
}
}
return buffer;
}
+#endif /* PNG_READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */
/* png_inflate_claim: claim the zstream for some nefarious purpose that involves
* decompression. Returns Z_OK on success, else a zlib error code. It checks
@@ -821,11 +818,6 @@ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) filter_type = buf[11];
interlace_type = buf[12];
-#ifdef PNG_READ_APNG_SUPPORTED
- png_ptr->first_frame_width = width;
- png_ptr->first_frame_height = height;
-#endif
-
/* Set internal variables */
png_ptr->width = width;
png_ptr->height = height;
@@ -986,22 +978,15 @@ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) 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");
- }
+ return;
else
- {
- png_chunk_warning(png_ptr, "CRC error");
- return;
- }
+ png_chunk_error(png_ptr, "CRC error");
}
/* 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
@@ -1112,13 +1097,12 @@ png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) void /* PRIVATE */
png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- unsigned int truelen;
+ unsigned int truelen, i;
+ png_byte sample_depth;
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_chunk_error(png_ptr, "missing IHDR");
@@ -1137,10 +1121,16 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) }
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
truelen = 3;
+ sample_depth = 8;
+ }
else
+ {
truelen = png_ptr->channels;
+ sample_depth = png_ptr->bit_depth;
+ }
if (length != truelen || length > 4)
{
@@ -1149,11 +1139,19 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) return;
}
+ buf[0] = buf[1] = buf[2] = buf[3] = sample_depth;
png_crc_read(png_ptr, buf, truelen);
if (png_crc_finish(png_ptr, 0))
return;
+ for (i=0; i<truelen; ++i)
+ if (buf[i] == 0 || buf[i] > sample_depth)
+ {
+ png_chunk_benign_error(png_ptr, "invalid");
+ return;
+ }
+
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
{
png_ptr->sig_bit.red = buf[0];
@@ -1423,7 +1421,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) (sizeof local_buffer), &length,
profile + (sizeof profile_header), &size, 0);
- /* Still expect a a buffer error because we expect
+ /* Still expect a buffer error because we expect
* there to be some tag data!
*/
if (size == 0)
@@ -2700,179 +2698,6 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) }
#endif
-#ifdef PNG_READ_APNG_SUPPORTED
-void /* PRIVATE */
-png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
-{
- png_byte data[8];
- png_uint_32 num_frames;
- png_uint_32 num_plays;
- png_uint_32 didSet;
-
- png_debug(1, "in png_handle_acTL");
-
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- {
- png_error(png_ptr, "Missing IHDR before acTL");
- }
- else if (png_ptr->mode & PNG_HAVE_IDAT)
- {
- png_warning(png_ptr, "Invalid acTL after IDAT skipped");
- png_crc_finish(png_ptr, length);
- return;
- }
- else if (png_ptr->mode & PNG_HAVE_acTL)
- {
- png_warning(png_ptr, "Duplicate acTL skipped");
- png_crc_finish(png_ptr, length);
- return;
- }
- else if (length != 8)
- {
- png_warning(png_ptr, "acTL with invalid length skipped");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- png_crc_read(png_ptr, data, 8);
- png_crc_finish(png_ptr, 0);
-
- num_frames = png_get_uint_31(png_ptr, data);
- num_plays = png_get_uint_31(png_ptr, data + 4);
-
- /* the set function will do error checking on num_frames */
- didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays);
- if(didSet)
- png_ptr->mode |= PNG_HAVE_acTL;
-}
-
-void /* PRIVATE */
-png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
-{
- png_byte data[22];
- png_uint_32 width;
- png_uint_32 height;
- png_uint_32 x_offset;
- png_uint_32 y_offset;
- png_uint_16 delay_num;
- png_uint_16 delay_den;
- png_byte dispose_op;
- png_byte blend_op;
-
- png_debug(1, "in png_handle_fcTL");
-
- png_ensure_sequence_number(png_ptr, length);
-
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- {
- png_error(png_ptr, "Missing IHDR before fcTL");
- }
- else if (png_ptr->mode & PNG_HAVE_IDAT)
- {
- /* for any frames other then the first this message may be misleading,
- * but correct. PNG_HAVE_IDAT is unset before the frame head is read
- * i can't think of a better message */
- png_warning(png_ptr, "Invalid fcTL after IDAT skipped");
- png_crc_finish(png_ptr, length-4);
- return;
- }
- else if (png_ptr->mode & PNG_HAVE_fcTL)
- {
- png_warning(png_ptr, "Duplicate fcTL within one frame skipped");
- png_crc_finish(png_ptr, length-4);
- return;
- }
- else if (length != 26)
- {
- png_warning(png_ptr, "fcTL with invalid length skipped");
- png_crc_finish(png_ptr, length-4);
- return;
- }
-
- png_crc_read(png_ptr, data, 22);
- png_crc_finish(png_ptr, 0);
-
- width = png_get_uint_31(png_ptr, data);
- height = png_get_uint_31(png_ptr, data + 4);
- x_offset = png_get_uint_31(png_ptr, data + 8);
- y_offset = png_get_uint_31(png_ptr, data + 12);
- delay_num = png_get_uint_16(data + 16);
- delay_den = png_get_uint_16(data + 18);
- dispose_op = data[20];
- blend_op = data[21];
-
- if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0))
- {
- png_warning(png_ptr, "fcTL for the first frame must have zero offset");
- return;
- }
-
- if (info_ptr != NULL)
- {
- if (png_ptr->num_frames_read == 0 &&
- (width != info_ptr->width || height != info_ptr->height))
- {
- png_warning(png_ptr, "size in first frame's fcTL must match "
- "the size in IHDR");
- return;
- }
-
- /* The set function will do more error checking */
- png_set_next_frame_fcTL(png_ptr, info_ptr, width, height,
- x_offset, y_offset, delay_num, delay_den,
- dispose_op, blend_op);
-
- png_read_reinit(png_ptr, info_ptr);
-
- png_ptr->mode |= PNG_HAVE_fcTL;
- }
-}
-
-void /* PRIVATE */
-png_have_info(png_structp png_ptr, png_infop info_ptr)
-{
- if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL))
- {
- png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
- info_ptr->num_frames++;
- }
-}
-
-void /* PRIVATE */
-png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
-{
- png_ensure_sequence_number(png_ptr, length);
-
- /* This function is only called from png_read_end(), png_read_info(),
- * and png_push_read_chunk() which means that:
- * - the user doesn't want to read this frame
- * - or this is an out-of-place fdAT
- * in either case it is safe to ignore the chunk with a warning */
- png_warning(png_ptr, "ignoring fdAT chunk");
- png_crc_finish(png_ptr, length - 4);
- PNG_UNUSED(info_ptr)
-}
-
-void /* PRIVATE */
-png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length)
-{
- png_byte data[4];
- png_uint_32 sequence_number;
-
- if (length < 4)
- png_error(png_ptr, "invalid fcTL or fdAT chunk found");
-
- png_crc_read(png_ptr, data, 4);
- sequence_number = png_get_uint_31(png_ptr, data);
-
- if (sequence_number != png_ptr->next_seq_num)
- png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence "
- "number found");
-
- png_ptr->next_seq_num++;
-}
-#endif /* PNG_READ_APNG_SUPPORTED */
-
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
static int
@@ -3110,9 +2935,8 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, }
# endif
}
-# else /* no store support! */
+# else /* no store support: the chunk must be handled by the user callback */
PNG_UNUSED(info_ptr)
-# error untested code (reading unknown chunks with no store support)
# endif
/* Regardless of the error handling below the cached data (if any) can be
@@ -4050,7 +3874,6 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, if (pb < pa) pa = pb, a = b;
if (pc < pa) a = c;
- c = b;
a += *row;
*row++ = (png_byte)a;
}
@@ -4058,7 +3881,8 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, static void
png_init_filter_functions(png_structrp pp)
- /* This function is called once for every PNG image to set the
+ /* This function is called once for every PNG image (except for PNG images
+ * that only use PNG_FILTER_VALUE_NONE for all rows) to set the
* implementations required to reverse the filtering of PNG rows. Reversing
* the filter is the first transformation performed on the row data. It is
* performed in place, therefore an implementation can be selected based on
@@ -4100,10 +3924,13 @@ png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic
* implementations. See png_init_filter_functions above.
*/
- if (pp->read_filter[0] == NULL)
- png_init_filter_functions(pp);
if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST)
+ {
+ if (pp->read_filter[0] == NULL)
+ png_init_filter_functions(pp);
+
pp->read_filter[filter-1](row_info, row, prev_row);
+ }
}
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
@@ -4128,38 +3955,6 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, uInt avail_in;
png_bytep buffer;
-#ifdef PNG_READ_APNG_SUPPORTED
- png_uint_32 bytes_to_skip = 0;
-
- while (png_ptr->idat_size == 0 || bytes_to_skip != 0)
- {
- png_crc_finish(png_ptr, bytes_to_skip);
- bytes_to_skip = 0;
-
- png_ptr->idat_size = png_read_chunk_header(png_ptr);
- if (png_ptr->num_frames_read == 0)
- {
- if (png_ptr->chunk_name != png_IDAT)
- png_error(png_ptr, "Not enough image data");
- }
- else
- {
- if (png_ptr->chunk_name == png_IEND)
- png_error(png_ptr, "Not enough image data");
- if (png_ptr->chunk_name != png_fdAT)
- {
- png_warning(png_ptr, "Skipped (ignored) a chunk "
- "between APNG chunks");
- bytes_to_skip = png_ptr->idat_size;
- continue;
- }
-
- png_ensure_sequence_number(png_ptr, png_ptr->idat_size);
-
- png_ptr->idat_size -= 4;
- }
- }
-#else
while (png_ptr->idat_size == 0)
{
png_crc_finish(png_ptr, 0);
@@ -4171,7 +3966,6 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, if (png_ptr->chunk_name != png_IDAT)
png_error(png_ptr, "Not enough image data");
}
-#endif /* PNG_READ_APNG_SUPPORTED */
avail_in = png_ptr->IDAT_read_size;
@@ -4235,9 +4029,6 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
-#ifdef PNG_READ_APNG_SUPPORTED
- png_ptr->num_frames_read++;
-#endif
if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
png_chunk_benign_error(png_ptr, "Extra compressed data");
@@ -4683,80 +4474,4 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) png_ptr->flags |= PNG_FLAG_ROW_INIT;
}
-
-#ifdef PNG_READ_APNG_SUPPORTED
-/* This function is to be called after the main IDAT set has been read and
- * before a new IDAT is read. It resets some parts of png_ptr
- * to make them usable by the read functions again */
-void /* PRIVATE */
-png_read_reset(png_structp png_ptr)
-{
- png_ptr->mode &= ~PNG_HAVE_IDAT;
- png_ptr->mode &= ~PNG_AFTER_IDAT;
- png_ptr->row_number = 0;
- png_ptr->pass = 0;
-}
-
-void /* PRIVATE */
-png_read_reinit(png_structp png_ptr, png_infop info_ptr)
-{
- png_ptr->width = info_ptr->next_frame_width;
- png_ptr->height = info_ptr->next_frame_height;
- png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
- png_ptr->info_rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,
- png_ptr->width);
- if (png_ptr->prev_row)
- memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
-}
-
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-/* same as png_read_reset() but for the progressive reader */
-void /* PRIVATE */
-png_progressive_read_reset(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[] = {0, 4, 0, 2, 0, 1, 0};
-
- /* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
-
- /* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
-
- /* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
-
- 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;
- }
- png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED;
- if (inflateReset(&(png_ptr->zstream)) != Z_OK)
- png_error(png_ptr, "inflateReset failed");
- png_ptr->zstream.avail_in = 0;
- png_ptr->zstream.next_in = 0;
- 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;
-}
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
-#endif /* PNG_READ_APNG_SUPPORTED */
#endif /* PNG_READ_SUPPORTED */
diff --git a/plugins/AdvaImg/src/LibPNG/pngset.c b/plugins/AdvaImg/src/LibPNG/pngset.c index 4f076c5951..6a7417a39c 100644 --- a/plugins/AdvaImg/src/LibPNG/pngset.c +++ b/plugins/AdvaImg/src/LibPNG/pngset.c @@ -1,7 +1,7 @@ /* pngset.c - storage of image information into info struct
*
- * Last changed in libpng 1.6.3 [July 18, 2013]
+ * Last changed in libpng 1.6.8 [December 19, 2013]
* Copyright (c) 1998-2013 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.)
@@ -239,11 +239,6 @@ png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr, info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
-
-#ifdef PNG_APNG_SUPPORTED
- /* for non-animated png. this may be overwritten from an acTL chunk later */
- info_ptr->num_frames = 1;
-#endif
}
#ifdef PNG_oFFs_SUPPORTED
@@ -532,7 +527,7 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, # endif
))
{
- png_chunk_report(png_ptr, "Invalid palette", PNG_CHUNK_ERROR);
+ png_error(png_ptr, "Invalid palette");
return;
}
@@ -1070,147 +1065,6 @@ png_set_sPLT(png_const_structrp png_ptr, }
#endif /* PNG_sPLT_SUPPORTED */
-#ifdef PNG_APNG_SUPPORTED
-png_uint_32 PNGAPI
-png_set_acTL(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 num_frames, png_uint_32 num_plays)
-{
- png_debug1(1, "in %s storage function", "acTL");
-
- if (png_ptr == NULL || info_ptr == NULL)
- {
- png_warning(png_ptr,
- "Call to png_set_acTL() with NULL png_ptr "
- "or info_ptr ignored");
- return (0);
- }
- if (num_frames == 0)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set acTL with num_frames zero");
- return (0);
- }
- if (num_frames > PNG_UINT_31_MAX)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set acTL with num_frames > 2^31-1");
- return (0);
- }
- if (num_plays > PNG_UINT_31_MAX)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set acTL with num_plays "
- "> 2^31-1");
- return (0);
- }
-
- info_ptr->num_frames = num_frames;
- info_ptr->num_plays = num_plays;
-
- info_ptr->valid |= PNG_INFO_acTL;
-
- return (1);
-}
-
-/* delay_num and delay_den can hold any 16-bit values including zero */
-png_uint_32 PNGAPI
-png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den,
- png_byte dispose_op, png_byte blend_op)
-{
- png_debug1(1, "in %s storage function", "fcTL");
-
- if (png_ptr == NULL || info_ptr == NULL)
- {
- png_warning(png_ptr,
- "Call to png_set_fcTL() with NULL png_ptr or info_ptr "
- "ignored");
- return (0);
- }
-
- png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
- delay_num, delay_den, dispose_op, blend_op);
-
- if (blend_op == PNG_BLEND_OP_OVER)
- {
- if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) &&
- !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
- {
- png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless "
- "and wasteful for opaque images, ignored");
- blend_op = PNG_BLEND_OP_SOURCE;
- }
- }
-
- info_ptr->next_frame_width = width;
- info_ptr->next_frame_height = height;
- info_ptr->next_frame_x_offset = x_offset;
- info_ptr->next_frame_y_offset = y_offset;
- info_ptr->next_frame_delay_num = delay_num;
- info_ptr->next_frame_delay_den = delay_den;
- info_ptr->next_frame_dispose_op = dispose_op;
- info_ptr->next_frame_blend_op = blend_op;
-
- info_ptr->valid |= PNG_INFO_fcTL;
-
- return (1);
-}
-
-void /* PRIVATE */
-png_ensure_fcTL_is_valid(png_structp png_ptr,
- png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den,
- png_byte dispose_op, png_byte blend_op)
-{
- if (width > PNG_UINT_31_MAX)
- png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
- if (height > PNG_UINT_31_MAX)
- png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
- if (x_offset > PNG_UINT_31_MAX)
- png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
- if (y_offset > PNG_UINT_31_MAX)
- png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
- if (width + x_offset > png_ptr->first_frame_width ||
- height + y_offset > png_ptr->first_frame_height)
- png_error(png_ptr, "dimensions of a frame are greater than"
- "the ones in IHDR");
-
- if (dispose_op != PNG_DISPOSE_OP_NONE &&
- dispose_op != PNG_DISPOSE_OP_BACKGROUND &&
- dispose_op != PNG_DISPOSE_OP_PREVIOUS)
- png_error(png_ptr, "invalid dispose_op in fcTL");
-
- if (blend_op != PNG_BLEND_OP_SOURCE &&
- blend_op != PNG_BLEND_OP_OVER)
- png_error(png_ptr, "invalid blend_op in fcTL");
-
- PNG_UNUSED(delay_num)
- PNG_UNUSED(delay_den)
-}
-
-png_uint_32 PNGAPI
-png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr,
- png_byte is_hidden)
-{
- png_debug(1, "in png_first_frame_is_hidden()");
-
- if (png_ptr == NULL)
- return 0;
-
- if (is_hidden)
- png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
- else
- png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN;
-
- PNG_UNUSED(info_ptr)
-
- return 1;
-}
-#endif /* PNG_APNG_SUPPORTED */
-
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
static png_byte
check_location(png_const_structrp png_ptr, int location)
diff --git a/plugins/AdvaImg/src/LibPNG/pngstruct.h b/plugins/AdvaImg/src/LibPNG/pngstruct.h index 1d73b80c86..b6935534c5 100644 --- a/plugins/AdvaImg/src/LibPNG/pngstruct.h +++ b/plugins/AdvaImg/src/LibPNG/pngstruct.h @@ -409,27 +409,6 @@ struct png_struct_def png_byte filter_type;
#endif
-#ifdef PNG_APNG_SUPPORTED
- png_uint_32 apng_flags;
- png_uint_32 next_seq_num; /* next fcTL/fdAT chunk sequence number */
- png_uint_32 first_frame_width;
- png_uint_32 first_frame_height;
-
-#ifdef PNG_READ_APNG_SUPPORTED
- png_uint_32 num_frames_read; /* incremented after all image data of */
- /* a frame is read */
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
- png_progressive_frame_ptr frame_info_fn; /* frame info read callback */
- png_progressive_frame_ptr frame_end_fn; /* frame data read callback */
-#endif
-#endif
-
-#ifdef PNG_WRITE_APNG_SUPPORTED
- png_uint_32 num_frames_to_write;
- png_uint_32 num_frames_written;
-#endif
-#endif /* PNG_APNG_SUPPORTED */
-
/* 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 */
diff --git a/plugins/AdvaImg/src/LibPNG/pngtest.c b/plugins/AdvaImg/src/LibPNG/pngtest.c index d92fade77f..7eeb0b8839 100644 --- a/plugins/AdvaImg/src/LibPNG/pngtest.c +++ b/plugins/AdvaImg/src/LibPNG/pngtest.c @@ -1,8 +1,8 @@ /* pngtest.c - a simple test program to test libpng
*
- * Last changed in libpng 1.6.2 [April 25, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -45,6 +45,11 @@ /* Known chunks that exist in pngtest.png must be supported or pngtest will fail
* simply as a result of re-ordering them. This may be fixed in 1.7
+ *
+ * pngtest allocates a single row buffer for each row and overwrites it,
+ * therefore if the write side doesn't support the writing of interlaced images
+ * nothing can be done for an interlaced image (and the code below will fail
+ * horribly trying to write extra data after writing garbage).
*/
#if defined PNG_READ_SUPPORTED && /* else nothing can be done */\
defined PNG_READ_bKGD_SUPPORTED &&\
@@ -58,9 +63,15 @@ defined PNG_READ_sRGB_SUPPORTED &&\
defined PNG_READ_tEXt_SUPPORTED &&\
defined PNG_READ_tIME_SUPPORTED &&\
- defined PNG_READ_zTXt_SUPPORTED
+ defined PNG_READ_zTXt_SUPPORTED &&\
+ defined PNG_WRITE_INTERLACING_SUPPORTED
+
+#ifdef PNG_ZLIB_HEADER
+# include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
+#else
+# include "zlib.h"
+#endif
-#include "zlib.h"
/* Copied from pngpriv.h but only used in error messages below. */
#ifndef PNG_ZBUF_SIZE
# define PNG_ZBUF_SIZE 8192
@@ -116,10 +127,6 @@ static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */ static int error_count = 0; /* count calls to png_error */
static int warning_count = 0; /* count calls to png_warning */
-#ifdef __TURBOC__
-#include <mem.h>
-#endif
-
/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
#ifndef png_jmpbuf
# define png_jmpbuf(png_ptr) png_ptr->jmpbuf
@@ -573,7 +580,8 @@ png_debug_free(png_structp png_ptr, png_voidp ptr) /* We must free the list element too, but first kill
the memory that is to be freed. */
memset(ptr, 0x55, pinfo->size);
- png_free_default(png_ptr, pinfo);
+ if (pinfo)
+ free(pinfo);
pinfo = NULL;
break;
}
@@ -592,7 +600,8 @@ png_debug_free(png_structp png_ptr, png_voidp ptr) if (verbose)
printf("Freeing %p\n", ptr);
- png_free_default(png_ptr, ptr);
+ if (ptr)
+ free(ptr);
ptr = NULL;
}
#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */
@@ -658,8 +667,8 @@ set_location(png_structp png_ptr, struct user_chunk_data *data, int what) return 1; /* handled */
}
-static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr,
- png_unknown_chunkp chunk)
+static int PNGCBAPI
+read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
{
struct user_chunk_data *my_user_chunk_data =
(struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);
@@ -723,18 +732,18 @@ static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, static void
write_sTER_chunk(png_structp write_ptr)
{
- png_byte png_sTER[5] = {115, 84, 69, 82, '\0'};
+ png_byte sTER[5] = {115, 84, 69, 82, '\0'};
if (verbose)
fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode);
- png_write_chunk(write_ptr, png_sTER, &user_chunk_data.sTER_mode, 1);
+ png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1);
}
static void
write_vpAg_chunk(png_structp write_ptr)
{
- png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'};
+ png_byte vpAg[5] = {118, 112, 65, 103, '\0'};
png_byte vpag_chunk_data[9];
@@ -747,7 +756,7 @@ write_vpAg_chunk(png_structp write_ptr) png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width);
png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height);
vpag_chunk_data[8] = user_chunk_data.vpAg_units;
- png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9);
+ png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9);
}
static void
@@ -828,6 +837,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) png_structp write_ptr;
png_infop write_info_ptr;
png_infop write_end_info_ptr;
+ int interlace_preserved = 1;
#else
png_structp write_ptr = NULL;
png_infop write_info_ptr = NULL;
@@ -836,7 +846,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) png_bytep row_buf;
png_uint_32 y;
png_uint_32 width, height;
- int num_pass, pass;
+ int num_pass = 1, pass;
int bit_depth, color_type;
row_buf = NULL;
@@ -1042,10 +1052,26 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) &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);
+#ifndef PNG_READ_INTERLACING_SUPPORTED
+ /* num_pass will not be set below, set it here if the image is
+ * interlaced: what happens is that write interlacing is *not* turned
+ * on an the partial interlaced rows are written directly.
+ */
+ switch (interlace_type)
+ {
+ case PNG_INTERLACE_NONE:
+ num_pass = 1;
+ break;
+
+ case PNG_INTERLACE_ADAM7:
+ num_pass = 7;
+ break;
+
+ default:
+ png_error(read_ptr, "invalid interlace type");
+ /*NOT REACHED*/
+ }
#endif
}
}
@@ -1338,14 +1364,10 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) #endif /* SINGLE_ROWBUF_ALLOC */
pngtest_debug("Writing row data");
-#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
- defined(PNG_WRITE_INTERLACING_SUPPORTED)
+#ifdef PNG_READ_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;
+ if (png_set_interlace_handling(write_ptr) != num_pass)
+ png_error(write_ptr, "png_set_interlace_handling: inconsistent num_pass");
#endif
#ifdef PNGTEST_TIMING
@@ -1391,11 +1413,13 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) }
}
-#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);
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+# 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
#endif
pngtest_debug("Reading and writing end_info data");
@@ -1575,15 +1599,14 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) }
#ifdef PNG_WRITE_SUPPORTED /* else nothing was written */
+ if (interlace_preserved) /* else the files will be changed */
{
- int wrote_question = 0;
-
for (;;)
{
+ static int wrote_question = 0;
png_size_t num_in, num_out;
char inbuf[256], outbuf[256];
-
num_in = fread(inbuf, 1, sizeof inbuf, fpin);
num_out = fread(outbuf, 1, sizeof outbuf, fpout);
@@ -1963,9 +1986,9 @@ main(void) fprintf(STDERR,
" test ignored because libpng was not built with read support\n");
/* And skip this test */
- return 77;
+ return PNG_LIBPNG_VER < 10600 ? 0 : 77;
}
#endif
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_3 Your_png_h_is_not_version_1_6_3;
+typedef png_libpng_version_1_6_10 Your_png_h_is_not_version_1_6_10;
diff --git a/plugins/AdvaImg/src/LibPNG/pngtrans.c b/plugins/AdvaImg/src/LibPNG/pngtrans.c index 99c6ea9d3b..4c88708a52 100644 --- a/plugins/AdvaImg/src/LibPNG/pngtrans.c +++ b/plugins/AdvaImg/src/LibPNG/pngtrans.c @@ -1,8 +1,8 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
- * Last changed in libpng 1.6.2 [April 25, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -57,7 +57,9 @@ png_set_packing(png_structrp png_ptr) if (png_ptr->bit_depth < 8)
{
png_ptr->transformations |= PNG_PACK;
- png_ptr->usr_bit_depth = 8;
+# ifdef PNG_WRITE_SUPPORTED
+ png_ptr->usr_bit_depth = 8;
+# endif
}
}
#endif
diff --git a/plugins/AdvaImg/src/LibPNG/pngwio.c b/plugins/AdvaImg/src/LibPNG/pngwio.c index c5fca989c8..5bc813832d 100644 --- a/plugins/AdvaImg/src/LibPNG/pngwio.c +++ b/plugins/AdvaImg/src/LibPNG/pngwio.c @@ -1,8 +1,8 @@ /* pngwio.c - functions for data output
*
- * Last changed in libpng 1.6.0 [February 14, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -149,8 +149,11 @@ png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr, # else
png_ptr->output_flush_fn = output_flush_fn;
# endif
+#else
+ PNG_UNUSED(output_flush_fn)
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+#ifdef PNG_READ_SUPPORTED
/* It is an error to read while writing a png file */
if (png_ptr->read_data_fn != NULL)
{
@@ -160,5 +163,6 @@ png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr, "Can't set both read_data_fn and write_data_fn in the"
" same structure");
}
+#endif
}
#endif /* PNG_WRITE_SUPPORTED */
diff --git a/plugins/AdvaImg/src/LibPNG/pngwrite.c b/plugins/AdvaImg/src/LibPNG/pngwrite.c index 8a27cfc53c..a75d6fd2be 100644 --- a/plugins/AdvaImg/src/LibPNG/pngwrite.c +++ b/plugins/AdvaImg/src/LibPNG/pngwrite.c @@ -1,8 +1,8 @@ /* pngwrite.c - general routines to write a PNG file
*
- * Last changed in libpng 1.6.2 [April 25, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -127,10 +127,6 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) * application continues writing the PNG. So check the 'invalid' flag here
* too.
*/
-#ifdef PNG_WRITE_APNG_SUPPORTED
- if (info_ptr->valid & PNG_INFO_acTL)
- png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays);
-#endif
#ifdef PNG_GAMMA_SUPPORTED
# ifdef PNG_WRITE_gAMA_SUPPORTED
if (!(info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) &&
@@ -356,11 +352,6 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) if (!(png_ptr->mode & PNG_HAVE_IDAT))
png_error(png_ptr, "No IDATs written into file");
-#ifdef PNG_WRITE_APNG_SUPPORTED
- if (png_ptr->num_frames_written != png_ptr->num_frames_to_write)
- png_error(png_ptr, "Not enough frames written");
-#endif
-
#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
if (png_ptr->num_palette_max > png_ptr->num_palette)
png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
@@ -616,6 +607,71 @@ png_write_image(png_structrp png_ptr, png_bytepp image) }
}
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Performs intrapixel differencing */
+static void
+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 */
+
/* Called by user to write a row of image data */
void PNGAPI
png_write_row(png_structrp png_ptr, png_const_bytep row)
@@ -1490,81 +1546,117 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr, if (png_ptr == NULL || info_ptr == NULL)
return;
+ if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
+ {
+ png_app_error(png_ptr, "no rows for png_write_image to write");
+ 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)
+#ifdef PNG_WRITE_INVERT_SUPPORTED
png_set_invert_mono(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
#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);
+ if (transforms & PNG_TRANSFORM_SHIFT)
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_sBIT)
+ png_set_shift(png_ptr, &info_ptr->sig_bit);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
#endif
-#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes */
if (transforms & PNG_TRANSFORM_PACKING)
- png_set_packing(png_ptr);
+#ifdef PNG_WRITE_PACK_SUPPORTED
+ png_set_packing(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
#endif
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
/* Swap location of alpha bytes from ARGB to RGBA */
if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
png_set_swap_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
#endif
+ /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
+ * RGB, note that the code expects the input color type to be G or RGB; no
+ * alpha channel.
+ */
+ if (transforms &
+ (PNG_TRANSFORM_STRIP_FILLER_AFTER|PNG_TRANSFORM_STRIP_FILLER_BEFORE))
+ {
#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);
+ if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
+ {
+ if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
+ png_app_error(png_ptr,
+ "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
+
+ /* Continue if ignored - this is the pre-1.6.10 behavior */
+ 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);
+ else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
+ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
#endif
+ }
-#ifdef PNG_WRITE_BGR_SUPPORTED
/* Flip BGR pixels to RGB */
if (transforms & PNG_TRANSFORM_BGR)
+#ifdef PNG_WRITE_BGR_SUPPORTED
png_set_bgr(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
#endif
-#ifdef PNG_WRITE_SWAP_SUPPORTED
/* Swap bytes of 16-bit files to most significant byte first */
if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+#ifdef PNG_WRITE_SWAP_SUPPORTED
png_set_swap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
#endif
-#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
/* Swap bits of 1, 2, 4 bit packed pixel formats */
if (transforms & PNG_TRANSFORM_PACKSWAP)
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
png_set_packswap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
#endif
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel from opacity to transparency */
if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
png_set_invert_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
#endif
/* ----------------------- end of transformations ------------------- */
/* Write the bits */
- if (info_ptr->valid & PNG_INFO_IDAT)
- png_write_image(png_ptr, info_ptr->row_pointers);
+ 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
@@ -1647,14 +1739,16 @@ png_write_image_16bit(png_voidp argument) if (image->format & PNG_FORMAT_FLAG_ALPHA)
{
- if (image->format & PNG_FORMAT_FLAG_AFIRST)
- {
- aindex = -1;
- ++input_row; /* To point to the first component */
- ++output_row;
- }
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if (image->format & PNG_FORMAT_FLAG_AFIRST)
+ {
+ aindex = -1;
+ ++input_row; /* To point to the first component */
+ ++output_row;
+ }
- else
+ else
+# endif
aindex = channels;
}
@@ -1803,14 +1897,16 @@ png_write_image_8bit(png_voidp argument) png_bytep row_end;
int aindex;
- if (image->format & PNG_FORMAT_FLAG_AFIRST)
- {
- aindex = -1;
- ++input_row; /* To point to the first component */
- ++output_row;
- }
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if (image->format & PNG_FORMAT_FLAG_AFIRST)
+ {
+ aindex = -1;
+ ++input_row; /* To point to the first component */
+ ++output_row;
+ }
- else
+ else
+# endif
aindex = channels;
/* Use row_end in place of a loop counter: */
@@ -1890,7 +1986,8 @@ png_image_set_PLTE(png_image_write_control *display) const png_uint_32 format = image->format;
const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
-# ifdef PNG_FORMAT_BGR_SUPPORTED
+# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
+ defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else
@@ -2336,42 +2433,4 @@ png_image_write_to_file(png_imagep image, const char *file_name, }
#endif /* PNG_STDIO_SUPPORTED */
#endif /* SIMPLIFIED_WRITE */
-
-#ifdef PNG_WRITE_APNG_SUPPORTED
-void PNGAPI
-png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
- png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
- png_byte blend_op)
-{
- png_debug(1, "in png_write_frame_head");
-
- /* there is a chance this has been set after png_write_info was called,
- * so it would be set but not written. is there a way to be sure? */
- if (!(info_ptr->valid & PNG_INFO_acTL))
- png_error(png_ptr, "png_write_frame_head(): acTL not set");
-
- png_write_reset(png_ptr);
-
- png_write_reinit(png_ptr, info_ptr, width, height);
-
- if ( !(png_ptr->num_frames_written == 0 &&
- (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) )
- png_write_fcTL(png_ptr, width, height, x_offset, y_offset,
- delay_num, delay_den, dispose_op, blend_op);
-
- PNG_UNUSED(row_pointers)
-}
-
-void PNGAPI
-png_write_frame_tail(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_write_frame_tail");
-
- png_ptr->num_frames_written++;
-
- PNG_UNUSED(info_ptr)
-}
-#endif /* PNG_WRITE_APNG_SUPPORTED */
#endif /* PNG_WRITE_SUPPORTED */
diff --git a/plugins/AdvaImg/src/LibPNG/pngwtran.c b/plugins/AdvaImg/src/LibPNG/pngwtran.c index 2cdd7c95c2..03eabf0b0b 100644 --- a/plugins/AdvaImg/src/LibPNG/pngwtran.c +++ b/plugins/AdvaImg/src/LibPNG/pngwtran.c @@ -1,8 +1,8 @@ /* pngwtran.c - transforms the data in a row for PNG writers
*
- * Last changed in libpng 1.6.0 [February 14, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -14,90 +14,14 @@ #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_structrp 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 */
+static void
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
{
png_debug(1, "in png_do_pack");
@@ -242,7 +166,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) * would pass 3 as bit_depth, and this routine would translate the
* data to 0 to 15.
*/
-void /* PRIVATE */
+static void
png_do_shift(png_row_infop row_info, png_bytep row,
png_const_color_8p bit_depth)
{
@@ -381,7 +305,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, #endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_swap_alpha");
@@ -475,7 +399,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) #endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_invert_alpha");
@@ -568,70 +492,81 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) }
}
#endif
-#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Undoes intrapixel differencing */
+/* Transform the data according to the user's wishes. The order of
+ * transformations is significant.
+ */
void /* PRIVATE */
-png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
+png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
{
- png_debug(1, "in png_do_write_intrapixel");
+ png_debug(1, "in png_do_write_transformations");
- 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 (png_ptr == NULL)
+ return;
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 3;
+#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
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 4;
+#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
- else
- return;
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
+ if (png_ptr->transformations & PNG_PACKSWAP)
+ png_do_packswap(row_info, png_ptr->row_buf + 1);
+#endif
- 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_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_16BIT_SUPPORTED
- else if (row_info->bit_depth == 16)
- {
- png_bytep rp;
- png_uint_32 i;
+#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
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 6;
+#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
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 8;
+#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
- else
- return;
+#ifdef PNG_WRITE_BGR_SUPPORTED
+ if (png_ptr->transformations & PNG_BGR)
+ png_do_bgr(row_info, png_ptr->row_buf + 1);
+#endif
- 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 */
- }
+#ifdef PNG_WRITE_INVERT_SUPPORTED
+ if (png_ptr->transformations & PNG_INVERT_MONO)
+ png_do_invert(row_info, png_ptr->row_buf + 1);
+#endif
}
-#endif /* PNG_MNG_FEATURES_SUPPORTED */
+#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
#endif /* PNG_WRITE_SUPPORTED */
diff --git a/plugins/AdvaImg/src/LibPNG/pngwutil.c b/plugins/AdvaImg/src/LibPNG/pngwutil.c index 9f3444e75f..da4ec20dd8 100644 --- a/plugins/AdvaImg/src/LibPNG/pngwutil.c +++ b/plugins/AdvaImg/src/LibPNG/pngwutil.c @@ -898,11 +898,6 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, /* Write the chunk */
png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
-#ifdef PNG_WRITE_APNG_SUPPORTED
- png_ptr->first_frame_width = width;
- png_ptr->first_frame_height = height;
-#endif
-
if (!(png_ptr->do_filter))
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
@@ -1081,15 +1076,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, optimize_cmf(data, png_image_size(png_ptr));
# endif
-# ifdef PNG_WRITE_APNG_SUPPORTED
- if (png_ptr->num_frames_written == 0)
-# endif
png_write_complete_chunk(png_ptr, png_IDAT, data, size);
-# ifdef PNG_WRITE_APNG_SUPPORTED
- else
- png_write_fdAT(png_ptr, data, size);
-# endif /* PNG_WRITE_APNG_SUPPORTED */
-
png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->zstream.next_out = data;
@@ -1135,15 +1122,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, optimize_cmf(data, png_image_size(png_ptr));
# endif
-# ifdef PNG_WRITE_APNG_SUPPORTED
- if (png_ptr->num_frames_written == 0)
-# endif
png_write_complete_chunk(png_ptr, png_IDAT, data, size);
-# ifdef PNG_WRITE_APNG_SUPPORTED
- else
- png_write_fdAT(png_ptr, data, size);
-# endif /* PNG_WRITE_APNG_SUPPORTED */
-
png_ptr->zstream.avail_out = 0;
png_ptr->zstream.next_out = NULL;
png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
@@ -1955,82 +1934,6 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) }
#endif
-#ifdef PNG_WRITE_APNG_SUPPORTED
-void /* PRIVATE */
-png_write_acTL(png_structp png_ptr,
- png_uint_32 num_frames, png_uint_32 num_plays)
-{
- png_byte buf[8];
-
- png_debug(1, "in png_write_acTL");
-
- png_ptr->num_frames_to_write = num_frames;
-
- if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
- num_frames--;
-
- png_save_uint_32(buf, num_frames);
- png_save_uint_32(buf + 4, num_plays);
-
- png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8);
-}
-
-void /* PRIVATE */
-png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
- png_uint_32 x_offset, png_uint_32 y_offset,
- png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
- png_byte blend_op)
-{
- png_byte buf[26];
-
- png_debug(1, "in png_write_fcTL");
-
- if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
- png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
- if (png_ptr->num_frames_written == 0 &&
- (width != png_ptr->first_frame_width ||
- height != png_ptr->first_frame_height))
- png_error(png_ptr, "width and/or height in the first frame's fcTL "
- "don't match the ones in IHDR");
-
- /* more error checking */
- png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
- delay_num, delay_den, dispose_op, blend_op);
-
- png_save_uint_32(buf, png_ptr->next_seq_num);
- png_save_uint_32(buf + 4, width);
- png_save_uint_32(buf + 8, height);
- png_save_uint_32(buf + 12, x_offset);
- png_save_uint_32(buf + 16, y_offset);
- png_save_uint_16(buf + 20, delay_num);
- png_save_uint_16(buf + 22, delay_den);
- buf[24] = dispose_op;
- buf[25] = blend_op;
-
- png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26);
-
- png_ptr->next_seq_num++;
-}
-
-void /* PRIVATE */
-png_write_fdAT(png_structp png_ptr,
- png_const_bytep data, png_size_t length)
-{
- png_byte buf[4];
-
- png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length));
-
- png_save_uint_32(buf, png_ptr->next_seq_num);
- png_write_chunk_data(png_ptr, buf, 4);
-
- png_write_chunk_data(png_ptr, data, length);
-
- png_write_chunk_end(png_ptr);
-
- png_ptr->next_seq_num++;
-}
-#endif /* PNG_WRITE_APNG_SUPPORTED */
-
/* Initializes the row writing capability of libpng */
void /* PRIVATE */
png_write_start_row(png_structrp png_ptr)
@@ -2406,7 +2309,8 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) * been specified by the application, and then writes the row out with the
* chosen filter.
*/
-static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
+static void
+png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
png_size_t row_bytes);
#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
@@ -3117,39 +3021,4 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, }
#endif
}
-
-#ifdef PNG_WRITE_APNG_SUPPORTED
-void /* PRIVATE */
-png_write_reset(png_structp png_ptr)
-{
- png_ptr->row_number = 0;
- png_ptr->pass = 0;
- png_ptr->mode &= ~PNG_HAVE_IDAT;
-}
-
-void /* PRIVATE */
-png_write_reinit(png_structp png_ptr, png_infop info_ptr,
- png_uint_32 width, png_uint_32 height)
-{
- if (png_ptr->num_frames_written == 0 &&
- (width != png_ptr->first_frame_width ||
- height != png_ptr->first_frame_height))
- png_error(png_ptr, "width and/or height in the first frame's fcTL "
- "don't match the ones in IHDR");
- if (width > png_ptr->first_frame_width ||
- height > png_ptr->first_frame_height)
- png_error(png_ptr, "width and/or height for a frame greater than"
- "the ones in IHDR");
-
- png_set_IHDR(png_ptr, info_ptr, width, height,
- info_ptr->bit_depth, info_ptr->color_type,
- info_ptr->interlace_type, info_ptr->compression_type,
- info_ptr->filter_type);
-
- png_ptr->width = width;
- png_ptr->height = height;
- png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
- png_ptr->usr_width = png_ptr->width;
-}
-#endif /* PNG_WRITE_APNG_SUPPORTED */
#endif /* PNG_WRITE_SUPPORTED */
diff --git a/plugins/AdvaImg/src/Metadata/Exif.cpp b/plugins/AdvaImg/src/Metadata/Exif.cpp index ed667b0974..abc840607b 100644 --- a/plugins/AdvaImg/src/Metadata/Exif.cpp +++ b/plugins/AdvaImg/src/Metadata/Exif.cpp @@ -515,17 +515,18 @@ processExifTag(FIBITMAP *dib, FITAG *tag, char *pval, BOOL msb_order, TagLib::MD } /** - 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 +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 +@param starting_md_model Metadata model of the IFD (should be TagLib::EXIF_MAIN for a jpeg) +@return Returns TRUE if sucessful, returns FALSE otherwise */ static BOOL -jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsigned int length, BOOL msb_order) { +jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsigned int length, BOOL msb_order, TagLib::MDMODEL starting_md_model) { WORD de, nde; std::stack<WORD> destack; // directory entries stack @@ -548,7 +549,7 @@ jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsig // set the metadata model to Exif - TagLib::MDMODEL md_model = TagLib::EXIF_MAIN; + TagLib::MDMODEL md_model = starting_md_model; // set the pointer to the first IFD (0th IFD) and follow it were it leads. @@ -787,6 +788,8 @@ jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsig return TRUE; } +// -------------------------------------------------------------------------- + /** Read and decode JPEG_APP1 marker (Exif profile) @param dib Input FIBITMAP @@ -795,7 +798,7 @@ jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsig @return Returns TRUE if successful, FALSE otherwise */ BOOL -jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { +jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned 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 @@ -849,11 +852,140 @@ jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) } */ - // process Exif directories - return jpeg_read_exif_dir(dib, profile, first_offset, length, bMotorolaOrder); + // process Exif directories, starting with Exif-TIFF IFD + return jpeg_read_exif_dir(dib, profile, first_offset, length, bMotorolaOrder, TagLib::EXIF_MAIN); } 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 +*/ +BOOL +jpeg_read_exif_profile_raw(FIBITMAP *dib, const BYTE *profile, unsigned 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_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 and decode JPEG-XR Exif IFD +@param dib Input FIBITMAP +@param profile Pointer to the Exif marker +@param length Exif marker length +@return Returns TRUE if successful, FALSE otherwise +*/ +BOOL +jpegxr_read_exif_profile(FIBITMAP *dib, const BYTE *profile, unsigned length) { + // assume Little Endian order + BOOL bMotorolaOrder = FALSE; + + // process Exif specific IFD + return jpeg_read_exif_dir(dib, profile, 0, length, bMotorolaOrder, TagLib::EXIF_EXIF); +} + +/** +Read and decode JPEG-XR Exif-GPS IFD +@param dib Input FIBITMAP +@param profile Pointer to the Exif-GPS marker +@param length Exif-GPS marker length +@return Returns TRUE if successful, FALSE otherwise +*/ +BOOL +jpegxr_read_exif_gps_profile(FIBITMAP *dib, const BYTE *profile, unsigned length) { + // assume Little Endian order + BOOL bMotorolaOrder = FALSE; + + // process Exif GPS IFD + return jpeg_read_exif_dir(dib, profile, 0, length, bMotorolaOrder, TagLib::EXIF_GPS); +} + +/** +Rotate a dib according to Exif info +@param dib Input / Output dib to rotate +@see PluginJPEG.cpp +*/ +void +RotateExif(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; + } + } + } + } +} diff --git a/plugins/AdvaImg/src/Metadata/FreeImageTag.cpp b/plugins/AdvaImg/src/Metadata/FreeImageTag.cpp index 5d9f3034ec..f8af31f9eb 100644 --- a/plugins/AdvaImg/src/Metadata/FreeImageTag.cpp +++ b/plugins/AdvaImg/src/Metadata/FreeImageTag.cpp @@ -117,11 +117,23 @@ FreeImage_CloneTag(FITAG *tag) { // 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; + switch(dst_tag->type) { + case FIDT_ASCII: + dst_tag->value = (BYTE*)malloc((src_tag->length + 1) * sizeof(BYTE)); + if(!dst_tag->value) { + throw FI_MSG_ERROR_MEMORY; + } + memcpy(dst_tag->value, src_tag->value, src_tag->length); + ((BYTE*)dst_tag->value)[src_tag->length] = 0; + break; + default: + 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); + break; } - memcpy(dst_tag->value, src_tag->value, src_tag->length); return clone; @@ -305,9 +317,9 @@ FreeImage_TagDataWidth(FREE_IMAGE_MDTYPE type) { 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
+ 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) }; diff --git a/plugins/AdvaImg/src/Metadata/FreeImageTag.h b/plugins/AdvaImg/src/Metadata/FreeImageTag.h index 4f3bffa1ce..f9021ace27 100644 --- a/plugins/AdvaImg/src/Metadata/FreeImageTag.h +++ b/plugins/AdvaImg/src/Metadata/FreeImageTag.h @@ -321,15 +321,15 @@ TagInfo *tag_info = s.getTagInfo(EXIF_MAIN, 0x0100); </code> Note on multi-threaded applications : -
-The singleton pattern must be carefully constructed in multi-threaded applications.
-If two threads are to execute the creation method at the same time when a singleton
-does not yet exist, they both must check for an instance of the singleton and then
-only one should create the new one.
-The classic solution to this problem is to use mutual exclusion on the class that
-indicates that the object is being instantiated.
-The FreeImage solution is to instantiate the singleton before any other thread is launched,
-i.e. inside the FreeImage_Initialise function (see Plugin.cpp).
+ +The singleton pattern must be carefully constructed in multi-threaded applications. +If two threads are to execute the creation method at the same time when a singleton +does not yet exist, they both must check for an instance of the singleton and then +only one should create the new one. +The classic solution to this problem is to use mutual exclusion on the class that +indicates that the object is being instantiated. +The FreeImage solution is to instantiate the singleton before any other thread is launched, +i.e. inside the FreeImage_Initialise function (see Plugin.cpp). */ class TagLib { @@ -468,7 +468,10 @@ extern "C" { #endif // JPEG Exif profile -BOOL jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen); +BOOL jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned datalen); +BOOL jpeg_read_exif_profile_raw(FIBITMAP *dib, const BYTE *profile, unsigned length); +BOOL jpegxr_read_exif_profile(FIBITMAP *dib, const BYTE *profile, unsigned length); +BOOL jpegxr_read_exif_gps_profile(FIBITMAP *dib, const BYTE *profile, unsigned length); // JPEG / TIFF IPTC profile BOOL read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen); diff --git a/plugins/AdvaImg/src/Metadata/IPTC.cpp b/plugins/AdvaImg/src/Metadata/IPTC.cpp index 6f28c486b3..bde718c986 100644 --- a/plugins/AdvaImg/src/Metadata/IPTC.cpp +++ b/plugins/AdvaImg/src/Metadata/IPTC.cpp @@ -91,7 +91,7 @@ read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { offset++; int directoryType = profile[offset++]; - int tagType = profile[offset++]; + int tagType = profile[offset++];; int tagByteCount = ((profile[offset] & 0xFF) << 8) | (profile[offset + 1] & 0xFF); offset += 2; diff --git a/plugins/AdvaImg/src/Metadata/TagConversion.cpp b/plugins/AdvaImg/src/Metadata/TagConversion.cpp index 06a1970cd8..f05818600c 100644 --- a/plugins/AdvaImg/src/Metadata/TagConversion.cpp +++ b/plugins/AdvaImg/src/Metadata/TagConversion.cpp @@ -1,1094 +1,1094 @@ -// ==========================================================
-// Tag to string conversion functions
-//
-// Design and implementation by
-// - Hervé Drolon <drolon@infonie.fr>
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#ifdef _MSC_VER
-#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
-#endif
-
-#include "FreeImage.h"
-#include "Utilities.h"
-#include "FreeImageTag.h"
-#include "FIRational.h"
-
-#define MAX_TEXT_EXTENT 512
-
-/**
-Convert a tag to a C string
-*/
-static const char*
-ConvertAnyTag(FITAG *tag) {
- char format[MAX_TEXT_EXTENT];
- static std::string buffer;
- DWORD i;
-
- if(!tag)
- return NULL;
-
- buffer.erase();
-
- // convert the tag value to a string buffer
-
- FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag);
- DWORD tag_count = FreeImage_GetTagCount(tag);
-
- switch(tag_type) {
- case FIDT_BYTE: // N x 8-bit unsigned integer
- {
- BYTE *pvalue = (BYTE*)FreeImage_GetTagValue(tag);
-
- sprintf(format, "%ld", (LONG) pvalue[0]);
- buffer += format;
- for(i = 1; i < tag_count; i++) {
- sprintf(format, " %ld", (LONG) pvalue[i]);
- buffer += format;
- }
- break;
- }
- case FIDT_SHORT: // N x 16-bit unsigned integer
- {
- unsigned short *pvalue = (unsigned short *)FreeImage_GetTagValue(tag);
-
- sprintf(format, "%hu", pvalue[0]);
- buffer += format;
- for(i = 1; i < tag_count; i++) {
- sprintf(format, " %hu", pvalue[i]);
- buffer += format;
- }
- break;
- }
- case FIDT_LONG: // N x 32-bit unsigned integer
- {
- 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
- {
- UINT64 *pvalue = (UINT64 *)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)
- {
- UINT64 *pvalue = (UINT64 *)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
- {
- INT64 *pvalue = (INT64 *)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);
-}
-
+// ========================================================== +// Tag to string conversion functions +// +// Design and implementation by +// - Hervé Drolon <drolon@infonie.fr> +// +// This file is part of FreeImage 3 +// +// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY +// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES +// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE +// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED +// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT +// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY +// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL +// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER +// THIS DISCLAIMER. +// +// Use at your own risk! +// ========================================================== + +#ifdef _MSC_VER +#pragma warning (disable : 4786) // identifier was truncated to 'number' characters +#endif + +#include "FreeImage.h" +#include "Utilities.h" +#include "FreeImageTag.h" +#include "FIRational.h" + +#define MAX_TEXT_EXTENT 512 + +/** +Convert a tag to a C string +*/ +static const char* +ConvertAnyTag(FITAG *tag) { + char format[MAX_TEXT_EXTENT]; + static std::string buffer; + DWORD i; + + if(!tag) + return NULL; + + buffer.erase(); + + // convert the tag value to a string buffer + + FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag); + DWORD tag_count = FreeImage_GetTagCount(tag); + + switch(tag_type) { + case FIDT_BYTE: // N x 8-bit unsigned integer + { + BYTE *pvalue = (BYTE*)FreeImage_GetTagValue(tag); + + sprintf(format, "%ld", (LONG) pvalue[0]); + buffer += format; + for(i = 1; i < tag_count; i++) { + sprintf(format, " %ld", (LONG) pvalue[i]); + buffer += format; + } + break; + } + case FIDT_SHORT: // N x 16-bit unsigned integer + { + unsigned short *pvalue = (unsigned short *)FreeImage_GetTagValue(tag); + + sprintf(format, "%hu", pvalue[0]); + buffer += format; + for(i = 1; i < tag_count; i++) { + sprintf(format, " %hu", pvalue[i]); + buffer += format; + } + break; + } + case FIDT_LONG: // N x 32-bit unsigned integer + { + 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 + { + UINT64 *pvalue = (UINT64 *)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) + { + UINT64 *pvalue = (UINT64 *)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 + { + INT64 *pvalue = (INT64 *)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/AdvaImg/src/Metadata/XTIFF.cpp b/plugins/AdvaImg/src/Metadata/XTIFF.cpp index e6f6bdd0d9..681eed12c5 100644 --- a/plugins/AdvaImg/src/Metadata/XTIFF.cpp +++ b/plugins/AdvaImg/src/Metadata/XTIFF.cpp @@ -1,665 +1,675 @@ -// ==========================================================
-// 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: {
- // remember that raw_data = _TIFFmalloc(value_size * value_count);
- const int value_size = _TIFFDataSize(fip->field_type);
- size_t length = value_size * value_count;
- 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_STRIPBYTECOUNTS:
- case TIFFTAG_STRIPOFFSETS:
- 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;
-}
+// ========================================================== +// 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; + + case TIFF_ASCII: + default: { + size_t length = 0; + if(!mem_alloc && (fip->field_type == TIFF_ASCII) && (fip->field_readcount == TIFF_VARIABLE)) { + // when metadata tag is of type ASCII and it's value is of variable size (TIFF_VARIABLE), + // tiff_read_exif_tag function gives length of 1 so all strings are truncated ... + // ... try to avoid this by using an explicit calculation for 'length' + length = strlen((char*)raw_data) + 1; + } + else { + // remember that raw_data = _TIFFmalloc(value_size * value_count); + const int value_size = _TIFFDataSize(fip->field_type); + length = value_size * value_count; + } + 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_STRIPBYTECOUNTS: + case TIFFTAG_STRIPOFFSETS: + 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/AdvaImg/src/Plugin.h b/plugins/AdvaImg/src/Plugin.h index dbb4540ef5..76ffc90522 100644 --- a/plugins/AdvaImg/src/Plugin.h +++ b/plugins/AdvaImg/src/Plugin.h @@ -138,5 +138,7 @@ 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); +void DLL_CALLCONV InitWEBP(Plugin *plugin, int format_id); +void DLL_CALLCONV InitJXR(Plugin *plugin, int format_id); #endif //!PLUGIN_H diff --git a/plugins/AdvaImg/src/Utilities.h b/plugins/AdvaImg/src/Utilities.h index ab0243cc41..c967de9ccc 100644 --- a/plugins/AdvaImg/src/Utilities.h +++ b/plugins/AdvaImg/src/Utilities.h @@ -98,9 +98,9 @@ DLL_API FIBITMAP * DLL_CALLCONV FreeImage_AllocateHeader(BOOL header_only, int w /** Helper for 16-bit FIT_BITMAP -@see FreeImage_GetRGBMasks
-*/
-DLL_API BOOL DLL_CALLCONV FreeImage_HasRGBMasks(FIBITMAP *dib);
+@see FreeImage_GetRGBMasks +*/ +DLL_API BOOL DLL_CALLCONV FreeImage_HasRGBMasks(FIBITMAP *dib); #if defined(__cplusplus) } @@ -365,6 +365,13 @@ RGBA to RGB conversion */ FIBITMAP* RemoveAlphaChannel(FIBITMAP* dib); +/** +Rotate a dib according to Exif info +@param dib Input / Output dib to rotate +@see Exif.cpp, PluginJPEG.cpp +*/ +void RotateExif(FIBITMAP **dib); + // ========================================================== // Big Endian / Little Endian utility functions |