summaryrefslogtreecommitdiff
path: root/plugins/AdvaImg/src/FreeImageToolkit
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2014-12-13 20:28:24 +0000
committerKirill Volinsky <mataes2007@gmail.com>2014-12-13 20:28:24 +0000
commitd2d798d0f11abcbf141db69869e76e8d123ec1eb (patch)
treecee8645964030b4b80231952885911f724850d12 /plugins/AdvaImg/src/FreeImageToolkit
parenta400ebf572dcad9b43d1b641b1742814f8b5e8a5 (diff)
FreeImage updated to 3.16
git-svn-id: http://svn.miranda-ng.org/main/trunk@11379 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/AdvaImg/src/FreeImageToolkit')
-rw-r--r--plugins/AdvaImg/src/FreeImageToolkit/Background.cpp8
-rw-r--r--plugins/AdvaImg/src/FreeImageToolkit/JPEGTransform.cpp1029
-rw-r--r--plugins/AdvaImg/src/FreeImageToolkit/Rescale.cpp338
-rw-r--r--plugins/AdvaImg/src/FreeImageToolkit/Resize.cpp142
-rw-r--r--plugins/AdvaImg/src/FreeImageToolkit/Resize.h21
5 files changed, 879 insertions, 659 deletions
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,