示例#1
0
bool CxImagePCX::Decode(CxFile *hFile)
{
	if (hFile == NULL) return false;

	PCXHEADER pcxHeader;
	int i, x, y, y2, nbytes, count, Height, Width;
	BYTE c, ColorMap[PCX_MAXCOLORS][3];
	BYTE *pcximage = NULL, *lpHead1 = NULL, *lpHead2 = NULL;
	BYTE *pcxplanes, *pcxpixels;

  try
  {
	if (hFile->Read(&pcxHeader,sizeof(PCXHEADER),1)==0) throw "Can't read PCX image";

    if (pcxHeader.Manufacturer != PCX_MAGIC) throw "Error: Not a PCX file";
    // Check for PCX run length encoding
    if (pcxHeader.Encoding != 1) throw "PCX file has unknown encoding scheme";
 
    Width = (pcxHeader.Xmax - pcxHeader.Xmin) + 1;
    Height = (pcxHeader.Ymax - pcxHeader.Ymin) + 1;
	info.xDPI = pcxHeader.Hres;
	info.yDPI = pcxHeader.Vres;

    // Check that we can handle this image format
    if (pcxHeader.ColorPlanes > 4)
		throw "Can't handle image with more than 4 planes";

	// Create the image
	if (pcxHeader.ColorPlanes >= 3 && pcxHeader.BitsPerPixel == 8){
		Create (Width, Height, 24, CXIMAGE_FORMAT_PCX);
#if CXIMAGE_SUPPORT_ALPHA
		if (pcxHeader.ColorPlanes==4) AlphaCreate();
#endif //CXIMAGE_SUPPORT_ALPHA
	} else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 1)
		Create (Width, Height, 4, CXIMAGE_FORMAT_PCX);
	else
		Create (Width, Height, pcxHeader.BitsPerPixel, CXIMAGE_FORMAT_PCX);

	if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding

	//Read the image and check if it's ok
    nbytes = pcxHeader.BytesPerLine * pcxHeader.ColorPlanes * Height;
    lpHead1 = pcximage = (BYTE*)malloc(nbytes);
    while (nbytes > 0){
		if (hFile == NULL || hFile->Eof()) throw "corrupted PCX";

		hFile->Read(&c,1,1);
		if ((c & 0XC0) != 0XC0){ // Repeated group
			*pcximage++ = c;
			--nbytes;
			continue;
		}
		count = c & 0X3F; // extract count
		hFile->Read(&c,1,1);
		if (count > nbytes) throw "repeat count spans end of image";

		nbytes -= count;
		while (--count >=0) *pcximage++ = c;
	}
    pcximage = lpHead1;

	//store the palette
    for (i = 0; i < 16; i++){
		ColorMap[i][0] = pcxHeader.ColorMap[i][0];
		ColorMap[i][1] = pcxHeader.ColorMap[i][1];
		ColorMap[i][2] = pcxHeader.ColorMap[i][2];
	}
    if (pcxHeader.BitsPerPixel == 8 && pcxHeader.ColorPlanes == 1){
		hFile->Read(&c,1,1);
		if (c != PCX_256_COLORS) throw "bad color map signature";
		
		for (i = 0; i < PCX_MAXCOLORS; i++){
			hFile->Read(&ColorMap[i][0],1,1);
			hFile->Read(&ColorMap[i][1],1,1);
			hFile->Read(&ColorMap[i][2],1,1);
		}
	}
    if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){
		ColorMap[0][0] = ColorMap[0][1] = ColorMap[0][2] = 0;
		ColorMap[1][0] = ColorMap[1][1] = ColorMap[1][2] = 255;
	}

	for (DWORD idx=0; idx<head.biClrUsed; idx++) SetPaletteColor((BYTE)idx,ColorMap[idx][0],ColorMap[idx][1],ColorMap[idx][2]);

    lpHead2 = pcxpixels = (BYTE *)malloc(Width + pcxHeader.BytesPerLine * 8);
    // Convert the image
    for (y = 0; y < Height; y++){

		if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding

		y2=Height-1-y;
		pcxpixels = lpHead2;
		pcxplanes = pcximage + (y * pcxHeader.BytesPerLine * pcxHeader.ColorPlanes);

		if (pcxHeader.ColorPlanes == 3 && pcxHeader.BitsPerPixel == 8){
			// Deal with 24 bit color image
			for (x = 0; x < Width; x++){
				SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x]));
			}
			continue;
#if CXIMAGE_SUPPORT_ALPHA
		} else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 8){
			for (x = 0; x < Width; x++){
				SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x]));
				AlphaSet(x,y2,pcxplanes[3*pcxHeader.BytesPerLine + x]);
			}
			continue;
