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 + -
显示快捷键?