Пример #1
0
void PLFilterGetAlpha::Apply(PLBmpBase * pBmpSource, PLBmp * pBmpDest) const
{
  // Only works for 32 bpp bitmaps.
  PLASSERT (pBmpSource->GetBitsPerPixel() == 32);

  PLASSERT (pBmpSource->HasAlpha());

  pBmpDest->Create (pBmpSource->GetWidth(), pBmpSource->GetHeight(), 
                    PLPixelFormat::L8, NULL, 0, 
                    pBmpSource->GetResolution());
  PLPixel32 ** pSrcLines = pBmpSource->GetLineArray32();
  PLBYTE ** pDstLines = pBmpDest->GetLineArray();

  for (int y = 0; y<pBmpDest->GetHeight(); ++y)
  { // For each line
    PLPixel32 * pSrcPixel = pSrcLines[y];
    PLBYTE * pDstPixel = pDstLines[y];

    for (int x = 0; x < pBmpDest->GetWidth(); ++x)
    { // For each pixel
      *pDstPixel = pSrcPixel->GetA();
      ++pSrcPixel;
      ++pDstPixel;
    }
  }
}
void PLFilterResizeBilinear::Apply(PLBmpBase * pBmpSource, PLBmp * pBmpDest) const
{
  PLASSERT(pBmpSource->GetBitsPerPixel()==32 || pBmpSource->GetBitsPerPixel()==24);

  // Create a new Bitmap 
  pBmpDest->Create(m_NewXSize,
                   m_NewYSize,
                   pBmpSource->GetPixelFormat(),
                   NULL, 0, 
                   pBmpSource->GetResolution());
                     
  // Create a Filter Class from template
  PLBilinearContribDef f(0.64);
  if (pBmpSource->GetBitsPerPixel() == 32) 
  {
    C2PassScale <CDataRGBA_UBYTE> sS(f);
    sS.Scale ((CDataRGBA_UBYTE::_RowType *) pBmpSource->GetLineArray(), 
               pBmpSource->GetWidth(), 
               pBmpSource->GetHeight(), 
               (CDataRGBA_UBYTE::_RowType *) pBmpDest->GetLineArray(),
               pBmpDest->GetWidth(),
               pBmpDest->GetHeight());
  }
  else
  {
    C2PassScale <CDataRGB_UBYTE> sS(f);
    sS.Scale ((CDataRGB_UBYTE::_RowType *) pBmpSource->GetLineArray(), 
               pBmpSource->GetWidth(), 
               pBmpSource->GetHeight(), 
               (CDataRGB_UBYTE::_RowType *) pBmpDest->GetLineArray(),
               pBmpDest->GetWidth(),
               pBmpDest->GetHeight());
  }
}
void PLFilterThreshold::Apply(PLBmpBase * pBmpSource, PLBmp * pBmpDest) const
{

  int threshold_min = m_threshold_min;
  int threshold_max = m_threshold_max;
  int channel = m_channel;

  // Only works for 32 bpp bitmaps at the moment.
  PLASSERT (pBmpSource->GetBitsPerPixel() == 32);

  pBmpDest->Create (pBmpSource->GetWidth(), pBmpSource->GetHeight(), 
            PLPixelFormat::L8, NULL, 0, pBmpSource->GetResolution());
  PLBYTE ** pSrcLines = pBmpSource->GetLineArray();
  PLBYTE ** pDstLines = pBmpDest->GetLineArray();

  for (int y = 0; y<pBmpDest->GetHeight(); ++y)
  { // For each line
    PLBYTE * pSrcPixel = pSrcLines[y];
    PLBYTE * pDstPixel = pDstLines[y];

    for (int x = 0; x < pBmpDest->GetWidth(); ++x)
    { // For each pixel
      if ((PLBYTE (pSrcPixel[channel]) <= PLBYTE (threshold_min)) ||
          (PLBYTE (pSrcPixel[channel]) >= PLBYTE(threshold_max)))
        *pDstPixel = 0;
      else
        *pDstPixel = pSrcPixel[channel];
      pSrcPixel += sizeof(PLPixel32);
      ++pDstPixel;
    }
  }
}
Пример #4
0
void PLWinBmp::AlphaBlt (PLWinBmp * pSrPLBmp, int x, int y)
// Do a bitblt using the alpha channel of pSrPLBmp.
// Legacy routine. Should not be used.
{
  PLASSERT_VALID (this);
  PLASSERT (GetBitsPerPixel() == 32);

  PLASSERT_VALID (pSrPLBmp);

  // Overlay picture
  int DestLineLen = GetWidth()*4;
  int SrcLineLen = pSrPLBmp->GetBytesPerLine();
  PLPixel32 * pPal = pSrPLBmp->GetPalette();

  // Perform clipping.
  int maxy = min (pSrPLBmp->GetHeight(),
                  GetHeight()-y);
  int maxx = min (pSrPLBmp->GetWidth(),
                  GetWidth()-x);
  int miny = max (0,-y);
  int minx = max (0,-x);

  if (pSrPLBmp->HasAlpha())
  {
    int alpha, negalpha;

    for (int sy = miny; sy<maxy; sy++)
    { // For each line
      BYTE * pDest = m_pBits+DestLineLen*(y+sy)+x*4;
      BYTE * pSrc = pSrPLBmp->m_pBits+SrcLineLen*sy;

      for (int sx = minx; sx<maxx; sx++)
      { // For each pixel
        if (pPal)
        {
          BYTE * pPixel = (BYTE *)&(pPal[*pSrc]);
          alpha = pPixel[3];
          negalpha = 255-alpha;
          pDest[0] = (pDest[0]*negalpha+pPixel[0]*alpha)>>8;
          pDest[1] = (pDest[1]*negalpha+pPixel[1]*alpha)>>8;
          pDest[2] = (pDest[2]*negalpha+pPixel[2]*alpha)>>8;

          pSrc++;
        }
        else
        {
          alpha = pSrc[3];
          negalpha = 255-alpha;
          pDest[0] = (pDest[0]*negalpha+pSrc[0]*alpha)>>8;
          pDest[1] = (pDest[1]*negalpha+pSrc[1]*alpha)>>8;
          pDest[2] = (pDest[2]*negalpha+pSrc[2]*alpha)>>8;
          pSrc += 4;
        }

        pDest += 4;
      }
    }
Пример #5
0
void PLDIBSection::AssertValid
    () const
{
  // call inherited PLASSERT_VALID first
  PLWinBmp::AssertValid();

  // Bitmap must exist
  PLASSERT (m_hBitmap);
}
Пример #6
0
// the actual data buffer is allocated in the derived classes
void PLDataSink::Open
    ( const char * pszName,
      PLBYTE*  pData,
      size_t MaxFileSize
    )
{
  // Data source may not be open already!
  PLASSERT (! m_pStartData);
  PLASSERT (MaxFileSize > 0);

  m_nMaxFileSize = MaxFileSize;
  // unchecked memory allocation, here!
  m_pszName = new char [strlen (pszName)+1];
  strcpy (m_pszName, pszName);
  m_pStartData = pData;
  m_nCurPos = 0;
#ifdef _WIN32
  m_bNameIsWide = false;
#endif
}
Пример #7
0
void PLDataSink::OpenW
    ( const wchar_t * pszwName,
      PLBYTE*  pData,
      size_t MaxFileSize
    )
{
  // Data source may not be open already!
  PLASSERT (! m_pStartData);
  PLASSERT (MaxFileSize > 0);

  m_nMaxFileSize = MaxFileSize;
  // unchecked memory allocation, here!
  m_pszwName = new wchar_t [wcslen (pszwName)+1];
  m_pszName = new char[strlen("Wide")+1];
  strcpy(m_pszName,"Wide");
  wcscpy (m_pszwName, pszwName);
  m_pStartData = pData;
  m_nCurPos = 0;
  m_bNameIsWide = true;
}
Пример #8
0
void PLDataSource::OpenW
    ( const wchar_t * pszwName,
      int    FileSize
    )
{
  // Data source may not be open already!
  PLASSERT (!m_FileSize);

  m_pszwName = new wchar_t [wcslen (pszwName)+1];
  wcscpy (m_pszwName, pszwName);
  m_pszName = new char[strlen("Wide")+1];
  strcpy(m_pszName,"Wide");
  m_FileSize = FileSize;
  m_BytesRead = 0;
  m_bNameIsWide = true;
}
Пример #9
0
void PLDataSource::Open
    ( const char * pszName,
      int    FileSize
    )
{
  // Data source may not be open already!
  PLASSERT (!m_FileSize);

  m_pszName = new char [strlen (pszName)+1];
  strcpy (m_pszName, pszName);
  m_FileSize = FileSize;
  m_BytesRead = 0;
#ifdef _WIN32
  m_bNameIsWide = false;
#endif
}
Пример #10
0
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);

}
Пример #11
0
void PLTIFFEncoder::DoEncode (PLBmpBase * pBmp, PLDataSink* pDataSnk)
{
  TIFF* tif = TIFFOpenMem (pDataSnk->m_pStartData,
                           pDataSnk->m_nMaxFileSize,
                           &(pDataSnk->m_nCurPos));
  PLASSERT( tif );
  /*
  if (!tif)
  raiseError (PL_ERRWRONG_SIGNATURE, PLTIFFDecoder::m_szLastErr);
  */

  // initialize TIFF "directory"
  SetBaseTags( tif, pBmp );

  DoTiffEncode( pBmp, tif );

  TIFFClose( tif );
}
Пример #12
0
void PLFilterVideoInvert::Apply(PLBmpBase *pBmpSource, PLBmp *pBmpDest) const
{
  // Only works for 32 bpp bitmaps at the moment.
  PLASSERT (pBmpSource->GetBitsPerPixel() == 32);

  pBmpDest->Create (pBmpSource->GetWidth(), pBmpSource->GetHeight(),
                    PLPixelFormat::X8R8G8B8, NULL, 0, pBmpSource->GetResolution());
  PLBYTE ** pSrcLines = pBmpSource->GetLineArray();
  PLBYTE ** pDstLines = pBmpDest->GetLineArray();

  for (int y = 0; y<pBmpDest->GetHeight(); ++y)
  { // For each line
    PLBYTE * pSrcPixel = pSrcLines[y];
    PLBYTE * pDstPixel = pDstLines[y];

    for (int x = 0; x < pBmpDest->GetWidth(); ++x)
    { // For each pixel
      double v1, v2, v3;

      v1 = (double)pSrcPixel[PL_RGBA_RED];
      v2 = (double)pSrcPixel[PL_RGBA_GREEN];
      v3 = (double)pSrcPixel[PL_RGBA_BLUE];

      fp_rgb_to_hsv(&v1, &v2, &v3);
      v3 = 255.0-v3;
      fp_hsv_to_rgb(&v1, &v2, &v3);

      *pDstPixel = static_cast<PLBYTE>(v3);
    pDstPixel++;
      *pDstPixel = static_cast<PLBYTE>(v2);
    pDstPixel++;
      *pDstPixel = static_cast<PLBYTE>(v1);
    pDstPixel++;

    pDstPixel++;

    /*PLBYTE (pSrcPixel[PL_RGBA_RED]*0.212671+
                         pSrcPixel[PL_RGBA_GREEN]*0.715160+
                         pSrcPixel[PL_RGBA_BLUE]*0.072169);*/
      pSrcPixel += sizeof(PLPixel32);
    }
  }

}
Пример #13
0
// now flush the data to disk
void PLFileSink::Close ()
{
#ifdef PL_FILE_MAPPING
#   ifdef _WIN32
  UnmapViewOfFile (m_pStartData);
  CloseHandle (m_hm);
  m_hm = NULL;
  ::SetFilePointer(m_hf,GetDataSize(),0,FILE_BEGIN);
  ::SetEndOfFile(m_hf); //Truncate the file to the right size
  CloseHandle (m_hf);
  m_hf = NULL;
#   else
  resizeMapping(GetDataSize());
  if (munmap(m_pDataBuf, GetDataSize()) != 0) {
    std::cerr <<"munmap failed, got error "<< strerror(errno)<<std::endl;
    throw PLTextException(PL_ERRINTERNAL, "munmap failed");
  }
  m_pDataBuf = NULL;
  close( m_File );
  m_File = 0;

#   endif
#else
  int towrite = GetDataSize();
  int written = fwrite( m_pStartData, 1, towrite, m_pFile );
#   ifndef _DEBUG
// avoid warnings
    (void)(towrite);
    (void)(written);
#   endif
  PLASSERT( written == towrite );
  fclose( m_pFile );
  m_pFile = 0;

  if (m_pDataBuf)
  {
    delete[] m_pDataBuf;
    m_pDataBuf = NULL;
  }
#endif

  PLDataSink::Close();
}
Пример #14
0
void PLFilterColorize::ApplyInPlace(PLBmpBase * pBmp) const
{
  PLAnyBmp TempBmp;
  TempBmp.CreateFilteredCopy(*pBmp, PLFilterGrayscale());
  
  PLPixel24 ColorTable[256];
  for (int i=0; i<256; i++) 
  {
    ColorTable[i] = hls2rgb(m_Hue, i, m_Saturation);
  }

  PLBYTE ** pSrcLines = TempBmp.GetLineArray();
  for (int y = 0; y < TempBmp.GetHeight(); y++)
  {
    PLBYTE * pSrcLine = pSrcLines[y];
    switch (pBmp->GetBitsPerPixel()) {
      case 32:
        {
          PLPixel32 * pDestLine = pBmp->GetLineArray32()[y];
          for (int x = 0; x < TempBmp.GetWidth(); x++) 
          { 
            pDestLine[x] = ColorTable[pSrcLine[x]];
          }
        }
        break;
      case 24:
        {
          PLPixel24 * pDestLine = pBmp->GetLineArray24()[y];
          for (int x = 0; x < TempBmp.GetWidth(); x++) 
          { 
            pDestLine[x] = ColorTable[pSrcLine[x]];
          }
        }
        break;
      default:
        // bpp other than 8 and 24 are not supported.
        PLASSERT(false);
    }
  }
}
Пример #15
0
void PLWinBmp::AssertValid () const
{
  // call inherited PLASSERT_VALID first
  PLBmp::AssertValid();

  // Bitmap must exist
  PLASSERT (m_pBMI);

  // Bitmapinfo must equal member variables
  PLASSERT (m_pBMI->biHeight == m_Size.y);
  PLASSERT (m_pBMI->biWidth == m_Size.x);
  PLASSERT (m_pBMI->biBitCount == GetBitsPerPixel());

  // Only uncompressed bitmaps allowed.
  PLASSERT (m_pBMI->biCompression == BI_RGB);

  // No optimized color tables allowed.
  PLASSERT (m_pBMI->biClrUsed == 0 ||
          m_pBMI->biClrUsed == (DWORD)(1 << GetBitsPerPixel()));
}
Пример #16
0
void PLFilterContrast::Apply(PLBmpBase * pBmpSource, PLBmp * pBmpDest) const
{
  // Consider a coordinate system with two axes: The x axis represents
  // an input RGB component or intensity, the y axis an output RGB
  // component or intensity. The ranges of input and output values go 
  // from 0 - 255. 
  // If I take a straight line that intersects (0,0) through (255,255), 
  // I have defined a Null filter that leaves the image unchanged. 

  // Next step: Let's rotate this straight line around the point (128,128).
  // If I increase the slope, output values above (128,128) are increased 
  // by the slope factor, output values below (128, 128) are decreased 
  // likewise. This is how I create the contrast enhancement effect.

  // Now we are having a problem: Increasing the slope means that our
  // straight line intersects the line (x, 255), creating output values 
  // above 255 which are not defined in our RGB model. Since in the RGB world
  // there is nothing whiter than white, I'll set all these values to 255. A 
  // similar thing happens  on the lower left of our imaginary diagram: All
  // values smaller than 0 have to be set 0 - according to the fact that 
  // there is nothing darker than absolute darkness...

  // Ok, now what is that offset value good for? Remember the point 
  // (128,128). At this position, input and output values of our filter 
  // remain unchanged, independent of the slope of our straight line. Now 
  // imagine we are shifting our line parallel to the x axis. Our filter 
  // works quite differently now: We create a cut-off for the higher output 
  // value range (shift right), or the lower ones (shift left).

  // int total = 0;
  register int inc = 0;

  double contrast = m_contrast;
 
  PLASSERT (pBmpSource->GetBitsPerPixel() >= 24);

  pBmpDest->Create (pBmpSource->GetWidth(), 
                    pBmpSource->GetHeight(),
                    pBmpSource->GetPixelFormat(),
                    NULL, 0, 
                    pBmpSource->GetResolution());

  PLBYTE ** pSrcLines = pBmpSource->GetLineArray();
  PLBYTE ** pDstLines = pBmpDest->GetLineArray();

  register int destWidth = pBmpDest->GetWidth();

  if(pBmpSource->GetBitsPerPixel() == 24)
   inc = 3;

  if(pBmpSource->GetBitsPerPixel() == 32)
   inc = sizeof(PLPixel32);

  register double red, green, blue;
  register double csupp = contrast * (m_offset - 128.0) + 128.0;

  for (int y = 0; y < pBmpDest->GetHeight(); ++y)
  { // For each line
    register PLBYTE * pSrcPixel = pSrcLines[y];
    register PLBYTE * pDstPixel = pDstLines[y];

    for (register int x = 0; x < destWidth; ++x)
    {
       // Formel für Kontrastberechnung:
       // v = (contrast * (v - 12580 + m_offset) + 128.0);
       red   = contrast * ((double) (pSrcPixel[PL_RGBA_RED])) + csupp;
       green = contrast * ((double) (pSrcPixel[PL_RGBA_GREEN])) + csupp;
       blue  = contrast * ((double) (pSrcPixel[PL_RGBA_BLUE])) + csupp;

       if(red >= 255.0)
        pDstPixel[PL_RGBA_RED] = (PLBYTE) 255;
       else if (red < 0.0)
        pDstPixel[PL_RGBA_RED] = (PLBYTE) 0;
       else
        pDstPixel[PL_RGBA_RED] = (PLBYTE) red;

       if(green >= 255.0)
        pDstPixel[PL_RGBA_GREEN] = (PLBYTE) 255;
       else if (green < 0.0)
        pDstPixel[PL_RGBA_GREEN] = (PLBYTE) 0;
       else
        pDstPixel[PL_RGBA_GREEN] = (PLBYTE) green;

       if(blue >= 255.0)
        pDstPixel[PL_RGBA_BLUE] = (PLBYTE) 255;
       else if (blue < 0.0)
        pDstPixel[PL_RGBA_BLUE] = (PLBYTE) 0;
       else
        pDstPixel[PL_RGBA_BLUE] = (PLBYTE) blue;

       pSrcPixel += inc;
       pDstPixel += inc;
    }
  }
}
Пример #17
0
void PLTIFFDecoder::doLoColor (TIFF * tif, PLBmpBase * pBmp)
{
  uint16  BitsPerSample;
  uint16  SamplePerPixel;
  int32  LineSize;
  int16  PhotometricInterpretation;
  int  row;
  PLBYTE  *pBits;

  TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample);
  TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &SamplePerPixel);
  TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation);

  if (PhotometricInterpretation!=PHOTOMETRIC_MINISWHITE &&
      PhotometricInterpretation!=PHOTOMETRIC_MINISBLACK &&
      PhotometricInterpretation!=PHOTOMETRIC_PALETTE)
  {
    PhotometricInterpretation = PHOTOMETRIC_MINISWHITE;
    Trace(2,"unexpected PhotometricInterpretation, default to PHOTOMETRIC_MINISWHITE");
  }

  LineSize = TIFFScanlineSize(tif); //Number of bytes in one line

  PLPixel32 pPal[256];

  pBits = new PLBYTE [LineSize]; // enough for 16-bits per pixel
  if (pBits == NULL)
    raiseError (PL_ERRNO_MEMORY, "Out of memory allocating TIFF buffer.");

  // phase one: build color map
  if (BitsPerSample < 16) {
    if /* monochrome (=bitonal) or grayscale */
      (PhotometricInterpretation == PHOTOMETRIC_MINISWHITE ||
       PhotometricInterpretation == PHOTOMETRIC_MINISBLACK)
      {
        int numColors = 1 << BitsPerSample;
        PLBYTE step = static_cast<PLBYTE>(255 / (numColors-1));
        PLBYTE *pb = (PLBYTE *) (pPal);
        int offset = sizeof(PLPixel32);
        if (PhotometricInterpretation == PHOTOMETRIC_MINISWHITE)
        {
          pb += (numColors-1) * sizeof(PLPixel32);
          offset = -offset;
        }
        // warning: the following ignores possible halftone hints
        for (int i = 0; i < numColors; ++i, pb += offset)
        {
          pb[PL_RGBA_RED] = pb[PL_RGBA_GREEN] = pb[PL_RGBA_BLUE] = static_cast<PLBYTE>(i * step);
          pb[PL_RGBA_ALPHA] = 255;
        }

      }
    //PhotometricInterpretation = 2 image is RGB
    //PhotometricInterpretation = 3 image has a color palette
    else if (PhotometricInterpretation == PHOTOMETRIC_PALETTE)
    {
      uint16* red;
      uint16* green;
      uint16* blue;
      int16 Palette16Bits;

      // we get pointers to libtiff-owned colormaps
      TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue);

      //Is the palette 16 or 8 bits ?
      Palette16Bits = checkcmap(1<<BitsPerSample, red, green, blue) == 16;

      //load the palette in the DIB
      for (int i = 0; i < 1<<BitsPerSample; ++i)
      {
        PLBYTE *pb = (PLBYTE *) ((pPal)+i);
        pb[PL_RGBA_RED  ] = (PLBYTE) (Palette16Bits ? CVT(  red[i]) :   red[i]);
        pb[PL_RGBA_GREEN] = (PLBYTE) (Palette16Bits ? CVT(green[i]) : green[i]);
        pb[PL_RGBA_BLUE ] = (PLBYTE) (Palette16Bits ? CVT( blue[i]) :  blue[i]);
        pb[PL_RGBA_ALPHA] = 255;
      }
    }
    else
      Trace( 2, "unexpected PhotometricInterpretation in PLTIFFDecoder::DoLoColor()" );
  }
  // phase two: read image itself

  //generally, TIFF images are ordered from upper-left to bottom-right
  // we implicitly assume PLANARCONFIG_CONTIG
  PLBYTE **pLineArray = pBmp->GetLineArray();  

  if (BitsPerSample > 16)
    Trace( 2, "unexpected bit-depth in PLTIFFDecoder::DoLoColor()" );
  else for ( row = 0; row < GetHeight(); ++row )
    {
      uint16 x;
      int status = TIFFReadScanline( tif, pBits, row, 0 );
      if (status == -1 && row < GetHeight()  / 3)
      {
        delete [] pBits;
        // we should maybe free the BMP memory as well...
        raiseError (PL_ERRINTERNAL, m_szLastErr);
      }
      /*
      if (BitsPerSample == 1)  // go ahead, waste space ;-)
        for (x=0; x < imageWidth; ++x)
          pLineArray[row][x] = pBits[x / 8] & (128 >> (x & 7)) ? 1 : 0;
      else */
      if (BitsPerSample == 4)
      {
        for (x=0; x < GetWidth() / 2; ++x)
        {
          pLineArray[row][2*x  ] = (pBits[x] & 0xf0) >> 4;
          pLineArray[row][2*x+1] = (pBits[x] & 0x0f);
        }
        // odd number of pixels
        if (GetWidth() & 1)
          pLineArray[row][GetWidth()-1] = (pBits[x] & 0xf0) >> 4;
      } else if (BitsPerSample == 16) {
          PLASSERT (SamplePerPixel == 1); // can't do 16-bit with alpha yet
          PLPixel16 **pLineArray16 = pBmp->GetLineArray16();
          memcpy( pLineArray16[row], pBits, LineSize );
      } else //if (BitsPerSample == 8 || BitsPerSample == 1)
        if (SamplePerPixel == 1)
          memcpy( pLineArray[row], pBits, LineSize );
        else
        {
          // We've got an 8 bit image with an alpha channel.
          // Ignore the alpha channel.
          PLASSERT (BitsPerSample == 8);
          for (x=0; x < GetWidth(); ++x)
            pLineArray[row][x] = pBits[x*2];
        }
    }
