source: branches/classes/c/c_image/bitmap.c

Last change on this file was 170, checked in by gyoung, 17 months ago

Add some error logging

File size: 18.9 KB
Line 
1/*
2 * (C) Chris Wohlgemuth 2001-2003
3 *
4 */
5/*
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; see the file COPYING. If not, write to
18 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20/*
21 * If you need another license for your project/product (commercial,
22 * noncommercial, whatever) contact me at
23 *
24 * http://www.os2world.com/cdwriting
25 * http://www.geocities.com/SiliconValley/Sector/5785/
26 *
27 */
28#define INCL_DOS
29#define INCL_GPI
30#define INCL_PM
31#define INCL_MMIOOS2
32#include <os2.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include "mmioos2.h"
37#include "mmres.h"
38#include "sys_funcs.h"
39
40//#define DEBUG
41
42extern HAB globalHab;
43ULONG showMsgBox(ULONG ulIDTitle, ULONG ulIDText, HMODULE hModule);
44void writeLog(char* chrFormat, ...);
45HMODULE queryModuleHandle(void);
46void HlpWriteToTrapLog(const char* chrFormat, ...);
47ULONG _checkFileSize(char* chrFileName);
48
49BOOL getBmpInfoHeader(PBITMAPINFOHEADER2 bmpih2, PSZ pszFileName, char* procName, ULONG ulLength, BOOL *bNoIOProcAvailable)
50{
51 MMIOINFO mmioinfo;
52 MMFORMATINFO mmFormatInfo;
53 HMMIO hmmio;
54 ULONG ulImageHeaderLength;
55 MMIMAGEHEADER mmImgHdr;
56 FOURCC fccStorageSystem;
57 FOURCC fccIOProc;
58 ULONG ulReturnCode;
59 ULONG ulBytesRead;
60 char *pName;
61
62 procName[0]=0;
63
64#ifdef DEBUG
65 HlpWriteToTrapLog("In getBmpInfoHeader(), trying to identify file: %s\n",
66 pszFileName);
67#endif
68
69 /* Check file size */
70 if(SysQueryFileSize(pszFileName)==0)
71 return FALSE; /* File is empty at the moment, so return without reading. */
72
73 ulReturnCode = mmioIdentifyFile ( pszFileName,
74 0L,
75 &mmFormatInfo,
76 &fccStorageSystem,
77 0L,
78 0L);
79 /*
80 * If this file was NOT identified, then this function won't
81 * work, so return an error by indicating an empty bitmap.
82 */
83 if ( ulReturnCode == MMIO_ERROR )
84 {
85#ifdef DEBUG
86 HlpWriteToTrapLog("In getBmpInfoHeader(), mmioIdentifyFile failed, file: %s\n",
87 pszFileName);
88#endif
89 /* Disabled, because when copying via WPS we end here before the image is available */
90 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
91 //*bNoIOProcAvailable=TRUE;
92 return (0L);
93 }
94
95#ifdef DEBUG
96 HlpWriteToTrapLog("In getBmpInfoHeader(), file identified\n");
97#endif
98
99 /*
100 * If mmioIdentifyFile did not find a custom-written IO proc which
101 * can understand the image file, then it will return the DOS IO Proc
102 * info because the image file IS a DOS file.
103 */
104 if( mmFormatInfo.fccIOProc == FOURCC_DOS )
105 {
106#ifdef DEBUG
107 HlpWriteToTrapLog("In getBmpInfoHeader(), mmFormatInfo.fccIOProc == FOURCC_DOS, file: %s\n",
108 pszFileName);
109#endif
110
111 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
112 *bNoIOProcAvailable=TRUE;
113 return ( 0L );
114 }
115
116 /*
117 * Ensure this is an IMAGE IOproc, and that it can read
118 * translated data
119 */
120 if ( (mmFormatInfo.ulMediaType != MMIO_MEDIATYPE_IMAGE) ||
121 ((mmFormatInfo.ulFlags & MMIO_CANREADTRANSLATED) == 0) )
122 {
123#ifdef DEBUG
124 HlpWriteToTrapLog("In getBmpInfoHeader(), mmFormatInfo check, file: %s\n",
125 pszFileName);
126#endif
127 /* Disabled, because it fails for templates */
128 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
129 *bNoIOProcAvailable=TRUE;
130 return (0L);
131 }
132 else
133 {
134 fccIOProc = mmFormatInfo.fccIOProc;
135 }
136
137#ifdef DEBUG
138 HlpWriteToTrapLog("In getBmpInfoHeader(), trying to get IO-Proc-Name...\n");
139#endif
140
141 if((pName=malloc(mmFormatInfo.lNameLength+1))!=NULLHANDLE)
142 {
143 LONG lBytesRead;
144 ulReturnCode = mmioGetFormatName(&mmFormatInfo, pName, &lBytesRead, 0,0);
145 if(ulReturnCode)
146 {
147 SysWriteToTrapLog("bitmap.c: %s %u\n\n", pName, ulReturnCode);
148 }
149 strncpy(procName, pName, ulLength-1);
150 free(pName);
151 }
152
153#ifdef DEBUG
154 HlpWriteToTrapLog("In getBmpInfoHeader(), trying to open the file...\n");
155#endif
156
157 /* Clear out and initialize mminfo structure */
158 memset ( &mmioinfo, 0L, sizeof ( MMIOINFO ) );
159 mmioinfo.fccIOProc = fccIOProc;
160 mmioinfo.ulTranslate = MMIO_TRANSLATEHEADER | MMIO_TRANSLATEDATA;
161 /*!!!!!!!!!!!!!!!!!!!!!!*/
162
163
164 hmmio = mmioOpen ( (PSZ) pszFileName,
165 &mmioinfo,
166 MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY );
167
168 if ( ! hmmio )
169 {
170 // If file could not be opened, return with error
171 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_OPENFILEERROR, queryModuleHandle());
172 return (0L);
173 }
174
175#ifdef DEBUG
176 HlpWriteToTrapLog("In getBmpInfoHeader(), now querying header length...\n");
177#endif
178
179 ulReturnCode = mmioQueryHeaderLength ( hmmio,
180 (PLONG)&ulImageHeaderLength,
181 0L,
182 0L);
183 if ( ulImageHeaderLength != sizeof ( MMIMAGEHEADER ) )
184 {
185 /* We have a problem.....possibly incompatible versions */
186 ulReturnCode = mmioClose (hmmio, 0L);
187 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
188 return (0L);
189 }
190
191#ifdef DEBUG
192 HlpWriteToTrapLog("In getBmpInfoHeader(), now querying header...\n");
193#endif
194
195 ulReturnCode = mmioGetHeader ( hmmio,
196 &mmImgHdr,
197 (LONG) sizeof ( MMIMAGEHEADER ),
198 (PLONG)&ulBytesRead,
199 0L,
200 0L);
201
202 if ( ulReturnCode != MMIO_SUCCESS )
203 {
204 /* Header unavailable */
205 ulReturnCode = mmioClose (hmmio, 0L);
206 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
207 return (0L);
208 }
209
210 memcpy(bmpih2, &mmImgHdr.mmXDIBHeader.BMPInfoHeader2,
211 sizeof(BITMAPINFOHEADER2)+256*sizeof(RGB2) );
212 ulReturnCode = mmioClose (hmmio, 0L);
213 return TRUE;
214}
215
216
217
218HBITMAP loadBitmap ( PSZ pszFileName, PBITMAPINFOHEADER2 pBMPInfoHeader2)
219{
220 HBITMAP hbm;
221 MMIOINFO mmioinfo;
222 MMFORMATINFO mmFormatInfo;
223 HMMIO hmmio;
224 // ULONG ulImageHeaderLength;
225 // MMIMAGEHEADER mmImgHdr;
226 ULONG ulBytesRead;
227 ULONG dwNumRowBytes;
228 PBYTE pRowBuffer;
229 ULONG dwRowCount;
230 SIZEL ImageSize;
231 ULONG dwHeight, dwWidth;
232 SHORT wBitCount;
233 FOURCC fccStorageSystem;
234 ULONG dwPadBytes;
235 ULONG dwRowBits;
236 ULONG ulReturnCode;
237 HBITMAP hbReturnCode;
238 LONG lReturnCode;
239 FOURCC fccIOProc;
240 HDC hdc;
241 HPS hps;
242
243
244 ulReturnCode = mmioIdentifyFile ( pszFileName,
245 0L,
246 &mmFormatInfo,
247 &fccStorageSystem,
248 0L,
249 0L);
250 /*
251 * If this file was NOT identified, then this function won't
252 * work, so return an error by indicating an empty bitmap.
253 */
254 if ( ulReturnCode == MMIO_ERROR )
255 {
256 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
257 return (0L);
258 }
259 /*
260 * If mmioIdentifyFile did not find a custom-written IO proc which
261 * can understand the image file, then it will return the DOS IO Proc
262 * info because the image file IS a DOS file.
263 */
264 if( mmFormatInfo.fccIOProc == FOURCC_DOS )
265 {
266 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
267 return ( 0L );
268 }
269 /*
270 * Ensure this is an IMAGE IOproc, and that it can read
271 * translated data
272 */
273 if ( (mmFormatInfo.ulMediaType != MMIO_MEDIATYPE_IMAGE) ||
274 ((mmFormatInfo.ulFlags & MMIO_CANREADTRANSLATED) == 0) )
275 {
276 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
277 return (0L);
278 }
279 else
280 {
281 fccIOProc = mmFormatInfo.fccIOProc;
282 }
283
284 /* Clear out and initialize mminfo structure */
285 memset ( &mmioinfo, 0L, sizeof ( MMIOINFO ) );
286 mmioinfo.fccIOProc = fccIOProc;
287 mmioinfo.ulTranslate = MMIO_TRANSLATEHEADER | MMIO_TRANSLATEDATA;
288 hmmio = mmioOpen ( (PSZ) pszFileName,
289 &mmioinfo,
290 MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY );
291 if ( ! hmmio )
292 {
293 // If file could not be opened, return with error
294 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_OPENFILEERROR, queryModuleHandle());
295 return (0L);
296 }
297
298#if 0
299 dwReturnCode = mmioQueryHeaderLength ( hmmio,
300 (PLONG)&ulImageHeaderLength,
301 0L,
302 0L);
303 if ( ulImageHeaderLength != sizeof ( MMIMAGEHEADER ) )
304 {
305 /* We have a problem.....possibly incompatible versions */
306 ulReturnCode = mmioClose (hmmio, 0L);
307 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR);
308 return (0L);
309 }
310
311 ulReturnCode = mmioGetHeader ( hmmio,
312 &mmImgHdr,
313 (LONG) sizeof ( MMIMAGEHEADER ),
314 (PLONG)&ulBytesRead,
315 0L,
316 0L);
317
318 if ( ulReturnCode != MMIO_SUCCESS )
319 {
320 /* Header unavailable */
321 ulReturnCode = mmioClose (hmmio, 0L);
322 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR);
323 return (0L);
324 }
325#endif
326 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
327#if 0
328 /*
329 * Determine the number of bytes required, per row.
330 * PLANES MUST ALWAYS BE = 1
331 */
332 dwHeight = mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cy;
333 dwWidth = mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cx;
334 wBitCount = mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount;
335 dwRowBits = dwWidth * mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount;
336 dwNumRowBytes = dwRowBits >> 3;
337#endif
338
339 /*
340 * Determine the number of bytes required, per row.
341 * PLANES MUST ALWAYS BE = 1
342 */
343 dwHeight = pBMPInfoHeader2->cy;
344 dwWidth = pBMPInfoHeader2->cx;
345 wBitCount = pBMPInfoHeader2->cBitCount;
346 dwRowBits = dwWidth * pBMPInfoHeader2->cBitCount;
347 dwNumRowBytes = dwRowBits >> 3;
348
349 /*
350 * Account for odd bits used in 1bpp or 4bpp images that are
351 * NOT on byte boundaries.
352 */
353 if ( dwRowBits % 8 )
354 {
355 dwNumRowBytes++;
356 }
357 /*
358 * Ensure the row length in bytes accounts for byte padding.
359 * All bitmap data rows must are aligned on LONG/4-BYTE boundaries.
360 * The data FROM an IOProc should always appear in this form.
361 */
362 dwPadBytes = ( dwNumRowBytes % 4 );
363 if ( dwPadBytes )
364 {
365 dwNumRowBytes += 4 - dwPadBytes;
366 }
367
368 /* Allocate space for ONE row of pels */
369 if ( DosAllocMem( (PPVOID)&pRowBuffer,
370 (ULONG)dwNumRowBytes,
371 fALLOC))
372 {
373 ulReturnCode = mmioClose (hmmio, 0L);
374 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOMEMERROR, queryModuleHandle());
375 return(0L);
376 }
377
378 /* Create a device context */
379 hdc=DevOpenDC(globalHab, OD_MEMORY,"*",0L, NULL, NULLHANDLE);
380 if(hdc==NULLHANDLE)
381 {
382 DosFreeMem(pRowBuffer);
383 mmioClose (hmmio, 0L);
384 return(0L);
385 }
386
387
388 // ***************************************************
389 // Create a memory presentation space that includes
390 // the memory device context obtained above.
391 // ***************************************************
392
393 ImageSize.cx = dwWidth;
394 ImageSize.cy = dwHeight;
395
396 hps = GpiCreatePS ( globalHab,
397 hdc,
398 &ImageSize,
399 PU_PELS | GPIT_NORMAL | GPIA_ASSOC );
400 // PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );
401 if ( !hps )
402 {
403#ifdef DEBUG
404 WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
405 "No HPS...",
406 "Open Image File",
407 (HMODULE) NULL,
408 (ULONG) MB_OK | MB_MOVEABLE |
409 MB_ERROR );
410#endif
411 DevCloseDC(hdc);
412 DosFreeMem(pRowBuffer);
413 mmioClose (hmmio, 0L);
414 return(0L);
415 }
416
417 // GpiSelectPalette(hps, NULLHANDLE);
418 // ***************************************************
419 // Create an uninitialized bitmap. This is where we
420 // will put all of the bits once we read them in.
421 // ***************************************************
422 hbm = GpiCreateBitmap ( hps,
423 pBMPInfoHeader2,
424 0L,
425 NULL,
426 NULL);
427
428 if ( !hbm )
429 {
430#ifdef DEBUG
431 WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
432 "No HBITMAP...",
433 "Open Image File",
434 (HMODULE) NULL,
435 (ULONG) MB_OK | MB_MOVEABLE |
436 MB_ERROR );
437#endif
438 GpiDestroyPS(hps);
439 DevCloseDC(hdc);
440 DosFreeMem(pRowBuffer);
441 ulReturnCode = mmioClose (hmmio, 0L);
442 return(0L);
443 }
444
445 // ***************************************************
446 // Select the bitmap into the memory device context.
447 // ***************************************************
448 hbReturnCode = GpiSetBitmap ( hps,
449 hbm );
450
451 //***************************************************************
452 // LOAD THE BITMAP DATA FROM THE FILE
453 // One line at a time, starting from the BOTTOM
454 //*************************************************************** */
455
456 for ( dwRowCount = 0; dwRowCount < dwHeight; dwRowCount++ )
457 {
458 ulBytesRead = (ULONG) mmioRead ( hmmio,
459 pRowBuffer,
460 dwNumRowBytes );
461 if ( !ulBytesRead )
462 {
463 break;
464 }
465 /*
466 * Allow context switching while previewing.. Couldn't get
467 * it to work. Perhaps will get to it when time is available...
468 */
469 lReturnCode = GpiSetBitmapBits ( hps,
470 (LONG) dwRowCount,
471 (LONG) 1,
472 (PBYTE) pRowBuffer,
473 (PBITMAPINFO2) pBMPInfoHeader2);
474 }
475
476 /* Clean up */
477 hbReturnCode = GpiSetBitmap ( hps,
478 NULLHANDLE );
479 ulReturnCode = mmioClose (hmmio, 0L);
480 DosFreeMem(pRowBuffer);
481 GpiDestroyPS(hps);
482 DevCloseDC(hdc);
483
484 return(hbm);
485}
486
487HBITMAP createNewBitmap ( HBITMAP hbm,
488 PBITMAPINFOHEADER2 pBmpInfoHeader2,
489 ULONG ulWidth,
490 ULONG ulHeight,
491 BOOL* pbQuitEarly)
492{
493 HBITMAP hbmTarget;
494 SIZEL ImageSize;
495 HBITMAP hbReturnCode;
496 HDC hdc;
497 HPS hps;
498 BITMAPINFOHEADER2 bmpih2;
499 POINTL aptl[4];
500
501 if(!ulWidth || !ulHeight)
502 return 0L;
503
504 /* Create a device context */
505 hdc=DevOpenDC(globalHab, OD_MEMORY,"*",0L, NULL, NULLHANDLE);
506 if(hdc==NULLHANDLE)
507 {
508 return(0L);
509 }
510
511 // ***************************************************
512 // Create a memory presentation space that includes
513 // the memory device context obtained above.
514 // ***************************************************
515 ImageSize.cx = ulWidth;
516 ImageSize.cy = ulHeight;
517 hps = GpiCreatePS ( globalHab,
518 hdc,
519 &ImageSize,
520 PU_PELS | GPIT_NORMAL | GPIA_ASSOC );
521 if ( !hps )
522 {
523#ifdef DEBUG
524 WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
525 "No HPS...",
526 "Create new bitmap",
527 (HMODULE) NULL,
528 (ULONG) MB_OK | MB_MOVEABLE |
529 MB_ERROR );
530#endif
531 DevCloseDC(hdc);
532 return(0L);
533 }
534 // GpiSelectPalette(hps, NULLHANDLE);
535
536 /* Now scale the bitmap */
537 memcpy(&bmpih2, pBmpInfoHeader2, sizeof(BITMAPINFOHEADER2));
538
539 bmpih2.cx=ulWidth;
540 bmpih2.cy=ulHeight;
541 bmpih2.cbImage=(((ulWidth*(1<<bmpih2.cPlanes)*(1<<bmpih2.cBitCount))+31) /32)*ulHeight;
542 // ***************************************************
543 // Create an uninitialized bitmap. This is where we
544 // ***************************************************
545
546 hbmTarget = GpiCreateBitmap ( hps,
547 &bmpih2,
548 0L,
549 NULL,
550 NULL);
551 if ( !hbmTarget )
552 {
553#ifdef DEBUG
554 WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
555 "No target HBITMAP...",
556 "Create new bitmap",
557 (HMODULE) NULL,
558 (ULONG) MB_OK | MB_MOVEABLE |
559 MB_ERROR );
560#endif
561 GpiDestroyPS(hps);
562 DevCloseDC(hdc);
563 return(0L);
564 }
565
566 /* Blit it */
567 hbReturnCode = GpiSetBitmap ( hps,
568 hbmTarget );
569
570 /*GpiBltBit*/
571 aptl[0].x=0;
572 aptl[0].y=0;
573 aptl[1].x=ulWidth;
574 aptl[1].y=ulHeight;
575 aptl[2].x=0;
576 aptl[2].y=0;
577 aptl[3].x=pBmpInfoHeader2->cx;
578 aptl[3].y=pBmpInfoHeader2->cy;
579
580 GpiWCBitBlt(hps, hbm,4L, aptl, ROP_SRCCOPY, BBO_IGNORE);
581
582 hbReturnCode = GpiSetBitmap( hps, NULLHANDLE );
583 GpiDestroyPS(hps);
584 DevCloseDC(hdc);
585 return(hbmTarget);
586}
587
588
589
Note: See TracBrowser for help on using the repository browser.