⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resample.c

📁 M8手机图片查看器
💻 C
📖 第 1 页 / 共 2 页
字号:
// Resample.cpp : Defines the entry point for the DLL application.
//

#include <windows.h>
#define _USE_MATH_DEFINES
#define M_PI       3.14159265358979323846

#include <math.h>
#include <assert.h>
#include "Resample.h"

/* Quite arbitrary */
#define MAX_FILTER_RADIUS 16.0
#define MIN_RESAMPLE_WIDTH  0x00000001
#define MAX_RESAMPLE_WIDTH  0x00001000
#define MIN_RESAMPLE_HEIGHT 0x00000001
#define MAX_RESAMPLE_HEIGHT 0x00001000


/* RGBA */
#define COLOR_COMPONENTS  4

/* Each core filter has its own radius */
#define DEFAULT_LANCZOS8_RADIUS					8.0
#define DEFAULT_LANCZOS3_RADIUS					3.0
#define DEFAULT_HERMITE_RADIUS					1.0
#define DEFAULT_BOX_RADIUS							0.5
#define DEFAULT_TRIANGLE_RADIUS					1.0
#define DEFAULT_BELL_RADIUS							1.5
#define DEFAULT_CUBICSPLINE_RADIUS			2.0
#define DEFAULT_MITCHELL_RADIUS					2.0
#define DEFAULT_COSINE_RADIUS						1.0
#define DEFAULT_CATMULLROM_RADIUS				2.0
#define DEFAULT_QUADRATIC_RADIUS				1.5
#define DEFAULT_QUADRATICBSPLINE_RADIUS	1.5
#define DEFAULT_CUBICCONVOLUTION_RADIUS	3.0

/* Filter function type */
typedef double(* PFN_FILTER)(double);

/* Core filters */
static double _Lanczos8(double);
static double _Lanczos3(double);
static double _Hermite(double);
static double _Box(double);
static double _Triangle(double);
static double _Bell(double);
static double _CubicSpline(double);
static double _Mitchell(double);
static double _Cosine(double);
static double _CatmullRom(double);
static double _Quadratic(double);
static double _QuadraticBSpline(double);
static double _CubicConvolution(double);

/* helper functions */
static BOOL _setResampleFilter(DWORD dwFilter, PFN_FILTER * ppFnFilter, double * pdRadius);
#ifndef WINCE
static HBITMAP _createResampledBitmap(HDC hdc, HBITMAP hBmpSource, DWORD dwWidth, DWORD dwHeight, PFN_FILTER pFnFilter, double dRadius);
#else
static BOOL _shrinkRGB24(LPBYTE source, int srcwidth, int srcheight, LPBYTE destion, int destwidth, int destheight, PFN_FILTER filter, double radius);
#endif
static BOOL _fillBITMAPINFO(HBITMAP hBmp, BITMAPINFO * pBinfo);
static BOOL _resample(BYTE * ibuf, LONG iw, LONG ih, BYTE * obuf, LONG ow, LONG oh, PFN_FILTER pFnFilter, double dRadius);


#ifdef _MANAGED
#pragma managed(push, off)
#endif

BOOL APIENTRY DllMain(HMODULE hModule,
                      DWORD  ul_reason_for_call,
                      LPVOID lpReserved
                     ) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif


#ifndef WINCE
/*-> The exported functions */
/* CreateResampledBitmap
	Creates a resampled bitmap given the original one, neew dimensions, the index of the core filter.
	The function is in fact a wrapper for the pair of helper functions _setResampleFilter and _createResampledBitmap.
	ARGS:
	hdc [IN] given device context
	hBmpSource [IN] original bitmap handle
	dwWidth [IN] resampled bitmap width
	dwHeight [IN] resampled bitmap height
	dwFilter [IN] index of the choosen core filter
	RETURN VALUE:
	the handle (HBITMAP) of the resampled bitmap on success, NULL on failure
*/