#endif //CXIMAGE_SUPPORT_ALPHA
		} else if (pcxHeader.ColorPlanes == 1) {
			PCX_UnpackPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel);
		} else {
			PCX_PlanesToPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel);
		}
		for (x = 0; x < Width; x++)	SetPixelIndex(x,y2,pcxpixels[x]);
	}

  } catch (char *message) {
	strncpy(info.szLastError,message,255);
	if (lpHead1){ free(lpHead1); lpHead1 = NULL; }
    if (lpHead2){ free(lpHead2); lpHead2 = NULL; }
	return false;
  }
	if (lpHead1){ free(lpHead1); lpHead1 = NULL; }
    if (lpHead2){ free(lpHead2); lpHead2 = NULL; }
	return true;
}
示例#2
0
文件: plpcxdec.cpp 项目: artcom/y60
void PLPCXDecoder::GetImage (PLBmpBase & Bmp)
{
  int i, x, y;
  PLBYTE ColorMap[PCX_MAXCOLORS][3];
  PLBYTE * pcximage = NULL;
  PLBYTE * lpHead1 = NULL;
  PLBYTE * lpHead2 = NULL;
  PLBYTE * pcxplanes;
  PLBYTE * pcxpixels;
  PLBYTE c;
  int nbytes, count;

  Trace (2, "PCX getimage.\n");

  try
  {
    nbytes = m_PcxHeader.BytesPerLine * m_PcxHeader.ColorPlanes * GetHeight();
    lpHead1 = pcximage = (PLBYTE *)malloc(nbytes);
    try
    {
      while (nbytes > 0)
      {
        c = ReadByte(m_pDataSrc);
        if ((c & 0XC0) != 0XC0) // Repeated group
        {
          *pcximage++ = c;
          --nbytes;
          continue;
        }
        count = c & 0X3F; // extract count
        c = ReadByte(m_pDataSrc);
        if (count > nbytes)
        {
          raiseError(PL_ERRINTERNAL, "repeat count spans end of image.");
        }
        nbytes -= count;
        while (--count >=0)
          *pcximage++ = c;
      }
    }
    catch (PLTextException e)
    {
      // Just in case BytesPerLine is bogus.
      // This will fall apart for images that have a palette after the
      // image data, however.
      if (e.GetCode() != PL_ERREND_OF_FILE)
        throw;
    }
    pcximage = lpHead1;

    for (i = 0; i < 16; i++)
    {
      ColorMap[i][0] = m_PcxHeader.ColorMap[i][0];
      ColorMap[i][1] = m_PcxHeader.ColorMap[i][1];
      ColorMap[i][2] = m_PcxHeader.ColorMap[i][2];
    }
    if (m_PcxHeader.BitsPerPixel == 8 && m_PcxHeader.ColorPlanes == 1)
    {
/* It seems like valid PCXs exist with a bad color map signature...
      PLBYTE colsig = ReadByte(m_pDataSrc);
      if (colsig != PCX_256_COLORS)
      {
        raiseError(PL_ERRINTERNAL, "bad color map signature.");
      }
*/
      for (i = 0; i < PCX_MAXCOLORS; i++)
      {
        ColorMap[i][0] = ReadByte(m_pDataSrc);
        ColorMap[i][1] = ReadByte(m_pDataSrc);
        ColorMap[i][2] = ReadByte(m_pDataSrc);
      }
    }
    if (m_PcxHeader.BitsPerPixel == 1 && m_PcxHeader.ColorPlanes == 1)
    {
      ColorMap[0][0] = ColorMap[0][1] = ColorMap[0][2] = 0;
      ColorMap[1][0] = ColorMap[1][1] = ColorMap[1][2] = 255;
    }

    lpHead2 = pcxpixels = (PLBYTE *)malloc(GetWidth() + m_PcxHeader.BytesPerLine * 8);
    // Convert the image
    PLPixel32 ** pLineArray = Bmp.GetLineArray32();
    for (y = 0; y < GetHeight(); y++)
    {
      pcxpixels = lpHead2;
      pcxplanes = pcximage + (y * m_PcxHeader.BytesPerLine * m_PcxHeader.ColorPlanes);
      if (m_PcxHeader.ColorPlanes == 3 && m_PcxHeader.BitsPerPixel == 8)
      {
        // Deal with 24 bit color image
        for (x = 0; x < GetWidth(); x++)
        {
          PLPixel32 * pPixel = pLineArray[y];
          pPixel[x].Set (pcxplanes[x],
                         pcxplanes[m_PcxHeader.BytesPerLine + x],
                         pcxplanes[2*m_PcxHeader.BytesPerLine + x],
                         0xFF);
        }
        continue;
      }
      else if (m_PcxHeader.ColorPlanes == 1)
      {
        PCX_UnpackPixels(pcxpixels, pcxplanes, m_PcxHeader.BytesPerLine, m_PcxHeader.ColorPlanes, m_PcxHeader.BitsPerPixel);
      }
      else
      {
        PCX_PlanesToPixels(pcxpixels, pcxplanes, m_PcxHeader.BytesPerLine, m_PcxHeader.ColorPlanes, m_PcxHeader.BitsPerPixel);
      }
      for (x = 0; x < GetWidth(); x++)
      {
        i = pcxpixels[x];
        PLPixel32 * pPixel = pLineArray[y];
        pPixel[x].Set (ColorMap[i][0], ColorMap[i][1],
                       ColorMap[i][2], 0xFF);
      }
    }
  }

  catch (PLTextException)
  {
    if (lpHead1)
    {
      free(lpHead1);
      lpHead1 = NULL;
    }
    if (lpHead2)
    {
      free(lpHead2);
      lpHead2 = NULL;
    }
    throw;
  }

  if (lpHead1)
  {
    free(lpHead1);
    lpHead1 = NULL;
  }
  if (lpHead2)
  {
    free(lpHead2);
    lpHead2 = NULL;
  }
}