You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3511 lines
94 KiB
3511 lines
94 KiB
//
|
|
// Sample code for using GDI+
|
|
//
|
|
// Revision History:
|
|
//
|
|
// 10/01/1999 Min Liu (minliu)
|
|
// Created it.
|
|
//
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <windows.h>
|
|
#include <commctrl.h>
|
|
#include <objbase.h>
|
|
#include <commdlg.h>
|
|
|
|
#include <initguid.h>
|
|
#include "imaging.h"
|
|
#include <gdiplus.h>
|
|
#include <gdiplusflat.h>
|
|
#include "frametest.h"
|
|
|
|
using namespace Gdiplus;
|
|
|
|
#include "../gpinit.inc"
|
|
|
|
#define MYWNDCLASSNAME "FrameTest"
|
|
#define K_DEFAULT_X 0
|
|
#define K_DEFAULT_Y 0
|
|
#define K_DEFAULT_WIDTH 300
|
|
#define K_DEFAULT_HEIGHT 300
|
|
#define MAX_FILENAME_LENGTH 1024
|
|
#define K_DEFAULT_DELAY 20
|
|
|
|
CHAR* g_pcAppName; // Application name
|
|
HINSTANCE g_hAppInstance; // Handle of the app instance
|
|
CHAR g_acImageName[MAX_PATH];// Current image filename
|
|
INT g_iCurrentPageIndex; // Current page/frame index (0 base)
|
|
UINT g_uiTotalPages = 0; // Total pages in current image
|
|
HWND g_hwndMain; // Handle to app's main window
|
|
HWND g_hwndStatus; // Handle to status window
|
|
HWND g_hwndDecoderDlg; // Handle to set color key dialog
|
|
HWND g_hwndColorMapDlg; // Handle to set color map dialog
|
|
HWND g_hwndAnnotationDlg; // Handle to annotation dialog
|
|
HWND g_hwndJpegSaveDlg; // Handle to JPEG save dialog
|
|
HWND g_hwndTiffSaveDlg; // Handle to TIFF save dialog
|
|
EncoderParameters* g_pEncoderParams = NULL;// Encoder parameters
|
|
|
|
//
|
|
// User preferred window size and initial position
|
|
//
|
|
INT g_iWinWidth = K_DEFAULT_WIDTH;
|
|
INT g_iWinHeight = K_DEFAULT_HEIGHT;
|
|
INT g_iWinX = K_DEFAULT_X;
|
|
INT g_iWinY = K_DEFAULT_Y;
|
|
|
|
//
|
|
// Image info
|
|
//
|
|
UINT g_ImageWidth; // Image width
|
|
UINT g_ImageHeight; // Image height
|
|
UINT g_ImageFlags; // Image flag
|
|
PixelFormat g_ImagePixelFormat; // Image pixel format
|
|
double g_ImageXDpi; // DPI info in X
|
|
double g_ImageYDpi; // DPI info in Y
|
|
GUID g_ImageRawDataFormat; // RAW data format
|
|
|
|
UINT g_uiDelay = K_DEFAULT_DELAY;
|
|
// Delay between frames for anima.
|
|
Image* g_pImage = NULL; // Pointer to current Image object
|
|
ImageAttributes* g_pDrawAttrib = NULL; // Pointer to draw attributes
|
|
PointF* g_pDestPoints = NULL; // Transformation points
|
|
INT g_DestPointCount = 0; // number of transformation points
|
|
REAL g_SourceX = NULL; // current image X offset
|
|
REAL g_SourceY = NULL; // current image Y offset
|
|
REAL g_SourceWidth = NULL; // current image width
|
|
REAL g_SourceHeight = NULL; // current image height
|
|
BOOL g_LoadImageWithICM = TRUE;
|
|
// Flag for loading image with ICM
|
|
// convertion or not
|
|
BOOL g_bRotated = FALSE;
|
|
|
|
REAL g_dScale = 1;
|
|
|
|
BOOL g_fFitToWindow_w = FALSE;
|
|
BOOL g_fFitToWindow_h = FALSE;
|
|
InterpolationMode g_InterpolationMode = InterpolationModeHighQualityBicubic;
|
|
WrapMode g_WrapMode = WrapModeTileFlipXY;
|
|
|
|
void
|
|
ValidateArguments(int argc,
|
|
char* argv[])
|
|
{
|
|
g_pcAppName = *argv++;
|
|
argc--;
|
|
|
|
while ( argc > 0 )
|
|
{
|
|
if ( strcmp(*argv, "-w") == 0 )
|
|
{
|
|
argc--;
|
|
argv++;
|
|
|
|
if ( argc == 0 )
|
|
{
|
|
// Not enough parameters
|
|
|
|
USAGE();
|
|
exit(1);
|
|
}
|
|
|
|
g_iWinWidth = atoi(*argv++);
|
|
argc--;
|
|
}
|
|
else if ( strcmp(*argv, "-h") == 0 )
|
|
{
|
|
argc--;
|
|
argv++;
|
|
|
|
if ( argc == 0 )
|
|
{
|
|
// Not enough parameters
|
|
|
|
USAGE();
|
|
exit(1);
|
|
}
|
|
|
|
g_iWinHeight = atoi(*argv++);
|
|
argc--;
|
|
}
|
|
else if ( strcmp(*argv, "-x") == 0 )
|
|
{
|
|
argc--;
|
|
argv++;
|
|
|
|
if ( argc == 0 )
|
|
{
|
|
// Not enough parameters
|
|
|
|
USAGE();
|
|
exit(1);
|
|
}
|
|
|
|
g_iWinX = atoi(*argv++);
|
|
argc--;
|
|
}
|
|
else if ( strcmp(*argv, "-y") == 0 )
|
|
{
|
|
argc--;
|
|
argv++;
|
|
|
|
if ( argc == 0 )
|
|
{
|
|
// Not enough parameters
|
|
|
|
USAGE();
|
|
exit(1);
|
|
}
|
|
|
|
g_iWinY = atoi(*argv++);
|
|
argc--;
|
|
}
|
|
else if ( strcmp(*argv, "-?") == 0 )
|
|
{
|
|
USAGE();
|
|
exit(1);
|
|
}
|
|
else
|
|
{
|
|
// Get the image name
|
|
|
|
strcpy(g_acImageName, *argv++);
|
|
VERBOSE(("Image file name %s\n",g_acImageName));
|
|
argc--;
|
|
}
|
|
}// while ( argc > 0 )
|
|
}// ValidateArguments()
|
|
|
|
// Update image info
|
|
|
|
BOOL
|
|
UpdateImageInfo()
|
|
{
|
|
SizeF sizeF;
|
|
|
|
g_ImageWidth = g_pImage->GetWidth();
|
|
g_ImageHeight = g_pImage->GetHeight();
|
|
g_ImageXDpi = g_pImage->GetVerticalResolution();
|
|
g_ImageYDpi = g_pImage->GetHorizontalResolution();
|
|
g_ImagePixelFormat = g_pImage->GetPixelFormat();
|
|
g_ImageFlags = g_pImage->GetFlags();
|
|
g_pImage->GetRawFormat(&g_ImageRawDataFormat);
|
|
|
|
return TRUE;
|
|
}// UpdateImageInfo()
|
|
|
|
//
|
|
// Force a refresh of the image window
|
|
//
|
|
inline VOID
|
|
RefreshImageDisplay()
|
|
{
|
|
SendMessage(g_hwndMain, WM_ERASEBKGND, WPARAM(GetDC(g_hwndMain)), NULL);
|
|
|
|
InvalidateRect(g_hwndMain, NULL, FALSE);
|
|
|
|
// Update window title
|
|
|
|
CHAR title[2 * MAX_PATH];
|
|
CHAR* p = title;
|
|
|
|
CHAR myChar = '%';
|
|
sprintf(p, "(%d%c) Page %d of image %s", (INT)(g_dScale * 100), myChar,
|
|
g_iCurrentPageIndex + 1, g_acImageName);
|
|
|
|
SetWindowText(g_hwndMain, title);
|
|
}// RefreshImageDisplay()
|
|
|
|
inline void
|
|
ResetImageAttribute()
|
|
{
|
|
if ( g_pDrawAttrib != NULL )
|
|
{
|
|
delete g_pDrawAttrib;
|
|
g_pDrawAttrib = NULL;
|
|
}
|
|
|
|
g_pDrawAttrib = new ImageAttributes();
|
|
|
|
g_pDrawAttrib->SetWrapMode(g_WrapMode, Color(0), FALSE);
|
|
}// ResetImageAttribute()
|
|
|
|
//
|
|
// Sets up the current page for decompressing in a multi-page image
|
|
//
|
|
VOID
|
|
SetCurrentPage()
|
|
{
|
|
// QueryFrame dimension info
|
|
|
|
UINT uiDimCount = g_pImage->GetFrameDimensionsCount();
|
|
|
|
GUID* pMyGuid = (GUID*)malloc(uiDimCount * sizeof(GUID));
|
|
if ( pMyGuid == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Status rCode = g_pImage->GetFrameDimensionsList(pMyGuid, uiDimCount);
|
|
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
return;
|
|
}
|
|
// Set current frame
|
|
|
|
rCode = g_pImage->SelectActiveFrame(pMyGuid, g_iCurrentPageIndex);
|
|
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("SelectActiveFrame() failed\n"));
|
|
free(pMyGuid);
|
|
return;
|
|
}
|
|
|
|
free(pMyGuid);
|
|
|
|
// Get image info for current frame
|
|
|
|
if ( UpdateImageInfo() == FALSE )
|
|
{
|
|
VERBOSE(("UpdateImageInfo() failed\n"));
|
|
return;
|
|
}
|
|
|
|
// Check if we need to set 'Fit window width"
|
|
// We will do a fit to window iff the "Scale factor is not set" and "Image
|
|
// is bigger than current window"
|
|
|
|
HMENU hMenu = GetMenu(g_hwndMain);
|
|
|
|
if ( ((INT)g_ImageWidth > g_iWinWidth)
|
|
||((INT)g_ImageHeight > g_iWinHeight) )
|
|
{
|
|
g_fFitToWindow_w = TRUE;
|
|
g_dScale = (REAL)g_iWinWidth / g_ImageWidth;
|
|
|
|
CheckMenuItem(hMenu, IDM_VIEW_ZOOM_FITWINDOW_W,
|
|
MF_BYCOMMAND | MF_CHECKED);
|
|
}
|
|
else
|
|
{
|
|
g_dScale = 1;
|
|
g_fFitToWindow_w = FALSE;
|
|
g_fFitToWindow_h = FALSE;
|
|
CheckMenuItem(hMenu, IDM_VIEW_ZOOM_FITWINDOW_W,
|
|
MF_BYCOMMAND | MF_UNCHECKED);
|
|
CheckMenuItem(hMenu, IDM_VIEW_ZOOM_FITWINDOW_H,
|
|
MF_BYCOMMAND | MF_UNCHECKED);
|
|
}
|
|
|
|
RefreshImageDisplay();
|
|
}// SetCurrentPage()
|
|
|
|
//
|
|
// Create an image object from a file
|
|
//
|
|
BOOL
|
|
OpenImageFile(
|
|
const CHAR* filename
|
|
)
|
|
{
|
|
if ( (NULL == filename) || (strlen(filename) < 1) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// We need to free the previous image resource and clean the draw attrib
|
|
|
|
if ( g_pImage != NULL )
|
|
{
|
|
delete g_pImage;
|
|
}
|
|
|
|
ResetImageAttribute();
|
|
|
|
if ( g_pDestPoints != NULL )
|
|
{
|
|
delete g_pDestPoints;
|
|
g_pDestPoints = NULL;
|
|
}
|
|
|
|
// Convert filename to a WCHAR
|
|
|
|
WCHAR namestr[MAX_FILENAME_LENGTH];
|
|
|
|
if ( !AnsiToUnicodeStr(filename, namestr, MAX_FILENAME_LENGTH) )
|
|
{
|
|
VERBOSE(("OpenImageFile:Convert %s to a WCHAR failed\n", filename));
|
|
return FALSE;
|
|
}
|
|
|
|
if ( g_LoadImageWithICM == TRUE )
|
|
{
|
|
g_pImage = new Image(namestr, g_LoadImageWithICM);
|
|
}
|
|
else
|
|
{
|
|
g_pImage = new Image(namestr);
|
|
}
|
|
|
|
UINT uiDimCount = g_pImage->GetFrameDimensionsCount();
|
|
|
|
GUID* pMyGuid = (GUID*)malloc(uiDimCount * sizeof(GUID));
|
|
if ( pMyGuid == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
Status rCode = g_pImage->GetFrameDimensionsList(pMyGuid, uiDimCount);
|
|
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Get total number of pages in this image
|
|
// !!!Todo need a for() loop here
|
|
|
|
g_uiTotalPages = g_pImage->GetFrameCount(pMyGuid);
|
|
if ( g_uiTotalPages == 0 )
|
|
{
|
|
// If the decoder doesn't support frame count query, we can just
|
|
// assume it has only 1 image. For example, gif decoder will fail
|
|
// if the query GUID is FRAMEDIM_PAGE
|
|
|
|
g_uiTotalPages = 1;
|
|
}
|
|
g_iCurrentPageIndex = 0;
|
|
|
|
if ( pMyGuid != NULL )
|
|
{
|
|
free(pMyGuid);
|
|
}
|
|
|
|
SetCurrentPage();
|
|
|
|
return TRUE;
|
|
}// OpenImageFile()
|
|
|
|
//
|
|
// Open image file
|
|
//
|
|
VOID
|
|
DoOpen(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
OPENFILENAME ofn;
|
|
|
|
ZeroMemory(&ofn, sizeof(ofn));
|
|
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hwnd;
|
|
ofn.hInstance = g_hAppInstance;
|
|
ofn.lpstrFile = g_acImageName;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrTitle = "Open Image File";
|
|
ofn.lpstrInitialDir = ".";
|
|
ofn.Flags = OFN_FILEMUSTEXIST;
|
|
g_acImageName[0] = '\0';
|
|
|
|
// Make up the file type filter string
|
|
|
|
ImageCodecInfo* codecs;
|
|
UINT count;
|
|
if ( g_pDestPoints != NULL )
|
|
{
|
|
free(g_pDestPoints);
|
|
}
|
|
g_DestPointCount = 0;
|
|
GpStatus status;
|
|
UINT cbCodecs = 0;
|
|
GetImageDecodersSize(&count, &cbCodecs);
|
|
codecs = static_cast<ImageCodecInfo *>(malloc (cbCodecs));
|
|
if (codecs == NULL)
|
|
{
|
|
return;
|
|
}
|
|
status = GetImageDecoders(count, cbCodecs, codecs);
|
|
if (status != Ok)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CHAR* filter = MakeFilterFromCodecs(count, codecs, TRUE);
|
|
|
|
if (codecs)
|
|
{
|
|
free(codecs);
|
|
}
|
|
|
|
if ( !filter )
|
|
{
|
|
VERBOSE(("DoOpen--MakeFilterFromCodecs() failed\n"));
|
|
return;
|
|
}
|
|
|
|
ofn.lpstrFilter = filter;
|
|
|
|
// Present the file/open dialog
|
|
|
|
if ( GetOpenFileName(&ofn) )
|
|
{
|
|
OpenImageFile(g_acImageName);
|
|
}
|
|
|
|
free(filter);
|
|
}// DoOpen()
|
|
|
|
//
|
|
// Open image file
|
|
//
|
|
VOID
|
|
DoOpenAudioFile(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
OPENFILENAME ofn;
|
|
char audioFileName[256];
|
|
|
|
ZeroMemory(&ofn, sizeof(ofn));
|
|
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hwnd;
|
|
ofn.hInstance = g_hAppInstance;
|
|
ofn.lpstrFile = audioFileName;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrTitle = "Attach Audio File To Image";
|
|
ofn.lpstrInitialDir = ".";
|
|
ofn.Flags = OFN_FILEMUSTEXIST;
|
|
g_acImageName[0] = '\0';
|
|
|
|
// Make up the file type filter string
|
|
|
|
ofn.lpstrFilter = ".wav";
|
|
|
|
// Present the file/open dialog
|
|
|
|
if ( GetOpenFileName(&ofn) )
|
|
{
|
|
UINT uiTextLength = strlen(audioFileName);
|
|
|
|
PropertyItem myItem;
|
|
myItem.id = PropertyTagExifRelatedWav;
|
|
myItem.length = uiTextLength;
|
|
myItem.type = TAG_TYPE_ASCII;
|
|
|
|
myItem.value = malloc(uiTextLength);
|
|
if ( myItem.value != NULL )
|
|
{
|
|
strcpy((char*)myItem.value, audioFileName);
|
|
|
|
Status rCode = g_pImage->SetPropertyItem(&myItem);
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("SetPropertyItem() failed\n"));
|
|
}
|
|
}
|
|
}
|
|
}// DoOpenAudioFile()
|
|
|
|
#define STEPS 100
|
|
|
|
VOID
|
|
CreateBackgroundBitmap()
|
|
{
|
|
BitmapData bmpData;
|
|
|
|
Bitmap* myBmp = new Bitmap(g_iWinWidth, g_iWinHeight, PIXFMT_32BPP_ARGB);
|
|
|
|
Rect rect(0, 0, g_iWinWidth, g_iWinHeight);
|
|
Status status = myBmp->LockBits(&rect,
|
|
ImageLockModeWrite,
|
|
PIXFMT_32BPP_ARGB,
|
|
&bmpData);
|
|
|
|
// Make a horizontal blue gradient
|
|
|
|
UINT x, y;
|
|
ARGB colors[STEPS];
|
|
|
|
for (x=0; x < STEPS; x++)
|
|
{
|
|
colors[x] = MAKEARGB(128, 0, 0, x * 255 / (STEPS-1));
|
|
}
|
|
|
|
for (y=0; y < STEPS; y++)
|
|
{
|
|
ARGB* p = (ARGB*)((BYTE*)bmpData.Scan0 + y * bmpData.Stride);
|
|
|
|
for (x=0; x < STEPS; x++)
|
|
{
|
|
*p++ = colors[(x+y) % STEPS];
|
|
}
|
|
}
|
|
|
|
status = myBmp->UnlockBits(&bmpData);
|
|
|
|
if ( g_pImage != NULL )
|
|
{
|
|
delete g_pImage;
|
|
g_pImage = NULL;
|
|
}
|
|
|
|
g_pImage = myBmp;
|
|
|
|
UpdateImageInfo();
|
|
|
|
return;
|
|
}// CreateBackgroundBitmap()
|
|
|
|
//
|
|
// Handle window repaint event
|
|
//
|
|
VOID
|
|
DoPaint(
|
|
HWND hwnd,
|
|
HDC *phdc = NULL
|
|
)
|
|
{
|
|
if ( g_pImage == NULL )
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
HDC hdc;
|
|
PAINTSTRUCT ps;
|
|
RECT rect;
|
|
ImageInfo imageInfo;
|
|
|
|
if (!phdc)
|
|
{
|
|
hdc = BeginPaint(hwnd, &ps);
|
|
}
|
|
else
|
|
{
|
|
hdc = *phdc;
|
|
}
|
|
|
|
// Get current window's client area. Used for paint later
|
|
|
|
GetClientRect(hwnd, &rect);
|
|
|
|
ULONG ulWinWidth = (ULONG)(rect.right - rect.left);
|
|
ULONG ulWinHeight = (ULONG)(rect.bottom - rect.top);
|
|
|
|
// Make up a dest rect that we need image to draw to
|
|
|
|
REAL dDestImageWidth = g_ImageWidth * g_dScale;
|
|
REAL dDestImageHeight = g_ImageHeight * g_dScale;
|
|
|
|
Rect dstRect(rect.left, rect.top, (UINT)(dDestImageWidth),
|
|
(UINT)(dDestImageHeight));
|
|
|
|
RectF srcRect;
|
|
Unit srcUnit;
|
|
|
|
g_pImage->GetBounds(&srcRect, &srcUnit);
|
|
|
|
Graphics* pGraphics = new Graphics(hdc);
|
|
if ( pGraphics == NULL )
|
|
{
|
|
VERBOSE(("DoPaint--new Graphics() failed"));
|
|
return;
|
|
}
|
|
|
|
pGraphics->SetInterpolationMode(g_InterpolationMode);
|
|
|
|
// Width and height, in pixel, of the src image need to be drawn
|
|
|
|
UINT uiImageWidth = g_ImageWidth;
|
|
UINT uiImageHeight = g_ImageHeight;
|
|
|
|
// Adjust the src image region need to be drawn.
|
|
// If the image is bigger than the viewable area, we just need to
|
|
// paint partial image, the viewable size
|
|
#if 0
|
|
if ( ulWinWidth < dDestImageWidth )
|
|
{
|
|
uiImageWidth = (UINT)(ulWinWidth / g_dScale);
|
|
}
|
|
|
|
if ( ulWinHeight < uiImageHeight )
|
|
{
|
|
uiImageHeight = (UINT)(ulWinHeight / g_dScale);
|
|
}
|
|
#endif
|
|
|
|
if ( (g_DestPointCount == 0) && (g_SourceWidth == 0) )
|
|
{
|
|
// Simple case, draw to destRect
|
|
|
|
pGraphics->DrawImage(g_pImage,
|
|
dstRect,
|
|
(UINT)srcRect.GetLeft(),
|
|
(UINT)srcRect.GetTop(),
|
|
uiImageWidth,
|
|
uiImageHeight,
|
|
UnitPixel,
|
|
g_pDrawAttrib,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
else if ( (g_DestPointCount == 0) && (g_SourceWidth != 0) )
|
|
{
|
|
// This case will allow cropping, etc.
|
|
|
|
pGraphics->DrawImage(g_pImage,
|
|
dstRect,
|
|
(int)g_SourceX,
|
|
(int)g_SourceY,
|
|
(int)g_SourceWidth,
|
|
(int)g_SourceHeight,
|
|
UnitPixel,
|
|
g_pDrawAttrib,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
else if ( (g_DestPointCount != 0) && (g_SourceWidth == 0) )
|
|
{
|
|
// This case will allow cropping, etc.
|
|
|
|
if ( g_DestPointCount == 4 )
|
|
{
|
|
// Hack until draw image support 4 transform points
|
|
|
|
pGraphics->DrawImage(g_pImage,
|
|
g_pDestPoints,
|
|
3,
|
|
0,
|
|
0,
|
|
(float)uiImageWidth,
|
|
(float)uiImageHeight,
|
|
UnitPixel,
|
|
g_pDrawAttrib,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
pGraphics->DrawImage(g_pImage,
|
|
g_pDestPoints,
|
|
g_DestPointCount,
|
|
0,
|
|
0,
|
|
(float)uiImageWidth,
|
|
(float)uiImageHeight,
|
|
UnitPixel,
|
|
g_pDrawAttrib,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This case will allow both cropping and rotation
|
|
|
|
if ( g_DestPointCount == 4 )
|
|
{
|
|
// Hack until DrawImage supports 4 transform points
|
|
|
|
pGraphics->DrawImage(g_pImage,
|
|
g_pDestPoints,
|
|
3,
|
|
g_SourceX,
|
|
g_SourceY,
|
|
g_SourceWidth,
|
|
g_SourceHeight,
|
|
UnitPixel,
|
|
g_pDrawAttrib,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
pGraphics->DrawImage(g_pImage,
|
|
g_pDestPoints,
|
|
g_DestPointCount,
|
|
g_SourceX,
|
|
g_SourceY,
|
|
g_SourceWidth,
|
|
g_SourceHeight,
|
|
UnitPixel,
|
|
g_pDrawAttrib,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
delete pGraphics;
|
|
|
|
// FillRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
|
|
|
if (!phdc)
|
|
EndPaint(hwnd, &ps);
|
|
}
|
|
}// DoPaint()
|
|
|
|
VOID
|
|
DoPrint(HWND hwnd)
|
|
{
|
|
PRINTDLG printdlg;
|
|
memset(&printdlg, 0, sizeof(PRINTDLG));
|
|
printdlg.lStructSize = sizeof(PRINTDLG);
|
|
printdlg.hwndOwner = hwnd;
|
|
DEVMODE dm;
|
|
memset(&dm, 0, sizeof(DEVMODE));
|
|
dm.dmICMMethod = DMICMMETHOD_SYSTEM;
|
|
printdlg.hDevMode = &dm;
|
|
printdlg.hDevNames = NULL;
|
|
printdlg.hDC = NULL;
|
|
printdlg.Flags = PD_RETURNDC;
|
|
if (PrintDlg(&printdlg))
|
|
{
|
|
DOCINFO di;
|
|
memset(&di, 0, sizeof(DOCINFO));
|
|
di.cbSize = sizeof(DOCINFO);
|
|
di.lpszDocName = g_acImageName;
|
|
di.lpszOutput = (LPTSTR)NULL;
|
|
di.lpszDatatype = (LPTSTR)NULL;
|
|
di.fwType = 0;
|
|
StartDoc(printdlg.hDC, &di);
|
|
StartPage(printdlg.hDC);
|
|
|
|
// Use GDI+ printing code to do the real print job
|
|
|
|
DoPaint(hwnd, &printdlg.hDC);
|
|
|
|
EndPage(printdlg.hDC);
|
|
EndDoc(printdlg.hDC);
|
|
}
|
|
else
|
|
{
|
|
DWORD error = CommDlgExtendedError();
|
|
if (error)
|
|
{
|
|
char errormessage[100];
|
|
sprintf(errormessage, "PrintDlg error: %d", error);
|
|
MessageBox(hwnd, errormessage, "PrintDlg error", MB_OK);
|
|
}
|
|
}
|
|
}// DoPrint()
|
|
|
|
BOOL
|
|
SetJpegDefaultParameters()
|
|
{
|
|
// Set default quality level as 100, unsigned value
|
|
|
|
SetDlgItemInt(g_hwndJpegSaveDlg, IDC_SAVEJPEG_QEFIELD, 100, FALSE);
|
|
|
|
// Set No transform as default
|
|
|
|
CheckRadioButton(g_hwndJpegSaveDlg,
|
|
IDC_SAVEJPEG_R90,
|
|
IDC_SAVEJPEG_NOTRANSFORM,
|
|
IDC_SAVEJPEG_NOTRANSFORM);
|
|
|
|
return TRUE;
|
|
}// SetJpegDefaultParameters()
|
|
|
|
BOOL
|
|
SetTiffDefaultParameters()
|
|
{
|
|
// Set default color depth and compression method as the same as current
|
|
// image
|
|
|
|
CheckRadioButton(g_hwndTiffSaveDlg,
|
|
IDC_SAVETIFF_1BPP,
|
|
IDC_SAVETIFF_ASSOURCE,
|
|
IDC_SAVETIFF_ASSOURCE);
|
|
|
|
CheckRadioButton(g_hwndTiffSaveDlg,
|
|
IDC_SAVETIFF_CCITT4,
|
|
IDC_SAVETIFF_COMPASSOURCE,
|
|
IDC_SAVETIFF_COMPASSOURCE);
|
|
|
|
// If the source image is multi-frame, check "save as multi-frame" on
|
|
|
|
if ( g_uiTotalPages > 1 )
|
|
{
|
|
SendDlgItemMessage(g_hwndTiffSaveDlg, IDC_SAVETIFF_MULTIFRAME,
|
|
BM_SETCHECK, 0, 0);
|
|
}
|
|
|
|
return TRUE;
|
|
}// SetTiffDefaultParameters()
|
|
|
|
/*****************************************************************************\
|
|
*
|
|
* FUNCTION : DecoderParamDlgProc(hDlg, uiMessage, wParam, lParam)
|
|
*
|
|
* PURPOSE : Dialog function for the Decoder Parameter settings dialog
|
|
*
|
|
\*****************************************************************************/
|
|
INT_PTR CALLBACK
|
|
DecoderParamDlgProc(
|
|
HWND hDlg,
|
|
UINT uiMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch ( uiMessage )
|
|
{
|
|
case WM_COMMAND:
|
|
switch ( LOWORD(wParam) )
|
|
{
|
|
case IDC_COLORKEY_CANCEL:
|
|
// End the dialog and return FALSE. So we won't do anything
|
|
|
|
EndDialog(hDlg, FALSE);
|
|
|
|
break;
|
|
|
|
case IDC_COLORKEY_OK:
|
|
// User hit the OK button. First, we need to get the values user
|
|
// entered
|
|
|
|
char acTemp[20];
|
|
UINT uiTempLow;
|
|
UINT uiTempHigh;
|
|
|
|
UINT TransKeyLow = 0x0;
|
|
UINT TransKeyHigh = 0x0;
|
|
|
|
// Get the RED key
|
|
|
|
uiTempLow = GetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_LOWER_RFIELD,
|
|
NULL, FALSE);
|
|
uiTempHigh = GetDlgItemInt(g_hwndDecoderDlg,
|
|
IDC_TRANS_HIGHER_RFIELD, NULL, FALSE);
|
|
|
|
if ( (uiTempLow > 255) || (uiTempHigh > 255)
|
|
||(uiTempLow > uiTempHigh) )
|
|
{
|
|
VERBOSE(("Input key value should be within 0 to 255"));
|
|
VERBOSE(("Lower key should be smaller or equal to higher key"));
|
|
|
|
break;
|
|
}
|
|
|
|
TransKeyLow = ((uiTempLow & 0xff) << 16);
|
|
TransKeyHigh = ((uiTempHigh & 0xff) << 16);
|
|
|
|
// Get the Green key
|
|
|
|
uiTempLow = GetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_LOWER_GFIELD,
|
|
NULL, FALSE);
|
|
uiTempHigh = GetDlgItemInt(g_hwndDecoderDlg,
|
|
IDC_TRANS_HIGHER_GFIELD, NULL, FALSE);
|
|
|
|
if ( (uiTempLow > 255)
|
|
||(uiTempHigh > 255)
|
|
||(uiTempLow > uiTempHigh) )
|
|
{
|
|
VERBOSE(("Input key value should be within 0 to 255"));
|
|
VERBOSE(("Lower key should be smaller or equal to higher key"));
|
|
|
|
break;
|
|
}
|
|
|
|
TransKeyLow |= ((uiTempLow & 0xff) << 8);
|
|
TransKeyHigh |= ((uiTempHigh & 0xff) << 8);
|
|
|
|
// Get the Blue key
|
|
|
|
uiTempLow = GetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_LOWER_BFIELD,
|
|
NULL, FALSE);
|
|
uiTempHigh = GetDlgItemInt(g_hwndDecoderDlg,
|
|
IDC_TRANS_HIGHER_BFIELD, NULL, FALSE);
|
|
|
|
if ( (uiTempLow > 255)
|
|
||(uiTempHigh > 255)
|
|
||(uiTempLow > uiTempHigh) )
|
|
{
|
|
VERBOSE(("Input key value should be within 0 to 255"));
|
|
VERBOSE(("Lower key should be smaller or equal to higher key"));
|
|
|
|
break;
|
|
}
|
|
|
|
TransKeyLow |= (uiTempLow & 0xff);
|
|
TransKeyHigh |= (uiTempHigh & 0xff);
|
|
|
|
// Get the C key
|
|
|
|
uiTempLow = GetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_LOWER_CFIELD,
|
|
NULL, FALSE);
|
|
uiTempHigh = GetDlgItemInt(g_hwndDecoderDlg,
|
|
IDC_TRANS_HIGHER_CFIELD, NULL, FALSE);
|
|
|
|
if ( (uiTempLow > 255)
|
|
||(uiTempHigh > 255)
|
|
||(uiTempLow > uiTempHigh) )
|
|
{
|
|
VERBOSE(("Input key value should be within 0 to 255"));
|
|
VERBOSE(("Lower key should be smaller or equal to higher key"));
|
|
|
|
break;
|
|
}
|
|
|
|
TransKeyLow |= ((uiTempLow & 0xff) << 24);
|
|
TransKeyHigh |= ((uiTempHigh & 0xff) << 24);
|
|
|
|
// Up to this point, the TRANSKEY, lower and higher, should be in
|
|
// the format of 0x00RRGGBB for RGB image or 0xCCMMYYKK for CMYK
|
|
// image
|
|
|
|
// Set draw attributes
|
|
|
|
if ( g_pDrawAttrib != NULL )
|
|
{
|
|
delete g_pDrawAttrib;
|
|
}
|
|
|
|
g_pDrawAttrib = new ImageAttributes();
|
|
|
|
Color lowKey(TransKeyLow);
|
|
Color highKey(TransKeyHigh);
|
|
|
|
g_pDrawAttrib->SetColorKey(lowKey, highKey);
|
|
|
|
RefreshImageDisplay();
|
|
|
|
EndDialog(hDlg, TRUE);
|
|
|
|
break;
|
|
}// switch on WM_COMMAND
|
|
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
// Remember the dialog handle so that we can use it to deal with items
|
|
// in this dialog
|
|
|
|
g_hwndDecoderDlg = hDlg;
|
|
|
|
// Set initial values
|
|
|
|
SetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_LOWER_RFIELD, 250, FALSE);
|
|
SetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_LOWER_GFIELD, 250, FALSE);
|
|
SetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_LOWER_BFIELD, 250, FALSE);
|
|
SetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_LOWER_CFIELD, 250, FALSE);
|
|
SetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_HIGHER_RFIELD, 255, FALSE);
|
|
SetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_HIGHER_GFIELD, 255, FALSE);
|
|
SetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_HIGHER_BFIELD, 255, FALSE);
|
|
SetDlgItemInt(g_hwndDecoderDlg, IDC_TRANS_HIGHER_CFIELD, 255, FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}// DecoderParamDlgProc()
|
|
|
|
INT_PTR CALLBACK
|
|
ColorMapDlgProc(
|
|
HWND hDlg,
|
|
UINT uiMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch ( uiMessage )
|
|
{
|
|
case WM_COMMAND:
|
|
switch ( LOWORD(wParam) )
|
|
{
|
|
case IDC_COLORMAP_CANCEL:
|
|
// End the dialog and return FALSE. So we won't do anything
|
|
|
|
EndDialog(hDlg, FALSE);
|
|
|
|
break;
|
|
|
|
case IDC_COLORMAP_OK:
|
|
// User hit the OK button. First, we need to get the values user
|
|
// entered
|
|
|
|
if ( NULL == g_pImage )
|
|
{
|
|
// If there is no image, just close the dialog
|
|
|
|
EndDialog(hDlg, TRUE);
|
|
|
|
break;
|
|
}
|
|
|
|
char acTemp[20];
|
|
UINT uiOldR;
|
|
UINT uiNewR;
|
|
UINT uiOldG;
|
|
UINT uiNewG;
|
|
UINT uiOldB;
|
|
UINT uiNewB;
|
|
UINT uiOldA;
|
|
UINT uiNewA;
|
|
|
|
// Get the RED key
|
|
|
|
uiOldR = GetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_OLD_RFIELD,
|
|
NULL, FALSE);
|
|
uiNewR = GetDlgItemInt(g_hwndColorMapDlg,
|
|
IDC_MAP_NEW_RFIELD, NULL, FALSE);
|
|
|
|
if ( (uiOldR > 255) || (uiNewR > 255) )
|
|
{
|
|
VERBOSE(("Input key value should be within 0 to 255"));
|
|
break;
|
|
}
|
|
|
|
// Get the Green key
|
|
|
|
uiOldG = GetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_OLD_GFIELD,
|
|
NULL, FALSE);
|
|
uiNewG = GetDlgItemInt(g_hwndColorMapDlg,
|
|
IDC_MAP_NEW_GFIELD, NULL, FALSE);
|
|
|
|
if ( (uiOldG > 255) || (uiNewG > 255) )
|
|
{
|
|
VERBOSE(("Input key value should be within 0 to 255"));
|
|
break;
|
|
}
|
|
|
|
// Get the Blue key
|
|
|
|
uiOldB = GetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_OLD_BFIELD,
|
|
NULL, FALSE);
|
|
uiNewB = GetDlgItemInt(g_hwndColorMapDlg,
|
|
IDC_MAP_NEW_BFIELD, NULL, FALSE);
|
|
|
|
if ( (uiOldB > 255) || (uiNewB > 255) )
|
|
{
|
|
VERBOSE(("Input key value should be within 0 to 255"));
|
|
break;
|
|
}
|
|
|
|
// Get the A key
|
|
|
|
uiOldA = GetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_OLD_AFIELD,
|
|
NULL, FALSE);
|
|
uiNewA = GetDlgItemInt(g_hwndColorMapDlg,
|
|
IDC_MAP_NEW_AFIELD, NULL, FALSE);
|
|
|
|
if ( (uiOldA > 255) || (uiNewA > 255) )
|
|
{
|
|
VERBOSE(("Input key value should be within 0 to 255"));
|
|
break;
|
|
}
|
|
|
|
// Set draw attributes
|
|
|
|
if ( g_pDrawAttrib == NULL )
|
|
{
|
|
g_pDrawAttrib = new ImageAttributes();
|
|
if ( g_pDrawAttrib == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
ColorMap myColorMap;
|
|
Color oldColor((BYTE)uiOldA, (BYTE)uiOldR, (BYTE)uiOldG,
|
|
(BYTE)uiOldB);
|
|
Color newColor((BYTE)uiNewA, (BYTE)uiNewR, (BYTE)uiNewG,
|
|
(BYTE)uiNewB);
|
|
|
|
myColorMap.oldColor = oldColor;
|
|
myColorMap.newColor = newColor;
|
|
|
|
g_pDrawAttrib->SetRemapTable(1, &myColorMap, ColorAdjustTypeBitmap);
|
|
|
|
RefreshImageDisplay();
|
|
EndDialog(hDlg, TRUE);
|
|
|
|
break;
|
|
}// switch()
|
|
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
// Remember the dialog handle so that we can use it to deal with items
|
|
// in this dialog
|
|
|
|
g_hwndColorMapDlg = hDlg;
|
|
|
|
// Set initial values
|
|
|
|
SetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_OLD_RFIELD, 255, FALSE);
|
|
SetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_OLD_GFIELD, 0, FALSE);
|
|
SetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_OLD_BFIELD, 0, FALSE);
|
|
SetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_OLD_AFIELD, 255, FALSE);
|
|
SetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_NEW_RFIELD, 0, FALSE);
|
|
SetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_NEW_GFIELD, 255, FALSE);
|
|
SetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_NEW_BFIELD, 0, FALSE);
|
|
SetDlgItemInt(g_hwndColorMapDlg, IDC_MAP_NEW_AFIELD, 255, FALSE);
|
|
|
|
return TRUE;
|
|
}// switch ( uiMessage )
|
|
|
|
return FALSE;
|
|
}// ColorMapDlgProc()
|
|
|
|
INT_PTR CALLBACK
|
|
AnnotationDlgProc(
|
|
HWND hDlg,
|
|
UINT uiMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch ( uiMessage )
|
|
{
|
|
case WM_COMMAND:
|
|
switch ( LOWORD(wParam) )
|
|
{
|
|
case IDC_ANNOTATION_CANCEL:
|
|
// End the dialog and return FALSE. So we won't do anything
|
|
|
|
EndDialog(hDlg, FALSE);
|
|
|
|
break;
|
|
|
|
case IDC_ANNOTATION_OK:
|
|
// User hit the OK button. First, we need to get the values user
|
|
// entered
|
|
|
|
if ( NULL == g_pImage )
|
|
{
|
|
// If there is no image, just close the dialog
|
|
|
|
EndDialog(hDlg, TRUE);
|
|
|
|
break;
|
|
}
|
|
|
|
char acTemp[200];
|
|
UINT uiTextLength = 0;
|
|
|
|
uiTextLength = GetDlgItemText(g_hwndAnnotationDlg,
|
|
IDC_ANNOTATION_EDITOR, acTemp, 200);
|
|
|
|
if ( uiTextLength > 0 )
|
|
{
|
|
// Add 1 for the NULL terminator
|
|
|
|
uiTextLength++;
|
|
|
|
PropertyItem myItem;
|
|
myItem.id = PropertyTagExifUserComment;
|
|
myItem.length = uiTextLength;
|
|
myItem.type = TAG_TYPE_ASCII;
|
|
|
|
myItem.value = malloc(uiTextLength);
|
|
if ( myItem.value != NULL )
|
|
{
|
|
strcpy((char*)myItem.value, acTemp);
|
|
|
|
Status rCode = g_pImage->SetPropertyItem(&myItem);
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("SetPropertyItem() failed\n"));
|
|
}
|
|
|
|
free(myItem.value);
|
|
}
|
|
}
|
|
|
|
EndDialog(hDlg, TRUE);
|
|
|
|
break;
|
|
}// switch()
|
|
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
// Remember the dialog handle so that we can use it to deal with items
|
|
// in this dialog
|
|
|
|
g_hwndAnnotationDlg = hDlg;
|
|
|
|
// Check to see if the image has annotation in it
|
|
|
|
// Check the size for this property item
|
|
|
|
if ( g_pImage != NULL )
|
|
{
|
|
UINT uiItemSize = g_pImage->GetPropertyItemSize(
|
|
PropertyTagExifUserComment);
|
|
|
|
if ( uiItemSize != 0 )
|
|
{
|
|
// Allocate memory and get this property item
|
|
|
|
PropertyItem* pBuffer = (PropertyItem*)malloc(uiItemSize);
|
|
if ( pBuffer == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( g_pImage->GetPropertyItem(PropertyTagExifUserComment,
|
|
uiItemSize, pBuffer) == Ok )
|
|
{
|
|
// Set initial values
|
|
|
|
SetDlgItemText(g_hwndAnnotationDlg, IDC_ANNOTATION_EDITOR,
|
|
(char*)pBuffer->value);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
// Can't get property item. Something wrong
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No this property item, just initialize it with NULL
|
|
|
|
SetDlgItemText(g_hwndAnnotationDlg, IDC_ANNOTATION_EDITOR, "");
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}// switch ( uiMessage )
|
|
|
|
return FALSE;
|
|
}// AnnotationDlgProc()
|
|
|
|
#define NO_TRANSFORM 9999
|
|
|
|
/*****************************************************************************\
|
|
*
|
|
* FUNCTION : JpegSaveDlgProc(hDlg, uiMessage, wParam, lParam)
|
|
*
|
|
* PURPOSE : Dialog function for the Encoder Parameter settings dialog
|
|
*
|
|
\*****************************************************************************/
|
|
INT_PTR CALLBACK
|
|
JpegSaveDlgProc(
|
|
HWND hDlg,
|
|
UINT uiMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
static ULONG flagValueTransform = NO_TRANSFORM; // No transform at all
|
|
|
|
switch ( uiMessage )
|
|
{
|
|
case WM_COMMAND:
|
|
switch ( LOWORD(wParam) )
|
|
{
|
|
case IDC_SAVEJPEG_CANCEL:
|
|
// End the dialog and return FALSE. So we won't save this image
|
|
|
|
EndDialog(hDlg, FALSE);
|
|
|
|
break;
|
|
|
|
case IDC_SAVEJPEG_OK:
|
|
// User hit the OK button. First, we need to set the EncoderParam
|
|
// based on user selection
|
|
|
|
if ( g_pImage == NULL )
|
|
{
|
|
VERBOSE(("EncoderParamDlgProc: No image avail\n"));
|
|
EndDialog(hDlg, FALSE);
|
|
}
|
|
else
|
|
{
|
|
if ( g_pEncoderParams != NULL )
|
|
{
|
|
free(g_pEncoderParams);
|
|
g_pEncoderParams = NULL;
|
|
}
|
|
|
|
if ( flagValueTransform != NO_TRANSFORM )
|
|
{
|
|
// User has set lossless transform, so we need set encoder
|
|
// parameter
|
|
|
|
g_pEncoderParams =
|
|
(EncoderParameters*)malloc(sizeof(EncoderParameters));
|
|
|
|
g_pEncoderParams->Parameter[0].Guid = EncoderTransformation;
|
|
g_pEncoderParams->Parameter[0].Type =
|
|
EncoderParameterValueTypeLong;
|
|
g_pEncoderParams->Parameter[0].NumberOfValues = 1;
|
|
g_pEncoderParams->Parameter[0].Value =
|
|
(VOID*)&flagValueTransform;
|
|
g_pEncoderParams->Count = 1;
|
|
}
|
|
|
|
EndDialog(hDlg, TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case IDC_SAVEJPEG_R90:
|
|
flagValueTransform = EncoderValueTransformRotate90;
|
|
break;
|
|
|
|
case IDC_SAVEJPEG_R180:
|
|
flagValueTransform = EncoderValueTransformRotate180;
|
|
break;
|
|
|
|
case IDC_SAVEJPEG_R270:
|
|
flagValueTransform = EncoderValueTransformRotate270;
|
|
break;
|
|
|
|
case IDC_SAVEJPEG_HFLIP:
|
|
flagValueTransform = EncoderValueTransformFlipHorizontal;
|
|
break;
|
|
|
|
case IDC_SAVEJPEG_VFLIP:
|
|
flagValueTransform = EncoderValueTransformFlipVertical;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
// Remember the dialog handle so that we can use it to deal with items
|
|
// in this dialog
|
|
|
|
g_hwndJpegSaveDlg = hDlg;
|
|
flagValueTransform = NO_TRANSFORM;
|
|
|
|
SetJpegDefaultParameters();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}// JpegSaveDlgProc()
|
|
|
|
/*****************************************************************************\
|
|
*
|
|
* FUNCTION : TiffSaveDlgProc(hDlg, uiMessage, wParam, lParam)
|
|
*
|
|
* PURPOSE : Dialog function for the Encoder Parameter settings dialog
|
|
*
|
|
\*****************************************************************************/
|
|
INT_PTR CALLBACK
|
|
TiffSaveDlgProc(
|
|
HWND hDlg,
|
|
UINT uiMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
static PixelFormat flagColorDepth = g_ImagePixelFormat; // Default color depth
|
|
static compressMethod = 0;
|
|
static ULONG colorTemp = 0;
|
|
|
|
switch ( uiMessage )
|
|
{
|
|
case WM_COMMAND:
|
|
switch ( LOWORD(wParam) )
|
|
{
|
|
case IDC_SAVETIFFDLG_CANCEL:
|
|
// End the dialog and return FALSE. So we won't save this image
|
|
|
|
EndDialog(hDlg, FALSE);
|
|
|
|
break;
|
|
|
|
case IDC_SAVETIFFDLG_OK:
|
|
{
|
|
// User hit the OK button. First, we need to set the EncoderParam
|
|
// based on user selection
|
|
|
|
if ( g_pImage == NULL )
|
|
{
|
|
VERBOSE(("EncoderParamDlgProc: No image avail\n"));
|
|
EndDialog(hDlg, FALSE);
|
|
}
|
|
else
|
|
{
|
|
if ( g_pEncoderParams != NULL )
|
|
{
|
|
free(g_pEncoderParams);
|
|
g_pEncoderParams = NULL;
|
|
}
|
|
|
|
UINT numOfParamSet = 0;
|
|
|
|
if ( flagColorDepth != g_ImagePixelFormat )
|
|
{
|
|
numOfParamSet++;
|
|
}
|
|
|
|
if ( compressMethod != 0 )
|
|
{
|
|
numOfParamSet++;
|
|
}
|
|
|
|
if ( numOfParamSet > 0 )
|
|
{
|
|
int iTemp = 0;
|
|
|
|
// User has set new color depth, so we need set encoder
|
|
// parameter for it
|
|
|
|
g_pEncoderParams =
|
|
(EncoderParameters*)malloc(sizeof(EncoderParameters) +
|
|
numOfParamSet * sizeof(EncoderParameter));
|
|
|
|
if ( compressMethod != 0 )
|
|
{
|
|
// Set compression method
|
|
|
|
g_pEncoderParams->Parameter[iTemp].Guid =
|
|
EncoderCompression;
|
|
g_pEncoderParams->Parameter[iTemp].Type =
|
|
EncoderParameterValueTypeLong;
|
|
g_pEncoderParams->Parameter[iTemp].NumberOfValues = 1;
|
|
g_pEncoderParams->Parameter[iTemp].Value =
|
|
(VOID*)&compressMethod;
|
|
|
|
iTemp++;
|
|
g_pEncoderParams->Count = iTemp;
|
|
}
|
|
|
|
if ( flagColorDepth != g_ImagePixelFormat )
|
|
{
|
|
// Set color depth
|
|
|
|
g_pEncoderParams->Parameter[iTemp].Guid =
|
|
EncoderColorDepth;
|
|
g_pEncoderParams->Parameter[iTemp].Type =
|
|
EncoderParameterValueTypeLong;
|
|
g_pEncoderParams->Parameter[iTemp].NumberOfValues = 1;
|
|
g_pEncoderParams->Parameter[iTemp].Value =
|
|
(VOID*)&colorTemp;
|
|
|
|
iTemp++;
|
|
g_pEncoderParams->Count = iTemp;
|
|
}
|
|
}// if ( numOfParamSet > 0 )
|
|
|
|
EndDialog(hDlg, TRUE);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case IDC_SAVETIFF_1BPP:
|
|
flagColorDepth = PIXFMT_1BPP_INDEXED;
|
|
colorTemp = 1;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_4BPP:
|
|
flagColorDepth = PIXFMT_4BPP_INDEXED;
|
|
colorTemp = 4;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_8BPP:
|
|
flagColorDepth = PIXFMT_8BPP_INDEXED;
|
|
colorTemp = 8;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_24BPP:
|
|
flagColorDepth = PIXFMT_24BPP_RGB;
|
|
colorTemp = 24;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_32ARGB:
|
|
flagColorDepth = PIXFMT_32BPP_ARGB;
|
|
colorTemp = 32;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_CCITT3:
|
|
compressMethod = EncoderValueCompressionCCITT3;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_CCITT4:
|
|
compressMethod = EncoderValueCompressionCCITT4;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_RLE:
|
|
compressMethod = EncoderValueCompressionRle;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_LZW:
|
|
compressMethod = EncoderValueCompressionLZW;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_UNCOMPRESSED:
|
|
compressMethod = EncoderValueCompressionNone;
|
|
break;
|
|
|
|
case IDC_SAVETIFF_COMPASSOURCE:
|
|
compressMethod = 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_INITDIALOG:
|
|
// Remember the dialog handle so that we can use it to deal with items
|
|
// in this dialog
|
|
|
|
g_hwndTiffSaveDlg = hDlg;
|
|
flagColorDepth = g_ImagePixelFormat; // Default color depth
|
|
compressMethod = 0;
|
|
colorTemp = 0;
|
|
|
|
SetTiffDefaultParameters();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}// TiffSaveDlgProc()
|
|
|
|
BOOL
|
|
StartSaveImage(
|
|
const CHAR* filename,
|
|
const CLSID* clsid
|
|
)
|
|
{
|
|
// Convert filename to a WCHAR
|
|
|
|
WCHAR namestr[MAX_FILENAME_LENGTH];
|
|
|
|
if ( !AnsiToUnicodeStr(filename, namestr, MAX_FILENAME_LENGTH) )
|
|
{
|
|
VERBOSE(("StartSaveImage: Convert %s to a WCHAR failed\n", filename));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if ( g_pImage != NULL )
|
|
{
|
|
CLSID tempClsID = *clsid;
|
|
Status rCode = Ok;
|
|
|
|
// Popup a dialog to let user set up the encoder parameters
|
|
|
|
if ( tempClsID == K_JPEGCLSID )
|
|
{
|
|
if ( ShowMyDialog((INT)IDD_SAVEJPEGDLG, g_hwndMain,
|
|
JpegSaveDlgProc) == FALSE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if ( tempClsID == K_TIFFCLSID )
|
|
{
|
|
if ( ShowMyDialog((INT)IDD_SAVETIFFDLG, g_hwndMain,
|
|
TiffSaveDlgProc) == FALSE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Note: during the save dialog, the g_pEncoderParams will be set
|
|
// depends on the user selection. Default is NULL
|
|
|
|
rCode = g_pImage->Save(namestr, &tempClsID, g_pEncoderParams);
|
|
|
|
free(g_pEncoderParams);
|
|
g_pEncoderParams = NULL;
|
|
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("StartSaveImage--SaveToFile() failed\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
VERBOSE(("StartSaveImage(): No image to save\n"));
|
|
return FALSE;
|
|
}
|
|
}// StartSaveImage()
|
|
|
|
BOOL
|
|
SaveCurrentFrame()
|
|
{
|
|
GUID guid = FRAMEDIM_PAGE;
|
|
|
|
if ( NULL == g_pImage )
|
|
{
|
|
VERBOSE(("SaveCurrentFrame(): No image available\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
Status rCode = Ok;
|
|
|
|
// Append the current frame
|
|
|
|
ULONG flagValueLastFrame = EncoderValueLastFrame;
|
|
ULONG flagValueDim = EncoderValueFrameDimensionPage;
|
|
|
|
EncoderParameters* pMyEncoderParams = (EncoderParameters*)malloc
|
|
(2 * sizeof(EncoderParameters));
|
|
|
|
pMyEncoderParams->Parameter[0].Guid = EncoderSaveFlag;
|
|
pMyEncoderParams->Parameter[0].Type = EncoderParameterValueTypeLong;
|
|
pMyEncoderParams->Parameter[0].NumberOfValues = 1;
|
|
pMyEncoderParams->Parameter[0].Value = (VOID*)&flagValueDim;
|
|
|
|
#if 0
|
|
pMyEncoderParams->Parameter[1].Guid = EncoderSaveFlag;
|
|
pMyEncoderParams->Parameter[1].Type = EncoderParameterValueTypeLong;
|
|
pMyEncoderParams->Parameter[1].NumberOfValues = 1;
|
|
pMyEncoderParams->Parameter[1].Value = (VOID*)& flagValueLastFrame;
|
|
|
|
pMyEncoderParams->Count = 2;
|
|
#endif
|
|
pMyEncoderParams->Count = 1;
|
|
|
|
#if 1
|
|
rCode = g_pImage->SaveAdd(pMyEncoderParams);
|
|
|
|
free(pMyEncoderParams);
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("SaveAdd() failed\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
#else // Save append testing
|
|
WCHAR *filename = L"x:/foo.jpg";
|
|
|
|
Image* newImage = new Image(filename);
|
|
rCode = g_pImage->SaveAdd(newImage, pMyEncoderParams);
|
|
delete newImage;
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("SaveAppend() failed\n"));
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
return TRUE;
|
|
}// SaveCurrentFrame()
|
|
|
|
VOID
|
|
CleanUp()
|
|
{
|
|
// Clean up before quit
|
|
|
|
if ( NULL != g_pImage )
|
|
{
|
|
delete g_pImage;
|
|
g_pImage = NULL;
|
|
}
|
|
|
|
if ( NULL != g_pDrawAttrib )
|
|
{
|
|
delete g_pDrawAttrib;
|
|
g_pDrawAttrib = NULL;
|
|
}
|
|
|
|
if ( NULL != g_pDestPoints )
|
|
{
|
|
delete g_pDestPoints;
|
|
g_pDestPoints = NULL;
|
|
}
|
|
}// CleanUp()
|
|
|
|
VOID
|
|
DoNextPage()
|
|
{
|
|
g_iCurrentPageIndex++;
|
|
|
|
// Check if we already at the last page of the image
|
|
// Note: g_iCurrentPageIndex is 0 based. So the max page index we can reach
|
|
// is g_uiTotalPages - 1
|
|
|
|
if ( g_iCurrentPageIndex >= (INT)g_uiTotalPages )
|
|
{
|
|
g_iCurrentPageIndex = g_uiTotalPages - 1;
|
|
}
|
|
|
|
// Display current page
|
|
|
|
SetCurrentPage();
|
|
}// DoNextPage()
|
|
|
|
VOID
|
|
DoPreviousPage()
|
|
{
|
|
g_iCurrentPageIndex--;
|
|
|
|
if ( g_iCurrentPageIndex < 0 )
|
|
{
|
|
g_iCurrentPageIndex = 0;
|
|
}
|
|
|
|
// Display current page
|
|
|
|
SetCurrentPage();
|
|
}// DoPreviousPage()
|
|
|
|
VOID
|
|
DoAnimated()
|
|
{
|
|
if ( g_uiTotalPages < 2 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Reset the page to the first page
|
|
|
|
g_iCurrentPageIndex = 0;
|
|
|
|
// Display current page
|
|
|
|
SetCurrentPage();
|
|
|
|
SetTimer(g_hwndMain, 0, g_uiDelay * 10, NULL);
|
|
}// DoNextPage()
|
|
|
|
VOID
|
|
DoSave(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
OPENFILENAME ofn;
|
|
CHAR filename[MAX_PATH];
|
|
|
|
ZeroMemory(&ofn, sizeof(ofn));
|
|
|
|
ofn.lStructSize = sizeof(ofn);
|
|
ofn.hwndOwner = hwnd;
|
|
ofn.hInstance = g_hAppInstance;
|
|
ofn.lpstrFile = filename;
|
|
ofn.nMaxFile = MAX_PATH;
|
|
ofn.lpstrTitle = "Save Image File";
|
|
ofn.lpstrInitialDir = ".";
|
|
ofn.Flags = OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT;
|
|
filename[0] = '\0';
|
|
|
|
// Make up the file type filter string
|
|
|
|
ImageCodecInfo* codecs;
|
|
UINT count;
|
|
|
|
GpStatus status;
|
|
UINT cbCodecs = 0;
|
|
GetImageEncodersSize(&count, &cbCodecs);
|
|
codecs = static_cast<ImageCodecInfo *>(malloc (cbCodecs));
|
|
if (codecs == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
status = GetImageEncoders(count, cbCodecs, codecs);
|
|
if (status != Ok)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CHAR* filter = MakeFilterFromCodecs(count, codecs, FALSE);
|
|
|
|
if ( !filter )
|
|
{
|
|
VERBOSE(("DoSave---MakeFilterFromCodecs() failed\n"));
|
|
}
|
|
else
|
|
{
|
|
ofn.lpstrFilter = filter;
|
|
|
|
// Present the file/save dialog
|
|
|
|
if ( GetSaveFileName(&ofn) )
|
|
{
|
|
INT iIndex = ofn.nFilterIndex;
|
|
|
|
if ( (iIndex < 0) || (iIndex > (INT)count) )
|
|
{
|
|
iIndex = 0;
|
|
}
|
|
else
|
|
{
|
|
iIndex--;
|
|
}
|
|
|
|
// Get the image encoder
|
|
|
|
if ( StartSaveImage(filename, &codecs[iIndex].Clsid) == FALSE )
|
|
{
|
|
// Fail to get an image encoder
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
free(filter);
|
|
}// Filter != NULL
|
|
|
|
if (codecs)
|
|
{
|
|
free(codecs);
|
|
}
|
|
|
|
}// DoSave()
|
|
|
|
//
|
|
// Flip or rotate the image in memory
|
|
//
|
|
VOID
|
|
DoTransFlipRotate(
|
|
HWND hwnd,
|
|
INT menuCmd
|
|
)
|
|
{
|
|
switch ( menuCmd )
|
|
{
|
|
case IDM_TRANSFORM_HORIZONTALFLIP:
|
|
g_pImage->RotateFlip(RotateNoneFlipX);
|
|
|
|
break;
|
|
|
|
case IDM_TRANSFORM_VERTICALFLIP:
|
|
g_pImage->RotateFlip(RotateNoneFlipY);
|
|
|
|
break;
|
|
|
|
case IDM_TRANSFORM_ROTATE90:
|
|
g_pImage->RotateFlip(Rotate90FlipNone);
|
|
|
|
break;
|
|
|
|
case IDM_TRANSFORM_ROTATE180:
|
|
g_pImage->RotateFlip(Rotate180FlipNone);
|
|
|
|
break;
|
|
|
|
case IDM_TRANSFORM_ROTATE270:
|
|
g_pImage->RotateFlip(Rotate270FlipNone);
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
UpdateImageInfo();
|
|
RefreshImageDisplay();
|
|
}
|
|
|
|
//
|
|
// Flip or rotate the image, just for effect. No change to the source image
|
|
//
|
|
VOID
|
|
DoFlipRotate(
|
|
HWND hwnd,
|
|
INT menuCmd
|
|
)
|
|
{
|
|
Matrix mat;
|
|
REAL tmpX, tmpY;
|
|
int i;
|
|
|
|
if ( g_pImage == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Graphics* pGraphics = Graphics::FromHWND(hwnd);
|
|
|
|
if ( (g_DestPointCount != 4) && (g_pDestPoints != NULL) )
|
|
{
|
|
free(g_pDestPoints);
|
|
}
|
|
|
|
g_DestPointCount = 4;
|
|
if ( g_pDestPoints == NULL )
|
|
{
|
|
g_pDestPoints = (PointF*)malloc(g_DestPointCount * sizeof(PointF));
|
|
if ( g_pDestPoints == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
g_pDestPoints[0].X = 0; // top left
|
|
g_pDestPoints[0].Y = 0;
|
|
g_pDestPoints[1].X = (float)g_ImageWidth - 1; // top right
|
|
g_pDestPoints[1].Y = 0;
|
|
g_pDestPoints[2].X = 0; // bottom left
|
|
g_pDestPoints[2].Y = (float)g_ImageHeight - 1;
|
|
g_pDestPoints[3].X = (float)g_ImageWidth - 1; // bottom right
|
|
g_pDestPoints[3].Y = (float)g_ImageHeight - 1;
|
|
|
|
}
|
|
|
|
switch ( menuCmd )
|
|
{
|
|
case IDM_VIEW_HORIZONTALFLIP:
|
|
if ( ((g_pDestPoints[1].X - g_pDestPoints[0].X)
|
|
== (float)g_ImageWidth)
|
|
||((g_pDestPoints[0].X - g_pDestPoints[1].X)
|
|
== (float)g_ImageWidth) )
|
|
{
|
|
tmpX = g_pDestPoints[0].X;
|
|
tmpY = g_pDestPoints[0].Y;
|
|
g_pDestPoints[0].X = g_pDestPoints[1].X;
|
|
g_pDestPoints[0].Y = g_pDestPoints[1].Y;
|
|
g_pDestPoints[1].X = tmpX;
|
|
g_pDestPoints[1].Y = tmpY;
|
|
tmpX = g_pDestPoints[3].X;
|
|
tmpY = g_pDestPoints[3].Y;
|
|
g_pDestPoints[3].X = g_pDestPoints[2].X;
|
|
g_pDestPoints[3].Y = g_pDestPoints[2].Y;
|
|
g_pDestPoints[2].X = tmpX;
|
|
g_pDestPoints[2].Y = tmpY;
|
|
}
|
|
else
|
|
{
|
|
tmpX = g_pDestPoints[0].X;
|
|
tmpY = g_pDestPoints[0].Y;
|
|
g_pDestPoints[0].X = g_pDestPoints[2].X;
|
|
g_pDestPoints[0].Y = g_pDestPoints[2].Y;
|
|
g_pDestPoints[2].X = tmpX;
|
|
g_pDestPoints[2].Y = tmpY;
|
|
tmpX = g_pDestPoints[3].X;
|
|
tmpY = g_pDestPoints[3].Y;
|
|
g_pDestPoints[3].X = g_pDestPoints[1].X;
|
|
g_pDestPoints[3].Y = g_pDestPoints[1].Y;
|
|
g_pDestPoints[1].X = tmpX;
|
|
g_pDestPoints[1].Y = tmpY;
|
|
}
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_VERTICALFLIP:
|
|
if (((g_pDestPoints[1].X - g_pDestPoints[0].X) == (float)g_ImageWidth) ||
|
|
((g_pDestPoints[0].X - g_pDestPoints[1].X) == (float)g_ImageWidth))
|
|
{
|
|
tmpX = g_pDestPoints[0].X;
|
|
tmpY = g_pDestPoints[0].Y;
|
|
g_pDestPoints[0].X = g_pDestPoints[2].X;
|
|
g_pDestPoints[0].Y = g_pDestPoints[2].Y;
|
|
g_pDestPoints[2].X = tmpX;
|
|
g_pDestPoints[2].Y = tmpY;
|
|
tmpX = g_pDestPoints[3].X;
|
|
tmpY = g_pDestPoints[3].Y;
|
|
g_pDestPoints[3].X = g_pDestPoints[1].X;
|
|
g_pDestPoints[3].Y = g_pDestPoints[1].Y;
|
|
g_pDestPoints[1].X = tmpX;
|
|
g_pDestPoints[1].Y = tmpY;
|
|
}
|
|
else
|
|
{
|
|
tmpX = g_pDestPoints[0].X;
|
|
tmpY = g_pDestPoints[0].Y;
|
|
g_pDestPoints[0].X = g_pDestPoints[1].X;
|
|
g_pDestPoints[0].Y = g_pDestPoints[1].Y;
|
|
g_pDestPoints[1].X = tmpX;
|
|
g_pDestPoints[1].Y = tmpY;
|
|
tmpX = g_pDestPoints[3].X;
|
|
tmpY = g_pDestPoints[3].Y;
|
|
g_pDestPoints[3].X = g_pDestPoints[2].X;
|
|
g_pDestPoints[3].Y = g_pDestPoints[2].Y;
|
|
g_pDestPoints[2].X = tmpX;
|
|
g_pDestPoints[2].Y = tmpY;
|
|
}
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_ROTATE90:
|
|
if (((g_pDestPoints[1].X - g_pDestPoints[0].X) == (float)g_ImageWidth - 1) ||
|
|
((g_pDestPoints[0].X - g_pDestPoints[1].X) == (float)g_ImageWidth - 1))
|
|
{
|
|
tmpX = g_pDestPoints[0].X;
|
|
tmpY = g_pDestPoints[0].Y;
|
|
g_pDestPoints[0].X = g_pDestPoints[1].X;
|
|
g_pDestPoints[0].Y = g_pDestPoints[1].Y;
|
|
g_pDestPoints[1].X = g_pDestPoints[3].X;
|
|
g_pDestPoints[1].Y = g_pDestPoints[3].Y;
|
|
g_pDestPoints[3].X = g_pDestPoints[2].X;
|
|
g_pDestPoints[3].Y = g_pDestPoints[2].Y;
|
|
g_pDestPoints[2].X = tmpX;
|
|
g_pDestPoints[2].Y = tmpY;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (g_pDestPoints[i].X == (float)g_ImageWidth - 1)
|
|
{
|
|
g_pDestPoints[i].X = (float)g_ImageHeight - 1;
|
|
}
|
|
else if (g_pDestPoints[i].X == (float)g_ImageHeight - 1)
|
|
{
|
|
g_pDestPoints[i].X = (float)g_ImageWidth - 1;
|
|
}
|
|
if (g_pDestPoints[i].Y == (float)g_ImageWidth - 1)
|
|
{
|
|
g_pDestPoints[i].Y = (float)g_ImageHeight - 1;
|
|
}
|
|
else if (g_pDestPoints[i].Y == (float)g_ImageHeight - 1)
|
|
{
|
|
g_pDestPoints[i].Y = (float)g_ImageWidth - 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tmpX = g_pDestPoints[0].X;
|
|
tmpY = g_pDestPoints[0].Y;
|
|
g_pDestPoints[0].X = g_pDestPoints[1].X;
|
|
g_pDestPoints[0].Y = g_pDestPoints[1].Y;
|
|
g_pDestPoints[1].X = g_pDestPoints[3].X;
|
|
g_pDestPoints[1].Y = g_pDestPoints[3].Y;
|
|
g_pDestPoints[3].X = g_pDestPoints[2].X;
|
|
g_pDestPoints[3].Y = g_pDestPoints[2].Y;
|
|
g_pDestPoints[2].X = tmpX;
|
|
g_pDestPoints[2].Y = tmpY;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (g_pDestPoints[i].X == (float)g_ImageWidth - 1)
|
|
{
|
|
g_pDestPoints[i].X = (float)g_ImageHeight - 1;
|
|
}
|
|
else if (g_pDestPoints[i].X == (float)g_ImageHeight - 1)
|
|
{
|
|
g_pDestPoints[i].X = (float)g_ImageWidth - 1;
|
|
}
|
|
if (g_pDestPoints[i].Y == (float)g_ImageWidth - 1)
|
|
{
|
|
g_pDestPoints[i].Y = (float)g_ImageHeight - 1;
|
|
}
|
|
else if (g_pDestPoints[i].Y == (float)g_ImageHeight - 1)
|
|
{
|
|
g_pDestPoints[i].Y = (float)g_ImageWidth - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
g_bRotated = !g_bRotated;
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_ROTATE270:
|
|
if (((g_pDestPoints[1].X - g_pDestPoints[0].X) == (float)g_ImageWidth) ||
|
|
((g_pDestPoints[0].X - g_pDestPoints[1].X) == (float)g_ImageWidth))
|
|
{
|
|
tmpX = g_pDestPoints[2].X;
|
|
tmpY = g_pDestPoints[2].Y;
|
|
g_pDestPoints[2].X = g_pDestPoints[3].X;
|
|
g_pDestPoints[2].Y = g_pDestPoints[3].Y;
|
|
g_pDestPoints[3].X = g_pDestPoints[1].X;
|
|
g_pDestPoints[3].Y = g_pDestPoints[1].Y;
|
|
g_pDestPoints[1].X = g_pDestPoints[0].X;
|
|
g_pDestPoints[1].Y = g_pDestPoints[0].Y;
|
|
g_pDestPoints[0].X = tmpX;
|
|
g_pDestPoints[0].Y = tmpY;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (g_pDestPoints[i].X == (float)g_ImageWidth)
|
|
{
|
|
g_pDestPoints[i].X = (float)g_ImageHeight;
|
|
}
|
|
else if (g_pDestPoints[i].X == (float)g_ImageHeight)
|
|
{
|
|
g_pDestPoints[i].X = (float)g_ImageWidth;
|
|
}
|
|
if (g_pDestPoints[i].Y == (float)g_ImageWidth)
|
|
{
|
|
g_pDestPoints[i].Y = (float)g_ImageHeight;
|
|
}
|
|
else if (g_pDestPoints[i].Y == (float)g_ImageHeight)
|
|
{
|
|
g_pDestPoints[i].Y = (float)g_ImageWidth;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tmpX = g_pDestPoints[2].X;
|
|
tmpY = g_pDestPoints[2].Y;
|
|
g_pDestPoints[2].X = g_pDestPoints[3].X;
|
|
g_pDestPoints[2].Y = g_pDestPoints[3].Y;
|
|
g_pDestPoints[3].X = g_pDestPoints[1].X;
|
|
g_pDestPoints[3].Y = g_pDestPoints[1].Y;
|
|
g_pDestPoints[1].X = g_pDestPoints[0].X;
|
|
g_pDestPoints[1].Y = g_pDestPoints[0].Y;
|
|
g_pDestPoints[0].X = tmpX;
|
|
g_pDestPoints[0].Y = tmpY;
|
|
for (i=0;i<4;i++)
|
|
{
|
|
if (g_pDestPoints[i].X == (float)g_ImageWidth)
|
|
{
|
|
g_pDestPoints[i].X = (float)g_ImageHeight;
|
|
}
|
|
else if (g_pDestPoints[i].X == (float)g_ImageHeight)
|
|
{
|
|
g_pDestPoints[i].X = (float)g_ImageWidth;
|
|
}
|
|
if (g_pDestPoints[i].Y == (float)g_ImageWidth)
|
|
{
|
|
g_pDestPoints[i].Y = (float)g_ImageHeight;
|
|
}
|
|
else if (g_pDestPoints[i].Y == (float)g_ImageHeight)
|
|
{
|
|
g_pDestPoints[i].Y = (float)g_ImageWidth;
|
|
}
|
|
}
|
|
}
|
|
|
|
g_bRotated = !g_bRotated;
|
|
|
|
break;
|
|
}// switch ( menuCmd )
|
|
mat.TransformPoints(g_pDestPoints, g_DestPointCount);
|
|
|
|
RefreshImageDisplay();
|
|
|
|
delete pGraphics;
|
|
|
|
RefreshImageDisplay();
|
|
}// DoFlipRotate()
|
|
|
|
VOID
|
|
DoGetProperties(
|
|
VOID
|
|
)
|
|
{
|
|
UINT numOfProperty;
|
|
UINT itemSize;
|
|
PropertyItem* pBuffer = NULL;
|
|
PropertyItem* pTotalBuffer = NULL;
|
|
|
|
// Check how many property items in this image
|
|
|
|
numOfProperty = g_pImage->GetPropertyCount();
|
|
|
|
VERBOSE(("There are %d property items in image %s\n", numOfProperty,
|
|
g_acImageName));
|
|
// Get all the property ID list from the image
|
|
|
|
PROPID* pList = (PROPID*)malloc(numOfProperty * sizeof(PROPID));
|
|
if ( pList == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Status rCode = g_pImage->GetPropertyIdList(numOfProperty, pList);
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("GetPropertyIdList() failed\n"));
|
|
return;
|
|
}
|
|
|
|
//#define UNITTEST 0
|
|
|
|
#if defined(UNITTEST)
|
|
for ( int i = 0; i < (int)numOfProperty; ++i )
|
|
{
|
|
// Show Property ID
|
|
|
|
VERBOSE(("ID[%d] = 0x%x, (%d) ", i, pList[i], pList[i]));
|
|
|
|
// Check the size for this property item
|
|
|
|
itemSize = g_pImage->GetPropertyItemSize(pList[i]);
|
|
|
|
VERBOSE(("size = %d, ", itemSize));
|
|
|
|
// Allocate memory and get this property item
|
|
|
|
pBuffer = (PropertyItem*)malloc(itemSize);
|
|
if ( pBuffer == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
rCode = g_pImage->GetPropertyItem(pList[i], itemSize, pBuffer);
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("GetPropertyItem() failed\n"));
|
|
return;
|
|
}
|
|
|
|
DisplayPropertyItem(pBuffer);
|
|
|
|
free(pBuffer);
|
|
|
|
// Test RemovePropertyItem()
|
|
|
|
rCode = g_pImage->RemovePropertyItem(pList[i]);
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("RemovePropertyItem() failed\n"));
|
|
return;
|
|
}
|
|
}// Loop through the list
|
|
|
|
free(pList);
|
|
#endif
|
|
|
|
rCode = g_pImage->GetPropertySize(&itemSize, &numOfProperty);
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("GetPropertySize() failed\n"));
|
|
return;
|
|
}
|
|
|
|
pTotalBuffer = (PropertyItem*)malloc(itemSize);
|
|
rCode = g_pImage->GetAllPropertyItems(itemSize, numOfProperty,
|
|
pTotalBuffer);
|
|
if ( (rCode != Ok) && (rCode != NotImplemented) )
|
|
{
|
|
VERBOSE(("GetAllPropertyItems() failed\n"));
|
|
return;
|
|
}
|
|
|
|
PropertyItem* pTemp = pTotalBuffer;
|
|
for ( int j = 0; j < (int)numOfProperty; ++j )
|
|
{
|
|
DisplayPropertyItem(pTemp);
|
|
|
|
pTemp++;
|
|
}
|
|
|
|
free(pTotalBuffer);
|
|
}// DoGetProperties()
|
|
|
|
VOID
|
|
DoViewThumbnail()
|
|
{
|
|
// Get build in thumbnail
|
|
|
|
Image* pThumbImage = g_pImage->GetThumbnailImage(0, 0);
|
|
|
|
if ( pThumbImage == NULL )
|
|
{
|
|
VERBOSE(("Image %s doesn't have a thumbnail\n", g_acImageName));
|
|
return;
|
|
}
|
|
|
|
if ( NULL != g_pImage )
|
|
{
|
|
delete g_pImage;
|
|
}
|
|
|
|
g_pImage = pThumbImage;
|
|
|
|
UpdateImageInfo();
|
|
g_dScale = 1;
|
|
RefreshImageDisplay();
|
|
}// DoViewThumbnail()
|
|
|
|
VOID
|
|
DoChannelView(
|
|
INT menuCmd
|
|
)
|
|
{
|
|
if ( g_pDrawAttrib != NULL )
|
|
{
|
|
delete g_pDrawAttrib;
|
|
}
|
|
|
|
g_pDrawAttrib = new ImageAttributes();
|
|
|
|
switch ( menuCmd )
|
|
{
|
|
case IDM_VIEW_CHANNEL_C:
|
|
g_pDrawAttrib->SetOutputChannel(ColorChannelFlagsC);
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_CHANNEL_M:
|
|
g_pDrawAttrib->SetOutputChannel(ColorChannelFlagsM);
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_CHANNEL_Y:
|
|
g_pDrawAttrib->SetOutputChannel(ColorChannelFlagsY);
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_CHANNEL_K:
|
|
g_pDrawAttrib->SetOutputChannel(ColorChannelFlagsK);
|
|
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
RefreshImageDisplay();
|
|
|
|
return;
|
|
}// DoChannelView()
|
|
|
|
VOID
|
|
DisplayImageInfo()
|
|
{
|
|
VERBOSE(("\nInformation for frame %d of Image %s\n",
|
|
g_iCurrentPageIndex + 1, g_acImageName));
|
|
VERBOSE(("--------------------------------\n"));
|
|
VERBOSE(("Width = %d\n", g_ImageWidth));
|
|
VERBOSE(("Height = %d\n", g_ImageHeight));
|
|
|
|
if ( g_ImageFlags & IMGFLAG_HASREALPIXELSIZE )
|
|
{
|
|
VERBOSE(("---The pixel size info is from the original image\n"));
|
|
}
|
|
else
|
|
{
|
|
VERBOSE(("---The pixel size info is NOT from the original image\n"));
|
|
}
|
|
|
|
switch ( g_ImagePixelFormat )
|
|
{
|
|
case PIXFMT_1BPP_INDEXED:
|
|
VERBOSE(("Color depth: 1 BPP INDEXED\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_4BPP_INDEXED:
|
|
VERBOSE(("Color depth: 4 BPP INDEXED\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_8BPP_INDEXED:
|
|
VERBOSE(("Color depth: 8 BPP INDEXED\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_16BPP_GRAYSCALE:
|
|
VERBOSE(("Color depth: 16 BPP GRAY SCALE\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_16BPP_RGB555:
|
|
VERBOSE(("Color depth: 16 BPP RGB 555\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_16BPP_RGB565:
|
|
VERBOSE(("Color depth: 16 BPP RGB 565\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_16BPP_ARGB1555:
|
|
VERBOSE(("Color depth: 16 BPP ARGB 1555\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_24BPP_RGB:
|
|
VERBOSE(("Color depth: 24 BPP RGB\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_32BPP_RGB:
|
|
VERBOSE(("Color depth: 32 BPP RGB\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_32BPP_ARGB:
|
|
VERBOSE(("Color depth: 32 BPP ARGB\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_32BPP_PARGB:
|
|
VERBOSE(("Color depth: 32 BPP PARGB\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_48BPP_RGB:
|
|
VERBOSE(("Color depth: 48 BPP PARGB\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_64BPP_ARGB:
|
|
VERBOSE(("Color depth: 64 BPP ARGB\n"));
|
|
|
|
break;
|
|
|
|
case PIXFMT_64BPP_PARGB:
|
|
VERBOSE(("Color depth: 64 BPP PARGB\n"));
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}// Color format
|
|
|
|
VERBOSE(("X DPI (dots per inch) = %f\n", g_ImageXDpi));
|
|
VERBOSE(("Y DPI (dots per inch) = %f\n", g_ImageYDpi));
|
|
|
|
if ( g_ImageFlags & IMGFLAG_HASREALDPI )
|
|
{
|
|
VERBOSE(("---The DPI info is from the original image\n"));
|
|
}
|
|
else
|
|
{
|
|
VERBOSE(("---The DPI info is NOT from the original image\n"));
|
|
}
|
|
|
|
// Parse image info flags
|
|
|
|
if ( g_ImageFlags & SINKFLAG_HASALPHA )
|
|
{
|
|
VERBOSE(("This image contains alpha pixels\n"));
|
|
|
|
if ( g_ImageFlags & IMGFLAG_HASTRANSLUCENT )
|
|
{
|
|
VERBOSE(("---It has non-0 and 1 alpha pixels (TRANSLUCENT)\n"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VERBOSE(("This image does not contain alpha pixels\n"));
|
|
}
|
|
|
|
// Figure out origianl file format
|
|
|
|
if ( g_ImageRawDataFormat == IMGFMT_MEMORYBMP )
|
|
{
|
|
VERBOSE(("RawDataFormat is MEMORYBMP\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_BMP )
|
|
{
|
|
VERBOSE(("RawDataFormat is BMP\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_EMF )
|
|
{
|
|
VERBOSE(("RawDataFormat is EMF\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_WMF )
|
|
{
|
|
VERBOSE(("RawDataFormat is WMF\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_JPEG )
|
|
{
|
|
VERBOSE(("RawDataFormat is JPEG\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_PNG )
|
|
{
|
|
VERBOSE(("RawDataFormat is PNG\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_GIF )
|
|
{
|
|
VERBOSE(("RawDataFormat is GIF\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_TIFF )
|
|
{
|
|
VERBOSE(("RawDataFormat is TIFF\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_EXIF )
|
|
{
|
|
VERBOSE(("RawDataFormat is EXIF\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_ICO )
|
|
{
|
|
VERBOSE(("RawDataFormat is ICO\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_PHOTOCD )
|
|
{
|
|
VERBOSE(("RawDataFormat is PHOTOCD\n"));
|
|
}
|
|
else if ( g_ImageRawDataFormat == IMGFMT_FLASHPIX )
|
|
{
|
|
VERBOSE(("RawDataFormat is FLASHPIX\n"));
|
|
}
|
|
else
|
|
{
|
|
VERBOSE(("RawDataFormat is UNDEFINED\n"));
|
|
}
|
|
|
|
// Figure out origianl color space
|
|
|
|
if ( g_ImageFlags & IMGFLAG_COLORSPACE_RGB )
|
|
{
|
|
VERBOSE(("This image is in RGB color space\n"));
|
|
}
|
|
else if ( g_ImageFlags & IMGFLAG_COLORSPACE_CMYK )
|
|
{
|
|
VERBOSE(("This image is in CMYK color space\n"));
|
|
}
|
|
else if ( g_ImageFlags & IMGFLAG_COLORSPACE_GRAY )
|
|
{
|
|
VERBOSE(("This image is a gray scale image\n"));
|
|
}
|
|
else if ( g_ImageFlags & IMGFLAG_COLORSPACE_YCCK )
|
|
{
|
|
VERBOSE(("This image is in YCCK color space\n"));
|
|
}
|
|
else if ( g_ImageFlags & IMGFLAG_COLORSPACE_YCBCR )
|
|
{
|
|
VERBOSE(("This image is in YCBCR color space\n"));
|
|
}
|
|
}// DisplayImageInfo()
|
|
|
|
//
|
|
// Convert the current image to a bitmap
|
|
//
|
|
|
|
VOID
|
|
DoConvertToBitmap(
|
|
HWND hwnd,
|
|
INT menuCmd
|
|
)
|
|
{
|
|
// Map menu selection to its corresponding pixel format
|
|
|
|
PixelFormatID pixfmt;
|
|
|
|
switch (menuCmd)
|
|
{
|
|
case IDM_CONVERT_8BIT:
|
|
pixfmt = PIXFMT_8BPP_INDEXED;
|
|
|
|
break;
|
|
|
|
case IDM_CONVERT_16BITRGB555:
|
|
pixfmt = PIXFMT_16BPP_RGB555;
|
|
|
|
break;
|
|
|
|
case IDM_CONVERT_16BITRGB565:
|
|
pixfmt = PIXFMT_16BPP_RGB565;
|
|
|
|
break;
|
|
|
|
case IDM_CONVERT_24BITRGB:
|
|
pixfmt = PIXFMT_24BPP_RGB;
|
|
|
|
break;
|
|
|
|
case IDM_CONVERT_32BITRGB:
|
|
pixfmt = PIXFMT_32BPP_RGB;
|
|
|
|
break;
|
|
|
|
case IDM_CONVERT_32BITARGB:
|
|
default:
|
|
pixfmt = PIXFMT_32BPP_ARGB;
|
|
|
|
break;
|
|
}
|
|
|
|
// Convert the current image to a bitmap image
|
|
|
|
if ( g_pImage != NULL )
|
|
{
|
|
Bitmap* pNewBmp = ((Bitmap*)g_pImage)->Clone(0, 0, g_ImageWidth,
|
|
g_ImageHeight, pixfmt);
|
|
if ( pNewBmp == NULL )
|
|
{
|
|
VERBOSE(("Clone failed in DoConvertToBitmap()\n"));
|
|
return;
|
|
}
|
|
|
|
//Release the old one
|
|
|
|
if ( g_pImage != NULL )
|
|
{
|
|
delete g_pImage;
|
|
}
|
|
|
|
g_pImage = (Image*)pNewBmp;
|
|
}
|
|
|
|
RefreshImageDisplay();
|
|
}// DoConvertToBitmap()
|
|
|
|
//
|
|
// Crop the image
|
|
//
|
|
// NOTE: We're not spending time here to do a fancy UI.
|
|
// So we'll just inset the image by 5 pixels each time.
|
|
//
|
|
|
|
VOID
|
|
DoCrop(
|
|
HWND hwnd
|
|
)
|
|
{
|
|
if ( g_SourceWidth == 0 )
|
|
{
|
|
// initialize global source width and height if not previously
|
|
// initialized
|
|
|
|
if ( g_pImage == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
g_SourceWidth = (REAL)g_ImageWidth;
|
|
g_SourceHeight = (REAL)g_ImageHeight;
|
|
}
|
|
|
|
// check to make sure source image is still at least one pixel big
|
|
if ( (g_SourceWidth - g_SourceX) > 11 )
|
|
{
|
|
g_SourceX += 10;
|
|
}
|
|
|
|
if ( (g_SourceHeight - g_SourceY) > 11 )
|
|
{
|
|
g_SourceY += 10;
|
|
}
|
|
|
|
if ( (g_SourceWidth - g_SourceX) > 6 )
|
|
{
|
|
g_SourceWidth -= 5;
|
|
}
|
|
|
|
if ( (g_SourceHeight - g_SourceY) > 6 )
|
|
{
|
|
g_SourceHeight -= 5;
|
|
}
|
|
|
|
RefreshImageDisplay();
|
|
}// DoCrop()
|
|
|
|
void
|
|
DoRender()
|
|
{
|
|
// Check if we have anything special for drawing
|
|
|
|
if ( (g_pDrawAttrib == NULL) && (g_pDestPoints == NULL) )
|
|
{
|
|
// Nothing special, we don't need "render"
|
|
|
|
return;
|
|
}
|
|
|
|
Bitmap* pNewBitmap = NULL;
|
|
|
|
// Create a Graphics object from this memory DC and draw onto it
|
|
|
|
if ( g_bRotated == TRUE )
|
|
{
|
|
pNewBitmap = new Bitmap(g_ImageHeight,
|
|
g_ImageWidth,
|
|
PIXFMT_32BPP_ARGB);
|
|
}
|
|
else
|
|
{
|
|
pNewBitmap = new Bitmap(g_ImageWidth,
|
|
g_ImageHeight,
|
|
PIXFMT_32BPP_ARGB);
|
|
}
|
|
|
|
if ( pNewBitmap == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Graphics* pGraphics = new Graphics(pNewBitmap);
|
|
|
|
REAL rWidth = (REAL)g_ImageWidth;
|
|
REAL rHeight = (REAL)g_ImageHeight;
|
|
|
|
if ( g_SourceWidth != 0 )
|
|
{
|
|
rWidth = g_SourceWidth;
|
|
}
|
|
|
|
if ( g_SourceHeight != 0 )
|
|
{
|
|
rHeight = g_SourceHeight;
|
|
}
|
|
|
|
if ( g_pDestPoints != NULL )
|
|
{
|
|
pGraphics->DrawImage(g_pImage,
|
|
g_pDestPoints,
|
|
3, // Should use g_DestPointCount,
|
|
g_SourceX,
|
|
g_SourceY,
|
|
rWidth,
|
|
rHeight,
|
|
UnitPixel,
|
|
g_pDrawAttrib,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
Rect dstRect(0, 0, g_ImageWidth, g_ImageHeight);
|
|
|
|
pGraphics->DrawImage(g_pImage,
|
|
dstRect,
|
|
(INT)g_SourceX,
|
|
(INT)g_SourceY,
|
|
(INT)rWidth,
|
|
(INT)rHeight,
|
|
UnitPixel,
|
|
g_pDrawAttrib,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
|
|
if ( g_pImage != NULL )
|
|
{
|
|
delete g_pImage;
|
|
}
|
|
|
|
g_pImage = (Image*)pNewBitmap;
|
|
|
|
delete pGraphics;
|
|
|
|
// Clear up all the drawing special attributes since we have already done
|
|
// the render
|
|
|
|
if ( g_pDrawAttrib != NULL )
|
|
{
|
|
delete g_pDrawAttrib;
|
|
g_pDrawAttrib = NULL;
|
|
}
|
|
|
|
if ( g_pDestPoints != NULL )
|
|
{
|
|
delete g_pDestPoints;
|
|
g_pDestPoints = NULL;
|
|
g_DestPointCount = 0;
|
|
}
|
|
|
|
RefreshImageDisplay();
|
|
}// DoRender()
|
|
|
|
VOID
|
|
DoICM()
|
|
{
|
|
HMENU hMenu = GetMenu(g_hwndMain);
|
|
UINT ulRC = GetMenuState(hMenu, IDM_EFFECT_ICC, MF_BYCOMMAND);
|
|
|
|
if ( ulRC == MF_CHECKED )
|
|
{
|
|
// Turn ICM off
|
|
|
|
CheckMenuItem(hMenu, IDM_EFFECT_ICC, MF_BYCOMMAND | MF_UNCHECKED);
|
|
|
|
// Check if we loaded the image with ICM on or off
|
|
|
|
if ( g_LoadImageWithICM == TRUE )
|
|
{
|
|
// The image we loaded is ICM converted. We need to through it
|
|
// away and load a new one without the convertion
|
|
|
|
g_LoadImageWithICM = FALSE;
|
|
OpenImageFile(g_acImageName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Turn ICM on
|
|
|
|
CheckMenuItem(hMenu, IDM_EFFECT_ICC, MF_BYCOMMAND | MF_CHECKED);
|
|
|
|
// Check if we loaded the image with ICM on or off
|
|
|
|
if ( g_LoadImageWithICM == FALSE )
|
|
{
|
|
// The image we loaded without ICM converted. We need to through
|
|
// it away and load a new one with the convertion
|
|
|
|
g_LoadImageWithICM = TRUE;
|
|
OpenImageFile(g_acImageName);
|
|
}
|
|
}
|
|
}// DoICM()
|
|
|
|
VOID
|
|
DoGamma()
|
|
{
|
|
// Set gamma
|
|
|
|
if ( g_pDrawAttrib == NULL )
|
|
{
|
|
g_pDrawAttrib = new ImageAttributes();
|
|
}
|
|
|
|
REAL rGamma = 1.5;
|
|
|
|
g_pDrawAttrib->SetGamma(rGamma);
|
|
}
|
|
|
|
VOID
|
|
DoMenuCommand(
|
|
HWND hwnd,
|
|
INT menuCmd
|
|
)
|
|
{
|
|
HMENU hMenu = GetMenu(g_hwndMain);
|
|
|
|
switch ( menuCmd )
|
|
{
|
|
case IDM_FILE_OPEN:
|
|
// Before we open a new image. We need be sure we have done the save
|
|
// for previous image
|
|
|
|
CleanUp();
|
|
|
|
// Now open a new image
|
|
|
|
DoOpen(hwnd);
|
|
|
|
break;
|
|
|
|
case IDM_FILE_SAVE:
|
|
DoSave(hwnd);
|
|
|
|
break;
|
|
|
|
case IDM_FILE_SAVEFRAME:
|
|
// Save the current frame
|
|
|
|
SaveCurrentFrame();
|
|
|
|
break;
|
|
|
|
case IDM_FILE_PRINT:
|
|
DoPrint(hwnd);
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_NEXTPAGE:
|
|
DoNextPage();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_PREVIOUSPAGE:
|
|
DoPreviousPage();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_ANIMATED:
|
|
DoAnimated();
|
|
break;
|
|
|
|
case IDM_VIEW_THUMBNAIL:
|
|
DoViewThumbnail();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_CHANNEL_C:
|
|
case IDM_VIEW_CHANNEL_M:
|
|
case IDM_VIEW_CHANNEL_Y:
|
|
case IDM_VIEW_CHANNEL_K:
|
|
case IDM_VIEW_CHANNEL_R:
|
|
case IDM_VIEW_CHANNEL_G:
|
|
case IDM_VIEW_CHANNEL_B:
|
|
case IDM_VIEW_CHANNEL_L:
|
|
DoChannelView(menuCmd);
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_ZOOM_IN:
|
|
g_dScale = g_dScale * 2;
|
|
g_fFitToWindow_w = FALSE;
|
|
g_fFitToWindow_h = FALSE;
|
|
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_ZOOM_OUT:
|
|
g_dScale = g_dScale / 2;
|
|
g_fFitToWindow_w = FALSE;
|
|
g_fFitToWindow_h = FALSE;
|
|
|
|
CheckMenuItem(hMenu, IDM_VIEW_ZOOM_FITWINDOW_W,
|
|
MF_BYCOMMAND | MF_UNCHECKED);
|
|
CheckMenuItem(hMenu, IDM_VIEW_ZOOM_FITWINDOW_H,
|
|
MF_BYCOMMAND | MF_UNCHECKED);
|
|
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_ZOOM_FITWINDOW_W:
|
|
g_dScale = (REAL)g_iWinWidth / g_ImageWidth;
|
|
|
|
g_fFitToWindow_w = TRUE;
|
|
g_fFitToWindow_h = FALSE;
|
|
|
|
ToggleScaleFactorMenu(IDM_VIEW_ZOOM_FITWINDOW_W, GetMenu(g_hwndMain));
|
|
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_ZOOM_FITWINDOW_H:
|
|
g_dScale = (REAL)g_iWinHeight / g_ImageHeight;
|
|
|
|
g_fFitToWindow_h = TRUE;
|
|
g_fFitToWindow_w = FALSE;
|
|
|
|
ToggleScaleFactorMenu(IDM_VIEW_ZOOM_FITWINDOW_H, GetMenu(g_hwndMain));
|
|
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_ZOOM_REALSIZE:
|
|
g_dScale = 1.0;
|
|
|
|
g_fFitToWindow_w = FALSE;
|
|
g_fFitToWindow_h = FALSE;
|
|
|
|
ToggleScaleFactorMenu(IDM_VIEW_ZOOM_REALSIZE, GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_BILINEAR:
|
|
g_InterpolationMode = InterpolationModeBilinear;
|
|
ToggleScaleOptionMenu(IDM_VIEW_OPTION_BILINEAR, GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_BICUBIC:
|
|
g_InterpolationMode = InterpolationModeBicubic;
|
|
ToggleScaleOptionMenu(IDM_VIEW_OPTION_BICUBIC, GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_NEARESTNEIGHBOR:
|
|
g_InterpolationMode = InterpolationModeNearestNeighbor;
|
|
ToggleScaleOptionMenu(IDM_VIEW_OPTION_NEARESTNEIGHBOR,
|
|
GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_HIGHLINEAR:
|
|
g_InterpolationMode = InterpolationModeHighQualityBilinear;
|
|
ToggleScaleOptionMenu(IDM_VIEW_OPTION_HIGHLINEAR, GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_HIGHCUBIC:
|
|
g_InterpolationMode = InterpolationModeHighQualityBicubic;
|
|
ToggleScaleOptionMenu(IDM_VIEW_OPTION_HIGHCUBIC, GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_WRAPMODETILE:
|
|
g_WrapMode = WrapModeTile;
|
|
g_pDrawAttrib->SetWrapMode(g_WrapMode, Color(0), FALSE);
|
|
ToggleWrapModeOptionMenu(IDM_VIEW_OPTION_WRAPMODETILE,
|
|
GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_WRAPMODEFLIPX:
|
|
g_WrapMode = WrapModeTileFlipX;
|
|
g_pDrawAttrib->SetWrapMode(g_WrapMode, Color(0), FALSE);
|
|
ToggleWrapModeOptionMenu(IDM_VIEW_OPTION_WRAPMODEFLIPX,
|
|
GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_WRAPMODEFLIPY:
|
|
g_WrapMode = WrapModeTileFlipY;
|
|
g_pDrawAttrib->SetWrapMode(g_WrapMode, Color(0), FALSE);
|
|
ToggleWrapModeOptionMenu(IDM_VIEW_OPTION_WRAPMODEFLIPY,
|
|
GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_WRAPMODEFLIPXY:
|
|
g_WrapMode = WrapModeTileFlipXY;
|
|
g_pDrawAttrib->SetWrapMode(g_WrapMode, Color(0), FALSE);
|
|
ToggleWrapModeOptionMenu(IDM_VIEW_OPTION_WRAPMODEFLIPXY,
|
|
GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_WRAPMODECLAMP0:
|
|
g_WrapMode = WrapModeClamp;
|
|
g_pDrawAttrib->SetWrapMode(g_WrapMode, Color(0), FALSE);
|
|
ToggleWrapModeOptionMenu(IDM_VIEW_OPTION_WRAPMODECLAMP0,
|
|
GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_OPTION_WRAPMODECLAMPFF:
|
|
g_WrapMode = WrapModeClamp;
|
|
g_pDrawAttrib->SetWrapMode(g_WrapMode, Color(0xffff0000), FALSE);
|
|
ToggleWrapModeOptionMenu(IDM_VIEW_OPTION_WRAPMODECLAMPFF,
|
|
GetMenu(g_hwndMain));
|
|
RefreshImageDisplay();
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_CROP:
|
|
DoCrop(hwnd);
|
|
break;
|
|
|
|
case IDM_VIEW_HORIZONTALFLIP:
|
|
case IDM_VIEW_VERTICALFLIP:
|
|
case IDM_VIEW_ROTATE90:
|
|
case IDM_VIEW_ROTATE270:
|
|
DoFlipRotate(hwnd, menuCmd);
|
|
|
|
break;
|
|
|
|
case IDM_TRANSFORM_HORIZONTALFLIP:
|
|
case IDM_TRANSFORM_VERTICALFLIP:
|
|
case IDM_TRANSFORM_ROTATE90:
|
|
case IDM_TRANSFORM_ROTATE180:
|
|
case IDM_TRANSFORM_ROTATE270:
|
|
DoTransFlipRotate(hwnd, menuCmd);
|
|
|
|
break;
|
|
|
|
case IDM_VIEW_ATTR_PROPERTY:
|
|
DoGetProperties();
|
|
break;
|
|
|
|
case IDM_VIEW_ATTR_INFO:
|
|
DisplayImageInfo();
|
|
break;
|
|
|
|
case IDM_FILE_RENDER:
|
|
DoRender();
|
|
|
|
break;
|
|
|
|
case IDM_FILE_QUIT:
|
|
CleanUp();
|
|
|
|
PostQuitMessage(0);
|
|
|
|
break;
|
|
|
|
case IDM_CONVERT_8BIT:
|
|
case IDM_CONVERT_16BITRGB555:
|
|
case IDM_CONVERT_16BITRGB565:
|
|
case IDM_CONVERT_24BITRGB:
|
|
case IDM_CONVERT_32BITRGB:
|
|
case IDM_CONVERT_32BITARGB:
|
|
DoConvertToBitmap(hwnd, menuCmd);
|
|
|
|
break;
|
|
|
|
case IDM_EFFECT_TRANSKEY:
|
|
// Popup a dialog to let user set up the transparent key
|
|
|
|
if ( ShowMyDialog((INT)IDD_COLORKEYDLG, g_hwndMain,
|
|
DecoderParamDlgProc) == FALSE )
|
|
|
|
{
|
|
return;
|
|
}
|
|
|
|
break;
|
|
|
|
case IDM_EFFECT_COLORMAP:
|
|
// Popup a dialog to let user set up the color map value
|
|
|
|
if ( ShowMyDialog((INT)IDD_COLORMAPDLG, g_hwndMain,
|
|
ColorMapDlgProc) == FALSE )
|
|
|
|
{
|
|
return;
|
|
}
|
|
|
|
break;
|
|
|
|
case IDM_EFFECT_ICC:
|
|
DoICM();
|
|
break;
|
|
|
|
case IDM_EFFECT_GAMMA:
|
|
DoGamma();
|
|
break;
|
|
|
|
case IDM_ANNOTATION_ANNOTATION:
|
|
// Popup a dialog to let user modify/add annotation
|
|
|
|
if ( ShowMyDialog((INT)IDD_ANNOTATIONDLG, g_hwndMain,
|
|
AnnotationDlgProc) == FALSE )
|
|
|
|
{
|
|
return;
|
|
}
|
|
|
|
break;
|
|
|
|
case IDM_ANNOTATION_SOFTWARE:
|
|
break;
|
|
|
|
case IDM_ANNOTATION_AUDIOFILE:
|
|
DoOpenAudioFile(hwnd);
|
|
}
|
|
}// DoMenuCommand()
|
|
|
|
void
|
|
DoMouseMove(
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
if ( (wParam & MK_LBUTTON) && (g_pImage != NULL)
|
|
&&(g_ImageRawDataFormat != IMGFMT_EMF)
|
|
&&(g_ImageRawDataFormat != IMGFMT_WMF) )
|
|
{
|
|
int x = LOWORD(lParam);
|
|
int y = HIWORD(lParam);
|
|
char szAnsiMessage[256];
|
|
|
|
if ( (x >= 0) && (y >= 0)
|
|
&& (x < (INT)g_ImageWidth) && ( y < (INT)g_ImageHeight) )
|
|
{
|
|
Color color;
|
|
((Bitmap*)g_pImage)->GetPixel(x, y, &color);
|
|
|
|
sprintf(szAnsiMessage, "(%d, %d) (%d, %d, %d, %d)", x, y,
|
|
color.GetAlpha(), color.GetRed(), color.GetGreen(),
|
|
color.GetBlue());
|
|
}
|
|
else
|
|
{
|
|
sprintf(szAnsiMessage, "Out of image bounds");
|
|
}
|
|
|
|
SetWindowText(g_hwndStatus, szAnsiMessage);
|
|
}
|
|
|
|
return;
|
|
}// DoMouseMove()
|
|
|
|
//
|
|
// Window callback procedure
|
|
//
|
|
LRESULT CALLBACK
|
|
MyWindowProc(
|
|
HWND hwnd,
|
|
UINT iMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
switch ( iMsg )
|
|
{
|
|
case WM_COMMAND:
|
|
DoMenuCommand(hwnd, LOWORD(wParam));
|
|
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
switch ( wParam )
|
|
{
|
|
case VK_NEXT:
|
|
|
|
// Page Down
|
|
|
|
DoNextPage();
|
|
|
|
break;
|
|
|
|
case VK_PRIOR:
|
|
|
|
// Page Up
|
|
|
|
DoPreviousPage();
|
|
|
|
break;
|
|
|
|
case VK_F1:
|
|
|
|
// F1 key for image info
|
|
|
|
UpdateImageInfo();
|
|
DisplayImageInfo();
|
|
break;
|
|
|
|
case VK_F2:
|
|
// F2 for property items
|
|
|
|
DoGetProperties();
|
|
|
|
break;
|
|
|
|
case VK_F3:
|
|
|
|
// F3 key for animation
|
|
|
|
DoAnimated();
|
|
|
|
break;
|
|
|
|
case VK_F4:
|
|
// F4 for ICM
|
|
|
|
DoICM();
|
|
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc(hwnd, iMsg, wParam, lParam);
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
DoPaint(hwnd);
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
g_iWinWidth = LOWORD(lParam);
|
|
g_iWinHeight = HIWORD(lParam);
|
|
|
|
if ( g_fFitToWindow_w == TRUE )
|
|
{
|
|
g_dScale = (REAL)g_iWinWidth / g_ImageWidth;
|
|
}
|
|
else if ( g_fFitToWindow_h == TRUE )
|
|
{
|
|
g_dScale = (REAL)g_iWinHeight / g_ImageHeight;
|
|
}
|
|
|
|
// Resize the status window
|
|
|
|
int x;
|
|
int y;
|
|
int cx;
|
|
int cy;
|
|
|
|
RECT rWindow;
|
|
|
|
// Keep status window height the same
|
|
|
|
GetWindowRect(g_hwndStatus, &rWindow);
|
|
cy = rWindow.bottom - rWindow.top;
|
|
|
|
x = 0;
|
|
y = g_iWinHeight - cy;
|
|
cx = g_iWinWidth;
|
|
MoveWindow(g_hwndStatus, x, y, cx, cy, TRUE);
|
|
SetWindowText(g_hwndStatus, "");
|
|
|
|
RefreshImageDisplay();
|
|
break;
|
|
|
|
case WM_MOUSEMOVE:
|
|
DoMouseMove(wParam, lParam);
|
|
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
KillTimer(g_hwndMain, 0);
|
|
|
|
DoNextPage();
|
|
|
|
if ( (UINT)g_iCurrentPageIndex < (g_uiTotalPages - 1) )
|
|
{
|
|
// View the next frame
|
|
|
|
SetTimer(g_hwndMain, 0, g_uiDelay * 10, NULL);
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
CleanUp();
|
|
|
|
PostQuitMessage(0);
|
|
|
|
break;
|
|
|
|
default:
|
|
return DefWindowProc(hwnd, iMsg, wParam, lParam);
|
|
}
|
|
|
|
return 0;
|
|
}// MyWindowProc()
|
|
|
|
//
|
|
// Create main application window
|
|
//
|
|
VOID
|
|
CreateMainWindow(
|
|
int iX,
|
|
int iY,
|
|
int iWidth,
|
|
int iHeight
|
|
)
|
|
{
|
|
HBRUSH hBrush = CreateHatchBrush(HS_HORIZONTAL,
|
|
RGB(0, 200, 0));
|
|
|
|
// Register window class
|
|
|
|
WNDCLASS wndClass =
|
|
{
|
|
CS_HREDRAW|CS_VREDRAW,
|
|
MyWindowProc,
|
|
0,
|
|
0,
|
|
g_hAppInstance,
|
|
LoadIcon(NULL, IDI_APPLICATION),
|
|
LoadCursor(NULL, IDC_ARROW),
|
|
hBrush,
|
|
MAKEINTRESOURCE(IDR_MAINMENU),
|
|
MYWNDCLASSNAME
|
|
};
|
|
|
|
RegisterClass(&wndClass);
|
|
|
|
g_hwndMain = CreateWindow(MYWNDCLASSNAME,
|
|
MYWNDCLASSNAME,
|
|
WS_OVERLAPPEDWINDOW,
|
|
iX,
|
|
iY,
|
|
iWidth,
|
|
iHeight,
|
|
NULL,
|
|
NULL,
|
|
g_hAppInstance,
|
|
NULL);
|
|
|
|
g_hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE,
|
|
(LPCSTR)"Ready",
|
|
g_hwndMain,
|
|
2);
|
|
|
|
if ( !g_hwndMain || (!g_hwndStatus) )
|
|
{
|
|
VERBOSE(("CreateMainWindow---CreateStatusWindow() failed"));
|
|
exit(-1);
|
|
}
|
|
}// CreateMainWindow()
|
|
|
|
//
|
|
// Main program entrypoint
|
|
//
|
|
INT _cdecl
|
|
main(
|
|
int argc,
|
|
char* argv[]
|
|
)
|
|
{
|
|
if (!gGdiplusInitHelper.IsValid())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Parse input parameters
|
|
|
|
ValidateArguments(argc, argv);
|
|
|
|
g_hAppInstance = GetModuleHandle(NULL);
|
|
|
|
g_iCurrentPageIndex = 0;
|
|
|
|
// Create the main application window
|
|
|
|
CreateMainWindow(g_iWinX, g_iWinY, g_iWinWidth, g_iWinHeight);
|
|
|
|
// Open an image
|
|
|
|
if ( OpenImageFile(g_acImageName) == FALSE )
|
|
{
|
|
// The user probably didn't give us image name or a wrong image name
|
|
// Create our own background image now
|
|
|
|
CreateBackgroundBitmap();
|
|
}
|
|
|
|
// After OpenImageFile() and CreateBackgroundBitmap(), we
|
|
// should have an IImage obj which points to the current frame/page. If not,
|
|
// end application
|
|
|
|
ShowWindow(g_hwndMain, SW_SHOW);
|
|
HMENU hMenu = GetMenu(g_hwndMain);
|
|
|
|
CheckMenuItem(hMenu, IDM_VIEW_OPTION_HIGHCUBIC, MF_BYCOMMAND | MF_CHECKED);
|
|
|
|
ResetImageAttribute();
|
|
CheckMenuItem(hMenu, IDM_VIEW_OPTION_WRAPMODEFLIPXY,
|
|
MF_BYCOMMAND | MF_CHECKED);
|
|
|
|
// Turn ICM on
|
|
|
|
CheckMenuItem(hMenu, IDM_EFFECT_ICC, MF_BYCOMMAND | MF_CHECKED);
|
|
|
|
// Main message loop
|
|
|
|
MSG msg;
|
|
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
return (INT)(msg.wParam);
|
|
}// main()
|
|
|
|
#if 0 // Set quality test
|
|
UINT uiSize = g_pImage->GetEncoderParameterListSize(&tempClsID);
|
|
EncoderParameters* pBuffer = (EncoderParameters*)malloc(uiSize);
|
|
rCode = g_pImage->GetEncoderParameterList(&tempClsID, uiSize,
|
|
pBuffer);
|
|
UINT qualityLevel = 50;
|
|
pMyEncoderParams->Parameter[0].Guid = EncoderQuality;
|
|
pMyEncoderParams->Parameter[0].Type = EncoderParameterValueTypeLong;
|
|
pMyEncoderParams->Parameter[0].NumberOfValues = 1;
|
|
pMyEncoderParams->Parameter[0].Value = (VOID*)&qualityLevel;
|
|
#endif
|
|
|
|
#if 0 // Save quantization table test
|
|
static const unsigned short luminance_tbl[64] = {
|
|
16, 11, 10, 16, 24, 40, 51, 61,
|
|
12, 12, 14, 19, 26, 58, 60, 55,
|
|
14, 13, 16, 24, 40, 57, 69, 56,
|
|
14, 17, 22, 29, 51, 87, 80, 62,
|
|
18, 22, 37, 56, 68, 109, 103, 77,
|
|
24, 35, 55, 64, 81, 104, 113, 92,
|
|
49, 64, 78, 87, 103, 121, 120, 101,
|
|
72, 92, 95, 98, 112, 100, 103, 99
|
|
};
|
|
static const unsigned short chrominance_tbl[64] = {
|
|
17, 18, 24, 47, 99, 99, 99, 99,
|
|
18, 21, 26, 66, 99, 99, 99, 99,
|
|
24, 26, 56, 99, 99, 99, 99, 99,
|
|
47, 66, 99, 99, 99, 99, 99, 99,
|
|
99, 99, 99, 99, 99, 99, 99, 99,
|
|
99, 99, 99, 99, 99, 99, 99, 99,
|
|
99, 99, 99, 99, 99, 99, 99, 99,
|
|
99, 99, 99, 99, 99, 99, 99, 99
|
|
};
|
|
|
|
pMyEncoderParams = (EncoderParameters*)malloc
|
|
(2 * sizeof(EncoderParameters));
|
|
|
|
pMyEncoderParams->Parameter[0].Guid = ENCODER_LUMINANCE_TABLE;
|
|
pMyEncoderParams->Parameter[0].Type = EncoderParameterValueTypeShort;
|
|
pMyEncoderParams->Parameter[0].NumberOfValues = 64;
|
|
pMyEncoderParams->Parameter[0].Value = (VOID*)luminance_tbl;
|
|
pMyEncoderParams->Parameter[1].Guid = ENCODER_CHROMINANCE_TABLE;
|
|
pMyEncoderParams->Parameter[1].Type = EncoderParameterValueTypeShort;
|
|
pMyEncoderParams->Parameter[1].NumberOfValues = 64;
|
|
pMyEncoderParams->Parameter[1].Value = (VOID*)chrominance_tbl;
|
|
pMyEncoderParams->Count = 2;
|
|
#endif // UNITTEST
|
|
|