コード例 #1
0
ファイル: plsgidec.cpp プロジェクト: artcom/y60
void PLSGIDecoder::Open (PLDataSource * pDataSrc)
{
  Trace (2, "Decoding SGI.\n");
  PLPixelFormat pf;
  readHeader (&m_Header, pDataSrc);

  bool bGreyscale = (m_Header.ZSize == 1 && static_cast<int>(m_Header.Colormap) == CMAP_NORMAL);

  switch (m_Header.ZSize)
  {
    case 1:
      if (bGreyscale) {
        pf = PLPixelFormat::L8;
      } else {
        pf = PLPixelFormat::I8;
      }
      break;
    case 2:
      throw PLTextException (PL_ERRFORMAT_NOT_SUPPORTED, "Two-channel SGI RGB files are not supported.");
      break;
    case 3:
      pf = PLPixelFormat::X8R8G8B8;
      break;
    case 4:
      // Image has alpha channel
      pf = PLPixelFormat::A8R8G8B8;      
  }
  if (m_Header.Dimension == 1)
  {
    throw PLTextException (PL_ERRFORMAT_NOT_SUPPORTED, "One-dimensional SGI RGB files are not supported.");
  }
  
  
  SetBmpInfo (PLPoint (m_Header.XSize, m_Header.YSize), PLPoint(0, 0), pf);
}
コード例 #2
0
ファイル: plbmpdec.cpp プロジェクト: artcom/y60
void PLBmpDecoder::Open (PLDataSource * pDataSrc)
{
  m_pBMI = getInfoHeader (pDataSrc, &m_Pal[0]);
  
  PLPixelFormat pf;
  if (m_pBMI->biBitCount <= 8) {
    pf = PLPixelFormat::L8;
  } else {
    if (m_pBMI->biBitCount == 32) {
      pf = PLPixelFormat::A8R8G8B8;
    } else {
      pf = PLPixelFormat::X8R8G8B8;
    }
  }

  PLPoint DPI(0,0);
  if (m_pBMI->biXPelsPerMeter > 0)
    DPI.x = (int)((float)m_pBMI->biXPelsPerMeter / 39.37f+0.5);
  if (DPI.x <= 1)
    DPI.x = 0;
  if (m_pBMI->biYPelsPerMeter > 0)
    DPI.y = (int)((float)m_pBMI->biYPelsPerMeter / 39.37f+0.5);
  if (DPI.y <= 1)
    DPI.y = 0;

  SetBmpInfo (PLPoint (m_pBMI->biWidth, m_pBMI->biHeight), 
        DPI, pf);
}
コード例 #3
0
ファイル: DEMODIB.CPP プロジェクト: vinnie38170/klImageCore
void CDemoDib::CreateDibSection(CDC* pDC, CImage* pImage)
{
     SetBmpInfo(pImage);
     m_hBmp = ::CreateDIBSection(
          pDC->GetSafeHdc(), GetBmpInfo(),
          DIB_RGB_COLORS, (void**)(&m_pBits), NULL, 0);
}
コード例 #4
0
ファイル: plpgmdec.cpp プロジェクト: artcom/y60
void PLPGMDecoder::Open (PLDataSource * pDataSrc)
{
  Trace (2, "Decoding PGM.\n");

  readPgmHeader(&m_PGMHeader, pDataSrc);
  SetBmpInfo (PLPoint(m_PGMHeader.ImageWidth, m_PGMHeader.ImageHeight), 
      PLPoint (0,0), PLPixelFormat::L8);
}
コード例 #5
0
ファイル: plpcxdec.cpp プロジェクト: artcom/y60
void PLPCXDecoder::Open(PLDataSource * pDataSrc)
{

  // Check if the file is a valid PCX file or not
  Trace (2, "Decoding PCX.\n");

  m_PcxHeader.Manufacturer = ReadByte (pDataSrc);
  m_PcxHeader.Version = ReadByte  (pDataSrc);
  m_PcxHeader.Encoding = ReadByte (pDataSrc);
  m_PcxHeader.BitsPerPixel = ReadByte (pDataSrc);
  m_PcxHeader.Xmin = ReadIWord (pDataSrc);
  m_PcxHeader.Ymin = ReadIWord (pDataSrc);
  m_PcxHeader.Xmax = ReadIWord (pDataSrc);
  m_PcxHeader.Ymax = ReadIWord (pDataSrc);
  m_PcxHeader.Hres = ReadIWord (pDataSrc);
  m_PcxHeader.Vres = ReadIWord (pDataSrc);
  memcpy (m_PcxHeader.ColorMap, pDataSrc->ReadNBytes (16*3),16*3);
  m_PcxHeader.Reserved = ReadByte (pDataSrc);
  m_PcxHeader.ColorPlanes = ReadByte (pDataSrc);
  m_PcxHeader.BytesPerLine = ReadIWord (pDataSrc);
  m_PcxHeader.PaletteType = ReadIWord (pDataSrc);
  memcpy (m_PcxHeader.Filter, pDataSrc->ReadNBytes (58), 58);
  
  if (m_PcxHeader.Manufacturer != PCX_MAGIC)
  {
    raiseError (PL_ERRWRONG_SIGNATURE, "Error decoding pcx: Not a PCX file.");
  }
  // Check for PCX run length encoding
  if (m_PcxHeader.Encoding != 1)
  {
    raiseError (PL_ERRWRONG_SIGNATURE, "File has unknown encoding scheme.");
  }

  // Check that we can handle this image format
  switch (m_PcxHeader.BitsPerPixel)
  {
    case 1:
      if (m_PcxHeader.ColorPlanes > 4)
      {
        raiseError(PL_ERRFORMAT_UNKNOWN, "Can't handle image with more than 4 planes.");
      }
      break;
    case 2:
    case 4:
    case 8:
      if (m_PcxHeader.ColorPlanes == 1 || m_PcxHeader.ColorPlanes == 3)
        break;
    default:
      raiseError(PL_ERRFORMAT_UNKNOWN, "Can't handle bits per pixel image with planes.");
      break;
  }

  int Width = (m_PcxHeader.Xmax - m_PcxHeader.Xmin) + 1;
  int Height = (m_PcxHeader.Ymax - m_PcxHeader.Ymin) + 1;
  SetBmpInfo (PLPoint(Width, Height), 
      PLPoint (m_PcxHeader.Hres, m_PcxHeader.Vres), PLPixelFormat::X8R8G8B8);
}
コード例 #6
0
ファイル: ImageLoader.cpp プロジェクト: artcom/y60
    void
    ImageLoader::removeUnusedAlpha() {
        if (!_isI60 && GetBitsPerPixel() == 32 && !HasAlpha()) {
            // Compress unused fourth channel
            AC_DEBUG << "ImageLoader removing unused fourth channel";

            unsigned myHeight = GetHeight();
            unsigned myWidth  = GetWidth();
            //unsigned myLineStride = GetBytesPerLine();

            asl::Ptr<Block> myDestinationBlock = asl::Ptr<Block>(new Block());
            myDestinationBlock->resize(myHeight * myWidth * 3);

            unsigned char ** myLineArray   = GetLineArray();
            unsigned char *  myDestination = myDestinationBlock->begin();

            for (unsigned i = 0; i < myHeight; ++i) {
                unsigned char * mySource = *myLineArray;
                for (unsigned j = 0; j < myWidth; ++j) {
                    myDestination[0]  = mySource[0];
                    myDestination[1]  = mySource[1];
                    myDestination[2]  = mySource[2];

                    mySource      += 4;
                    myDestination += 3;
                }
                myLineArray++;
            }

            // Update internal representation
            switch (_myEncoding) {
                case RGBA :
                    _myEncoding = RGB;
                    break;
                case BGRA :
                    _myEncoding = BGR;
                    break;
                default:
                    throw ImageLoaderException("Unsupported pixel encoding", PLUS_FILE_LINE);
            }
            _myData = myDestinationBlock;
            PLPixelFormat myPixelFormat;
            mapPixelEncodingToFormat(_myEncoding, myPixelFormat);
            SetBmpInfo(GetSize(), GetResolution(), myPixelFormat);
            updateLineArray();
        }
    }
