testtoolsconn/stat/desktop/source/lib/src/cstatdataformatconverter.cpp
changeset 0 3da2a79470a7
equal deleted inserted replaced
-1:000000000000 0:3da2a79470a7
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 #include "stdafx.h"
       
    22 #include "afxpriv.h"
       
    23 #include "CSTATDataFormatConverter.h"
       
    24 
       
    25 //-------------------------------------------------------------------------------
       
    26 //standard functions for new variant class
       
    27 CSTATDataFormatConverter::CSTATDataFormatConverter(CSTATLogFile *pLog)
       
    28 : bWriteToFile(true)
       
    29 {
       
    30 	vt = VT_BLOB;
       
    31 	    
       
    32 	BLOB* pBody = new BLOB;
       
    33 	byref = pBody;
       
    34 	pBody->pBlobData = m_index = new BYTE [16];	//16 is the default buffer size
       
    35 	pBody->cbSize = m_bufsize = 16;
       
    36 
       
    37 	// set up logging
       
    38 	pLogFile = pLog;
       
    39 
       
    40 	// reset bitmap structures
       
    41 	memset(&iPbmHeader, 0xff, sizeof(iPbmHeader));
       
    42 	memset(&fileheader, 0xff, sizeof(fileheader));
       
    43 	memset(&bmpHeader, 0xff, sizeof(bmpHeader));
       
    44 	pPbmBits = NULL;
       
    45 	bmpBits = NULL;
       
    46 	lDataSize = 0;
       
    47 }
       
    48 
       
    49 //-------------------------------------------------------------------------------
       
    50 
       
    51 //Destructor
       
    52 CSTATDataFormatConverter::~CSTATDataFormatConverter()
       
    53 {
       
    54 	BLOB* pBody = (BLOB*)byref;
       
    55 	if (pBody)
       
    56 	{
       
    57 		if (pBody->pBlobData) 
       
    58 			delete [] pBody->pBlobData;
       
    59 	
       
    60 		delete pBody;
       
    61 	}
       
    62 
       
    63 	if (pPbmBits)
       
    64 	{
       
    65 		delete [] pPbmBits;
       
    66 		pPbmBits = NULL;
       
    67 	}
       
    68 
       
    69 	if (bmpBits)
       
    70 	{
       
    71 		delete [] bmpBits;
       
    72 		bmpBits = NULL;
       
    73 	}
       
    74 }
       
    75 
       
    76 //----------------------------------------------------------------------------
       
    77 
       
    78 bool CSTATDataFormatConverter::ConvertStringToUnicode(CString& data)
       
    79 {
       
    80 	// clear the existing buffer
       
    81 	((BLOB*)byref)->cbSize = 0;
       
    82 
       
    83 	// length IN BYTES of the UNICODE result (not the TCHAR input)
       
    84 	UINT len = (data.GetLength() + 1) * 2;
       
    85 
       
    86 	// check that the buffer can hold the contents -- otherwise enlarge
       
    87 	EnsureBufSize( len );
       
    88 
       
    89 	// convert the input string to unicode
       
    90 	USES_CONVERSION;
       
    91 	LPWSTR wstr = T2W(data.GetBuffer(0));
       
    92 
       
    93 	// copy data into the buffer and set the size
       
    94 	memcpy( m_index, wstr, len);
       
    95 	((BLOB*)byref)->cbSize = len;
       
    96 
       
    97 	// done
       
    98 	return true;
       
    99 }
       
   100 
       
   101 //----------------------------------------------------------------------------
       
   102 
       
   103 void CSTATDataFormatConverter::EnsureBufSize(int size)
       
   104 {
       
   105 	if (size > m_bufsize)
       
   106 	{
       
   107 		BLOB* pBody = (BLOB*)byref;
       
   108 		BYTE* newbuf = new BYTE [size];
       
   109 		delete[] pBody->pBlobData;
       
   110 		m_index = pBody->pBlobData = newbuf;
       
   111 		m_bufsize = size;
       
   112 	}
       
   113 }
       
   114 
       
   115 //----------------------------------------------------------------------------
       
   116 //Converts from .mbm to .bmp
       
   117 int
       
   118 CSTATDataFormatConverter::ConvertScreenShot(CString &mbmdirectory, CString &destdir)
       
   119 {
       
   120 	CFileFind imagefinder;
       
   121 	CString searchpattern = mbmdirectory;
       
   122 	if (searchpattern.Right(1) != _T('\\'))
       
   123 		searchpattern += _T("\\");
       
   124 	searchpattern += "*.mbm";
       
   125 
       
   126 	// there will only ever be one file to be converted at a time
       
   127 	if (imagefinder.FindFile(searchpattern, 0))
       
   128 	{
       
   129 		imagefinder.FindNextFile();
       
   130 
       
   131 		// get the source filename (in quotes)
       
   132 		CString imagefilename = _T("\"");
       
   133 		imagefilename += imagefinder.GetFilePath();
       
   134 		imagefilename += _T("\"");
       
   135 
       
   136 		// get the destination folder (in quotes)
       
   137 		CString newimagefilename = _T("\"");
       
   138 		newimagefilename += destdir;
       
   139 
       
   140 		// add a backslash if we need one
       
   141 		if (newimagefilename.Right(1) != _T("\\"))
       
   142 			newimagefilename += _T("\\");
       
   143 
       
   144 		// add the filename
       
   145 		newimagefilename += imagefinder.GetFileName();
       
   146 		newimagefilename.Replace(_T(".mbm"), _T(".bmp"));
       
   147 		newimagefilename += _T("\"");
       
   148 		imagefinder.Close();
       
   149 
       
   150 		// remove dest file if it already exists
       
   151 		if(imagefinder.FindFile(newimagefilename, 0))
       
   152 		{
       
   153 			imagefinder.Close();
       
   154 			DeleteFile(newimagefilename);
       
   155 		}
       
   156 
       
   157 		imagefilename.Remove('\"');
       
   158 		newimagefilename.Remove('\"');
       
   159 
       
   160 		if (bWriteToFile)
       
   161 		{
       
   162 			pLogFile->Set(CONVERTINGIMAGE, imagefilename.GetBuffer(0));
       
   163 			pLogFile->Set(TO, newimagefilename.GetBuffer(0));
       
   164 		}
       
   165 		else
       
   166 			pLogFile->Set(READINGIMAGE, imagefilename.GetBuffer(0));
       
   167 
       
   168 		// convert the bitmap
       
   169 		int errorcode = LoadBitmap(imagefilename);
       
   170 		if (errorcode != ITS_OK)
       
   171 			return pLogFile->Set(E_BITMAPLOADFAILED, pLogFile->Text(errorcode));
       
   172 
       
   173 		if ((errorcode = SaveBitmap(newimagefilename)) != ITS_OK)
       
   174 			return pLogFile->Set(E_BITMAPSAVEFAILED, pLogFile->Text(errorcode));
       
   175 
       
   176 		DeleteFile(imagefilename);	//delete original .mbm image
       
   177 
       
   178 		// success
       
   179 		mbmdirectory = newimagefilename;
       
   180 
       
   181 		// log a message that desktop STAT can use to display bitmap
       
   182 		pLogFile->Set(SCREENSHOT_CONVERSION_OK, mbmdirectory, false, true);
       
   183 
       
   184 		return ITS_OK;
       
   185 	}
       
   186 
       
   187 	return pLogFile->Set(E_NOIMAGESTOCONVERT, searchpattern);
       
   188 }
       
   189 
       
   190 //----------------------------------------------------------------------------
       
   191 int CSTATDataFormatConverter::LoadBitmap(CString &file)
       
   192 {
       
   193 	// reset structures
       
   194 	memset(&iPbmHeader, 0xff, sizeof(iPbmHeader));
       
   195 	if (pPbmBits)
       
   196 	{
       
   197 		delete [] pPbmBits;
       
   198 		pPbmBits = NULL;
       
   199 	}
       
   200 
       
   201 	// open file
       
   202 	HANDLE infile;
       
   203 	if (INVALID_HANDLE_VALUE != (infile = CreateFile(file, 
       
   204 										   GENERIC_READ,
       
   205 										   FILE_SHARE_READ, 
       
   206 										   NULL, 
       
   207 										   OPEN_EXISTING,
       
   208 										   FILE_ATTRIBUTE_NORMAL,
       
   209 										   0)))
       
   210 	{
       
   211 		long int iBuffer;
       
   212 		DWORD dwBytesRead = 0;
       
   213 
       
   214 		// read the header to ensure it is a valid file
       
   215 		if (!ReadFile(infile, (LPVOID *)&iBuffer, 4, &dwBytesRead, NULL) ||
       
   216 			dwBytesRead != 4 || iBuffer != KWriteOnceFileStoreUid)
       
   217 		{
       
   218 			CloseHandle(infile);
       
   219 			return E_BADFORMAT;
       
   220 		}
       
   221 
       
   222 		if (!ReadFile(infile, (LPVOID *)&iBuffer, 4, &dwBytesRead, NULL) ||
       
   223 			dwBytesRead != 4 || iBuffer != KMultiBitmapFileImageUid)
       
   224 		{
       
   225 			CloseHandle(infile);
       
   226 			return E_BADFORMAT;
       
   227 		}
       
   228 
       
   229 		if (!ReadFile(infile, (LPVOID *)&iBuffer, 4, &dwBytesRead, NULL) ||
       
   230 			dwBytesRead != 4 || iBuffer != 0)
       
   231 		{
       
   232 			CloseHandle(infile);
       
   233 			return E_BADFORMAT;
       
   234 		}
       
   235 
       
   236 		if (!ReadFile(infile, (LPVOID *)&iBuffer, 4, &dwBytesRead, NULL) ||
       
   237 			dwBytesRead != 4 || iBuffer != KMultiBitmapFileImageChecksum)
       
   238 		{
       
   239 			CloseHandle(infile);
       
   240 			return E_BADFORMAT;
       
   241 		}
       
   242 
       
   243 		if (!ReadFile(infile, (LPVOID *)&iBuffer, 4, &dwBytesRead, NULL) ||
       
   244 			dwBytesRead != 4)
       
   245 		{
       
   246 			CloseHandle(infile);
       
   247 			return E_BADFORMAT;
       
   248 		}
       
   249 
       
   250 		// go back to offset from the beginning
       
   251 		if (SetFilePointer(infile, iBuffer, NULL, FILE_BEGIN) == 0xFFFFFFFF)
       
   252 		{
       
   253 			CloseHandle(infile);
       
   254 			return E_BADFORMAT;
       
   255 		}
       
   256 
       
   257 		// read the number of sources (in our case it will always be one)
       
   258 		if (!ReadFile(infile, (LPVOID *)&iBuffer, 4, &dwBytesRead, NULL) ||
       
   259 			dwBytesRead != 4)
       
   260 		{
       
   261 			CloseHandle(infile);
       
   262 			return E_BADFORMAT;
       
   263 		}
       
   264 
       
   265 		// read offset from the beginning of this bitmap
       
   266 		if (!ReadFile(infile, (LPVOID *)&iBuffer, 4, &dwBytesRead, NULL) ||
       
   267 			dwBytesRead != 4)
       
   268 		{
       
   269 			CloseHandle(infile);
       
   270 			return E_BADFORMAT;
       
   271 		}
       
   272 
       
   273 		// go back to offset from the beginning
       
   274 		if (SetFilePointer(infile, iBuffer, NULL, FILE_BEGIN) == 0xFFFFFFFF)
       
   275 		{
       
   276 			CloseHandle(infile);
       
   277 			return E_BADFORMAT;
       
   278 		}
       
   279 
       
   280 		// read in the header
       
   281 		DWORD dwSize = sizeof(SEpocBitmapHeader);
       
   282 		if (!ReadFile(infile, (LPVOID *)&iPbmHeader, dwSize, &dwBytesRead, NULL) || dwBytesRead != dwSize)
       
   283 		{
       
   284 			CloseHandle(infile);
       
   285 			return E_BADFORMAT;
       
   286 		}
       
   287 
       
   288 		dwSize = iPbmHeader.iBitmapSize - iPbmHeader.iStructSize;
       
   289 
       
   290 		// now read in the bitmap matrix
       
   291 		pPbmBits = new char[dwSize];
       
   292 		if (pPbmBits)
       
   293 		{
       
   294 			memset(pPbmBits, 0xff, dwSize);
       
   295 			if (!ReadFile(infile, (LPVOID *)pPbmBits, dwSize, &dwBytesRead, NULL) || dwBytesRead != dwSize)
       
   296 			{
       
   297 				CloseHandle(infile);
       
   298 				return E_BADFORMAT;
       
   299 			}
       
   300 
       
   301 			if (iPbmHeader.iCompression != ENoBitmapCompression)
       
   302 			{
       
   303 				int byteWidth = ByteWidth(iPbmHeader.iWidthInPixels, iPbmHeader.iBitsPerPixel);
       
   304 				int expandedsize = byteWidth * iPbmHeader.iHeightInPixels;
       
   305 				char* newbits = new char[expandedsize];
       
   306 				if (newbits)
       
   307 				{
       
   308 					memset(newbits,0xff,expandedsize);
       
   309 					int ret = ITS_OK;
       
   310 
       
   311 					switch (iPbmHeader.iCompression)
       
   312 					{
       
   313 						case EByteRLECompression:
       
   314 							ret = ExpandByteRLEData(newbits,expandedsize,pPbmBits, dwSize);
       
   315 							break;
       
   316 						case ETwelveBitRLECompression:
       
   317 							ret = ExpandTwelveBitRLEData(newbits,expandedsize,pPbmBits, dwSize);
       
   318 							break;
       
   319 						case ESixteenBitRLECompression:
       
   320 							ret = ExpandSixteenBitRLEData(newbits,expandedsize,pPbmBits, dwSize);
       
   321 							break;
       
   322 						case ETwentyFourBitRLECompression:
       
   323 							ret = ExpandTwentyFourBitRLEData(newbits,expandedsize,pPbmBits, dwSize);
       
   324 							break;
       
   325 						default:
       
   326 							delete [] pPbmBits;
       
   327 							return E_BADCOMPRESSION;
       
   328 							break;
       
   329 					}
       
   330 
       
   331 					delete [] pPbmBits;
       
   332 					pPbmBits = newbits;
       
   333 					iPbmHeader.iCompression = ENoBitmapCompression;
       
   334 					iPbmHeader.iBitmapSize += expandedsize - dwSize;
       
   335 				}
       
   336 				else
       
   337 				{
       
   338 					CloseHandle(infile);
       
   339 					return E_OUTOFMEM;
       
   340 				}
       
   341 			}
       
   342 
       
   343 			CloseHandle(infile);
       
   344 		}
       
   345 		else
       
   346 		{
       
   347 			CloseHandle(infile);
       
   348 			return E_OUTOFMEM;
       
   349 		}
       
   350 	}
       
   351 	else
       
   352 		return E_FILE_OPEN_READ_FAILED;
       
   353 
       
   354 	return ITS_OK;
       
   355 }
       
   356 
       
   357 bool
       
   358 CSTATDataFormatConverter::ExpandByteRLEData(char* aDest,int aDestSize,char* aSrce,int aSrceSize)
       
   359 {
       
   360 	char* srcelimit=aSrce+aSrceSize;
       
   361 	char* destlimit=aDest+aDestSize;
       
   362 	while(aSrce<srcelimit && aDest<destlimit)
       
   363 		{
       
   364 		char count=*aSrce++;
       
   365 		if (count<0)
       
   366 			{
       
   367 			int runLength=-count;
       
   368 			memcpy(aDest,aSrce,runLength);
       
   369 			aSrce+=runLength;
       
   370 			aDest+=runLength;
       
   371 			}
       
   372 		else
       
   373 			{
       
   374 			char value=*aSrce++;
       
   375 			while(count>=0)
       
   376 				{
       
   377 				*aDest++=value;
       
   378 				count--;
       
   379 				}
       
   380 			}
       
   381 		}
       
   382 	if (aSrce!=srcelimit || aDest!=destlimit)
       
   383 		return false;
       
   384 
       
   385 	return true;
       
   386 }
       
   387 
       
   388 bool
       
   389 CSTATDataFormatConverter::ExpandTwelveBitRLEData(char* aDest,int aDestSizeInBytes,char* aSrce,int aSrceSizeInBytes)
       
   390 {
       
   391 	unsigned short* srcePtr = (unsigned short*)aSrce;
       
   392 	unsigned short* destPtr = (unsigned short*)aDest;
       
   393 	unsigned short* srcePtrLimit = srcePtr + (aSrceSizeInBytes / 2);
       
   394 	unsigned short* destPtrLimit = destPtr + (aDestSizeInBytes / 2);
       
   395 
       
   396 	while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
       
   397 		{
       
   398 		unsigned short value = *srcePtr++;
       
   399 		int runLength = (value >> 12) + 1;
       
   400 		value &= 0x0fff;
       
   401 
       
   402 		for (;runLength > 0;runLength--)
       
   403 			*destPtr++ = value;
       
   404 		}
       
   405 
       
   406 	if (srcePtr != srcePtrLimit || destPtr != destPtrLimit)
       
   407 		return false;
       
   408 
       
   409 	return true;
       
   410 }
       
   411 
       
   412 bool
       
   413 CSTATDataFormatConverter::ExpandSixteenBitRLEData(char* aDest,int aDestSizeInBytes,char* aSrce,int aSrceSizeInBytes)
       
   414 {
       
   415 	char* srcePtrLimit = aSrce + aSrceSizeInBytes;
       
   416 	unsigned short* destPtr = (unsigned short*)aDest;
       
   417 	unsigned short* destPtrLimit = destPtr + (aDestSizeInBytes / 2);
       
   418 
       
   419 	while (aSrce < srcePtrLimit && destPtr < destPtrLimit)
       
   420 		{
       
   421 		int runLength = *aSrce++;
       
   422 
       
   423 		if (runLength >= 0)
       
   424 			{
       
   425 			unsigned short value = *((unsigned short*)(aSrce));
       
   426 			aSrce += 2;
       
   427 			for (runLength++; runLength > 0; runLength--)
       
   428 				*destPtr++ = value;
       
   429 			}
       
   430 		else
       
   431 			{
       
   432 			runLength = -runLength;
       
   433 			int byteLength = runLength * 2;
       
   434 			memcpy(destPtr,aSrce,byteLength);
       
   435 			aSrce += byteLength;
       
   436 			destPtr += runLength;
       
   437 			}
       
   438 		}
       
   439 
       
   440 	if (aSrce != srcePtrLimit || destPtr != destPtrLimit)
       
   441 		return false;
       
   442 
       
   443 	return true;
       
   444 }
       
   445 
       
   446 bool
       
   447 CSTATDataFormatConverter::ExpandTwentyFourBitRLEData(char* aDest,int aDestSizeInBytes,char* aSrce,int aSrceSizeInBytes)
       
   448 {
       
   449 	char* srcePtrLimit = aSrce + aSrceSizeInBytes;
       
   450 	char* destPtrLimit = aDest + aDestSizeInBytes;
       
   451 
       
   452 	while (aSrce < srcePtrLimit && aDest < destPtrLimit)
       
   453 		{
       
   454 		int runLength = *aSrce++;
       
   455 
       
   456 		if (runLength >= 0)
       
   457 			{
       
   458 			char component1 = *aSrce++;
       
   459 			char component2 = *aSrce++;
       
   460 			char component3 = *aSrce++;
       
   461 			for (runLength++; runLength > 0; runLength--)
       
   462 				{
       
   463 				*aDest++ = component1;
       
   464 				*aDest++ = component2;
       
   465 				*aDest++ = component3;
       
   466 				}
       
   467 			}
       
   468 		else
       
   469 			{
       
   470 			runLength = -runLength;
       
   471 			int byteLength = runLength * 3;
       
   472 			memcpy(aDest,aSrce,byteLength);
       
   473 			aSrce += byteLength;
       
   474 			aDest += byteLength;
       
   475 			}
       
   476 		}
       
   477 
       
   478 	if (aSrce != srcePtrLimit || aDest != destPtrLimit)
       
   479 		return false;
       
   480 
       
   481 	return true;
       
   482 }
       
   483 
       
   484 int
       
   485 CSTATDataFormatConverter::SaveBitmap(CString &newfilename)
       
   486 {
       
   487 	// reset structures
       
   488 	memset(&fileheader, 0xff, sizeof(fileheader));
       
   489 	memset(&bmpHeader, 0xff, sizeof(bmpHeader));
       
   490 	if (bmpBits)
       
   491 	{
       
   492 		delete [] bmpBits;
       
   493 		bmpBits = NULL;
       
   494 	}
       
   495 	lDataSize = 0;
       
   496 
       
   497 	// copy header info into BMP structures
       
   498 	bmpHeader.biSize = sizeof(TBitmapInfoHeader);
       
   499 	bmpHeader.biWidth = iPbmHeader.iWidthInPixels;
       
   500 	bmpHeader.biHeight = iPbmHeader.iHeightInPixels;
       
   501 	bmpHeader.biPlanes = 1;
       
   502 	bmpHeader.biBitCount = 24;
       
   503 	bmpHeader.biCompression = 0;
       
   504 	bmpHeader.biSizeImage = 0;
       
   505 	bmpHeader.biXPelsPerMeter = 0;
       
   506 	bmpHeader.biYPelsPerMeter = 0;
       
   507 	bmpHeader.biClrUsed = 0;
       
   508 	bmpHeader.biClrImportant = 0;
       
   509 
       
   510 	long byteWidth = ((bmpHeader.biWidth * 3) + 3) & ~3;
       
   511 	lDataSize = bmpHeader.biHeight * byteWidth;
       
   512 
       
   513 	fileheader.bfType = 'B'+('M'<<8);
       
   514 	fileheader.bfSize = sizeof(TBitmapFileHeader)+sizeof(TBitmapInfoHeader) + lDataSize;
       
   515 	fileheader.bfReserved1 = 0;
       
   516 	fileheader.bfReserved2 = 0;
       
   517 	fileheader.bfOffBits = sizeof(TBitmapFileHeader)+sizeof(TBitmapInfoHeader);
       
   518 
       
   519 	// copy BMP data
       
   520 	bmpBits = new char[lDataSize];
       
   521 	if (!bmpBits)
       
   522 		return E_OUTOFMEM;
       
   523 
       
   524 	memset(bmpBits,0xff,lDataSize);
       
   525 
       
   526 	for(long y=0;y<bmpHeader.biHeight;y++)
       
   527 	{
       
   528 		char* dest=&bmpBits[(bmpHeader.biHeight-y-1)*byteWidth];
       
   529 		for(long x=0;x<bmpHeader.biWidth;x++)
       
   530 		{
       
   531 			TRgb pixel=GetPixel(x,y);
       
   532 			*dest++=pixel.iBlue;
       
   533 			*dest++=pixel.iGreen;
       
   534 			*dest++=pixel.iRed;
       
   535 		}
       
   536 	}
       
   537 
       
   538 	int ret = ITS_OK;
       
   539 	if (bWriteToFile)
       
   540 	{
       
   541 		// write the whole lot out to file
       
   542 		HANDLE infile;
       
   543 		if (INVALID_HANDLE_VALUE != (infile = CreateFile(newfilename, 
       
   544 											   GENERIC_WRITE,
       
   545 											   0, 
       
   546 											   NULL, 
       
   547 											   CREATE_ALWAYS,
       
   548 											   FILE_ATTRIBUTE_NORMAL,
       
   549 											   0)))
       
   550 		{
       
   551 			DWORD dwBytesWritten = 0;
       
   552 
       
   553 			// read the header to ensure it is a valid file
       
   554 			if (WriteFile(infile, (LPVOID *)&fileheader, sizeof(TBitmapFileHeader), &dwBytesWritten, NULL) &&
       
   555 				dwBytesWritten == sizeof(TBitmapFileHeader))
       
   556 			{
       
   557 				// read the header to ensure it is a valid file
       
   558 				if (WriteFile(infile, (LPVOID *)&bmpHeader, sizeof(TBitmapInfoHeader), &dwBytesWritten, NULL) &&
       
   559 					dwBytesWritten == sizeof(TBitmapInfoHeader))
       
   560 				{
       
   561 					if (WriteFile(infile, (LPVOID *)bmpBits, lDataSize, &dwBytesWritten, NULL) &&
       
   562 						dwBytesWritten == lDataSize)
       
   563 					{
       
   564 						ret = ITS_OK;
       
   565 					}
       
   566 					else
       
   567 						ret = E_BADWRITE;
       
   568 				}
       
   569 				else
       
   570 					ret = E_BADWRITE;
       
   571 			}
       
   572 			else
       
   573 				ret = E_BADWRITE;
       
   574 
       
   575 			CloseHandle(infile);
       
   576 		}
       
   577 		else
       
   578 			ret = E_FILE_OPEN_WRITE_FAILED;
       
   579 	}
       
   580 
       
   581 	return ret;
       
   582 }
       
   583 
       
   584 TRgb
       
   585 CSTATDataFormatConverter::GetPixel(int aXCoord,int aYCoord)
       
   586 {
       
   587 	unsigned char col;
       
   588 	aXCoord%=iPbmHeader.iWidthInPixels;
       
   589 	aYCoord%=iPbmHeader.iHeightInPixels;
       
   590 	int byteWidth = ByteWidth(iPbmHeader.iWidthInPixels,iPbmHeader.iBitsPerPixel);
       
   591 	int yOffset = aYCoord * byteWidth;
       
   592 
       
   593 	switch(iPbmHeader.iBitsPerPixel)
       
   594 	{
       
   595 		case 1:
       
   596 			col = pPbmBits[yOffset + (aXCoord / 8)];
       
   597 			col >>= (aXCoord&7);
       
   598 			return TRgb::Gray2(col & 1);
       
   599 		case 2:
       
   600 			col = pPbmBits[yOffset + (aXCoord / 4)];
       
   601 			col = (unsigned char)(col>>(2*(aXCoord%4)));
       
   602 			return TRgb::Gray4(col & 3);
       
   603 		case 4:
       
   604 			col = pPbmBits[yOffset + (aXCoord / 2)];
       
   605 			if (aXCoord & 1)
       
   606 				col >>= 4;
       
   607 			col &= 0xf;
       
   608 			if (iPbmHeader.iColor==EColorBitmap)
       
   609 				return TRgb::Color16(col);
       
   610 			else
       
   611 				return TRgb::Gray16(col);
       
   612 		case 8:
       
   613 			col=pPbmBits[yOffset + aXCoord];
       
   614 			if (iPbmHeader.iColor==EColorBitmap)
       
   615 				return TRgb::Color256(col);
       
   616 			else
       
   617 				return TRgb::Gray256(col);
       
   618 		case 12:
       
   619 		case 16:
       
   620 		{
       
   621 			unsigned short* shortPtr = (unsigned short*)&pPbmBits[yOffset + (aXCoord * 2)];
       
   622 			if (iPbmHeader.iBitsPerPixel == 12)
       
   623 				return TRgb::Color4K(*shortPtr);
       
   624 			else
       
   625 				return TRgb::Color64K(*shortPtr);
       
   626 		}
       
   627 		case 24:
       
   628 		{
       
   629 			char* pixelPtr = pPbmBits + yOffset + (aXCoord * 3);
       
   630 			TRgb pixelColor;
       
   631 			pixelColor.iBlue = *pixelPtr++;
       
   632 			pixelColor.iGreen = *pixelPtr++;
       
   633 			pixelColor.iRed = *pixelPtr;
       
   634 			return pixelColor;
       
   635 		}
       
   636 		default:
       
   637 			return TRgb(0);
       
   638 	}
       
   639 }
       
   640 
       
   641 int
       
   642 CSTATDataFormatConverter::ByteWidth(int aPixelWidth,int aBitsPerPixel)
       
   643 {
       
   644 	int wordWidth = 0;
       
   645 
       
   646 	switch (aBitsPerPixel)
       
   647 	{
       
   648 	case 1:
       
   649 		wordWidth = (aPixelWidth + 31) / 32;
       
   650 		break;
       
   651 	case 2:
       
   652 		wordWidth = (aPixelWidth + 15) / 16;
       
   653 		break;
       
   654 	case 4:
       
   655 		wordWidth = (aPixelWidth + 7) / 8;
       
   656 		break;
       
   657 	case 8:
       
   658 		wordWidth = (aPixelWidth + 3) / 4;
       
   659 		break;
       
   660 	case 12:
       
   661 	case 16:
       
   662 		wordWidth = (aPixelWidth + 1) / 2;
       
   663 		break;
       
   664 	case 24:
       
   665 		wordWidth = (((aPixelWidth * 3) + 11) / 12) * 3;
       
   666 		break;
       
   667 	default:
       
   668 		break;
       
   669 	};
       
   670 
       
   671 	return wordWidth * 4;
       
   672 }
       
   673