1 /* 2 * PROJECT: PAINT for ReactOS 3 * LICENSE: LGPL 4 * FILE: base/applications/mspaint/dib.cpp 5 * PURPOSE: Some DIB related functions 6 * PROGRAMMERS: Benedikt Freisen 7 */ 8 9 /* INCLUDES *********************************************************/ 10 11 #include "precomp.h" 12 #include <math.h> 13 14 /* FUNCTIONS ********************************************************/ 15 16 HBITMAP 17 CreateDIBWithProperties(int width, int height) 18 { 19 BITMAPINFO bmi; 20 ZeroMemory(&bmi, sizeof(BITMAPINFO)); 21 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 22 bmi.bmiHeader.biWidth = width; 23 bmi.bmiHeader.biHeight = height; 24 bmi.bmiHeader.biPlanes = 1; 25 bmi.bmiHeader.biBitCount = 24; 26 bmi.bmiHeader.biCompression = BI_RGB; 27 return CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, NULL, NULL, 0); 28 } 29 30 HBITMAP 31 CreateColorDIB(int width, int height, COLORREF rgb) 32 { 33 HBITMAP ret = CreateDIBWithProperties(width, height); 34 if (!ret) 35 return NULL; 36 37 if (rgb) 38 { 39 HDC hdc = CreateCompatibleDC(NULL); 40 HGDIOBJ hbmOld = SelectObject(hdc, ret); 41 RECT rc; 42 SetRect(&rc, 0, 0, width, height); 43 HBRUSH hbr = CreateSolidBrush(rgb); 44 FillRect(hdc, &rc, hbr); 45 DeleteObject(hbr); 46 SelectObject(hdc, hbmOld); 47 DeleteDC(hdc); 48 } 49 50 return ret; 51 } 52 53 int 54 GetDIBWidth(HBITMAP hBitmap) 55 { 56 BITMAP bm; 57 GetObject(hBitmap, sizeof(BITMAP), &bm); 58 return bm.bmWidth; 59 } 60 61 int 62 GetDIBHeight(HBITMAP hBitmap) 63 { 64 BITMAP bm; 65 GetObject(hBitmap, sizeof(BITMAP), &bm); 66 return bm.bmHeight; 67 } 68 69 BOOL SaveDIBToFile(HBITMAP hBitmap, LPTSTR FileName, HDC hDC) 70 { 71 CImage img; 72 img.Attach(hBitmap); 73 img.Save(FileName); // TODO: error handling 74 img.Detach(); 75 76 WIN32_FIND_DATA find; 77 HANDLE hFind = FindFirstFile(FileName, &find); 78 if (hFind == INVALID_HANDLE_VALUE) 79 { 80 ShowFileLoadError(FileName); 81 return FALSE; 82 } 83 FindClose(hFind); 84 85 // update time and size 86 FILETIME ft; 87 FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft); 88 FileTimeToSystemTime(&ft, &fileTime); 89 fileSize = find.nFileSizeLow; 90 91 // TODO: update hRes and vRes 92 93 registrySettings.SetMostRecentFile(FileName); 94 95 isAFile = TRUE; 96 imageSaved = TRUE; 97 return TRUE; 98 } 99 100 void ShowFileLoadError(LPCTSTR name) 101 { 102 CString strText; 103 strText.Format(IDS_LOADERRORTEXT, (LPCTSTR) name); 104 CString strProgramName; 105 strProgramName.LoadString(IDS_PROGRAMNAME); 106 mainWindow.MessageBox(strText, strProgramName, MB_OK | MB_ICONEXCLAMATION); 107 } 108 109 HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL isFile) 110 { 111 if (hBitmap == NULL) 112 { 113 COLORREF white = RGB(255, 255, 255); 114 hBitmap = CreateColorDIB(registrySettings.BMPWidth, 115 registrySettings.BMPHeight, white); 116 if (hBitmap == NULL) 117 return FALSE; 118 119 fileHPPM = fileVPPM = 2834; 120 ZeroMemory(&fileTime, sizeof(fileTime)); 121 isFile = FALSE; 122 } 123 else 124 { 125 // update PPMs 126 HDC hScreenDC = GetDC(NULL); 127 fileHPPM = (int)(GetDeviceCaps(hScreenDC, LOGPIXELSX) * 1000 / 25.4); 128 fileVPPM = (int)(GetDeviceCaps(hScreenDC, LOGPIXELSY) * 1000 / 25.4); 129 ReleaseDC(NULL, hScreenDC); 130 } 131 132 // update image 133 imageModel.Insert(hBitmap); 134 imageModel.ClearHistory(); 135 136 // update fileSize 137 fileSize = dwFileSize; 138 139 // update filepathname 140 if (name && name[0]) 141 GetFullPathName(name, _countof(filepathname), filepathname, NULL); 142 else 143 LoadString(hProgInstance, IDS_DEFAULTFILENAME, filepathname, _countof(filepathname)); 144 145 // set title 146 CString strTitle; 147 strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(filepathname)); 148 mainWindow.SetWindowText(strTitle); 149 150 // update file info and recent 151 isAFile = isFile; 152 if (isAFile) 153 registrySettings.SetMostRecentFile(filepathname); 154 155 imageSaved = TRUE; 156 157 return hBitmap; 158 } 159 160 HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile) 161 { 162 // find the file 163 WIN32_FIND_DATA find; 164 HANDLE hFind = FindFirstFile(name, &find); 165 if (hFind == INVALID_HANDLE_VALUE) 166 { 167 // does not exist 168 CStringW strText; 169 strText.Format(IDS_LOADERRORTEXT, name); 170 MessageBoxW(hwnd, strText, NULL, MB_ICONERROR); 171 return NULL; 172 } 173 DWORD dwFileSize = find.nFileSizeLow; // get file size 174 FindClose(hFind); 175 176 // is file empty? 177 if (dwFileSize == 0) 178 { 179 if (fIsMainFile) 180 { 181 FILETIME ft; 182 FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft); 183 FileTimeToSystemTime(&ft, &fileTime); 184 return SetBitmapAndInfo(NULL, name, dwFileSize, TRUE); 185 } 186 } 187 188 // load the image 189 CImage img; 190 img.Load(name); 191 HBITMAP hBitmap = img.Detach(); 192 193 if (hBitmap == NULL) 194 { 195 // cannot open 196 CStringW strText; 197 strText.Format(IDS_LOADERRORTEXT, name); 198 MessageBoxW(hwnd, strText, NULL, MB_ICONERROR); 199 return NULL; 200 } 201 202 if (fIsMainFile) 203 { 204 FILETIME ft; 205 FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft); 206 FileTimeToSystemTime(&ft, &fileTime); 207 SetBitmapAndInfo(hBitmap, name, dwFileSize, TRUE); 208 } 209 210 return hBitmap; 211 } 212 213 HBITMAP Rotate90DegreeBlt(HDC hDC1, INT cx, INT cy, BOOL bRight) 214 { 215 HBITMAP hbm2 = CreateDIBWithProperties(cy, cx); 216 if (!hbm2) 217 return NULL; 218 219 HDC hDC2 = CreateCompatibleDC(NULL); 220 HGDIOBJ hbm2Old = SelectObject(hDC2, hbm2); 221 if (bRight) 222 { 223 for (INT y = 0; y < cy; ++y) 224 { 225 for (INT x = 0; x < cx; ++x) 226 { 227 COLORREF rgb = GetPixel(hDC1, x, y); 228 SetPixelV(hDC2, cy - (y + 1), x, rgb); 229 } 230 } 231 } 232 else 233 { 234 for (INT y = 0; y < cy; ++y) 235 { 236 for (INT x = 0; x < cx; ++x) 237 { 238 COLORREF rgb = GetPixel(hDC1, x, y); 239 SetPixelV(hDC2, y, cx - (x + 1), rgb); 240 } 241 } 242 } 243 SelectObject(hDC2, hbm2Old); 244 DeleteDC(hDC2); 245 return hbm2; 246 } 247 248 #ifndef M_PI 249 #define M_PI 3.14159265 250 #endif 251 252 HBITMAP SkewDIB(HDC hDC1, HBITMAP hbm, INT nDegree, BOOL bVertical) 253 { 254 if (nDegree == 0) 255 return CopyDIBImage(hbm); 256 257 const double eTan = tan(abs(nDegree) * M_PI / 180); 258 259 BITMAP bm; 260 GetObjectW(hbm, sizeof(bm), &bm); 261 INT cx = bm.bmWidth, cy = bm.bmHeight, dx = 0, dy = 0; 262 if (bVertical) 263 dy = INT(cx * eTan); 264 else 265 dx = INT(cy * eTan); 266 267 if (dx == 0 && dy == 0) 268 return CopyDIBImage(hbm); 269 270 HBITMAP hbmNew = CreateColorDIB(cx + dx, cy + dy, RGB(255, 255, 255)); 271 if (!hbmNew) 272 return NULL; 273 274 HDC hDC2 = CreateCompatibleDC(NULL); 275 HGDIOBJ hbm2Old = SelectObject(hDC2, hbmNew); 276 if (bVertical) 277 { 278 for (INT x = 0; x < cx; ++x) 279 { 280 INT delta = INT(x * eTan); 281 if (nDegree > 0) 282 BitBlt(hDC2, x, (dy - delta), 1, cy, hDC1, x, 0, SRCCOPY); 283 else 284 BitBlt(hDC2, x, delta, 1, cy, hDC1, x, 0, SRCCOPY); 285 } 286 } 287 else 288 { 289 for (INT y = 0; y < cy; ++y) 290 { 291 INT delta = INT(y * eTan); 292 if (nDegree > 0) 293 BitBlt(hDC2, (dx - delta), y, cx, 1, hDC1, 0, y, SRCCOPY); 294 else 295 BitBlt(hDC2, delta, y, cx, 1, hDC1, 0, y, SRCCOPY); 296 } 297 } 298 SelectObject(hDC2, hbm2Old); 299 DeleteDC(hDC2); 300 return hbmNew; 301 } 302