1 /* 2 * PROJECT: PAINT for ReactOS 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Loading/Saving an image file with getting/setting resolution 5 * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 8 #pragma once 9 10 class CImageDx : public CImage 11 { 12 public: 13 CImageDx() : CImage() 14 { 15 GetImageHorizontalResolution = NULL; 16 GetImageVerticalResolution = NULL; 17 BitmapSetResolution = NULL; 18 } 19 20 BOOL GetResolution(Gdiplus::GpImage *pImage, float *pxDpi, float *pyDpi) 21 { 22 *pxDpi = 96; 23 *pyDpi = 96; 24 25 if (GetImageHorizontalResolution == NULL || GetImageVerticalResolution == NULL) 26 { 27 GetImageHorizontalResolution = 28 AddrOf<GETIMAGEHORIZONTALRESOLUTION>("GdipGetImageHorizontalResolution"); 29 GetImageVerticalResolution = 30 AddrOf<GETIMAGEVERTICALRESOLUTION>("GdipGetImageVerticalResolution"); 31 } 32 33 if (GetImageHorizontalResolution == NULL || GetImageVerticalResolution == NULL) 34 return FALSE; 35 36 GetImageHorizontalResolution(pImage, pxDpi); 37 GetImageVerticalResolution(pImage, pyDpi); 38 return TRUE; 39 } 40 41 BOOL SetResolution(Gdiplus::GpBitmap *pBitmap, float xDpi, float yDpi) const 42 { 43 if (BitmapSetResolution == NULL) 44 BitmapSetResolution = AddrOf<BITMAPSETRESOLUTION>("GdipBitmapSetResolution"); 45 46 if (BitmapSetResolution == NULL) 47 return FALSE; 48 49 BitmapSetResolution(pBitmap, xDpi, yDpi); 50 return TRUE; 51 } 52 53 HRESULT LoadDx(LPCTSTR pszFileName, float *pxDpi, float *pyDpi) throw() 54 { 55 // convert the file name string into Unicode 56 CStringW pszNameW(pszFileName); 57 58 // create a GpBitmap object from file 59 using namespace Gdiplus; 60 GpBitmap *pBitmap = NULL; 61 if (GetCommon().CreateBitmapFromFile(pszNameW, &pBitmap) != Ok) 62 { 63 return E_FAIL; 64 } 65 66 // get bitmap handle 67 HBITMAP hbm = NULL; 68 Color color(0xFF, 0xFF, 0xFF); 69 Gdiplus::Status status; 70 status = GetCommon().CreateHBITMAPFromBitmap(pBitmap, &hbm, color.GetValue()); 71 72 // get the resolution 73 GetResolution((Gdiplus::GpImage*)pBitmap, pxDpi, pyDpi); 74 75 // delete GpBitmap 76 GetCommon().DisposeImage(pBitmap); 77 78 // attach it 79 if (status == Ok) 80 Attach(hbm); 81 return (status == Ok ? S_OK : E_FAIL); 82 } 83 84 HRESULT SaveDx(LPCTSTR pszFileName, REFGUID guidFileType = GUID_NULL, 85 float xDpi = 0, float yDpi = 0) const throw() 86 { 87 using namespace Gdiplus; 88 ATLASSERT(m_hbm); 89 90 // TODO & FIXME: set parameters (m_rgbTransColor etc.) 91 92 // convert the file name string into Unicode 93 CStringW pszNameW(pszFileName); 94 95 // if the file type is null, get the file type from extension 96 const GUID *FileType = &guidFileType; 97 if (IsGuidEqual(guidFileType, GUID_NULL)) 98 { 99 LPCWSTR pszExt = GetFileExtension(pszNameW); 100 FileType = FileTypeFromExtension(pszExt); 101 } 102 103 // get CLSID from file type 104 CLSID clsid; 105 if (!GetClsidFromFileType(&clsid, FileType)) 106 return E_FAIL; 107 108 // create a GpBitmap from HBITMAP 109 GpBitmap *pBitmap = NULL; 110 GetCommon().CreateBitmapFromHBITMAP(m_hbm, NULL, &pBitmap); 111 112 // set the resolution 113 SetResolution(pBitmap, xDpi, yDpi); 114 115 // save to file 116 Status status; 117 status = GetCommon().SaveImageToFile(pBitmap, pszNameW, &clsid, NULL); 118 119 // destroy GpBitmap 120 GetCommon().DisposeImage(pBitmap); 121 122 return (status == Ok ? S_OK : E_FAIL); 123 } 124 125 protected: 126 // get procedure address of the DLL 127 template <typename TYPE> 128 TYPE AddrOf(const char *name) const 129 { 130 FARPROC proc = ::GetProcAddress(GetCommon().hinstGdiPlus, name); 131 return reinterpret_cast<TYPE>(proc); 132 } 133 134 typedef St (WINGDIPAPI *GETIMAGEHORIZONTALRESOLUTION)(Im *, float*); 135 typedef St (WINGDIPAPI *GETIMAGEVERTICALRESOLUTION)(Im *, float*); 136 typedef St (WINGDIPAPI *BITMAPSETRESOLUTION)(Bm *, float, float); 137 138 GETIMAGEHORIZONTALRESOLUTION GetImageHorizontalResolution; 139 GETIMAGEVERTICALRESOLUTION GetImageVerticalResolution; 140 mutable BITMAPSETRESOLUTION BitmapSetResolution; 141 }; 142