msrle32.c
来自「Wine-20031016」· C语言 代码 · 共 1,915 行 · 第 1/4 页
C
1,915 行
/* check for over end of line */ if (x + count > lpbi->biWidth) count = lpbi->biWidth - x; /* absolute pixel(s) in groups of atleast 3 and maximal 255 pixels */ while (count > 2) { INT i; INT size = min(count, 255); BOOL extra_byte = size % 2; *lpSizeImage += 2 + size + extra_byte; count -= size; *lpOut++ = 0; *lpOut++ = size; for (i = 0; i < size; i++) { *lpOut++ = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; x++; } if (extra_byte) *lpOut++ = 0; } if (count > 0) { /* too less for absoluting so we must encode them even if it's expensive! */ assert(count <= 2); *lpSizeImage += 2 * count; *lpOut++ = 1; *lpOut++ = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; x++; if (count == 2) { *lpOut++ = 1; *lpOut++ = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; x++; } } } else { /* encode count pixel(s) */ clr = pi->palette_map[GetRawPixel(lpbi,lpIn,x)]; /* optimize end of line */ if (x + count + 1 == lpbi->biWidth) count++; x += count; while (count > 0) { INT size = min(count, 255); *lpSizeImage += 2; count -= size; *lpOut++ = size; *lpOut++ = clr; } } *ppOut = lpOut; return x;}LRESULT MSRLE32_CompressRLE4(CodecInfo *pi, LPBITMAPINFOHEADER lpbiIn, LPBYTE lpIn, LPBITMAPINFOHEADER lpbiOut, LPBYTE lpOut, BOOL isKey){ LPWORD lpC; LONG lLine, lInLine, lDist; LPBYTE lpOutStart = lpOut; /* pre-conditions */ assert(pi != NULL && lpbiOut != NULL); assert(lpIn != NULL && lpOut != NULL); assert(pi->pCurFrame != NULL); lpC = pi->pCurFrame; lDist = QUALITY_to_DIST(pi->dwQuality); lInLine = DIBWIDTHBYTES(*lpbiIn); lLine = WIDTHBYTES(lpbiOut->biWidth * 16) / 2; lpbiOut->biSizeImage = 0; if (isKey) { /* keyframe -- convert internal frame to output format */ INT x, y; for (y = 0; y < lpbiOut->biHeight; y++) { x = 0; do { x = MSRLE32_CompressRLE4Line(pi, NULL, lpC, lpbiIn, lpIn, lDist, x, &lpOut, &lpbiOut->biSizeImage); } while (x < lpbiOut->biWidth); lpC += lLine; lpIn += lInLine; /* add EOL -- end of line */ lpbiOut->biSizeImage += 2; *((LPWORD)lpOut)++ = 0; assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); } } else { /* delta-frame -- compute delta between last and this internal frame */ LPWORD lpP; INT x, y; INT jumpx, jumpy; assert(pi->pPrevFrame != NULL); lpP = pi->pPrevFrame; jumpy = 0; jumpx = -1; for (y = 0; y < lpbiOut->biHeight; y++) { x = 0; do { INT count, pos; if (jumpx == -1) jumpx = x; for (count = 0, pos = x; pos < lpbiOut->biWidth; pos++, count++) { if (ColorCmp(lpP[pos], lpC[pos]) > lDist) break; } if (pos == lpbiOut->biWidth && count > 8) { /* (count > 8) secures that we will save space */ jumpy++; break; } else if (jumpy || jumpx != pos) { /* time to jump */ assert(jumpx != -1); if (pos < jumpx) { /* can only jump in positive direction -- jump until EOL, EOL */ INT w = lpbiOut->biWidth - jumpx; assert(jumpy > 0); assert(w >= 4); jumpx = 0; jumpy--; /* if (w % 255 == 2) then equal costs * else if (w % 255 < 4 && we could encode all) then 2 bytes too expensive * else it will be cheaper */ while (w > 0) { lpbiOut->biSizeImage += 4; *lpOut++ = 0; *lpOut++ = 2; *lpOut = min(w, 255); w -= *lpOut++; *lpOut++ = 0; } /* add EOL -- end of line */ lpbiOut->biSizeImage += 2; *((LPWORD)lpOut)++ = 0; } /* FIXME: if (jumpy == 0 && could encode all) then jump too expensive */ /* write out real jump(s) */ while (jumpy || pos != jumpx) { lpbiOut->biSizeImage += 4; *lpOut++ = 0; *lpOut++ = 2; *lpOut = min(pos - jumpx, 255); x += *lpOut; jumpx += *lpOut++; *lpOut = min(jumpy, 255); jumpy -= *lpOut++; } jumpy = 0; } jumpx = -1; if (x < lpbiOut->biWidth) { /* skipped the 'same' things corresponding to previous frame */ x = MSRLE32_CompressRLE4Line(pi, lpP, lpC, lpbiIn, lpIn, lDist, x, &lpOut, &lpbiOut->biSizeImage); } } while (x < lpbiOut->biWidth); lpP += lLine; lpC += lLine; lpIn += lInLine; if (jumpy == 0) { assert(jumpx == -1); /* add EOL -- end of line */ lpbiOut->biSizeImage += 2; *((LPWORD)lpOut)++ = 0; assert(lpOut == lpOutStart + lpbiOut->biSizeImage); } } /* add EOL -- will be changed to EOI */ lpbiOut->biSizeImage += 2; *((LPWORD)lpOut)++ = 0; } /* change EOL to EOI -- end of image */ lpOut[-1] = 1; assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); return ICERR_OK;}LRESULT MSRLE32_CompressRLE8(CodecInfo *pi, LPBITMAPINFOHEADER lpbiIn, LPBYTE lpIn, LPBITMAPINFOHEADER lpbiOut, LPBYTE lpOut, BOOL isKey){ LPWORD lpC; LONG lDist, lInLine, lLine; LPBYTE lpOutStart = lpOut; assert(pi != NULL && lpbiOut != NULL); assert(lpIn != NULL && lpOut != NULL); assert(pi->pCurFrame != NULL); lpC = pi->pCurFrame; lDist = QUALITY_to_DIST(pi->dwQuality); lInLine = DIBWIDTHBYTES(*lpbiIn); lLine = WIDTHBYTES(lpbiOut->biWidth * 16) / 2; lpbiOut->biSizeImage = 0; if (isKey) { /* keyframe -- convert internal frame to output format */ INT x, y; for (y = 0; y < lpbiOut->biHeight; y++) { x = 0; do { x = MSRLE32_CompressRLE8Line(pi, NULL, lpC, lpbiIn, lpIn, lDist, x, &lpOut, &lpbiOut->biSizeImage); assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); } while (x < lpbiOut->biWidth); lpC += lLine; lpIn += lInLine; /* add EOL -- end of line */ lpbiOut->biSizeImage += 2; *((LPWORD)lpOut)++ = 0; assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); } } else { /* delta-frame -- compute delta between last and this internal frame */ LPWORD lpP; INT x, y; INT jumpx, jumpy; assert(pi->pPrevFrame != NULL); lpP = pi->pPrevFrame; jumpx = -1; jumpy = 0; for (y = 0; y < lpbiOut->biHeight; y++) { x = 0; do { INT count, pos; if (jumpx == -1) jumpx = x; for (count = 0, pos = x; pos < lpbiOut->biWidth; pos++, count++) { if (ColorCmp(lpP[pos], lpC[pos]) > lDist) break; } if (pos == lpbiOut->biWidth && count > 4) { /* (count > 4) secures that we will save space */ jumpy++; break; } else if (jumpy || jumpx != pos) { /* time to jump */ assert(jumpx != -1); if (pos < jumpx) { /* can only jump in positive direction -- do a EOL then jump */ assert(jumpy > 0); jumpx = 0; jumpy--; /* add EOL -- end of line */ lpbiOut->biSizeImage += 2; *((LPWORD)lpOut)++ = 0; assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); } /* FIXME: if (jumpy == 0 && could encode all) then jump too expensive */ /* write out real jump(s) */ while (jumpy || pos != jumpx) { lpbiOut->biSizeImage += 4; *lpOut++ = 0; *lpOut++ = 2; *lpOut = min(pos - jumpx, 255); jumpx += *lpOut++; *lpOut = min(jumpy, 255); jumpy -= *lpOut++; } x = pos; jumpy = 0; } jumpx = -1; if (x < lpbiOut->biWidth) { /* skip the 'same' things corresponding to previous frame */ x = MSRLE32_CompressRLE8Line(pi, lpP, lpC, lpbiIn, lpIn, lDist, x, &lpOut, &lpbiOut->biSizeImage); assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); } } while (x < lpbiOut->biWidth); lpP += lLine; lpC += lLine; lpIn += lInLine; if (jumpy == 0) { /* add EOL -- end of line */ lpbiOut->biSizeImage += 2; *((LPWORD)lpOut)++ = 0; assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); } } /* add EOL -- will be changed to EOI */ lpbiOut->biSizeImage += 2; *((LPWORD)lpOut)++ = 0; } /* change EOL to EOI -- end of image */ lpOut[-1] = 1; assert(lpOut == (lpOutStart + lpbiOut->biSizeImage)); return ICERR_OK;}/*****************************************************************************/static LRESULT MSRLE32_DecompressRLE4(CodecInfo *pi, LPCBITMAPINFOHEADER lpbi, LPBYTE lpIn, LPBYTE lpOut){ int bytes_per_pixel; int line_size; int pixel_ptr = 0; int i; BOOL bEndFlag = FALSE; assert(pi != NULL); assert(lpbi != NULL && lpbi->biCompression == BI_RGB); assert(lpIn != NULL && lpOut != NULL); bytes_per_pixel = (lpbi->biBitCount + 1) / 8; line_size = DIBWIDTHBYTES(*lpbi); do { BYTE code0, code1; code0 = *lpIn++; code1 = *lpIn++; if (code0 == 0) { int extra_byte; switch (code1) { case 0: /* EOL - end of line */ pixel_ptr = 0; lpOut += line_size; break; case 1: /* EOI - end of image */ bEndFlag = TRUE; break; case 2: /* skip */ pixel_ptr += *lpIn++ * bytes_per_pixel; lpOut += *lpIn++ * line_size; if (pixel_ptr >= lpbi->biWidth * bytes_per_pixel) { pixel_ptr = 0; lpOut += line_size; } break; default: /* absolute mode */ extra_byte = (((code1 + 1) & (~1)) / 2) & 0x01; if (pixel_ptr/bytes_per_pixel + code1 > lpbi->biWidth) return ICERR_ERROR; code0 = code1; for (i = 0; i < code0 / 2; i++) { if (bytes_per_pixel == 1) { code1 = lpIn[i]; lpOut[pixel_ptr++] = pi->palette_map[(code1 >> 4)]; if (2 * i + 1 <= code0) lpOut[pixel_ptr++] = pi->palette_map[(code1 & 0x0F)]; } else if (bytes_per_pixel == 2) { code1 = lpIn[i] >> 4; lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 0]; lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 1]; if (2 * i + 1 <= code0) { code1 = lpIn[i] & 0x0F; lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 0]; lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 1]; } } else { code1 = lpIn[i] >> 4; lpOut[pixel_ptr + 0] = pi->palette_map[code1 * 4 + 0]; lpOut[pixel_ptr + 1] = pi->palette_map[code1 * 4 + 1]; lpOut[pixel_ptr + 2] = pi->palette_map[code1 * 4 + 2]; pixel_ptr += bytes_per_pixel; if (2 * i + 1 <= code0) { code1 = lpIn[i] & 0x0F; lpOut[pixel_ptr + 0] = pi->palette_map[code1 * 4 + 0]; lpOut[pixel_ptr + 1] = pi->palette_map[code1 * 4 + 1]; lpOut[pixel_ptr + 2] = pi->palette_map[code1 * 4 + 2]; pixel_ptr += bytes_per_pixel; } } } if (code0 & 0x01) { if (bytes_per_pixel == 1) { code1 = lpIn[i]; lpOut[pixel_ptr++] = pi->palette_map[(code1 >> 4)]; } else if (bytes_per_pixel == 2) { code1 = lpIn[i] >> 4; lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 0]; lpOut[pixel_ptr++] = pi->palette_map[code1 * 2 + 1]; } else { code1 = lpIn[i] >> 4; lpOut[pixel_ptr + 0] = pi->palette_map[code1 * 4 + 0]; lpOut[pixel_ptr + 1] = pi->palette_map[code1 * 4 + 1]; lpOut[pixel_ptr + 2] = pi->palette_map[code1 * 4 + 2]; pixel_ptr += bytes_per_pixel; } lpIn++; } lpIn += code0 / 2; /* if the RLE code is odd, skip a byte in the stream */ if (extra_byte) lpIn++; }; } else { /* coded mode */ if (pixel_ptr/bytes_per_pixel + code0 > lpbi->biWidth) return ICERR_ERROR; if (bytes_per_pixel == 1) { BYTE c1 = pi->palette_map[(code1 >> 4)]; BYTE c2 = pi->palette_map[(code1 & 0x0F)]; for (i = 0; i < code0; i++) { if ((i & 1) == 0) lpOut[pixel_ptr++] = c1; else lpOut[pixel_ptr++] = c2; } } else if (bytes_per_pixel == 2) { BYTE hi1 = pi->palette_map[(code1 >> 4) * 2 + 0]; BYTE lo1 = pi->palette_map[(code1 >> 4) * 2 + 1]; BYTE hi2 = pi->palette_map[(code1 & 0x0F) * 2 + 0]; BYTE lo2 = pi->palette_map[(code1 & 0x0F) * 2 + 1]; for (i = 0; i < code0; i++) { if ((i & 1) == 0) { lpOut[pixel_ptr++] = hi1; lpOut[pixel_ptr++] = lo1; } else { lpOut[pixel_ptr++] = hi2; lpOut[pixel_ptr++] = lo2; } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?