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

Last change on this file was 2, checked in by stevenhl, 8 years ago

Import sources from cwmm-full.zip dated 2005-03-21

File size: 18.8 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 mmioGetFormatName(&mmFormatInfo, pName, &lBytesRead, 0,0);
145 strncpy(procName, pName, ulLength-1);
146 free(pName);
147 }
148
149#ifdef DEBUG
150 HlpWriteToTrapLog("In getBmpInfoHeader(), trying to open the file...\n");
151#endif
152
153 /* Clear out and initialize mminfo structure */
154 memset ( &mmioinfo, 0L, sizeof ( MMIOINFO ) );
155 mmioinfo.fccIOProc = fccIOProc;
156 mmioinfo.ulTranslate = MMIO_TRANSLATEHEADER | MMIO_TRANSLATEDATA;
157 /*!!!!!!!!!!!!!!!!!!!!!!*/
158
159
160 hmmio = mmioOpen ( (PSZ) pszFileName,
161 &mmioinfo,
162 MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY );
163
164 if ( ! hmmio )
165 {
166 // If file could not be opened, return with error
167 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_OPENFILEERROR, queryModuleHandle());
168 return (0L);
169 }
170
171#ifdef DEBUG
172 HlpWriteToTrapLog("In getBmpInfoHeader(), now querying header length...\n");
173#endif
174
175 ulReturnCode = mmioQueryHeaderLength ( hmmio,
176 (PLONG)&ulImageHeaderLength,
177 0L,
178 0L);
179 if ( ulImageHeaderLength != sizeof ( MMIMAGEHEADER ) )
180 {
181 /* We have a problem.....possibly incompatible versions */
182 ulReturnCode = mmioClose (hmmio, 0L);
183 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
184 return (0L);
185 }
186
187#ifdef DEBUG
188 HlpWriteToTrapLog("In getBmpInfoHeader(), now querying header...\n");
189#endif
190
191 ulReturnCode = mmioGetHeader ( hmmio,
192 &mmImgHdr,
193 (LONG) sizeof ( MMIMAGEHEADER ),
194 (PLONG)&ulBytesRead,
195 0L,
196 0L);
197
198 if ( ulReturnCode != MMIO_SUCCESS )
199 {
200 /* Header unavailable */
201 ulReturnCode = mmioClose (hmmio, 0L);
202 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
203 return (0L);
204 }
205
206 memcpy(bmpih2, &mmImgHdr.mmXDIBHeader.BMPInfoHeader2,
207 sizeof(BITMAPINFOHEADER2)+256*sizeof(RGB2) );
208 ulReturnCode = mmioClose (hmmio, 0L);
209 return TRUE;
210}
211
212
213
214HBITMAP loadBitmap ( PSZ pszFileName, PBITMAPINFOHEADER2 pBMPInfoHeader2)
215{
216 HBITMAP hbm;
217 MMIOINFO mmioinfo;
218 MMFORMATINFO mmFormatInfo;
219 HMMIO hmmio;
220 // ULONG ulImageHeaderLength;
221 // MMIMAGEHEADER mmImgHdr;
222 ULONG ulBytesRead;
223 ULONG dwNumRowBytes;
224 PBYTE pRowBuffer;
225 ULONG dwRowCount;
226 SIZEL ImageSize;
227 ULONG dwHeight, dwWidth;
228 SHORT wBitCount;
229 FOURCC fccStorageSystem;
230 ULONG dwPadBytes;
231 ULONG dwRowBits;
232 ULONG ulReturnCode;
233 HBITMAP hbReturnCode;
234 LONG lReturnCode;
235 FOURCC fccIOProc;
236 HDC hdc;
237 HPS hps;
238
239
240 ulReturnCode = mmioIdentifyFile ( pszFileName,
241 0L,
242 &mmFormatInfo,
243 &fccStorageSystem,
244 0L,
245 0L);
246 /*
247 * If this file was NOT identified, then this function won't
248 * work, so return an error by indicating an empty bitmap.
249 */
250 if ( ulReturnCode == MMIO_ERROR )
251 {
252 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
253 return (0L);
254 }
255 /*
256 * If mmioIdentifyFile did not find a custom-written IO proc which
257 * can understand the image file, then it will return the DOS IO Proc
258 * info because the image file IS a DOS file.
259 */
260 if( mmFormatInfo.fccIOProc == FOURCC_DOS )
261 {
262 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
263 return ( 0L );
264 }
265 /*
266 * Ensure this is an IMAGE IOproc, and that it can read
267 * translated data
268 */
269 if ( (mmFormatInfo.ulMediaType != MMIO_MEDIATYPE_IMAGE) ||
270 ((mmFormatInfo.ulFlags & MMIO_CANREADTRANSLATED) == 0) )
271 {
272 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR, queryModuleHandle());
273 return (0L);
274 }
275 else
276 {
277 fccIOProc = mmFormatInfo.fccIOProc;
278 }
279
280 /* Clear out and initialize mminfo structure */
281 memset ( &mmioinfo, 0L, sizeof ( MMIOINFO ) );
282 mmioinfo.fccIOProc = fccIOProc;
283 mmioinfo.ulTranslate = MMIO_TRANSLATEHEADER | MMIO_TRANSLATEDATA;
284 hmmio = mmioOpen ( (PSZ) pszFileName,
285 &mmioinfo,
286 MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY );
287 if ( ! hmmio )
288 {
289 // If file could not be opened, return with error
290 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_OPENFILEERROR, queryModuleHandle());
291 return (0L);
292 }
293
294#if 0
295 dwReturnCode = mmioQueryHeaderLength ( hmmio,
296 (PLONG)&ulImageHeaderLength,
297 0L,
298 0L);
299 if ( ulImageHeaderLength != sizeof ( MMIMAGEHEADER ) )
300 {
301 /* We have a problem.....possibly incompatible versions */
302 ulReturnCode = mmioClose (hmmio, 0L);
303 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR);
304 return (0L);
305 }
306
307 ulReturnCode = mmioGetHeader ( hmmio,
308 &mmImgHdr,
309 (LONG) sizeof ( MMIMAGEHEADER ),
310 (PLONG)&ulBytesRead,
311 0L,
312 0L);
313
314 if ( ulReturnCode != MMIO_SUCCESS )
315 {
316 /* Header unavailable */
317 ulReturnCode = mmioClose (hmmio, 0L);
318 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOIMGIOPROCERROR);
319 return (0L);
320 }
321#endif
322 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
323#if 0
324 /*
325 * Determine the number of bytes required, per row.
326 * PLANES MUST ALWAYS BE = 1
327 */
328 dwHeight = mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cy;
329 dwWidth = mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cx;
330 wBitCount = mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount;
331 dwRowBits = dwWidth * mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount;
332 dwNumRowBytes = dwRowBits >> 3;
333#endif
334
335 /*
336 * Determine the number of bytes required, per row.
337 * PLANES MUST ALWAYS BE = 1
338 */
339 dwHeight = pBMPInfoHeader2->cy;
340 dwWidth = pBMPInfoHeader2->cx;
341 wBitCount = pBMPInfoHeader2->cBitCount;
342 dwRowBits = dwWidth * pBMPInfoHeader2->cBitCount;
343 dwNumRowBytes = dwRowBits >> 3;
344
345 /*
346 * Account for odd bits used in 1bpp or 4bpp images that are
347 * NOT on byte boundaries.
348 */
349 if ( dwRowBits % 8 )
350 {
351 dwNumRowBytes++;
352 }
353 /*
354 * Ensure the row length in bytes accounts for byte padding.
355 * All bitmap data rows must are aligned on LONG/4-BYTE boundaries.
356 * The data FROM an IOProc should always appear in this form.
357 */
358 dwPadBytes = ( dwNumRowBytes % 4 );
359 if ( dwPadBytes )
360 {
361 dwNumRowBytes += 4 - dwPadBytes;
362 }
363
364 /* Allocate space for ONE row of pels */
365 if ( DosAllocMem( (PPVOID)&pRowBuffer,
366 (ULONG)dwNumRowBytes,
367 fALLOC))
368 {
369 ulReturnCode = mmioClose (hmmio, 0L);
370 // showMsgBox(IDSTR_CWIMAGETITLE, IDSTR_NOMEMERROR, queryModuleHandle());
371 return(0L);
372 }
373
374 /* Create a device context */
375 hdc=DevOpenDC(globalHab, OD_MEMORY,"*",0L, NULL, NULLHANDLE);
376 if(hdc==NULLHANDLE)
377 {
378 DosFreeMem(pRowBuffer);
379 mmioClose (hmmio, 0L);
380 return(0L);
381 }
382
383
384 // ***************************************************
385 // Create a memory presentation space that includes
386 // the memory device context obtained above.
387 // ***************************************************
388
389 ImageSize.cx = dwWidth;
390 ImageSize.cy = dwHeight;
391
392 hps = GpiCreatePS ( globalHab,
393 hdc,
394 &ImageSize,
395 PU_PELS | GPIT_NORMAL | GPIA_ASSOC );
396 // PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );
397 if ( !hps )
398 {
399#ifdef DEBUG
400 WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
401 "No HPS...",
402 "Open Image File",
403 (HMODULE) NULL,
404 (ULONG) MB_OK | MB_MOVEABLE |
405 MB_ERROR );
406#endif
407 DevCloseDC(hdc);
408 DosFreeMem(pRowBuffer);
409 mmioClose (hmmio, 0L);
410 return(0L);
411 }
412
413 // GpiSelectPalette(hps, NULLHANDLE);
414 // ***************************************************
415 // Create an uninitialized bitmap. This is where we
416 // will put all of the bits once we read them in.
417 // ***************************************************
418 hbm = GpiCreateBitmap ( hps,
419 pBMPInfoHeader2,
420 0L,
421 NULL,
422 NULL);
423
424 if ( !hbm )
425 {
426#ifdef DEBUG
427 WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
428 "No HBITMAP...",
429 "Open Image File",
430 (HMODULE) NULL,
431 (ULONG) MB_OK | MB_MOVEABLE |
432 MB_ERROR );
433#endif
434 GpiDestroyPS(hps);
435 DevCloseDC(hdc);
436 DosFreeMem(pRowBuffer);
437 ulReturnCode = mmioClose (hmmio, 0L);
438 return(0L);
439 }
440
441 // ***************************************************
442 // Select the bitmap into the memory device context.
443 // ***************************************************
444 hbReturnCode = GpiSetBitmap ( hps,
445 hbm );
446
447 //***************************************************************
448 // LOAD THE BITMAP DATA FROM THE FILE
449 // One line at a time, starting from the BOTTOM
450 //*************************************************************** */
451
452 for ( dwRowCount = 0; dwRowCount < dwHeight; dwRowCount++ )
453 {
454 ulBytesRead = (ULONG) mmioRead ( hmmio,
455 pRowBuffer,
456 dwNumRowBytes );
457 if ( !ulBytesRead )
458 {
459 break;
460 }
461 /*
462 * Allow context switching while previewing.. Couldn't get
463 * it to work. Perhaps will get to it when time is available...
464 */
465 lReturnCode = GpiSetBitmapBits ( hps,
466 (LONG) dwRowCount,
467 (LONG) 1,
468 (PBYTE) pRowBuffer,
469 (PBITMAPINFO2) pBMPInfoHeader2);
470 }
471
472 /* Clean up */
473 hbReturnCode = GpiSetBitmap ( hps,
474 NULLHANDLE );
475 ulReturnCode = mmioClose (hmmio, 0L);
476 DosFreeMem(pRowBuffer);
477 GpiDestroyPS(hps);
478 DevCloseDC(hdc);
479
480 return(hbm);
481}
482
483HBITMAP createNewBitmap ( HBITMAP hbm,
484 PBITMAPINFOHEADER2 pBmpInfoHeader2,
485 ULONG ulWidth,
486 ULONG ulHeight,
487 BOOL* pbQuitEarly)
488{
489 HBITMAP hbmTarget;
490 SIZEL ImageSize;
491 HBITMAP hbReturnCode;
492 HDC hdc;
493 HPS hps;
494 BITMAPINFOHEADER2 bmpih2;
495 POINTL aptl[4];
496
497 if(!ulWidth || !ulHeight)
498 return 0L;
499
500 /* Create a device context */
501 hdc=DevOpenDC(globalHab, OD_MEMORY,"*",0L, NULL, NULLHANDLE);
502 if(hdc==NULLHANDLE)
503 {
504 return(0L);
505 }
506
507 // ***************************************************
508 // Create a memory presentation space that includes
509 // the memory device context obtained above.
510 // ***************************************************
511 ImageSize.cx = ulWidth;
512 ImageSize.cy = ulHeight;
513 hps = GpiCreatePS ( globalHab,
514 hdc,
515 &ImageSize,
516 PU_PELS | GPIT_NORMAL | GPIA_ASSOC );
517 if ( !hps )
518 {
519#ifdef DEBUG
520 WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
521 "No HPS...",
522 "Create new bitmap",
523 (HMODULE) NULL,
524 (ULONG) MB_OK | MB_MOVEABLE |
525 MB_ERROR );
526#endif
527 DevCloseDC(hdc);
528 return(0L);
529 }
530 // GpiSelectPalette(hps, NULLHANDLE);
531
532 /* Now scale the bitmap */
533 memcpy(&bmpih2, pBmpInfoHeader2, sizeof(BITMAPINFOHEADER2));
534
535 bmpih2.cx=ulWidth;
536 bmpih2.cy=ulHeight;
537 bmpih2.cbImage=(((ulWidth*(1<<bmpih2.cPlanes)*(1<<bmpih2.cBitCount))+31) /32)*ulHeight;
538 // ***************************************************
539 // Create an uninitialized bitmap. This is where we
540 // ***************************************************
541
542 hbmTarget = GpiCreateBitmap ( hps,
543 &bmpih2,
544 0L,
545 NULL,
546 NULL);
547 if ( !hbmTarget )
548 {
549#ifdef DEBUG
550 WinMessageBox( HWND_DESKTOP, HWND_DESKTOP,
551 "No target HBITMAP...",
552 "Create new bitmap",
553 (HMODULE) NULL,
554 (ULONG) MB_OK | MB_MOVEABLE |
555 MB_ERROR );
556#endif
557 GpiDestroyPS(hps);
558 DevCloseDC(hdc);
559 return(0L);
560 }
561
562 /* Blit it */
563 hbReturnCode = GpiSetBitmap ( hps,
564 hbmTarget );
565
566 /*GpiBltBit*/
567 aptl[0].x=0;
568 aptl[0].y=0;
569 aptl[1].x=ulWidth;
570 aptl[1].y=ulHeight;
571 aptl[2].x=0;
572 aptl[2].y=0;
573 aptl[3].x=pBmpInfoHeader2->cx;
574 aptl[3].y=pBmpInfoHeader2->cy;
575
576 GpiWCBitBlt(hps, hbm,4L, aptl, ROP_SRCCOPY, BBO_IGNORE);
577
578 hbReturnCode = GpiSetBitmap( hps, NULLHANDLE );
579 GpiDestroyPS(hps);
580 DevCloseDC(hdc);
581 return(hbmTarget);
582}
583
584
585
Note: See TracBrowser for help on using the repository browser.