/* PCX *********************************************************************** * This routine reads file with given file name and if it is valid PCX file it * loads it into given ImageInfo structure in CroTeam true-color format. * (and, if the one exists, loads the palette) */ void CImageInfo::LoadPCX_t( const CTFileName &strFileName) // throw char * { PCXHeader *pPCXHdr; UBYTE *pPCXBuffer, *pPCXImage, *pPCXDecodedImage, *pTmp; UBYTE data, counter; SLONG pic_size, PCX_size, slFileSize; CTFileStream PCXFile; Clear(); // inconvinent way to determine file size PCXFile.Open_t( strFileName, CTStream::OM_READ); slFileSize = PCXFile.GetStreamSize(); // load entire PCX file to memory, as is, and close it (no further usage) pPCXBuffer = (UBYTE*)AllocMemory( slFileSize); PCXFile.Read_t( pPCXBuffer, slFileSize); PCXFile.Close(); // PCX header starts at the begining of the PCX file pPCXHdr = (struct PCXHeader*)pPCXBuffer; // PCX image bytes definition follows up pPCXImage = pPCXBuffer + sizeof( struct PCXHeader); // detremine picture size dimensions ii_Width = (SLONG)(pPCXHdr->Xmax - pPCXHdr->Xmin +1); ii_Height = (SLONG)(pPCXHdr->Ymax - pPCXHdr->Ymin +1); ii_BitsPerPixel = (SLONG)pPCXHdr->Planes*8; pic_size = ii_Width * ii_Height * ii_BitsPerPixel/8; // allocate memory for image content ii_Picture = (UBYTE*)AllocMemory( pic_size); // allocate memory for decoded PCX file that hasn't been converted to CT RAW Image format PCX_size = (SLONG)(pPCXHdr->BytesPerLine * ii_Height * ii_BitsPerPixel/8); pPCXDecodedImage = (UBYTE*)AllocMemory( PCX_size); pTmp = pPCXDecodedImage; // save pointer for latter usage // decode PCX file for( INDEX i=0; i<PCX_size; ) // i is incremented by counter value at the and of the loop { // read one byte from PCX image in memory data = *pPCXImage++; // check byte-run mark if( (data & 0xC0) == 0xC0) { counter = data & 0x3F; // determine repeat value data = *pPCXImage++; // read repeated data // put several bytes of PCX image to decoded image area in memory for( INDEX j=0; j<counter; j++) *pPCXDecodedImage++ = data; } else { // put just one byte from PCX image to decoded image area in memory counter = 1; *pPCXDecodedImage++ = data; } // increment encoded image counter i += counter; } pPCXDecodedImage = pTmp; // reset pointer // convert decoded PCX image to CroTeam RAW Image Info format SLONG slBytesPerPixel = ii_BitsPerPixel/8; for( INDEX y=0; y<ii_Height; y++) { SLONG slYSrcOfs = y * ii_Width * slBytesPerPixel; SLONG slYDstOfs = y * pPCXHdr->BytesPerLine * slBytesPerPixel; // channel looper for( INDEX p=0; p<slBytesPerPixel; p++) { SLONG slPOffset = p * pPCXHdr->BytesPerLine; // byte looper for( INDEX x=0; x<ii_Width; x++) *(ii_Picture + slYSrcOfs + x*slBytesPerPixel + p) = *(pPCXDecodedImage + slYDstOfs + slPOffset + x); } } // free temorary allocated memory for PCX encoded and decoded image FreeMemory( pPCXBuffer); FreeMemory( pPCXDecodedImage); }
void CImageInfo::LoadTGA_t( const CTFileName &strFileName) // throw char * { TGAHeader *pTGAHdr; UBYTE *pTGABuffer, *pTGAImage; SLONG slFileSize; CTFileStream TGAFile; Clear(); // determine file size TGAFile.Open_t( strFileName, CTStream::OM_READ); slFileSize = TGAFile.GetStreamSize(); // load entire TGA file to memory, as is, and close it (no further usage) pTGABuffer = (UBYTE*)AllocMemory( slFileSize); TGAFile.Read_t( pTGABuffer, slFileSize); TGAFile.Close(); // TGA header starts at the begining of the TGA file pTGAHdr = (struct TGAHeader*)pTGABuffer; // TGA image bytes definition follows up pTGAImage = pTGABuffer + sizeof(struct TGAHeader) + pTGAHdr->IdLenght; // detremine picture size dimensions ii_Width = (SLONG)pTGAHdr->Width; ii_Height = (SLONG)pTGAHdr->Height; ii_BitsPerPixel = (SLONG)pTGAHdr->BitsPerPixel; SLONG slBytesPerPixel = ii_BitsPerPixel/8; PIX pixBitmapSize = ii_Width*ii_Height; BOOL bAlphaChannel = (slBytesPerPixel==4); // check for supported file types ASSERT( slBytesPerPixel==3 || slBytesPerPixel==4); if( slBytesPerPixel!=3 && slBytesPerPixel!=4) throw( TRANS("Unsupported BitsPerPixel in TGA format.")); // allocate memory for image content ii_Picture = (UBYTE*)AllocMemory( ii_Width*ii_Height *slBytesPerPixel); UBYTE *pubSrc = pTGAImage; // need 'walking' pointers UBYTE *pubDst = ii_Picture; // determine TGA image type if( pTGAHdr->ImageType==10) { // RLE encoded UBYTE ubControl; INDEX iBlockSize; BOOL bRepeat; PIX pixCurrentSize=0; // loop thru blocks while( pixCurrentSize<pixBitmapSize) { // readout control byte ubControl = *pubSrc++; bRepeat = ubControl&0x80; iBlockSize = (ubControl&0x7F) +1; // repeat or copy color values for( INDEX i=0; i<iBlockSize; i++) { *pubDst++ = pubSrc[0]; *pubDst++ = pubSrc[1]; *pubDst++ = pubSrc[2]; if( bAlphaChannel) *pubDst++ = pubSrc[3]; if( !bRepeat) pubSrc += slBytesPerPixel; } // advance for next block if repeated if( bRepeat) pubSrc += slBytesPerPixel; // update image size pixCurrentSize += iBlockSize; } // mark that image was encoded to ImageInfo buffer pTGAImage = ii_Picture; } // not true-colored? else if( pTGAHdr->ImageType!=2) { // whoops! ASSERTALWAYS("Unsupported TGA format."); throw( TRANS("Unsupported TGA format.")); } // determine image flipping INDEX iFlipType; switch( (pTGAHdr->Descriptor&0x30)>>4) { case 0: iFlipType = 1; break; // vertical flipping case 1: iFlipType = 3; break; // diagonal flipping case 3: iFlipType = 2; break; // horizontal flipping default: iFlipType = 0; break; // no flipping (just copying) } // do flipping FlipBitmap( pTGAImage, ii_Picture, ii_Width, ii_Height, iFlipType, bAlphaChannel); // convert TGA pixel format to CroTeam pubSrc = ii_Picture; // need 'walking' pointer again for( INDEX iPix=0; iPix<pixBitmapSize; iPix++) { // flip bytes Swap( pubSrc[0], pubSrc[2]); // R & B channels pubSrc += slBytesPerPixel; } // free temorary allocated memory for TGA image format FreeMemory( pTGABuffer); }