msrle32.c

来自「Wine-20031016」· C语言 代码 · 共 1,915 行 · 第 1/4 页

C
1,915
字号
      } else {	BYTE b1 = pi->palette_map[(code1 >> 4) * 4 + 0];	BYTE g1 = pi->palette_map[(code1 >> 4) * 4 + 1];	BYTE r1 = pi->palette_map[(code1 >> 4) * 4 + 2];	BYTE b2 = pi->palette_map[(code1 & 0x0F) * 4 + 0];	BYTE g2 = pi->palette_map[(code1 & 0x0F) * 4 + 1];	BYTE r2 = pi->palette_map[(code1 & 0x0F) * 4 + 2];	for (i = 0; i < code0; i++) {	  if ((i & 1) == 0) {	    lpOut[pixel_ptr + 0] = b1;	    lpOut[pixel_ptr + 1] = g1;	    lpOut[pixel_ptr + 2] = r1;	  } else {	    lpOut[pixel_ptr + 0] = b2;	    lpOut[pixel_ptr + 1] = g2;	    lpOut[pixel_ptr + 2] = r2;	  }	  pixel_ptr += bytes_per_pixel;	}      }    }  } while (! bEndFlag);  return ICERR_OK;}static LRESULT MSRLE32_DecompressRLE8(CodecInfo *pi, LPCBITMAPINFOHEADER lpbi,				      LPBYTE lpIn, LPBYTE lpOut){  int  bytes_per_pixel;  int  line_size;  int  pixel_ptr  = 0;  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 */	if (pixel_ptr/bytes_per_pixel + code1 > lpbi->biWidth) {	  WARN("aborted absolute: (%d=%d/%d+%d) > %ld\n",pixel_ptr/bytes_per_pixel + code1,pixel_ptr,bytes_per_pixel,code1,lpbi->biWidth);	  return ICERR_ERROR;	}	extra_byte = code1 & 0x01;	code0 = code1;	while (code0--) {	  code1 = *lpIn++;	  if (bytes_per_pixel == 1) {	    lpOut[pixel_ptr] = pi->palette_map[code1];	  } else if (bytes_per_pixel == 2) {	    lpOut[pixel_ptr + 0] = pi->palette_map[code1 * 2 + 0];	    lpOut[pixel_ptr + 1] = pi->palette_map[code1 * 2 + 1];	  } else {	    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 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) {	WARN("aborted coded: (%d=%d/%d+%d) > %ld\n",pixel_ptr/bytes_per_pixel + code1,pixel_ptr,bytes_per_pixel,code1,lpbi->biWidth);	return ICERR_ERROR;      }      if (bytes_per_pixel == 1) {	code1 = pi->palette_map[code1];	while (code0--)	  lpOut[pixel_ptr++] = code1;      } else if (bytes_per_pixel == 2) {	BYTE hi = pi->palette_map[code1 * 2 + 0];	BYTE lo = pi->palette_map[code1 * 2 + 1];	while (code0--) {	  lpOut[pixel_ptr + 0] = hi;	  lpOut[pixel_ptr + 1] = lo;	  pixel_ptr += bytes_per_pixel;	}      } else {	BYTE r = pi->palette_map[code1 * 4 + 2];	BYTE g = pi->palette_map[code1 * 4 + 1];	BYTE b = pi->palette_map[code1 * 4 + 0];	while (code0--) {	  lpOut[pixel_ptr + 0] = b;	  lpOut[pixel_ptr + 1] = g;	  lpOut[pixel_ptr + 2] = r;	  pixel_ptr += bytes_per_pixel;	}      }    }  } while (! bEndFlag);  return ICERR_OK;}/*****************************************************************************/static CodecInfo* Open(LPICOPEN icinfo){  CodecInfo* pi = NULL;  if (icinfo == NULL) {    TRACE("(NULL)\n");    return (LPVOID)0xFFFF0000;  }  TRACE("(%p = {%lu,0x%08lX(%4.4s),0x%08lX(%4.4s),0x%lX,0x%lX,...})\n", icinfo,	icinfo->dwSize,	icinfo->fccType, (char*)&icinfo->fccType,	icinfo->fccHandler, (char*)&icinfo->fccHandler,	icinfo->dwVersion,icinfo->dwFlags);  if (icinfo->fccType != ICTYPE_VIDEO)    return NULL;  switch (icinfo->fccHandler) {  case FOURCC_RLE:  case FOURCC_RLE4:  case FOURCC_RLE8:  case FOURCC_MRLE:    break;  case mmioFOURCC('m','r','l','e'):    icinfo->fccHandler = FOURCC_MRLE;    break;  default:    WARN("unknown FOURCC = 0x%08lX(%4.4s) !\n",	 icinfo->fccHandler,(char*)&icinfo->fccHandler);    return NULL;  }  pi = (CodecInfo*)LocalAlloc(LPTR, sizeof(CodecInfo));  if (pi != NULL) {    pi->fccHandler  = icinfo->fccHandler;    pi->bCompress   = FALSE;    pi->dwQuality   = MSRLE32_DEFAULTQUALITY;    pi->nPrevFrame  = -1;    pi->pPrevFrame  = pi->pCurFrame = NULL;    pi->bDecompress = FALSE;    pi->palette_map = NULL;  }  icinfo->dwError = (pi != NULL ? ICERR_OK : ICERR_MEMORY);  return pi;}static LRESULT Close(CodecInfo *pi){  TRACE("(%p)\n", pi);  /* pre-condition */  assert(pi != NULL);  if (pi->pPrevFrame != NULL || pi->pCurFrame != NULL)    CompressEnd(pi);  LocalFree((HLOCAL)pi);  return 1;}static LRESULT GetInfo(CodecInfo *pi, ICINFO *icinfo, DWORD dwSize){  /* pre-condition */  assert(pi != NULL);  /* check parameters */  if (icinfo == NULL)    return sizeof(ICINFO);  if (dwSize < sizeof(ICINFO))    return 0;  icinfo->dwSize       = sizeof(ICINFO);  icinfo->fccType      = streamtypeVIDEO;  icinfo->fccHandler   = (pi != NULL ? pi->fccHandler : FOURCC_MRLE);  icinfo->dwFlags      = VIDCF_QUALITY | VIDCF_TEMPORAL | VIDCF_CRUNCH | VIDCF_FASTTEMPORALC;  icinfo->dwVersion    = MSRLE32_VERSION;  icinfo->dwVersionICM = 0x01040000; /* Version 1.4 build 0 */  LoadWideString(IDS_NAME, icinfo->szName, sizeof(icinfo->szName));  LoadWideString(IDS_DESCRIPTION, icinfo->szDescription, sizeof(icinfo->szDescription));  return sizeof(ICINFO);}static LRESULT SetQuality(CodecInfo *pi, LONG lQuality){  /* pre-condition */  assert(pi != NULL);  if (lQuality == -1)    lQuality = MSRLE32_DEFAULTQUALITY;  else if (ICQUALITY_LOW > lQuality || lQuality > ICQUALITY_HIGH)    return ICERR_BADPARAM;  pi->dwQuality = (DWORD)lQuality;  return ICERR_OK;}static LRESULT Configure(CodecInfo *pi, HWND hWnd){  /* pre-condition */  assert(pi != NULL);  /* FIXME */  return ICERR_OK;}static LRESULT About(CodecInfo *pi, HWND hWnd){  CHAR szTitle[20];  CHAR szAbout[128];  /* pre-condition */  assert(MSRLE32_hModule != 0);  LoadStringA(MSRLE32_hModule, IDS_NAME, szTitle, sizeof(szTitle));  LoadStringA(MSRLE32_hModule, IDS_ABOUT, szAbout, sizeof(szAbout));  MessageBoxA(hWnd, szAbout, szTitle, MB_OK|MB_ICONINFORMATION);  return ICERR_OK;}static LRESULT CompressGetFormat(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn,				 LPBITMAPINFOHEADER lpbiOut){  LRESULT size;  TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut);  /* pre-condition */  assert(pi != NULL);  /* check parameters -- need atleast input format */  if (lpbiIn == NULL) {    if (lpbiOut != NULL)      return ICERR_BADPARAM;    return 0;  }  /* handle unsupported input format */  if (CompressQuery(pi, lpbiIn, NULL) != ICERR_OK)    return (lpbiOut == NULL ? ICERR_BADFORMAT : 0);  assert(0 < lpbiIn->biBitCount && lpbiIn->biBitCount <= 8);  switch (pi->fccHandler) {  case FOURCC_RLE4:    size = 1 << 4;    break;  case FOURCC_RLE8:    size = 1 << 8;    break;  case FOURCC_RLE:  case FOURCC_MRLE:    size = (lpbiIn->biBitCount <= 4 ? 1 << 4 : 1 << 8);    break;  default:    return ICERR_ERROR;  }  if (lpbiIn->biClrUsed != 0)    size = lpbiIn->biClrUsed;  size = sizeof(BITMAPINFOHEADER) + size * sizeof(RGBQUAD);  if (lpbiOut != NULL) {    lpbiOut->biSize          = sizeof(BITMAPINFOHEADER);    lpbiOut->biWidth         = lpbiIn->biWidth;    lpbiOut->biHeight        = lpbiIn->biHeight;    lpbiOut->biPlanes        = 1;    if (pi->fccHandler == FOURCC_RLE4 ||	lpbiIn->biBitCount <= 4) {      lpbiOut->biCompression = BI_RLE4;      lpbiOut->biBitCount    = 4;    } else {      lpbiOut->biCompression = BI_RLE8;      lpbiOut->biBitCount    = 8;    }    lpbiOut->biSizeImage     = MSRLE32_GetMaxCompressedSize(lpbiOut);    lpbiOut->biXPelsPerMeter = lpbiIn->biXPelsPerMeter;    lpbiOut->biYPelsPerMeter = lpbiIn->biYPelsPerMeter;    if (lpbiIn->biClrUsed == 0)      size = 1<<lpbiIn->biBitCount;    else      size = lpbiIn->biClrUsed;    lpbiOut->biClrUsed       = min(size, 1 << lpbiOut->biBitCount);    lpbiOut->biClrImportant  = 0;    memcpy((LPBYTE)lpbiOut + lpbiOut->biSize,	   (const BYTE*)lpbiIn + lpbiIn->biSize, lpbiOut->biClrUsed * sizeof(RGBQUAD));    return ICERR_OK;  } else    return size;}static LRESULT CompressGetSize(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn,			       LPCBITMAPINFOHEADER lpbiOut){  /* pre-condition */  assert(pi != NULL);  TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut);  /* check parameter -- need atleast one format */  if (lpbiIn == NULL && lpbiOut == NULL)    return 0;  /* check if the given format is supported */  if (CompressQuery(pi, lpbiIn, lpbiOut) != ICERR_OK)    return 0;  /* the worst case is coding the complete image in absolute mode. */  if (lpbiIn)    return MSRLE32_GetMaxCompressedSize(lpbiIn);  else    return MSRLE32_GetMaxCompressedSize(lpbiOut);}static LRESULT CompressQuery(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn,			     LPCBITMAPINFOHEADER lpbiOut){  /* pre-condition */  assert(pi != NULL);  /* need atleast one format */  if (lpbiIn == NULL && lpbiOut == NULL)    return ICERR_BADPARAM;  /* check input format if given */  if (lpbiIn != NULL) {    if (!isSupportedDIB(lpbiIn))      return ICERR_BADFORMAT;    /* for 4-bit need an even width */    if (lpbiIn->biBitCount <= 4 && (lpbiIn->biWidth % 2))      return ICERR_BADFORMAT;    if (pi->fccHandler == FOURCC_RLE4 && lpbiIn->biBitCount > 4)      return ICERR_UNSUPPORTED;    else if (lpbiIn->biBitCount > 8)      return ICERR_UNSUPPORTED;  }  /* check output format if given */  if (lpbiOut != NULL) {    if (!isSupportedMRLE(lpbiOut))      return ICERR_BADFORMAT;    if (lpbiIn != NULL) {      if (lpbiIn->biWidth  != lpbiOut->biWidth)	return ICERR_UNSUPPORTED;      if (lpbiIn->biHeight != lpbiOut->biHeight)	return ICERR_UNSUPPORTED;      if (lpbiIn->biBitCount > lpbiOut->biBitCount)	return ICERR_UNSUPPORTED;    }  }  return ICERR_OK;}static LRESULT CompressBegin(CodecInfo *pi, LPCBITMAPINFOHEADER lpbiIn,			     LPCBITMAPINFOHEADER lpbiOut){  const RGBQUAD *rgbIn;  const RGBQUAD *rgbOut;  UINT   i;  size_t size;  TRACE("(%p,%p,%p)\n",pi,lpbiIn,lpbiOut);  /* pre-condition */  assert(pi != NULL);  /* check parameters -- need both formats */  if (lpbiIn == NULL || lpbiOut == NULL)    return ICERR_BADPARAM;  /* And both must be supported */  if (CompressQuery(pi, lpbiIn, lpbiOut) != ICERR_OK)    return ICERR_BADFORMAT;  /* FIXME: cannot compress and decompress at same time! */  if (pi->bDecompress) {    FIXME("cannot compress and decompress at same time!\n");    return ICERR_ERROR;  }  if (pi->bCompress)    CompressEnd(pi);  size = WIDTHBYTES(lpbiOut->biWidth * 16) / 2 * lpbiOut->biHeight;  pi->pPrevFrame = (LPWORD)GlobalAllocPtr(GPTR, size * sizeof(WORD));  if (pi->pPrevFrame == NULL)    return ICERR_MEMORY;  pi->pCurFrame = (LPWORD)GlobalAllocPtr(GPTR, size * sizeof(WORD));  if (pi->pCurFrame == NULL) {    CompressEnd(pi);    return ICERR_MEMORY;  }  pi->nPrevFrame = -1;  pi->bCompress  = TRUE;  rgbIn  = (const RGBQUAD*)((const BYTE*)lpbiIn  + lpbiIn->biSize);  rgbOut = (const RGBQUAD*)((const BYTE*)lpbiOut + lpbiOut->biSize);  switch (lpbiOut->biBitCount) {  case 4:  case 8:    pi->palette_map = (LPBYTE)LocalAlloc(LPTR, lpbiIn->biClrUsed);    if (pi->palette_map == NULL) {      CompressEnd(pi);      return ICERR_MEMORY;    }    for (i = 0; i < lpbiIn->biClrUsed; i++) {      pi->palette_map[i] = MSRLE32_GetNearestPaletteIndex(lpbiOut->biClrUsed, rgbOut, rgbIn[i]);    }    break;  };  return ICERR_OK;}static LRESULT Compress(CodecInfo *pi, ICCOMPRESS* lpic, DWORD dwSize){  int i;  TRACE("(%p,%p,%lu)\n",pi,lpic,dwSize);  /* pre-condition */  assert(pi != NULL);  /* check parameters */  if (lpic == NULL || dwSize < sizeof(ICCOMPRESS))    return ICERR_BADPARAM;  if (!lpic->lpbiOutput || !lpic->lpOutput ||      !lpic->lpbiInput  || !lpic->lpInput)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?