Пример #18
0
void PLTIFFDecoder::doHiColor (TIFF * tif, PLBmpBase * pBmp, uint16 SamplePerPixel)
{
  int ok;
  PLULONG x, y;

  TIFFRGBAImage img;
  char emsg[1024];
  PLBYTE * pBits;

  ok = TIFFRGBAImageBegin(&img, tif, 0, emsg);

  if (ok == 0)
  {
    raiseError (PL_ERRWRONG_SIGNATURE, "TIFF subformat not supported.");
  }

  //bool bHasAlpha = pBmp->HasAlpha();
  PLASSERT (int(img.width) == pBmp->GetWidth());
  PLASSERT (int(img.height) == pBmp->GetHeight());
  PLASSERT (pBmp->GetBitsPerPixel() == 32);
  pBits = new PLBYTE [img.width*img.height*4];
  if (pBits == NULL)
    raiseError (PL_ERRNO_MEMORY, "Out of memory allocating TIFF buffer.");

  // Hack for photoshop alpha channel support
  if (SamplePerPixel == 4 && img.bitspersample == 8 && img.photometric == 2)
  {
    img.put.contig = putRGBAAcontig8bittile;
  }

  ok = TIFFRGBAImageGet(&img, (uint32 *) pBits, img.width, img.height);
  if (!ok)
  {
    TIFFRGBAImageEnd(&img);
    raiseError (PL_ERRWRONG_SIGNATURE, m_szLastErr);
  }

  PLPixel32 ** pLineArray = pBmp->GetLineArray32();

  // Correct the byte ordering. This could be replaced by appropriate 
  // putRGBAcontig... routines.
  for (y=0; y<img.height; y++)
  {
    PLBYTE * pSrc = pBits+(img.height-y-1)*img.width*4;
    PLPixel32 * pPixel = pLineArray[y];
    for  (x=0; x<img.width; x++)
    {
#ifdef WORDS_BIGENDIAN
      pPixel->Set (*(pSrc+3), *(pSrc+2), *(pSrc+1), *(pSrc));
#else
      pPixel->Set (*pSrc, *(pSrc+1), *(pSrc+2), *(pSrc+3));
#endif    
      pPixel++;
      pSrc += 4;
    }
  }

  // Clean up.
  delete [] pBits;
  TIFFRGBAImageEnd(&img);
}
Пример #19
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);
  }
}
Пример #20
0
int PLTIFFEncoder::SetBaseTags (TIFF* tif, PLBmpBase* pBmp)
{
  PLASSERT( tif && pBmp );

  uint16 ui16 = 0;
  uint32 ui32 = 0;

  ui32 = pBmp->GetWidth();
  SetField( tif, TIFFTAG_IMAGEWIDTH,      ui32 );
  ui32 = pBmp->GetHeight();
  SetField( tif, TIFFTAG_IMAGELENGTH,     ui32 );
  // one strip = the whole image
  // SetField( tif, TIFFTAG_ROWSPERSTRIP,    ui32 );
  ui16 = static_cast<uint16>(pBmp->GetBitsPerPixel());
  if (ui16 > 8) ui16 = 8;
  SetField( tif, TIFFTAG_BITSPERSAMPLE,   ui16 );
  ui16 = static_cast<uint16>(pBmp->GetBitsPerPixel());
  ui16 = ui16 <= 8 ? 1 : (pBmp->HasAlpha() ? 4 : 3);
  SetField( tif, TIFFTAG_SAMPLESPERPIXEL, ui16 );

  if (pBmp->HasAlpha())
  {
    // We'll default the alpha to "associated" and
    // assume it's pre-multiplied. Note that Photoshop
    // will load such a TIFF and use the alpha as the
    // layer's transparency. If extraType is 2, then 
    // the alpha is unassociated, and Photoshop will
    // import the alpha as a fourth channel.
    short extraType[1] = {1};
    SetField( tif, TIFFTAG_EXTRASAMPLES, 1, extraType);
  }

  ui16 = m_Compression;
  SetField( tif, TIFFTAG_COMPRESSION,     ui16 );

  ui16 = PLANARCONFIG_CONTIG;
  SetField( tif, TIFFTAG_PLANARCONFIG,    ui16 );

  /*
   * The following tags are supposedly mandatory,
   * but libtiff seems to have sensible defaults for us
   *

  ui32 = 0;
  SetField( TIFFTAG_SUBFILETYPE,     ui32 );
  ?!?
  SetField( TIFFTAG_STRIPOFFSETS,    ui32 );
  ?!?
  SetField( TIFFTAG_STRIPBYTECOUNT,  ui32 );
   *
   *
   */

  float nRes = float(pBmp->GetResolution().x);
  SetField(tif,TIFFTAG_XRESOLUTION,nRes);
  nRes = float(pBmp->GetResolution().y);
  SetField(tif,TIFFTAG_YRESOLUTION,nRes);
  SetField (tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);

  switch (pBmp->GetBitsPerPixel())
  {
    case 1:
      {
        // look at bi-level palette...
        PLBYTE* p = (PLBYTE*) pBmp->GetPalette();
        ui16 = p[PL_RGBA_RED] < p[PL_RGBA_RED + sizeof(PLPixel32)] &&
               p[PL_RGBA_GREEN] < p[PL_RGBA_GREEN + sizeof(PLPixel32)] &&
               p[PL_RGBA_BLUE] < p[PL_RGBA_BLUE + sizeof(PLPixel32)] ?
               PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_MINISWHITE;
        SetField( tif, TIFFTAG_PHOTOMETRIC,   ui16 );
      }
      break;

    case 8:
      ui16 = PHOTOMETRIC_PALETTE;
      SetField( tif, TIFFTAG_PHOTOMETRIC,    ui16 );
      break;

    case 24:
    case 32:
      ui16 = PHOTOMETRIC_RGB;
      SetField( tif, TIFFTAG_PHOTOMETRIC,    ui16 );
      break;

    default:
      PLASSERT(false);
  }

  return 1; // should reflect the successful directory initialisation
}
Пример #21
0
void PLTIFFEncoderEx::DoEncode (PLBmpBase * pBmp, PLDataSink* /* pDataSnk */)
{
  PLASSERT( m_TiffToken );
  // call base version on open tiff descriptor
  PLTIFFEncoder::DoTiffEncode( pBmp, m_TiffToken );
}
Пример #22
0
void PLTIFFEncoder::DoTiffEncode (PLBmpBase* pBmp, TIFF* tif)
{
  uint32 l, c, image_length, image_width;
  // iterate over data
  PLBYTE **pla = pBmp->GetLineArray();
  PLASSERT( pla );

  image_length = (uint32) pBmp->GetHeight();
  image_width  = (uint32) pBmp->GetWidth();
  switch (pBmp->GetBitsPerPixel())
  {
    case 8:
      {
        // first, save the colormap
        uint16 red[256];
        uint16 green[256];
        uint16 blue[256];

        PLPixel32 * pPal = pBmp->GetPalette();
        PLASSERT( pPal );
        for (int i = 0; i < pBmp->GetNumColors(); i++, pPal++)
        {
          red[i]   = pPal->GetR ();
          green[i] = pPal->GetG ();
          blue[i]  = pPal->GetB ();
        }
        SetField( tif, TIFFTAG_COLORMAP, red, green, blue );
      }
      // fall-through

    case 1:  // TODO: a bit of error checking
      for (l = 0; l < image_length; l++)
        if(TIFFWriteScanline( tif, pla[l], l, 0 ) < 1) {
            throw PLTextException(PL_ERRINTERNAL, "TIFFWriteScanline failed");
        }
      break;

    case 24:
      {
        // TODO: check whether (r,g,b) components come in the correct order here...
        PLBYTE* pBuf = new PLBYTE[3*image_width];
        for (l = 0; l < image_length; l++)
        {
          for (c = 0; c < image_width; c++)
          {
            pBuf[c*3 + 0] = pla[l][c*sizeof(PLPixel24) + PL_RGBA_RED];
            pBuf[c*3 + 1] = pla[l][c*sizeof(PLPixel24) + PL_RGBA_GREEN];
            pBuf[c*3 + 2] = pla[l][c*sizeof(PLPixel24) + PL_RGBA_BLUE];
          }
          if(TIFFWriteScanline( tif, pBuf, l, 0 ) < 1) {
              throw PLTextException(PL_ERRINTERNAL, "TIFFWriteScanline failed");
          }
        }
        delete [] pBuf;
      }
      break;
    case 32:
      {
        // TODO: check whether (r,g,b) components come in the correct order here...
        if (pBmp->HasAlpha())
        {
          uint32 *plBuf = new uint32[image_width];
          for (l = 0; l < image_length; l++)
          {
            for (c = 0; c < image_width; c++)
            {
                // For 32 bit, TIFFLIB wants abgr long word packed...
                plBuf[c] = 
                    ((uint32)(pla[l][c*sizeof(PLPixel32) + PL_RGBA_ALPHA]) << 24) |
                    ((uint32)(pla[l][c*sizeof(PLPixel32) + PL_RGBA_BLUE])  << 16) |
                    ((uint32)(pla[l][c*sizeof(PLPixel32) + PL_RGBA_GREEN]) << 8 ) |
                    ((uint32)(pla[l][c*sizeof(PLPixel32) + PL_RGBA_RED]));
            }
            if(TIFFWriteScanline( tif, plBuf, l, 0 ) < 1) {
                throw PLTextException(PL_ERRINTERNAL, "TIFFWriteScanline failed");
            }
          }
          delete [] plBuf;
        }
        else
        {
          PLBYTE* pBuf = new PLBYTE[3*image_width];
          for (l = 0; l < image_length; l++)
          {
            for (c = 0; c < image_width; c++)
            {
              pBuf[c*3 + 0] = pla[l][c*sizeof(PLPixel32) + PL_RGBA_RED];
              pBuf[c*3 + 1] = pla[l][c*sizeof(PLPixel32) + PL_RGBA_GREEN];
              pBuf[c*3 + 2] = pla[l][c*sizeof(PLPixel32) + PL_RGBA_BLUE];
            }
            if(TIFFWriteScanline( tif, pBuf, l, 0 ) < 1) {
                throw PLTextException(PL_ERRINTERNAL, "TIFFWriteScanline failed");
            }
          }
          delete [] pBuf;
        }
      }
      break;

    default:
      PLASSERT(false);
      throw PLTextException(PL_ERRFORMAT_NOT_SUPPORTED, "unsupported bitsPerPixel");
  }
  // we could flush at this point, but TIFFClose will do it anyway
}
Пример #23
0
void PLWEMFDecoder::GetImage (PLBmpBase & Bmp)
{
	HPALETTE hpal = NULL;
  LPLOGPALETTE plogpal (0);

  if (GetBitsPerPixel() == 8) {
		plogpal = (LPLOGPALETTE)new PLBYTE[sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256)];
		memset(plogpal,0x0,sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*256);
		plogpal->palVersion = 0x300;
		plogpal->palNumEntries = 256;
		if (plogpal == NULL) {
			PLASSERT(false);
			raiseError (PL_ERRNO_MEMORY,"Cannot allocate palette.");
		}
    UINT pe = GetEnhMetaFilePaletteEntries(m_hemf, 0, NULL);
		GetEnhMetaFilePaletteEntries(m_hemf, pe, plogpal->palPalEntry);
	}

	// Setup a logical palette for our memory dc and also a
	// paintlib compatible palette for the paintlib bitmap
  PLPixel32 pPal[256];
	if (plogpal) {
		for (UINT i = 0; i < 256; i++) {
			pPal[i] = *(PLPixel32*)&plogpal->palPalEntry[i];
		}

		if ((hpal = CreatePalette((LPLOGPALETTE)plogpal))) {
			m_holdpal = SelectPalette(m_memdc, hpal, false);
			RealizePalette(m_memdc);
		}
		Bmp.SetPalette(pPal);
		delete [] plogpal;
	}

	// Play the metafile into the device context
	// First, setup a bounding rectangle and fill
	// the memory dc with white (some metafiles only
	// use a black pen to draw and have no actual fill
	// color set, This would cause a black on black
	// painting which is rather useless
	RECT rc;
	rc.left = rc.top = 0;
	rc.bottom = GetHeight();
	rc.right = GetWidth();

	FillRect(m_memdc,&rc,(HBRUSH)GetStockObject(WHITE_BRUSH));

	// Heeere we go....
	BOOL bres = PlayEnhMetaFile(m_memdc,m_hemf,&rc);

	// Finally, convert the Windows bitmap into a paintlib bitmap
	PLWinBmp& winbmp = dynamic_cast<PLWinBmp&>(Bmp);
	BITMAPINFO* pBMI = (BITMAPINFO*)winbmp.GetBMI();
	PLBYTE* pBits = (PLBYTE*)winbmp.GetBits();
	if (GetBitsPerPixel() == 8) {
		GetDIBits(m_dc, m_bm, 0, GetHeight(), winbmp.GetBits(), pBMI, DIB_RGB_COLORS);
	}
	else {
		GetDIBits(m_dc, m_bm, 0, GetHeight(), winbmp.GetBits(), pBMI, DIB_PAL_COLORS);
	}
}
Пример #24
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));
  }
}
Пример #25
0
void PLIFF85Decoder::GetImage(PLBmpBase & Bmp)
{
  Trace(2, "Decoding IFF-85 body.\n");

  if (GetBitsPerPixel() == 8)
  {
    Bmp.SetPalette(&m_pal[0]);
  }

  // Decode each row into local storage, further processing depends on
  // form type.
  const int bytes_per_row = getBytesPerRow();

  std::vector<PLBYTE> buf(bytes_per_row);

  for (int row = 0; row < m_bitmapHeader.h; ++row)
  {
    #if DETAILED_TRACE
      std::ostringstream strTrace;
      strTrace << "#Row " << row << ".\n";
      Trace(3, strTrace.str().c_str());
    #endif

    if (m_bitmapHeader.compression == PLIFF85::cmpByteRun1)
    {
      readCompressedRow(&buf[0], m_pDataSrc, bytes_per_row);
    }
    else
    {
      PLASSERT(m_bitmapHeader.compression == PLIFF85::cmpNone);
      readUncompressedRow(&buf[0], m_pDataSrc, bytes_per_row);
    }

    std::vector<PLBYTE> decodedBuf(m_bitmapHeader.w * GetBitsPerPixel() / 8);

    if (m_formType == PLIFF85::ID_PBM)
    {
      // The number of bytes we want to output may be less than the number
      // we have read in, as the input must have an even number of bytes per
      // plane (which can produce a lot of unnecessary padding for a PBM).
      const int bytes_per_row = m_bitmapHeader.w * GetBitsPerPixel() / 8;
      decodedBuf.assign(buf.begin(), buf.begin() + bytes_per_row);
    }
    else
    {
      PLASSERT(m_formType == PLIFF85::ID_ILBM);

      for (int bp = 0; bp < m_bitmapHeader.nPlanes; ++bp)
      {
        const int start_index = bp * bytes_per_row / m_bitmapHeader.nPlanes;
        for (int i = 0; i < m_bitmapHeader.w; ++i)
        {
          // Get the byte we're interested in.
          PLBYTE the_byte = buf[start_index + i / 8];
          // Isolate the bit we're interested in.
          the_byte &= static_cast<PLBYTE> (1 << (7 - (i % 8)));
          // Now shift the bit to the correct position for this plane.
          if ((7 - (i % 8)) > bp)
          {
            the_byte >>= 7 - (i % 8) - bp;
          }
          else
          {
            the_byte <<= bp - (7 - (i % 8));
          }
          decodedBuf[i] |= the_byte;
        }
      }
    }