RESAMPLE_API HBITMAP CreateResampledBitmap(HDC hdc,
        HBITMAP hBmpSource,
        DWORD dwWidth, DWORD dwHeight,
        DWORD dwFilter) {
    double(* pFnFilter)(double);
    double dRadius;
    if (_setResampleFilter(dwFilter, &pFnFilter, &dRadius) == FALSE) {
        SetLastError(E_UNABLE_TO_SET_FILTER);
        return NULL;
    }

    return _createResampledBitmap(hdc, hBmpSource, dwWidth, dwHeight, pFnFilter, dRadius);

}
#else
BOOL ShrinkRGB32(LPBYTE source, int srcwidth, int srcheight, LPBYTE destion, int destwidth, int destheight, unsigned filter) {
    BOOL Result = FALSE;

    double(* pFnFilter)(double);
    double dRadius;
    if (_setResampleFilter(filter, &pFnFilter, &dRadius) == FALSE) {
        SetLastError(E_UNABLE_TO_SET_FILTER);
        return FALSE;
    }

    return _shrinkRGB24(source, srcwidth, srcheight, destion, destwidth, destheight, pFnFilter, dRadius);
}

BOOL _shrinkRGB24(LPBYTE source, int srcwidth, int srcheight, LPBYTE destion, int destwidth, int destheight, PFN_FILTER filter, double radius) {


    BOOL Result = FALSE;
    if (_resample(source, srcwidth, srcheight,
                  destion, destwidth, destheight,
                  filter, radius) == FALSE) {
        SetLastError(E_RESAMPLE_ERROR);
        return Result;
    }

    return Result;
}
#endif


/* CreateResampledBitmap
	Creates a resampled bitmap given the original one, neew dimensions, the index of the core filter
	ARGS:
	hdc [IN] given device context
	hBmpSource [IN] original bitmap handle
	dwWidth [IN] resampled bitmap width
	dwHeight [IN] resampled bitmap height
	dwFilter [IN] index of the choosen core filter
	pFnCustomFilter [IN] custom filter function pointer
	dRadius [IN] radius of the custom filter
	RETURN VALUE:
	the handle (HBITMAP) of the resampled bitmap on success, NULL on failure
*/

#ifndef WINCE
RESAMPLE_API HBITMAP CreateUserFilterResampledBitmap(HDC hdc,
        HBITMAP hBmpSource,
        DWORD dwWidth, DWORD dwHeight,
        double(*pFnCustomFilter)(double), double dRadius) {
    if (! pFnCustomFilter || dRadius < 0.0 || dRadius > MAX_FILTER_RADIUS) {
        SetLastError(E_UNABLE_TO_SET_FILTER);
        return NULL;
    }
    return _createResampledBitmap(hdc, hBmpSource, dwWidth, dwHeight, pFnCustomFilter, dRadius);
}
#endif