コード例 #7
0
ファイル: pltiffdec.cpp プロジェクト: artcom/y60
void PLTIFFDecoder::Open (PLDataSource * pDataSrc)
{
  PLASSERT (m_pTif == 0);
  m_pTif = TIFFOpenMem (pDataSrc->ReadEverything(), pDataSrc->GetFileSize(), 
                        NULL);
  if (!m_pTif)
    raiseError (PL_ERRWRONG_SIGNATURE, m_szLastErr);

  uint16  BitsPerSample;
  uint16  SamplesPerPixel;
  uint32  ImageHeight;
  uint32  ImageWidth;

  // get tagged image parameters
  TIFFGetFieldDefaulted(m_pTif, TIFFTAG_IMAGEWIDTH, &ImageWidth);
  TIFFGetFieldDefaulted(m_pTif, TIFFTAG_IMAGELENGTH, &ImageHeight);
  TIFFGetFieldDefaulted(m_pTif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample);
  TIFFGetFieldDefaulted(m_pTif, TIFFTAG_SAMPLESPERPIXEL, &SamplesPerPixel);

  int16  PhotometricInterpretation;
  TIFFGetFieldDefaulted(m_pTif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation);
  PLPixelFormat pf = PLPixelFormat::X8R8G8B8;
  if (!TIFFIsTiled(m_pTif))
  { 
    if (SamplesPerPixel == 1 && BitsPerSample ==1)
      pf = PLPixelFormat::L1;
    else if (SamplesPerPixel < 3 && BitsPerSample <= 8)
      if (PhotometricInterpretation == PHOTOMETRIC_MINISWHITE ||
          PhotometricInterpretation == PHOTOMETRIC_MINISBLACK)
        pf = PLPixelFormat::L8;
      else
        pf = PLPixelFormat::I8;
    else if (SamplesPerPixel < 3 && BitsPerSample <= 16)
        pf = PLPixelFormat::L16;
  }
  if (SamplesPerPixel == 4 && 
      (PhotometricInterpretation == PHOTOMETRIC_MINISWHITE ||
       PhotometricInterpretation == PHOTOMETRIC_MINISBLACK || 
       PhotometricInterpretation == PHOTOMETRIC_RGB || 
       PhotometricInterpretation == PHOTOMETRIC_PALETTE))
    pf = PLPixelFormat::A8R8G8B8;
  
  SetBmpInfo (PLPoint (ImageWidth, ImageHeight), getResolution (m_pTif), pf);

}
コード例 #8
0
ファイル: ImageLoader.cpp プロジェクト: artcom/y60
    void
    ImageLoader::loadI60File(asl::Ptr<ReadableBlockHandle> theImageBlock) {
        _myImageMatrix.makeIdentity();
        I60Header myHeader;
        theImageBlock->getBlock().readData(myHeader, 0);

        if (!myHeader.checkMagicNumber()) {
            throw ImageLoaderException(string("Image ") + _myFilename +
                " has a wrong magic number. '" + I60_MAGIC_NUMBER + "' expeced.", PLUS_FILE_LINE);
        }
        if (!myHeader.checkVersion()) {
            throw ImageLoaderException(string("Image ") + _myFilename + " file format version: " +
                as_string(myHeader.version) + " does not match current reader version: " +
                as_string(CURRENT_IMAGE_FORMAT_VERSION), PLUS_FILE_LINE);
        }

        _myHeaderSize = myHeader.headersize;
        _myEncoding   = PixelEncoding(myHeader.encoding);
        _isI60        = true;

        unsigned myWidthPowerOfTwo  = asl::nextPowerOfTwo(myHeader.width);
        unsigned myHeightPowerOfTwo = asl::nextPowerOfTwo(myHeader.height);

        _myImageMatrix.scale(Vector3f(float(myHeader.width) / myWidthPowerOfTwo,
                                        float(myHeader.height) / myHeightPowerOfTwo,
                                        1.0f));
        // maybe we should cut off the i60 header here?
        unsigned myBlockSize = theImageBlock->getBlock().size();
        _myData = asl::Ptr<Block>(new Block());
        _myData->resize(myBlockSize - sizeof(I60Header));
        std::copy(theImageBlock->getBlock().begin()+sizeof(I60Header),
                  theImageBlock->getBlock().end(), _myData->begin());

        // TODO: Add support for other compression formats
        SetBmpInfo(PLPoint(myWidthPowerOfTwo, myHeightPowerOfTwo * myHeader.layercount),
            GetResolution(), PLPixelFormat::L1 /* only correct for DXT5 */);
    }
