2 * Copyright 1998 Marcus Meissner
3 * Copyright 2000 Bradley Baetz
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * FIXME: This all assumes 32 bit codecs
20 * Win95 appears to prefer 32 bit codecs, even from 16 bit code.
21 * There is the ICOpenFunction16 to worry about still, though.
25 * - the four CC comparisons are wrong on big endian machines
31 #include "msvideo_private.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
39 LRESULT (CALLBACK *pFnCallTo16)(HDRVR, HIC, UINT, LPARAM, LPARAM) = NULL;
41 static WINE_HIC* MSVIDEO_FirstHic /* = NULL */;
43 /******************************************************************
48 WINE_HIC* MSVIDEO_GetHicPtr(HIC hic)
52 for (whic = MSVIDEO_FirstHic; whic && whic->hic != hic; whic = whic->next);
56 /***********************************************************************
57 * VideoForWindowsVersion [MSVFW32.2]
58 * VideoForWindowsVersion [MSVIDEO.2]
59 * Returns the version in major.minor form.
60 * In Windows95 this returns 0x040003b6 (4.950)
62 DWORD WINAPI VideoForWindowsVersion(void)
64 return 0x040003B6; /* 4.950 */
67 /* system.ini: [drivers] */
69 /***********************************************************************
71 * Get information about an installable compressor. Return TRUE if there
75 DWORD fccType, /* [in] type of compressor ('vidc') */
76 DWORD fccHandler, /* [in] <n>th compressor */
77 ICINFO *lpicinfo) /* [out] information about compressor */
81 TRACE("(%.4s,%.4s,%p)\n", (char*)&fccType, (char*)&fccHandler, lpicinfo);
83 if (GetPrivateProfileStringA("drivers32", NULL, NULL, buf, sizeof(buf), "system.ini"))
88 if (!strncasecmp((char*)&fccType, s, 4) && s[4] == '.' && s[9] == '=')
94 lpicinfo->fccHandler = mmioStringToFOURCCA(s + 5, 0);
95 hic = ICOpen(fccType, lpicinfo->fccHandler, ICMODE_QUERY);
98 ICGetInfo(hic, lpicinfo, lpicinfo->dwSize);
105 s += strlen(s) + 1; /* either next char or \0 */
111 static DWORD IC_HandleRef = 1;
113 /***********************************************************************
115 * Opens an installable compressor. Return special handle.
117 HIC VFWAPI ICOpen(DWORD fccType, DWORD fccHandler, UINT wMode)
125 TRACE("(%.4s,%.4s,0x%08lx)\n", (char*)&fccType, (char*)&fccHandler, (DWORD)wMode);
127 sprintf(codecname, "%.4s.%.4s", (char*)&fccType, (char*)&fccHandler);
129 /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the
130 * same layout as ICOPEN
132 icopen.dwSize = sizeof(ICOPEN);
133 icopen.fccType = fccType;
134 icopen.fccHandler = fccHandler;
135 icopen.dwVersion = 0x00001000; /* FIXME */
136 icopen.dwFlags = wMode;
138 icopen.pV1Reserved = NULL;
139 icopen.pV2Reserved = NULL;
140 icopen.dnDevNode = 0; /* FIXME */
142 hdrv = OpenDriverA(codecname, "drivers32", (LPARAM)&icopen);
145 if (fccType == streamtypeVIDEO)
147 sprintf(codecname, "vidc.%.4s", (char*)&fccHandler);
148 fccType = ICTYPE_VIDEO;
149 hdrv = OpenDriverA(codecname, "drivers32", (LPARAM)&icopen);
154 bIs16 = GetDriverFlags(hdrv) & WINE_GDF_16BIT;
156 if (bIs16 && !pFnCallTo16)
158 FIXME("Got a 16 bit driver, but no 16 bit support in msvfw\n");
161 whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
164 CloseDriver(hdrv, 0, 0);
168 /* FIXME: is the signature the real one ? */
169 whic->driverproc = bIs16 ? (DRIVERPROC)pFnCallTo16 : NULL;
170 whic->driverproc16 = 0;
171 whic->type = fccType;
172 whic->handler = fccHandler;
173 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++;
174 whic->hic = HIC_32(IC_HandleRef++);
175 whic->next = MSVIDEO_FirstHic;
176 MSVIDEO_FirstHic = whic;
178 TRACE("=> %p\n", whic->hic);
182 /***********************************************************************
183 * MSVIDEO_OpenFunction
185 HIC MSVIDEO_OpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode,
186 DRIVERPROC lpfnHandler, DWORD lpfnHandler16)
191 TRACE("(%.4s,%.4s,%d,%p,%08lx)\n",
192 (char*)&fccType, (char*)&fccHandler, wMode, lpfnHandler, lpfnHandler16);
194 icopen.dwSize = sizeof(ICOPEN);
195 icopen.fccType = fccType;
196 icopen.fccHandler = fccHandler;
197 icopen.dwVersion = 0x00001000; /* FIXME */
198 icopen.dwFlags = wMode;
200 icopen.pV1Reserved = NULL;
201 icopen.pV2Reserved = NULL;
202 icopen.dnDevNode = 0; /* FIXME */
204 whic = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_HIC));
207 whic->driverproc = lpfnHandler;
208 whic->driverproc16 = lpfnHandler16;
209 while (MSVIDEO_GetHicPtr(HIC_32(IC_HandleRef)) != NULL) IC_HandleRef++;
210 whic->hic = HIC_32(IC_HandleRef++);
211 whic->next = MSVIDEO_FirstHic;
212 MSVIDEO_FirstHic = whic;
214 /* Now try opening/loading the driver. Taken from DRIVER_AddToList */
215 /* What if the function is used more than once? */
217 if (MSVIDEO_SendMessage(whic->hic, DRV_LOAD, 0L, 0L) != DRV_SUCCESS)
219 WARN("DRV_LOAD failed for hic %p\n", whic->hic);
220 MSVIDEO_FirstHic = whic->next;
221 HeapFree(GetProcessHeap(), 0, whic);
224 /* return value is not checked */
225 MSVIDEO_SendMessage(whic->hic, DRV_ENABLE, 0L, 0L);
227 whic->hdrv = (HDRVR)MSVIDEO_SendMessage(whic->hic, DRV_OPEN, 0, (DWORD)&icopen);
231 WARN("DRV_OPEN failed for hic %p\n", whic->hic);
232 MSVIDEO_FirstHic = whic->next;
233 HeapFree(GetProcessHeap(), 0, whic);
237 TRACE("=> %p\n", whic->hic);
241 /***********************************************************************
242 * ICOpenFunction [MSVFW32.@]
244 HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode, FARPROC lpfnHandler)
246 return MSVIDEO_OpenFunction(fccType, fccHandler, wMode, (DRIVERPROC)lpfnHandler, 0);
249 /***********************************************************************
250 * ICGetInfo [MSVFW32.@]
252 LRESULT VFWAPI ICGetInfo(HIC hic,ICINFO *picinfo,DWORD cb) {
255 TRACE("(%p,%p,%ld)\n",hic,picinfo,cb);
256 ret = ICSendMessage(hic,ICM_GETINFO,(DWORD)picinfo,cb);
257 TRACE(" -> 0x%08lx\n",ret);
261 /***********************************************************************
262 * ICLocate [MSVFW32.@]
264 HIC VFWAPI ICLocate(DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
265 LPBITMAPINFOHEADER lpbiOut, WORD wMode)
271 TRACE("(%.4s,%.4s,%p,%p,0x%04x)\n",
272 (char*)&fccType, (char*)&fccHandler, lpbiIn, lpbiOut, wMode);
276 case ICMODE_FASTCOMPRESS:
277 case ICMODE_COMPRESS:
278 querymsg = ICM_COMPRESS_QUERY;
280 case ICMODE_FASTDECOMPRESS:
281 case ICMODE_DECOMPRESS:
282 querymsg = ICM_DECOMPRESS_QUERY;
285 querymsg = ICM_DRAW_QUERY;
288 WARN("Unknown mode (%d)\n", wMode);
292 /* Easy case: handler/type match, we just fire a query and return */
293 hic = ICOpen(fccType, fccHandler, wMode);
296 if (!ICSendMessage(hic, querymsg, (DWORD)lpbiIn, (DWORD)lpbiOut))
298 TRACE("=> %p\n", hic);
304 /* Now try each driver in turn. 32 bit codecs only. */
305 /* FIXME: Move this to an init routine? */
307 pszBuffer = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 1024);
308 if (GetPrivateProfileSectionA("drivers32", pszBuffer, 1024, "system.ini"))
313 if (!strncasecmp((char*)&fccType, s, 4) && s[4] == '.' && s[9] == '=')
316 while (*s2 != '\0' && *s2 != '.') s2++;
319 hic = ICOpen(fccType, *(DWORD*)s2, wMode);
322 if (!ICSendMessage(hic, querymsg, (DWORD)lpbiIn, (DWORD)lpbiOut))
324 HeapFree(GetProcessHeap(), 0, pszBuffer);
325 TRACE("=> %p\n", hic);
335 HeapFree(GetProcessHeap(), 0, pszBuffer);
337 if (fccType == streamtypeVIDEO)
338 return ICLocate(ICTYPE_VIDEO, fccHandler, lpbiIn, lpbiOut, wMode);
340 WARN("(%.4s,%.4s,%p,%p,0x%04x) not found!\n",
341 (char*)&fccType, (char*)&fccHandler, lpbiIn, lpbiOut, wMode);
345 /***********************************************************************
346 * ICGetDisplayFormat [MSVFW32.@]
348 HIC VFWAPI ICGetDisplayFormat(
349 HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
350 INT depth,INT dx,INT dy)
354 FIXME("(%p,%p,%p,%d,%d,%d),stub!\n",hic,lpbiIn,lpbiOut,depth,dx,dy);
356 tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS);
360 if ((dy == lpbiIn->biHeight) && (dx == lpbiIn->biWidth))
361 dy = dx = 0; /* no resize needed */
363 /* Can we decompress it ? */
364 if (ICDecompressQuery(tmphic,lpbiIn,NULL) != 0)
365 goto errout; /* no, sorry */
367 ICDecompressGetFormat(tmphic,lpbiIn,lpbiOut);
369 if (lpbiOut->biCompression != 0) {
370 FIXME("Ooch, how come decompressor outputs compressed data (%ld)??\n",
371 lpbiOut->biCompression);
373 if (lpbiOut->biSize < sizeof(*lpbiOut)) {
374 FIXME("Ooch, size of output BIH is too small (%ld)\n",
376 lpbiOut->biSize = sizeof(*lpbiOut);
382 depth = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
384 if (depth==15) depth = 16;
385 if (depth<8) depth = 8;
387 if (lpbiIn->biBitCount == 8)
390 TRACE("=> %p\n", tmphic);
400 /***********************************************************************
401 * ICCompress [MSVFW32.@]
405 HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiOutput,LPVOID lpData,
406 LPBITMAPINFOHEADER lpbiInput,LPVOID lpBits,LPDWORD lpckid,
407 LPDWORD lpdwFlags,LONG lFrameNum,DWORD dwFrameSize,DWORD dwQuality,
408 LPBITMAPINFOHEADER lpbiPrev,LPVOID lpPrev)
412 TRACE("(%p,%ld,%p,%p,%p,%p,...)\n",hic,dwFlags,lpbiOutput,lpData,lpbiInput,lpBits);
414 iccmp.dwFlags = dwFlags;
416 iccmp.lpbiOutput = lpbiOutput;
417 iccmp.lpOutput = lpData;
418 iccmp.lpbiInput = lpbiInput;
419 iccmp.lpInput = lpBits;
421 iccmp.lpckid = lpckid;
422 iccmp.lpdwFlags = lpdwFlags;
423 iccmp.lFrameNum = lFrameNum;
424 iccmp.dwFrameSize = dwFrameSize;
425 iccmp.dwQuality = dwQuality;
426 iccmp.lpbiPrev = lpbiPrev;
427 iccmp.lpPrev = lpPrev;
428 return ICSendMessage(hic,ICM_COMPRESS,(DWORD)&iccmp,sizeof(iccmp));
431 /***********************************************************************
432 * ICDecompress [MSVFW32.@]
434 DWORD VFWAPIV ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat,
435 LPVOID lpData,LPBITMAPINFOHEADER lpbi,LPVOID lpBits)
440 TRACE("(%p,%ld,%p,%p,%p,%p)\n",hic,dwFlags,lpbiFormat,lpData,lpbi,lpBits);
442 TRACE("lpBits[0] == %ld\n",((LPDWORD)lpBits)[0]);
444 icd.dwFlags = dwFlags;
445 icd.lpbiInput = lpbiFormat;
446 icd.lpInput = lpData;
448 icd.lpbiOutput = lpbi;
449 icd.lpOutput = lpBits;
451 ret = ICSendMessage(hic,ICM_DECOMPRESS,(DWORD)&icd,sizeof(ICDECOMPRESS));
453 TRACE("lpBits[0] == %ld\n",((LPDWORD)lpBits)[0]);
455 TRACE("-> %ld\n",ret);
461 /***********************************************************************
462 * ICCompressorChoose [MSVFW32.@]
464 BOOL VFWAPI ICCompressorChoose(HWND hwnd, UINT uiFlags, LPVOID pvIn, LPVOID lpData,
465 PCOMPVARS pc, LPSTR lpszTitle)
472 /***********************************************************************
473 * ICCompressorFree [MSVFW32.@]
475 void VFWAPI ICCompressorFree(PCOMPVARS pc)
481 /******************************************************************
482 * MSVIDEO_SendMessage
486 LRESULT MSVIDEO_SendMessage(HIC hic,UINT msg,DWORD lParam1,DWORD lParam2)
489 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic);
491 #define XX(x) case x: TRACE("(%p,"#x",0x%08lx,0x%08lx)\n",hic,lParam1,lParam2);break;
506 XX(ICM_GETDEFAULTQUALITY);
513 XX(ICM_COMPRESS_FRAMES_INFO);
514 XX(ICM_COMPRESS_GET_FORMAT);
515 XX(ICM_COMPRESS_GET_SIZE);
516 XX(ICM_COMPRESS_QUERY);
517 XX(ICM_COMPRESS_BEGIN);
519 XX(ICM_COMPRESS_END);
520 XX(ICM_DECOMPRESS_GET_FORMAT);
521 XX(ICM_DECOMPRESS_QUERY);
522 XX(ICM_DECOMPRESS_BEGIN);
524 XX(ICM_DECOMPRESS_END);
525 XX(ICM_DECOMPRESS_SET_PALETTE);
526 XX(ICM_DECOMPRESS_GET_PALETTE);
529 XX(ICM_DRAW_GET_PALETTE);
533 XX(ICM_DRAW_GETTIME);
536 XX(ICM_DRAW_SETTIME);
537 XX(ICM_DRAW_REALIZE);
539 XX(ICM_DRAW_RENDERBUFFER);
540 XX(ICM_DRAW_START_PLAY);
541 XX(ICM_DRAW_STOP_PLAY);
542 XX(ICM_DRAW_SUGGESTFORMAT);
543 XX(ICM_DRAW_CHANGEPALETTE);
544 XX(ICM_GETBUFFERSWANTED);
545 XX(ICM_GETDEFAULTKEYFRAMERATE);
546 XX(ICM_DECOMPRESSEX_BEGIN);
547 XX(ICM_DECOMPRESSEX_QUERY);
548 XX(ICM_DECOMPRESSEX);
549 XX(ICM_DECOMPRESSEX_END);
550 XX(ICM_SET_STATUS_PROC);
552 FIXME("(%p,0x%08lx,0x%08lx,0x%08lx) unknown message\n",hic,(DWORD)msg,lParam1,lParam2);
557 if (!whic) return ICERR_BADHANDLE;
559 if (whic->driverproc) {
560 ret = whic->driverproc((DWORD)hic, whic->hdrv, msg, lParam1, lParam2);
562 ret = SendDriverMessage(whic->hdrv, msg, lParam1, lParam2);
565 TRACE(" -> 0x%08lx\n", ret);
569 /***********************************************************************
570 * ICSendMessage [MSVFW32.@]
572 LRESULT VFWAPI ICSendMessage(HIC hic, UINT msg, DWORD lParam1, DWORD lParam2) {
573 return MSVIDEO_SendMessage(hic,msg,lParam1,lParam2);
576 /***********************************************************************
577 * ICDrawBegin [MSVFW32.@]
579 DWORD VFWAPIV ICDrawBegin(
581 DWORD dwFlags, /* [in] flags */
582 HPALETTE hpal, /* [in] palette to draw with */
583 HWND hwnd, /* [in] window to draw to */
584 HDC hdc, /* [in] HDC to draw to */
585 INT xDst, /* [in] destination rectangle */
587 INT dxDst, /* [in] */
588 INT dyDst, /* [in] */
589 LPBITMAPINFOHEADER lpbi, /* [in] format of frame to draw */
590 INT xSrc, /* [in] source rectangle */
592 INT dxSrc, /* [in] */
593 INT dySrc, /* [in] */
594 DWORD dwRate, /* [in] frames/second = (dwRate/dwScale) */
595 DWORD dwScale) /* [in] */
600 TRACE("(%p,%ld,%p,%p,%p,%u,%u,%u,%u,%p,%u,%u,%u,%u,%ld,%ld)\n",
601 hic, dwFlags, hpal, hwnd, hdc, xDst, yDst, dxDst, dyDst,
602 lpbi, xSrc, ySrc, dxSrc, dySrc, dwRate, dwScale);
604 icdb.dwFlags = dwFlags;
617 icdb.dwRate = dwRate;
618 icdb.dwScale = dwScale;
619 return ICSendMessage(hic,ICM_DRAW_BEGIN,(DWORD)&icdb,sizeof(icdb));
622 /***********************************************************************
625 DWORD VFWAPIV ICDraw(HIC hic, DWORD dwFlags, LPVOID lpFormat, LPVOID lpData, DWORD cbData, LONG lTime) {
628 TRACE("(%p,%ld,%p,%p,%ld,%ld)\n",hic,dwFlags,lpFormat,lpData,cbData,lTime);
630 icd.dwFlags = dwFlags;
631 icd.lpFormat = lpFormat;
636 return ICSendMessage(hic,ICM_DRAW,(DWORD)&icd,sizeof(icd));
639 /***********************************************************************
640 * ICClose [MSVFW32.@]
642 LRESULT WINAPI ICClose(HIC hic)
644 WINE_HIC* whic = MSVIDEO_GetHicPtr(hic);
649 if (!whic) return ICERR_BADHANDLE;
651 if (whic->driverproc)
653 MSVIDEO_SendMessage(hic, DRV_CLOSE, 0, 0);
654 MSVIDEO_SendMessage(hic, DRV_DISABLE, 0, 0);
655 MSVIDEO_SendMessage(hic, DRV_FREE, 0, 0);
659 CloseDriver(whic->hdrv, 0, 0);
662 /* remove whic from list */
663 for (p = &MSVIDEO_FirstHic; *p != NULL; p = &((*p)->next))
672 HeapFree(GetProcessHeap(), 0, whic);
678 /***********************************************************************
679 * ICImageCompress [MSVFW32.@]
681 HANDLE VFWAPI ICImageCompress(
682 HIC hic, UINT uiFlags,
683 LPBITMAPINFO lpbiIn, LPVOID lpBits,
684 LPBITMAPINFO lpbiOut, LONG lQuality,
687 FIXME("(%p,%08x,%p,%p,%p,%ld,%p)\n",
688 hic, uiFlags, lpbiIn, lpBits, lpbiOut, lQuality, plSize);
693 /***********************************************************************
694 * ICImageDecompress [MSVFW32.@]
697 HANDLE VFWAPI ICImageDecompress(
698 HIC hic, UINT uiFlags, LPBITMAPINFO lpbiIn,
699 LPVOID lpBits, LPBITMAPINFO lpbiOut)
703 BOOL bReleaseIC = FALSE;
706 BOOL bSucceeded = FALSE;
707 BOOL bInDecompress = FALSE;
710 TRACE("(%p,%08x,%p,%p,%p)\n",
711 hic, uiFlags, lpbiIn, lpBits, lpbiOut);
715 hic = ICDecompressOpen( mmioFOURCC('V','I','D','C'), 0, &lpbiIn->bmiHeader, (lpbiOut != NULL) ? &lpbiOut->bmiHeader : NULL );
718 WARN("no handler\n" );
725 FIXME( "unknown flag %08x\n", uiFlags );
728 if ( lpbiIn == NULL || lpBits == NULL )
730 WARN("invalid argument\n");
734 if ( lpbiOut != NULL )
736 if ( lpbiOut->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) )
738 cbHdr = sizeof(BITMAPINFOHEADER);
739 if ( lpbiOut->bmiHeader.biCompression == 3 )
740 cbHdr += sizeof(DWORD)*3;
742 if ( lpbiOut->bmiHeader.biBitCount <= 8 )
744 if ( lpbiOut->bmiHeader.biClrUsed == 0 )
745 cbHdr += sizeof(RGBQUAD) * (1<<lpbiOut->bmiHeader.biBitCount);
747 cbHdr += sizeof(RGBQUAD) * lpbiOut->bmiHeader.biClrUsed;
752 TRACE( "get format\n" );
754 cbHdr = ICDecompressGetFormatSize(hic,lpbiIn);
755 if ( cbHdr < sizeof(BITMAPINFOHEADER) )
757 pHdr = (BYTE*)HeapAlloc(GetProcessHeap(),0,cbHdr+sizeof(RGBQUAD)*256);
760 ZeroMemory( pHdr, cbHdr+sizeof(RGBQUAD)*256 );
761 if ( ICDecompressGetFormat( hic, lpbiIn, (BITMAPINFO*)pHdr ) != ICERR_OK )
763 lpbiOut = (BITMAPINFO*)pHdr;
764 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
765 ICDecompressGetPalette( hic, lpbiIn, lpbiOut ) != ICERR_OK &&
766 lpbiIn->bmiHeader.biBitCount == lpbiOut->bmiHeader.biBitCount )
768 if ( lpbiIn->bmiHeader.biClrUsed == 0 )
769 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*(1<<lpbiOut->bmiHeader.biBitCount) );
771 memcpy( lpbiOut->bmiColors, lpbiIn->bmiColors, sizeof(RGBQUAD)*lpbiIn->bmiHeader.biClrUsed );
773 if ( lpbiOut->bmiHeader.biBitCount <= 8 &&
774 lpbiOut->bmiHeader.biClrUsed == 0 )
775 lpbiOut->bmiHeader.biClrUsed = 1<<lpbiOut->bmiHeader.biBitCount;
777 lpbiOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
778 cbHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*lpbiOut->bmiHeader.biClrUsed;
781 biSizeImage = lpbiOut->bmiHeader.biSizeImage;
782 if ( biSizeImage == 0 )
783 biSizeImage = ((((lpbiOut->bmiHeader.biWidth * lpbiOut->bmiHeader.biBitCount + 7) >> 3) + 3) & (~3)) * abs(lpbiOut->bmiHeader.biHeight);
785 TRACE( "call ICDecompressBegin\n" );
787 if ( ICDecompressBegin( hic, lpbiIn, lpbiOut ) != ICERR_OK )
789 bInDecompress = TRUE;
791 TRACE( "cbHdr %ld, biSizeImage %ld\n", cbHdr, biSizeImage );
793 hMem = GlobalAlloc( GMEM_MOVEABLE|GMEM_ZEROINIT, cbHdr + biSizeImage );
796 WARN( "out of memory\n" );
799 pMem = (BYTE*)GlobalLock( hMem );
802 memcpy( pMem, lpbiOut, cbHdr );
804 TRACE( "call ICDecompress\n" );
805 if ( ICDecompress( hic, 0, &lpbiIn->bmiHeader, lpBits, &lpbiOut->bmiHeader, pMem+cbHdr ) != ICERR_OK )
811 ICDecompressEnd( hic );
815 HeapFree(GetProcessHeap(),0,pHdr);
817 GlobalUnlock( hMem );
818 if ( !bSucceeded && hMem != NULL )
820 GlobalFree(hMem); hMem = NULL;