/* Sets proper (core) filter and radius given filter index
		ARGS:
		dwFilter [IN] filter index
		ppFnFilter [OUT] filter function
		pdRadius [OUT] filter radius
*/
BOOL _setResampleFilter(DWORD dwFilter, PFN_FILTER * ppFnFilter, double * pdRadius) {
    BOOL fResult;

    fResult = TRUE;
    dwFilter = dwFilter % STOCK_FILTERS;
    switch (dwFilter) {
    case STOCK_FILTER_LANCZOS3:
        *ppFnFilter = _Lanczos3;
        *pdRadius = DEFAULT_LANCZOS3_RADIUS;
        break;
    case STOCK_FILTER_LANCZOS8:
        *ppFnFilter = _Lanczos8;
        *pdRadius = DEFAULT_LANCZOS8_RADIUS;
        break;
    case STOCK_FILTER_HERMITE:
        *ppFnFilter = _Hermite;
        *pdRadius = DEFAULT_HERMITE_RADIUS;
        break;
    case STOCK_FILTER_BOX:
        *ppFnFilter = _Box;
        *pdRadius = DEFAULT_BOX_RADIUS;
        break;
    case STOCK_FILTER_TRIANGLE:
        *ppFnFilter = _Triangle;
        *pdRadius = DEFAULT_TRIANGLE_RADIUS;
        break;
    case STOCK_FILTER_BELL:
        *ppFnFilter = _Bell;
        *pdRadius = DEFAULT_BELL_RADIUS;
        break;
    case STOCK_FILTER_CUBICSPLINE:
        *ppFnFilter = _CubicSpline;
        *pdRadius = DEFAULT_CUBICSPLINE_RADIUS;
        break;
    case STOCK_FILTER_MITCHELL:
        *ppFnFilter = _Mitchell;
        *pdRadius = DEFAULT_MITCHELL_RADIUS;
        break;
    case STOCK_FILTER_COSINE:
        *ppFnFilter = _Cosine;
        *pdRadius = DEFAULT_COSINE_RADIUS;
        break;
    case STOCK_FILTER_CATMULLROM:
        *ppFnFilter = _CatmullRom;
        *pdRadius = DEFAULT_CATMULLROM_RADIUS;
        break;
    case STOCK_FILTER_QUADRATIC:
        *ppFnFilter = _Quadratic;
        *pdRadius = DEFAULT_QUADRATIC_RADIUS;
        break;
    case STOCK_FILTER_QUADRATICBSPLINE:
        *ppFnFilter = _QuadraticBSpline;
        *pdRadius = DEFAULT_QUADRATICBSPLINE_RADIUS;
        break;
    case STOCK_FILTER_CUBICCONVOLUTION:
        *ppFnFilter = _CubicConvolution;
        *pdRadius = DEFAULT_CUBICCONVOLUTION_RADIUS;
        break;
    default:
        assert(0);
        fResult = FALSE;
    }
    return fResult;
}

#ifndef WINCE
/* Creates the resampled bitmap
		ARGS:
		hdc [IN] provided HDC
		hBmpSource [IN] original bitmap handle
		dwWidth [IN] resampled bitmap width
		dwHeight [IN] resampled bitmap height
		pnFnFilter [IN] filter function
		dRAdius [IN] filter radius
		RETURN VALUE:
		Handle (HBITMAP) of the resampled bitmap
*/

