// // Sample code for using GDI+ // // Revision History: // // 10/01/1999 Min Liu (minliu) // Created it. // #include #include #include #include #include #include #include #include #include "imaging.h" #include #include #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(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(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