コード例 #9
0
void PLWEMFDecoder::Open (PLDataSource * pDataSrc)
{
	PLASSERT_VALID(this);
  PLASSERT(m_bm == 0);
  PLASSERT(m_memdc == 0);
  PLASSERT(m_hemf == 0);

	SAPMFILEHEADER* pplaceablehdr = NULL;
	bool isadobe = false;
      bool isemf;

	// Get the type of the file (WMF or EMF) from the file name
      if (pDataSrc->NameIsWide()){
        wchar_t* strname = _wcsdup(pDataSrc->GetNameW());
        PLASSERT(strname);
        if (strname == NULL) {
                // This should never happen under 32-Bit, but who knows?
                PLASSERT(false);
                raiseError (PL_ERRNO_MEMORY,"Out of memory during strdup.");
        }
        _wcsupr(strname);
        isemf = wcsstr(strname,L".EMF") != NULL;
        free(strname);
      }
      else{
	char* strname = _strdup(pDataSrc->GetName());
	PLASSERT(strname);
	if (strname == NULL) {
		// This should never happen under 32-Bit, but who knows?
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Out of memory during strdup.");
	}
	_strupr(strname);
	bool isemf = strstr(strname,".EMF") != NULL;
	free(strname);
      }

	// Get a DC for the display
	m_dc = ::GetDC(NULL);
	PLASSERT(m_dc);
	if (m_dc == NULL) {
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Cannot allocate device context.");
	}

	if (isemf) {
		// We have an enhanced meta file which makes it alot easier
		m_hemf = SetEnhMetaFileBits(pDataSrc->GetFileSize(),pDataSrc->ReadEverything());
	}
	else {
		// Buh, old 16-Bit WMF, Convert it to an enhanced metafile before proceeding.
		// Also, check if this is a placeable metafile with an Adobe Placeable header
		pplaceablehdr = (SAPMFILEHEADER*)pDataSrc->ReadEverything();
		PLBYTE* p = NULL;
		UINT size;
		// If we have an adobe header, skip it to use only the real windows-conform data
		if (pplaceablehdr->key == ALDUSKEY) {
			isadobe = true;
			p = pDataSrc->ReadEverything()+sizeof(SAPMFILEHEADER);
			size = pDataSrc->GetFileSize() - sizeof(SAPMFILEHEADER);
		}
		else {
			// Else use the whole file contents as the metafile and assume
			// a native 16-Bit Windows-conform WMF
			p = pDataSrc->ReadEverything();
			size = pDataSrc->GetFileSize();
		}
		#ifdef _MFC_VER
		PLASSERT(AfxIsValidAddress(p,size,false));
		#endif
		m_hemf = SetWinMetaFileBits(size,p,m_dc,NULL);
	}

	// If m_hemf is NULL, windows refused to load the metafile. If this is
	// the case, we're done. Notify the caller
	if (m_hemf == NULL) {
		raiseError (PL_ERRFORMAT_NOT_SUPPORTED,"Windows Metafile functions failed to load this image.");
	}

	// Get the header from the enhanced metafile, It contains some
	// useful information which will aid us during constuction of
	// the bitmap.
	// The header is of variable length. First get the amount of
	//  memory required for the header
	UINT sizeneeded = GetEnhMetaFileHeader(m_hemf,0,NULL);
	if (sizeneeded == 0) {
		raiseError (PL_ERRFORMAT_UNKNOWN,"No header information in metafile");
	}

	// Allocate storage for the header and read it in
	m_phdr = (LPENHMETAHEADER) new PLBYTE[sizeneeded];
	if (m_phdr == NULL) {
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Out of memory during allocation of header.");
	}
	m_phdr->iType = EMR_HEADER;
	m_phdr->nSize = sizeneeded;
	#ifdef _MFC_VER
	PLASSERT(AfxIsValidAddress(m_phdr,sizeneeded,true));
	#endif
	GetEnhMetaFileHeader(m_hemf,sizeneeded,m_phdr);

	int bpp = GetDeviceCaps(m_dc,BITSPIXEL);

	// Calculate the dimensions of the final bitmap. If we have
	// a placeable header in the WMF, we use the dimensions of
	// that image, else we use the calculated dimensions in the
	// EMF
	int width,height;
	if (isadobe) {
		PLASSERT(pplaceablehdr);
		int lpx = GetDeviceCaps(m_dc,LOGPIXELSX);
		int lpy = GetDeviceCaps(m_dc,LOGPIXELSY);
		// Calculate the absolute with and height and transform from twips to pixel
		width  = (int) (pplaceablehdr->Right-pplaceablehdr->Left) * lpx / pplaceablehdr->inch;
		height = (int) (pplaceablehdr->Bottom-pplaceablehdr->Top) * lpy / pplaceablehdr->inch;
	}
	else {
		// Use the rclFrame of the header because it is the true device independent
		// information and also some applications (e.g. Corel) don't fill the
		// rclBounds correctly
		// Using:
		//     MetaPixelsX = MetaWidthMM * MetaPixels / (MetaMM * 100);
		// where:
		//     MetaWidthMM = metafile width in 0.01mm units
		//     MetaPixels  = width in pixels of the reference device
		//     MetaMM      = width in millimeters of the reference device
		// Same applies to the Y axis
		width  = ((m_phdr->rclFrame.right  - m_phdr->rclFrame.left) * m_phdr->szlDevice.cx) / (m_phdr->szlMillimeters.cx*100);
		height = ((m_phdr->rclFrame.bottom  - m_phdr->rclFrame.top) * m_phdr->szlDevice.cy) / (m_phdr->szlMillimeters.cy*100);
	}

	// If this is a very old WMF without a PLACEABLE info,
	// we use somewhat meaningful defaults. Also, if the header was
	// not written correctly, we use this as a fallback
	if (width <= 0) {
		width = 320;
	}
	if (height <= 0) {
		height = 200;
	}

	// Create a device content for the screen, and a memory device
	// content to play the metafile to

	m_memdc = CreateCompatibleDC(m_dc);
	PLASSERT(m_memdc);
	if (m_memdc == NULL) {
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Cannot allocate device context.");
	}

	m_bm = CreateCompatibleBitmap(m_dc,width,height);
	if (m_bm == NULL) {
		PLASSERT(false);
		raiseError (PL_ERRNO_MEMORY,"Cannot allocate memory bitmap.");
	}

	m_holdbm = SelectObject(m_memdc,m_bm);

	// If the metafile has a palette, read it in
	UINT pe = GetEnhMetaFilePaletteEntries(m_hemf, 0, NULL);

	// pe is the real number of palette entries. To make the resulting
	// bitmap more useful, we always setup a 256 color palette if the
	// metafile has a palette
  if (pe>0 && pe<256)
  {
    SetBmpInfo (PLPoint (width, height), PLPoint(0,0), 
             PLPixelFormat::L8);
	}
	else 
  {
    SetBmpInfo (PLPoint (width, height), PLPoint(0,0), 
            PLPixelFormat::B8G8R8A8);
  }
}
コード例 #10
0
void PLPNGDecoder::Open(PLDataSource *pDataSrc) {
  png_uint_32 width, height;

  m_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, user_error_fn, user_warning_fn);
  PLASSERT(m_png_ptr);

  m_info_ptr = png_create_info_struct(m_png_ptr);
  PLASSERT(m_info_ptr);

  png_set_read_fn(m_png_ptr, (void*)pDataSrc, my_read_data);

  /* The call to png_read_info() gives us all of the information from the
   * PNG file before the first IDAT (image data chunk).
   */
  png_read_info(m_png_ptr, m_info_ptr);

