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); }
void PLDIBSection::internalCreate ( PLLONG Width, PLLONG Height, const PLPixelFormat& pf ) // Create a new empty DIBSection. // Assumes that no memory is allocated before the call. { #ifdef MAX_BITMAP_SIZE if (GetMemNeeded (Width, Height, pf.GetBitsPerPixel()) > MAX_BITMAP_SIZE) throw PLTextException(PL_ERRDIB_TOO_LARGE, "Bitmap size too large.\n"); #endif int MemNeeded = sizeof (BITMAPINFOHEADER); if (pf.GetBitsPerPixel() <= 8) { // Color table exists MemNeeded += (1 << pf.GetBitsPerPixel())*sizeof (RGBQUAD); } m_pBMI = (BITMAPINFOHEADER*) malloc (MemNeeded); // out of memory? if (!m_pBMI) throw (PLTextException (PL_ERRNO_MEMORY, "Out of memory creating bitmap.")); // Fill in the header info. m_pBMI->biSize = sizeof(BITMAPINFOHEADER); m_pBMI->biWidth = Width; m_pBMI->biHeight = Height; m_pBMI->biPlanes = 1; m_pBMI->biBitCount = pf.GetBitsPerPixel(); m_pBMI->biCompression = BI_RGB; // No compression m_pBMI->biSizeImage = 0; m_pBMI->biXPelsPerMeter = 0; m_pBMI->biYPelsPerMeter = 0; m_pBMI->biClrUsed = 0; // Always use the whole palette. m_pBMI->biClrImportant = 0; // Create DIB section in shared memory m_hBitmap = CreateDIBSection (NULL, (BITMAPINFO *)m_pBMI, DIB_RGB_COLORS, (void **)&m_pBits, 0, 0l); if (!m_hBitmap) throw (PLTextException (PL_ERRNO_MEMORY, "Out of memory creating bitmap.")); // Set color table pointer & pointer to bits. initPointers (); initLocals (Width, Height, pf); PLASSERT_VALID (this); }
HANDLE PLDIBSection::createCopyHandle () // Creates a copy of the current bitmap in a global memory block // and returns a handle to this block. { HANDLE hCopy; int MemUsed = GetMemUsed(); hCopy = (HANDLE) ::GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, MemUsed); if (hCopy == NULL) throw (PLTextException (PL_ERRNO_MEMORY, "Out of memory creating bitmap.")); long * lpCopy = (long *) ::GlobalLock((HGLOBAL) hCopy); int BPP = GetBitsPerPixel(); int HeaderMem = sizeof (BITMAPINFOHEADER); if (BPP < 16) { // Color table exists HeaderMem += (1 << BPP)*sizeof (RGBQUAD); } memcpy (lpCopy, m_pBMI, HeaderMem); int BitsMem = GetBitsMemNeeded (GetWidth(), GetHeight(), BPP); memcpy (((PLBYTE *)lpCopy)+HeaderMem, m_pBits, BitsMem); ::GlobalUnlock((HGLOBAL) hCopy); return hCopy; }
void PLFileSink::resizeMapping(size_t theNewSize) { if (m_pDataBuf) { if (munmap(m_pDataBuf, _myMappedSize) != 0) { } m_pDataBuf = 0; _myMappedSize = 0; } if (theNewSize > 0) { if (ftruncate(m_File, theNewSize) != 0) { throw PLTextException(PL_ERRINTERNAL, "error truncating to new size"); } m_pDataBuf = (PLBYTE *) mmap(NULL, theNewSize, PROT_READ|PROT_WRITE, MAP_SHARED, m_File, 0); if (m_pDataBuf == MAP_FAILED) { std::cerr <<"mmap failed, got error "<< strerror(errno)<<std::endl; throw PLTextException(PL_ERRINTERNAL, "mmap failed"); } _myMappedSize = theNewSize; } }
size_t PLDataSink::WriteNBytes ( size_t n, PLBYTE* pData ) { if (m_nCurPos+n > m_nMaxFileSize) throw PLTextException (PL_ERREND_OF_FILE, "Buffer overflow while encoding.\n"); memcpy(m_pStartData + m_nCurPos, pData, n); m_nCurPos += n; return n; }
void PLDIBSection::internalCreate ( BITMAPINFOHEADER* pBMI ) // Creates a PLDIBSection from an existing bitmap pointer. // Assumes that no memory is allocated before the call. { #ifdef MAX_BITMAP_SIZE if (GetMemNeeded (pBMI->biWidth, pBMI->biHeight, pBMI->biBitCount) > MAX_BITMAP_SIZE) throw PLTextException(PL_ERRDIB_TOO_LARGE, "Bitmap size too large.\n"); #endif int MemNeeded = sizeof (BITMAPINFOHEADER); if (pBMI->biBitCount < 16) { // Color table exists MemNeeded += (1 << pBMI->biBitCount)*sizeof (RGBQUAD); } m_pBMI = (BITMAPINFOHEADER *) malloc (MemNeeded); memcpy (m_pBMI, pBMI, MemNeeded); // Create DIB section in shared memory m_hBitmap = CreateDIBSection (NULL, (BITMAPINFO *)m_pBMI, DIB_RGB_COLORS, (void **)&m_pBits, 0, 0l); if (!m_hBitmap) throw (PLTextException (PL_ERRNO_MEMORY, "Out of memory creating bitmap.")); // Set color table pointer & pointer to bits. initPointers (); PLPixelFormat pf = pixelFormatFromBMI(m_pBMI); initLocals (m_pBMI->biWidth, m_pBMI->biHeight, pf); PLASSERT_VALID (this); }
void PLSGIDecoder::GetImage (PLBmpBase & Bmp) { switch (m_Header.Storage) { case STORAGE_VERBATIM: readUncompressed(Bmp); break; case STORAGE_RLE: readRLE(Bmp); break; default: throw PLTextException (PL_ERRFORMAT_NOT_SUPPORTED, "Unknown SGI RGB file compression format."); } }
// 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(); }
void PLSGIDecoder::readHeader ( SGIHeader * pHeader, PLDataSource * pDataSrc ) { pHeader->Magic = ReadMWord (pDataSrc); pHeader->Storage = ReadByte (pDataSrc); pHeader->bpc = ReadByte (pDataSrc); pHeader->Dimension = ReadMWord (pDataSrc); pHeader->XSize = ReadMWord (pDataSrc); pHeader->YSize = ReadMWord (pDataSrc); pHeader->ZSize = ReadMWord (pDataSrc); pHeader->PixMin = ReadMLong (pDataSrc); pHeader->PixMax = ReadMLong (pDataSrc); ReadMLong(pDataSrc); memcpy (pHeader->Name, (char *)pDataSrc->ReadNBytes(80), 80); pHeader->Colormap = ReadMLong (pDataSrc); pDataSrc->Skip(404); if (pHeader->Magic != SGI_MAGIC) { throw PLTextException (PL_ERRWRONG_SIGNATURE, "SGI decoder invoked for non-SGI file."); } }
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 }
PLBYTE* PLMemSink::GetBytes() { if (m_pDataBuf) return m_pDataBuf; else throw PLTextException(PL_ERRINTERNAL, "Open was not called for CMemSink"); }