Added support for ResetDC.
[wine.git] / dlls / msrle32 / msrle32.c
blob6e81246cb410864054c170b9bf98be46e0496e6e
1 /*
2 * MSRLE32 Driver
4 * Copyright 2001 TAKESHIMA Hidenori <hidenori@a2.ctktv.ne.jp>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * FIXME - encoding
21 * FIXME - RLE4
25 #include "config.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "mmsystem.h"
32 #include "vfw.h"
34 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msrle32);
40 typedef struct CodecImpl
42 BOOL bInCompress;
43 BOOL bInDecompress;
44 BOOL bInDecompressEx;
45 } CodecImpl;
47 /***********************************************************************/
49 static LONG MSRLE32_DecompressRLE4(
50 BYTE* pDst, LONG pitch,
51 const BYTE* pSrc,
52 LONG width, LONG height )
54 FIXME( "RLE4 - not implemented yet\n" );
55 return ICERR_UNSUPPORTED;
58 static LONG MSRLE32_DecompressRLE8(
59 BYTE* pDst, LONG pitch,
60 const BYTE* pSrc,
61 LONG width, LONG height )
63 LONG x,y;
64 LONG delta_x,delta_y;
65 int len;
66 UINT data;
68 x = 0; y = 0;
69 while ( y < height )
71 len = *pSrc++; data = *pSrc++;
72 if ( len > 0 )
74 /* run length encoding */
75 while ( len-- > 0 && x < width )
76 pDst[x++] = (BYTE)data;
78 else
80 switch ( data )
82 case 0: /* EOL */
83 x = 0; y++; pDst += pitch;
84 break;
85 case 1: /* END */
86 return ICERR_OK;
87 case 2: /* DELTA */
88 delta_x = (LONG)*pSrc++;
89 delta_y = (LONG)*pSrc++;
90 x += delta_x;
91 y += delta_y;
92 pDst += delta_y * pitch;
93 break;
94 default: /* RAW */
95 len = data;
96 if ( (len+x) > width )
97 len = width-x;
98 memcpy( &pDst[x], pSrc, len );
99 x += len;
100 pSrc += (data+1)&(~1);
101 break;
106 return ICERR_OK;
109 /***********************************************************************/
111 static BOOL MSRLE32_IsValidInfoHeader( const BITMAPINFO* pbiIn )
113 if ( pbiIn->bmiHeader.biSize < sizeof(BITMAPINFOHEADER) ||
114 pbiIn->bmiHeader.biWidth <= 0 ||
115 pbiIn->bmiHeader.biHeight == 0 ||
116 pbiIn->bmiHeader.biPlanes != 1 )
117 return FALSE;
119 return TRUE;
122 static DWORD MSRLE32_GetClrUsed( const BITMAPINFO* pbiIn )
124 if ( pbiIn->bmiHeader.biBitCount > 8 )
125 return 0;
126 return (pbiIn->bmiHeader.biClrUsed == 0) ? (1<<pbiIn->bmiHeader.biBitCount) : pbiIn->bmiHeader.biClrUsed;
129 static DWORD MSRLE32_GetUncompressedPitch( const BITMAPINFOHEADER* pbiIn )
131 return ((((pbiIn->biWidth*pbiIn->biBitCount)+7)>>3)+3)&(~3);
134 static DWORD MSRLE32_GetUncompressedSize( const BITMAPINFOHEADER* pbiIn )
136 return MSRLE32_GetUncompressedPitch( pbiIn ) * abs(pbiIn->biHeight);
140 static BOOL MSRLE32_IsValidRGB( const BITMAPINFO* pbiIn )
142 if ( !MSRLE32_IsValidInfoHeader( pbiIn ) )
143 return FALSE;
145 if ( pbiIn->bmiHeader.biSizeImage != 0 &&
146 pbiIn->bmiHeader.biSizeImage < MSRLE32_GetUncompressedSize( &pbiIn->bmiHeader ) )
147 return FALSE;
150 switch ( pbiIn->bmiHeader.biCompression )
152 case 0:
153 case mmioFOURCC('R','G','B',' '):
154 if ( pbiIn->bmiHeader.biBitCount == 1 ||
155 pbiIn->bmiHeader.biBitCount == 4 ||
156 pbiIn->bmiHeader.biBitCount == 8 ||
157 pbiIn->bmiHeader.biBitCount == 16 ||
158 pbiIn->bmiHeader.biBitCount == 24 ||
159 pbiIn->bmiHeader.biBitCount == 32 )
160 return TRUE;
161 break;
162 default:
163 break;
166 return FALSE;
169 static BOOL MSRLE32_IsValidRLE( const BITMAPINFO* pbiIn )
171 if ( !MSRLE32_IsValidInfoHeader( pbiIn ) )
172 return FALSE;
174 switch ( pbiIn->bmiHeader.biCompression )
176 case 1:
177 case 2:
178 case mmioFOURCC('R','L','E',' '):
179 case mmioFOURCC('R','L','E','8'):
180 case mmioFOURCC('R','L','E','4'):
181 case mmioFOURCC('M','R','L','E'):
182 if ( pbiIn->bmiHeader.biBitCount == 8 ||
183 pbiIn->bmiHeader.biBitCount == 4 )
184 return TRUE;
185 break;
186 default:
187 break;
190 return FALSE;
193 static BOOL MSRLE32_CompareInfoHeader( const BITMAPINFO* pbiIn, const BITMAPINFO* pbiOut )
195 if ( !MSRLE32_IsValidInfoHeader( pbiIn ) ||
196 !MSRLE32_IsValidInfoHeader( pbiOut ) )
197 return FALSE;
199 if ( pbiIn->bmiHeader.biWidth != pbiOut->bmiHeader.biWidth ||
200 pbiIn->bmiHeader.biHeight != pbiOut->bmiHeader.biHeight ||
201 pbiIn->bmiHeader.biPlanes != pbiOut->bmiHeader.biPlanes ||
202 pbiIn->bmiHeader.biBitCount != pbiOut->bmiHeader.biBitCount )
203 return FALSE;
205 return TRUE;
209 /***********************************************************************/
211 static LONG Codec_DrvQueryConfigure( CodecImpl* This )
213 return ICERR_UNSUPPORTED;
216 static LONG Codec_DrvConfigure( CodecImpl* This, HWND hwnd, DRVCONFIGINFO* pinfo )
218 return ICERR_UNSUPPORTED;
221 static LONG Codec_QueryAbout( void )
223 return ICERR_UNSUPPORTED;
226 static LONG Codec_About( HWND hwnd )
228 return ICERR_UNSUPPORTED;
231 static LONG Codec_CompressQuery( CodecImpl* This, BITMAPINFO* pbiIn, BITMAPINFO* pbiOut )
233 FIXME( "compression is not implemented!\n" );
234 return ICERR_UNSUPPORTED;
237 static LONG Codec_CompressBegin( CodecImpl* This, BITMAPINFO* pbiIn, BITMAPINFO* pbiOut )
239 return ICERR_UNSUPPORTED;
242 static LONG Codec_Compress( CodecImpl* This, ICCOMPRESS* picc, DWORD dwSize )
244 FIXME( "compression is not implemented!\n" );
245 return ICERR_UNSUPPORTED;
248 static LONG Codec_CompressEnd( CodecImpl* This )
250 This->bInCompress = FALSE;
251 return ICERR_UNSUPPORTED;
254 static LONG Codec_CompressFramesInfo( CodecImpl* This, ICCOMPRESSFRAMES* piccf, DWORD dwSize )
256 return ICERR_UNSUPPORTED;
259 static LONG Codec_CompressGetFormat( CodecImpl* This, BITMAPINFO* pbiIn, BITMAPINFO* pbiOut )
261 return ICERR_UNSUPPORTED;
264 static LONG Codec_CompressGetSize( CodecImpl* This, BITMAPINFO* pbiIn, BITMAPINFO* pbiOut )
266 return ICERR_UNSUPPORTED;
269 static LONG Codec_ICQueryConfigure( CodecImpl* This )
271 return ICERR_OK;
273 static LONG Codec_ICConfigure( CodecImpl* This, HWND hwnd )
275 MessageBoxA( hwnd, "Wine RLE Driver", "MSRLE32", MB_OK );
276 return ICERR_OK;
279 static LONG Codec_DecompressQuery( CodecImpl* This, BITMAPINFO* pbiIn, BITMAPINFO* pbiOut )
281 if ( pbiIn == NULL )
282 return ICERR_BADPARAM;
283 if ( !MSRLE32_IsValidRLE( pbiIn ) )
284 return ICERR_UNSUPPORTED;
286 if ( pbiOut != NULL )
288 if ( !MSRLE32_IsValidRGB( pbiOut ) )
289 return ICERR_UNSUPPORTED;
290 if ( !MSRLE32_CompareInfoHeader( pbiIn, pbiOut ) )
291 return ICERR_UNSUPPORTED;
294 return ICERR_OK;
297 static LONG Codec_DecompressBegin( CodecImpl* This, BITMAPINFO* pbiIn, BITMAPINFO* pbiOut )
299 LONG lr;
301 if ( pbiIn == NULL || pbiOut == NULL )
302 return ICERR_BADPARAM;
303 lr = Codec_DecompressQuery( This, pbiIn, pbiOut );
304 if ( lr != ICERR_OK )
305 return lr;
307 This->bInDecompress = TRUE;
309 return ICERR_OK;
312 static LONG Codec_Decompress( CodecImpl* This, ICDECOMPRESS* picd, DWORD dwSize )
314 LONG lr;
316 if ( !This->bInDecompress )
317 return ICERR_BADHANDLE; /* FIXME? */
319 if ( ( picd->dwFlags & ICDECOMPRESS_NOTKEYFRAME ) &&
320 ( picd->dwFlags & ICDECOMPRESS_UPDATE ) )
321 return ICERR_CANTUPDATE; /* FIXME? */
323 if ( picd->lpbiInput == NULL ||
324 picd->lpInput == NULL ||
325 picd->lpbiOutput == NULL ||
326 picd->lpOutput == NULL )
327 return ICERR_BADPARAM;
329 switch ( picd->lpbiInput->biBitCount )
331 case 4: /* RLE4 */
332 lr = MSRLE32_DecompressRLE4(
333 (BYTE*)picd->lpOutput,
334 MSRLE32_GetUncompressedPitch( picd->lpbiInput ),
335 (const BYTE*)picd->lpInput,
336 picd->lpbiInput->biWidth,
337 picd->lpbiInput->biHeight );
338 break;
339 case 8: /* RLE8 */
340 lr = MSRLE32_DecompressRLE8(
341 (BYTE*)picd->lpOutput,
342 MSRLE32_GetUncompressedPitch( picd->lpbiInput ),
343 (const BYTE*)picd->lpInput,
344 picd->lpbiInput->biWidth,
345 picd->lpbiInput->biHeight );
346 break;
347 default:
348 lr = ICERR_BADBITDEPTH;
349 break;
352 return lr;
355 static LONG Codec_DecompressEnd( CodecImpl* This )
357 This->bInDecompress = FALSE;
358 return ICERR_OK;
361 static LONG Codec_DecompressGetFormat( CodecImpl* This, BITMAPINFO* pbiIn, BITMAPINFO* pbiOut )
363 DWORD biClrUsed;
364 LONG lr;
366 if ( pbiIn == NULL )
367 return ICERR_BADPARAM;
369 lr = Codec_DecompressQuery( This, pbiIn, NULL );
370 if ( lr != ICERR_OK )
371 return ( pbiOut == NULL ) ? 0 : lr;
373 biClrUsed = MSRLE32_GetClrUsed(pbiIn);
374 if ( pbiOut == NULL )
375 return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * biClrUsed;
377 ZeroMemory( pbiOut, sizeof(BITMAPINFOHEADER) );
378 memcpy( &pbiOut->bmiHeader, &pbiIn->bmiHeader, sizeof(BITMAPINFOHEADER) );
379 memcpy( &pbiOut->bmiColors, &pbiIn->bmiColors, sizeof(RGBQUAD) * biClrUsed );
380 pbiOut->bmiHeader.biCompression = 0;
381 pbiOut->bmiHeader.biSizeImage = MSRLE32_GetUncompressedSize( &pbiOut->bmiHeader );
383 return ICERR_OK;
386 static LONG Codec_DecompressGetPalette( CodecImpl* This, BITMAPINFO* pbiIn, BITMAPINFO* pbiOut )
388 if ( pbiIn == NULL )
389 return ICERR_BADPARAM;
391 return (pbiOut == NULL) ? 0 : ICERR_UNSUPPORTED;
394 static LONG Codec_DecompressSetPalette( CodecImpl* This, BITMAPINFO* pbiIn )
396 return ICERR_UNSUPPORTED;
399 static LONG Codec_DecompressExQuery( CodecImpl* This, ICDECOMPRESSEX* picdex, DWORD dwSize )
401 FIXME( "DecompressEx is not implemented!\n" );
402 return ICERR_UNSUPPORTED;
405 static LONG Codec_DecompressExBegin( CodecImpl* This, ICDECOMPRESSEX* picdex, DWORD dwSize )
407 FIXME( "DecompressEx is not implemented!\n" );
408 return ICERR_UNSUPPORTED;
411 static LONG Codec_DecompressEx( CodecImpl* This, ICDECOMPRESSEX* picdex, DWORD dwSize )
413 return ICERR_UNSUPPORTED;
416 static LONG Codec_DecompressExEnd( CodecImpl* This )
418 This->bInDecompressEx = FALSE;
419 return ICERR_UNSUPPORTED;
422 static LONG Codec_GetInfo( CodecImpl* This, ICINFO* pici, DWORD dwSize )
424 return ICERR_UNSUPPORTED;
427 static LONG Codec_GetQuality( CodecImpl* This, DWORD* pdwQuality )
429 return ICERR_UNSUPPORTED;
432 static LONG Codec_GetState( CodecImpl* This, LPVOID pvState, DWORD dwSize )
434 if ( pvState == NULL )
435 return 0;
437 /* no driver-specific state */
439 return 0;
442 static LONG Codec_SetQuality( CodecImpl* This, DWORD* pdwQuality )
444 return ICERR_UNSUPPORTED;
447 static LONG Codec_SetStatusProc(CodecImpl* This, ICSETSTATUSPROC* picssp, DWORD dwSize )
449 if ( picssp == NULL )
450 return 0;
452 /* no driver-specific state */
454 return 0;
457 static LONG Codec_SetState( CodecImpl* This, LPVOID pvState, DWORD dwSize )
459 return ICERR_UNSUPPORTED;
462 static CodecImpl* Codec_AllocDriver( void )
464 CodecImpl* This;
466 This = HeapAlloc( GetProcessHeap(), 0, sizeof(CodecImpl) );
467 if ( This == NULL )
468 return NULL;
469 ZeroMemory( This, sizeof(CodecImpl) );
470 This->bInCompress = FALSE;
471 This->bInDecompress = FALSE;
472 This->bInDecompressEx = FALSE;
474 return This;
477 static void Codec_Close( CodecImpl* This )
479 if ( This->bInCompress )
480 Codec_CompressEnd(This);
481 if ( This->bInDecompress )
482 Codec_DecompressEnd(This);
483 if ( This->bInDecompressEx )
484 Codec_DecompressExEnd(This);
486 HeapFree( GetProcessHeap(), 0, This );
494 LONG WINAPI MSRLE32_DriverProc(
495 DWORD dwDriverId, HDRVR hdrvr, UINT msg, LONG lParam1, LONG lParam2 )
497 TRACE( "DriverProc(%08lx,%08x,%08x,%08lx,%08lx)\n",
498 dwDriverId, hdrvr, msg, lParam1, lParam2 );
500 switch ( msg )
502 case DRV_LOAD:
503 TRACE("DRV_LOAD\n");
504 return TRUE;
505 case DRV_FREE:
506 TRACE("DRV_FREE\n");
507 return TRUE;
508 case DRV_OPEN:
509 TRACE("DRV_OPEN\n");
510 return (LONG)Codec_AllocDriver();
511 case DRV_CLOSE:
512 TRACE("DRV_CLOSE\n");
513 Codec_Close( (CodecImpl*)dwDriverId );
514 return TRUE;
515 case DRV_ENABLE:
516 TRACE("DRV_ENABLE\n");
517 return TRUE;
518 case DRV_DISABLE:
519 TRACE("DRV_DISABLE\n");
520 return TRUE;
521 case DRV_QUERYCONFIGURE:
522 TRACE("DRV_QUERYCONFIGURE\n");
523 return Codec_DrvQueryConfigure( (CodecImpl*)dwDriverId );
524 case DRV_CONFIGURE:
525 TRACE("DRV_CONFIGURE\n");
526 return Codec_DrvConfigure( (CodecImpl*)dwDriverId,
527 (HWND)lParam1, (DRVCONFIGINFO*)lParam2 );
528 case DRV_INSTALL:
529 TRACE("DRV_INSTALL\n");
530 return DRVCNF_OK;
531 case DRV_REMOVE:
532 TRACE("DRV_REMOVE\n");
533 return 0;
534 case DRV_POWER:
535 TRACE("DRV_POWER\n");
536 return TRUE;
538 case ICM_ABOUT:
539 TRACE("ICM_ABOUT\n");
540 return (lParam1 == -1) ? Codec_QueryAbout() : Codec_About( (HWND)lParam1 );
541 case ICM_COMPRESS:
542 TRACE("ICM_COMPRESS\n");
543 return Codec_Compress((CodecImpl*)dwDriverId,(ICCOMPRESS*)lParam1,(DWORD)lParam2);
544 case ICM_COMPRESS_BEGIN:
545 TRACE("ICM_COMPRESS_BEGIN\n");
546 return Codec_CompressBegin((CodecImpl*)dwDriverId,(BITMAPINFO*)lParam1,(BITMAPINFO*)lParam2);
547 case ICM_COMPRESS_END:
548 TRACE("ICM_COMPRESS_END\n");
549 return Codec_CompressEnd((CodecImpl*)dwDriverId);
550 case ICM_COMPRESS_FRAMES_INFO:
551 TRACE("ICM_COMPRESS_FRAMES_INFO\n");
552 return Codec_CompressFramesInfo((CodecImpl*)dwDriverId,(ICCOMPRESSFRAMES*)lParam1,(DWORD)lParam2);
553 case ICM_COMPRESS_GET_FORMAT:
554 TRACE("ICM_COMPRESS_GET_FORMAT\n");
555 return Codec_CompressGetFormat((CodecImpl*)dwDriverId,(BITMAPINFO*)lParam1,(BITMAPINFO*)lParam2);
556 case ICM_COMPRESS_GET_SIZE:
557 TRACE("ICM_COMPRESS_GET_SIZE\n");
558 return Codec_CompressGetSize((CodecImpl*)dwDriverId,(BITMAPINFO*)lParam1,(BITMAPINFO*)lParam2);
559 case ICM_COMPRESS_QUERY:
560 TRACE("ICM_COMPRESS_GET_SIZE\n");
561 return Codec_CompressQuery((CodecImpl*)dwDriverId,(BITMAPINFO*)lParam1,(BITMAPINFO*)lParam2);
563 case ICM_CONFIGURE:
564 TRACE("ICM_CONFIGURE\n");
565 return ( lParam1 == -1 ) ? Codec_ICQueryConfigure( (CodecImpl*)dwDriverId ) : Codec_ICConfigure( (CodecImpl*)dwDriverId, (HWND)lParam1 );
567 case ICM_DECOMPRESS:
568 TRACE( "ICM_DECOMPRESS\n" );
569 return Codec_Decompress((CodecImpl*)dwDriverId,(ICDECOMPRESS*)lParam1,(DWORD)lParam2);
570 case ICM_DECOMPRESS_BEGIN:
571 TRACE( "ICM_DECOMPRESS_BEGIN\n" );
572 return Codec_DecompressBegin((CodecImpl*)dwDriverId,(BITMAPINFO*)lParam1,(BITMAPINFO*)lParam2);
573 case ICM_DECOMPRESS_END:
574 TRACE( "ICM_DECOMPRESS_END\n" );
575 return Codec_DecompressEnd((CodecImpl*)dwDriverId);
576 case ICM_DECOMPRESS_GET_FORMAT:
577 TRACE( "ICM_DECOMPRESS_GET_FORMAT\n" );
578 return Codec_DecompressGetFormat((CodecImpl*)dwDriverId,(BITMAPINFO*)lParam1,(BITMAPINFO*)lParam2);
579 case ICM_DECOMPRESS_GET_PALETTE:
580 TRACE( "ICM_DECOMPRESS_GET_PALETTE\n" );
581 return Codec_DecompressGetPalette((CodecImpl*)dwDriverId,(BITMAPINFO*)lParam1,(BITMAPINFO*)lParam2);
582 case ICM_DECOMPRESS_QUERY:
583 TRACE( "ICM_DECOMPRESS_QUERY\n" );
584 return Codec_DecompressQuery((CodecImpl*)dwDriverId,(BITMAPINFO*)lParam1,(BITMAPINFO*)lParam2);
585 case ICM_DECOMPRESS_SET_PALETTE:
586 TRACE( "ICM_DECOMPRESS_SET_PALETTE\n" );
587 return Codec_DecompressSetPalette((CodecImpl*)dwDriverId,(BITMAPINFO*)lParam1);
589 case ICM_DECOMPRESSEX_BEGIN:
590 TRACE( "ICM_DECOMPRESSEX_BEGIN\n" );
591 return Codec_DecompressExBegin((CodecImpl*)dwDriverId,(ICDECOMPRESSEX*)lParam1,(DWORD)lParam2);
592 case ICM_DECOMPRESSEX:
593 TRACE( "ICM_DECOMPRESSEX\n" );
594 return Codec_DecompressEx((CodecImpl*)dwDriverId,(ICDECOMPRESSEX*)lParam1,(DWORD)lParam2);
595 case ICM_DECOMPRESSEX_END:
596 TRACE( "ICM_DECOMPRESSEX_END\n" );
597 return Codec_DecompressExEnd((CodecImpl*)dwDriverId);
598 case ICM_DECOMPRESSEX_QUERY:
599 TRACE( "ICM_DECOMPRESSEX_QUERY\n" );
600 return Codec_DecompressExQuery((CodecImpl*)dwDriverId,(ICDECOMPRESSEX*)lParam1,(DWORD)lParam2);
602 case ICM_GETINFO:
603 TRACE( "ICM_GETINFO\n" );
604 return Codec_GetInfo((CodecImpl*)dwDriverId,(ICINFO*)lParam1,(DWORD)lParam2);
605 case ICM_GETQUALITY:
606 TRACE( "ICM_SETQUALITY\n");
607 return Codec_GetQuality((CodecImpl*)dwDriverId,(DWORD*)lParam1);
608 case ICM_GETSTATE:
609 TRACE( "ICM_GETSTATE\n" );
610 return Codec_GetState((CodecImpl*)dwDriverId,(LPVOID)lParam1,(DWORD)lParam2);
611 case ICM_SETQUALITY:
612 TRACE( "ICM_SETQUALITY\n");
613 return Codec_SetQuality((CodecImpl*)dwDriverId,(DWORD*)lParam1);
614 case ICM_SET_STATUS_PROC:
615 TRACE( "ICM_SET_STATUS_PROC\n" );
616 return Codec_SetStatusProc((CodecImpl*)dwDriverId,(ICSETSTATUSPROC*)lParam1,(DWORD)lParam2);
617 case ICM_SETSTATE:
618 TRACE( "ICM_SETSTATE\n" );
619 return Codec_SetState((CodecImpl*)dwDriverId,(LPVOID)lParam1,(DWORD)lParam2);
623 return DefDriverProc( dwDriverId, hdrvr, msg, lParam1, lParam2 );
626 BOOL WINAPI MSRLE32_DllMain( HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved )
628 TRACE( "(%08x,%08lx,%p)\n",hInst,dwReason,lpvReserved );
630 return TRUE;