#ifdef DUMP_PNG_DATA
  debugLog("%s", toString(*m_png_ptr).cstr());
#endif

  png_get_IHDR(m_png_ptr, m_info_ptr, &width, &height, &m_bit_depth
              ,&m_color_type, NULL, NULL, NULL);


  if(  (m_color_type != PNG_COLOR_TYPE_RGB_ALPHA) 
   &&  (m_color_type != PNG_COLOR_TYPE_GRAY_ALPHA) 
   && ((m_color_type != PNG_COLOR_TYPE_RGB) || (m_bit_depth < 16))
    ) {

#ifdef PNG_READ_16_TO_8_SUPPORTED
    if(m_bit_depth == 16) {
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
      png_set_scale_16(png_ptr);
#else
      png_set_strip_16(png_ptr);
#endif
    }
#endif

    if(m_color_type == PNG_COLOR_TYPE_PALETTE) {
      png_set_expand(m_png_ptr);
    }
    if(m_bit_depth < 8) {
      png_set_expand(m_png_ptr);
    }
    if(png_get_valid(m_png_ptr, m_info_ptr, PNG_INFO_tRNS)) {
      png_set_expand(m_png_ptr);
    }
    if((m_color_type == PNG_COLOR_TYPE_GRAY) || (m_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) {
      png_set_gray_to_rgb(m_png_ptr);
    }

    /* set the background color to draw transparent and alpha images over */
    png_color_16 *pBackground;
    png_color     bkgColor = {127, 127, 127};
    if(png_get_bKGD(m_png_ptr, m_info_ptr, &pBackground)) {
      png_set_background(m_png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
      bkgColor.red   = (png_byte)pBackground->red;
      bkgColor.green = (png_byte)pBackground->green;
      bkgColor.blue  = (png_byte)pBackground->blue;

#ifdef DUMP_PNG_DATA
      debugLog("  Background         : (%d,%d,%d)\n", bkgColor.red, bkgColor.green, bkgColor.blue);
#endif
  }

    /* if required set gamma conversion */
    double dGamma;
    if(png_get_gAMA(m_png_ptr, m_info_ptr, &dGamma)) {
      png_set_gamma(m_png_ptr, (double)2.2, dGamma);
    }

    /* after the transformations are registered, update info_ptr data */
    png_read_update_info(m_png_ptr, m_info_ptr);

    png_get_IHDR(m_png_ptr, m_info_ptr, &width, &height, &m_bit_depth
                ,&m_color_type, NULL, NULL, NULL);

  }

  PLPixelFormat pf;
  switch(m_color_type) {
    case PNG_COLOR_TYPE_RGB:  
      pf = PLPixelFormat::R8G8B8;
      break;
    case PNG_COLOR_TYPE_RGB_ALPHA:      
      pf = PLPixelFormat::A8R8G8B8;
      break;
    case PNG_COLOR_TYPE_GRAY:
      pf = PLPixelFormat::L8;
      break;
    case PNG_COLOR_TYPE_GRAY_ALPHA:      
      png_set_gray_to_rgb(m_png_ptr);
      png_set_expand(m_png_ptr);      
      pf = PLPixelFormat::A8R8G8B8;
      break;
    case PNG_COLOR_TYPE_PALETTE:
      if(m_bit_depth != 16) {
        pf = PLPixelFormat::I8;
      } else { // 16-bit palette image
        png_set_expand(m_png_ptr);        
        pf = PLPixelFormat::R8G8B8;
      }
      break;
  }

  if((pf.GetBitsPerPixel() == 32) || (pf.GetBitsPerPixel() == 24)) { 
    png_set_bgr(m_png_ptr);
  }

  SetBmpInfo(PLPoint(width, height), PLPoint(0,0), pf);

  png_uint_32 XRes, YRes;
  int UnitType;
  png_get_pHYs(m_png_ptr, m_info_ptr, &XRes, &YRes, &UnitType);
  if(UnitType == PNG_RESOLUTION_METER) {
    m_Resolution = PLPoint(int (XRes/39.37f+0.5), int (YRes/39.37f+0.5));
  }
}
コード例 #11
0
ファイル: pliff85dec.cpp プロジェクト: artcom/y60
void PLIFF85Decoder::Open(PLDataSource * pDataSrc)
{

  // Check if the file is a valid IFF-85 file or not
  Trace(2, "Decoding IFF-85 header.\n");

  PLIFF85::Chunk chunk;

  if (PLIFF85::MakeID(reinterpret_cast<const char*> (pDataSrc->GetBufferPtr(sizeof chunk))) !=
        PLIFF85::ID_FORM)
  {
    raiseError(PL_ERRWRONG_SIGNATURE, "File is not a single-form IFF.");
  }

  readChunkHeader(chunk, pDataSrc);

  size_t totalSize = chunk.ckSize + sizeof chunk;
  size_t lumpIndex = sizeof chunk;

  // Now read the form type - we only know how to handle PBM and ILBM.
  chunk.ckID   = ReadMLong(pDataSrc);
  if (chunk.ckID == PLIFF85::ID_PBM)
  {
    Trace(2, "Form type: PBM\n");
  }
  else if (chunk.ckID == PLIFF85::ID_ILBM)
  {
    Trace(2, "Form type: ILBM\n");
  }
  else
  {
    raiseError(PL_ERRFORMAT_UNKNOWN, "Unknown form type.");
  }

  m_formType = chunk.ckID;
  lumpIndex += sizeof chunk.ckID;

  int numCMapElements = 0;

  m_viewMode = 0;

  // Now loop through the chunks, processing the header and cmap.
  // Stop when we find the body, so the data source is left in the correct
  // position to read it.
  bool  readBitmapHeader    = false;
  bool  readPalette         = false;
  bool  foundBody           = false;
  bool  done                = false;

  PLIFF85::LONG bodySize    = 0;

  while (!done)
  {
    readChunkHeader(chunk, pDataSrc);
    lumpIndex += sizeof chunk;

    if (chunk.ckID == PLIFF85::ID_BMHD)
    {
      if (size_t(chunk.ckSize) != sizeof m_bitmapHeader)
      {
        raiseError(PL_ERRFORMAT_UNKNOWN, "Unexpected header size.");
      }

      m_bitmapHeader.w                  = ReadMWord(pDataSrc);
      m_bitmapHeader.h                  = ReadMWord(pDataSrc);
      m_bitmapHeader.x                  = ReadMWord(pDataSrc);
      m_bitmapHeader.y                  = ReadMWord(pDataSrc);
      m_bitmapHeader.nPlanes            = ReadByte(pDataSrc);
      m_bitmapHeader.masking            = ReadByte(pDataSrc);
      m_bitmapHeader.compression        = ReadByte(pDataSrc);
      m_bitmapHeader.pad1               = ReadByte(pDataSrc);
      m_bitmapHeader.transparentColor   = ReadMWord(pDataSrc);
      m_bitmapHeader.xAspect            = ReadByte(pDataSrc);
      m_bitmapHeader.yAspect            = ReadByte(pDataSrc);
      m_bitmapHeader.pageWidth          = ReadMWord(pDataSrc);
      m_bitmapHeader.pageHeight         = ReadMWord(pDataSrc);

      switch (m_bitmapHeader.masking)
      {
        case PLIFF85::mskNone:
          Trace(2, "No masking.\n");
          break;
        case PLIFF85::mskHasMask:
          Trace(2, "Has mask plane.\n");
          break;
        case PLIFF85::mskHasTransparentColor:
          Trace(2, "Has transparent colour.\n");
          break;
        case PLIFF85::mskLasso:
          Trace(2, "Lasso");
          break;
        default:
          raiseError(PL_ERRFORMAT_UNKNOWN, "Unknown masking technique.");
          break;
      }

      switch (m_bitmapHeader.compression)
      {
        case PLIFF85::cmpNone:
          Trace(2, "No compression.\n");
          break;
        case PLIFF85::cmpByteRun1:
          Trace(2, "Byte run encoding.\n");
          break;
        default:
          raiseError(PL_ERRFORMAT_UNKNOWN, "Unknown compression method.");
          break;
      }
      readBitmapHeader = true;
    }
    else if (chunk.ckID == PLIFF85::ID_CMAP)
    {
      // The palette.
      PLCOMPILER_ASSERT(sizeof(PLIFF85::ColorRegister) == 3);

      numCMapElements = chunk.ckSize / 3;

      for (int i = 0; i < numCMapElements; ++i)
      {
        const PLIFF85::ColorRegister * pElement =
          reinterpret_cast<const PLIFF85::ColorRegister *> (pDataSrc->ReadNBytes(3));
        m_pal[i].Set(pElement->red, pElement->green, pElement->blue, 0xFF);
      }
      readPalette = true;
    }
    else if (chunk.ckID == PLIFF85::ID_CAMG)
    {
      // The viewport mode.
      if (size_t(chunk.ckSize) != sizeof m_viewMode)
      {
        raiseError(PL_ERRFORMAT_UNKNOWN, "Unexpected CAMG size.");
      }
      m_viewMode = ReadMLong(pDataSrc);
      #if DETAILED_TRACE
        std::ostringstream strTrace;
        strTrace << "View mode " << std::hex << std::showbase << m_viewMode << ".\n";
        Trace(2, strTrace.str().c_str());
      #endif
    }
    else if (chunk.ckID == PLIFF85::ID_BODY)
    {
      bodySize      = chunk.ckSize;
      foundBody     = true;
      done          = true;
    }
    else
    {
      // Some other chunk type - ignore it.
      pDataSrc->Skip(chunk.ckSize);
    }

    if (!done)
    {
      lumpIndex += chunk.ckSize;
    }

    if (lumpIndex >= totalSize - 1)
    {
      done = true;
    }
  }

  // We must have seen a header, cmap and body at this point.
  if (!readBitmapHeader)
  {
    raiseError(PL_ERRFORMAT_UNKNOWN, "Header not found.");
  }

  if ((!readPalette) && (m_bitmapHeader.nPlanes <= 8))
  {
    raiseError(PL_ERRFORMAT_UNKNOWN, "Palette not found.");
  }

  if (!foundBody)
  {
    raiseError(PL_ERRFORMAT_UNKNOWN, "Body not found.");
  }

  // Check the body is the expected size ...
  if (m_bitmapHeader.compression == PLIFF85::cmpNone)
  {
    if (bodySize != getBytesPerRow() * m_bitmapHeader.h)
    {
      raiseError(PL_ERRFORMAT_UNKNOWN, "Unexpected body size.");
    }
  }

  // ... and that it does not extend beyond the end of the form.
  if (lumpIndex + bodySize > totalSize)
  {
    raiseError(PL_ERRFORMAT_UNKNOWN, "Body extends beyond form.");
  }

  // Too many CMAP entries probably indicates an error.
  const int maxExpectedCMapElements = int(((m_viewMode & PLIFF85::viewHAM) != 0) ?
    pow(2.0, m_bitmapHeader.nPlanes - 2) :
    pow(2.0, m_bitmapHeader.nPlanes));

  if (numCMapElements > maxExpectedCMapElements)
  {
    raiseError(PL_ERRFORMAT_UNKNOWN, "Too many CMAP entries.");
  }

  PLPixelFormat pf;
  int DestBPP = m_bitmapHeader.nPlanes;
  bool bAlpha = (m_bitmapHeader.masking == PLIFF85::mskHasTransparentColor);

  if ((DestBPP > 8)
  ||  ((m_viewMode & PLIFF85::viewHAM) != 0)
  ||  (m_bitmapHeader.masking == PLIFF85::mskHasTransparentColor))
  {
    if (bAlpha) {
      pf = PLPixelFormat::A8R8G8B8;
    } else {
      pf = PLPixelFormat::X8R8G8B8;
    }
  }
  else 
  {
    pf = PLPixelFormat::I8;
  }

  SetBmpInfo(PLPoint(m_bitmapHeader.w, m_bitmapHeader.h), PLPoint(0, 0), pf);
} // Open
コード例 #12
0
void PLPPMDecoder::Open (PLDataSource *pDataSrc) {
  Trace (2, "Decoding PPM.\n");

  readPpmHeader(&m_PPMHead, pDataSrc);
  SetBmpInfo(PLPoint(m_PPMHead.ImageWidth, m_PPMHead.ImageHeight), PLPoint (0,0), PLPixelFormat::X8R8G8B8);
}