HBITMAP _createResampledBitmap(HDC hdc, HBITMAP hBmpSource,
                               DWORD dwWidth, DWORD dwHeight,
                               PFN_FILTER pFnFilter, double dRadius) {
    BOOL fResult;

    BITMAPINFO binfoSource;
    BYTE * pbSource;

    HBITMAP hBmpTarget;
    BITMAPINFO binfoTarget;
    BYTE * pbTarget;


    /* Bare initialization */
    fResult = FALSE;
    pbSource = NULL;


    hBmpTarget = NULL;
    pbTarget = NULL;

    /*<- Bare initialization */

    if (! pFnFilter) {
        SetLastError(E_UNABLE_TO_SET_FILTER);
        return FALSE;
    }

    if (! hBmpSource) {
        SetLastError(E_INVALID_BITMAP);
        return FALSE;
    }

    if (dwWidth < MIN_RESAMPLE_WIDTH) {
        dwWidth = MIN_RESAMPLE_WIDTH;
    } else if (dwWidth > MAX_RESAMPLE_WIDTH) {
        dwWidth = MAX_RESAMPLE_WIDTH;
    }

    if (dwHeight < MIN_RESAMPLE_HEIGHT) {
        dwHeight = MIN_RESAMPLE_HEIGHT;
    } else if (dwHeight > MAX_RESAMPLE_HEIGHT) {
        dwHeight = MAX_RESAMPLE_HEIGHT;
    }

    if (_fillBITMAPINFO(hBmpSource, &binfoSource) == FALSE) {
        SetLastError(E_INVALID_BITMAP_DATA);
        return FALSE;
    }


    /* Creating target bitmap */
    hBmpTarget = CreateCompatibleBitmap(hdc, dwWidth, dwHeight);
    if (! hBmpTarget) {

        SetLastError(E_UNABLE_TO_CREATE_BITMAP);
        return FALSE;
    }

    /* Getting info about the target bitmap */
    if (_fillBITMAPINFO(hBmpTarget, &binfoTarget) == FALSE) {
        SetLastError(E_INVALID_OUT_BITMAP_DATA);
        goto Cleanup;
    }

    /* Allocating buffer for the Source image bits */
    pbSource = GlobalAlloc(0, binfoSource.bmiHeader.biSizeImage);
    if (! pbSource) {
        SetLastError(E_MEMORY_ERROR);
        goto Cleanup;
    }

    /* Getting data of the source bitmap  */
    if (binfoSource.bmiHeader.biHeight != GetDIBits(hdc, hBmpSource, 0, binfoSource.bmiHeader.biHeight, pbSource, &binfoSource, DIB_RGB_COLORS)) {
        SetLastError(E_UNABLE_TO_LOAD_BITMAP_BITS);
        goto Cleanup;
    }

    /* Allocating  buffer for the Target image bits */
    pbTarget = GlobalAlloc(0, binfoTarget.bmiHeader.biSizeImage);
    if (! pbTarget) {
        SetLastError(E_MEMORY_ERROR);
        goto Cleanup;
    }

    if (_resample(pbSource, binfoSource.bmiHeader.biWidth, binfoSource.bmiHeader.biHeight,
                  pbTarget, binfoTarget.bmiHeader.biWidth, binfoTarget.bmiHeader.biHeight,
                  pFnFilter, dRadius) == FALSE) {
        SetLastError(E_RESAMPLE_ERROR);
        goto Cleanup;
    }

    if (binfoTarget.bmiHeader.biHeight != SetDIBits(hdc, hBmpTarget, 0, binfoTarget.bmiHeader.biHeight, pbTarget, &binfoTarget, DIB_RGB_COLORS)) {
        SetLastError(E_UNABLE_TO_SET_BITMAP);
        goto Cleanup;

    }

    fResult = TRUE;



Cleanup:

    if (pbSource) GlobalFree(pbSource);

    if (pbTarget) GlobalFree(pbTarget);


    if (fResult == FALSE) {
        if (hBmpTarget) {
            DeleteObject(hBmpTarget);
            hBmpTarget = NULL;
        }
    }


    return hBmpTarget;
}/* <- CreateResampledBitmap */
#endif // WINCE


/* _resample
  This function does the real resampling stuff.
	ARGS:
	ibuf [IN] pointer of original bitmap bits
	iw [IN] original image width
	ih [IN] original image height
	obuf [OUT] resampled image bits
	ow [IN] resampled image width
	oh [IN] resampled image height
	pFnFilter [IN] filter function pointer
	dRadius [IN] filter radius
	RETURN VALUE
	TRUE on success
*/
BOOL _resample(BYTE * ibuf, LONG iw, LONG ih, BYTE * obuf, LONG ow, LONG oh, PFN_FILTER pFnFilter, double dRadius) {
    BOOL fSuccess = FALSE;

    LONG i, j, n, c;
    double xScale, yScale;

    /* Alias (pointer to DWORD) for ibuf */
    DWORD * ib;
    /* Alias (pointer to DWORD ) for obuf */
    DWORD * ob;

    // Temporary values
    DWORD val;
    int col; /* This should remain int (a bit tricky stuff) */

    double * h_weight; // Weight contribution    [ow][MAX_CONTRIBS]
    LONG    * h_pixel; // Pixel that contributes [ow][MAX_CONTRIBS]
    LONG    * h_count; // How many contribution for the pixel [ow]
    double * h_wsum;   // Sum of weights [ow]

    double * v_weight; // Weight contribution    [oh][MAX_CONTRIBS]
    LONG   * v_pixel;  // Pixel that contributes [oh][MAX_CONTRIBS]
    LONG  * v_count;	 // How many contribution for the pixel [oh]
    double * v_wsum;   // Sum of weights [oh]

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -