Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmsrle32.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2002-2003 Michael Günnewig 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 /* TODO: 00020 * - some improvements possible 00021 * - implement DecompressSetPalette? -- do we need it for anything? 00022 */ 00023 00024 #include <assert.h> 00025 00026 #include "msrle_private.h" 00027 00028 #include "winnls.h" 00029 #include "winuser.h" 00030 00031 #include "wine/debug.h" 00032 00033 WINE_DEFAULT_DEBUG_CHANNEL(msrle32); 00034 00035 static HINSTANCE MSRLE32_hModule = 0; 00036 00037 #define compare_fourcc(fcc1, fcc2) (((fcc1)^(fcc2))&~0x20202020) 00038 00039 #define ABS(a) ((a) < 0 ? -(a) : (a)) 00040 #define SQR(a) ((a) * (a)) 00041 00042 #define QUALITY_to_DIST(q) (ICQUALITY_HIGH - q) 00043 static inline WORD ColorCmp(WORD clr1, WORD clr2) 00044 { 00045 register UINT a = (clr1-clr2); 00046 return SQR(a); 00047 } 00048 static inline WORD Intensity(RGBQUAD clr) 00049 { 00050 return (30 * clr.rgbRed + 59 * clr.rgbGreen + 11 * clr.rgbBlue)/4; 00051 } 00052 00053 #define GetRawPixel(lpbi,lp,x) \ 00054 ((lpbi)->biBitCount == 1 ? ((lp)[(x)/8] >> (8 - (x)%8)) & 1 : \ 00055 ((lpbi)->biBitCount == 4 ? ((lp)[(x)/2] >> (4 * (1 - (x)%2))) & 15 : lp[x])) 00056 00057 /*****************************************************************************/ 00058 00059 /* utility functions */ 00060 static BOOL isSupportedDIB(LPCBITMAPINFOHEADER lpbi); 00061 static BOOL isSupportedMRLE(LPCBITMAPINFOHEADER lpbi); 00062 static BYTE MSRLE32_GetNearestPaletteIndex(UINT count, const RGBQUAD *clrs, RGBQUAD clr); 00063 00064 /* compression functions */ 00065 static void computeInternalFrame(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, const BYTE *lpIn); 00066 static LONG MSRLE32_GetMaxCompressedSize(LPCBITMAPINFOHEADER lpbi); 00067 static LRESULT MSRLE32_CompressRLE4(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00068 const BYTE *lpIn, LPBITMAPINFOHEADER lpbiOut, 00069 LPBYTE lpOut, BOOL isKey); 00070 static LRESULT MSRLE32_CompressRLE8(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00071 const BYTE *lpIn, LPBITMAPINFOHEADER lpbiOut, 00072 LPBYTE lpOut, BOOL isKey); 00073 00074 /* decompression functions */ 00075 static LRESULT MSRLE32_DecompressRLE4(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbi, 00076 const BYTE *lpIn, LPBYTE lpOut); 00077 static LRESULT MSRLE32_DecompressRLE8(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbi, 00078 const BYTE *lpIn, LPBYTE lpOut); 00079 00080 /* API functions */ 00081 static LRESULT CompressGetFormat(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00082 LPBITMAPINFOHEADER lpbiOut); 00083 static LRESULT CompressGetSize(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00084 LPCBITMAPINFOHEADER lpbiOut); 00085 static LRESULT CompressQuery(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00086 LPCBITMAPINFOHEADER lpbiOut); 00087 static LRESULT CompressBegin(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00088 LPCBITMAPINFOHEADER lpbiOut); 00089 static LRESULT Compress(CodecInfo *pi, ICCOMPRESS* lpic, DWORD dwSize); 00090 static LRESULT CompressEnd(CodecInfo *pi); 00091 00092 static LRESULT DecompressGetFormat(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00093 LPBITMAPINFOHEADER lpbiOut); 00094 static LRESULT DecompressQuery(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00095 LPCBITMAPINFOHEADER lpbiOut); 00096 static LRESULT DecompressBegin(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00097 LPCBITMAPINFOHEADER lpbiOut); 00098 static LRESULT Decompress(CodecInfo *pi, ICDECOMPRESS *pic, DWORD dwSize); 00099 static LRESULT DecompressEnd(CodecInfo *pi); 00100 static LRESULT DecompressGetPalette(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00101 LPBITMAPINFOHEADER lpbiOut); 00102 00103 /*****************************************************************************/ 00104 00105 static BOOL isSupportedMRLE(LPCBITMAPINFOHEADER lpbi) 00106 { 00107 /* pre-conditions */ 00108 assert(lpbi != NULL); 00109 00110 if (lpbi->biSize < sizeof(BITMAPINFOHEADER) || 00111 lpbi->biPlanes != 1) 00112 return FALSE; 00113 00114 if (lpbi->biCompression == BI_RLE4) { 00115 if (lpbi->biBitCount != 4 || 00116 (lpbi->biWidth % 2) != 0) 00117 return FALSE; 00118 } else if (lpbi->biCompression == BI_RLE8) { 00119 if (lpbi->biBitCount != 8) 00120 return FALSE; 00121 } else 00122 return FALSE; 00123 00124 return TRUE; 00125 } 00126 00127 static BOOL isSupportedDIB(LPCBITMAPINFOHEADER lpbi) 00128 { 00129 /* pre-conditions */ 00130 assert(lpbi != NULL); 00131 00132 /* check structure version/planes/compression */ 00133 if (lpbi->biSize < sizeof(BITMAPINFOHEADER) || 00134 lpbi->biPlanes != 1) 00135 return FALSE; 00136 if (lpbi->biCompression != BI_RGB && 00137 lpbi->biCompression != BI_BITFIELDS) 00138 return FALSE; 00139 00140 /* check bit-depth */ 00141 if (lpbi->biBitCount != 1 && 00142 lpbi->biBitCount != 4 && 00143 lpbi->biBitCount != 8 && 00144 lpbi->biBitCount != 15 && 00145 lpbi->biBitCount != 16 && 00146 lpbi->biBitCount != 24 && 00147 lpbi->biBitCount != 32) 00148 return FALSE; 00149 00150 /* check for size(s) */ 00151 if (!lpbi->biWidth || !lpbi->biHeight) 00152 return FALSE; /* image with zero size, makes no sense so error ! */ 00153 if (DIBWIDTHBYTES(*lpbi) * (DWORD)lpbi->biHeight >= (1UL << 31) - 1) 00154 return FALSE; /* image too big ! */ 00155 00156 /* check for nonexistent colortable for hi- and true-color DIB's */ 00157 if (lpbi->biBitCount >= 15 && lpbi->biClrUsed > 0) 00158 return FALSE; 00159 00160 return TRUE; 00161 } 00162 00163 static BYTE MSRLE32_GetNearestPaletteIndex(UINT count, const RGBQUAD *clrs, RGBQUAD clr) 00164 { 00165 INT diff = 0x00FFFFFF; 00166 UINT i; 00167 UINT idx = 0; 00168 00169 /* pre-conditions */ 00170 assert(clrs != NULL); 00171 00172 for (i = 0; i < count; i++) { 00173 int r = ((int)clrs[i].rgbRed - (int)clr.rgbRed); 00174 int g = ((int)clrs[i].rgbGreen - (int)clr.rgbGreen); 00175 int b = ((int)clrs[i].rgbBlue - (int)clr.rgbBlue); 00176 00177 r = r*r + g*g + b*b; 00178 00179 if (r < diff) { 00180 idx = i; 00181 diff = r; 00182 if (diff == 0) 00183 break; 00184 } 00185 } 00186 00187 return idx; 00188 } 00189 00190 /*****************************************************************************/ 00191 00192 void computeInternalFrame(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, const BYTE *lpIn) 00193 { 00194 WORD wIntensityTbl[256]; 00195 DWORD lInLine, lOutLine; 00196 LPWORD lpOut; 00197 UINT i; 00198 LONG y; 00199 00200 /* pre-conditions */ 00201 assert(pi != NULL && lpbiIn != NULL && lpIn != NULL); 00202 assert(pi->pCurFrame != NULL); 00203 00204 lInLine = DIBWIDTHBYTES(*lpbiIn); 00205 lOutLine = WIDTHBYTES((WORD)lpbiIn->biWidth * 8u * sizeof(WORD)) / 2u; 00206 lpOut = pi->pCurFrame; 00207 00208 assert(lpbiIn->biClrUsed != 0); 00209 00210 { 00211 const RGBQUAD *lp = 00212 (const RGBQUAD *)((const BYTE*)lpbiIn + lpbiIn->biSize); 00213 00214 for (i = 0; i < lpbiIn->biClrUsed; i++) 00215 wIntensityTbl[i] = Intensity(lp[i]); 00216 } 00217 00218 for (y = 0; y < lpbiIn->biHeight; y++) { 00219 LONG x; 00220 00221 switch (lpbiIn->biBitCount) { 00222 case 1: 00223 for (x = 0; x < lpbiIn->biWidth / 8; x++) { 00224 for (i = 0; i < 7; i++) 00225 lpOut[8 * x + i] = wIntensityTbl[(lpIn[x] >> (7 - i)) & 1]; 00226 } 00227 break; 00228 case 4: 00229 for (x = 0; x < lpbiIn->biWidth / 2; x++) { 00230 lpOut[2 * x + 0] = wIntensityTbl[(lpIn[x] >> 4)]; 00231 lpOut[2 * x + 1] = wIntensityTbl[(lpIn[x] & 0x0F)]; 00232 } 00233 break; 00234 case 8: 00235 for (x = 0; x < lpbiIn->biWidth; x++) 00236 lpOut[x] = wIntensityTbl[lpIn[x]]; 00237 break; 00238 } 00239 00240 lpIn += lInLine; 00241 lpOut += lOutLine; 00242 } 00243 } 00244 00245 static LONG MSRLE32_GetMaxCompressedSize(LPCBITMAPINFOHEADER lpbi) 00246 { 00247 LONG a, b, size; 00248 00249 /* pre-condition */ 00250 assert(lpbi != NULL); 00251 00252 a = lpbi->biWidth / 255; 00253 b = lpbi->biWidth % 255; 00254 if (lpbi->biBitCount <= 4) { 00255 a /= 2; 00256 b /= 2; 00257 } 00258 00259 size = (2 + a * (2 + ((a + 2) & ~2)) + b * (2 + ((b + 2) & ~2))); 00260 return size * lpbi->biHeight; 00261 } 00262 00263 /* lpP => current pos in previous frame 00264 * lpA => previous pos in current frame 00265 * lpB => current pos in current frame 00266 */ 00267 static INT countDiffRLE4(const WORD *lpP, const WORD *lpA, const WORD *lpB, INT pos, LONG lDist, LONG width) 00268 { 00269 INT count; 00270 WORD clr1, clr2; 00271 00272 /* pre-conditions */ 00273 assert(lpA && lpB && lDist >= 0 && width > 0); 00274 00275 if (pos >= width) 00276 return 0; 00277 if (pos+1 == width) 00278 return 1; 00279 00280 clr1 = lpB[pos++]; 00281 clr2 = lpB[pos]; 00282 00283 count = 2; 00284 while (pos + 1 < width) { 00285 WORD clr3, clr4; 00286 00287 clr3 = lpB[++pos]; 00288 if (pos + 1 >= width) 00289 return count + 1; 00290 00291 clr4 = lpB[++pos]; 00292 if (ColorCmp(clr1, clr3) <= lDist && 00293 ColorCmp(clr2, clr4) <= lDist) { 00294 /* diff at end? -- look-ahead for at least ?? more encodable pixels */ 00295 if (pos + 2 < width && ColorCmp(clr1,lpB[pos+1]) <= lDist && 00296 ColorCmp(clr2,lpB[pos+2]) <= lDist) { 00297 if (pos + 4 < width && ColorCmp(lpB[pos+1],lpB[pos+3]) <= lDist && 00298 ColorCmp(lpB[pos+2],lpB[pos+4]) <= lDist) 00299 return count - 3; /* followed by at least 4 encodable pixels */ 00300 return count - 2; 00301 } 00302 } else if (lpP != NULL && ColorCmp(lpP[pos], lpB[pos]) <= lDist) { 00303 /* 'compare' with previous frame for end of diff */ 00304 INT count2 = 0; 00305 00306 /* FIXME */ 00307 00308 if (count2 >= 8) 00309 return count; 00310 00311 pos -= count2; 00312 } 00313 00314 count += 2; 00315 clr1 = clr3; 00316 clr2 = clr4; 00317 } 00318 00319 return count; 00320 } 00321 00322 /* lpP => current pos in previous frame 00323 * lpA => previous pos in current frame 00324 * lpB => current pos in current frame 00325 */ 00326 static INT countDiffRLE8(const WORD *lpP, const WORD *lpA, const WORD *lpB, INT pos, LONG lDist, LONG width) 00327 { 00328 INT count; 00329 00330 for (count = 0; pos < width; pos++, count++) { 00331 if (ColorCmp(lpA[pos], lpB[pos]) <= lDist) { 00332 /* diff at end? -- look-ahead for some more encodable pixel */ 00333 if (pos + 1 < width && ColorCmp(lpB[pos], lpB[pos+1]) <= lDist) 00334 return count - 1; 00335 if (pos + 2 < width && ColorCmp(lpB[pos+1], lpB[pos+2]) <= lDist) 00336 return count - 1; 00337 } else if (lpP != NULL && ColorCmp(lpP[pos], lpB[pos]) <= lDist) { 00338 /* 'compare' with previous frame for end of diff */ 00339 INT count2 = 0; 00340 00341 for (count2 = 0, pos++; pos < width && count2 <= 5; pos++, count2++) { 00342 if (ColorCmp(lpP[pos], lpB[pos]) > lDist) 00343 break; 00344 } 00345 if (count2 > 4) 00346 return count; 00347 00348 pos -= count2; 00349 } 00350 } 00351 00352 return count; 00353 } 00354 00355 static INT MSRLE32_CompressRLE4Line(const CodecInfo *pi, const WORD *lpP, 00356 const WORD *lpC, LPCBITMAPINFOHEADER lpbi, 00357 const BYTE *lpIn, LONG lDist, 00358 INT x, LPBYTE *ppOut, 00359 DWORD *lpSizeImage) 00360 { 00361 LPBYTE lpOut = *ppOut; 00362 INT count, pos; 00363 WORD clr1, clr2; 00364 00365 /* try to encode as many pixel as possible */ 00366 count = 1; 00367 pos = x; 00368 clr1 = lpC[pos++]; 00369 if (pos < lpbi->biWidth) { 00370 clr2 = lpC[pos]; 00371 for (++count; pos + 1 < lpbi->biWidth; ) { 00372 ++pos; 00373 if (ColorCmp(clr1, lpC[pos]) > lDist) 00374 break; 00375 count++; 00376 if (pos + 1 >= lpbi->biWidth) 00377 break; 00378 ++pos; 00379 if (ColorCmp(clr2, lpC[pos]) > lDist) 00380 break; 00381 count++; 00382 } 00383 } 00384 00385 if (count < 4) { 00386 /* add some pixel for absoluting if possible */ 00387 count += countDiffRLE4(lpP, lpC - 1, lpC, pos-1, lDist, lpbi->biWidth); 00388 00389 assert(count > 0); 00390 00391 /* check for near end of line */ 00392 if (x + count > lpbi->biWidth) 00393 count = lpbi->biWidth - x; 00394 00395 /* absolute pixel(s) in groups of at least 3 and at most 254 pixels */ 00396 while (count > 2) { 00397 INT i; 00398 INT size = min(count, 254); 00399 int bytes = ((size + 1) & (~1)) / 2; 00400 int extra_byte = bytes & 0x01; 00401 00402 *lpSizeImage += 2 + bytes + extra_byte; 00403 assert(((*lpSizeImage) % 2) == 0); 00404 count -= size; 00405 *lpOut++ = 0; 00406 *lpOut++ = size; 00407 for (i = 0; i < size; i += 2) { 00408 clr1 = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; 00409 x++; 00410 if (i + 1 < size) { 00411 clr2 = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; 00412 x++; 00413 } else 00414 clr2 = 0; 00415 00416 *lpOut++ = (clr1 << 4) | clr2; 00417 } 00418 if (extra_byte) 00419 *lpOut++ = 0; 00420 } 00421 00422 if (count > 0) { 00423 /* too little for absoluting so we must encode them */ 00424 assert(count <= 2); 00425 00426 *lpSizeImage += 2; 00427 clr1 = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; 00428 x++; 00429 if (count == 2) { 00430 clr2 = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; 00431 x++; 00432 } else 00433 clr2 = 0; 00434 *lpOut++ = count; 00435 *lpOut++ = (clr1 << 4) | clr2; 00436 } 00437 } else { 00438 /* encode count pixel(s) */ 00439 clr1 = ((pi->palette_map[GetRawPixel(lpbi,lpIn,x)] << 4) | 00440 pi->palette_map[GetRawPixel(lpbi,lpIn,x + 1)]); 00441 00442 x += count; 00443 while (count > 0) { 00444 INT size = min(count, 254); 00445 00446 *lpSizeImage += 2; 00447 count -= size; 00448 *lpOut++ = size; 00449 *lpOut++ = clr1; 00450 } 00451 } 00452 00453 *ppOut = lpOut; 00454 00455 return x; 00456 } 00457 00458 static INT MSRLE32_CompressRLE8Line(const CodecInfo *pi, const WORD *lpP, 00459 const WORD *lpC, LPCBITMAPINFOHEADER lpbi, 00460 const BYTE *lpIn, LONG lDist, 00461 INT x, LPBYTE *ppOut, 00462 DWORD *lpSizeImage) 00463 { 00464 LPBYTE lpOut = *ppOut; 00465 INT count, pos; 00466 WORD clr; 00467 00468 assert(lpbi->biBitCount <= 8); 00469 assert(lpbi->biCompression == BI_RGB); 00470 00471 /* try to encode as much as possible */ 00472 pos = x; 00473 clr = lpC[pos++]; 00474 for (count = 1; pos < lpbi->biWidth; count++) { 00475 if (ColorCmp(clr, lpC[pos++]) > lDist) 00476 break; 00477 } 00478 00479 if (count < 2) { 00480 /* add some more pixels for absoluting if possible */ 00481 count += countDiffRLE8(lpP, lpC - 1, lpC, pos-1, lDist, lpbi->biWidth); 00482 00483 assert(count > 0); 00484 00485 /* check for over end of line */ 00486 if (x + count > lpbi->biWidth) 00487 count = lpbi->biWidth - x; 00488 00489 /* absolute pixel(s) in groups of at least 3 and at most 255 pixels */ 00490 while (count > 2) { 00491 INT i; 00492 INT size = min(count, 255); 00493 int extra_byte = size % 2; 00494 00495 *lpSizeImage += 2 + size + extra_byte; 00496 count -= size; 00497 *lpOut++ = 0; 00498 *lpOut++ = size; 00499 for (i = 0; i < size; i++) { 00500 *lpOut++ = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; 00501 x++; 00502 } 00503 if (extra_byte) 00504 *lpOut++ = 0; 00505 } 00506 if (count > 0) { 00507 /* too little for absoluting so we must encode them even if it's expensive! */ 00508 assert(count <= 2); 00509 00510 *lpSizeImage += 2 * count; 00511 *lpOut++ = 1; 00512 *lpOut++ = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; 00513 x++; 00514 00515 if (count == 2) { 00516 *lpOut++ = 1; 00517 *lpOut++ = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; 00518 x++; 00519 } 00520 } 00521 } else { 00522 /* encode count pixel(s) */ 00523 clr = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; 00524 00525 /* optimize end of line */ 00526 if (x + count + 1 == lpbi->biWidth) 00527 count++; 00528 00529 x += count; 00530 while (count > 0) { 00531 INT size = min(count, 255); 00532 00533 *lpSizeImage += 2; 00534 count -= size; 00535 *lpOut++ = size; 00536 *lpOut++ = clr; 00537 } 00538 } 00539 00540 *ppOut = lpOut; 00541 00542 return x; 00543 } 00544 00545 LRESULT MSRLE32_CompressRLE4(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00546 const BYTE *lpIn, LPBITMAPINFOHEADER lpbiOut, 00547 LPBYTE lpOut, BOOL isKey) 00548 { 00549 LPWORD lpC; 00550 LONG lLine, lInLine, lDist; 00551 LPBYTE lpOutStart = lpOut; 00552 00553 /* pre-conditions */ 00554 assert(pi != NULL && lpbiOut != NULL); 00555 assert(lpIn != NULL && lpOut != NULL); 00556 assert(pi->pCurFrame != NULL); 00557 00558 lpC = pi->pCurFrame; 00559 lDist = QUALITY_to_DIST(pi->dwQuality); 00560 lInLine = DIBWIDTHBYTES(*lpbiIn); 00561 lLine = WIDTHBYTES(lpbiOut->biWidth * 16) / 2; 00562 00563 lpbiOut->biSizeImage = 0; 00564 if (isKey) { 00565 /* keyframe -- convert internal frame to output format */ 00566 INT x, y; 00567 00568 for (y = 0; y < lpbiOut->biHeight; y++) { 00569 x = 0; 00570 00571 do { 00572 x = MSRLE32_CompressRLE4Line(pi, NULL, lpC, lpbiIn, lpIn, lDist, x, 00573 &lpOut, &lpbiOut->biSizeImage); 00574 } while (x < lpbiOut->biWidth); 00575 00576 lpC += lLine; 00577 lpIn += lInLine; 00578 00579 /* add EOL -- end of line */ 00580 lpbiOut->biSizeImage += 2; 00581 *(LPWORD)lpOut = 0; 00582 lpOut += sizeof(WORD); 00583 assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); 00584 } 00585 } else { 00586 /* delta-frame -- compute delta between last and this internal frame */ 00587 LPWORD lpP; 00588 INT x, y; 00589 INT jumpx, jumpy; 00590 00591 assert(pi->pPrevFrame != NULL); 00592 00593 lpP = pi->pPrevFrame; 00594 jumpy = 0; 00595 jumpx = -1; 00596 00597 for (y = 0; y < lpbiOut->biHeight; y++) { 00598 x = 0; 00599 00600 do { 00601 INT count, pos; 00602 00603 if (jumpx == -1) 00604 jumpx = x; 00605 for (count = 0, pos = x; pos < lpbiOut->biWidth; pos++, count++) { 00606 if (ColorCmp(lpP[pos], lpC[pos]) > lDist) 00607 break; 00608 } 00609 00610 if (pos == lpbiOut->biWidth && count > 8) { 00611 /* (count > 8) secures that we will save space */ 00612 jumpy++; 00613 break; 00614 } else if (jumpy || jumpx != pos) { 00615 /* time to jump */ 00616 assert(jumpx != -1); 00617 00618 if (pos < jumpx) { 00619 /* can only jump in positive direction -- jump until EOL, EOL */ 00620 INT w = lpbiOut->biWidth - jumpx; 00621 00622 assert(jumpy > 0); 00623 assert(w >= 4); 00624 00625 jumpx = 0; 00626 jumpy--; 00627 /* if (w % 255 == 2) then equal costs 00628 * else if (w % 255 < 4 && we could encode all) then 2 bytes too expensive 00629 * else it will be cheaper 00630 */ 00631 while (w > 0) { 00632 lpbiOut->biSizeImage += 4; 00633 *lpOut++ = 0; 00634 *lpOut++ = 2; 00635 *lpOut = min(w, 255); 00636 w -= *lpOut++; 00637 *lpOut++ = 0; 00638 } 00639 /* add EOL -- end of line */ 00640 lpbiOut->biSizeImage += 2; 00641 *((LPWORD)lpOut) = 0; 00642 lpOut += sizeof(WORD); 00643 } 00644 00645 /* FIXME: if (jumpy == 0 && could encode all) then jump too expensive */ 00646 00647 /* write out real jump(s) */ 00648 while (jumpy || pos != jumpx) { 00649 lpbiOut->biSizeImage += 4; 00650 *lpOut++ = 0; 00651 *lpOut++ = 2; 00652 *lpOut = min(pos - jumpx, 255); 00653 x += *lpOut; 00654 jumpx += *lpOut++; 00655 *lpOut = min(jumpy, 255); 00656 jumpy -= *lpOut++; 00657 } 00658 00659 jumpy = 0; 00660 } 00661 00662 jumpx = -1; 00663 00664 if (x < lpbiOut->biWidth) { 00665 /* skipped the 'same' things corresponding to previous frame */ 00666 x = MSRLE32_CompressRLE4Line(pi, lpP, lpC, lpbiIn, lpIn, lDist, x, 00667 &lpOut, &lpbiOut->biSizeImage); 00668 } 00669 } while (x < lpbiOut->biWidth); 00670 00671 lpP += lLine; 00672 lpC += lLine; 00673 lpIn += lInLine; 00674 00675 if (jumpy == 0) { 00676 assert(jumpx == -1); 00677 00678 /* add EOL -- end of line */ 00679 lpbiOut->biSizeImage += 2; 00680 *((LPWORD)lpOut) = 0; 00681 lpOut += sizeof(WORD); 00682 assert(lpOut == lpOutStart + lpbiOut->biSizeImage); 00683 } 00684 } 00685 00686 /* add EOL -- will be changed to EOI */ 00687 lpbiOut->biSizeImage += 2; 00688 *((LPWORD)lpOut) = 0; 00689 lpOut += sizeof(WORD); 00690 } 00691 00692 /* change EOL to EOI -- end of image */ 00693 lpOut[-1] = 1; 00694 assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); 00695 00696 return ICERR_OK; 00697 } 00698 00699 LRESULT MSRLE32_CompressRLE8(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 00700 const BYTE *lpIn, LPBITMAPINFOHEADER lpbiOut, 00701 LPBYTE lpOut, BOOL isKey) 00702 { 00703 LPWORD lpC; 00704 LONG lDist, lInLine, lLine; 00705 LPBYTE lpOutStart = lpOut; 00706 00707 assert(pi != NULL && lpbiOut != NULL); 00708 assert(lpIn != NULL && lpOut != NULL); 00709 assert(pi->pCurFrame != NULL); 00710 00711 lpC = pi->pCurFrame; 00712 lDist = QUALITY_to_DIST(pi->dwQuality); 00713 lInLine = DIBWIDTHBYTES(*lpbiIn); 00714 lLine = WIDTHBYTES(lpbiOut->biWidth * 16) / 2; 00715 00716 lpbiOut->biSizeImage = 0; 00717 if (isKey) { 00718 /* keyframe -- convert internal frame to output format */ 00719 INT x, y; 00720 00721 for (y = 0; y < lpbiOut->biHeight; y++) { 00722 x = 0; 00723 00724 do { 00725 x = MSRLE32_CompressRLE8Line(pi, NULL, lpC, lpbiIn, lpIn, lDist, x, 00726 &lpOut, &lpbiOut->biSizeImage); 00727 assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); 00728 } while (x < lpbiOut->biWidth); 00729 00730 lpC += lLine; 00731 lpIn += lInLine; 00732 00733 /* add EOL -- end of line */ 00734 lpbiOut->biSizeImage += 2; 00735 *((LPWORD)lpOut) = 0; 00736 lpOut += sizeof(WORD); 00737 assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); 00738 } 00739 } else { 00740 /* delta-frame -- compute delta between last and this internal frame */ 00741 LPWORD lpP; 00742 INT x, y; 00743 INT jumpx, jumpy; 00744 00745 assert(pi->pPrevFrame != NULL); 00746 00747 lpP = pi->pPrevFrame; 00748 jumpx = -1; 00749 jumpy = 0; 00750 00751 for (y = 0; y < lpbiOut->biHeight; y++) { 00752 x = 0; 00753 00754 do { 00755 INT count, pos; 00756 00757 if (jumpx == -1) 00758 jumpx = x; 00759 for (count = 0, pos = x; pos < lpbiOut->biWidth; pos++, count++) { 00760 if (ColorCmp(lpP[pos], lpC[pos]) > lDist) 00761 break; 00762 } 00763 00764 if (pos == lpbiOut->biWidth && count > 4) { 00765 /* (count > 4) secures that we will save space */ 00766 jumpy++; 00767 break; 00768 } else if (jumpy || jumpx != pos) { 00769 /* time to jump */ 00770 assert(jumpx != -1); 00771 00772 if (pos < jumpx) { 00773 /* can only jump in positive direction -- do an EOL then jump */ 00774 assert(jumpy > 0); 00775 00776 jumpx = 0; 00777 jumpy--; 00778 00779 /* add EOL -- end of line */ 00780 lpbiOut->biSizeImage += 2; 00781 *((LPWORD)lpOut) = 0; 00782 lpOut += sizeof(WORD); 00783 assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); 00784 } 00785 00786 /* FIXME: if (jumpy == 0 && could encode all) then jump too expensive */ 00787 00788 /* write out real jump(s) */ 00789 while (jumpy || pos != jumpx) { 00790 lpbiOut->biSizeImage += 4; 00791 *lpOut++ = 0; 00792 *lpOut++ = 2; 00793 *lpOut = min(pos - jumpx, 255); 00794 jumpx += *lpOut++; 00795 *lpOut = min(jumpy, 255); 00796 jumpy -= *lpOut++; 00797 } 00798 x = pos; 00799 00800 jumpy = 0; 00801 } 00802 00803 jumpx = -1; 00804 00805 if (x < lpbiOut->biWidth) { 00806 /* skip the 'same' things corresponding to previous frame */ 00807 x = MSRLE32_CompressRLE8Line(pi, lpP, lpC, lpbiIn, lpIn, lDist, x, 00808 &lpOut, &lpbiOut->biSizeImage); 00809 assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); 00810 } 00811 } while (x < lpbiOut->biWidth); 00812 00813 lpP += lLine; 00814 lpC += lLine; 00815 lpIn += lInLine; 00816 00817 if (jumpy == 0) { 00818 /* add EOL -- end of line */ 00819 lpbiOut->biSizeImage += 2; 00820 *((LPWORD)lpOut) = 0; 00821 lpOut += sizeof(WORD); 00822 assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); 00823 } 00824 } 00825 00826 /* add EOL -- will be changed to EOI */ 00827 lpbiOut->biSizeImage += 2; 00828 *((LPWORD)lpOut) = 0; 00829 lpOut += sizeof(WORD); 00830 } 00831 00832 /* change EOL to EOI -- end of image */ 00833 lpOut[-1] = 1; 00834 assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); 00835 00836 return ICERR_OK; 00837 } 00838 00839 /*****************************************************************************/ 00840 00841 static LRESULT MSRLE32_DecompressRLE4(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbi, 00842 const BYTE *lpIn, LPBYTE lpOut) 00843 { 00844 int bytes_per_pixel; 00845 int line_size; 00846 int pixel_ptr = 0; 00847 int i; 00848 BOOL bEndFlag = FALSE; 00849 00850 assert(pi != NULL); 00851 assert(lpbi != NULL && lpbi->biCompression == BI_RGB); 00852 assert(lpIn != NULL && lpOut != NULL); 00853 00854 bytes_per_pixel = (lpbi->biBitCount + 1) / 8; 00855 line_size = DIBWIDTHBYTES(*lpbi); 00856 00857 do { 00858 BYTE code0, code1; 00859 00860 code0 = *lpIn++; 00861 code1 = *lpIn++; 00862 00863 if (code0 == 0) { 00864 int extra_byte; 00865 00866 switch (code1) { 00867 case 0: /* EOL - end of line */ 00868 pixel_ptr = 0; 00869 lpOut += line_size; 00870 break; 00871 case 1: /* EOI - end of image */ 00872 bEndFlag = TRUE; 00873 break; 00874 case 2: /* skip */ 00875 pixel_ptr += *lpIn++ * bytes_per_pixel; 00876 lpOut += *lpIn++ * line_size; 00877 if (pixel_ptr >= lpbi->biWidth * bytes_per_pixel) { 00878 pixel_ptr = 0; 00879 lpOut += line_size; 00880 } 00881 break; 00882 default: /* absolute mode */ 00883 extra_byte = (((code1 + 1) & (~1)) / 2) & 0x01; 00884 00885 if (pixel_ptr/bytes_per_pixel + code1 > lpbi->biWidth) 00886 return ICERR_ERROR; 00887 00888 code0 = code1; 00889 for (i = 0; i < code0 / 2; i++) { 00890 if (bytes_per_pixel == 1) { 00891 code1 = lpIn[i]; 00892 lpOut[pixel_ptr++] = pi->palette_map[(code1 >> 4)]; 00893 if (2 * i + 1 <= code0) 00894 lpOut[pixel_ptr++] = pi->palette_map[(code1 & 0x0F)]; 00895 } else if (bytes_per_pixel == 2) { 00896 code1 = lpIn[i] >> 4; 00897 lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 0]; 00898 lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 1]; 00899 00900 if (2 * i + 1 <= code0) { 00901 code1 = lpIn[i] & 0x0F; 00902 lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 0]; 00903 lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 1]; 00904 } 00905 } else { 00906 code1 = lpIn[i] >> 4; 00907 lpOut[pixel_ptr + 0] = pi->palette_map[code1 * 4 + 0]; 00908 lpOut[pixel_ptr + 1] = pi->palette_map[code1 * 4 + 1]; 00909 lpOut[pixel_ptr + 2] = pi->palette_map[code1 * 4 + 2]; 00910 pixel_ptr += bytes_per_pixel; 00911 00912 if (2 * i + 1 <= code0) { 00913 code1 = lpIn[i] & 0x0F; 00914 lpOut[pixel_ptr + 0] = pi->palette_map[code1 * 4 + 0]; 00915 lpOut[pixel_ptr + 1] = pi->palette_map[code1 * 4 + 1]; 00916 lpOut[pixel_ptr + 2] = pi->palette_map[code1 * 4 + 2]; 00917 pixel_ptr += bytes_per_pixel; 00918 } 00919 } 00920 } 00921 if (code0 & 0x01) { 00922 if (bytes_per_pixel == 1) { 00923 code1 = lpIn[i]; 00924 lpOut[pixel_ptr++] = pi->palette_map[(code1 >> 4)]; 00925 } else if (bytes_per_pixel == 2) { 00926 code1 = lpIn[i] >> 4; 00927 lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 0]; 00928 lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 1]; 00929 } else { 00930 code1 = lpIn[i] >> 4; 00931 lpOut[pixel_ptr + 0] = pi->palette_map[code1 * 4 + 0]; 00932 lpOut[pixel_ptr + 1] = pi->palette_map[code1 * 4 + 1]; 00933 lpOut[pixel_ptr + 2] = pi->palette_map[code1 * 4 + 2]; 00934 pixel_ptr += bytes_per_pixel; 00935 } 00936 lpIn++; 00937 } 00938 lpIn += code0 / 2; 00939 00940 /* if the RLE code is odd, skip a byte in the stream */ 00941 if (extra_byte) 00942 lpIn++; 00943 }; 00944 } else { 00945 /* coded mode */ 00946 if (pixel_ptr/bytes_per_pixel + code0 > lpbi->biWidth) 00947 return ICERR_ERROR; 00948 00949 if (bytes_per_pixel == 1) { 00950 BYTE c1 = pi->palette_map[(code1 >> 4)]; 00951 BYTE c2 = pi->palette_map[(code1 & 0x0F)]; 00952 00953 for (i = 0; i < code0; i++) { 00954 if ((i & 1) == 0) 00955 lpOut[pixel_ptr++] = c1; 00956 else 00957 lpOut[pixel_ptr++] = c2; 00958 } 00959 } else if (bytes_per_pixel == 2) { 00960 BYTE hi1 = pi->palette_map[(code1 >> 4) * 2 + 0]; 00961 BYTE lo1 = pi->palette_map[(code1 >> 4) * 2 + 1]; 00962 00963 BYTE hi2 = pi->palette_map[(code1 & 0x0F) * 2 + 0]; 00964 BYTE lo2 = pi->palette_map[(code1 & 0x0F) * 2 + 1]; 00965 00966 for (i = 0; i < code0; i++) { 00967 if ((i & 1) == 0) { 00968 lpOut[pixel_ptr++] = hi1; 00969 lpOut[pixel_ptr++] = lo1; 00970 } else { 00971 lpOut[pixel_ptr++] = hi2; 00972 lpOut[pixel_ptr++] = lo2; 00973 } 00974 } 00975 } else { 00976 BYTE b1 = pi->palette_map[(code1 >> 4) * 4 + 0]; 00977 BYTE g1 = pi->palette_map[(code1 >> 4) * 4 + 1]; 00978 BYTE r1 = pi->palette_map[(code1 >> 4) * 4 + 2]; 00979 00980 BYTE b2 = pi->palette_map[(code1 & 0x0F) * 4 + 0]; 00981 BYTE g2 = pi->palette_map[(code1 & 0x0F) * 4 + 1]; 00982 BYTE r2 = pi->palette_map[(code1 & 0x0F) * 4 + 2]; 00983 00984 for (i = 0; i < code0; i++) { 00985 if ((i & 1) == 0) { 00986 lpOut[pixel_ptr + 0] = b1; 00987 lpOut[pixel_ptr + 1] = g1; 00988 lpOut[pixel_ptr + 2] = r1; 00989 } else { 00990 lpOut[pixel_ptr + 0] = b2; 00991 lpOut[pixel_ptr + 1] = g2; 00992 lpOut[pixel_ptr + 2] = r2; 00993 } 00994 pixel_ptr += bytes_per_pixel; 00995 } 00996 } 00997 } 00998 } while (! bEndFlag); 00999 01000 return ICERR_OK; 01001 } 01002 01003 static LRESULT MSRLE32_DecompressRLE8(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbi, 01004 const BYTE *lpIn, LPBYTE lpOut) 01005 { 01006 int bytes_per_pixel; 01007 int line_size; 01008 int pixel_ptr = 0; 01009 BOOL bEndFlag = FALSE; 01010 01011 assert(pi != NULL); 01012 assert(lpbi != NULL && lpbi->biCompression == BI_RGB); 01013 assert(lpIn != NULL && lpOut != NULL); 01014 01015 bytes_per_pixel = (lpbi->biBitCount + 1) / 8; 01016 line_size = DIBWIDTHBYTES(*lpbi); 01017 01018 do { 01019 BYTE code0, code1; 01020 01021 code0 = *lpIn++; 01022 code1 = *lpIn++; 01023 01024 if (code0 == 0) { 01025 int extra_byte; 01026 01027 switch (code1) { 01028 case 0: /* EOL - end of line */ 01029 pixel_ptr = 0; 01030 lpOut += line_size; 01031 break; 01032 case 1: /* EOI - end of image */ 01033 bEndFlag = TRUE; 01034 break; 01035 case 2: /* skip */ 01036 pixel_ptr += *lpIn++ * bytes_per_pixel; 01037 lpOut += *lpIn++ * line_size; 01038 if (pixel_ptr >= lpbi->biWidth * bytes_per_pixel) { 01039 pixel_ptr = 0; 01040 lpOut += line_size; 01041 } 01042 break; 01043 default: /* absolute mode */ 01044 if (pixel_ptr/bytes_per_pixel + code1 > lpbi->biWidth) { 01045 WARN("aborted absolute: (%d=%d/%d+%d) > %d\n",pixel_ptr/bytes_per_pixel + code1,pixel_ptr,bytes_per_pixel,code1,lpbi->biWidth); 01046 return ICERR_ERROR; 01047 } 01048 extra_byte = code1 & 0x01; 01049 01050 code0 = code1; 01051 while (code0--) { 01052 code1 = *lpIn++; 01053 if (bytes_per_pixel == 1) { 01054 lpOut[pixel_ptr] = pi->palette_map[code1]; 01055 } else if (bytes_per_pixel == 2) { 01056 lpOut[pixel_ptr + 0] = pi->palette_map[code1 * 2 + 0]; 01057 lpOut[pixel_ptr + 1] = pi->palette_map[code1 * 2 + 1]; 01058 } else { 01059 lpOut[pixel_ptr + 0] = pi->palette_map[code1 * 4 + 0]; 01060 lpOut[pixel_ptr + 1] = pi->palette_map[code1 * 4 + 1]; 01061 lpOut[pixel_ptr + 2] = pi->palette_map[code1 * 4 + 2]; 01062 } 01063 pixel_ptr += bytes_per_pixel; 01064 } 01065 01066 /* if the RLE code is odd, skip a byte in the stream */ 01067 if (extra_byte) 01068 lpIn++; 01069 }; 01070 } else { 01071 /* coded mode */ 01072 if (pixel_ptr/bytes_per_pixel + code0 > lpbi->biWidth) { 01073 WARN("aborted coded: (%d=%d/%d+%d) > %d\n",pixel_ptr/bytes_per_pixel + code1,pixel_ptr,bytes_per_pixel,code1,lpbi->biWidth); 01074 return ICERR_ERROR; 01075 } 01076 01077 if (bytes_per_pixel == 1) { 01078 code1 = pi->palette_map[code1]; 01079 while (code0--) 01080 lpOut[pixel_ptr++] = code1; 01081 } else if (bytes_per_pixel == 2) { 01082 BYTE hi = pi->palette_map[code1 * 2 + 0]; 01083 BYTE lo = pi->palette_map[code1 * 2 + 1]; 01084 01085 while (code0--) { 01086 lpOut[pixel_ptr + 0] = hi; 01087 lpOut[pixel_ptr + 1] = lo; 01088 pixel_ptr += bytes_per_pixel; 01089 } 01090 } else { 01091 BYTE r = pi->palette_map[code1 * 4 + 2]; 01092 BYTE g = pi->palette_map[code1 * 4 + 1]; 01093 BYTE b = pi->palette_map[code1 * 4 + 0]; 01094 01095 while (code0--) { 01096 lpOut[pixel_ptr + 0] = b; 01097 lpOut[pixel_ptr + 1] = g; 01098 lpOut[pixel_ptr + 2] = r; 01099 pixel_ptr += bytes_per_pixel; 01100 } 01101 } 01102 } 01103 } while (! bEndFlag); 01104 01105 return ICERR_OK; 01106 } 01107 01108 /*****************************************************************************/ 01109 01110 static CodecInfo* Open(LPICOPEN icinfo) 01111 { 01112 CodecInfo* pi = NULL; 01113 01114 if (icinfo == NULL) { 01115 TRACE("(NULL)\n"); 01116 return (LPVOID)0xFFFF0000; 01117 } 01118 01119 if (compare_fourcc(icinfo->fccType, ICTYPE_VIDEO)) return NULL; 01120 01121 TRACE("(%p = {%u,0x%08X(%4.4s),0x%08X(%4.4s),0x%X,0x%X,...})\n", icinfo, 01122 icinfo->dwSize, icinfo->fccType, (char*)&icinfo->fccType, 01123 icinfo->fccHandler, (char*)&icinfo->fccHandler, 01124 icinfo->dwVersion,icinfo->dwFlags); 01125 01126 switch (icinfo->fccHandler) { 01127 case FOURCC_RLE: 01128 case FOURCC_RLE4: 01129 case FOURCC_RLE8: 01130 case FOURCC_MRLE: 01131 break; 01132 case mmioFOURCC('m','r','l','e'): 01133 icinfo->fccHandler = FOURCC_MRLE; 01134 break; 01135 default: 01136 WARN("unknown FOURCC = 0x%08X(%4.4s) !\n", 01137 icinfo->fccHandler,(char*)&icinfo->fccHandler); 01138 return NULL; 01139 } 01140 01141 pi = LocalAlloc(LPTR, sizeof(CodecInfo)); 01142 01143 if (pi != NULL) { 01144 pi->fccHandler = icinfo->fccHandler; 01145 01146 pi->bCompress = FALSE; 01147 pi->dwQuality = MSRLE32_DEFAULTQUALITY; 01148 pi->nPrevFrame = -1; 01149 pi->pPrevFrame = pi->pCurFrame = NULL; 01150 01151 pi->bDecompress = FALSE; 01152 pi->palette_map = NULL; 01153 } 01154 01155 icinfo->dwError = (pi != NULL ? ICERR_OK : ICERR_MEMORY); 01156 01157 return pi; 01158 } 01159 01160 static LRESULT Close(CodecInfo *pi) 01161 { 01162 TRACE("(%p)\n", pi); 01163 01164 /* pre-condition */ 01165 assert(pi != NULL); 01166 01167 if (pi->pPrevFrame != NULL || pi->pCurFrame != NULL) 01168 CompressEnd(pi); 01169 01170 LocalFree(pi); 01171 return 1; 01172 } 01173 01174 static LRESULT GetInfo(const CodecInfo *pi, ICINFO *icinfo, DWORD dwSize) 01175 { 01176 /* pre-condition */ 01177 assert(pi != NULL); 01178 01179 /* check parameters */ 01180 if (icinfo == NULL) 01181 return sizeof(ICINFO); 01182 if (dwSize < sizeof(ICINFO)) 01183 return 0; 01184 01185 icinfo->dwSize = sizeof(ICINFO); 01186 icinfo->fccType = ICTYPE_VIDEO; 01187 icinfo->fccHandler = (pi != NULL ? pi->fccHandler : FOURCC_MRLE); 01188 icinfo->dwFlags = VIDCF_QUALITY | VIDCF_TEMPORAL | VIDCF_CRUNCH | VIDCF_FASTTEMPORALC; 01189 icinfo->dwVersion = ICVERSION; 01190 icinfo->dwVersionICM = ICVERSION; 01191 01192 LoadStringW(MSRLE32_hModule, IDS_NAME, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR)); 01193 LoadStringW(MSRLE32_hModule, IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR)); 01194 01195 return sizeof(ICINFO); 01196 } 01197 01198 static LRESULT SetQuality(CodecInfo *pi, LONG lQuality) 01199 { 01200 /* pre-condition */ 01201 assert(pi != NULL); 01202 01203 if (lQuality == -1) 01204 lQuality = MSRLE32_DEFAULTQUALITY; 01205 else if (ICQUALITY_LOW > lQuality || lQuality > ICQUALITY_HIGH) 01206 return ICERR_BADPARAM; 01207 01208 pi->dwQuality = (DWORD)lQuality; 01209 01210 return ICERR_OK; 01211 } 01212 01213 static LRESULT Configure(const CodecInfo *pi, HWND hWnd) 01214 { 01215 /* pre-condition */ 01216 assert(pi != NULL); 01217 01218 /* FIXME */ 01219 return ICERR_OK; 01220 } 01221 01222 static LRESULT About(CodecInfo *pi, HWND hWnd) 01223 { 01224 WCHAR szTitle[20]; 01225 WCHAR szAbout[128]; 01226 01227 /* pre-condition */ 01228 assert(MSRLE32_hModule != 0); 01229 01230 LoadStringW(MSRLE32_hModule, IDS_NAME, szTitle, sizeof(szTitle)/sizeof(szTitle[0])); 01231 LoadStringW(MSRLE32_hModule, IDS_ABOUT, szAbout, sizeof(szAbout)/sizeof(szAbout[0])); 01232 01233 MessageBoxW(hWnd, szAbout, szTitle, MB_OK|MB_ICONINFORMATION); 01234 01235 return ICERR_OK; 01236 } 01237 01238 static LRESULT CompressGetFormat(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 01239 LPBITMAPINFOHEADER lpbiOut) 01240 { 01241 LRESULT size; 01242 01243 TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut); 01244 01245 /* pre-condition */ 01246 assert(pi != NULL); 01247 01248 /* check parameters -- need at least input format */ 01249 if (lpbiIn == NULL) { 01250 if (lpbiOut != NULL) 01251 return ICERR_BADPARAM; 01252 return 0; 01253 } 01254 01255 /* handle unsupported input format */ 01256 if (CompressQuery(pi, lpbiIn, NULL) != ICERR_OK) 01257 return (lpbiOut == NULL ? ICERR_BADFORMAT : 0); 01258 01259 assert(0 < lpbiIn->biBitCount && lpbiIn->biBitCount <= 8); 01260 01261 switch (pi->fccHandler) { 01262 case FOURCC_RLE4: 01263 size = 1 << 4; 01264 break; 01265 case FOURCC_RLE8: 01266 size = 1 << 8; 01267 break; 01268 case FOURCC_RLE: 01269 case FOURCC_MRLE: 01270 size = (lpbiIn->biBitCount <= 4 ? 1 << 4 : 1 << 8); 01271 break; 01272 default: 01273 return ICERR_ERROR; 01274 } 01275 01276 if (lpbiIn->biClrUsed != 0) 01277 size = lpbiIn->biClrUsed; 01278 01279 size = sizeof(BITMAPINFOHEADER) + size * sizeof(RGBQUAD); 01280 01281 if (lpbiOut != NULL) { 01282 lpbiOut->biSize = sizeof(BITMAPINFOHEADER); 01283 lpbiOut->biWidth = lpbiIn->biWidth; 01284 lpbiOut->biHeight = lpbiIn->biHeight; 01285 lpbiOut->biPlanes = 1; 01286 if (pi->fccHandler == FOURCC_RLE4 || 01287 lpbiIn->biBitCount <= 4) { 01288 lpbiOut->biCompression = BI_RLE4; 01289 lpbiOut->biBitCount = 4; 01290 } else { 01291 lpbiOut->biCompression = BI_RLE8; 01292 lpbiOut->biBitCount = 8; 01293 } 01294 lpbiOut->biSizeImage = MSRLE32_GetMaxCompressedSize(lpbiOut); 01295 lpbiOut->biXPelsPerMeter = lpbiIn->biXPelsPerMeter; 01296 lpbiOut->biYPelsPerMeter = lpbiIn->biYPelsPerMeter; 01297 if (lpbiIn->biClrUsed == 0) 01298 size = 1<<lpbiIn->biBitCount; 01299 else 01300 size = lpbiIn->biClrUsed; 01301 lpbiOut->biClrUsed = min(size, 1 << lpbiOut->biBitCount); 01302 lpbiOut->biClrImportant = 0; 01303 01304 memcpy((LPBYTE)lpbiOut + lpbiOut->biSize, 01305 (const BYTE*)lpbiIn + lpbiIn->biSize, lpbiOut->biClrUsed * sizeof(RGBQUAD)); 01306 01307 return ICERR_OK; 01308 } else 01309 return size; 01310 } 01311 01312 static LRESULT CompressGetSize(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 01313 LPCBITMAPINFOHEADER lpbiOut) 01314 { 01315 /* pre-condition */ 01316 assert(pi != NULL); 01317 01318 TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut); 01319 01320 /* check parameter -- need at least one format */ 01321 if (lpbiIn == NULL && lpbiOut == NULL) 01322 return 0; 01323 /* check if the given format is supported */ 01324 if (CompressQuery(pi, lpbiIn, lpbiOut) != ICERR_OK) 01325 return 0; 01326 01327 /* the worst case is coding the complete image in absolute mode. */ 01328 if (lpbiIn) 01329 return MSRLE32_GetMaxCompressedSize(lpbiIn); 01330 else 01331 return MSRLE32_GetMaxCompressedSize(lpbiOut); 01332 } 01333 01334 static LRESULT CompressQuery(const CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 01335 LPCBITMAPINFOHEADER lpbiOut) 01336 { 01337 /* pre-condition */ 01338 assert(pi != NULL); 01339 01340 /* need at least one format */ 01341 if (lpbiIn == NULL && lpbiOut == NULL) 01342 return ICERR_BADPARAM; 01343 01344 /* check input format if given */ 01345 if (lpbiIn != NULL) { 01346 if (!isSupportedDIB(lpbiIn)) 01347 return ICERR_BADFORMAT; 01348 01349 /* for 4-bit need an even width */ 01350 if (lpbiIn->biBitCount <= 4 && (lpbiIn->biWidth % 2)) 01351 return ICERR_BADFORMAT; 01352 01353 if (pi->fccHandler == FOURCC_RLE4 && lpbiIn->biBitCount > 4) 01354 return ICERR_UNSUPPORTED; 01355 else if (lpbiIn->biBitCount > 8) 01356 return ICERR_UNSUPPORTED; 01357 } 01358 01359 /* check output format if given */ 01360 if (lpbiOut != NULL) { 01361 if (!isSupportedMRLE(lpbiOut)) 01362 return ICERR_BADFORMAT; 01363 01364 if (lpbiIn != NULL) { 01365 if (lpbiIn->biWidth != lpbiOut->biWidth) 01366 return ICERR_UNSUPPORTED; 01367 if (lpbiIn->biHeight != lpbiOut->biHeight) 01368 return ICERR_UNSUPPORTED; 01369 if (lpbiIn->biBitCount > lpbiOut->biBitCount) 01370 return ICERR_UNSUPPORTED; 01371 } 01372 } 01373 01374 return ICERR_OK; 01375 } 01376 01377 static LRESULT CompressBegin(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 01378 LPCBITMAPINFOHEADER lpbiOut) 01379 { 01380 const RGBQUAD *rgbIn; 01381 const RGBQUAD *rgbOut; 01382 UINT i; 01383 size_t size; 01384 01385 TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut); 01386 01387 /* pre-condition */ 01388 assert(pi != NULL); 01389 01390 /* check parameters -- need both formats */ 01391 if (lpbiIn == NULL || lpbiOut == NULL) 01392 return ICERR_BADPARAM; 01393 /* And both must be supported */ 01394 if (CompressQuery(pi, lpbiIn, lpbiOut) != ICERR_OK) 01395 return ICERR_BADFORMAT; 01396 01397 /* FIXME: cannot compress and decompress at same time! */ 01398 if (pi->bDecompress) { 01399 FIXME("cannot compress and decompress at same time!\n"); 01400 return ICERR_ERROR; 01401 } 01402 01403 if (pi->bCompress) 01404 CompressEnd(pi); 01405 01406 size = WIDTHBYTES(lpbiOut->biWidth * 16) / 2 * lpbiOut->biHeight; 01407 pi->pPrevFrame = GlobalLock(GlobalAlloc(GPTR, size * sizeof(WORD))); 01408 if (pi->pPrevFrame == NULL) 01409 return ICERR_MEMORY; 01410 pi->pCurFrame = GlobalLock(GlobalAlloc(GPTR, size * sizeof(WORD))); 01411 if (pi->pCurFrame == NULL) { 01412 CompressEnd(pi); 01413 return ICERR_MEMORY; 01414 } 01415 pi->nPrevFrame = -1; 01416 pi->bCompress = TRUE; 01417 01418 rgbIn = (const RGBQUAD*)((const BYTE*)lpbiIn + lpbiIn->biSize); 01419 rgbOut = (const RGBQUAD*)((const BYTE*)lpbiOut + lpbiOut->biSize); 01420 01421 switch (lpbiOut->biBitCount) { 01422 case 4: 01423 case 8: 01424 pi->palette_map = LocalAlloc(LPTR, lpbiIn->biClrUsed); 01425 if (pi->palette_map == NULL) { 01426 CompressEnd(pi); 01427 return ICERR_MEMORY; 01428 } 01429 01430 for (i = 0; i < lpbiIn->biClrUsed; i++) { 01431 pi->palette_map[i] = MSRLE32_GetNearestPaletteIndex(lpbiOut->biClrUsed, rgbOut, rgbIn[i]); 01432 } 01433 break; 01434 }; 01435 01436 return ICERR_OK; 01437 } 01438 01439 static LRESULT Compress(CodecInfo *pi, ICCOMPRESS* lpic, DWORD dwSize) 01440 { 01441 int i; 01442 01443 TRACE("(%p,%p,%u)\n",pi,lpic,dwSize); 01444 01445 /* pre-condition */ 01446 assert(pi != NULL); 01447 01448 /* check parameters */ 01449 if (lpic == NULL || dwSize < sizeof(ICCOMPRESS)) 01450 return ICERR_BADPARAM; 01451 if (!lpic->lpbiOutput || !lpic->lpOutput || 01452 !lpic->lpbiInput || !lpic->lpInput) 01453 return ICERR_BADPARAM; 01454 01455 TRACE("lpic={0x%X,%p,%p,%p,%p,%p,%p,%d,%u,%u,%p,%p}\n",lpic->dwFlags,lpic->lpbiOutput,lpic->lpOutput,lpic->lpbiInput,lpic->lpInput,lpic->lpckid,lpic->lpdwFlags,lpic->lFrameNum,lpic->dwFrameSize,lpic->dwQuality,lpic->lpbiPrev,lpic->lpPrev); 01456 01457 if (! pi->bCompress) { 01458 LRESULT hr = CompressBegin(pi, lpic->lpbiInput, lpic->lpbiOutput); 01459 if (hr != ICERR_OK) 01460 return hr; 01461 } else if (CompressQuery(pi, lpic->lpbiInput, lpic->lpbiOutput) != ICERR_OK) 01462 return ICERR_BADFORMAT; 01463 01464 if (lpic->lFrameNum >= pi->nPrevFrame + 1) { 01465 /* we continue in the sequence so we need to initialize 01466 * our internal framedata */ 01467 01468 computeInternalFrame(pi, lpic->lpbiInput, lpic->lpInput); 01469 } else if (lpic->lFrameNum == pi->nPrevFrame) { 01470 /* Oops, compress same frame again ? Okay, as you wish. 01471 * No need to recompute internal framedata, because we only swapped buffers */ 01472 LPWORD pTmp = pi->pPrevFrame; 01473 01474 pi->pPrevFrame = pi->pCurFrame; 01475 pi->pCurFrame = pTmp; 01476 } else if ((lpic->dwFlags & ICCOMPRESS_KEYFRAME) == 0) { 01477 LPWORD pTmp; 01478 01479 WARN(": prev=%d cur=%d gone back? -- untested\n",pi->nPrevFrame,lpic->lFrameNum); 01480 if (lpic->lpbiPrev == NULL || lpic->lpPrev == NULL) 01481 return ICERR_GOTOKEYFRAME; /* Need a keyframe if you go back */ 01482 if (CompressQuery(pi, lpic->lpbiPrev, lpic->lpbiOutput) != ICERR_OK) 01483 return ICERR_BADFORMAT; 01484 01485 WARN(": prev=%d cur=%d compute swapped -- untested\n",pi->nPrevFrame,lpic->lFrameNum); 01486 computeInternalFrame(pi, lpic->lpbiPrev, lpic->lpPrev); 01487 01488 /* swap buffers for current and previous frame */ 01489 /* Don't free and alloc new -- costs to much time and they are of equal size ! */ 01490 pTmp = pi->pPrevFrame; 01491 pi->pPrevFrame = pi->pCurFrame; 01492 pi->pCurFrame = pTmp; 01493 pi->nPrevFrame = lpic->lFrameNum; 01494 } 01495 01496 for (i = 0; i < 3; i++) { 01497 SetQuality(pi, lpic->dwQuality); 01498 01499 lpic->lpbiOutput->biSizeImage = 0; 01500 01501 if (lpic->lpbiOutput->biBitCount == 4) 01502 MSRLE32_CompressRLE4(pi, lpic->lpbiInput, lpic->lpInput, 01503 lpic->lpbiOutput, lpic->lpOutput, (lpic->dwFlags & ICCOMPRESS_KEYFRAME) != 0); 01504 else 01505 MSRLE32_CompressRLE8(pi, lpic->lpbiInput, lpic->lpInput, 01506 lpic->lpbiOutput, lpic->lpOutput, (lpic->dwFlags & ICCOMPRESS_KEYFRAME) != 0); 01507 01508 if (lpic->dwFrameSize == 0 || 01509 lpic->lpbiOutput->biSizeImage < lpic->dwFrameSize) 01510 break; 01511 01512 if ((*lpic->lpdwFlags & ICCOMPRESS_KEYFRAME) == 0) { 01513 if (lpic->lpbiOutput->biBitCount == 4) 01514 MSRLE32_CompressRLE4(pi, lpic->lpbiInput, lpic->lpInput, 01515 lpic->lpbiOutput, lpic->lpOutput, TRUE); 01516 else 01517 MSRLE32_CompressRLE8(pi, lpic->lpbiInput, lpic->lpInput, 01518 lpic->lpbiOutput, lpic->lpOutput, TRUE); 01519 01520 if (lpic->dwFrameSize == 0 || 01521 lpic->lpbiOutput->biSizeImage < lpic->dwFrameSize) { 01522 WARN("switched to keyframe, was small enough!\n"); 01523 *lpic->lpdwFlags |= ICCOMPRESS_KEYFRAME; 01524 *lpic->lpckid = MAKEAVICKID(cktypeDIBbits, 01525 StreamFromFOURCC(*lpic->lpckid)); 01526 break; 01527 } 01528 } 01529 01530 if (lpic->dwQuality < 1000) 01531 break; 01532 01533 lpic->dwQuality -= 1000; /* reduce quality by 10% */ 01534 } 01535 01536 { /* swap buffer for current and previous frame */ 01537 /* Don't free and alloc new -- costs to much time and they are of equal size ! */ 01538 register LPWORD pTmp = pi->pPrevFrame; 01539 01540 pi->pPrevFrame = pi->pCurFrame; 01541 pi->pCurFrame = pTmp; 01542 pi->nPrevFrame = lpic->lFrameNum; 01543 } 01544 01545 return ICERR_OK; 01546 } 01547 01548 static LRESULT CompressEnd(CodecInfo *pi) 01549 { 01550 TRACE("(%p)\n",pi); 01551 01552 if (pi != NULL) { 01553 if (pi->pPrevFrame != NULL) 01554 { 01555 GlobalUnlock(GlobalHandle(pi->pPrevFrame)); 01556 GlobalFree(GlobalHandle(pi->pPrevFrame)); 01557 } 01558 if (pi->pCurFrame != NULL) 01559 { 01560 GlobalUnlock(GlobalHandle(pi->pCurFrame)); 01561 GlobalFree(GlobalHandle(pi->pCurFrame)); 01562 } 01563 pi->pPrevFrame = NULL; 01564 pi->pCurFrame = NULL; 01565 pi->nPrevFrame = -1; 01566 pi->bCompress = FALSE; 01567 } 01568 01569 return ICERR_OK; 01570 } 01571 01572 static LRESULT DecompressGetFormat(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 01573 LPBITMAPINFOHEADER lpbiOut) 01574 { 01575 DWORD size; 01576 01577 TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut); 01578 01579 /* pre-condition */ 01580 assert(pi != NULL); 01581 01582 if (lpbiIn == NULL) 01583 return (lpbiOut != NULL ? ICERR_BADPARAM : 0); 01584 01585 if (DecompressQuery(pi, lpbiIn, NULL) != ICERR_OK) 01586 return (lpbiOut != NULL ? ICERR_BADFORMAT : 0); 01587 01588 size = lpbiIn->biSize; 01589 01590 if (lpbiIn->biBitCount <= 8) 01591 size += lpbiIn->biClrUsed * sizeof(RGBQUAD); 01592 01593 if (lpbiOut != NULL) { 01594 memcpy(lpbiOut, lpbiIn, size); 01595 lpbiOut->biCompression = BI_RGB; 01596 lpbiOut->biSizeImage = DIBWIDTHBYTES(*lpbiOut) * lpbiOut->biHeight; 01597 01598 return ICERR_OK; 01599 } else 01600 return size; 01601 } 01602 01603 static LRESULT DecompressQuery(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 01604 LPCBITMAPINFOHEADER lpbiOut) 01605 { 01606 LRESULT hr = ICERR_OK; 01607 01608 TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut); 01609 01610 /* pre-condition */ 01611 assert(pi != NULL); 01612 01613 /* need at least one format */ 01614 if (lpbiIn == NULL && lpbiOut == NULL) 01615 return ICERR_BADPARAM; 01616 01617 /* check input format if given */ 01618 if (lpbiIn != NULL) { 01619 if (!isSupportedMRLE(lpbiIn)) 01620 return ICERR_BADFORMAT; 01621 } 01622 01623 /* check output format if given */ 01624 if (lpbiOut != NULL) { 01625 if (!isSupportedDIB(lpbiOut)) 01626 hr = ICERR_BADFORMAT; 01627 01628 if (lpbiIn != NULL) { 01629 if (lpbiIn->biWidth != lpbiOut->biWidth) 01630 hr = ICERR_UNSUPPORTED; 01631 if (lpbiIn->biHeight != lpbiOut->biHeight) 01632 hr = ICERR_UNSUPPORTED; 01633 if (lpbiIn->biBitCount > lpbiOut->biBitCount) 01634 hr = ICERR_UNSUPPORTED; 01635 } 01636 } 01637 01638 return hr; 01639 } 01640 01641 static LRESULT DecompressBegin(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 01642 LPCBITMAPINFOHEADER lpbiOut) 01643 { 01644 const RGBQUAD *rgbIn; 01645 const RGBQUAD *rgbOut; 01646 UINT i; 01647 01648 TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut); 01649 01650 /* pre-condition */ 01651 assert(pi != NULL); 01652 01653 /* check parameters */ 01654 if (lpbiIn == NULL || lpbiOut == NULL) 01655 return ICERR_BADPARAM; 01656 if (DecompressQuery(pi, lpbiIn, lpbiOut) != ICERR_OK) 01657 return ICERR_BADFORMAT; 01658 01659 /* FIXME: cannot compress and decompress at a time! */ 01660 if (pi->bCompress) { 01661 FIXME("cannot compress and decompress at same time!\n"); 01662 return ICERR_ERROR; 01663 } 01664 01665 if (pi->bDecompress) 01666 DecompressEnd(pi); 01667 01668 rgbIn = (const RGBQUAD*)((const BYTE*)lpbiIn + lpbiIn->biSize); 01669 rgbOut = (const RGBQUAD*)((const BYTE*)lpbiOut + lpbiOut->biSize); 01670 01671 switch (lpbiOut->biBitCount) { 01672 case 4: 01673 case 8: 01674 pi->palette_map = LocalAlloc(LPTR, lpbiIn->biClrUsed); 01675 if (pi->palette_map == NULL) 01676 return ICERR_MEMORY; 01677 01678 for (i = 0; i < lpbiIn->biClrUsed; i++) { 01679 pi->palette_map[i] = MSRLE32_GetNearestPaletteIndex(lpbiOut->biClrUsed, rgbOut, rgbIn[i]); 01680 } 01681 break; 01682 case 15: 01683 case 16: 01684 pi->palette_map = LocalAlloc(LPTR, lpbiIn->biClrUsed * 2); 01685 if (pi->palette_map == NULL) 01686 return ICERR_MEMORY; 01687 01688 for (i = 0; i < lpbiIn->biClrUsed; i++) { 01689 WORD color; 01690 01691 if (lpbiOut->biBitCount == 15) 01692 color = ((rgbIn[i].rgbRed >> 3) << 10) 01693 | ((rgbIn[i].rgbGreen >> 3) << 5) | (rgbIn[i].rgbBlue >> 3); 01694 else 01695 color = ((rgbIn[i].rgbRed >> 3) << 11) 01696 | ((rgbIn[i].rgbGreen >> 3) << 5) | (rgbIn[i].rgbBlue >> 3); 01697 01698 pi->palette_map[i * 2 + 1] = color >> 8; 01699 pi->palette_map[i * 2 + 0] = color & 0xFF; 01700 }; 01701 break; 01702 case 24: 01703 case 32: 01704 pi->palette_map = LocalAlloc(LPTR, lpbiIn->biClrUsed * sizeof(RGBQUAD)); 01705 if (pi->palette_map == NULL) 01706 return ICERR_MEMORY; 01707 memcpy(pi->palette_map, rgbIn, lpbiIn->biClrUsed * sizeof(RGBQUAD)); 01708 break; 01709 }; 01710 01711 pi->bDecompress = TRUE; 01712 01713 return ICERR_OK; 01714 } 01715 01716 static LRESULT Decompress(CodecInfo *pi, ICDECOMPRESS *pic, DWORD dwSize) 01717 { 01718 TRACE("(%p,%p,%u)\n",pi,pic,dwSize); 01719 01720 /* pre-condition */ 01721 assert(pi != NULL); 01722 01723 /* check parameters */ 01724 if (pic == NULL) 01725 return ICERR_BADPARAM; 01726 if (pic->lpbiInput == NULL || pic->lpInput == NULL || 01727 pic->lpbiOutput == NULL || pic->lpOutput == NULL) 01728 return ICERR_BADPARAM; 01729 01730 /* check formats */ 01731 if (! pi->bDecompress) { 01732 LRESULT hr = DecompressBegin(pi, pic->lpbiInput, pic->lpbiOutput); 01733 if (hr != ICERR_OK) 01734 return hr; 01735 } else if (DecompressQuery(pi, pic->lpbiInput, pic->lpbiOutput) != ICERR_OK) 01736 return ICERR_BADFORMAT; 01737 01738 assert(pic->lpbiInput->biWidth == pic->lpbiOutput->biWidth); 01739 assert(pic->lpbiInput->biHeight == pic->lpbiOutput->biHeight); 01740 01741 pic->lpbiOutput->biSizeImage = DIBWIDTHBYTES(*pic->lpbiOutput) * pic->lpbiOutput->biHeight; 01742 if (pic->lpbiInput->biBitCount == 4) 01743 return MSRLE32_DecompressRLE4(pi, pic->lpbiOutput, pic->lpInput, pic->lpOutput); 01744 else 01745 return MSRLE32_DecompressRLE8(pi, pic->lpbiOutput, pic->lpInput, pic->lpOutput); 01746 } 01747 01748 static LRESULT DecompressEnd(CodecInfo *pi) 01749 { 01750 TRACE("(%p)\n",pi); 01751 01752 /* pre-condition */ 01753 assert(pi != NULL); 01754 01755 pi->bDecompress = FALSE; 01756 01757 if (pi->palette_map != NULL) { 01758 LocalFree(pi->palette_map); 01759 pi->palette_map = NULL; 01760 } 01761 01762 return ICERR_OK; 01763 } 01764 01765 static LRESULT DecompressGetPalette(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn, 01766 LPBITMAPINFOHEADER lpbiOut) 01767 { 01768 int size; 01769 01770 TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut); 01771 01772 /* pre-condition */ 01773 assert(pi != NULL); 01774 01775 /* check parameters */ 01776 if (lpbiIn == NULL || lpbiOut == NULL) 01777 return ICERR_BADPARAM; 01778 01779 if (DecompressQuery(pi, lpbiIn, lpbiOut) != ICERR_OK) 01780 return ICERR_BADFORMAT; 01781 01782 if (lpbiOut->biBitCount > 8) 01783 return ICERR_ERROR; 01784 01785 if (lpbiIn->biBitCount <= 8) { 01786 if (lpbiIn->biClrUsed > 0) 01787 size = lpbiIn->biClrUsed; 01788 else 01789 size = (1 << lpbiIn->biBitCount); 01790 01791 lpbiOut->biClrUsed = size; 01792 01793 memcpy((LPBYTE)lpbiOut + lpbiOut->biSize, (const BYTE*)lpbiIn + lpbiIn->biSize, size * sizeof(RGBQUAD)); 01794 } /* else could never occur ! */ 01795 01796 return ICERR_OK; 01797 } 01798 01799 /* DriverProc - entry point for an installable driver */ 01800 LRESULT CALLBACK MSRLE32_DriverProc(DWORD_PTR dwDrvID, HDRVR hDrv, UINT uMsg, 01801 LPARAM lParam1, LPARAM lParam2) 01802 { 01803 CodecInfo *pi = (CodecInfo*)dwDrvID; 01804 01805 TRACE("(%lx,%p,0x%04X,0x%08lX,0x%08lX)\n", dwDrvID, hDrv, uMsg, lParam1, lParam2); 01806 01807 switch (uMsg) { 01808 /* standard driver messages */ 01809 case DRV_LOAD: 01810 return DRVCNF_OK; 01811 case DRV_OPEN: 01812 return (LRESULT)Open((ICOPEN*)lParam2); 01813 case DRV_CLOSE: 01814 if (dwDrvID != 0xFFFF0000 && (LPVOID)dwDrvID != NULL) 01815 Close(pi); 01816 return DRVCNF_OK; 01817 case DRV_ENABLE: 01818 case DRV_DISABLE: 01819 return DRVCNF_OK; 01820 case DRV_FREE: 01821 return DRVCNF_OK; 01822 case DRV_QUERYCONFIGURE: 01823 return DRVCNF_CANCEL; /* FIXME */ 01824 case DRV_CONFIGURE: 01825 return DRVCNF_OK; /* FIXME */ 01826 case DRV_INSTALL: 01827 case DRV_REMOVE: 01828 return DRVCNF_OK; 01829 01830 /* installable compression manager messages */ 01831 case ICM_CONFIGURE: 01832 FIXME("ICM_CONFIGURE (%ld)\n",lParam1); 01833 if (lParam1 == -1) 01834 return ICERR_UNSUPPORTED; /* FIXME */ 01835 else 01836 return Configure(pi, (HWND)lParam1); 01837 case ICM_ABOUT: 01838 if (lParam1 == -1) 01839 return ICERR_OK; 01840 else 01841 return About(pi, (HWND)lParam1); 01842 case ICM_GETSTATE: 01843 case ICM_SETSTATE: 01844 return 0; /* no state */ 01845 case ICM_GETINFO: 01846 return GetInfo(pi, (ICINFO*)lParam1, (DWORD)lParam2); 01847 case ICM_GETDEFAULTQUALITY: 01848 if ((LPVOID)lParam1 != NULL) { 01849 *((LPDWORD)lParam1) = MSRLE32_DEFAULTQUALITY; 01850 return ICERR_OK; 01851 } 01852 break; 01853 case ICM_GETQUALITY: 01854 if ((LPVOID)lParam1 != NULL) { 01855 *((LPDWORD)lParam1) = pi->dwQuality; 01856 return ICERR_OK; 01857 } 01858 break; 01859 case ICM_SETQUALITY: 01860 return SetQuality(pi, *(LPLONG)lParam1); 01861 case ICM_COMPRESS_GET_FORMAT: 01862 return CompressGetFormat(pi, (LPCBITMAPINFOHEADER)lParam1, 01863 (LPBITMAPINFOHEADER)lParam2); 01864 case ICM_COMPRESS_GET_SIZE: 01865 return CompressGetSize(pi, (LPCBITMAPINFOHEADER)lParam1, 01866 (LPCBITMAPINFOHEADER)lParam2); 01867 case ICM_COMPRESS_QUERY: 01868 return CompressQuery(pi, (LPCBITMAPINFOHEADER)lParam1, 01869 (LPCBITMAPINFOHEADER)lParam2); 01870 case ICM_COMPRESS_BEGIN: 01871 return CompressBegin(pi, (LPCBITMAPINFOHEADER)lParam1, 01872 (LPCBITMAPINFOHEADER)lParam2); 01873 case ICM_COMPRESS: 01874 return Compress(pi, (ICCOMPRESS*)lParam1, (DWORD)lParam2); 01875 case ICM_COMPRESS_END: 01876 return CompressEnd(pi); 01877 case ICM_DECOMPRESS_GET_FORMAT: 01878 return DecompressGetFormat(pi, (LPCBITMAPINFOHEADER)lParam1, 01879 (LPBITMAPINFOHEADER)lParam2); 01880 case ICM_DECOMPRESS_QUERY: 01881 return DecompressQuery(pi, (LPCBITMAPINFOHEADER)lParam1, 01882 (LPCBITMAPINFOHEADER)lParam2); 01883 case ICM_DECOMPRESS_BEGIN: 01884 return DecompressBegin(pi, (LPCBITMAPINFOHEADER)lParam1, 01885 (LPCBITMAPINFOHEADER)lParam2); 01886 case ICM_DECOMPRESS: 01887 return Decompress(pi, (ICDECOMPRESS*)lParam1, (DWORD)lParam2); 01888 case ICM_DECOMPRESS_END: 01889 return DecompressEnd(pi); 01890 case ICM_DECOMPRESS_SET_PALETTE: 01891 FIXME("(...) -> SetPalette(%p,%p,%p): stub!\n", pi, (LPVOID)lParam1, (LPVOID)lParam2); 01892 return ICERR_UNSUPPORTED; 01893 case ICM_DECOMPRESS_GET_PALETTE: 01894 return DecompressGetPalette(pi, (LPBITMAPINFOHEADER)lParam1, 01895 (LPBITMAPINFOHEADER)lParam2); 01896 case ICM_GETDEFAULTKEYFRAMERATE: 01897 if ((LPVOID)lParam1 != NULL) 01898 *(LPDWORD)lParam1 = 15; 01899 return ICERR_OK; 01900 default: 01901 if (uMsg < DRV_USER) 01902 return DefDriverProc(dwDrvID, hDrv, uMsg, lParam1, lParam2); 01903 else 01904 FIXME("Unknown message uMsg=0x%08X lParam1=0x%08lX lParam2=0x%08lX\n",uMsg,lParam1,lParam2); 01905 }; 01906 01907 return ICERR_UNSUPPORTED; 01908 } 01909 01910 /* DllMain - library initialization code */ 01911 BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) 01912 { 01913 TRACE("(%p,%d,%p)\n",hModule,dwReason,lpReserved); 01914 01915 switch (dwReason) { 01916 case DLL_PROCESS_ATTACH: 01917 DisableThreadLibraryCalls(hModule); 01918 MSRLE32_hModule = hModule; 01919 break; 01920 01921 case DLL_PROCESS_DETACH: 01922 break; 01923 } 01924 01925 return TRUE; 01926 } Generated on Sat May 26 2012 04:23:53 for ReactOS by
1.7.6.1
|