From 557f2816f5cd30705dec989c97a8a67c026d36d1 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Fri, 12 Oct 2012 10:49:29 +0000 Subject: FreeImage: folders restructurization git-svn-id: http://svn.miranda-ng.org/main/trunk@1884 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- .../Source/FreeImageToolkit/BSplineRotate.cpp | 730 ---------------- .../FreeImage/Source/FreeImageToolkit/Channels.cpp | 488 ----------- .../Source/FreeImageToolkit/ClassicRotate.cpp | 917 ------------------- .../FreeImage/Source/FreeImageToolkit/Colors.cpp | 967 --------------------- .../Source/FreeImageToolkit/CopyPaste.cpp | 747 ---------------- .../FreeImage/Source/FreeImageToolkit/Display.cpp | 230 ----- .../FreeImage/Source/FreeImageToolkit/Filters.h | 287 ------ plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp | 166 ---- .../Source/FreeImageToolkit/JPEGTransform.cpp | 410 --------- .../FreeImageToolkit/MultigridPoissonSolver.cpp | 505 ----------- .../FreeImage/Source/FreeImageToolkit/Rescale.cpp | 231 ----- .../FreeImage/Source/FreeImageToolkit/Resize.cpp | 656 -------------- plugins/FreeImage/Source/FreeImageToolkit/Resize.h | 145 --- 13 files changed, 6479 deletions(-) delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/BSplineRotate.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/ClassicRotate.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Colors.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Display.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Filters.h delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/JPEGTransform.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/MultigridPoissonSolver.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Rescale.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Resize.cpp delete mode 100644 plugins/FreeImage/Source/FreeImageToolkit/Resize.h (limited to 'plugins/FreeImage/Source/FreeImageToolkit') diff --git a/plugins/FreeImage/Source/FreeImageToolkit/BSplineRotate.cpp b/plugins/FreeImage/Source/FreeImageToolkit/BSplineRotate.cpp deleted file mode 100644 index e4be1d0bd2..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/BSplineRotate.cpp +++ /dev/null @@ -1,730 +0,0 @@ -// ========================================================== -// Bitmap rotation using B-Splines -// -// Design and implementation by -// - Philippe Thévenaz (philippe.thevenaz@epfl.ch) -// Adaptation for FreeImage by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -/* -========================================================== -This code was taken and adapted from the following reference : - -[1] Philippe Thévenaz, Spline interpolation, a C source code -implementation. http://bigwww.epfl.ch/thevenaz/ - -It implements ideas described in the following papers : - -[2] Unser M., Splines: A Perfect Fit for Signal and Image Processing. -IEEE Signal Processing Magazine, vol. 16, no. 6, pp. 22-38, November 1999. - -[3] Unser M., Aldroubi A., Eden M., B-Spline Signal Processing: Part I--Theory. -IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-832, February 1993. - -[4] Unser M., Aldroubi A., Eden M., B-Spline Signal Processing: Part II--Efficient Design and Applications. -IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 834-848, February 1993. - -========================================================== -*/ - - -#include -#include "FreeImage.h" -#include "Utilities.h" - -#define PI ((double)3.14159265358979323846264338327950288419716939937510) - -#define ROTATE_QUADRATIC 2L // Use B-splines of degree 2 (quadratic interpolation) -#define ROTATE_CUBIC 3L // Use B-splines of degree 3 (cubic interpolation) -#define ROTATE_QUARTIC 4L // Use B-splines of degree 4 (quartic interpolation) -#define ROTATE_QUINTIC 5L // Use B-splines of degree 5 (quintic interpolation) - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Prototypes definition - -static void ConvertToInterpolationCoefficients(double *c, long DataLength, double *z, long NbPoles, double Tolerance); -static double InitialCausalCoefficient(double *c, long DataLength, double z, double Tolerance); -static void GetColumn(double *Image, long Width, long x, double *Line, long Height); -static void GetRow(double *Image, long y, double *Line, long Width); -static double InitialAntiCausalCoefficient(double *c, long DataLength, double z); -static void PutColumn(double *Image, long Width, long x, double *Line, long Height); -static void PutRow(double *Image, long y, double *Line, long Width); -static bool SamplesToCoefficients(double *Image, long Width, long Height, long spline_degree); -static double InterpolatedValue(double *Bcoeff, long Width, long Height, double x, double y, long spline_degree); - -static FIBITMAP * Rotate8Bit(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, long spline_degree, BOOL use_mask); - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Coefficients routines - -/** - ConvertToInterpolationCoefficients - - @param c Input samples --> output coefficients - @param DataLength Number of samples or coefficients - @param z Poles - @param NbPoles Number of poles - @param Tolerance Admissible relative error -*/ -static void -ConvertToInterpolationCoefficients(double *c, long DataLength, double *z, long NbPoles, double Tolerance) { - double Lambda = 1; - long n, k; - - // special case required by mirror boundaries - if(DataLength == 1L) { - return; - } - // compute the overall gain - for(k = 0L; k < NbPoles; k++) { - Lambda = Lambda * (1.0 - z[k]) * (1.0 - 1.0 / z[k]); - } - // apply the gain - for (n = 0L; n < DataLength; n++) { - c[n] *= Lambda; - } - // loop over all poles - for (k = 0L; k < NbPoles; k++) { - // causal initialization - c[0] = InitialCausalCoefficient(c, DataLength, z[k], Tolerance); - // causal recursion - for (n = 1L; n < DataLength; n++) { - c[n] += z[k] * c[n - 1L]; - } - // anticausal initialization - c[DataLength - 1L] = InitialAntiCausalCoefficient(c, DataLength, z[k]); - // anticausal recursion - for (n = DataLength - 2L; 0 <= n; n--) { - c[n] = z[k] * (c[n + 1L] - c[n]); - } - } -} - -/** - InitialCausalCoefficient - - @param c Coefficients - @param DataLength Number of coefficients - @param z Actual pole - @param Tolerance Admissible relative error - @return -*/ -static double -InitialCausalCoefficient(double *c, long DataLength, double z, double Tolerance) { - double Sum, zn, z2n, iz; - long n, Horizon; - - // this initialization corresponds to mirror boundaries - Horizon = DataLength; - if(Tolerance > 0) { - Horizon = (long)ceil(log(Tolerance) / log(fabs(z))); - } - if(Horizon < DataLength) { - // accelerated loop - zn = z; - Sum = c[0]; - for (n = 1L; n < Horizon; n++) { - Sum += zn * c[n]; - zn *= z; - } - return(Sum); - } - else { - // full loop - zn = z; - iz = 1.0 / z; - z2n = pow(z, (double)(DataLength - 1L)); - Sum = c[0] + z2n * c[DataLength - 1L]; - z2n *= z2n * iz; - for (n = 1L; n <= DataLength - 2L; n++) { - Sum += (zn + z2n) * c[n]; - zn *= z; - z2n *= iz; - } - return(Sum / (1.0 - zn * zn)); - } -} - -/** - GetColumn - - @param Image Input image array - @param Width Width of the image - @param x x coordinate of the selected line - @param Line Output linear array - @param Height Length of the line -*/ -static void -GetColumn(double *Image, long Width, long x, double *Line, long Height) { - long y; - - Image = Image + x; - for(y = 0L; y < Height; y++) { - Line[y] = (double)*Image; - Image += Width; - } -} - -/** - GetRow - - @param Image Input image array - @param y y coordinate of the selected line - @param Line Output linear array - @param Width Length of the line -*/ -static void -GetRow(double *Image, long y, double *Line, long Width) { - long x; - - Image = Image + (y * Width); - for(x = 0L; x < Width; x++) { - Line[x] = (double)*Image++; - } -} - -/** - InitialAntiCausalCoefficient - - @param c Coefficients - @param DataLength Number of samples or coefficients - @param z Actual pole - @return -*/ -static double -InitialAntiCausalCoefficient(double *c, long DataLength, double z) { - // this initialization corresponds to mirror boundaries - return((z / (z * z - 1.0)) * (z * c[DataLength - 2L] + c[DataLength - 1L])); -} - -/** - PutColumn - - @param Image Output image array - @param Width Width of the image - @param x x coordinate of the selected line - @param Line Input linear array - @param Height Length of the line and height of the image -*/ -static void -PutColumn(double *Image, long Width, long x, double *Line, long Height) { - long y; - - Image = Image + x; - for(y = 0L; y < Height; y++) { - *Image = (double)Line[y]; - Image += Width; - } -} - -/** - PutRow - - @param Image Output image array - @param y y coordinate of the selected line - @param Line Input linear array - @param Width length of the line and width of the image -*/ -static void -PutRow(double *Image, long y, double *Line, long Width) { - long x; - - Image = Image + (y * Width); - for(x = 0L; x < Width; x++) { - *Image++ = (double)Line[x]; - } -} - -/** - SamplesToCoefficients.
- Implement the algorithm that converts the image samples into B-spline coefficients. - This efficient procedure essentially relies on the three papers cited above; - data are processed in-place. - Even though this algorithm is robust with respect to quantization, - we advocate the use of a floating-point format for the data. - - @param Image Input / Output image (in-place processing) - @param Width Width of the image - @param Height Height of the image - @param spline_degree Degree of the spline model - @return Returns true if success, false otherwise -*/ -static bool -SamplesToCoefficients(double *Image, long Width, long Height, long spline_degree) { - double *Line; - double Pole[2]; - long NbPoles; - long x, y; - - // recover the poles from a lookup table - switch (spline_degree) { - case 2L: - NbPoles = 1L; - Pole[0] = sqrt(8.0) - 3.0; - break; - case 3L: - NbPoles = 1L; - Pole[0] = sqrt(3.0) - 2.0; - break; - case 4L: - NbPoles = 2L; - Pole[0] = sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0; - Pole[1] = sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0; - break; - case 5L: - NbPoles = 2L; - Pole[0] = sqrt(135.0 / 2.0 - sqrt(17745.0 / 4.0)) + sqrt(105.0 / 4.0) - - 13.0 / 2.0; - Pole[1] = sqrt(135.0 / 2.0 + sqrt(17745.0 / 4.0)) - sqrt(105.0 / 4.0) - - 13.0 / 2.0; - break; - default: - // Invalid spline degree - return false; - } - - // convert the image samples into interpolation coefficients - - // in-place separable process, along x - Line = (double *)malloc(Width * sizeof(double)); - if (Line == NULL) { - // Row allocation failed - return false; - } - for (y = 0L; y < Height; y++) { - GetRow(Image, y, Line, Width); - ConvertToInterpolationCoefficients(Line, Width, Pole, NbPoles, DBL_EPSILON); - PutRow(Image, y, Line, Width); - } - free(Line); - - // in-place separable process, along y - Line = (double *)malloc(Height * sizeof(double)); - if (Line == NULL) { - // Column allocation failed - return false; - } - for (x = 0L; x < Width; x++) { - GetColumn(Image, Width, x, Line, Height); - ConvertToInterpolationCoefficients(Line, Height, Pole, NbPoles, DBL_EPSILON); - PutColumn(Image, Width, x, Line, Height); - } - free(Line); - - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Interpolation routines - -/** -Perform the bidimensional interpolation of an image. -Given an array of spline coefficients, return the value of -the underlying continuous spline model, sampled at the location (x, y). -The model degree can be 2 (quadratic), 3 (cubic), 4 (quartic), or 5 (quintic). - -@param Bcoeff Input B-spline array of coefficients -@param Width Width of the image -@param Height Height of the image -@param x x coordinate where to interpolate -@param y y coordinate where to interpolate -@param spline_degree Degree of the spline model -@return Returns the value of the underlying continuous spline model, -sampled at the location (x, y) -*/ -static double -InterpolatedValue(double *Bcoeff, long Width, long Height, double x, double y, long spline_degree) { - double *p; - double xWeight[6], yWeight[6]; - double interpolated; - double w, w2, w4, t, t0, t1; - long xIndex[6], yIndex[6]; - long Width2 = 2L * Width - 2L, Height2 = 2L * Height - 2L; - long i, j, k; - - // compute the interpolation indexes - if (spline_degree & 1L) { - i = (long)floor(x) - spline_degree / 2L; - j = (long)floor(y) - spline_degree / 2L; - for(k = 0; k <= spline_degree; k++) { - xIndex[k] = i++; - yIndex[k] = j++; - } - } - else { - i = (long)floor(x + 0.5) - spline_degree / 2L; - j = (long)floor(y + 0.5) - spline_degree / 2L; - for (k = 0; k <= spline_degree; k++) { - xIndex[k] = i++; - yIndex[k] = j++; - } - } - - // compute the interpolation weights - switch (spline_degree) { - case 2L: - /* x */ - w = x - (double)xIndex[1]; - xWeight[1] = 3.0 / 4.0 - w * w; - xWeight[2] = (1.0 / 2.0) * (w - xWeight[1] + 1.0); - xWeight[0] = 1.0 - xWeight[1] - xWeight[2]; - /* y */ - w = y - (double)yIndex[1]; - yWeight[1] = 3.0 / 4.0 - w * w; - yWeight[2] = (1.0 / 2.0) * (w - yWeight[1] + 1.0); - yWeight[0] = 1.0 - yWeight[1] - yWeight[2]; - break; - case 3L: - /* x */ - w = x - (double)xIndex[1]; - xWeight[3] = (1.0 / 6.0) * w * w * w; - xWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - xWeight[3]; - xWeight[2] = w + xWeight[0] - 2.0 * xWeight[3]; - xWeight[1] = 1.0 - xWeight[0] - xWeight[2] - xWeight[3]; - /* y */ - w = y - (double)yIndex[1]; - yWeight[3] = (1.0 / 6.0) * w * w * w; - yWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - yWeight[3]; - yWeight[2] = w + yWeight[0] - 2.0 * yWeight[3]; - yWeight[1] = 1.0 - yWeight[0] - yWeight[2] - yWeight[3]; - break; - case 4L: - /* x */ - w = x - (double)xIndex[2]; - w2 = w * w; - t = (1.0 / 6.0) * w2; - xWeight[0] = 1.0 / 2.0 - w; - xWeight[0] *= xWeight[0]; - xWeight[0] *= (1.0 / 24.0) * xWeight[0]; - t0 = w * (t - 11.0 / 24.0); - t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t); - xWeight[1] = t1 + t0; - xWeight[3] = t1 - t0; - xWeight[4] = xWeight[0] + t0 + (1.0 / 2.0) * w; - xWeight[2] = 1.0 - xWeight[0] - xWeight[1] - xWeight[3] - xWeight[4]; - /* y */ - w = y - (double)yIndex[2]; - w2 = w * w; - t = (1.0 / 6.0) * w2; - yWeight[0] = 1.0 / 2.0 - w; - yWeight[0] *= yWeight[0]; - yWeight[0] *= (1.0 / 24.0) * yWeight[0]; - t0 = w * (t - 11.0 / 24.0); - t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t); - yWeight[1] = t1 + t0; - yWeight[3] = t1 - t0; - yWeight[4] = yWeight[0] + t0 + (1.0 / 2.0) * w; - yWeight[2] = 1.0 - yWeight[0] - yWeight[1] - yWeight[3] - yWeight[4]; - break; - case 5L: - /* x */ - w = x - (double)xIndex[2]; - w2 = w * w; - xWeight[5] = (1.0 / 120.0) * w * w2 * w2; - w2 -= w; - w4 = w2 * w2; - w -= 1.0 / 2.0; - t = w2 * (w2 - 3.0); - xWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - xWeight[5]; - t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0); - t1 = (-1.0 / 12.0) * w * (t + 4.0); - xWeight[2] = t0 + t1; - xWeight[3] = t0 - t1; - t0 = (1.0 / 16.0) * (9.0 / 5.0 - t); - t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0); - xWeight[1] = t0 + t1; - xWeight[4] = t0 - t1; - /* y */ - w = y - (double)yIndex[2]; - w2 = w * w; - yWeight[5] = (1.0 / 120.0) * w * w2 * w2; - w2 -= w; - w4 = w2 * w2; - w -= 1.0 / 2.0; - t = w2 * (w2 - 3.0); - yWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - yWeight[5]; - t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0); - t1 = (-1.0 / 12.0) * w * (t + 4.0); - yWeight[2] = t0 + t1; - yWeight[3] = t0 - t1; - t0 = (1.0 / 16.0) * (9.0 / 5.0 - t); - t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0); - yWeight[1] = t0 + t1; - yWeight[4] = t0 - t1; - break; - default: - // Invalid spline degree - return 0; - } - - // apply the mirror boundary conditions - for(k = 0; k <= spline_degree; k++) { - xIndex[k] = (Width == 1L) ? (0L) : ((xIndex[k] < 0L) ? - (-xIndex[k] - Width2 * ((-xIndex[k]) / Width2)) - : (xIndex[k] - Width2 * (xIndex[k] / Width2))); - if (Width <= xIndex[k]) { - xIndex[k] = Width2 - xIndex[k]; - } - yIndex[k] = (Height == 1L) ? (0L) : ((yIndex[k] < 0L) ? - (-yIndex[k] - Height2 * ((-yIndex[k]) / Height2)) - : (yIndex[k] - Height2 * (yIndex[k] / Height2))); - if (Height <= yIndex[k]) { - yIndex[k] = Height2 - yIndex[k]; - } - } - - // perform interpolation - interpolated = 0.0; - for(j = 0; j <= spline_degree; j++) { - p = Bcoeff + (yIndex[j] * Width); - w = 0.0; - for(i = 0; i <= spline_degree; i++) { - w += xWeight[i] * p[xIndex[i]]; - } - interpolated += yWeight[j] * w; - } - - return interpolated; -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// FreeImage implementation - - -/** - Image translation and rotation using B-Splines. - - @param dib Input 8-bit greyscale image - @param angle Output image rotation in degree - @param x_shift Output image horizontal shift - @param y_shift Output image vertical shift - @param x_origin Output origin of the x-axis - @param y_origin Output origin of the y-axis - @param spline_degree Output degree of the B-spline model - @param use_mask Whether or not to mask the image - @return Returns the translated & rotated dib if successful, returns NULL otherwise -*/ -static FIBITMAP * -Rotate8Bit(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, long spline_degree, BOOL use_mask) { - double *ImageRasterArray; - double p; - double a11, a12, a21, a22; - double x0, y0, x1, y1; - long x, y; - long spline; - bool bResult; - - int bpp = FreeImage_GetBPP(dib); - if(bpp != 8) { - return NULL; - } - - int width = FreeImage_GetWidth(dib); - int height = FreeImage_GetHeight(dib); - switch(spline_degree) { - case ROTATE_QUADRATIC: - spline = 2L; // Use splines of degree 2 (quadratic interpolation) - break; - case ROTATE_CUBIC: - spline = 3L; // Use splines of degree 3 (cubic interpolation) - break; - case ROTATE_QUARTIC: - spline = 4L; // Use splines of degree 4 (quartic interpolation) - break; - case ROTATE_QUINTIC: - spline = 5L; // Use splines of degree 5 (quintic interpolation) - break; - default: - spline = 3L; - } - - // allocate output image - FIBITMAP *dst = FreeImage_Allocate(width, height, bpp); - if (!dst) - return NULL; - // buid a grey scale palette - RGBQUAD *pal = FreeImage_GetPalette(dst); - for(int i = 0; i < 256; i++) { - pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)i; - } - - // allocate a temporary array - ImageRasterArray = (double*)malloc(width * height * sizeof(double)); - if (!ImageRasterArray) { - FreeImage_Unload(dst); - return NULL; - } - // copy data samples - for(y = 0; y < height; y++) { - double *pImage = &ImageRasterArray[y*width]; - BYTE *src_bits = FreeImage_GetScanLine(dib, height-1-y); - - for(x = 0; x < width; x++) { - pImage[x] = (double)src_bits[x]; - } - } - - // convert between a representation based on image samples - // and a representation based on image B-spline coefficients - bResult = SamplesToCoefficients(ImageRasterArray, width, height, spline); - if (!bResult) { - FreeImage_Unload(dst); - free(ImageRasterArray); - return NULL; - } - - // prepare the geometry - angle *= PI / 180.0; - a11 = cos(angle); - a12 = -sin(angle); - a21 = sin(angle); - a22 = cos(angle); - x0 = a11 * (x_shift + x_origin) + a12 * (y_shift + y_origin); - y0 = a21 * (x_shift + x_origin) + a22 * (y_shift + y_origin); - x_shift = x_origin - x0; - y_shift = y_origin - y0; - - // visit all pixels of the output image and assign their value - for(y = 0; y < height; y++) { - BYTE *dst_bits = FreeImage_GetScanLine(dst, height-1-y); - - x0 = a12 * (double)y + x_shift; - y0 = a22 * (double)y + y_shift; - - for(x = 0; x < width; x++) { - x1 = x0 + a11 * (double)x; - y1 = y0 + a21 * (double)x; - if(use_mask) { - if ((x1 <= -0.5) || (((double)width - 0.5) <= x1) || (y1 <= -0.5) || (((double)height - 0.5) <= y1)) { - p = 0; - } - else { - p = (double)InterpolatedValue(ImageRasterArray, width, height, x1, y1, spline); - } - } - else { - p = (double)InterpolatedValue(ImageRasterArray, width, height, x1, y1, spline); - } - // clamp and convert to BYTE - dst_bits[x] = (BYTE)MIN(MAX((int)0, (int)(p + 0.5)), (int)255); - } - } - - // free working array and return - free(ImageRasterArray); - - return dst; -} - -/** - Image rotation using a 3rd order (cubic) B-Splines. - - @param dib Input dib (8, 24 or 32-bit) - @param angle Output image rotation - @param x_shift Output image horizontal shift - @param y_shift Output image vertical shift - @param x_origin Output origin of the x-axis - @param y_origin Output origin of the y-axis - @param use_mask Whether or not to mask the image - @return Returns the translated & rotated dib if successful, returns NULL otherwise -*/ -FIBITMAP * DLL_CALLCONV -FreeImage_RotateEx(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask) { - - int x, y, bpp; - int channel, nb_channels; - BYTE *src_bits, *dst_bits; - FIBITMAP *src8 = NULL, *dst8 = NULL, *dst = NULL; - - if (!FreeImage_HasPixels(dib)) return NULL; - - try { - - bpp = FreeImage_GetBPP(dib); - - if(bpp == 8) { - FIBITMAP *dst_8 = Rotate8Bit(dib, angle, x_shift, y_shift, x_origin, y_origin, ROTATE_CUBIC, use_mask); - if(dst_8) { - // copy metadata from src to dst - FreeImage_CloneMetadata(dst_8, dib); - } - return dst_8; - } - if ((bpp == 24) || (bpp == 32)) { - // allocate dst image - int width = FreeImage_GetWidth(dib); - int height = FreeImage_GetHeight(dib); - if ( bpp == 24 ) { - dst = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } else { - dst = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - } - if (!dst) throw(1); - - // allocate a temporary 8-bit dib (no need to build a palette) - src8 = FreeImage_Allocate(width, height, 8); - if (!src8) throw(1); - - // process each channel separately - // ------------------------------- - nb_channels = (bpp / 8); - - for(channel = 0; channel < nb_channels; channel++) { - // extract channel from source dib - for(y = 0; y < height; y++) { - src_bits = FreeImage_GetScanLine(dib, y); - dst_bits = FreeImage_GetScanLine(src8, y); - for(x = 0; x < width; x++) { - dst_bits[x] = src_bits[channel]; - src_bits += nb_channels; - } - } - - // process channel - dst8 = Rotate8Bit(src8, angle, x_shift, y_shift, x_origin, y_origin, ROTATE_CUBIC, use_mask); - if (!dst8) throw(1); - - // insert channel to destination dib - for(y = 0; y < height; y++) { - src_bits = FreeImage_GetScanLine(dst8, y); - dst_bits = FreeImage_GetScanLine(dst, y); - for(x = 0; x < width; x++) { - dst_bits[channel] = src_bits[x]; - dst_bits += nb_channels; - } - } - - FreeImage_Unload(dst8); - } - - FreeImage_Unload(src8); - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, dib); - - return dst; - } - } catch(int) { - if(src8) FreeImage_Unload(src8); - if(dst8) FreeImage_Unload(dst8); - if(dst) FreeImage_Unload(dst); - } - - return NULL; -} diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp deleted file mode 100644 index f6e6c5509c..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Channels.cpp +++ /dev/null @@ -1,488 +0,0 @@ -// ========================================================== -// Channel processing support -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - - -/** @brief Retrieves the red, green, blue or alpha channel of a BGR[A] image. -@param src Input image to be processed. -@param channel Color channel to extract -@return Returns the extracted channel if successful, returns NULL otherwise. -*/ -FIBITMAP * DLL_CALLCONV -FreeImage_GetChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { - - if (!FreeImage_HasPixels(src)) return NULL; - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - unsigned bpp = FreeImage_GetBPP(src); - - // 24- or 32-bit - if(image_type == FIT_BITMAP && ((bpp == 24) || (bpp == 32))) { - int c; - - // select the channel to extract - switch(channel) { - case FICC_BLUE: - c = FI_RGBA_BLUE; - break; - case FICC_GREEN: - c = FI_RGBA_GREEN; - break; - case FICC_RED: - c = FI_RGBA_RED; - break; - case FICC_ALPHA: - if(bpp != 32) return NULL; - c = FI_RGBA_ALPHA; - break; - default: - return NULL; - } - - // allocate a 8-bit dib - unsigned width = FreeImage_GetWidth(src); - unsigned height = FreeImage_GetHeight(src); - FIBITMAP *dst = FreeImage_Allocate(width, height, 8) ; - if (!dst) return NULL; - // build a greyscale palette - RGBQUAD *pal = FreeImage_GetPalette(dst); - for(int i = 0; i < 256; i++) { - pal[i].rgbBlue = pal[i].rgbGreen = pal[i].rgbRed = (BYTE)i; - } - - // perform extraction - - int bytespp = bpp / 8; // bytes / pixel - - for(unsigned y = 0; y < height; y++) { - BYTE *src_bits = FreeImage_GetScanLine(src, y); - BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - dst_bits[x] = src_bits[c]; - src_bits += bytespp; - } - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - return dst; - } - - // 48-bit RGB or 64-bit RGBA images - if ((image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) { - int c; - - // select the channel to extract (always RGB[A]) - switch(channel) { - case FICC_BLUE: - c = 2; - break; - case FICC_GREEN: - c = 1; - break; - case FICC_RED: - c = 0; - break; - case FICC_ALPHA: - if(bpp != 64) return NULL; - c = 3; - break; - default: - return NULL; - } - - // allocate a greyscale dib - unsigned width = FreeImage_GetWidth(src); - unsigned height = FreeImage_GetHeight(src); - FIBITMAP *dst = FreeImage_AllocateT(FIT_UINT16, width, height) ; - if (!dst) return NULL; - - // perform extraction - - int bytespp = bpp / 16; // words / pixel - - for(unsigned y = 0; y < height; y++) { - unsigned short *src_bits = (unsigned short*)FreeImage_GetScanLine(src, y); - unsigned short *dst_bits = (unsigned short*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - dst_bits[x] = src_bits[c]; - src_bits += bytespp; - } - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - return dst; - } - - // 96-bit RGBF or 128-bit RGBAF images - if ((image_type == FIT_RGBF) || (image_type == FIT_RGBAF)) { - int c; - - // select the channel to extract (always RGB[A]) - switch(channel) { - case FICC_BLUE: - c = 2; - break; - case FICC_GREEN: - c = 1; - break; - case FICC_RED: - c = 0; - break; - case FICC_ALPHA: - if(bpp != 128) return NULL; - c = 3; - break; - default: - return NULL; - } - - // allocate a greyscale dib - unsigned width = FreeImage_GetWidth(src); - unsigned height = FreeImage_GetHeight(src); - FIBITMAP *dst = FreeImage_AllocateT(FIT_FLOAT, width, height) ; - if (!dst) return NULL; - - // perform extraction - - int bytespp = bpp / 32; // floats / pixel - - for(unsigned y = 0; y < height; y++) { - float *src_bits = (float*)FreeImage_GetScanLine(src, y); - float *dst_bits = (float*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < width; x++) { - dst_bits[x] = src_bits[c]; - src_bits += bytespp; - } - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - return dst; - } - - return NULL; -} - -/** @brief Insert a greyscale dib into a RGB[A] image. -Both src and dst must have the same width and height. -@param dst Image to modify (RGB or RGBA) -@param src Input greyscale image to insert -@param channel Color channel to modify -@return Returns TRUE if successful, FALSE otherwise. -*/ -BOOL DLL_CALLCONV -FreeImage_SetChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { - int c; - - if (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(dst)) return FALSE; - - // src and dst images should have the same width and height - unsigned src_width = FreeImage_GetWidth(src); - unsigned src_height = FreeImage_GetHeight(src); - unsigned dst_width = FreeImage_GetWidth(dst); - unsigned dst_height = FreeImage_GetHeight(dst); - if ((src_width != dst_width) || (src_height != dst_height)) - return FALSE; - - // src image should be grayscale, dst image should be RGB or RGBA - FREE_IMAGE_COLOR_TYPE src_type = FreeImage_GetColorType(src); - FREE_IMAGE_COLOR_TYPE dst_type = FreeImage_GetColorType(dst); - if ((dst_type != FIC_RGB) && (dst_type != FIC_RGBALPHA) || (src_type != FIC_MINISBLACK)) { - return FALSE; - } - - FREE_IMAGE_TYPE src_image_type = FreeImage_GetImageType(src); - FREE_IMAGE_TYPE dst_image_type = FreeImage_GetImageType(dst); - - if ((dst_image_type == FIT_BITMAP) && (src_image_type == FIT_BITMAP)) { - - // src image should be grayscale, dst image should be 24- or 32-bit - unsigned src_bpp = FreeImage_GetBPP(src); - unsigned dst_bpp = FreeImage_GetBPP(dst); - if ((src_bpp != 8) || (dst_bpp != 24) && (dst_bpp != 32)) - return FALSE; - - - // select the channel to modify - switch(channel) { - case FICC_BLUE: - c = FI_RGBA_BLUE; - break; - case FICC_GREEN: - c = FI_RGBA_GREEN; - break; - case FICC_RED: - c = FI_RGBA_RED; - break; - case FICC_ALPHA: - if(dst_bpp != 32) return FALSE; - c = FI_RGBA_ALPHA; - break; - default: - return FALSE; - } - - // perform insertion - - int bytespp = dst_bpp / 8; // bytes / pixel - - for(unsigned y = 0; y < dst_height; y++) { - BYTE *src_bits = FreeImage_GetScanLine(src, y); - BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < dst_width; x++) { - dst_bits[c] = src_bits[x]; - dst_bits += bytespp; - } - } - - return TRUE; - } - - if (((dst_image_type == FIT_RGB16) || (dst_image_type == FIT_RGBA16)) && (src_image_type == FIT_UINT16)) { - - // src image should be grayscale, dst image should be 48- or 64-bit - unsigned src_bpp = FreeImage_GetBPP(src); - unsigned dst_bpp = FreeImage_GetBPP(dst); - if ((src_bpp != 16) || (dst_bpp != 48) && (dst_bpp != 64)) - return FALSE; - - - // select the channel to modify (always RGB[A]) - switch(channel) { - case FICC_BLUE: - c = 2; - break; - case FICC_GREEN: - c = 1; - break; - case FICC_RED: - c = 0; - break; - case FICC_ALPHA: - if(dst_bpp != 64) return FALSE; - c = 3; - break; - default: - return FALSE; - } - - // perform insertion - - int bytespp = dst_bpp / 16; // words / pixel - - for(unsigned y = 0; y < dst_height; y++) { - unsigned short *src_bits = (unsigned short*)FreeImage_GetScanLine(src, y); - unsigned short *dst_bits = (unsigned short*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < dst_width; x++) { - dst_bits[c] = src_bits[x]; - dst_bits += bytespp; - } - } - - return TRUE; - } - - if (((dst_image_type == FIT_RGBF) || (dst_image_type == FIT_RGBAF)) && (src_image_type == FIT_FLOAT)) { - - // src image should be grayscale, dst image should be 96- or 128-bit - unsigned src_bpp = FreeImage_GetBPP(src); - unsigned dst_bpp = FreeImage_GetBPP(dst); - if ((src_bpp != 32) || (dst_bpp != 96) && (dst_bpp != 128)) - return FALSE; - - - // select the channel to modify (always RGB[A]) - switch(channel) { - case FICC_BLUE: - c = 2; - break; - case FICC_GREEN: - c = 1; - break; - case FICC_RED: - c = 0; - break; - case FICC_ALPHA: - if(dst_bpp != 128) return FALSE; - c = 3; - break; - default: - return FALSE; - } - - // perform insertion - - int bytespp = dst_bpp / 32; // floats / pixel - - for(unsigned y = 0; y < dst_height; y++) { - float *src_bits = (float*)FreeImage_GetScanLine(src, y); - float *dst_bits = (float*)FreeImage_GetScanLine(dst, y); - for(unsigned x = 0; x < dst_width; x++) { - dst_bits[c] = src_bits[x]; - dst_bits += bytespp; - } - } - - return TRUE; - } - - return FALSE; -} - -/** @brief Retrieves the real part, imaginary part, magnitude or phase of a complex image. -@param src Input image to be processed. -@param channel Channel to extract -@return Returns the extracted channel if successful, returns NULL otherwise. -*/ -FIBITMAP * DLL_CALLCONV -FreeImage_GetComplexChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { - unsigned x, y; - double mag, phase; - FICOMPLEX *src_bits = NULL; - double *dst_bits = NULL; - FIBITMAP *dst = NULL; - - if (!FreeImage_HasPixels(src)) return NULL; - - if(FreeImage_GetImageType(src) == FIT_COMPLEX) { - // allocate a dib of type FIT_DOUBLE - unsigned width = FreeImage_GetWidth(src); - unsigned height = FreeImage_GetHeight(src); - dst = FreeImage_AllocateT(FIT_DOUBLE, width, height) ; - if (!dst) return NULL; - - // perform extraction - - switch(channel) { - case FICC_REAL: // real part - for(y = 0; y < height; y++) { - src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y); - dst_bits = (double *)FreeImage_GetScanLine(dst, y); - for(x = 0; x < width; x++) { - dst_bits[x] = src_bits[x].r; - } - } - break; - - case FICC_IMAG: // imaginary part - for(y = 0; y < height; y++) { - src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y); - dst_bits = (double *)FreeImage_GetScanLine(dst, y); - for(x = 0; x < width; x++) { - dst_bits[x] = src_bits[x].i; - } - } - break; - - case FICC_MAG: // magnitude - for(y = 0; y < height; y++) { - src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y); - dst_bits = (double *)FreeImage_GetScanLine(dst, y); - for(x = 0; x < width; x++) { - mag = src_bits[x].r * src_bits[x].r + src_bits[x].i * src_bits[x].i; - dst_bits[x] = sqrt(mag); - } - } - break; - - case FICC_PHASE: // phase - for(y = 0; y < height; y++) { - src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y); - dst_bits = (double *)FreeImage_GetScanLine(dst, y); - for(x = 0; x < width; x++) { - if ((src_bits[x].r == 0) && (src_bits[x].i == 0)) { - phase = 0; - } else { - phase = atan2(src_bits[x].i, src_bits[x].r); - } - dst_bits[x] = phase; - } - } - break; - } - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - return dst; -} - -/** @brief Set the real or imaginary part of a complex image. -Both src and dst must have the same width and height. -@param dst Image to modify (image of type FIT_COMPLEX) -@param src Input image of type FIT_DOUBLE -@param channel Channel to modify -@return Returns TRUE if successful, FALSE otherwise. -*/ -BOOL DLL_CALLCONV -FreeImage_SetComplexChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) { - unsigned x, y; - double *src_bits = NULL; - FICOMPLEX *dst_bits = NULL; - - if (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(dst)) return FALSE; - - // src image should be of type FIT_DOUBLE, dst image should be of type FIT_COMPLEX - const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src); - const FREE_IMAGE_TYPE dst_type = FreeImage_GetImageType(dst); - if ((src_type != FIT_DOUBLE) || (dst_type != FIT_COMPLEX)) - return FALSE; - - // src and dst images should have the same width and height - unsigned src_width = FreeImage_GetWidth(src); - unsigned src_height = FreeImage_GetHeight(src); - unsigned dst_width = FreeImage_GetWidth(dst); - unsigned dst_height = FreeImage_GetHeight(dst); - if ((src_width != dst_width) || (src_height != dst_height)) - return FALSE; - - // select the channel to modify - switch(channel) { - case FICC_REAL: // real part - for(y = 0; y < dst_height; y++) { - src_bits = (double *)FreeImage_GetScanLine(src, y); - dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y); - for(x = 0; x < dst_width; x++) { - dst_bits[x].r = src_bits[x]; - } - } - break; - case FICC_IMAG: // imaginary part - for(y = 0; y < dst_height; y++) { - src_bits = (double *)FreeImage_GetScanLine(src, y); - dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y); - for(x = 0; x < dst_width; x++) { - dst_bits[x].i = src_bits[x]; - } - } - break; - } - - return TRUE; -} diff --git a/plugins/FreeImage/Source/FreeImageToolkit/ClassicRotate.cpp b/plugins/FreeImage/Source/FreeImageToolkit/ClassicRotate.cpp deleted file mode 100644 index d38d8c1bcd..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/ClassicRotate.cpp +++ /dev/null @@ -1,917 +0,0 @@ -// ========================================================== -// Bitmap rotation by means of 3 shears. -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Thorsten Radde (support@IdealSoftware.com) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -/* - ============================================================ - References : - [1] Paeth A., A Fast Algorithm for General Raster Rotation. - Graphics Gems, p. 179, Andrew Glassner editor, Academic Press, 1990. - [2] Yariv E., High quality image rotation (rotate by shear). - [Online] http://www.codeproject.com/bitmap/rotatebyshear.asp - [3] Treskunov A., Fast and high quality true-color bitmap rotation function. - [Online] http://anton.treskunov.net/Software/doc/fast_and_high_quality_true_color_bitmap_rotation_function.html - ============================================================ -*/ - -#include "FreeImage.h" -#include "Utilities.h" - -#define RBLOCK 64 // image blocks of RBLOCK*RBLOCK pixels - -// -------------------------------------------------------------------------- - -/** -Skews a row horizontally (with filtered weights). -Limited to 45 degree skewing only. Filters two adjacent pixels. -Parameter T can be BYTE, WORD of float. -@param src Pointer to source image to rotate -@param dst Pointer to destination image -@param row Row index -@param iOffset Skew offset -@param dWeight Relative weight of right pixel -@param bkcolor Background color -*/ -template void -HorizontalSkewT(FIBITMAP *src, FIBITMAP *dst, int row, int iOffset, double weight, const void *bkcolor = NULL) { - int iXPos; - - const unsigned src_width = FreeImage_GetWidth(src); - const unsigned dst_width = FreeImage_GetWidth(dst); - - T pxlSrc[4], pxlLeft[4], pxlOldLeft[4]; // 4 = 4*sizeof(T) max - - // background - const T pxlBlack[4] = {0, 0, 0, 0 }; - const T *pxlBkg = static_cast(bkcolor); // assume at least bytespp and 4*sizeof(T) max - if (!pxlBkg) { - // default background color is black - pxlBkg = pxlBlack; - } - - // calculate the number of bytes per pixel - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - // calculate the number of samples per pixel - const unsigned samples = bytespp / sizeof(T); - - BYTE *src_bits = FreeImage_GetScanLine(src, row); - BYTE *dst_bits = FreeImage_GetScanLine(dst, row); - - // fill gap left of skew with background - if(bkcolor) { - for(int k = 0; k < iOffset; k++) { - memcpy(&dst_bits[k * bytespp], bkcolor, bytespp); - } - AssignPixel((BYTE*)&pxlOldLeft[0], (BYTE*)bkcolor, bytespp); - } else { - if(iOffset > 0) { - memset(dst_bits, 0, iOffset * bytespp); - } - memset(&pxlOldLeft[0], 0, bytespp); - } - - for(unsigned i = 0; i < src_width; i++) { - // loop through row pixels - AssignPixel((BYTE*)&pxlSrc[0], (BYTE*)src_bits, bytespp); - // calculate weights - for(unsigned j = 0; j < samples; j++) { - pxlLeft[j] = static_cast(pxlBkg[j] + (pxlSrc[j] - pxlBkg[j]) * weight + 0.5); - } - // check boundaries - iXPos = i + iOffset; - if ((iXPos >= 0) && (iXPos < (int)dst_width)) { - // update left over on source - for(unsigned j = 0; j < samples; j++) { - pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]); - } - AssignPixel((BYTE*)&dst_bits[iXPos*bytespp], (BYTE*)&pxlSrc[0], bytespp); - } - // save leftover for next pixel in scan - AssignPixel((BYTE*)&pxlOldLeft[0], (BYTE*)&pxlLeft[0], bytespp); - - // next pixel in scan - src_bits += bytespp; - } - - // go to rightmost point of skew - iXPos = src_width + iOffset; - - if ((iXPos >= 0) && (iXPos < (int)dst_width)) { - dst_bits = FreeImage_GetScanLine(dst, row) + iXPos * bytespp; - - // If still in image bounds, put leftovers there - AssignPixel((BYTE*)dst_bits, (BYTE*)&pxlOldLeft[0], bytespp); - - // clear to the right of the skewed line with background - dst_bits += bytespp; - if(bkcolor) { - for(unsigned i = 0; i < dst_width - iXPos - 1; i++) { - memcpy(&dst_bits[i * bytespp], bkcolor, bytespp); - } - } else { - memset(dst_bits, 0, bytespp * (dst_width - iXPos - 1)); - } - - } -} - -/** -Skews a row horizontally (with filtered weights). -Limited to 45 degree skewing only. Filters two adjacent pixels. -@param src Pointer to source image to rotate -@param dst Pointer to destination image -@param row Row index -@param iOffset Skew offset -@param dWeight Relative weight of right pixel -@param bkcolor Background color -*/ -static void -HorizontalSkew(FIBITMAP *src, FIBITMAP *dst, int row, int iOffset, double dWeight, const void *bkcolor) { - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - switch(image_type) { - case FIT_BITMAP: - switch(FreeImage_GetBPP(src)) { - case 8: - case 24: - case 32: - HorizontalSkewT(src, dst, row, iOffset, dWeight, bkcolor); - break; - } - break; - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - HorizontalSkewT(src, dst, row, iOffset, dWeight, bkcolor); - break; - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - HorizontalSkewT(src, dst, row, iOffset, dWeight, bkcolor); - break; - } -} - -/** -Skews a column vertically (with filtered weights). -Limited to 45 degree skewing only. Filters two adjacent pixels. -Parameter T can be BYTE, WORD of float. -@param src Pointer to source image to rotate -@param dst Pointer to destination image -@param col Column index -@param iOffset Skew offset -@param dWeight Relative weight of upper pixel -@param bkcolor Background color -*/ -template void -VerticalSkewT(FIBITMAP *src, FIBITMAP *dst, int col, int iOffset, double weight, const void *bkcolor = NULL) { - int iYPos; - - unsigned src_height = FreeImage_GetHeight(src); - unsigned dst_height = FreeImage_GetHeight(dst); - - T pxlSrc[4], pxlLeft[4], pxlOldLeft[4]; // 4 = 4*sizeof(T) max - - // background - const T pxlBlack[4] = {0, 0, 0, 0 }; - const T *pxlBkg = static_cast(bkcolor); // assume at least bytespp and 4*sizeof(T) max - if (!pxlBkg) { - // default background color is black - pxlBkg = pxlBlack; - } - - // calculate the number of bytes per pixel - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - // calculate the number of samples per pixel - const unsigned samples = bytespp / sizeof(T); - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - const unsigned index = col * bytespp; - - BYTE *src_bits = FreeImage_GetBits(src) + index; - BYTE *dst_bits = FreeImage_GetBits(dst) + index; - - // fill gap above skew with background - if(bkcolor) { - for(int k = 0; k < iOffset; k++) { - memcpy(dst_bits, bkcolor, bytespp); - dst_bits += dst_pitch; - } - memcpy(&pxlOldLeft[0], bkcolor, bytespp); - } else { - for(int k = 0; k < iOffset; k++) { - memset(dst_bits, 0, bytespp); - dst_bits += dst_pitch; - } - memset(&pxlOldLeft[0], 0, bytespp); - } - - for(unsigned i = 0; i < src_height; i++) { - // loop through column pixels - AssignPixel((BYTE*)(&pxlSrc[0]), src_bits, bytespp); - // calculate weights - for(unsigned j = 0; j < samples; j++) { - pxlLeft[j] = static_cast(pxlBkg[j] + (pxlSrc[j] - pxlBkg[j]) * weight + 0.5); - } - // check boundaries - iYPos = i + iOffset; - if ((iYPos >= 0) && (iYPos < (int)dst_height)) { - // update left over on source - for(unsigned j = 0; j < samples; j++) { - pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]); - } - dst_bits = FreeImage_GetScanLine(dst, iYPos) + index; - AssignPixel(dst_bits, (BYTE*)(&pxlSrc[0]), bytespp); - } - // save leftover for next pixel in scan - AssignPixel((BYTE*)(&pxlOldLeft[0]), (BYTE*)(&pxlLeft[0]), bytespp); - - // next pixel in scan - src_bits += src_pitch; - } - // go to bottom point of skew - iYPos = src_height + iOffset; - - if ((iYPos >= 0) && (iYPos < (int)dst_height)) { - dst_bits = FreeImage_GetScanLine(dst, iYPos) + index; - - // if still in image bounds, put leftovers there - AssignPixel((BYTE*)(dst_bits), (BYTE*)(&pxlOldLeft[0]), bytespp); - - // clear below skewed line with background - if(bkcolor) { - while(++iYPos < (int)dst_height) { - dst_bits += dst_pitch; - AssignPixel((BYTE*)(dst_bits), (BYTE*)(bkcolor), bytespp); - } - } else { - while(++iYPos < (int)dst_height) { - dst_bits += dst_pitch; - memset(dst_bits, 0, bytespp); - } - } - } -} - -/** -Skews a column vertically (with filtered weights). -Limited to 45 degree skewing only. Filters two adjacent pixels. -@param src Pointer to source image to rotate -@param dst Pointer to destination image -@param col Column index -@param iOffset Skew offset -@param dWeight Relative weight of upper pixel -@param bkcolor Background color -*/ -static void -VerticalSkew(FIBITMAP *src, FIBITMAP *dst, int col, int iOffset, double dWeight, const void *bkcolor) { - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - switch(image_type) { - case FIT_BITMAP: - switch(FreeImage_GetBPP(src)) { - case 8: - case 24: - case 32: - VerticalSkewT(src, dst, col, iOffset, dWeight, bkcolor); - break; - } - break; - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - VerticalSkewT(src, dst, col, iOffset, dWeight, bkcolor); - break; - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - VerticalSkewT(src, dst, col, iOffset, dWeight, bkcolor); - break; - } -} - -/** -Rotates an image by 90 degrees (counter clockwise). -Precise rotation, no filters required.
-Code adapted from CxImage (http://www.xdp.it/cximage.htm) -@param src Pointer to source image to rotate -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP* -Rotate90(FIBITMAP *src) { - - const unsigned bpp = FreeImage_GetBPP(src); - - const unsigned src_width = FreeImage_GetWidth(src); - const unsigned src_height = FreeImage_GetHeight(src); - const unsigned dst_width = src_height; - const unsigned dst_height = src_width; - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - // allocate and clear dst image - FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp); - if(NULL == dst) return NULL; - - // get src and dst scan width - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - switch(image_type) { - case FIT_BITMAP: - if(bpp == 1) { - // speedy rotate for BW images - - BYTE *bsrc = FreeImage_GetBits(src); - BYTE *bdest = FreeImage_GetBits(dst); - - BYTE *dbitsmax = bdest + dst_height * dst_pitch - 1; - - for(unsigned y = 0; y < src_height; y++) { - // figure out the column we are going to be copying to - const div_t div_r = div(y, 8); - // set bit pos of src column byte - const BYTE bitpos = (BYTE)(128 >> div_r.rem); - BYTE *srcdisp = bsrc + y * src_pitch; - for(unsigned x = 0; x < src_pitch; x++) { - // get source bits - BYTE *sbits = srcdisp + x; - // get destination column - BYTE *nrow = bdest + (dst_height - 1 - (x * 8)) * dst_pitch + div_r.quot; - for (int z = 0; z < 8; z++) { - // get destination byte - BYTE *dbits = nrow - z * dst_pitch; - if ((dbits < bdest) || (dbits > dbitsmax)) break; - if (*sbits & (128 >> z)) *dbits |= bitpos; - } - } - } - } - else if ((bpp == 8) || (bpp == 24) || (bpp == 32)) { - // anything other than BW : - // This optimized version of rotation rotates image by smaller blocks. It is quite - // a bit faster than obvious algorithm, because it produces much less CPU cache misses. - // This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current - // CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase - // speed somehow, but once you drop out of CPU's cache, things will slow down drastically. - // For older CPUs with less cache, lower value would yield better results. - - BYTE *bsrc = FreeImage_GetBits(src); // source pixels - BYTE *bdest = FreeImage_GetBits(dst); // destination pixels - - // calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - // for all image blocks of RBLOCK*RBLOCK pixels - - // x-segment - for(unsigned xs = 0; xs < dst_width; xs += RBLOCK) { - // y-segment - for(unsigned ys = 0; ys < dst_height; ys += RBLOCK) { - for(unsigned y = ys; y < MIN(dst_height, ys + RBLOCK); y++) { // do rotation - const unsigned y2 = dst_height - y - 1; - // point to src pixel at (y2, xs) - BYTE *src_bits = bsrc + (xs * src_pitch) + (y2 * bytespp); - // point to dst pixel at (xs, y) - BYTE *dst_bits = bdest + (y * dst_pitch) + (xs * bytespp); - for(unsigned x = xs; x < MIN(dst_width, xs + RBLOCK); x++) { - // dst.SetPixel(x, y, src.GetPixel(y2, x)); - AssignPixel(dst_bits, src_bits, bytespp); - dst_bits += bytespp; - src_bits += src_pitch; - } - } - } - } - } - break; - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - { - BYTE *bsrc = FreeImage_GetBits(src); // source pixels - BYTE *bdest = FreeImage_GetBits(dst); // destination pixels - - // calculate the number of bytes per pixel - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(unsigned y = 0; y < dst_height; y++) { - BYTE *src_bits = bsrc + (src_width - 1 - y) * bytespp; - BYTE *dst_bits = bdest + (y * dst_pitch); - for(unsigned x = 0; x < dst_width; x++) { - AssignPixel(dst_bits, src_bits, bytespp); - src_bits += src_pitch; - dst_bits += bytespp; - } - } - } - break; - } - - return dst; -} - -/** -Rotates an image by 180 degrees (counter clockwise). -Precise rotation, no filters required. -@param src Pointer to source image to rotate -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP* -Rotate180(FIBITMAP *src) { - int x, y, k, pos; - - const int bpp = FreeImage_GetBPP(src); - - const int src_width = FreeImage_GetWidth(src); - const int src_height = FreeImage_GetHeight(src); - const int dst_width = src_width; - const int dst_height = src_height; - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp); - if(NULL == dst) return NULL; - - switch(image_type) { - case FIT_BITMAP: - if(bpp == 1) { - for(int y = 0; y < src_height; y++) { - BYTE *src_bits = FreeImage_GetScanLine(src, y); - BYTE *dst_bits = FreeImage_GetScanLine(dst, dst_height - y - 1); - for(int x = 0; x < src_width; x++) { - // get bit at (x, y) - k = (src_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0; - // set bit at (dst_width - x - 1, dst_height - y - 1) - pos = dst_width - x - 1; - k ? dst_bits[pos >> 3] |= (0x80 >> (pos & 0x7)) : dst_bits[pos >> 3] &= (0xFF7F >> (pos & 0x7)); - } - } - break; - } - // else if ((bpp == 8) || (bpp == 24) || (bpp == 32)) FALL TROUGH - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - { - // Calculate the number of bytes per pixel - const int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(y = 0; y < src_height; y++) { - BYTE *src_bits = FreeImage_GetScanLine(src, y); - BYTE *dst_bits = FreeImage_GetScanLine(dst, dst_height - y - 1) + (dst_width - 1) * bytespp; - for(x = 0; x < src_width; x++) { - // get pixel at (x, y) - // set pixel at (dst_width - x - 1, dst_height - y - 1) - AssignPixel(dst_bits, src_bits, bytespp); - src_bits += bytespp; - dst_bits -= bytespp; - } - } - } - break; - } - - return dst; -} - -/** -Rotates an image by 270 degrees (counter clockwise). -Precise rotation, no filters required.
-Code adapted from CxImage (http://www.xdp.it/cximage.htm) -@param src Pointer to source image to rotate -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP* -Rotate270(FIBITMAP *src) { - int x2, dlineup; - - const unsigned bpp = FreeImage_GetBPP(src); - - const unsigned src_width = FreeImage_GetWidth(src); - const unsigned src_height = FreeImage_GetHeight(src); - const unsigned dst_width = src_height; - const unsigned dst_height = src_width; - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - // allocate and clear dst image - FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp); - if(NULL == dst) return NULL; - - // get src and dst scan width - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - switch(image_type) { - case FIT_BITMAP: - if(bpp == 1) { - // speedy rotate for BW images - - BYTE *bsrc = FreeImage_GetBits(src); - BYTE *bdest = FreeImage_GetBits(dst); - BYTE *dbitsmax = bdest + dst_height * dst_pitch - 1; - dlineup = 8 * dst_pitch - dst_width; - - for(unsigned y = 0; y < src_height; y++) { - // figure out the column we are going to be copying to - const div_t div_r = div(y + dlineup, 8); - // set bit pos of src column byte - const BYTE bitpos = (BYTE)(1 << div_r.rem); - const BYTE *srcdisp = bsrc + y * src_pitch; - for(unsigned x = 0; x < src_pitch; x++) { - // get source bits - const BYTE *sbits = srcdisp + x; - // get destination column - BYTE *nrow = bdest + (x * 8) * dst_pitch + dst_pitch - 1 - div_r.quot; - for(unsigned z = 0; z < 8; z++) { - // get destination byte - BYTE *dbits = nrow + z * dst_pitch; - if ((dbits < bdest) || (dbits > dbitsmax)) break; - if (*sbits & (128 >> z)) *dbits |= bitpos; - } - } - } - } - else if ((bpp == 8) || (bpp == 24) || (bpp == 32)) { - // anything other than BW : - // This optimized version of rotation rotates image by smaller blocks. It is quite - // a bit faster than obvious algorithm, because it produces much less CPU cache misses. - // This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current - // CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase - // speed somehow, but once you drop out of CPU's cache, things will slow down drastically. - // For older CPUs with less cache, lower value would yield better results. - - BYTE *bsrc = FreeImage_GetBits(src); // source pixels - BYTE *bdest = FreeImage_GetBits(dst); // destination pixels - - // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - // for all image blocks of RBLOCK*RBLOCK pixels - - // x-segment - for(unsigned xs = 0; xs < dst_width; xs += RBLOCK) { - // y-segment - for(unsigned ys = 0; ys < dst_height; ys += RBLOCK) { - for(unsigned x = xs; x < MIN(dst_width, xs + RBLOCK); x++) { // do rotation - x2 = dst_width - x - 1; - // point to src pixel at (ys, x2) - BYTE *src_bits = bsrc + (x2 * src_pitch) + (ys * bytespp); - // point to dst pixel at (x, ys) - BYTE *dst_bits = bdest + (ys * dst_pitch) + (x * bytespp); - for(unsigned y = ys; y < MIN(dst_height, ys + RBLOCK); y++) { - // dst.SetPixel(x, y, src.GetPixel(y, x2)); - AssignPixel(dst_bits, src_bits, bytespp); - src_bits += bytespp; - dst_bits += dst_pitch; - } - } - } - } - } - break; - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - { - BYTE *bsrc = FreeImage_GetBits(src); // source pixels - BYTE *bdest = FreeImage_GetBits(dst); // destination pixels - - // calculate the number of bytes per pixel - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(unsigned y = 0; y < dst_height; y++) { - BYTE *src_bits = bsrc + (src_height - 1) * src_pitch + y * bytespp; - BYTE *dst_bits = bdest + (y * dst_pitch); - for(unsigned x = 0; x < dst_width; x++) { - AssignPixel(dst_bits, src_bits, bytespp); - src_bits -= src_pitch; - dst_bits += bytespp; - } - } - } - break; - } - - return dst; -} - -/** -Rotates an image by a given degree in range [-45 .. +45] (counter clockwise) -using the 3-shear technique. -@param src Pointer to source image to rotate -@param dAngle Rotation angle -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP* -Rotate45(FIBITMAP *src, double dAngle, const void *bkcolor) { - const double ROTATE_PI = double(3.1415926535897932384626433832795); - - unsigned u; - - const unsigned bpp = FreeImage_GetBPP(src); - - const double dRadAngle = dAngle * ROTATE_PI / double(180); // Angle in radians - const double dSinE = sin(dRadAngle); - const double dTan = tan(dRadAngle / 2); - - const unsigned src_width = FreeImage_GetWidth(src); - const unsigned src_height = FreeImage_GetHeight(src); - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - // Calc first shear (horizontal) destination image dimensions - const unsigned width_1 = src_width + unsigned((double)src_height * fabs(dTan) + 0.5); - const unsigned height_1 = src_height; - - // Perform 1st shear (horizontal) - // ---------------------------------------------------------------------- - - // Allocate image for 1st shear - FIBITMAP *dst1 = FreeImage_AllocateT(image_type, width_1, height_1, bpp); - if(NULL == dst1) { - return NULL; - } - - for(u = 0; u < height_1; u++) { - double dShear; - - if(dTan >= 0) { - // Positive angle - dShear = (u + 0.5) * dTan; - } - else { - // Negative angle - dShear = (double(u) - height_1 + 0.5) * dTan; - } - int iShear = int(floor(dShear)); - HorizontalSkew(src, dst1, u, iShear, dShear - double(iShear), bkcolor); - } - - // Perform 2nd shear (vertical) - // ---------------------------------------------------------------------- - - // Calc 2nd shear (vertical) destination image dimensions - const unsigned width_2 = width_1; - unsigned height_2 = unsigned((double)src_width * fabs(dSinE) + (double)src_height * cos(dRadAngle) + 0.5) + 1; - - // Allocate image for 2nd shear - FIBITMAP *dst2 = FreeImage_AllocateT(image_type, width_2, height_2, bpp); - if(NULL == dst2) { - FreeImage_Unload(dst1); - return NULL; - } - - double dOffset; // Variable skew offset - if(dSinE > 0) { - // Positive angle - dOffset = (src_width - 1.0) * dSinE; - } - else { - // Negative angle - dOffset = -dSinE * (double(src_width) - width_2); - } - - for(u = 0; u < width_2; u++, dOffset -= dSinE) { - int iShear = int(floor(dOffset)); - VerticalSkew(dst1, dst2, u, iShear, dOffset - double(iShear), bkcolor); - } - - // Perform 3rd shear (horizontal) - // ---------------------------------------------------------------------- - - // Free result of 1st shear - FreeImage_Unload(dst1); - - // Calc 3rd shear (horizontal) destination image dimensions - const unsigned width_3 = unsigned(double(src_height) * fabs(dSinE) + double(src_width) * cos(dRadAngle) + 0.5) + 1; - const unsigned height_3 = height_2; - - // Allocate image for 3rd shear - FIBITMAP *dst3 = FreeImage_AllocateT(image_type, width_3, height_3, bpp); - if(NULL == dst3) { - FreeImage_Unload(dst2); - return NULL; - } - - if(dSinE >= 0) { - // Positive angle - dOffset = (src_width - 1.0) * dSinE * -dTan; - } - else { - // Negative angle - dOffset = dTan * ( (src_width - 1.0) * -dSinE + (1.0 - height_3)); - } - for(u = 0; u < height_3; u++, dOffset += dTan) { - int iShear = int(floor(dOffset)); - HorizontalSkew(dst2, dst3, u, iShear, dOffset - double(iShear), bkcolor); - } - // Free result of 2nd shear - FreeImage_Unload(dst2); - - // Return result of 3rd shear - return dst3; -} - -/** -Rotates a 1-, 8-, 24- or 32-bit image by a given angle (given in degree). -Angle is unlimited, except for 1-bit images (limited to integer multiples of 90 degree). -3-shears technique is used. -@param src Pointer to source image to rotate -@param dAngle Rotation angle -@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise -*/ -static FIBITMAP* -RotateAny(FIBITMAP *src, double dAngle, const void *bkcolor) { - if(NULL == src) { - return NULL; - } - - FIBITMAP *image = src; - - while(dAngle >= 360) { - // Bring angle to range of (-INF .. 360) - dAngle -= 360; - } - while(dAngle < 0) { - // Bring angle to range of [0 .. 360) - dAngle += 360; - } - if ((dAngle > 45) && (dAngle <= 135)) { - // Angle in (45 .. 135] - // Rotate image by 90 degrees into temporary image, - // so it requires only an extra rotation angle - // of -45 .. +45 to complete rotation. - image = Rotate90(src); - dAngle -= 90; - } - else if ((dAngle > 135) && (dAngle <= 225)) { - // Angle in (135 .. 225] - // Rotate image by 180 degrees into temporary image, - // so it requires only an extra rotation angle - // of -45 .. +45 to complete rotation. - image = Rotate180(src); - dAngle -= 180; - } - else if ((dAngle > 225) && (dAngle <= 315)) { - // Angle in (225 .. 315] - // Rotate image by 270 degrees into temporary image, - // so it requires only an extra rotation angle - // of -45 .. +45 to complete rotation. - image = Rotate270(src); - dAngle -= 270; - } - - // If we got here, angle is in (-45 .. +45] - - if(NULL == image) { - // Failed to allocate middle image - return NULL; - } - - if(0 == dAngle) { - if(image == src) { - // Nothing to do ... - return FreeImage_Clone(src); - } else { - // No more rotation needed - return image; - } - } - else { - // Perform last rotation - FIBITMAP *dst = Rotate45(image, dAngle, bkcolor); - - if(src != image) { - // Middle image was required, free it now. - FreeImage_Unload(image); - } - - return dst; - } -} - -// ========================================================== - -FIBITMAP *DLL_CALLCONV -FreeImage_Rotate(FIBITMAP *dib, double angle, const void *bkcolor) { - if (!FreeImage_HasPixels(dib)) return NULL; - - if(0 == angle) { - return FreeImage_Clone(dib); - } - // DIB are stored upside down ... - angle *= -1; - - try { - unsigned bpp = FreeImage_GetBPP(dib); - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - switch(image_type) { - case FIT_BITMAP: - if(bpp == 1) { - // only rotate for integer multiples of 90 degree - if(fmod(angle, 90) != 0) - return NULL; - - // perform the rotation - FIBITMAP *dst = RotateAny(dib, angle, bkcolor); - if (!dst) throw(1); - - // build a greyscale palette - RGBQUAD *dst_pal = FreeImage_GetPalette(dst); - if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) { - dst_pal[0].rgbRed = dst_pal[0].rgbGreen = dst_pal[0].rgbBlue = 0; - dst_pal[1].rgbRed = dst_pal[1].rgbGreen = dst_pal[1].rgbBlue = 255; - } else { - dst_pal[0].rgbRed = dst_pal[0].rgbGreen = dst_pal[0].rgbBlue = 255; - dst_pal[1].rgbRed = dst_pal[1].rgbGreen = dst_pal[1].rgbBlue = 0; - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, dib); - - return dst; - } - else if ((bpp == 8) || (bpp == 24) || (bpp == 32)) { - FIBITMAP *dst = RotateAny(dib, angle, bkcolor); - if (!dst) throw(1); - - if(bpp == 8) { - // copy original palette to rotated bitmap - RGBQUAD *src_pal = FreeImage_GetPalette(dib); - RGBQUAD *dst_pal = FreeImage_GetPalette(dst); - memcpy(&dst_pal[0], &src_pal[0], 256 * sizeof(RGBQUAD)); - - // copy transparency table - FreeImage_SetTransparencyTable(dst, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib)); - - // copy background color - RGBQUAD bkcolor; - if ( FreeImage_GetBackgroundColor(dib, &bkcolor)) { - FreeImage_SetBackgroundColor(dst, &bkcolor); - } - - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, dib); - - return dst; - } - break; - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - { - FIBITMAP *dst = RotateAny(dib, angle, bkcolor); - if (!dst) throw(1); - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, dib); - - return dst; - } - break; - } - - } catch(int) { - return NULL; - } - - return NULL; -} - diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Colors.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Colors.cpp deleted file mode 100644 index 8b9bbd6482..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Colors.cpp +++ /dev/null @@ -1,967 +0,0 @@ -// ========================================================== -// Color manipulation routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Carsten Klein (c.klein@datagis.com) -// - Mihail Naydenov (mnaydenov@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// Macros + structures -// ---------------------------------------------------------- - -#define GET_HI_NIBBLE(byte) ((byte) >> 4) -#define SET_HI_NIBBLE(byte, n) byte &= 0x0F, byte |= ((n) << 4) -#define GET_LO_NIBBLE(byte) ((byte) & 0x0F) -#define SET_LO_NIBBLE(byte, n) byte &= 0xF0, byte |= ((n) & 0x0F) -#define GET_NIBBLE(cn, byte) ((cn) ? (GET_HI_NIBBLE(byte)) : (GET_LO_NIBBLE(byte))) -#define SET_NIBBLE(cn, byte, n) if (cn) SET_HI_NIBBLE(byte, n); else SET_LO_NIBBLE(byte, n) - -// ---------------------------------------------------------- - - -/** @brief Inverts each pixel data. - -@param src Input image to be processed. -@return Returns TRUE if successful, FALSE otherwise. -*/ -BOOL DLL_CALLCONV -FreeImage_Invert(FIBITMAP *src) { - - if (!FreeImage_HasPixels(src)) return FALSE; - - unsigned i, x, y, k; - - const unsigned width = FreeImage_GetWidth(src); - const unsigned height = FreeImage_GetHeight(src); - const unsigned bpp = FreeImage_GetBPP(src); - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - if(image_type == FIT_BITMAP) { - switch(bpp) { - case 1 : - case 4 : - case 8 : - { - // if the dib has a colormap, just invert it - // else, keep the linear grayscale - - if (FreeImage_GetColorType(src) == FIC_PALETTE) { - RGBQUAD *pal = FreeImage_GetPalette(src); - - for(i = 0; i < FreeImage_GetColorsUsed(src); i++) { - pal[i].rgbRed = 255 - pal[i].rgbRed; - pal[i].rgbGreen = 255 - pal[i].rgbGreen; - pal[i].rgbBlue = 255 - pal[i].rgbBlue; - } - } else { - for(y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(src, y); - - for (x = 0; x < FreeImage_GetLine(src); x++) { - bits[x] = ~bits[x]; - } - } - } - - break; - } - - case 24 : - case 32 : - { - // Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / width; - - for(y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < width; x++) { - for(k = 0; k < bytespp; k++) { - bits[k] = ~bits[k]; - } - bits += bytespp; - } - } - - break; - } - default: - return FALSE; - } - } - else if ((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) { - // Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) - const unsigned wordspp = (FreeImage_GetLine(src) / width) / sizeof(WORD); - - for(y = 0; y < height; y++) { - WORD *bits = (WORD*)FreeImage_GetScanLine(src, y); - for(x = 0; x < width; x++) { - for(k = 0; k < wordspp; k++) { - bits[k] = ~bits[k]; - } - bits += wordspp; - } - } - } - else { - // anything else ... - return FALSE; - } - - return TRUE; -} - -/** @brief Perfoms an histogram transformation on a 8, 24 or 32-bit image -according to the values of a lookup table (LUT). - -The transformation is done as follows.
-Image 8-bit : if the image has a color palette, the LUT is applied to this palette, -otherwise, it is applied to the grey values.
-Image 24-bit & 32-bit : if channel == FICC_RGB, the same LUT is applied to each color -plane (R,G, and B). Otherwise, the LUT is applied to the specified channel only. -@param src Input image to be processed. -@param LUT Lookup table. The size of 'LUT' is assumed to be 256. -@param channel The color channel to be processed (only used with 24 & 32-bit DIB). -@return Returns TRUE if successful, FALSE otherwise. -@see FREE_IMAGE_COLOR_CHANNEL -*/ -BOOL DLL_CALLCONV -FreeImage_AdjustCurve(FIBITMAP *src, BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel) { - unsigned x, y; - BYTE *bits = NULL; - - if (!FreeImage_HasPixels(src) || !LUT || (FreeImage_GetImageType(src) != FIT_BITMAP)) - return FALSE; - - int bpp = FreeImage_GetBPP(src); - if ((bpp != 8) && (bpp != 24) && (bpp != 32)) - return FALSE; - - // apply the LUT - switch(bpp) { - - case 8 : - { - // if the dib has a colormap, apply the LUT to it - // else, apply the LUT to pixel values - - if(FreeImage_GetColorType(src) == FIC_PALETTE) { - RGBQUAD *rgb = FreeImage_GetPalette(src); - for (unsigned pal = 0; pal < FreeImage_GetColorsUsed(src); pal++) { - rgb->rgbRed = LUT[rgb->rgbRed]; - rgb->rgbGreen = LUT[rgb->rgbGreen]; - rgb->rgbBlue = LUT[rgb->rgbBlue]; - rgb++; - } - } - else { - for(y = 0; y < FreeImage_GetHeight(src); y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < FreeImage_GetWidth(src); x++) { - bits[x] = LUT[ bits[x] ]; - } - } - } - - break; - } - - case 24 : - case 32 : - { - int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - switch(channel) { - case FICC_RGB : - for(y = 0; y < FreeImage_GetHeight(src); y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < FreeImage_GetWidth(src); x++) { - bits[FI_RGBA_BLUE] = LUT[ bits[FI_RGBA_BLUE] ]; // B - bits[FI_RGBA_GREEN] = LUT[ bits[FI_RGBA_GREEN] ]; // G - bits[FI_RGBA_RED] = LUT[ bits[FI_RGBA_RED] ]; // R - - bits += bytespp; - } - } - break; - - case FICC_BLUE : - for(y = 0; y < FreeImage_GetHeight(src); y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < FreeImage_GetWidth(src); x++) { - bits[FI_RGBA_BLUE] = LUT[ bits[FI_RGBA_BLUE] ]; // B - - bits += bytespp; - } - } - break; - - case FICC_GREEN : - for(y = 0; y < FreeImage_GetHeight(src); y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < FreeImage_GetWidth(src); x++) { - bits[FI_RGBA_GREEN] = LUT[ bits[FI_RGBA_GREEN] ]; // G - - bits += bytespp; - } - } - break; - - case FICC_RED : - for(y = 0; y < FreeImage_GetHeight(src); y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < FreeImage_GetWidth(src); x++) { - bits[FI_RGBA_RED] = LUT[ bits[FI_RGBA_RED] ]; // R - - bits += bytespp; - } - } - break; - - case FICC_ALPHA : - if(32 == bpp) { - for(y = 0; y < FreeImage_GetHeight(src); y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < FreeImage_GetWidth(src); x++) { - bits[FI_RGBA_ALPHA] = LUT[ bits[FI_RGBA_ALPHA] ]; // A - - bits += bytespp; - } - } - } - break; - - default: - break; - } - break; - } - } - - return TRUE; -} - -/** @brief Performs gamma correction on a 8, 24 or 32-bit image. - -@param src Input image to be processed. -@param gamma Gamma value to use. A value of 1.0 leaves the image alone, -less than one darkens it, and greater than one lightens it. -@return Returns TRUE if successful, FALSE otherwise. -*/ -BOOL DLL_CALLCONV -FreeImage_AdjustGamma(FIBITMAP *src, double gamma) { - BYTE LUT[256]; // Lookup table - - if (!FreeImage_HasPixels(src) || (gamma <= 0)) - return FALSE; - - // Build the lookup table - - double exponent = 1 / gamma; - double v = 255.0 * (double)pow((double)255, -exponent); - for(int i = 0; i < 256; i++) { - double color = (double)pow((double)i, exponent) * v; - if(color > 255) - color = 255; - LUT[i] = (BYTE)floor(color + 0.5); - } - - // Apply the gamma correction - return FreeImage_AdjustCurve(src, LUT, FICC_RGB); -} - -/** @brief Adjusts the brightness of a 8, 24 or 32-bit image by a certain amount. - -@param src Input image to be processed. -@param percentage Where -100 <= percentage <= 100
-A value 0 means no change, less than 0 will make the image darker -and greater than 0 will make the image brighter. -@return Returns TRUE if successful, FALSE otherwise. -*/ -BOOL DLL_CALLCONV -FreeImage_AdjustBrightness(FIBITMAP *src, double percentage) { - BYTE LUT[256]; // Lookup table - double value; - - if (!FreeImage_HasPixels(src)) - return FALSE; - - // Build the lookup table - const double scale = (100 + percentage) / 100; - for(int i = 0; i < 256; i++) { - value = i * scale; - value = MAX(0.0, MIN(value, 255.0)); - LUT[i] = (BYTE)floor(value + 0.5); - } - return FreeImage_AdjustCurve(src, LUT, FICC_RGB); -} - -/** @brief Adjusts the contrast of a 8, 24 or 32-bit image by a certain amount. - -@param src Input image to be processed. -@param percentage Where -100 <= percentage <= 100
-A value 0 means no change, less than 0 will decrease the contrast -and greater than 0 will increase the contrast of the image. -@return Returns TRUE if successful, FALSE otherwise. -*/ -BOOL DLL_CALLCONV -FreeImage_AdjustContrast(FIBITMAP *src, double percentage) { - BYTE LUT[256]; // Lookup table - double value; - - if (!FreeImage_HasPixels(src)) - return FALSE; - - // Build the lookup table - const double scale = (100 + percentage) / 100; - for(int i = 0; i < 256; i++) { - value = 128 + (i - 128) * scale; - value = MAX(0.0, MIN(value, 255.0)); - LUT[i] = (BYTE)floor(value + 0.5); - } - return FreeImage_AdjustCurve(src, LUT, FICC_RGB); -} - -/** @brief Computes image histogram - -For 24-bit and 32-bit images, histogram can be computed from red, green, blue and -black channels. For 8-bit images, histogram is computed from the black channel. Other -bit depth is not supported (nothing is done). -@param src Input image to be processed. -@param histo Histogram array to fill. The size of 'histo' is assumed to be 256. -@param channel Color channel to use -@return Returns TRUE if succesful, returns FALSE if the image bit depth isn't supported. -*/ -BOOL DLL_CALLCONV -FreeImage_GetHistogram(FIBITMAP *src, DWORD *histo, FREE_IMAGE_COLOR_CHANNEL channel) { - BYTE pixel; - BYTE *bits = NULL; - unsigned x, y; - - if (!FreeImage_HasPixels(src) || !histo) return FALSE; - - unsigned width = FreeImage_GetWidth(src); - unsigned height = FreeImage_GetHeight(src); - unsigned bpp = FreeImage_GetBPP(src); - - if(bpp == 8) { - // clear histogram array - memset(histo, 0, 256 * sizeof(DWORD)); - // compute histogram for black channel - for(y = 0; y < height; y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < width; x++) { - // get pixel value - pixel = bits[x]; - histo[pixel]++; - } - } - return TRUE; - } - else if ((bpp == 24) || (bpp == 32)) { - int bytespp = bpp / 8; // bytes / pixel - - // clear histogram array - memset(histo, 0, 256 * sizeof(DWORD)); - - switch(channel) { - case FICC_RED: - // compute histogram for red channel - for(y = 0; y < height; y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < width; x++) { - pixel = bits[FI_RGBA_RED]; // R - histo[pixel]++; - bits += bytespp; - } - } - return TRUE; - - case FICC_GREEN: - // compute histogram for green channel - for(y = 0; y < height; y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < width; x++) { - pixel = bits[FI_RGBA_GREEN]; // G - histo[pixel]++; - bits += bytespp; - } - } - return TRUE; - - case FICC_BLUE: - // compute histogram for blue channel - for(y = 0; y < height; y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < width; x++) { - pixel = bits[FI_RGBA_BLUE]; // B - histo[pixel]++; - bits += bytespp; - } - } - return TRUE; - - case FICC_BLACK: - case FICC_RGB: - // compute histogram for black channel - for(y = 0; y < height; y++) { - bits = FreeImage_GetScanLine(src, y); - for(x = 0; x < width; x++) { - // RGB to GREY conversion - pixel = GREY(bits[FI_RGBA_RED], bits[FI_RGBA_GREEN], bits[FI_RGBA_BLUE]); - histo[pixel]++; - bits += bytespp; - } - } - return TRUE; - - default: - return FALSE; - } - } - - return FALSE; -} - -// ---------------------------------------------------------- - - -/** @brief Creates a lookup table to be used with FreeImage_AdjustCurve() which - may adjust brightness and contrast, correct gamma and invert the image with a - single call to FreeImage_AdjustCurve(). - - This function creates a lookup table to be used with FreeImage_AdjustCurve() - which may adjust brightness and contrast, correct gamma and invert the image - with a single call to FreeImage_AdjustCurve(). If more than one of these image - display properties need to be adjusted, using a combined lookup table should be - preferred over calling each adjustment function separately. That's particularly - true for huge images or if performance is an issue. Then, the expensive process - of iterating over all pixels of an image is performed only once and not up to - four times. - - Furthermore, the lookup table created does not depend on the order, in which - each single adjustment operation is performed. Due to rounding and byte casting - issues, it actually matters in which order individual adjustment operations - are performed. Both of the following snippets most likely produce different - results: - - // snippet 1: contrast, brightness - FreeImage_AdjustContrast(dib, 15.0); - FreeImage_AdjustBrightness(dib, 50.0); - - // snippet 2: brightness, contrast - FreeImage_AdjustBrightness(dib, 50.0); - FreeImage_AdjustContrast(dib, 15.0); - - Better and even faster would be snippet 3: - - // snippet 3: - BYTE LUT[256]; - FreeImage_GetAdjustColorsLookupTable(LUT, 50.0, 15.0, 1.0, FALSE); - FreeImage_AdjustCurve(dib, LUT, FICC_RGB); - - This function is also used internally by FreeImage_AdjustColors(), which does - not return the lookup table, but uses it to call FreeImage_AdjustCurve() on the - passed image. - - @param LUT Output lookup table to be used with FreeImage_AdjustCurve(). The - size of 'LUT' is assumed to be 256. - @param brightness Percentage brightness value where -100 <= brightness <= 100
- A value of 0 means no change, less than 0 will make the image darker and greater - than 0 will make the image brighter. - @param contrast Percentage contrast value where -100 <= contrast <= 100
- A value of 0 means no change, less than 0 will decrease the contrast - and greater than 0 will increase the contrast of the image. - @param gamma Gamma value to be used for gamma correction. A value of 1.0 leaves - the image alone, less than one darkens it, and greater than one lightens it. - This parameter must not be zero or smaller than zero. If so, it will be ignored - and no gamma correction will be performed using the lookup table created. - @param invert If set to TRUE, the image will be inverted. - @return Returns the number of adjustments applied to the resulting lookup table - compared to a blind lookup table. - */ -int DLL_CALLCONV -FreeImage_GetAdjustColorsLookupTable(BYTE *LUT, double brightness, double contrast, double gamma, BOOL invert) { - double dblLUT[256]; - double value; - int result = 0; - - if ((brightness == 0.0) && (contrast == 0.0) && (gamma == 1.0) && (!invert)) { - // nothing to do, if all arguments have their default values - // return a blind LUT - for (int i = 0; i < 256; i++) { - LUT[i] = (BYTE)i; - } - return 0; - } - - // first, create a blind LUT, which does nothing to the image - for (int i = 0; i < 256; i++) { - dblLUT[i] = i; - } - - if (contrast != 0.0) { - // modify lookup table with contrast adjustment data - const double v = (100.0 + contrast) / 100.0; - for (int i = 0; i < 256; i++) { - value = 128 + (dblLUT[i] - 128) * v; - dblLUT[i] = MAX(0.0, MIN(value, 255.0)); - } - result++; - } - - if (brightness != 0.0) { - // modify lookup table with brightness adjustment data - const double v = (100.0 + brightness) / 100.0; - for (int i = 0; i < 256; i++) { - value = dblLUT[i] * v; - dblLUT[i] = MAX(0.0, MIN(value, 255.0)); - } - result++; - } - - if ((gamma > 0) && (gamma != 1.0)) { - // modify lookup table with gamma adjustment data - double exponent = 1 / gamma; - const double v = 255.0 * (double)pow((double)255, -exponent); - for (int i = 0; i < 256; i++) { - value = pow(dblLUT[i], exponent) * v; - dblLUT[i] = MAX(0.0, MIN(value, 255.0)); - } - result++; - } - - if (!invert) { - for (int i = 0; i < 256; i++) { - LUT[i] = (BYTE)floor(dblLUT[i] + 0.5); - } - } else { - for (int i = 0; i < 256; i++) { - LUT[i] = 255 - (BYTE)floor(dblLUT[i] + 0.5); - } - result++; - } - // return the number of adjustments made - return result; -} - -/** @brief Adjusts an image's brightness, contrast and gamma as well as it may - optionally invert the image within a single operation. - - This function adjusts an image's brightness, contrast and gamma as well as it - may optionally invert the image within a single operation. If more than one of - these image display properties need to be adjusted, using this function should - be preferred over calling each adjustment function separately. That's - particularly true for huge images or if performance is an issue. - - This function relies on FreeImage_GetAdjustColorsLookupTable(), which creates a - single lookup table, that combines all adjustment operations requested. - - Furthermore, the lookup table created by FreeImage_GetAdjustColorsLookupTable() - does not depend on the order, in which each single adjustment operation is - performed. Due to rounding and byte casting issues, it actually matters in which - order individual adjustment operations are performed. Both of the following - snippets most likely produce different results: - - // snippet 1: contrast, brightness - FreeImage_AdjustContrast(dib, 15.0); - FreeImage_AdjustBrightness(dib, 50.0); - - // snippet 2: brightness, contrast - FreeImage_AdjustBrightness(dib, 50.0); - FreeImage_AdjustContrast(dib, 15.0); - - Better and even faster would be snippet 3: - - // snippet 3: - FreeImage_AdjustColors(dib, 50.0, 15.0, 1.0, FALSE); - - @param dib Input/output image to be processed. - @param brightness Percentage brightness value where -100 <= brightness <= 100
- A value of 0 means no change, less than 0 will make the image darker and greater - than 0 will make the image brighter. - @param contrast Percentage contrast value where -100 <= contrast <= 100
- A value of 0 means no change, less than 0 will decrease the contrast - and greater than 0 will increase the contrast of the image. - @param gamma Gamma value to be used for gamma correction. A value of 1.0 leaves - the image alone, less than one darkens it, and greater than one lightens it.
- This parameter must not be zero or smaller than zero. If so, it will be ignored - and no gamma correction will be performed on the image. - @param invert If set to TRUE, the image will be inverted. - @return Returns TRUE on success, FALSE otherwise (e.g. when the bitdeph of the - source dib cannot be handled). - */ -BOOL DLL_CALLCONV -FreeImage_AdjustColors(FIBITMAP *dib, double brightness, double contrast, double gamma, BOOL invert) { - BYTE LUT[256]; - - if (!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { - return FALSE; - } - - int bpp = FreeImage_GetBPP(dib); - if ((bpp != 8) && (bpp != 24) && (bpp != 32)) { - return FALSE; - } - - if (FreeImage_GetAdjustColorsLookupTable(LUT, brightness, contrast, gamma, invert)) { - return FreeImage_AdjustCurve(dib, LUT, FICC_RGB); - } - return FALSE; -} - -/** @brief Applies color mapping for one or several colors on a 1-, 4- or 8-bit - palletized or a 16-, 24- or 32-bit high color image. - - This function maps up to count colors specified in srccolors to - these specified in dstcolors. Thereby, color srccolors[N], - if found in the image, will be replaced by color dstcolors[N]. If - parameter swap is TRUE, additionally all colors specified in - dstcolors are also mapped to these specified in srccolors. For - high color images, the actual image data will be modified whereas, for - palletized images only the palette will be changed.
- - The function returns the number of pixels changed or zero, if no pixels were - changed. - - Both arrays srccolors and dstcolors are assumed not to hold less - than count colors.
- - For 16-bit images, all colors specified are transparently converted to their - proper 16-bit representation (either in RGB555 or RGB565 format, which is - determined by the image's red- green- and blue-mask).
- - Note, that this behaviour is different from what FreeImage_ApplyPaletteIndexMapping() - does, which modifies the actual image data on palletized images. - - @param dib Input/output image to be processed. - @param srccolors Array of colors to be used as the mapping source. - @param dstcolors Array of colors to be used as the mapping destination. - @param count The number of colors to be mapped. This is the size of both - srccolors and dstcolors. - @param ignore_alpha If TRUE, 32-bit images and colors are treated as 24-bit. - @param swap If TRUE, source and destination colors are swapped, that is, - each destination color is also mapped to the corresponding source color. - @return Returns the total number of pixels changed. - */ -unsigned DLL_CALLCONV -FreeImage_ApplyColorMapping(FIBITMAP *dib, RGBQUAD *srccolors, RGBQUAD *dstcolors, unsigned count, BOOL ignore_alpha, BOOL swap) { - unsigned result = 0; - - if (!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { - return 0; - } - - // validate parameters - if ((!srccolors) || (!dstcolors)|| (count < 1)) { - return 0; - } - - int bpp = FreeImage_GetBPP(dib); - switch (bpp) { - case 1: - case 4: - case 8: { - unsigned size = FreeImage_GetColorsUsed(dib); - RGBQUAD *pal = FreeImage_GetPalette(dib); - RGBQUAD *a, *b; - for (unsigned x = 0; x < size; x++) { - for (unsigned j = 0; j < count; j++) { - a = srccolors; - b = dstcolors; - for (int i = (swap ? 0 : 1); i < 2; i++) { - if ((pal[x].rgbBlue == a[j].rgbBlue)&&(pal[x].rgbGreen == a[j].rgbGreen) &&(pal[x].rgbRed== a[j].rgbRed)) { - pal[x].rgbBlue = b[j].rgbBlue; - pal[x].rgbGreen = b[j].rgbGreen; - pal[x].rgbRed = b[j].rgbRed; - result++; - j = count; - break; - } - a = dstcolors; - b = srccolors; - } - } - } - return result; - } - case 16: { - WORD *src16 = (WORD *)malloc(sizeof(WORD) * count); - if (NULL == src16) { - return 0; - } - - WORD *dst16 = (WORD *)malloc(sizeof(WORD) * count); - if (NULL == dst16) { - free(src16); - return 0; - } - - for (unsigned j = 0; j < count; j++) { - src16[j] = RGBQUAD_TO_WORD(dib, (srccolors + j)); - dst16[j] = RGBQUAD_TO_WORD(dib, (dstcolors + j)); - } - - unsigned height = FreeImage_GetHeight(dib); - unsigned width = FreeImage_GetWidth(dib); - WORD *a, *b; - for (unsigned y = 0; y < height; y++) { - WORD *bits = (WORD *)FreeImage_GetScanLine(dib, y); - for (unsigned x = 0; x < width; x++, bits++) { - for (unsigned j = 0; j < count; j++) { - a = src16; - b = dst16; - for (int i = (swap ? 0 : 1); i < 2; i++) { - if (*bits == a[j]) { - *bits = b[j]; - result++; - j = count; - break; - } - a = dst16; - b = src16; - } - } - } - } - free(src16); - free(dst16); - return result; - } - case 24: { - unsigned height = FreeImage_GetHeight(dib); - unsigned width = FreeImage_GetWidth(dib); - RGBQUAD *a, *b; - for (unsigned y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - for (unsigned x = 0; x < width; x++, bits += 3) { - for (unsigned j = 0; j < count; j++) { - a = srccolors; - b = dstcolors; - for (int i = (swap ? 0 : 1); i < 2; i++) { - if ((bits[FI_RGBA_BLUE] == a[j].rgbBlue) && (bits[FI_RGBA_GREEN] == a[j].rgbGreen) &&(bits[FI_RGBA_RED] == a[j].rgbRed)) { - bits[FI_RGBA_BLUE] = b[j].rgbBlue; - bits[FI_RGBA_GREEN] = b[j].rgbGreen; - bits[FI_RGBA_RED] = b[j].rgbRed; - result++; - j = count; - break; - } - a = dstcolors; - b = srccolors; - } - } - } - } - return result; - } - case 32: { - unsigned height = FreeImage_GetHeight(dib); - unsigned width = FreeImage_GetWidth(dib); - RGBQUAD *a, *b; - for (unsigned y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - for (unsigned x = 0; x < width; x++, bits += 4) { - for (unsigned j = 0; j < count; j++) { - a = srccolors; - b = dstcolors; - for (int i = (swap ? 0 : 1); i < 2; i++) { - if ((bits[FI_RGBA_BLUE] == a[j].rgbBlue) &&(bits[FI_RGBA_GREEN] == a[j].rgbGreen) &&(bits[FI_RGBA_RED] == a[j].rgbRed) - &&((ignore_alpha) || (bits[FI_RGBA_ALPHA] == a[j].rgbReserved))) { - bits[FI_RGBA_BLUE] = b[j].rgbBlue; - bits[FI_RGBA_GREEN] = b[j].rgbGreen; - bits[FI_RGBA_RED] = b[j].rgbRed; - if (!ignore_alpha) { - bits[FI_RGBA_ALPHA] = b[j].rgbReserved; - } - result++; - j = count; - break; - } - a = dstcolors; - b = srccolors; - } - } - } - } - return result; - } - default: { - return 0; - } - } -} - -/** @brief Swaps two specified colors on a 1-, 4- or 8-bit palletized - or a 16-, 24- or 32-bit high color image. - - This function swaps the two specified colors color_a and color_b - on a palletized or high color image. For high color images, the actual image - data will be modified whereas, for palletized images only the palette will be - changed.
- - Note, that this behaviour is different from what FreeImage_SwapPaletteIndices() - does, which modifies the actual image data on palletized images.
- - This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:
- return FreeImage_ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, TRUE); - - @param dib Input/output image to be processed. - @param color_a On of the two colors to be swapped. - @param color_b The other of the two colors to be swapped. - @param ignore_alpha If TRUE, 32-bit images and colors are treated as 24-bit. - @return Returns the total number of pixels changed. - */ -unsigned DLL_CALLCONV -FreeImage_SwapColors(FIBITMAP *dib, RGBQUAD *color_a, RGBQUAD *color_b, BOOL ignore_alpha) { - return FreeImage_ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, TRUE); -} - -/** @brief Applies palette index mapping for one or several indices on a 1-, 4- - or 8-bit palletized image. - - This function maps up to count palette indices specified in - srcindices to these specified in dstindices. Thereby, index - srcindices[N], if present in the image, will be replaced by index - dstindices[N]. If parameter swap is TRUE, additionally all indices - specified in dstindices are also mapped to these specified in - srcindices.
- - The function returns the number of pixels changed or zero, if no pixels were - changed. - - Both arrays srcindices and dstindices are assumed not to hold less - than count indices.
- - Note, that this behaviour is different from what FreeImage_ApplyColorMapping() - does, which modifies the actual image data on palletized images. - - @param dib Input/output image to be processed. - @param srcindices Array of palette indices to be used as the mapping source. - @param dstindices Array of palette indices to be used as the mapping destination. - @param count The number of palette indices to be mapped. This is the size of both - srcindices and dstindices. - @param swap If TRUE, source and destination palette indices are swapped, that is, - each destination index is also mapped to the corresponding source index. - @return Returns the total number of pixels changed. - */ -unsigned DLL_CALLCONV -FreeImage_ApplyPaletteIndexMapping(FIBITMAP *dib, BYTE *srcindices, BYTE *dstindices, unsigned count, BOOL swap) { - unsigned result = 0; - - if (!FreeImage_HasPixels(dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { - return 0; - } - - // validate parameters - if ((!srcindices) || (!dstindices)|| (count < 1)) { - return 0; - } - - unsigned height = FreeImage_GetHeight(dib); - unsigned width = FreeImage_GetLine(dib); - BYTE *a, *b; - - int bpp = FreeImage_GetBPP(dib); - switch (bpp) { - case 1: { - - return result; - } - case 4: { - int skip_last = (FreeImage_GetWidth(dib) & 0x01); - unsigned max_x = width - 1; - for (unsigned y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - for (unsigned x = 0; x < width; x++) { - int start = ((skip_last) && (x == max_x)) ? 1 : 0; - for (int cn = start; cn < 2; cn++) { - for (unsigned j = 0; j < count; j++) { - a = srcindices; - b = dstindices; - for (int i = ((swap) ? 0 : 1); i < 2; i++) { - if (GET_NIBBLE(cn, bits[x]) == (a[j] & 0x0F)) { - SET_NIBBLE(cn, bits[x], b[j]); - result++; - j = count; - break; - } - a = dstindices; - b = srcindices; - } - } - } - } - } - return result; - } - case 8: { - for (unsigned y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - for (unsigned x = 0; x < width; x++) { - for (unsigned j = 0; j < count; j++) { - a = srcindices; - b = dstindices; - for (int i = ((swap) ? 0 : 1); i < 2; i++) { - if (bits[x] == a[j]) { - bits[x] = b[j]; - result++; - j = count; - break; - } - a = dstindices; - b = srcindices; - } - } - } - } - return result; - } - default: { - return 0; - } - } -} - -/** @brief Swaps two specified palette indices on a 1-, 4- or 8-bit palletized - image. - - This function swaps the two specified palette indices index_a and - index_b on a palletized image. Therefore, not the palette, but the - actual image data will be modified.
- - Note, that this behaviour is different from what FreeImage_SwapColors() does - on palletized images, which only swaps the colors in the palette.
- - This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:
- return FreeImage_ApplyPaletteIndexMapping(dib, index_a, index_b, 1, TRUE); - - @param dib Input/output image to be processed. - @param index_a On of the two palette indices to be swapped. - @param index_b The other of the two palette indices to be swapped. - @return Returns the total number of pixels changed. - */ -unsigned DLL_CALLCONV -FreeImage_SwapPaletteIndices(FIBITMAP *dib, BYTE *index_a, BYTE *index_b) { - return FreeImage_ApplyPaletteIndexMapping(dib, index_a, index_b, 1, TRUE); -} - diff --git a/plugins/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp b/plugins/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp deleted file mode 100644 index 753fdc736e..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/CopyPaste.cpp +++ /dev/null @@ -1,747 +0,0 @@ -// ========================================================== -// Copy / paste routines -// -// - Floris van den Berg (flvdberg@wxs.nl) -// - Alexander Dymerets (sashad@te.net.ua) -// - Hervé Drolon (drolon@infonie.fr) -// - Manfred Tausch (manfred.tausch@t-online.de) -// - Riley McNiff (rmcniff@marexgroup.com) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// Helpers -// ---------------------------------------------------------- - -///////////////////////////////////////////////////////////// -// Alpha blending / combine functions - -// ---------------------------------------------------------- -/// 1-bit -static BOOL Combine1(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); -/// 4-bit -static BOOL Combine4(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); -/// 8-bit -static BOOL Combine8(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); -/// 16-bit 555 -static BOOL Combine16_555(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); -/// 16-bit 565 -static BOOL Combine16_565(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); -/// 24-bit -static BOOL Combine24(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); -/// 32- bit -static BOOL Combine32(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha); -// ---------------------------------------------------------- - -// ---------------------------------------------------------- -// 1-bit -// ---------------------------------------------------------- - -static BOOL -Combine1(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { - BOOL value; - - // check the bit depth of src and dst images - if ((FreeImage_GetBPP(dst_dib) != 1) || (FreeImage_GetBPP(src_dib) != 1)) { - return FALSE; - } - - // check the size of src image - if ((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { - return FALSE; - } - - BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)); - BYTE *src_bits = FreeImage_GetBits(src_dib); - - // combine images - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - for(unsigned cols = 0; cols < FreeImage_GetWidth(src_dib); cols++) { - // get bit at (rows, cols) in src image - value = (src_bits[cols >> 3] & (0x80 >> (cols & 0x07))) != 0; - // set bit at (rows, x+cols) in dst image - value ? dst_bits[(x + cols) >> 3] |= (0x80 >> ((x + cols) & 0x7)) : dst_bits[(x + cols) >> 3] &= (0xFF7F >> ((x + cols) & 0x7)); - } - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - - return TRUE; -} - -// ---------------------------------------------------------- -// 4-bit -// ---------------------------------------------------------- - -static BOOL -Combine4(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { - - int swapTable[16]; - BOOL bOddStart, bOddEnd; - - // check the bit depth of src and dst images - if ((FreeImage_GetBPP(dst_dib) != 4) || (FreeImage_GetBPP(src_dib) != 4)) { - return FALSE; - } - - // check the size of src image - if ((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { - return FALSE; - } - - // get src and dst palettes - RGBQUAD *src_pal = FreeImage_GetPalette(src_dib); - RGBQUAD *dst_pal = FreeImage_GetPalette(dst_dib); - if (src_pal == NULL || dst_pal == NULL) { - return FALSE; - } - - // build a swap table for the closest color match from the source palette to the destination palette - - for (int i = 0; i < 16; i++) { - WORD min_diff = (WORD)-1; - - for (int j = 0; j < 16; j++) { - // calculates the color difference using a Manhattan distance - WORD abs_diff = (WORD)( - abs(src_pal[i].rgbBlue - dst_pal[j].rgbBlue) - + abs(src_pal[i].rgbGreen - dst_pal[j].rgbGreen) - + abs(src_pal[i].rgbRed - dst_pal[j].rgbRed) - ); - - if (abs_diff < min_diff) { - swapTable[i] = j; - min_diff = abs_diff; - if (abs_diff == 0) { - break; - } - } - } - } - - BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x >> 1); - BYTE *src_bits = FreeImage_GetBits(src_dib); - - // combine images - - // allocate space for our temporary row - unsigned src_line = FreeImage_GetLine(src_dib); - unsigned src_width = FreeImage_GetWidth(src_dib); - unsigned src_height = FreeImage_GetHeight(src_dib); - - BYTE *buffer = (BYTE *)malloc(src_line * sizeof(BYTE)); - if (buffer == NULL) { - return FALSE; - } - - bOddStart = (x & 0x01) ? TRUE : FALSE; - - if ((bOddStart && !(src_width & 0x01)) || (!bOddStart && (src_width & 0x01))) { - bOddEnd = TRUE; - } - else { - bOddEnd = FALSE; - } - - for(unsigned rows = 0; rows < src_height; rows++) { - memcpy(buffer, src_bits, src_line); - - // change the values in the temp row to be those from the swap table - - for (unsigned cols = 0; cols < src_line; cols++) { - buffer[cols] = (BYTE)((swapTable[HINIBBLE(buffer[cols]) >> 4] << 4) + swapTable[LOWNIBBLE(buffer[cols])]); - } - - if (bOddStart) { - buffer[0] = HINIBBLE(dst_bits[0]) + LOWNIBBLE(buffer[0]); - } - - if (bOddEnd) { - buffer[src_line - 1] = HINIBBLE(buffer[src_line - 1]) + LOWNIBBLE(dst_bits[src_line - 1]); - } - - memcpy(dst_bits, buffer, src_line); - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - - free(buffer); - - return TRUE; - -} - -// ---------------------------------------------------------- -// 8-bit -// ---------------------------------------------------------- - -static BOOL -Combine8(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { - // check the bit depth of src and dst images - if ((FreeImage_GetBPP(dst_dib) != 8) || (FreeImage_GetBPP(src_dib) != 8)) { - return FALSE; - } - - // check the size of src image - if ((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { - return FALSE; - } - - BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x); - BYTE *src_bits = FreeImage_GetBits(src_dib); - - if(alpha > 255) { - // combine images - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } else { - // alpha blend images - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - for (unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) { - dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8); - } - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } - - return TRUE; -} - -// ---------------------------------------------------------- -// 16-bit -// ---------------------------------------------------------- - -static BOOL -Combine16_555(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { - // check the bit depth of src and dst images - if ((FreeImage_GetBPP(dst_dib) != 16) || (FreeImage_GetBPP(src_dib) != 16)) { - return FALSE; - } - - // check the size of src image - if ((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { - return FALSE; - } - - BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 2); - BYTE *src_bits = FreeImage_GetBits(src_dib); - - if (alpha > 255) { - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } else { - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols += 2) { - RGBTRIPLE color_s; - RGBTRIPLE color_t; - - WORD *tmp1 = (WORD *)&dst_bits[cols]; - WORD *tmp2 = (WORD *)&src_bits[cols]; - - // convert 16-bit colors to 24-bit - - color_s.rgbtRed = (BYTE)(((*tmp1 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) << 3); - color_s.rgbtGreen = (BYTE)(((*tmp1 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) << 3); - color_s.rgbtBlue = (BYTE)(((*tmp1 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) << 3); - - color_t.rgbtRed = (BYTE)(((*tmp2 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) << 3); - color_t.rgbtGreen = (BYTE)(((*tmp2 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) << 3); - color_t.rgbtBlue = (BYTE)(((*tmp2 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) << 3); - - // alpha blend - - color_s.rgbtRed = (BYTE)(((color_t.rgbtRed - color_s.rgbtRed) * alpha + (color_s.rgbtRed << 8)) >> 8); - color_s.rgbtGreen = (BYTE)(((color_t.rgbtGreen - color_s.rgbtGreen) * alpha + (color_s.rgbtGreen << 8)) >> 8); - color_s.rgbtBlue = (BYTE)(((color_t.rgbtBlue - color_s.rgbtBlue) * alpha + (color_s.rgbtBlue << 8)) >> 8); - - // convert 24-bit color back to 16-bit - - *tmp1 = RGB555(color_s.rgbtRed, color_s.rgbtGreen, color_s.rgbtBlue); - } - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } - - return TRUE; -} - -static BOOL -Combine16_565(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { - // check the bit depth of src and dst images - if ((FreeImage_GetBPP(dst_dib) != 16) || (FreeImage_GetBPP(src_dib) != 16)) { - return FALSE; - } - - // check the size of src image - if ((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { - return FALSE; - } - - BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 2); - BYTE *src_bits = FreeImage_GetBits(src_dib); - - if (alpha > 255) { - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } else { - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols += 2) { - RGBTRIPLE color_s; - RGBTRIPLE color_t; - - WORD *tmp1 = (WORD *)&dst_bits[cols]; - WORD *tmp2 = (WORD *)&src_bits[cols]; - - // convert 16-bit colors to 24-bit - - color_s.rgbtRed = (BYTE)(((*tmp1 & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) << 3); - color_s.rgbtGreen = (BYTE)(((*tmp1 & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) << 2); - color_s.rgbtBlue = (BYTE)(((*tmp1 & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) << 3); - - color_t.rgbtRed = (BYTE)(((*tmp2 & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) << 3); - color_t.rgbtGreen = (BYTE)(((*tmp2 & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) << 2); - color_t.rgbtBlue = (BYTE)(((*tmp2 & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) << 3); - - // alpha blend - - color_s.rgbtRed = (BYTE)(((color_t.rgbtRed - color_s.rgbtRed) * alpha + (color_s.rgbtRed << 8)) >> 8); - color_s.rgbtGreen = (BYTE)(((color_t.rgbtGreen - color_s.rgbtGreen) * alpha + (color_s.rgbtGreen << 8)) >> 8); - color_s.rgbtBlue = (BYTE)(((color_t.rgbtBlue - color_s.rgbtBlue) * alpha + (color_s.rgbtBlue << 8)) >> 8); - - // convert 24-bit color back to 16-bit - - *tmp1 = RGB565(color_s.rgbtRed, color_s.rgbtGreen, color_s.rgbtBlue); - } - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } - - return TRUE; -} - -// ---------------------------------------------------------- -// 24-bit -// ---------------------------------------------------------- - -static BOOL -Combine24(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { - // check the bit depth of src and dst images - if ((FreeImage_GetBPP(dst_dib) != 24) || (FreeImage_GetBPP(src_dib) != 24)) { - return FALSE; - } - - // check the size of src image - if ((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { - return FALSE; - } - - BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 3); - BYTE *src_bits = FreeImage_GetBits(src_dib); - - if(alpha > 255) { - // combine images - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } else { - // alpha blend images - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - for (unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) { - dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8); - } - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } - - return TRUE; -} - -// ---------------------------------------------------------- -// 32-bit -// ---------------------------------------------------------- - -static BOOL -Combine32(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) { - // check the bit depth of src and dst images - if ((FreeImage_GetBPP(dst_dib) != 32) || (FreeImage_GetBPP(src_dib) != 32)) { - return FALSE; - } - - // check the size of src image - if ((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) { - return FALSE; - } - - BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 4); - BYTE *src_bits = FreeImage_GetBits(src_dib); - - if (alpha > 255) { - // combine images - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib)); - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } else { - // alpha blend images - for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) { - for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) { - dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8); - } - - dst_bits += FreeImage_GetPitch(dst_dib); - src_bits += FreeImage_GetPitch(src_dib); - } - } - - return TRUE; -} - -// ---------------------------------------------------------- -// Any type other than FIBITMAP -// ---------------------------------------------------------- - -static BOOL -CombineSameType(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y) { - // check the bit depth of src and dst images - if(FreeImage_GetImageType(dst_dib) != FreeImage_GetImageType(src_dib)) { - return FALSE; - } - - unsigned src_width = FreeImage_GetWidth(src_dib); - unsigned src_height = FreeImage_GetHeight(src_dib); - unsigned src_pitch = FreeImage_GetPitch(src_dib); - unsigned src_line = FreeImage_GetLine(src_dib); - unsigned dst_width = FreeImage_GetWidth(dst_dib); - unsigned dst_height = FreeImage_GetHeight(dst_dib); - unsigned dst_pitch = FreeImage_GetPitch(dst_dib); - - // check the size of src image - if ((x + src_width > dst_width) || (y + src_height > dst_height)) { - return FALSE; - } - - BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((dst_height - src_height - y) * dst_pitch) + (x * (src_line / src_width)); - BYTE *src_bits = FreeImage_GetBits(src_dib); - - // combine images - for(unsigned rows = 0; rows < src_height; rows++) { - memcpy(dst_bits, src_bits, src_line); - - dst_bits += dst_pitch; - src_bits += src_pitch; - } - - return TRUE; -} - -// ---------------------------------------------------------- -// FreeImage interface -// ---------------------------------------------------------- - -/** -Copy a sub part of the current image and returns it as a FIBITMAP*. -Works with any bitmap type. -@param left Specifies the left position of the cropped rectangle. -@param top Specifies the top position of the cropped rectangle. -@param right Specifies the right position of the cropped rectangle. -@param bottom Specifies the bottom position of the cropped rectangle. -@return Returns the subimage if successful, NULL otherwise. -*/ -FIBITMAP * DLL_CALLCONV -FreeImage_Copy(FIBITMAP *src, int left, int top, int right, int bottom) { - - if (!FreeImage_HasPixels(src)) - return NULL; - - // normalize the rectangle - if(right < left) { - INPLACESWAP(left, right); - } - if(bottom < top) { - INPLACESWAP(top, bottom); - } - // check the size of the sub image - int src_width = FreeImage_GetWidth(src); - int src_height = FreeImage_GetHeight(src); - if ((left < 0) || (right > src_width) || (top < 0) || (bottom > src_height)) { - return NULL; - } - - // allocate the sub image - unsigned bpp = FreeImage_GetBPP(src); - int dst_width = (right - left); - int dst_height = (bottom - top); - - FIBITMAP *dst = - FreeImage_AllocateT(FreeImage_GetImageType(src), - dst_width, - dst_height, - bpp, - FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src)); - - if(NULL == dst) return NULL; - - // get the dimensions - int dst_line = FreeImage_GetLine(dst); - int dst_pitch = FreeImage_GetPitch(dst); - int src_pitch = FreeImage_GetPitch(src); - - // get the pointers to the bits and such - - BYTE *src_bits = FreeImage_GetScanLine(src, src_height - top - dst_height); - switch(bpp) { - case 1: - // point to x = 0 - break; - - case 4: - // point to x = 0 - break; - - default: - { - // calculate the number of bytes per pixel - unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - // point to x = left - src_bits += left * bytespp; - } - break; - } - - // point to x = 0 - BYTE *dst_bits = FreeImage_GetBits(dst); - - // copy the palette - - memcpy(FreeImage_GetPalette(dst), FreeImage_GetPalette(src), FreeImage_GetColorsUsed(src) * sizeof(RGBQUAD)); - - // copy the bits - if(bpp == 1) { - BOOL value; - unsigned y_src, y_dst; - - for(int y = 0; y < dst_height; y++) { - y_src = y * src_pitch; - y_dst = y * dst_pitch; - for(int x = 0; x < dst_width; x++) { - // get bit at (y, x) in src image - value = (src_bits[y_src + ((left+x) >> 3)] & (0x80 >> ((left+x) & 0x07))) != 0; - // set bit at (y, x) in dst image - value ? dst_bits[y_dst + (x >> 3)] |= (0x80 >> (x & 0x7)) : dst_bits[y_dst + (x >> 3)] &= (0xff7f >> (x & 0x7)); - } - } - } - - else if(bpp == 4) { - BYTE shift, value; - unsigned y_src, y_dst; - - for(int y = 0; y < dst_height; y++) { - y_src = y * src_pitch; - y_dst = y * dst_pitch; - for(int x = 0; x < dst_width; x++) { - // get nibble at (y, x) in src image - shift = (BYTE)((1 - (left+x) % 2) << 2); - value = (src_bits[y_src + ((left+x) >> 1)] & (0x0F << shift)) >> shift; - // set nibble at (y, x) in dst image - shift = (BYTE)((1 - x % 2) << 2); - dst_bits[y_dst + (x >> 1)] &= ~(0x0F << shift); - dst_bits[y_dst + (x >> 1)] |= ((value & 0x0F) << shift); - } - } - } - - else if(bpp >= 8) { - for(int y = 0; y < dst_height; y++) { - memcpy(dst_bits + (y * dst_pitch), src_bits + (y * src_pitch), dst_line); - } - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - // copy transparency table - FreeImage_SetTransparencyTable(dst, FreeImage_GetTransparencyTable(src), FreeImage_GetTransparencyCount(src)); - - // copy background color - RGBQUAD bkcolor; - if ( FreeImage_GetBackgroundColor(src, &bkcolor)) { - FreeImage_SetBackgroundColor(dst, &bkcolor); - } - - // clone resolution - FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src)); - FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src)); - - // clone ICC profile - FIICCPROFILE *src_profile = FreeImage_GetICCProfile(src); - FIICCPROFILE *dst_profile = FreeImage_CreateICCProfile(dst, src_profile->data, src_profile->size); - dst_profile->flags = src_profile->flags; - - return dst; -} - -/** -Alpha blend or combine a sub part image with the current image. -The bit depth of dst bitmap must be greater than or equal to the bit depth of src. -Upper promotion of src is done internally. Supported bit depth equals to 1, 4, 8, 16, 24 or 32. -@param src Source subimage -@param left Specifies the left position of the sub image. -@param top Specifies the top position of the sub image. -@param alpha Alpha blend factor. The source and destination images are alpha blended if -alpha = 0..255. If alpha > 255, then the source image is combined to the destination image. -@return Returns TRUE if successful, FALSE otherwise. -*/ -BOOL DLL_CALLCONV -FreeImage_Paste(FIBITMAP *dst, FIBITMAP *src, int left, int top, int alpha) { - BOOL bResult = FALSE; - - if (!FreeImage_HasPixels(src) || !FreeImage_HasPixels(dst)) return FALSE; - - // check the size of src image - if ((left < 0) || (top < 0)) { - return FALSE; - } - if ((left + FreeImage_GetWidth(src) > FreeImage_GetWidth(dst)) || (top + FreeImage_GetHeight(src) > FreeImage_GetHeight(dst))) { - return FALSE; - } - - // check data type - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dst); - if(image_type != FreeImage_GetImageType(src)) { - // no conversion between data type is done - return FALSE; - } - - if(image_type == FIT_BITMAP) { - FIBITMAP *clone = NULL; - - // check the bit depth of src and dst images - unsigned bpp_src = FreeImage_GetBPP(src); - unsigned bpp_dst = FreeImage_GetBPP(dst); - BOOL isRGB565 = FALSE; - - if ((FreeImage_GetRedMask(dst) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dst) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dst) == FI16_565_BLUE_MASK)) { - isRGB565 = TRUE; - } else { - // includes case where all the masks are 0 - isRGB565 = FALSE; - } - - // perform promotion if needed - if(bpp_dst == bpp_src) { - clone = src; - } else if(bpp_dst > bpp_src) { - // perform promotion - switch(bpp_dst) { - case 4: - clone = FreeImage_ConvertTo4Bits(src); - break; - case 8: - clone = FreeImage_ConvertTo8Bits(src); - break; - case 16: - if (isRGB565) { - clone = FreeImage_ConvertTo16Bits565(src); - } else { - // includes case where all the masks are 0 - clone = FreeImage_ConvertTo16Bits555(src); - } - break; - case 24: - clone = FreeImage_ConvertTo24Bits(src); - break; - case 32: - clone = FreeImage_ConvertTo32Bits(src); - break; - default: - return FALSE; - } - } else { - return FALSE; - } - - if (!clone) return FALSE; - - // paste src to dst - switch(FreeImage_GetBPP(dst)) { - case 1: - bResult = Combine1(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); - break; - case 4: - bResult = Combine4(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); - break; - case 8: - bResult = Combine8(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); - break; - case 16: - if (isRGB565) { - bResult = Combine16_565(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); - } else { - // includes case where all the masks are 0 - bResult = Combine16_555(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); - } - break; - case 24: - bResult = Combine24(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); - break; - case 32: - bResult = Combine32(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha); - break; - } - - if(clone != src) - FreeImage_Unload(clone); - - } - else { // any type other than FITBITMAP - bResult = CombineSameType(dst, src, (unsigned)left, (unsigned)top); - } - - return bResult; -} - - diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp deleted file mode 100644 index 3e4807042d..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Display.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// ========================================================== -// Display routines -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - - -/** -@brief Composite a foreground image against a background color or a background image. - -The equation for computing a composited sample value is:
-output = alpha * foreground + (1-alpha) * background
-where alpha and the input and output sample values are expressed as fractions in the range 0 to 1. -For colour images, the computation is done separately for R, G, and B samples. - -@param fg Foreground image -@param useFileBkg If TRUE and a file background is present, use it as the background color -@param appBkColor If not equal to NULL, and useFileBkg is FALSE, use this color as the background color -@param bg If not equal to NULL and useFileBkg is FALSE and appBkColor is NULL, use this as the background image -@return Returns the composite image if successful, returns NULL otherwise -@see FreeImage_IsTransparent, FreeImage_HasBackgroundColor -*/ -FIBITMAP * DLL_CALLCONV -FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) { - if (!FreeImage_HasPixels(fg)) return NULL; - - int width = FreeImage_GetWidth(fg); - int height = FreeImage_GetHeight(fg); - int bpp = FreeImage_GetBPP(fg); - - if ((bpp != 8) && (bpp != 32)) - return NULL; - - if(bg) { - int bg_width = FreeImage_GetWidth(bg); - int bg_height = FreeImage_GetHeight(bg); - int bg_bpp = FreeImage_GetBPP(bg); - if ((bg_width != width) || (bg_height != height) || (bg_bpp != 24)) - return NULL; - } - - int bytespp = (bpp == 8) ? 1 : 4; - - - int x, y, c; - BYTE alpha = 0, not_alpha; - BYTE index; - RGBQUAD fgc; // foreground color - RGBQUAD bkc; // background color - - memset(&fgc, 0, sizeof(RGBQUAD)); - memset(&bkc, 0, sizeof(RGBQUAD)); - - // allocate the composite image - FIBITMAP *composite = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); - if (!composite) return NULL; - - // get the palette - RGBQUAD *pal = FreeImage_GetPalette(fg); - - // retrieve the alpha table from the foreground image - BOOL bIsTransparent = FreeImage_IsTransparent(fg); - BYTE *trns = FreeImage_GetTransparencyTable(fg); - - // retrieve the background color from the foreground image - BOOL bHasBkColor = FALSE; - - if(useFileBkg && FreeImage_HasBackgroundColor(fg)) { - FreeImage_GetBackgroundColor(fg, &bkc); - bHasBkColor = TRUE; - } else { - // no file background color - // use application background color ? - if(appBkColor) { - memcpy(&bkc, appBkColor, sizeof(RGBQUAD)); - bHasBkColor = TRUE; - } - // use background image ? - else if(bg) { - bHasBkColor = FALSE; - } - } - - for(y = 0; y < height; y++) { - // foreground - BYTE *fg_bits = FreeImage_GetScanLine(fg, y); - // background - BYTE *bg_bits = FreeImage_GetScanLine(bg, y); - // composite image - BYTE *cp_bits = FreeImage_GetScanLine(composite, y); - - for(x = 0; x < width; x++) { - - // foreground color + alpha - - if(bpp == 8) { - // get the foreground color - index = fg_bits[0]; - memcpy(&fgc, &pal[index], sizeof(RGBQUAD)); - // get the alpha - if(bIsTransparent) { - alpha = trns[index]; - } else { - alpha = 255; - } - } - else if(bpp == 32) { - // get the foreground color - fgc.rgbBlue = fg_bits[FI_RGBA_BLUE]; - fgc.rgbGreen = fg_bits[FI_RGBA_GREEN]; - fgc.rgbRed = fg_bits[FI_RGBA_RED]; - // get the alpha - alpha = fg_bits[FI_RGBA_ALPHA]; - } - - // background color - - if (!bHasBkColor) { - if(bg) { - // get the background color from the background image - bkc.rgbBlue = bg_bits[FI_RGBA_BLUE]; - bkc.rgbGreen = bg_bits[FI_RGBA_GREEN]; - bkc.rgbRed = bg_bits[FI_RGBA_RED]; - } - else { - // use a checkerboard pattern - c = (((y & 0x8) == 0) ^ ((x & 0x8) == 0)) * 192; - c = c ? c : 255; - bkc.rgbBlue = (BYTE)c; - bkc.rgbGreen = (BYTE)c; - bkc.rgbRed = (BYTE)c; - } - } - - // composition - - if(alpha == 0) { - // output = background - cp_bits[FI_RGBA_BLUE] = bkc.rgbBlue; - cp_bits[FI_RGBA_GREEN] = bkc.rgbGreen; - cp_bits[FI_RGBA_RED] = bkc.rgbRed; - } - else if(alpha == 255) { - // output = foreground - cp_bits[FI_RGBA_BLUE] = fgc.rgbBlue; - cp_bits[FI_RGBA_GREEN] = fgc.rgbGreen; - cp_bits[FI_RGBA_RED] = fgc.rgbRed; - } - else { - // output = alpha * foreground + (1-alpha) * background - not_alpha = (BYTE)~alpha; - cp_bits[FI_RGBA_BLUE] = (BYTE)((alpha * (WORD)fgc.rgbBlue + not_alpha * (WORD)bkc.rgbBlue) >> 8); - cp_bits[FI_RGBA_GREEN] = (BYTE)((alpha * (WORD)fgc.rgbGreen + not_alpha * (WORD)bkc.rgbGreen) >> 8); - cp_bits[FI_RGBA_RED] = (BYTE)((alpha * (WORD)fgc.rgbRed + not_alpha * (WORD)bkc.rgbRed) >> 8); - } - - fg_bits += bytespp; - bg_bits += 3; - cp_bits += 3; - } - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(composite, fg); - - return composite; -} - -/** -Pre-multiplies a 32-bit image's red-, green- and blue channels with it's alpha channel -for to be used with e.g. the Windows GDI function AlphaBlend(). -The transformation changes the red-, green- and blue channels according to the following equation: -channel(x, y) = channel(x, y) * alpha_channel(x, y) / 255 -@param dib Input/Output dib to be premultiplied -@return Returns TRUE on success, FALSE otherwise (e.g. when the bitdepth of the source dib cannot be handled). -*/ -BOOL DLL_CALLCONV -FreeImage_PreMultiplyWithAlpha(FIBITMAP *dib) { - if (!FreeImage_HasPixels(dib)) return FALSE; - - if ((FreeImage_GetBPP(dib) != 32) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) { - return FALSE; - } - - int width = FreeImage_GetWidth(dib); - int height = FreeImage_GetHeight(dib); - - for(int y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(dib, y); - for (int x = 0; x < width; x++, bits += 4) { - const BYTE alpha = bits[FI_RGBA_ALPHA]; - // slightly faster: care for two special cases - if(alpha == 0x00) { - // special case for alpha == 0x00 - // color * 0x00 / 0xFF = 0x00 - bits[FI_RGBA_BLUE] = 0x00; - bits[FI_RGBA_GREEN] = 0x00; - bits[FI_RGBA_RED] = 0x00; - } else if(alpha == 0xFF) { - // nothing to do for alpha == 0xFF - // color * 0xFF / 0xFF = color - continue; - } else { - bits[FI_RGBA_BLUE] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_BLUE] + 127) / 255 ); - bits[FI_RGBA_GREEN] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_GREEN] + 127) / 255 ); - bits[FI_RGBA_RED] = (BYTE)( (alpha * (WORD)bits[FI_RGBA_RED] + 127) / 255 ); - } - } - } - return TRUE; -} - diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Filters.h b/plugins/FreeImage/Source/FreeImageToolkit/Filters.h deleted file mode 100644 index 7a45c493f4..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Filters.h +++ /dev/null @@ -1,287 +0,0 @@ -// ========================================================== -// Upsampling / downsampling filters -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#ifndef _FILTERS_H_ -#define _FILTERS_H_ - -/** - CGenericFilter is a generic abstract filter class used to access to the filter library.
- Filters used in this library have been mainly taken from the following references :
-Main reference :
-Paul Heckbert, C code to zoom raster images up or down, with nice filtering. -UC Berkeley, August 1989. [online] http://www-2.cs.cmu.edu/afs/cs.cmu.edu/Web/People/ph/heckbert.html - -Heckbert references :
-
    -
  • Oppenheim A.V., Schafer R.W., Digital Signal Processing, Prentice-Hall, 1975 -
  • Hamming R.W., Digital Filters, Prentice-Hall, Englewood Cliffs, NJ, 1983 -
  • Pratt W.K., Digital Image Processing, John Wiley and Sons, 1978 -
  • Hou H.S., Andrews H.C., "Cubic Splines for Image Interpolation and Digital Filtering", -IEEE Trans. Acoustics, Speech, and Signal Proc., vol. ASSP-26, no. 6, pp. 508-517, Dec. 1978. -
- -*/ -class CGenericFilter -{ -protected: - - #define FILTER_PI double (3.1415926535897932384626433832795) - #define FILTER_2PI double (2.0 * 3.1415926535897932384626433832795) - #define FILTER_4PI double (4.0 * 3.1415926535897932384626433832795) - - /// Filter support - double m_dWidth; - -public: - - /// Constructor - CGenericFilter (double dWidth) : m_dWidth (dWidth) {} - /// Destructor - virtual ~CGenericFilter() {} - - /// Returns the filter support - double GetWidth() { return m_dWidth; } - /// Change the filter suport - void SetWidth (double dWidth) { m_dWidth = dWidth; } - - /// Returns F(dVal) where F is the filter's impulse response - virtual double Filter (double dVal) = 0; -}; - -// ----------------------------------------------------------------------------------- -// Filters library -// All filters are centered on 0 -// ----------------------------------------------------------------------------------- - -/** - Box filter
- Box, pulse, Fourier window, 1st order (constant) b-spline.

- - Reference :
- Glassner A.S., Principles of digital image synthesis. Morgan Kaufmann Publishers, Inc, San Francisco, Vol. 2, 1995 -*/ -class CBoxFilter : public CGenericFilter -{ -public: - /** - Constructor
- Default fixed width = 0.5 - */ - CBoxFilter() : CGenericFilter(0.5) {} - virtual ~CBoxFilter() {} - - double Filter (double dVal) { return (fabs(dVal) <= m_dWidth ? 1.0 : 0.0); } -}; - -/** Bilinear filter -*/ -class CBilinearFilter : public CGenericFilter -{ -public: - - CBilinearFilter () : CGenericFilter(1) {} - virtual ~CBilinearFilter() {} - - double Filter (double dVal) { - dVal = fabs(dVal); - return (dVal < m_dWidth ? m_dWidth - dVal : 0.0); - } -}; - - -/** - Mitchell & Netravali's two-param cubic filter
- - The parameters b and c can be used to adjust the properties of the cubic. - They are sometimes referred to as "blurring" and "ringing" respectively. - The default is b = 1/3 and c = 1/3, which were the values recommended by - Mitchell and Netravali as yielding the most visually pleasing results in subjective tests of human beings. - Larger values of b and c can produce interesting op-art effects--for example, try b = 0 and c = -5.

- - Reference :
- Don P. Mitchell and Arun N. Netravali, Reconstruction filters in computer graphics. - In John Dill, editor, Computer Graphics (SIGGRAPH '88 Proceedings), Vol. 22, No. 4, August 1988, pp. 221-228. -*/ -class CBicubicFilter : public CGenericFilter -{ -protected: - // data for parameterized Mitchell filter - double p0, p2, p3; - double q0, q1, q2, q3; - -public: - /** - Constructor
- Default fixed width = 2 - @param b Filter parameter (default value is 1/3) - @param c Filter parameter (default value is 1/3) - */ - CBicubicFilter (double b = (1/(double)3), double c = (1/(double)3)) : CGenericFilter(2) { - p0 = (6 - 2*b) / 6; - p2 = (-18 + 12*b + 6*c) / 6; - p3 = (12 - 9*b - 6*c) / 6; - q0 = (8*b + 24*c) / 6; - q1 = (-12*b - 48*c) / 6; - q2 = (6*b + 30*c) / 6; - q3 = (-b - 6*c) / 6; - } - virtual ~CBicubicFilter() {} - - double Filter(double dVal) { - dVal = fabs(dVal); - if(dVal < 1) - return (p0 + dVal*dVal*(p2 + dVal*p3)); - if(dVal < 2) - return (q0 + dVal*(q1 + dVal*(q2 + dVal*q3))); - return 0; - } -}; - -/** - Catmull-Rom spline, Overhauser spline
- - When using CBicubicFilter filters, you have to set parameters b and c such that
- b + 2 * c = 1
- in order to use the numerically most accurate filter.
- This gives for b = 0 the maximum value for c = 0.5, which is the Catmull-Rom - spline and a good suggestion for sharpness.

- - - References :
-
    -
  • Mitchell Don P., Netravali Arun N., Reconstruction filters in computer graphics. - In John Dill, editor, Computer Graphics (SIGGRAPH '88 Proceedings), Vol. 22, No. 4, August 1988, pp. 221-228. -
  • Keys R.G., Cubic Convolution Interpolation for Digital Image Processing. - IEEE Trans. Acoustics, Speech, and Signal Processing, vol. 29, no. 6, pp. 1153-1160, Dec. 1981. -
- -*/ -class CCatmullRomFilter : public CGenericFilter -{ -public: - - /** - Constructor
- Default fixed width = 2 - */ - CCatmullRomFilter() : CGenericFilter(2) {} - virtual ~CCatmullRomFilter() {} - - double Filter(double dVal) { - if(dVal < -2) return 0; - if(dVal < -1) return (0.5*(4 + dVal*(8 + dVal*(5 + dVal)))); - if(dVal < 0) return (0.5*(2 + dVal*dVal*(-5 - 3*dVal))); - if(dVal < 1) return (0.5*(2 + dVal*dVal*(-5 + 3*dVal))); - if(dVal < 2) return (0.5*(4 + dVal*(-8 + dVal*(5 - dVal)))); - return 0; - } -}; - -/** - Lanczos-windowed sinc filter
- - Lanczos3 filter is an alternative to CBicubicFilter with high values of c about 0.6 ... 0.75 - which produces quite strong sharpening. It usually offers better quality (fewer artifacts) and a sharp image.

- -*/ -class CLanczos3Filter : public CGenericFilter -{ -public: - /** - Constructor
- Default fixed width = 3 - */ - CLanczos3Filter() : CGenericFilter(3) {} - virtual ~CLanczos3Filter() {} - - double Filter(double dVal) { - dVal = fabs(dVal); - if(dVal < m_dWidth) { - return (sinc(dVal) * sinc(dVal / m_dWidth)); - } - return 0; - } - -private: - double sinc(double value) { - if(value != 0) { - value *= FILTER_PI; - return (sin(value) / value); - } - return 1; - } -}; - -/** - 4th order (cubic) b-spline
- -*/ -class CBSplineFilter : public CGenericFilter -{ -public: - - /** - Constructor
- Default fixed width = 2 - */ - CBSplineFilter() : CGenericFilter(2) {} - virtual ~CBSplineFilter() {} - - double Filter(double dVal) { - - dVal = fabs(dVal); - if(dVal < 1) return (4 + dVal*dVal*(-6 + 3*dVal)) / 6; - if(dVal < 2) { - double t = 2 - dVal; - return (t*t*t / 6); - } - return 0; - } -}; - -// ----------------------------------------------------------------------------------- -// Window function library -// ----------------------------------------------------------------------------------- - -/** - Blackman window -*/ -class CBlackmanFilter : public CGenericFilter -{ -public: - /** - Constructor
- Default width = 0.5 - */ - CBlackmanFilter (double dWidth = double(0.5)) : CGenericFilter(dWidth) {} - virtual ~CBlackmanFilter() {} - - double Filter (double dVal) { - if(fabs (dVal) > m_dWidth) { - return 0; - } - double dN = 2 * m_dWidth + 1; - dVal /= (dN - 1); - return 0.42 + 0.5*cos(FILTER_2PI*dVal) + 0.08*cos(FILTER_4PI*dVal); - } -}; - -#endif // _FILTERS_H_ diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp deleted file mode 100644 index c7898a7813..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Flip.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// ========================================================== -// Flipping routines -// -// Design and implementation by -// - Floris van den Berg (flvdberg@wxs.nl) -// - Hervé Drolon (drolon@infonie.fr) -// - Jim Keir (jimkeir@users.sourceforge.net) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" - -/** -Flip the image horizontally along the vertical axis. -@param src Input image to be processed. -@return Returns TRUE if successful, FALSE otherwise. -*/ -BOOL DLL_CALLCONV -FreeImage_FlipHorizontal(FIBITMAP *src) { - if (!FreeImage_HasPixels(src)) return FALSE; - - unsigned line = FreeImage_GetLine(src); - unsigned width = FreeImage_GetWidth(src); - unsigned height = FreeImage_GetHeight(src); - - unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - // copy between aligned memories - BYTE *new_bits = (BYTE*)FreeImage_Aligned_Malloc(line * sizeof(BYTE), FIBITMAP_ALIGNMENT); - if (!new_bits) return FALSE; - - // mirror the buffer - - for (unsigned y = 0; y < height; y++) { - BYTE *bits = FreeImage_GetScanLine(src, y); - memcpy(new_bits, bits, line); - - switch (FreeImage_GetBPP(src)) { - case 1 : - { - for(unsigned x = 0; x < width; x++) { - // get pixel at (x, y) - BOOL value = (new_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0; - // set pixel at (new_x, y) - unsigned new_x = width - 1 - x; - value ? bits[new_x >> 3] |= (0x80 >> (new_x & 0x7)) : bits[new_x >> 3] &= (0xff7f >> (new_x & 0x7)); - } - } - break; - - case 4 : - { - for(unsigned c = 0; c < line; c++) { - bits[c] = new_bits[line - c - 1]; - - BYTE nibble = (bits[c] & 0xF0) >> 4; - - bits[c] = bits[c] << 4; - bits[c] |= nibble; - } - } - break; - - case 8: - { - BYTE *dst_data = (BYTE*) bits; - BYTE *src_data = (BYTE*) (new_bits + line - bytespp); - for(unsigned c = 0; c < width; c++) { - *dst_data++ = *src_data--; - } - } - break; - - case 16: - { - WORD *dst_data = (WORD*) bits; - WORD *src_data = (WORD*) (new_bits + line - bytespp); - for(unsigned c = 0; c < width; c++) { - *dst_data++ = *src_data--; - } - } - break; - - case 24 : - case 32 : - case 48: - case 64: - case 96: - case 128: - { - BYTE *dst_data = (BYTE*) bits; - BYTE *src_data = (BYTE*) (new_bits + line - bytespp); - for(unsigned c = 0; c < width; c++) { - for(unsigned k = 0; k < bytespp; k++) { - *dst_data++ = src_data[k]; - } - src_data -= bytespp; - } - } - break; - - } - } - - FreeImage_Aligned_Free(new_bits); - - return TRUE; -} - - -/** -Flip the image vertically along the horizontal axis. -@param src Input image to be processed. -@return Returns TRUE if successful, FALSE otherwise. -*/ - -BOOL DLL_CALLCONV -FreeImage_FlipVertical(FIBITMAP *src) { - BYTE *From, *Mid; - - if (!FreeImage_HasPixels(src)) return FALSE; - - // swap the buffer - - unsigned pitch = FreeImage_GetPitch(src); - unsigned height = FreeImage_GetHeight(src); - - // copy between aligned memories - Mid = (BYTE*)FreeImage_Aligned_Malloc(pitch * sizeof(BYTE), FIBITMAP_ALIGNMENT); - if (!Mid) return FALSE; - - From = FreeImage_GetBits(src); - - unsigned line_s = 0; - unsigned line_t = (height-1) * pitch; - - for(unsigned y = 0; y < height/2; y++) { - - memcpy(Mid, From + line_s, pitch); - memcpy(From + line_s, From + line_t, pitch); - memcpy(From + line_t, Mid, pitch); - - line_s += pitch; - line_t -= pitch; - - } - - FreeImage_Aligned_Free(Mid); - - return TRUE; -} - diff --git a/plugins/FreeImage/Source/FreeImageToolkit/JPEGTransform.cpp b/plugins/FreeImage/Source/FreeImageToolkit/JPEGTransform.cpp deleted file mode 100644 index 2d7399dcb2..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/JPEGTransform.cpp +++ /dev/null @@ -1,410 +0,0 @@ -// ========================================================== -// JPEG lossless transformations -// -// Design and implementation by -// - Petr Pytelka (pyta@lightcomp.com) -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -extern "C" { -#define XMD_H -#undef FAR -#include - -#include "../LibJPEG/jinclude.h" -#include "../LibJPEG/jpeglib.h" -#include "../LibJPEG/jerror.h" -#include "../LibJPEG/transupp.h" -} - -#include "FreeImage.h" -#include "Utilities.h" - -// ---------------------------------------------------------- -// IO filename handling -// ---------------------------------------------------------- - -typedef struct tagFilenameIO { - const char *src_file; - const char *dst_file; - const wchar_t *wsrc_file; - const wchar_t *wdst_file; -} FilenameIO; - -// ---------------------------------------------------------- -// Error handling -// ---------------------------------------------------------- - -/** - Receives control for a fatal error. Information sufficient to - generate the error message has been stored in cinfo->err; call - output_message to display it. Control must NOT return to the caller; - generally this routine will exit() or longjmp() somewhere. -*/ -METHODDEF(void) -ls_jpeg_error_exit (j_common_ptr cinfo) { - // always display the message - (*cinfo->err->output_message)(cinfo); - - // allow JPEG with a premature end of file - if ((cinfo)->err->msg_parm.i[0] != 13) { - - // let the memory manager delete any temp files before we die - jpeg_destroy(cinfo); - - throw FIF_JPEG; - } -} - -/** - Actual output of any JPEG message. Note that this method does not know - how to generate a message, only where to send it. -*/ -METHODDEF(void) -ls_jpeg_output_message (j_common_ptr cinfo) { - char buffer[JMSG_LENGTH_MAX]; - - // create the message - (*cinfo->err->format_message)(cinfo, buffer); - // send it to user's message proc - FreeImage_OutputMessageProc(FIF_JPEG, buffer); -} - -// ---------------------------------------------------------- -// Main program -// ---------------------------------------------------------- - -static BOOL -LosslessTransform(const FilenameIO *filenameIO, FREE_IMAGE_JPEG_OPERATION operation, const char *crop, BOOL perfect) { - // We assume all-in-memory processing and can therefore use only a - // single file pointer for sequential input and output operation - FILE *fp = NULL; - - // check for UNICODE filenames - previous structure filling was done before - bool bUseUnicode = filenameIO && filenameIO->wsrc_file && filenameIO->wdst_file; - - // Set up the jpeglib structures - jpeg_decompress_struct srcinfo; - jpeg_compress_struct dstinfo; - jpeg_error_mgr jsrcerr, jdsterr; - jvirt_barray_ptr *src_coef_arrays = NULL; - jvirt_barray_ptr *dst_coef_arrays = NULL; - // Support for copying optional markers from source to destination file - JCOPY_OPTION copyoption; - // Image transformation options - jpeg_transform_info transfoptions; - - // Initialize structures - memset(&srcinfo, 0, sizeof(srcinfo)); - memset(&jsrcerr, 0, sizeof(jsrcerr)); - memset(&jdsterr, 0, sizeof(jdsterr)); - memset(&dstinfo, 0, sizeof(dstinfo)); - memset(&transfoptions, 0, sizeof(transfoptions)); - - // Copy all extra markers from source file - copyoption = JCOPYOPT_ALL; - - // Set up default JPEG parameters - transfoptions.force_grayscale = FALSE; - transfoptions.crop = FALSE; - - // Select the transform option - switch(operation) { - case FIJPEG_OP_FLIP_H: // horizontal flip - transfoptions.transform = JXFORM_FLIP_H; - break; - case FIJPEG_OP_FLIP_V: // vertical flip - transfoptions.transform = JXFORM_FLIP_V; - break; - case FIJPEG_OP_TRANSPOSE: // transpose across UL-to-LR axis - transfoptions.transform = JXFORM_TRANSPOSE; - break; - case FIJPEG_OP_TRANSVERSE: // transpose across UR-to-LL axis - transfoptions.transform = JXFORM_TRANSVERSE; - break; - case FIJPEG_OP_ROTATE_90: // 90-degree clockwise rotation - transfoptions.transform = JXFORM_ROT_90; - break; - case FIJPEG_OP_ROTATE_180: // 180-degree rotation - transfoptions.transform = JXFORM_ROT_180; - break; - case FIJPEG_OP_ROTATE_270: // 270-degree clockwise (or 90 ccw) - transfoptions.transform = JXFORM_ROT_270; - break; - default: - case FIJPEG_OP_NONE: // no transformation - transfoptions.transform = JXFORM_NONE; - break; - } - // (perfect == TRUE) ==> fail if there is non-transformable edge blocks - transfoptions.perfect = (perfect == TRUE) ? TRUE : FALSE; - // Drop non-transformable edge blocks: trim off any partial edge MCUs that the transform can't handle. - transfoptions.trim = TRUE; - - try { - - // Initialize the JPEG decompression object with default error handling - srcinfo.err = jpeg_std_error(&jsrcerr); - srcinfo.err->error_exit = ls_jpeg_error_exit; - srcinfo.err->output_message = ls_jpeg_output_message; - jpeg_create_decompress(&srcinfo); - - // Initialize the JPEG compression object with default error handling - dstinfo.err = jpeg_std_error(&jdsterr); - dstinfo.err->error_exit = ls_jpeg_error_exit; - dstinfo.err->output_message = ls_jpeg_output_message; - jpeg_create_compress(&dstinfo); - - // crop option - if(crop != NULL) { - if (!jtransform_parse_crop_spec(&transfoptions, crop)) { - FreeImage_OutputMessageProc(FIF_JPEG, "Bogus crop argument %s", crop); - throw(1); - } - } - - // Open the input file - if(bUseUnicode) { -#ifdef _WIN32 - if ((fp = _wfopen(filenameIO->wsrc_file, L"rb")) == NULL) { - FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open input file for reading"); - } -#else - fp = NULL; -#endif // _WIN32 - } else { - if ((fp = fopen(filenameIO->src_file, "rb")) == NULL) { - FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open %s for reading", filenameIO->src_file); - } - } - if(fp == NULL) { - jpeg_destroy_compress(&dstinfo); - jpeg_destroy_decompress(&srcinfo); - return FALSE; - } - - // Specify data source for decompression - jpeg_stdio_src(&srcinfo, fp); - - // Enable saving of extra markers that we want to copy - jcopy_markers_setup(&srcinfo, copyoption); - - // Read the file header - jpeg_read_header(&srcinfo, TRUE); - - // Any space needed by a transform option must be requested before - // jpeg_read_coefficients so that memory allocation will be done right - - // Prepare transformation workspace - // Fails right away if perfect flag is TRUE and transformation is not perfect - if ( !jtransform_request_workspace(&srcinfo, &transfoptions)) { - FreeImage_OutputMessageProc(FIF_JPEG, "Transformation is not perfect"); - throw(1); - } - - // Read source file as DCT coefficients - src_coef_arrays = jpeg_read_coefficients(&srcinfo); - - // Initialize destination compression parameters from source values - jpeg_copy_critical_parameters(&srcinfo, &dstinfo); - - // Adjust destination parameters if required by transform options; - // also find out which set of coefficient arrays will hold the output - dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, src_coef_arrays, &transfoptions); - - // Close the input file. - // Note: we assume that jpeg_read_coefficients consumed all input - // until JPEG_REACHED_EOI, and that jpeg_finish_decompress will - // only consume more while (! cinfo->inputctl->eoi_reached). - // We cannot call jpeg_finish_decompress here since we still need the - // virtual arrays allocated from the source object for processing. - fclose(fp); - - // Open the output file - if(bUseUnicode) { -#ifdef _WIN32 - if ((fp = _wfopen(filenameIO->wdst_file, L"wb")) == NULL) { - FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open output file for writing"); - } -#else - fp = NULL; -#endif // _WIN32 - } else { - if ((fp = fopen(filenameIO->dst_file, "wb")) == NULL) { - FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open %s for writing", filenameIO->dst_file); - } - } - if(fp == NULL) { - throw(1); - } - - // Specify data destination for compression - jpeg_stdio_dest(&dstinfo, fp); - - // Start compressor (note no image data is actually written here) - jpeg_write_coefficients(&dstinfo, dst_coef_arrays); - - // Copy to the output file any extra markers that we want to preserve - jcopy_markers_execute(&srcinfo, &dstinfo, copyoption); - - // Execute image transformation, if any - jtransform_execute_transformation(&srcinfo, &dstinfo, src_coef_arrays, &transfoptions); - - // Finish compression and release memory - jpeg_finish_compress(&dstinfo); - jpeg_destroy_compress(&dstinfo); - jpeg_finish_decompress(&srcinfo); - jpeg_destroy_decompress(&srcinfo); - - // Close output file and return - fclose(fp); - } - catch(...) { - if(fp) fclose(fp); - jpeg_destroy_compress(&dstinfo); - jpeg_destroy_decompress(&srcinfo); - return FALSE; - } - - return TRUE; -} - -// ---------------------------------------------------------- -// FreeImage interface -// ---------------------------------------------------------- - -BOOL DLL_CALLCONV -FreeImage_JPEGTransform(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect) { - try { - // check the src file format - if(FreeImage_GetFileType(src_file) != FIF_JPEG) { - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // setup IO - FilenameIO filenameIO; - memset(&filenameIO, 0, sizeof(FilenameIO)); - filenameIO.src_file = src_file; - filenameIO.dst_file = dst_file; - - // perform the transformation - return LosslessTransform(&filenameIO, operation, NULL, perfect); - - } catch(const char *text) { - FreeImage_OutputMessageProc(FIF_JPEG, text); - return FALSE; - } -} - -BOOL DLL_CALLCONV -FreeImage_JPEGCrop(const char *src_file, const char *dst_file, int left, int top, int right, int bottom) { - char crop[64]; - - try { - // check the src file format - if(FreeImage_GetFileType(src_file) != FIF_JPEG) { - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // normalize the rectangle - if(right < left) { - INPLACESWAP(left, right); - } - if(bottom < top) { - INPLACESWAP(top, bottom); - } - - // build the crop option - sprintf(crop, "%dx%d+%d+%d", right - left, bottom - top, left, top); - - // setup IO - FilenameIO filenameIO; - memset(&filenameIO, 0, sizeof(FilenameIO)); - filenameIO.src_file = src_file; - filenameIO.dst_file = dst_file; - - // perform the transformation - return LosslessTransform(&filenameIO, FIJPEG_OP_NONE, crop, FALSE); - - } catch(const char *text) { - FreeImage_OutputMessageProc(FIF_JPEG, text); - return FALSE; - } -} - -BOOL DLL_CALLCONV -FreeImage_JPEGTransformU(const wchar_t *src_file, const wchar_t *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect) { -#ifdef _WIN32 - try { - // check the src file format - if(FreeImage_GetFileTypeU(src_file) != FIF_JPEG) { - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // setup IO - FilenameIO filenameIO; - memset(&filenameIO, 0, sizeof(FilenameIO)); - filenameIO.wsrc_file = src_file; - filenameIO.wdst_file = dst_file; - - // perform the transformation - return LosslessTransform(&filenameIO, operation, NULL, perfect); - - } catch(const char *text) { - FreeImage_OutputMessageProc(FIF_JPEG, text); - } -#endif /// _WIN32 - return FALSE; -} - -BOOL DLL_CALLCONV -FreeImage_JPEGCropU(const wchar_t *src_file, const wchar_t *dst_file, int left, int top, int right, int bottom) { -#ifdef _WIN32 - char crop[64]; - - try { - // check the src file format - if(FreeImage_GetFileTypeU(src_file) != FIF_JPEG) { - throw FI_MSG_ERROR_MAGIC_NUMBER; - } - - // normalize the rectangle - if(right < left) { - INPLACESWAP(left, right); - } - if(bottom < top) { - INPLACESWAP(top, bottom); - } - - // build the crop option - sprintf(crop, "%dx%d+%d+%d", right - left, bottom - top, left, top); - - // setup IO - FilenameIO filenameIO; - memset(&filenameIO, 0, sizeof(FilenameIO)); - filenameIO.wsrc_file = src_file; - filenameIO.wdst_file = dst_file; - - // perform the transformation - return LosslessTransform(&filenameIO, FIJPEG_OP_NONE, crop, FALSE); - - } catch(const char *text) { - FreeImage_OutputMessageProc(FIF_JPEG, text); - } -#endif // _WIN32 - return FALSE; -} diff --git a/plugins/FreeImage/Source/FreeImageToolkit/MultigridPoissonSolver.cpp b/plugins/FreeImage/Source/FreeImageToolkit/MultigridPoissonSolver.cpp deleted file mode 100644 index a31961447a..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/MultigridPoissonSolver.cpp +++ /dev/null @@ -1,505 +0,0 @@ -// ========================================================== -// Poisson solver based on a full multigrid algorithm -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// Reference: -// PRESS, W. H., TEUKOLSKY, S. A., VETTERLING, W. T., AND FLANNERY, B. P. -// 1992. Numerical Recipes in C: The Art of Scientific Computing, 2nd ed. Cambridge University Press. -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#include "FreeImage.h" -#include "Utilities.h" -#include "ToneMapping.h" - -static const int NPRE = 1; // Number of relaxation sweeps before ... -static const int NPOST = 1; // ... and after the coarse-grid correction is computed -static const int NGMAX = 15; // Maximum number of grids - -/** -Copy src into dst -*/ -static inline void fmg_copyArray(FIBITMAP *dst, FIBITMAP *src) { - memcpy(FreeImage_GetBits(dst), FreeImage_GetBits(src), FreeImage_GetHeight(dst) * FreeImage_GetPitch(dst)); -} - -/** -Fills src with zeros -*/ -static inline void fmg_fillArrayWithZeros(FIBITMAP *src) { - memset(FreeImage_GetBits(src), 0, FreeImage_GetHeight(src) * FreeImage_GetPitch(src)); -} - -/** -Half-weighting restriction. nc is the coarse-grid dimension. The fine-grid solution is input in -uf[0..2*nc-2][0..2*nc-2], the coarse-grid solution is returned in uc[0..nc-1][0..nc-1]. -*/ -static void fmg_restrict(FIBITMAP *UC, FIBITMAP *UF, int nc) { - int row_uc, row_uf, col_uc, col_uf; - - const int uc_pitch = FreeImage_GetPitch(UC) / sizeof(float); - const int uf_pitch = FreeImage_GetPitch(UF) / sizeof(float); - - float *uc_bits = (float*)FreeImage_GetBits(UC); - const float *uf_bits = (float*)FreeImage_GetBits(UF); - - // interior points - { - float *uc_scan = uc_bits + uc_pitch; - for (row_uc = 1, row_uf = 2; row_uc < nc-1; row_uc++, row_uf += 2) { - const float *uf_scan = uf_bits + row_uf * uf_pitch; - for (col_uc = 1, col_uf = 2; col_uc < nc-1; col_uc++, col_uf += 2) { - // calculate - // UC(row_uc, col_uc) = - // 0.5 * UF(row_uf, col_uf) + 0.125 * [ UF(row_uf+1, col_uf) + UF(row_uf-1, col_uf) + UF(row_uf, col_uf+1) + UF(row_uf, col_uf-1) ] - float *uc_pixel = uc_scan + col_uc; - const float *uf_center = uf_scan + col_uf; - *uc_pixel = 0.5F * *uf_center + 0.125F * ( *(uf_center + uf_pitch) + *(uf_center - uf_pitch) + *(uf_center + 1) + *(uf_center - 1)); - } - uc_scan += uc_pitch; - } - } - // boundary points - const int ncc = 2*nc-1; - { - /* - calculate the following: - for (row_uc = 0, row_uf = 0; row_uc < nc; row_uc++, row_uf += 2) { - UC(row_uc, 0) = UF(row_uf, 0); - UC(row_uc, nc-1) = UF(row_uf, ncc-1); - } - */ - float *uc_scan = uc_bits; - for (row_uc = 0, row_uf = 0; row_uc < nc; row_uc++, row_uf += 2) { - const float *uf_scan = uf_bits + row_uf * uf_pitch; - uc_scan[0] = uf_scan[0]; - uc_scan[nc-1] = uf_scan[ncc-1]; - uc_scan += uc_pitch; - } - } - { - /* - calculate the following: - for (col_uc = 0, col_uf = 0; col_uc < nc; col_uc++, col_uf += 2) { - UC(0, col_uc) = UF(0, col_uf); - UC(nc-1, col_uc) = UF(ncc-1, col_uf); - } - */ - float *uc_scan_top = uc_bits; - float *uc_scan_bottom = uc_bits + (nc-1)*uc_pitch; - const float *uf_scan_top = uf_bits + (ncc-1)*uf_pitch; - const float *uf_scan_bottom = uf_bits; - for (col_uc = 0, col_uf = 0; col_uc < nc; col_uc++, col_uf += 2) { - uc_scan_top[col_uc] = uf_scan_top[col_uf]; - uc_scan_bottom[col_uc] = uf_scan_bottom[col_uf]; - } - } -} - -/** -Solution of the model problem on the coarsest grid, where h = 1/2 . -The right-hand side is input -in rhs[0..2][0..2] and the solution is returned in u[0..2][0..2]. -*/ -static void fmg_solve(FIBITMAP *U, FIBITMAP *RHS) { - // fill U with zeros - fmg_fillArrayWithZeros(U); - // calculate U(1, 1) = -h*h*RHS(1, 1)/4.0 where h = 1/2 - float *u_scan = (float*)FreeImage_GetScanLine(U, 1); - const float *rhs_scan = (float*)FreeImage_GetScanLine(RHS, 1); - u_scan[1] = -rhs_scan[1] / 16; -} - -/** -Coarse-to-fine prolongation by bilinear interpolation. nf is the fine-grid dimension. The coarsegrid -solution is input as uc[0..nc-1][0..nc-1], where nc = nf/2 + 1. The fine-grid solution is -returned in uf[0..nf-1][0..nf-1]. -*/ -static void fmg_prolongate(FIBITMAP *UF, FIBITMAP *UC, int nf) { - int row_uc, row_uf, col_uc, col_uf; - - const int uf_pitch = FreeImage_GetPitch(UF) / sizeof(float); - const int uc_pitch = FreeImage_GetPitch(UC) / sizeof(float); - - float *uf_bits = (float*)FreeImage_GetBits(UF); - const float *uc_bits = (float*)FreeImage_GetBits(UC); - - // do elements that are copies - { - const int nc = nf/2 + 1; - - float *uf_scan = uf_bits; - const float *uc_scan = uc_bits; - for (row_uc = 0; row_uc < nc; row_uc++) { - for (col_uc = 0, col_uf = 0; col_uc < nc; col_uc++, col_uf += 2) { - // calculate UF(2*row_uc, col_uf) = UC(row_uc, col_uc); - uf_scan[col_uf] = uc_scan[col_uc]; - } - uc_scan += uc_pitch; - uf_scan += 2 * uf_pitch; - } - } - // do odd-numbered columns, interpolating vertically - { - for(row_uf = 1; row_uf < nf-1; row_uf += 2) { - float *uf_scan = uf_bits + row_uf * uf_pitch; - for (col_uf = 0; col_uf < nf; col_uf += 2) { - // calculate UF(row_uf, col_uf) = 0.5 * ( UF(row_uf+1, col_uf) + UF(row_uf-1, col_uf)) - uf_scan[col_uf] = 0.5F * ( *(uf_scan + uf_pitch + col_uf) + *(uf_scan - uf_pitch + col_uf)); - } - } - } - // do even-numbered columns, interpolating horizontally - { - float *uf_scan = uf_bits; - for(row_uf = 0; row_uf < nf; row_uf++) { - for (col_uf = 1; col_uf < nf-1; col_uf += 2) { - // calculate UF(row_uf, col_uf) = 0.5 * ( UF(row_uf, col_uf+1) + UF(row_uf, col_uf-1)) - uf_scan[col_uf] = 0.5F * ( uf_scan[col_uf + 1] + uf_scan[col_uf - 1] ); - } - uf_scan += uf_pitch; - } - } -} - -/** -Red-black Gauss-Seidel relaxation for model problem. Updates the current value of the solution -u[0..n-1][0..n-1], using the right-hand side function rhs[0..n-1][0..n-1]. -*/ -static void fmg_relaxation(FIBITMAP *U, FIBITMAP *RHS, int n) { - int row, col, ipass, isw, jsw; - const float h = 1.0F / (n - 1); - const float h2 = h*h; - - const int u_pitch = FreeImage_GetPitch(U) / sizeof(float); - const int rhs_pitch = FreeImage_GetPitch(RHS) / sizeof(float); - - float *u_bits = (float*)FreeImage_GetBits(U); - const float *rhs_bits = (float*)FreeImage_GetBits(RHS); - - for (ipass = 0, jsw = 1; ipass < 2; ipass++, jsw = 3-jsw) { // Red and black sweeps - float *u_scan = u_bits + u_pitch; - const float *rhs_scan = rhs_bits + rhs_pitch; - for (row = 1, isw = jsw; row < n-1; row++, isw = 3-isw) { - for (col = isw; col < n-1; col += 2) { - // Gauss-Seidel formula - // calculate U(row, col) = - // 0.25 * [ U(row+1, col) + U(row-1, col) + U(row, col+1) + U(row, col-1) - h2 * RHS(row, col) ] - float *u_center = u_scan + col; - const float *rhs_center = rhs_scan + col; - *u_center = *(u_center + u_pitch) + *(u_center - u_pitch) + *(u_center + 1) + *(u_center - 1); - *u_center -= h2 * *rhs_center; - *u_center *= 0.25F; - } - u_scan += u_pitch; - rhs_scan += rhs_pitch; - } - } -} - -/** -Returns minus the residual for the model problem. Input quantities are u[0..n-1][0..n-1] and -rhs[0..n-1][0..n-1], while res[0..n-1][0..n-1] is returned. -*/ -static void fmg_residual(FIBITMAP *RES, FIBITMAP *U, FIBITMAP *RHS, int n) { - int row, col; - - const float h = 1.0F / (n-1); - const float h2i = 1.0F / (h*h); - - const int res_pitch = FreeImage_GetPitch(RES) / sizeof(float); - const int u_pitch = FreeImage_GetPitch(U) / sizeof(float); - const int rhs_pitch = FreeImage_GetPitch(RHS) / sizeof(float); - - float *res_bits = (float*)FreeImage_GetBits(RES); - const float *u_bits = (float*)FreeImage_GetBits(U); - const float *rhs_bits = (float*)FreeImage_GetBits(RHS); - - // interior points - { - float *res_scan = res_bits + res_pitch; - const float *u_scan = u_bits + u_pitch; - const float *rhs_scan = rhs_bits + rhs_pitch; - for (row = 1; row < n-1; row++) { - for (col = 1; col < n-1; col++) { - // calculate RES(row, col) = - // -h2i * [ U(row+1, col) + U(row-1, col) + U(row, col+1) + U(row, col-1) - 4 * U(row, col) ] + RHS(row, col); - float *res_center = res_scan + col; - const float *u_center = u_scan + col; - const float *rhs_center = rhs_scan + col; - *res_center = *(u_center + u_pitch) + *(u_center - u_pitch) + *(u_center + 1) + *(u_center - 1) - 4 * *u_center; - *res_center *= -h2i; - *res_center += *rhs_center; - } - res_scan += res_pitch; - u_scan += u_pitch; - rhs_scan += rhs_pitch; - } - } - - // boundary points - { - memset(FreeImage_GetScanLine(RES, 0), 0, FreeImage_GetPitch(RES)); - memset(FreeImage_GetScanLine(RES, n-1), 0, FreeImage_GetPitch(RES)); - float *left = res_bits; - float *right = res_bits + (n-1); - for(int k = 0; k < n; k++) { - *left = 0; - *right = 0; - left += res_pitch; - right += res_pitch; - } - } -} - -/** -Does coarse-to-fine interpolation and adds result to uf. nf is the fine-grid dimension. The -coarse-grid solution is input as uc[0..nc-1][0..nc-1], where nc = nf/2+1. The fine-grid solution -is returned in uf[0..nf-1][0..nf-1]. res[0..nf-1][0..nf-1] is used for temporary storage. -*/ -static void fmg_addint(FIBITMAP *UF, FIBITMAP *UC, FIBITMAP *RES, int nf) { - fmg_prolongate(RES, UC, nf); - - const int uf_pitch = FreeImage_GetPitch(UF) / sizeof(float); - const int res_pitch = FreeImage_GetPitch(RES) / sizeof(float); - - float *uf_bits = (float*)FreeImage_GetBits(UF); - const float *res_bits = (float*)FreeImage_GetBits(RES); - - for(int row = 0; row < nf; row++) { - for(int col = 0; col < nf; col++) { - // calculate UF(row, col) = UF(row, col) + RES(row, col); - uf_bits[col] += res_bits[col]; - } - uf_bits += uf_pitch; - res_bits += res_pitch; - } -} - -/** -Full Multigrid Algorithm for solution of linear elliptic equation, here the model problem (19.0.6). -On input u[0..n-1][0..n-1] contains the right-hand side ñ, while on output it returns the solution. -The dimension n must be of the form 2^j + 1 for some integer j. (j is actually the number of -grid levels used in the solution, called ng below.) ncycle is the number of V-cycles to be -used at each level. -*/ -static BOOL fmg_mglin(FIBITMAP *U, int n, int ncycle) { - int j, jcycle, jj, jpost, jpre, nf, ngrid; - - FIBITMAP **IRHO = NULL; - FIBITMAP **IU = NULL; - FIBITMAP **IRHS = NULL; - FIBITMAP **IRES = NULL; - - int ng = 0; // number of allocated grids - -// -------------------------------------------------------------------------- - -#define _CREATE_ARRAY_GRID_(array, array_size) \ - array = (FIBITMAP**)malloc(array_size * sizeof(FIBITMAP*));\ - if (!array) throw(1);\ - memset(array, 0, array_size * sizeof(FIBITMAP*)) - -#define _FREE_ARRAY_GRID_(array, array_size) \ - if(NULL != array) {\ - for(int k = 0; k < array_size; k++) {\ - if(NULL != array[k]) {\ - FreeImage_Unload(array[k]); array[k] = NULL;\ - }\ - }\ - free(array);\ - } - -// -------------------------------------------------------------------------- - - try { - int nn = n; - // check grid size and grid levels - while (nn >>= 1) ng++; - if (n != 1 + (1L << ng)) { - FreeImage_OutputMessageProc(FIF_UNKNOWN, "Multigrid algorithm: n = %d, while n-1 must be a power of 2.", n); - throw(1); - } - if (ng > NGMAX) { - FreeImage_OutputMessageProc(FIF_UNKNOWN, "Multigrid algorithm: ng = %d while NGMAX = %d, increase NGMAX.", ng, NGMAX); - throw(1); - } - // allocate grid arrays - { - _CREATE_ARRAY_GRID_(IRHO, ng); - _CREATE_ARRAY_GRID_(IU, ng); - _CREATE_ARRAY_GRID_(IRHS, ng); - _CREATE_ARRAY_GRID_(IRES, ng); - } - - nn = n/2 + 1; - ngrid = ng - 2; - - // allocate storage for r.h.s. on grid (ng - 2) ... - IRHO[ngrid] = FreeImage_AllocateT(FIT_FLOAT, nn, nn); - if (!IRHO[ngrid]) throw(1); - - // ... and fill it by restricting from the fine grid - fmg_restrict(IRHO[ngrid], U, nn); - - // similarly allocate storage and fill r.h.s. on all coarse grids. - while (nn > 3) { - nn = nn/2 + 1; - ngrid--; - IRHO[ngrid] = FreeImage_AllocateT(FIT_FLOAT, nn, nn); - if (!IRHO[ngrid]) throw(1); - fmg_restrict(IRHO[ngrid], IRHO[ngrid+1], nn); - } - - nn = 3; - - IU[0] = FreeImage_AllocateT(FIT_FLOAT, nn, nn); - if (!IU[0]) throw(1); - IRHS[0] = FreeImage_AllocateT(FIT_FLOAT, nn, nn); - if (!IRHS[0]) throw(1); - - // initial solution on coarsest grid - fmg_solve(IU[0], IRHO[0]); - // irho[0] no longer needed ... - FreeImage_Unload(IRHO[0]); IRHO[0] = NULL; - - ngrid = ng; - - // nested iteration loop - for (j = 1; j < ngrid; j++) { - nn = 2*nn - 1; - - IU[j] = FreeImage_AllocateT(FIT_FLOAT, nn, nn); - if (!IU[j]) throw(1); - IRHS[j] = FreeImage_AllocateT(FIT_FLOAT, nn, nn); - if (!IRHS[j]) throw(1); - IRES[j] = FreeImage_AllocateT(FIT_FLOAT, nn, nn); - if (!IRES[j]) throw(1); - - fmg_prolongate(IU[j], IU[j-1], nn); - - // interpolate from coarse grid to next finer grid - - // set up r.h.s. - fmg_copyArray(IRHS[j], j != (ngrid - 1) ? IRHO[j] : U); - - // V-cycle loop - for (jcycle = 0; jcycle < ncycle; jcycle++) { - nf = nn; - // downward stoke of the V - for (jj = j; jj >= 1; jj--) { - // pre-smoothing - for (jpre = 0; jpre < NPRE; jpre++) { - fmg_relaxation(IU[jj], IRHS[jj], nf); - } - fmg_residual(IRES[jj], IU[jj], IRHS[jj], nf); - nf = nf/2 + 1; - // restriction of the residual is the next r.h.s. - fmg_restrict(IRHS[jj-1], IRES[jj], nf); - // zero for initial guess in next relaxation - fmg_fillArrayWithZeros(IU[jj-1]); - } - // bottom of V: solve on coarsest grid - fmg_solve(IU[0], IRHS[0]); - nf = 3; - // upward stroke of V. - for (jj = 1; jj <= j; jj++) { - nf = 2*nf - 1; - // use res for temporary storage inside addint - fmg_addint(IU[jj], IU[jj-1], IRES[jj], nf); - // post-smoothing - for (jpost = 0; jpost < NPOST; jpost++) { - fmg_relaxation(IU[jj], IRHS[jj], nf); - } - } - } - } - - // return solution in U - fmg_copyArray(U, IU[ngrid-1]); - - // delete allocated arrays - _FREE_ARRAY_GRID_(IRES, ng); - _FREE_ARRAY_GRID_(IRHS, ng); - _FREE_ARRAY_GRID_(IU, ng); - _FREE_ARRAY_GRID_(IRHO, ng); - - return TRUE; - - } catch(int) { - // delete allocated arrays - _FREE_ARRAY_GRID_(IRES, ng); - _FREE_ARRAY_GRID_(IRHS, ng); - _FREE_ARRAY_GRID_(IU, ng); - _FREE_ARRAY_GRID_(IRHO, ng); - - return FALSE; - } -} - -// -------------------------------------------------------------------------- - -/** -Poisson solver based on a multigrid algorithm. -This routine solves a Poisson equation, remap result pixels to [0..1] and returns the solution. -NB: The input image is first stored inside a square image whose size is (2^j + 1)x(2^j + 1) for some integer j, -where j is such that 2^j is the nearest larger dimension corresponding to MAX(image width, image height). -@param Laplacian Laplacian image -@param ncycle Number of cycles in the multigrid algorithm (usually 2 or 3) -@return Returns the solved PDE equations if successful, returns NULL otherwise -*/ -FIBITMAP* DLL_CALLCONV -FreeImage_MultigridPoissonSolver(FIBITMAP *Laplacian, int ncycle) { - if (!FreeImage_HasPixels(Laplacian)) return NULL; - - int width = FreeImage_GetWidth(Laplacian); - int height = FreeImage_GetHeight(Laplacian); - - // get nearest larger dimension length that is acceptable by the algorithm - int n = MAX(width, height); - int size = 0; - while((n >>= 1) > 0) size++; - if ((1 << size) < MAX(width, height)) { - size++; - } - // size must be of the form 2^j + 1 for some integer j - size = 1 + (1 << size); - - // allocate a temporary square image I - FIBITMAP *I = FreeImage_AllocateT(FIT_FLOAT, size, size); - if (!I) return NULL; - - // copy Laplacian into I and shift pixels to create a boundary - FreeImage_Paste(I, Laplacian, 1, 1, 255); - - // solve the PDE equation - fmg_mglin(I, size, ncycle); - - // shift pixels back - FIBITMAP *U = FreeImage_Copy(I, 1, 1, width + 1, height + 1); - FreeImage_Unload(I); - - // remap pixels to [0..1] - NormalizeY(U, 0, 1); - - // copy metadata from src to dst - FreeImage_CloneMetadata(U, Laplacian); - - // return the integrated image - return U; -} - diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Rescale.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Rescale.cpp deleted file mode 100644 index e79e5f456c..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Rescale.cpp +++ /dev/null @@ -1,231 +0,0 @@ -// ========================================================== -// Upsampling / downsampling routine -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#include "Resize.h" - -FIBITMAP * DLL_CALLCONV -FreeImage_Rescale(FIBITMAP *src, int dst_width, int dst_height, FREE_IMAGE_FILTER filter) { - FIBITMAP *dst = NULL; - - if (!FreeImage_HasPixels(src) || (dst_width <= 0) || (dst_height <= 0) || (FreeImage_GetWidth(src) <= 0) || (FreeImage_GetHeight(src) <= 0)) { - return NULL; - } - - // select the filter - CGenericFilter *pFilter = NULL; - switch(filter) { - case FILTER_BOX: - pFilter = new(std::nothrow) CBoxFilter(); - break; - case FILTER_BICUBIC: - pFilter = new(std::nothrow) CBicubicFilter(); - break; - case FILTER_BILINEAR: - pFilter = new(std::nothrow) CBilinearFilter(); - break; - case FILTER_BSPLINE: - pFilter = new(std::nothrow) CBSplineFilter(); - break; - case FILTER_CATMULLROM: - pFilter = new(std::nothrow) CCatmullRomFilter(); - break; - case FILTER_LANCZOS3: - pFilter = new(std::nothrow) CLanczos3Filter(); - break; - } - - if (!pFilter) { - return NULL; - } - - CResizeEngine Engine(pFilter); - - // perform upsampling or downsampling - - if ((FreeImage_GetBPP(src) == 4) || (FreeImage_GetColorType(src) == FIC_PALETTE)) { - // special case for 4-bit images or color map indexed images ... - if(FreeImage_IsTransparent(src) == FALSE) { - FIBITMAP *src24 = NULL; - FIBITMAP *dst24 = NULL; - try { - // transparent conversion to 24-bit (any transparency table will be destroyed) - src24 = FreeImage_ConvertTo24Bits(src); - if (!src24) throw(1); - // perform upsampling or downsampling - dst24 = Engine.scale(src24, dst_width, dst_height); - if (!dst24) throw(1); - FreeImage_Unload(src24); src24 = NULL; - // color quantize to 8-bit - dst = FreeImage_ColorQuantize(dst24, FIQ_NNQUANT); - // free and return - FreeImage_Unload(dst24); - } catch(int) { - if(src24) FreeImage_Unload(src24); - if(dst24) FreeImage_Unload(dst24); - } - } else { - FIBITMAP *src32 = NULL; - try { - // transparent conversion to 32-bit (keep transparency) - src32 = FreeImage_ConvertTo32Bits(src); - if (!src32) throw(1); - // perform upsampling or downsampling - dst = Engine.scale(src32, dst_width, dst_height); - if (!dst) throw(1); - // free and return - FreeImage_Unload(src32); - } catch(int) { - if(src32) FreeImage_Unload(src32); - if(dst) FreeImage_Unload(dst); - } - } - } - else if ((FreeImage_GetBPP(src) == 16) && (FreeImage_GetImageType(src) == FIT_BITMAP)) { - // convert 16-bit RGB to 24-bit - FIBITMAP *src24 = NULL; - try { - // transparent conversion to 24-bit (any transparency table will be destroyed) - src24 = FreeImage_ConvertTo24Bits(src); - if (!src24) throw(1); - // perform upsampling or downsampling - dst = Engine.scale(src24, dst_width, dst_height); - if (!dst) throw(1); - // free and return - FreeImage_Unload(src24); - } catch(int) { - if(src24) FreeImage_Unload(src24); - if(dst) FreeImage_Unload(dst); - } - } - else { - // normal case : - // 1- or 8-bit greyscale, 24- or 32-bit RGB(A) images - // 16-bit greyscale, 48- or 64-bit RGB(A) images - // 32-bit float, 96- or 128-bit RGB(A) float images - dst = Engine.scale(src, dst_width, dst_height); - } - - - delete pFilter; - - // copy metadata from src to dst - FreeImage_CloneMetadata(dst, src); - - return dst; -} - -FIBITMAP * DLL_CALLCONV -FreeImage_MakeThumbnail(FIBITMAP *dib, int max_pixel_size, BOOL convert) { - FIBITMAP *thumbnail = NULL; - int new_width, new_height; - - if (!FreeImage_HasPixels(dib) || (max_pixel_size <= 0)) return NULL; - - int width = FreeImage_GetWidth(dib); - int height = FreeImage_GetHeight(dib); - - if(max_pixel_size == 0) max_pixel_size = 1; - - if ((width < max_pixel_size) && (height < max_pixel_size)) { - // image is smaller than the requested thumbnail - return FreeImage_Clone(dib); - } - - if(width > height) { - new_width = max_pixel_size; - // change image height with the same ratio - double ratio = ((double)new_width / (double)width); - new_height = (int)(height * ratio + 0.5); - if(new_height == 0) new_height = 1; - } else { - new_height = max_pixel_size; - // change image width with the same ratio - double ratio = ((double)new_height / (double)height); - new_width = (int)(width * ratio + 0.5); - if(new_width == 0) new_width = 1; - } - - const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib); - - // perform downsampling using a bilinear interpolation - - switch(image_type) { - case FIT_BITMAP: - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - { - FREE_IMAGE_FILTER filter = FILTER_BILINEAR; - thumbnail = FreeImage_Rescale(dib, new_width, new_height, filter); - } - break; - - case FIT_INT16: - case FIT_UINT32: - case FIT_INT32: - case FIT_DOUBLE: - case FIT_COMPLEX: - default: - // cannot rescale this kind of image - thumbnail = NULL; - break; - } - - if ((thumbnail != NULL) && (image_type != FIT_BITMAP) && convert) { - // convert to a standard bitmap - FIBITMAP *bitmap = NULL; - switch(image_type) { - case FIT_UINT16: - bitmap = FreeImage_ConvertTo8Bits(thumbnail); - break; - case FIT_RGB16: - bitmap = FreeImage_ConvertTo24Bits(thumbnail); - break; - case FIT_RGBA16: - bitmap = FreeImage_ConvertTo32Bits(thumbnail); - break; - case FIT_FLOAT: - bitmap = FreeImage_ConvertToStandardType(thumbnail, TRUE); - break; - case FIT_RGBF: - bitmap = FreeImage_ToneMapping(thumbnail, FITMO_DRAGO03); - break; - case FIT_RGBAF: - // no way to keep the transparency yet ... - FIBITMAP *rgbf = FreeImage_ConvertToRGBF(thumbnail); - bitmap = FreeImage_ToneMapping(rgbf, FITMO_DRAGO03); - FreeImage_Unload(rgbf); - break; - } - if(bitmap != NULL) { - FreeImage_Unload(thumbnail); - thumbnail = bitmap; - } - } - - // copy metadata from src to dst - FreeImage_CloneMetadata(thumbnail, dib); - - return thumbnail; -} diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Resize.cpp b/plugins/FreeImage/Source/FreeImageToolkit/Resize.cpp deleted file mode 100644 index 5421bd47ab..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Resize.cpp +++ /dev/null @@ -1,656 +0,0 @@ -// ========================================================== -// Upsampling / downsampling classes -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Detlev Vendt (detlev.vendt@brillit.de) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#include "Resize.h" - -/** - Filter weights table. - This class stores contribution information for an entire line (row or column). -*/ -CWeightsTable::CWeightsTable(CGenericFilter *pFilter, unsigned uDstSize, unsigned uSrcSize) { - unsigned u; - double dWidth; - double dFScale = 1.0; - const double dFilterWidth = pFilter->GetWidth(); - - // scale factor - const double dScale = double(uDstSize) / double(uSrcSize); - - if(dScale < 1.0) { - // minification - dWidth = dFilterWidth / dScale; - dFScale = dScale; - } else { - // magnification - dWidth= dFilterWidth; - } - - // allocate a new line contributions structure - // - // window size is the number of sampled pixels - m_WindowSize = 2 * (int)ceil(dWidth) + 1; - m_LineLength = uDstSize; - // allocate list of contributions - m_WeightTable = (Contribution*)malloc(m_LineLength * sizeof(Contribution)); - for(u = 0 ; u < m_LineLength ; u++) { - // allocate contributions for every pixel - m_WeightTable[u].Weights = (double*)malloc(m_WindowSize * sizeof(double)); - } - - // offset for discrete to continuous coordinate conversion - const double dOffset = (0.5 / dScale) - 0.5; - - - for(u = 0; u < m_LineLength; u++) { - // scan through line of contributions - const double dCenter = (double)u / dScale + dOffset; // reverse mapping - // find the significant edge points that affect the pixel - int iLeft = MAX (0, (int)floor (dCenter - dWidth)); - int iRight = MIN ((int)ceil (dCenter + dWidth), int(uSrcSize) - 1); - - // cut edge points to fit in filter window in case of spill-off - if ((iRight - iLeft + 1) > int(m_WindowSize)) { - if(iLeft < (int(uSrcSize) - 1 / 2)) { - iLeft++; - } else { - iRight--; - } - } - - m_WeightTable[u].Left = iLeft; - m_WeightTable[u].Right = iRight; - - int iSrc = 0; - double dTotalWeight = 0; // zero sum of weights - for(iSrc = iLeft; iSrc <= iRight; iSrc++) { - // calculate weights - const double weight = dFScale * pFilter->Filter(dFScale * (dCenter - (double)iSrc)); - m_WeightTable[u].Weights[iSrc-iLeft] = weight; - dTotalWeight += weight; - } - if ((dTotalWeight > 0) && (dTotalWeight != 1)) { - // normalize weight of neighbouring points - for(iSrc = iLeft; iSrc <= iRight; iSrc++) { - // normalize point - m_WeightTable[u].Weights[iSrc-iLeft] /= dTotalWeight; - } - // simplify the filter, discarding null weights at the right - iSrc = iRight - iLeft; - while(m_WeightTable[u].Weights[iSrc] == 0){ - m_WeightTable[u].Right--; - iSrc--; - if(m_WeightTable[u].Right == m_WeightTable[u].Left) - break; - } - - } - } -} - -CWeightsTable::~CWeightsTable() { - for(unsigned u = 0; u < m_LineLength; u++) { - // free contributions for every pixel - free(m_WeightTable[u].Weights); - } - // free list of pixels contributions - free(m_WeightTable); -} - -// --------------------------------------------- - -/** - CResizeEngine
- This class performs filtered zoom. It scales an image to the desired dimensions with - any of the CGenericFilter derived filter class.
- It works with 8-, 24- and 32-bit buffers.

- - References :
- [1] Paul Heckbert, C code to zoom raster images up or down, with nice filtering. - UC Berkeley, August 1989. [online] http://www-2.cs.cmu.edu/afs/cs.cmu.edu/Web/People/ph/heckbert.html - [2] Eran Yariv, Two Pass Scaling using Filters. The Code Project, December 1999. - [online] http://www.codeproject.com/bitmap/2_pass_scaling.asp - -*/ - -FIBITMAP* CResizeEngine::scale(FIBITMAP *src, unsigned dst_width, unsigned dst_height) { - unsigned src_width = FreeImage_GetWidth(src); - unsigned src_height = FreeImage_GetHeight(src); - - unsigned redMask = FreeImage_GetRedMask(src); - unsigned greenMask = FreeImage_GetGreenMask(src); - unsigned blueMask = FreeImage_GetBlueMask(src); - - unsigned bpp = FreeImage_GetBPP(src); - if(bpp == 1) { - // convert output to 8-bit - bpp = 8; - } - - FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src); - - // allocate the dst image - FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp, redMask, greenMask, blueMask); - if (!dst) return NULL; - - if(bpp == 8) { - if(FreeImage_GetColorType(src) == FIC_MINISWHITE) { - // build an inverted greyscale palette - RGBQUAD *dst_pal = FreeImage_GetPalette(dst); - for(unsigned i = 0; i < 256; i++) { - dst_pal[i].rgbRed = dst_pal[i].rgbGreen = dst_pal[i].rgbBlue = (BYTE)(255 - i); - } - } else { - // build a greyscale palette - RGBQUAD *dst_pal = FreeImage_GetPalette(dst); - for(unsigned i = 0; i < 256; i++) { - dst_pal[i].rgbRed = dst_pal[i].rgbGreen = dst_pal[i].rgbBlue = (BYTE)i; - } - } - } - - /** - Decide which filtering order (xy or yx) is faster for this mapping. - --- The theory --- - Try to minimize calculations by counting the number of convolution multiplies - if(dst_width*src_height <= src_width*dst_height) { - // xy filtering - } else { - // yx filtering - } - --- The practice --- - Try to minimize calculations by counting the number of vertical convolutions (the most time consuming task) - if(dst_width*dst_height <= src_width*dst_height) { - // xy filtering - } else { - // yx filtering - } - */ - - if(dst_width <= src_width) { - // xy filtering - // ------------- - - // allocate a temporary image - FIBITMAP *tmp = FreeImage_AllocateT(image_type, dst_width, src_height, bpp, redMask, greenMask, blueMask); - if (!tmp) { - FreeImage_Unload(dst); - return NULL; - } - - // scale source image horizontally into temporary image - horizontalFilter(src, src_width, src_height, tmp, dst_width, src_height); - - // scale temporary image vertically into result image - verticalFilter(tmp, dst_width, src_height, dst, dst_width, dst_height); - - // free temporary image - FreeImage_Unload(tmp); - - } else { - // yx filtering - // ------------- - - // allocate a temporary image - FIBITMAP *tmp = FreeImage_AllocateT(image_type, src_width, dst_height, bpp, redMask, greenMask, blueMask); - if (!tmp) { - FreeImage_Unload(dst); - return NULL; - } - - // scale source image vertically into temporary image - verticalFilter(src, src_width, src_height, tmp, src_width, dst_height); - - // scale temporary image horizontally into result image - horizontalFilter(tmp, src_width, dst_height, dst, dst_width, dst_height); - - // free temporary image - FreeImage_Unload(tmp); - } - - return dst; -} - - -/// Performs horizontal image filtering -void CResizeEngine::horizontalFilter(FIBITMAP *src, unsigned src_width, unsigned src_height, FIBITMAP *dst, unsigned dst_width, unsigned dst_height) { - if(dst_width == src_width) { - // no scaling required, just copy - switch(FreeImage_GetBPP(src)) { - case 1: - { - if(FreeImage_GetBPP(dst) != 8) break; - for(unsigned y = 0; y < dst_height; y++) { - // convert each row - BYTE *src_bits = FreeImage_GetScanLine(src, y); - BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - FreeImage_ConvertLine1To8(dst_bits, src_bits, dst_width); - } - } - break; - - default: - { - const BYTE *src_bits = FreeImage_GetBits(src); - BYTE *dst_bits = FreeImage_GetBits(dst); - memcpy(dst_bits, src_bits, dst_height * FreeImage_GetPitch(dst)); - } - break; - } - } - else { - - // allocate and calculate the contributions - CWeightsTable weightsTable(m_pFilter, dst_width, src_width); - - // step through rows - switch(FreeImage_GetImageType(src)) { - case FIT_BITMAP: - { - switch(FreeImage_GetBPP(src)) { - case 1: - { - // scale and convert to 8-bit - if(FreeImage_GetBPP(dst) != 8) break; - - for(unsigned y = 0; y < dst_height; y++) { - // scale each row - const BYTE *src_bits = FreeImage_GetScanLine(src, y); - BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - - for(unsigned x = 0; x < dst_width; x++) { - // loop through row - double value = 0; - const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(x, i-iLeft); - - const BYTE pixel = (src_bits[i >> 3] & (0x80 >> (i & 0x07))) != 0; - value += (weight * (double)pixel); - } - value *= 255; - - // clamp and place result in destination pixel - dst_bits[x] = (BYTE)CLAMP((int)(value + 0.5), 0, 255); - } - } - } - break; - - case 8: - case 24: - case 32: - { - // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - for(unsigned y = 0; y < dst_height; y++) { - // scale each row - const BYTE *src_bits = FreeImage_GetScanLine(src, y); - BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - - for(unsigned x = 0; x < dst_width; x++) { - // loop through row - double value[4] = {0, 0, 0, 0}; // 4 = 32 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(x, i-iLeft); - - unsigned index = i * bytespp; // pixel index - for (unsigned j = 0; j < bytespp; j++) { - value[j] += (weight * (double)src_bits[index++]); - } - } - - // clamp and place result in destination pixel - for (unsigned j = 0; j < bytespp; j++) { - dst_bits[j] = (BYTE)CLAMP((int)(value[j] + 0.5), 0, 0xFF); - } - - dst_bits += bytespp; - } - } - } - break; - } - } - break; - - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - { - // Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) - const unsigned wordspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(WORD); - - for(unsigned y = 0; y < dst_height; y++) { - // scale each row - const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y); - WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y); - - for(unsigned x = 0; x < dst_width; x++) { - // loop through row - double value[4] = {0, 0, 0, 0}; // 4 = 64 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(x, i-iLeft); - - unsigned index = i * wordspp; // pixel index - for (unsigned j = 0; j < wordspp; j++) { - value[j] += (weight * (double)src_bits[index++]); - } - } - - // clamp and place result in destination pixel - for (unsigned j = 0; j < wordspp; j++) { - dst_bits[j] = (WORD)CLAMP((int)(value[j] + 0.5), 0, 0xFFFF); - } - - dst_bits += wordspp; - } - } - } - break; - - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - { - // Calculate the number of floats per pixel (1 for 32-bit, 3 for 96-bit or 4 for 128-bit) - const unsigned floatspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(float); - - for(unsigned y = 0; y < dst_height; y++) { - // scale each row - const float *src_bits = (float*)FreeImage_GetScanLine(src, y); - float *dst_bits = (float*)FreeImage_GetScanLine(dst, y); - - for(unsigned x = 0; x < dst_width; x++) { - // loop through row - double value[4] = {0, 0, 0, 0}; // 4 = 128 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(x); // retrieve right boundary - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(x, i-iLeft); - - unsigned index = i * floatspp; // pixel index - for (unsigned j = 0; j < floatspp; j++) { - value[j] += (weight * (double)src_bits[index++]); - } - } - - // place result in destination pixel - for (unsigned j = 0; j < floatspp; j++) { - dst_bits[j] = (float)value[j]; - } - - dst_bits += floatspp; - } - } - } - break; - - } - } -} - -/// Performs vertical image filtering -void CResizeEngine::verticalFilter(FIBITMAP *src, unsigned src_width, unsigned src_height, FIBITMAP *dst, unsigned dst_width, unsigned dst_height) { - if(src_height == dst_height) { - // no scaling required, just copy - switch(FreeImage_GetBPP(src)) { - case 1: - { - if(FreeImage_GetBPP(dst) != 8) break; - for(unsigned y = 0; y < dst_height; y++) { - // convert each row - BYTE *src_bits = FreeImage_GetScanLine(src, y); - BYTE *dst_bits = FreeImage_GetScanLine(dst, y); - FreeImage_ConvertLine1To8(dst_bits, src_bits, dst_width); - } - } - break; - - default: - { - const BYTE *src_bits = FreeImage_GetBits(src); - BYTE *dst_bits = FreeImage_GetBits(dst); - memcpy(dst_bits, src_bits, dst_height * FreeImage_GetPitch(dst)); - } - break; - } - - } - else { - - // allocate and calculate the contributions - CWeightsTable weightsTable(m_pFilter, dst_height, src_height); - - // step through columns - switch(FreeImage_GetImageType(src)) { - case FIT_BITMAP: - { - switch(FreeImage_GetBPP(src)) { - case 1: - { - // scale and convert to 8-bit - if(FreeImage_GetBPP(dst) != 8) break; - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - for(unsigned x = 0; x < dst_width; x++) { - - // work on column x in dst - BYTE *dst_bits = FreeImage_GetBits(dst) + x; - - // scale each column - for(unsigned y = 0; y < dst_height; y++) { - // loop through column - double value = 0; - const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary - - BYTE *src_bits = FreeImage_GetScanLine(src, iLeft); - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(y, i-iLeft); - - const BYTE pixel = (src_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0; - value += (weight * (double)pixel); - - src_bits += src_pitch; - } - value *= 255; - - // clamp and place result in destination pixel - *dst_bits = (BYTE)CLAMP((int)(value + 0.5), 0, 0xFF); - - dst_bits += dst_pitch; - } - } - } - break; - - case 8: - case 24: - case 32: - { - // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit) - const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src); - - const unsigned src_pitch = FreeImage_GetPitch(src); - const unsigned dst_pitch = FreeImage_GetPitch(dst); - - for(unsigned x = 0; x < dst_width; x++) { - const unsigned index = x * bytespp; // pixel index - - // work on column x in dst - BYTE *dst_bits = FreeImage_GetBits(dst) + index; - - // scale each column - for(unsigned y = 0; y < dst_height; y++) { - // loop through column - double value[4] = {0, 0, 0, 0}; // 4 = 32 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary - - const BYTE *src_bits = FreeImage_GetScanLine(src, iLeft) + index; - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(y, i-iLeft); - for (unsigned j = 0; j < bytespp; j++) { - value[j] += (weight * (double)src_bits[j]); - } - - src_bits += src_pitch; - } - - // clamp and place result in destination pixel - for (unsigned j = 0; j < bytespp; j++) { - dst_bits[j] = (BYTE)CLAMP((int)(value[j] + 0.5), 0, 0xFF); - } - - dst_bits += dst_pitch; - } - } - } - break; - } - } - break; - - case FIT_UINT16: - case FIT_RGB16: - case FIT_RGBA16: - { - // Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit) - const unsigned wordspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(WORD); - - const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(WORD); - const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(WORD); - - for(unsigned x = 0; x < dst_width; x++) { - const unsigned index = x * wordspp; // pixel index - - // work on column x in dst - WORD *dst_bits = (WORD*)FreeImage_GetBits(dst) + index; - - // scale each column - for(unsigned y = 0; y < dst_height; y++) { - // loop through column - double value[4] = {0, 0, 0, 0}; // 4 = 64 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary - - const WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, iLeft) + index; - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(y, i-iLeft); - for (unsigned j = 0; j < wordspp; j++) { - value[j] += (weight * (double)src_bits[j]); - } - - src_bits += src_pitch; - } - - // clamp and place result in destination pixel - for (unsigned j = 0; j < wordspp; j++) { - dst_bits[j] = (WORD)CLAMP((int)(value[j] + 0.5), 0, 0xFFFF); - } - - dst_bits += dst_pitch; - } - } - } - break; - - case FIT_FLOAT: - case FIT_RGBF: - case FIT_RGBAF: - { - // Calculate the number of floats per pixel (1 for 32-bit, 3 for 96-bit or 4 for 128-bit) - const unsigned floatspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(float); - - const unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(float); - const unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(float); - - for(unsigned x = 0; x < dst_width; x++) { - const unsigned index = x * floatspp; // pixel index - - // work on column x in dst - float *dst_bits = (float*)FreeImage_GetBits(dst) + index; - - // scale each column - for(unsigned y = 0; y < dst_height; y++) { - // loop through column - double value[4] = {0, 0, 0, 0}; // 4 = 128 bpp max - const unsigned iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary - const unsigned iRight = weightsTable.getRightBoundary(y); // retrieve right boundary - - const float *src_bits = (float*)FreeImage_GetScanLine(src, iLeft) + index; - - for(unsigned i = iLeft; i <= iRight; i++) { - // scan between boundaries - // accumulate weighted effect of each neighboring pixel - const double weight = weightsTable.getWeight(y, i-iLeft); - for (unsigned j = 0; j < floatspp; j++) { - value[j] += (weight * (double)src_bits[j]); - } - - src_bits += src_pitch; - } - - // clamp and place result in destination pixel - for (unsigned j = 0; j < floatspp; j++) { - dst_bits[j] = (float)value[j]; - } - - dst_bits += dst_pitch; - } - } - } - break; - - } - } -} - diff --git a/plugins/FreeImage/Source/FreeImageToolkit/Resize.h b/plugins/FreeImage/Source/FreeImageToolkit/Resize.h deleted file mode 100644 index 0d5d0b451a..0000000000 --- a/plugins/FreeImage/Source/FreeImageToolkit/Resize.h +++ /dev/null @@ -1,145 +0,0 @@ -// ========================================================== -// Upsampling / downsampling classes -// -// Design and implementation by -// - Hervé Drolon (drolon@infonie.fr) -// - Detlev Vendt (detlev.vendt@brillit.de) -// -// This file is part of FreeImage 3 -// -// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY -// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES -// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE -// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED -// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT -// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY -// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL -// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER -// THIS DISCLAIMER. -// -// Use at your own risk! -// ========================================================== - -#ifndef _RESIZE_H_ -#define _RESIZE_H_ - -#include "FreeImage.h" -#include "Utilities.h" -#include "Filters.h" - -/** - Filter weights table.
- This class stores contribution information for an entire line (row or column). -*/ -class CWeightsTable -{ -/** - Sampled filter weight table.
- Contribution information for a single pixel -*/ -typedef struct { - /// Normalized weights of neighboring pixels - double *Weights; - /// Bounds of source pixels window - unsigned Left, Right; -} Contribution; - -private: - /// Row (or column) of contribution weights - Contribution *m_WeightTable; - /// Filter window size (of affecting source pixels) - unsigned m_WindowSize; - /// Length of line (no. of rows / cols) - unsigned m_LineLength; - -public: - /** - Constructor
- Allocate and compute the weights table - @param pFilter Filter used for upsampling or downsampling - @param uDstSize Length (in pixels) of the destination line buffer - @param uSrcSize Length (in pixels) of the source line buffer - */ - CWeightsTable(CGenericFilter *pFilter, unsigned uDstSize, unsigned uSrcSize); - - /** - Destructor
- Destroy the weights table - */ - ~CWeightsTable(); - - /** Retrieve a filter weight, given source and destination positions - @param dst_pos Pixel position in destination line buffer - @param src_pos Pixel position in source line buffer - @return Returns the filter weight - */ - double getWeight(unsigned dst_pos, unsigned src_pos) { - return m_WeightTable[dst_pos].Weights[src_pos]; - } - - /** Retrieve left boundary of source line buffer - @param dst_pos Pixel position in destination line buffer - @return Returns the left boundary of source line buffer - */ - unsigned getLeftBoundary(unsigned dst_pos) { - return m_WeightTable[dst_pos].Left; - } - - /** Retrieve right boundary of source line buffer - @param dst_pos Pixel position in destination line buffer - @return Returns the right boundary of source line buffer - */ - unsigned getRightBoundary(unsigned dst_pos) { - return m_WeightTable[dst_pos].Right; - } -}; - -// --------------------------------------------- - -/** - CResizeEngine
- This class performs filtered zoom. It scales an image to the desired dimensions with - any of the CGenericFilter derived filter class.
- It works with 8-, 24- and 32-bit buffers.

- - References :
- [1] Paul Heckbert, C code to zoom raster images up or down, with nice filtering. - UC Berkeley, August 1989. [online] http://www-2.cs.cmu.edu/afs/cs.cmu.edu/Web/People/ph/heckbert.html - [2] Eran Yariv, Two Pass Scaling using Filters. The Code Project, December 1999. - [online] http://www.codeproject.com/bitmap/2_pass_scaling.asp - -*/ -class CResizeEngine -{ -private: - /// Pointer to the FIR / IIR filter - CGenericFilter* m_pFilter; - -public: - - /// Constructor - CResizeEngine(CGenericFilter* filter):m_pFilter(filter) {} - - /// Destructor - virtual ~CResizeEngine() {} - - /** Scale an image to the desired dimensions - @param src Pointer to the source image - @param dst_width Destination image width - @param dst_height Destination image height - @return Returns the scaled image if successful, returns NULL otherwise - */ - FIBITMAP* scale(FIBITMAP *src, unsigned dst_width, unsigned dst_height); - -private: - - /// Performs horizontal image filtering - void horizontalFilter(FIBITMAP *src, unsigned src_width, unsigned src_height, FIBITMAP *dst, unsigned dst_width, unsigned dst_height); - - /// Performs vertical image filtering - void verticalFilter(FIBITMAP *src, unsigned src_width, unsigned src_height, FIBITMAP *dst, unsigned dst_width, unsigned dst_height); -}; - - - -#endif // _RESIZE_H_ -- cgit v1.2.3