..::NaΦtenφ a zobrazenφ obrßzku PCX::..

Na www.codeguru.com jsem narazil na komentovan² zdrojov² k≤d pro naΦtenφ souboru typu PCX (╚lßnek Viewing PCX Files). Tady je. Jen jsem p°elo₧il komentß°e a doplnil funkci pro smazßnφ, kterß tam chyb∞la.

Nejd°φv si do svΘ t°φdy pohledu p°idejte deklaraci dvou funkcφ a t°φ prom∞nn²ch. Hodnoty ukazatel∙ nezapome≥te v konstruktoru nastavit na NULL.

public:

void LoadPCX( LPCSTR lpcszFilename );

void DeletePCX();

 

protected:

CSize BitmapSize;

BITMAPINFO *psBmpInfo;

BYTE *pabRawBitmap;

A potΘ definici funkce pro naΦtenφ PCX. (Tento k≤d vy₧aduje vlo₧enφ hlaviΦkovΘho souboru io.h.) Zdrojov² k≤d ned∞lß nic jinΘho ne₧ ₧e p°evede obsah souboru PCX na standartnφ formßt DIBu.

void CMyView::LoadPCX( LPCSTR lpcszFilename )

{

// Standartnφ hlaviΦka PCX

struct PCXHead {

char   ID;

char   Version;

char   Encoding;

char   BitPerPixel;

short  X1;

short  Y1;

short  X2;

short  Y2;

short  HRes;

short VRes;

char   ClrMap[16*3];

char   Reserved1;

char   NumPlanes;

short  BPL;

short  Pal_t;

char   Filler[58];

} sHeader;

 

// Otev°enφ souboru a jeho naΦtenφ do pam∞ti

FILE *pFile = fopen( lpcszFilename, "rb" );

if ( !pFile )

{

MessageBox("Unable to open the PCX file");

return;

}

const long clFileSize = _filelength(_fileno(pFile));

BYTE *pabFileData = (BYTE *)new BYTE[ clFileSize ];

fread( pabFileData, clFileSize, 1, pFile );

fclose( pFile );

 

// Zkopφrujeme si hlaviΦku

memcpy( &sHeader, pabFileData, sizeof(sHeader) );

 

// Ka₧d² Φten² °ßdek MUS═ mφt velikost, kterß jde d∞lit velikostφ datovΘho typu long

int iScanLineSize = sHeader.NumPlanes * sHeader.BPL;

ldiv_t sDivResult = ldiv( iScanLineSize, sizeof(long) );

if ( sDivResult.rem > 0 )

iScanLineSize = (iScanLineSize/sizeof(long)+1) * sizeof(long);

 

// Nastavφme velikost ΦlenskΘ prom∞nnΘ urΦujφcφ velikost bitmapy

BitmapSize = CSize( sHeader.X2-sHeader.X1+1, sHeader.Y2-sHeader.Y1+1 );

const long clImageSize = iScanLineSize * BitmapSize.cy;

 

// Nastavφme informace o bitmap∞

psBmpInfo = (BITMAPINFO *)new BYTE[ sizeof(BITMAPINFOHEADER) +

                                             (sizeof(RGBQUAD)*256) ];

psBmpInfo->bmiHeader.biSize           = sizeof(BITMAPINFOHEADER);

psBmpInfo->bmiHeader.biWidth          = BitmapSize.cx;

psBmpInfo->bmiHeader.biHeight         = -BitmapSize.cy;

psBmpInfo->bmiHeader.biPlanes         = sHeader.NumPlanes;

psBmpInfo->bmiHeader.biBitCount       = sHeader.BitPerPixel;

psBmpInfo->bmiHeader.biCompression    = BI_RGB;

psBmpInfo->bmiHeader.biSizeImage      = 0;

psBmpInfo->bmiHeader.biXPelsPerMeter  = 0;

psBmpInfo->bmiHeader.biYPelsPerMeter  = 0;

psBmpInfo->bmiHeader.biClrUsed        = 0;

psBmpInfo->bmiHeader.biClrImportant   = 0;

 

// P°ipravφme buffer dostateΦn∞ velk² pro ulo₧enφ obrßzku

pabRawBitmap = (BYTE *)new BYTE[ clImageSize ];

if ( !pabRawBitmap )

{

MessageBox( "Nemohu alokovat p∞m∞¥ pro obrßzek" );

delete [] pabFileData;

return;

}

 

// NaΦteme komprimovan² obrßzek

long lDataPos = 0;

long lPos = 128;     // Toto je kde data zaΦφnajφ

 

for ( int iY=0; iY < BitmapSize.cy; iY++ )

{

// Dekomprimujeme Φtenou °ßdku

for ( int iX=0; iX < sHeader.BPL; )

{

UINT uiValue = pabFileData[lPos++];

if ( uiValue > 192 )   // Dva vyÜÜφ bity jsou nastaveny = opakovat

{

uiValue -= 192;                  // Kolikrßt opakovat?

BYTE Color = pabFileData[lPos++];  // Jakß barva?

 

if ( iX <= BitmapSize.cx )

{  // Data obrßzku.  Umφstit do bitmapy.

for ( BYTE bRepeat=0; bRepeat < uiValue; bRepeat++ )

{

pabRawBitmap[lDataPos++] = Color;

iX++;

}

}

else

iX += uiValue; // Mimo obrßzek.  P°eskoΦit.

}

else

{

if ( iX <= BitmapSize.cx )

pabRawBitmap[lDataPos++] = uiValue;

iX++;

}

}

 

// Vyplnit zbytek nulami

if ( iX < iScanLineSize )

{

for ( ;iX < iScanLineSize; iX++ )

pabRawBitmap[lDataPos++] = 0;

}

}

 

if ( pabFileData[lPos++] == 12 )          // Jednoduchß kontrola

// NaΦφst paletu

for ( short Entry=0; Entry < 256; Entry++ )

{

psBmpInfo->bmiColors[Entry].rgbRed       = pabFileData[lPos++];

psBmpInfo->bmiColors[Entry].rgbGreen     = pabFileData[lPos++];

psBmpInfo->bmiColors[Entry].rgbBlue      = pabFileData[lPos++];

psBmpInfo->bmiColors[Entry].rgbReserved  = 0;

}

 

delete [] pabFileData;

}

Te∩ u₧ mßme obrßzek v pam∞ti a m∙₧eme jej zobrazit.

void CMyView::OnDraw(CDC* pDC)

{

if ( pabRawBitmap && psBmpInfo )

// Pokud byl obrßzek nahrßn (ukazatele nejsou NULL) zobrazφme jej pomocφ standartnφ API funkce

SetDIBitsToDevice( *pDC, 0, 0,

BitmapSize.cx, BitmapSize.cy, 0, 0,

0, BitmapSize.cy,

pabRawBitmap, psBmpInfo, DIB_RGB_COLORS);

}

A nakonec jeÜt∞ dopφÜeme funci pro smazßnφ obrßzku z pam∞ti.

void CMyView::DeletePCX()

{

// Smazßnφ obrßzku se provede jednoduch²m smazßnφm pam∞ti.

if (pabRawBitmap) delete[] pabRawBitmap;

if (psBmpInfo) delete[] psBmpInfo;

pabRawBitmap = NULL;

psBmpInfo = NULL;

}