1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Utility Toolkit Sources
4 // Copyright (C) 2000-2008 by Denton Woods
5 // Last modified: 12/14/2008
6 //
7 // Filename: src-ILUT/src/ilut_win32.c
8 //
9 // Description: Windows functions for images
10 //
11 //-----------------------------------------------------------------------------
12 
13 
14 #include "ilut_internal.h"
15 #ifdef ILUT_USE_WIN32
16 #include <windows.h>
17 #include <wininet.h>
18 
19 // For ilutWinLoadUrl().
20 #ifdef _MSC_VER
21 #pragma comment(lib, "wininet.lib")
22 #endif
23 
24 
25 #if !_WIN32_WCE && (_WIN32 && __GNUC__)
26 	PRINTDLG	Pd;
27 #endif//_WIN32_WCE
28 
ilutWin32Init()29 ILboolean ilutWin32Init()
30 {
31 
32 
33 	return IL_TRUE;
34 }
35 
36 
ilutConvertSliceToHBitmap(HDC hDC,ILuint slice)37 ILAPI HBITMAP ILAPIENTRY ilutConvertSliceToHBitmap(HDC hDC, ILuint slice)
38 {
39 	ILubyte		*Data, *DataBackup;
40 	HBITMAP		hBitmap = NULL;
41 	ILimage		*TempImage = NULL;
42 	ILuint		pad, i, j, k, l, m, n, DepthBackup;
43 	ILpal		*palImg;
44 	ILboolean	alloc_buffer;
45 
46 	//reserve space for palette in every case...
47 	ILubyte		buff[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)];
48 	BITMAPINFO	*info = (BITMAPINFO*)buff;
49 	RGBQUAD		*pal = info->bmiColors;
50 
51 	ilutCurImage = ilGetCurImage();
52 	if (ilutCurImage == NULL) {
53 		ilSetError(ILUT_ILLEGAL_OPERATION);
54 		return NULL;
55 	}
56 
57 	//check if the image has the wanted slice
58 	if (slice < 0 || slice >= ilutCurImage->Depth) {
59 		ilSetError(ILUT_INVALID_PARAM);
60 		return NULL;
61 	}
62 
63 	// Fool iConvertImage into thinking that the current image has
64 	//   only one slice, the one we want:
65 	DepthBackup = ilutCurImage->Depth;
66 	DataBackup = ilutCurImage->Data;
67 	ilutCurImage->Depth = 1;
68 	ilutCurImage->Data += ilutCurImage->SizeOfPlane*slice;
69 
70 	if (ilutCurImage->Type != IL_UNSIGNED_BYTE)
71 		TempImage = iConvertImage(ilutCurImage, ilutCurImage->Format, IL_UNSIGNED_BYTE);
72 	else
73 		TempImage = ilutCurImage;
74 	if (TempImage == NULL) {
75 		goto error;
76 	}
77 
78 	//changed 2003-09-09: use Temp!
79 	ilSetCurImage(TempImage);
80 
81 	hBitmap = CreateCompatibleBitmap(hDC, ilutCurImage->Width, ilutCurImage->Height);
82 	if (hBitmap == NULL) {
83 		ilSetError(IL_UNKNOWN_ERROR);
84 		goto error;
85 	}
86 
87 	info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
88 	info->bmiHeader.biWidth = TempImage->Width;
89 	if (TempImage->Origin == IL_ORIGIN_UPPER_LEFT)
90 		info->bmiHeader.biHeight = -(ILint)TempImage->Height;
91 	else
92 		info->bmiHeader.biHeight = TempImage->Height;
93 	info->bmiHeader.biPlanes = 1;
94 	info->bmiHeader.biCompression = 0;
95 	info->bmiHeader.biSizeImage = 0;
96 	info->bmiHeader.biXPelsPerMeter = 0;
97 	info->bmiHeader.biYPelsPerMeter = 0;
98 	info->bmiHeader.biClrUsed = 0;
99 	info->bmiHeader.biClrImportant = 0;
100 
101 	pad = (4 - TempImage->Bps%4)%4;
102 	alloc_buffer = (ILboolean)!(pad == 0 && TempImage->Format != IL_RGB
103 		&& TempImage->Format != IL_RGBA && TempImage->Format != IL_LUMINANCE_ALPHA);
104 	if (!alloc_buffer) {
105 		Data = TempImage->Data;
106 	}
107 	else {
108 		ILsizei DataSize = 0;
109 		if (TempImage->Format == IL_RGBA) {  // Strip alpha during byte swapping for faster upload to GDI.
110 			// Recalculate pad, because it changes when bpp changes.
111 			pad = (4 - (3 * TempImage->Width) % 4) % 4;
112 			DataSize = (TempImage->Width + pad) * TempImage->Height * 3;
113 		}
114 		// Strip alpha channel from grayscale image.
115 		else if (TempImage->Format == IL_LUMINANCE_ALPHA) {
116 			// Added 01-09-2009: Recalculate pad.
117 			pad = (4 - TempImage->Width % 4) % 4;
118 			DataSize = (TempImage->Width + pad) * TempImage->Height;
119 		}
120 		else {
121 			DataSize = (TempImage->Width + pad) * TempImage->Height * TempImage->Bpp;
122 		}
123 
124 		Data = (ILubyte*)ialloc(DataSize);
125 		if (Data == NULL) {
126 			goto error;
127 		}
128 
129 		if (TempImage->Format == IL_RGB || TempImage->Format == IL_RGBA) {
130 			//swap bytes
131 			m = (TempImage->Format == IL_RGB)?3:4;
132 			k = l = 0;
133 			for (j = 0; j < TempImage->Height; j++) {
134 				for (i = 0, n = 0; i < 3*TempImage->Width; i += 3, n += m) {
135 					Data[l + i] = TempImage->Data[k + n + 2];
136 					Data[l + i + 1] = TempImage->Data[k + n + 1];
137 					Data[l + i + 2] = TempImage->Data[k + n];
138 				}
139 
140 				k += TempImage->Bps;
141 				l += 3*TempImage->Width + pad;
142 			}
143 		}
144 		else if (TempImage->Format == IL_LUMINANCE_ALPHA) {
145 			//strip alpha channel
146 			//recalculate pad because it included alpha channel info
147 			pad = (4 - TempImage->Width%4)%4;
148 			k = l = 0;
149 			for (j = 0; j < TempImage->Height; j++) {
150 				for (i = 0, n = 0; i < TempImage->Width; ++i, n += 2) {
151 					Data[l + i] = TempImage->Data[k + n];
152 				}
153 				k += TempImage->Bps;
154 				l += TempImage->Width + pad;
155 			}
156 		}
157 		else
158 			for (i = 0; i < TempImage->Height; i++)
159 				memcpy(Data + i*(TempImage->Bps + pad), TempImage->Data + i*TempImage->Bps, TempImage->Bps);
160 	}
161 
162 	switch (TempImage->Format)
163 	{
164 		case IL_LUMINANCE:
165 		case IL_LUMINANCE_ALPHA:
166 		case IL_COLOUR_INDEX:
167 			if (TempImage->Format != IL_COLOUR_INDEX) {
168 				//generate greyscale palette
169 				for (i = 0; i < 256; i++)
170 					pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (ILubyte)i;
171 			}
172 			else {
173 				palImg = iConvertPal(&TempImage->Pal, IL_PAL_BGR32);
174 				if (palImg != NULL) {
175 					memcpy(pal, palImg->Palette, palImg->PalSize);
176 					ilClosePal(palImg);
177 				}
178 				else {
179 					//ilSetError(IL_INVALID_PARAM);
180 					// Generate greyscale palette  <-- Why is this here?
181 					for (i = 0; i < 256; i++)
182 						pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (ILubyte)i;
183 				}
184 			}
185 			info->bmiHeader.biBitCount = 8;
186 			break;
187 
188 		case IL_RGB:
189 		case IL_BGR:
190 		case IL_RGBA: //alpha is removed during byte swapping
191 			info->bmiHeader.biBitCount = 24;
192 			break;
193 
194 		case IL_BGRA:
195 			info->bmiHeader.biBitCount = 32;
196 			break;
197 
198 		/*default:
199 			ilSetError(IL_FORMAT_NOT_SUPPORTED);
200 			return hBitmap;*/
201 	}
202 
203 	// Restore original data
204 	ilutCurImage->Data = DataBackup;
205 	ilutCurImage->Depth = DepthBackup;
206 
207 	SetDIBits(hDC, hBitmap, 0, ilutCurImage->Height, Data, info, DIB_RGB_COLORS);
208 
209 	if (alloc_buffer)
210 		ifree(Data);
211 
212 	if (ilutCurImage != TempImage) {
213 		ilSetCurImage(ilutCurImage);
214 		ilCloseImage(TempImage);
215 	}
216 
217 	return hBitmap;
218 
219 error:
220 	// Restore original data
221 	ilutCurImage->Data = DataBackup;
222 	ilutCurImage->Depth = DepthBackup;
223 	if (ilutCurImage != TempImage) {
224 		ilSetCurImage(ilutCurImage);
225 		ilCloseImage(TempImage);
226 	}
227 	ilSetCurImage(ilutCurImage);
228 	if (hBitmap)
229 		DeleteObject(hBitmap);
230 
231 	return NULL;
232 }
233 
ilutConvertToHBitmap(HDC hDC)234 HBITMAP ILAPIENTRY ilutConvertToHBitmap(HDC hDC)
235 {
236 	return ilutConvertSliceToHBitmap(hDC, 0);
237 }
238 
iGetPaddedData(ILimage * Image)239 ILubyte* ILAPIENTRY iGetPaddedData(ILimage *Image)
240 {
241 	ILubyte	*NewData = NULL, *TempBuff = NULL;
242 	ILuint	i, CurPos = 0, PadSize;
243 	ILubyte	*TempData = NULL;
244 
245 	if (Image == NULL) {
246 		ilSetError(ILUT_INVALID_PARAM);
247 		return NULL;
248 	}
249 
250 	if (Image->Origin != IL_ORIGIN_LOWER_LEFT) {
251 		TempData = iGetFlipped(Image);
252 	}
253 	else {
254 		TempData = Image->Data;
255 	}
256 
257 	if (Image->Format == IL_RGB || Image->Format == IL_RGBA) {
258 		TempBuff = (ILubyte*)ialloc(Image->SizeOfData);
259 
260 		if (TempBuff == NULL) {
261 			return NULL;
262 		}
263 		// Swap red and blue.
264 		for (i = 0; i < Image->SizeOfData; i += Image->Bpp) {
265 			TempBuff[i] = TempData[i+2];
266 			TempBuff[i+1] = TempData[i+1];
267 			TempBuff[i+2] = TempData[i];
268 			// Copy the alpha channel if present.
269 			if (Image->Bpp == 4)
270 				TempBuff[i+3] = TempData[i+3];
271 		}
272 	}
273 	else {
274 		TempBuff = TempData;
275 	}
276 
277 	PadSize = (4 - (Image->Bps % 4)) % 4;
278 	NewData = (ILubyte*)ialloc((Image->Width + PadSize) * Image->Height * Image->Bpp);
279 	if (NewData == NULL) {
280 		return NULL;
281 	}
282 
283 	for (i = 0; i < Image->Height; i++) {
284 		memcpy(NewData + CurPos, TempBuff + Image->Bps * i, Image->Bps);
285 		CurPos += Image->Bps;
286 		memset(NewData + CurPos, 0, PadSize);
287 		CurPos += PadSize;
288 	}
289 
290 	if (TempData != TempBuff && TempData != Image->Data)
291 		ifree(TempData);
292 	if (TempBuff != Image->Data)
293 		ifree(TempBuff);
294 
295 	return NewData;
296 }
297 
298 
299 
ilutFreePaddedData(ILubyte * Data)300 void ILAPIENTRY ilutFreePaddedData(ILubyte *Data)
301 {
302 	ifree(Data);
303 	return;
304 }
305 
306 
307 // DirectX/GDI insists that all scanlines end on a dword boundary. =(
ilutGetPaddedData()308 ILubyte* ILAPIENTRY ilutGetPaddedData()
309 {
310 	return iGetPaddedData(ilGetCurImage());
311 }
312 
313 
314 // @TODO:  Figure how to mess with multiple bpc's!
ilutGetBmpInfo(BITMAPINFO * Info)315 void ILAPIENTRY ilutGetBmpInfo(BITMAPINFO *Info)
316 {
317 	ILuint NewBps, Padding;
318 
319 	ilutCurImage = ilGetCurImage();
320 	if (ilutCurImage == NULL) {
321 		ilSetError(ILUT_ILLEGAL_OPERATION);
322 		return;
323 	}
324 
325 	Padding = (4 - (ilutCurImage->Bps % 4)) % 4;
326 	NewBps = ilutCurImage->Bps/* + Padding*/;
327 
328 	Info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
329 	Info->bmiHeader.biWidth = ilutCurImage->Width;
330 	Info->bmiHeader.biHeight = ilutCurImage->Height;
331 	Info->bmiHeader.biPlanes = 1;
332 	Info->bmiHeader.biBitCount = ilutCurImage->Bpp << 3;
333 	Info->bmiHeader.biCompression = BI_RGB;
334 	Info->bmiHeader.biSizeImage = NewBps * ilutCurImage->Height;
335 	Info->bmiHeader.biXPelsPerMeter = 0;
336 	Info->bmiHeader.biYPelsPerMeter = 0;
337 	Info->bmiHeader.biClrUsed = ilutCurImage->Bpp == 1 ? 255 : 0;
338 	if (Info->bmiHeader.biClrUsed < 24)
339 		Info->bmiHeader.biClrImportant = Info->bmiHeader.biClrUsed;
340 	else
341 		Info->bmiHeader.biClrImportant = 0;
342 
343 	return;
344 }
345 
346 
347 //! Just a convenience function.
ilutWinLoadImage(ILstring FileName,HDC hDC)348 HBITMAP ILAPIENTRY ilutWinLoadImage(ILstring FileName, HDC hDC)
349 {
350 	HBITMAP	Bitmap;
351 
352 	iBindImageTemp();
353 	if (!ilLoadImage(FileName))
354 		return 0;
355 
356 	Bitmap = ilutConvertToHBitmap(hDC);
357 
358 	return Bitmap;
359 }
360 
361 
362 #ifndef _WIN32_WCE
ilutWinSaveImage(ILstring FileName,HBITMAP Bitmap)363 ILboolean ILAPIENTRY ilutWinSaveImage(ILstring FileName, HBITMAP Bitmap)
364 {
365 	ILuint		CurName;
366 	ILboolean	Saved;
367 
368 	CurName = ilGetCurName();
369 
370 	iBindImageTemp();
371 
372 	if (!ilutSetHBitmap(Bitmap)) {
373 		ilBindImage(CurName);
374 		return IL_FALSE;
375 	}
376 
377 	Saved = ilSaveImage(FileName);
378 	ilBindImage(CurName);
379 
380 	return Saved;
381 }
382 #endif//_WIN32_WCE
383 
384 
385 // @TODO:  Just create a copy of the palette!
386 // Credit for this goes to the OpenGL SuperBible.
ilutGetHPal()387 HPALETTE ILAPIENTRY ilutGetHPal()
388 {
389 	HPALETTE	Palette;
390 	LOGPALETTE	*LogPal;
391 	ILuint		NumEntries, i;
392 	ILenum		CurPalType;
393 
394 	ilutCurImage = ilGetCurImage();
395 	if (ilutCurImage == NULL) {
396 		ilSetError(ILUT_ILLEGAL_OPERATION);
397 		return NULL;
398 	}
399 
400 	if (!ilutCurImage->Pal.Palette || !ilutCurImage->Pal.PalSize || ilutCurImage->Pal.PalType == IL_PAL_NONE) {
401 		//ilSetError(ILUT_ILLEGAL_OPERATION);
402 		return NULL;
403 	}
404 
405 	CurPalType = ilutCurImage->Pal.PalType;
406 	if (!ilConvertPal(IL_PAL_RGB24)) {
407 		return NULL;  // ilConvertPal already sets the error
408 	}
409 	NumEntries = ilutCurImage->Pal.PalSize / 3;
410 
411 	LogPal = (LOGPALETTE*)ialloc(sizeof(LOGPALETTE) + NumEntries * sizeof(PALETTEENTRY));
412 	if (!LogPal) {
413 		return NULL;
414 	}
415 
416 	LogPal->palVersion = 0x300;
417 	LogPal->palNumEntries = (WORD)NumEntries;
418 
419 	for (i = 0; i < NumEntries; i++) {
420 		LogPal->palPalEntry[i].peRed   = ilutCurImage->Pal.Palette[i * 3];
421 		LogPal->palPalEntry[i].peGreen = ilutCurImage->Pal.Palette[i * 3 + 1];
422 		LogPal->palPalEntry[i].peBlue  = ilutCurImage->Pal.Palette[i * 3 + 2];
423 		LogPal->palPalEntry[i].peFlags = 0;
424 	}
425 
426 	Palette = CreatePalette(LogPal);
427 	ifree(LogPal);
428 
429 	ilConvertPal(CurPalType);  // Should we check the return value?
430 
431 	return Palette;
432 }
433 
434 
ilutSetHBitmap(HBITMAP Bitmap)435 ILboolean ILAPIENTRY ilutSetHBitmap(HBITMAP Bitmap)
436 {
437 #ifndef _WIN32_WCE
438 	BITMAPINFO	Info[2];
439 	HWND		hWnd;
440 	HDC			hDC;
441 	ILubyte		*Buffer1 = NULL, *Buffer2 = NULL;
442 	ILuint		i, j, PadSize, Bps;
443 
444 	ilutCurImage = ilGetCurImage();
445 	if (ilutCurImage == NULL) {
446 		ilSetError(ILUT_ILLEGAL_OPERATION);
447 		return IL_FALSE;
448 	}
449 
450 	hWnd = GetForegroundWindow();
451 	hDC = GetDC(hWnd);
452 
453 	// Query the dimensions
454 	memset(&Info, 0, sizeof(BITMAPINFO));
455 	Info[0].bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
456 	GetDIBits(hDC, Bitmap, 0, 0, NULL, Info, DIB_RGB_COLORS);
457 
458 	// @TODO:  Implement this shitz0rz!
459 	if (Info[0].bmiHeader.biBitCount < 24) {
460 		ReleaseDC(hWnd, hDC); //added 20040527
461 		return IL_FALSE;
462 	}
463 
464 	Buffer1 = (ILubyte*)ialloc(Info[0].bmiHeader.biSizeImage);
465 	Buffer2 = (ILubyte*)ialloc(Info[0].bmiHeader.biSizeImage);
466 	if (Buffer1 == NULL || Buffer2 == NULL) {
467 		ReleaseDC(hWnd, hDC); //added 20040527
468 		ifree(Buffer1);
469 		ifree(Buffer2);
470 		return IL_FALSE;
471 	}
472 
473 	//GetBitmapBits
474 	GetDIBits(hDC, Bitmap, 0, Info[0].bmiHeader.biHeight, Buffer1, Info, DIB_RGB_COLORS);
475 
476 	Bps = Info[0].bmiHeader.biWidth * (Info[0].bmiHeader.biBitCount >> 3);
477 	PadSize = (4 - (Bps % 4)) % 4;
478 
479 	// Remove the padding.
480 	for (i = 0, j = 0; i < Info[0].bmiHeader.biSizeImage; i += Bps + PadSize, j += Bps) {
481 		memcpy(Buffer2 + j, Buffer1 + i, Bps);
482 	}
483 
484 	if (Info[0].bmiHeader.biBitCount == 24) {
485 		ilTexImage(Info[0].bmiHeader.biWidth, Info[0].bmiHeader.biHeight, 1,
486 			(ILubyte)(Info[0].bmiHeader.biBitCount >> 3), IL_BGR, IL_UNSIGNED_BYTE, Buffer2);
487 	}
488 	else if (Info[0].bmiHeader.biBitCount == 32) {
489 		ilTexImage(Info[0].bmiHeader.biWidth, Info[0].bmiHeader.biHeight, 1,
490 			(ILubyte)(Info[0].bmiHeader.biBitCount >> 3), IL_BGRA, IL_UNSIGNED_BYTE, Buffer2);
491 	}
492 	ilutCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
493 
494 	ReleaseDC(hWnd, hDC); //added 20040527
495 	ifree(Buffer1);
496 	ifree(Buffer2);
497 
498 #endif//_WIN32_WCE
499 
500 	return IL_TRUE;
501 }
502 
503 
ilutSetHPal(HPALETTE Pal)504 ILboolean ILAPIENTRY ilutSetHPal(HPALETTE Pal)
505 {
506 	LPPALETTEENTRY	PalEntries;
507 	ILuint			NumEntries, i;
508 	ILubyte			*TempPal;
509 
510 	ilutCurImage = ilGetCurImage();
511 	if (ilutCurImage == NULL) {
512 		ilSetError(ILUT_ILLEGAL_OPERATION);
513 		return IL_FALSE;
514 	}
515 
516 	NumEntries = GetPaletteEntries(Pal, 0, 0, NULL);
517 	if (NumEntries == 0)
518 		return IL_TRUE;  // @TODO:  Determine if correct...
519 
520 	PalEntries = (LPPALETTEENTRY)ialloc(NumEntries * sizeof(PALETTEENTRY));
521 	if (PalEntries == NULL) {
522 		return IL_FALSE;
523 	}
524 
525 	NumEntries = GetPaletteEntries(Pal, 0, NumEntries, PalEntries);
526 
527 	TempPal = (ILubyte*)ialloc(NumEntries * 3);
528 	if (TempPal == NULL) {
529 		ifree(PalEntries);
530 		return IL_FALSE;
531 	}
532 	if (ilutCurImage->Pal.Palette)
533 		ifree(ilutCurImage->Pal.Palette);
534 	ilutCurImage->Pal.Palette = TempPal;
535 	ilutCurImage->Pal.PalSize = NumEntries * 3;
536 	ilutCurImage->Pal.PalType = IL_PAL_RGB24;
537 
538 	for (i = 0; i < NumEntries; i++) {
539 		*TempPal++ = PalEntries[i].peRed;
540 		*TempPal++ = PalEntries[i].peGreen;
541 		*TempPal++ = PalEntries[i].peBlue;
542 	}
543 
544 	ifree(PalEntries);
545 
546 	return IL_TRUE;
547 }
548 
549 
ilutSetWinClipboard()550 ILboolean ILAPIENTRY ilutSetWinClipboard()
551 {
552 	HBITMAP	Bitmap;
553 	HANDLE	Handle;
554 	HWND	hWnd;
555 	HDC		hDC;
556 	ILimage	*TempImage, *CurImage;
557 
558 	ilutCurImage = ilGetCurImage();
559 	if (ilutCurImage == NULL) {
560 		ilSetError(ILUT_ILLEGAL_OPERATION);
561 		return IL_FALSE;
562 	}
563 
564 	if (ilutCurImage->Format != IL_BGR || ilutCurImage->Bps > 1) {
565 		TempImage = iConvertImage(ilutCurImage, IL_BGR, IL_UNSIGNED_BYTE);
566 		if (TempImage == NULL)
567 			return IL_FALSE;
568 	}
569 	else
570 		TempImage = ilutCurImage;
571 
572 	CurImage = ilutCurImage;
573 	ilSetCurImage(TempImage);
574 
575 	hWnd = GetForegroundWindow();
576 	hDC = GetDC(hWnd);
577 
578 	if (!OpenClipboard(NULL)) {
579 		if (TempImage != ilutCurImage)
580 			ilCloseImage(TempImage);
581 		ilSetCurImage(CurImage);
582 		ilSetError(ILUT_ILLEGAL_OPERATION);  // Dunno if this is the correct error.
583 		ReleaseDC(hWnd, hDC); //added 20040604
584 		if (TempImage != ilutCurImage)
585 			ilCloseImage(TempImage);
586 		ilSetCurImage(CurImage);
587 		return IL_FALSE;
588 	}
589 
590 	//note that this is not the best method to put an image into the
591 	//clipboard, CF_DIB is much better because HBITMAPS are device-dependent.
592 	//TODO: eventually change that if there is a need
593 	Bitmap = ilutConvertToHBitmap(hDC);
594 	ReleaseDC(hWnd, hDC); //added 20040604
595 
596 	EmptyClipboard();
597 	Handle = SetClipboardData(CF_BITMAP, Bitmap);
598 
599 	CloseClipboard();
600 
601 	//DeleteObject(Bitmap);  // Needed? No! Clipboard takes care of image.
602 
603 	if (TempImage != ilutCurImage)
604 		ilCloseImage(TempImage);
605 	ilSetCurImage(CurImage);
606 
607 	return IL_TRUE;
608 }
609 
610 
ilutGetWinClipboard()611 ILboolean ILAPIENTRY ilutGetWinClipboard()
612 {
613 	//HBITMAP		Bitmap;
614 	HWND		hWnd;
615 	HGLOBAL		hGlobal;
616 	PTSTR		pGlobal, data;
617 	BITMAPFILEHEADER	*BmpHeader;
618 	BITMAPINFOHEADER	*InfoHeader;
619 	SIZE_T		Size;
620 
621 	ilutCurImage = ilGetCurImage();
622 	if (ilutCurImage == NULL) {
623 		ilSetError(ILUT_ILLEGAL_OPERATION);
624 		return IL_FALSE;
625 	}
626 
627 	if (IsClipboardFormatAvailable(CF_DIB)) {
628 		hWnd = GetForegroundWindow();
629 
630 		if (!OpenClipboard(hWnd)) {
631 			ilSetError(ILUT_ILLEGAL_OPERATION);  // Dunno if this is the correct error.
632 			return IL_FALSE;
633 		}
634 
635 		hGlobal = GetClipboardData(CF_DIB);
636 		if (!hGlobal) {
637 			CloseClipboard();
638 			return IL_FALSE;  // No error?
639 		}
640 
641 		//copy DIB to buffer because windows delivers it without the
642 		//BITMAPFILEHEADER that DevIL needs to load the image
643 		Size = GlobalSize(hGlobal);
644 		//@TODO: Size should never be larger than an ILuint?
645 		data = (PTSTR)ialloc((ILuint)Size + sizeof(BITMAPFILEHEADER));
646 		pGlobal = (PTSTR)GlobalLock(hGlobal);
647 		if (!pGlobal || !data) {
648 			ifree(data);
649 			CloseClipboard();
650 			return IL_FALSE;  // No error?
651 		}
652 		memcpy(data + sizeof(BITMAPFILEHEADER), pGlobal, Size);
653 		GlobalUnlock(hGlobal);
654 		CloseClipboard();
655 
656 		//create BITMAPFILEHEADER
657 		InfoHeader = (BITMAPINFOHEADER*)(data + sizeof(BITMAPFILEHEADER));
658 		BmpHeader = (BITMAPFILEHEADER*)data;
659 		BmpHeader->bfType = 'B' | ('M' << 8);
660 		//@TODO: Again, could it ever be larger than an unsigned integer (DWORD)?
661 		BmpHeader->bfSize = (DWORD)Size + sizeof(BITMAPFILEHEADER);
662 		BmpHeader->bfReserved1 = BmpHeader->bfReserved2 = 0;
663 		BmpHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + InfoHeader->biSize + InfoHeader->biClrUsed*4;
664 		if (InfoHeader->biCompression == BI_BITFIELDS)
665 			BmpHeader->bfOffBits += 12;
666 
667 		return ilLoadL(IL_BMP, data, BmpHeader->bfSize);
668 	}
669 	/*
670 	//this is not required becaus CF_BITMAP is converted to CF_DIB automatically
671 	//when needed. CF_DIB suffices.
672 	else if (IsClipboardFormatAvailable(CF_BITMAP)) {
673 		hWnd = GetForegroundWindow();
674 
675 		if (!OpenClipboard(hWnd)) {
676 			ilSetError(ILUT_ILLEGAL_OPERATION);  // Dunno if this is the correct error.
677 			return IL_FALSE;
678 		}
679 
680 		Bitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
681 		if (!Bitmap) {
682 			CloseClipboard();
683 			return IL_FALSE;  // No error?
684 		}
685 
686 		if (!ilutSetHBitmap(Bitmap)) {
687 			CloseClipboard();
688 			return IL_FALSE;
689 		}
690 
691 		CloseClipboard();
692 	}*/
693 
694 	//no data in clipboard
695 	ilSetError(ILUT_ILLEGAL_OPERATION);
696 	return IL_FALSE;
697 }
698 
699 
ilutWinPrint(ILuint XPos,ILuint YPos,ILuint Width,ILuint Height,HDC hDC)700 ILboolean ILAPIENTRY ilutWinPrint(ILuint XPos, ILuint YPos, ILuint Width, ILuint Height, HDC hDC)
701 {
702 #if !defined(_WIN32_WCE) && !(defined(_WIN32) && defined(__GNUC__))
703 	PRINTDLG	Pd;
704 	DOCINFO		Di;
705 	HBITMAP		Bitmap, hReplaced;
706 	HDC			hMemDC;
707 
708 	ilutCurImage = ilGetCurImage();
709 	if (ilutCurImage == NULL) {
710 		ilSetError(ILUT_ILLEGAL_OPERATION);
711 		return IL_FALSE;
712 	}
713 
714 	//@TODO: Needs error checking!
715 	hMemDC = CreateCompatibleDC(hDC);
716 	Bitmap = ilutConvertToHBitmap(hDC);
717 	hReplaced = (HBITMAP)SelectObject(hMemDC, Bitmap);
718 
719 	memset(&Pd, 0, sizeof(PRINTDLG));
720 	Pd.lStructSize = sizeof(PRINTDLG);
721 	Pd.hwndOwner = GetForegroundWindow();
722 	Pd.Flags = PD_RETURNDC;
723 	Pd.nCopies = 1;
724 	Pd.nFromPage = 0xFFFF;
725 	Pd.nToPage = 0xFFFF;
726 	Pd.nMinPage = 1;
727 	Pd.nMaxPage = 0xFFFF;
728 
729 	if (!PrintDlg(&Pd))
730 		return (0L);
731 
732 	Di.cbSize = sizeof(DOCINFO);
733 	Di.lpszDocName = IL_TEXT("DevIL Print Job");
734 	Di.lpszOutput = NULL;
735 	Di.lpszDatatype = NULL;
736 	Di.fwType = 0;
737 
738 	StartDoc(Pd.hDC, &Di);
739 	StartPage(Pd.hDC);
740 
741 	StretchBlt(Pd.hDC, XPos, YPos, Width, Height, hMemDC, 0, 0, ilutCurImage->Width, ilutCurImage->Height, SRCCOPY);
742 
743 	EndPage(Pd.hDC);
744 	EndDoc(Pd.hDC);
745 	DeleteObject(Bitmap);
746 	DeleteObject(hReplaced);
747 	DeleteDC(Pd.hDC);
748 
749 #endif
750 
751 	return IL_TRUE;
752 }
753 
754 
ilutLoadResource(HINSTANCE hInst,ILint ID,ILstring ResourceType,ILenum Type)755 ILboolean ILAPIENTRY ilutLoadResource(HINSTANCE hInst, ILint ID, ILstring ResourceType, ILenum Type)
756 {
757 	HRSRC Resource = (HRSRC)LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(ID), ResourceType));
758 	ILubyte *Data = (ILubyte*)LockResource(Resource);
759 
760 	return ilLoadL(Type, Data, SizeofResource(hInst, FindResource(hInst, MAKEINTRESOURCE(ID), ResourceType)));
761 }
762 
763 
764 #if !defined(_WIN32_WCE) && !(defined(_WIN32) && defined(__GNUC__))
765 #define BUFFSIZE 8192  // Change to suit the efficiency.
ilutWinLoadUrl(ILstring Url)766 ILboolean ILAPIENTRY ilutWinLoadUrl(ILstring Url)
767 {
768 	HINTERNET	Handle, UrlHandle;
769 	DWORD		BytesRead = 0, Context = 1;
770 	ILubyte		Buff[BUFFSIZE], *Buffer, *TempBuff;
771 	ILuint		BufferSize = 0, i;
772 	ILboolean	Is404 = IL_TRUE;
773 	char		Buffer404[] = { '<', 'h', 't', 'm', 'l', '>' };
774 
775 	Buffer = (ILubyte*)ialloc(0);
776 	if (Buffer == NULL) {
777 		return IL_FALSE;
778 	}
779 
780 	Handle = InternetOpen(IL_TEXT("Developer's Image Library"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
781 	if (Handle == NULL) {
782 		ifree(Buffer);
783 		ilSetError(ILUT_COULD_NOT_OPEN_FILE);
784 		return IL_FALSE;
785 	}
786 
787 	// Try again if fails the first time, loading only from the cache.
788 	UrlHandle = InternetOpenUrl(Handle, Url, NULL, 0, 0, Context);
789 	if (UrlHandle == NULL) {
790 		InternetCloseHandle(Handle);
791 		Handle = InternetOpen(IL_TEXT("Developer's Image Library"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_FROM_CACHE);
792 		if (Handle == NULL) {
793 			ifree(Buffer);
794 			ilSetError(ILUT_COULD_NOT_OPEN_FILE);
795 			return IL_FALSE;
796 		}
797 		UrlHandle = InternetOpenUrl(Handle, Url, NULL, 0, 0, Context);
798 		if (UrlHandle == NULL) {
799 			ifree(Buffer);
800 			InternetCloseHandle(Handle);
801 			ilSetError(ILUT_COULD_NOT_OPEN_FILE);
802 			return IL_FALSE;
803 		}
804 	}
805 
806 	do {
807 		if (!InternetReadFile(UrlHandle, Buff, BUFFSIZE, &BytesRead)) {
808 			InternetCloseHandle(UrlHandle);
809 			InternetCloseHandle(Handle);
810 			ifree(Buffer);
811 			ilSetError(ILUT_COULD_NOT_OPEN_FILE);
812 			return IL_FALSE;
813 		}
814 
815 		TempBuff = (ILubyte*)ialloc(BufferSize + BytesRead);
816 		if (TempBuff == NULL) {
817 			ifree(Buffer);
818 			return IL_FALSE;
819 		}
820 
821 		memcpy(TempBuff, Buffer, BufferSize);
822 		memcpy(TempBuff + BufferSize, Buff, BytesRead);
823 		ifree(Buffer);
824 		Buffer = TempBuff;
825 
826 		BufferSize += BytesRead;
827 	} while (BytesRead > 0);
828 
829 	InternetCloseHandle(UrlHandle);
830 	InternetCloseHandle(Handle);
831 
832 	// If the image does not exist, the server usually returns a 404 HTML page.
833 	for (i = 0; i < sizeof(Buffer404) && i < BufferSize; i++) {
834 		if (tolower(Buffer[i]) != Buffer404[i]) {
835 			Is404 = IL_FALSE;
836 			break;
837 		}
838 	}
839 
840 	if (!Is404) {
841 		if (!ilLoadL(ilTypeFromExt(Url), Buffer, BufferSize)) {
842 			if (!ilLoadL(IL_TYPE_UNKNOWN, Buffer, BufferSize)) {
843 				ifree(Buffer);
844 				return IL_FALSE;
845 			}
846 		}
847 	}
848 
849 	ifree(Buffer);
850 
851 	return IL_TRUE;
852 }
853 #endif
854 
855 
856 #endif//ILUT_USE_WIN32
857