// Copyright (C) 2004-5 Alexander R. Pruss
//
#include <PalmOS.h>
#include <VFSMgr.h>
typedef struct {
UInt16 magic;
UInt32 fileSize;
UInt16 res1;
UInt16 res2;
UInt32 offset;
UInt32 infoSize;
Int32 width;
Int32 height;
UInt16 planes;
UInt16 bitsPerPixel;
UInt32 compression;
UInt32 imageSize;
Int32 xRes;
Int32 yRes;
UInt32 nColors;
UInt32 nImpColors;
} BMPHeaderType;
#define BMP_HEADER_LENGTH (14+40)
#define BMP_INFO_LENGTH 40
#define LINES_PER_BUFFER 20
#define SWAP16(x) ( ( (UInt16)(x) << 8 ) | ( (UInt16)(x) >> 8 ) )
#define SWAP32( x ) ( ( ( x ) >> 24 ) | ( ( ( x ) & 0x00FF0000l ) >> 8 ) | ( ( ( x ) & 0x0000FF00l ) << 8 ) | ( ( x ) << 24 ) )
#define SET32( x, y ) { UInt32 value32 = ( y ); ( h->x ) = SWAP32( value32 ); }
#define SET16( x, y ) { UInt32 value16 = ( y ); ( h->x ) = SWAP16( value16 ); }
static void DumpBMP( Char* fname );
void DAStart( void )
{
Char fileName[ 80 ];
DateTimeType dt;
UInt16 len;
TimSecondsToDateTime( TimGetSeconds(), &dt );
DateToAscii( dt.month, dt.day, dt.year, dfYMDLongWithDot, fileName );
len = StrLen( fileName );
fileName[ len ] = '-';
TimeToAscii( dt.hour, dt.minute, tfDot24h, fileName + len + 1 );
len = StrLen( fileName );
fileName[ len++ ] = '.';
fileName[ len++ ] = ( dt.second / 10 ) + '0';
fileName[ len++ ] = ( dt.second % 10 ) + '0';
fileName[ len++ ] = '.';
fileName[ len++ ] = 'b';
fileName[ len++ ] = 'm';
fileName[ len++ ] = 'p';
fileName[ len++ ] = 0;
DumpBMP( fileName );
}
static void MakeBMPHeader( BMPHeaderType* h, Coord maxX, Coord maxY )
{
UInt16 rowLen;
UInt32 imageSize;
rowLen = maxX * 3 + ( maxX % 2 );
MemSet( h, BMP_HEADER_LENGTH, 0 );
h->magic = 'BM';
imageSize = rowLen * maxY + BMP_HEADER_LENGTH;
SET32( fileSize, imageSize + BMP_HEADER_LENGTH );
SET32( offset, BMP_HEADER_LENGTH );
SET32( infoSize, BMP_INFO_LENGTH );
SET32( width, maxX );
SET32( height, maxY );
SET16( planes, 1 );
SET16( bitsPerPixel, 24 );
SET32( imageSize, imageSize );
SET32( xRes, 5669 );
SET32( yRes, 5669 );
}
static void Invert( Coord x, Coord y )
{
RGBColorType c;
WinGetPixelRGB( x, y, &c );
c.r = 255 - c.r;
c.g = 255 - c.g;
c.b = 255 - c.b;
WinSetForeColorRGB( &c, NULL );
WinDrawPixel( x, y );
WinGetPixelRGB( x + 1, y, &c );
c.r = 255 - c.r;
c.g = 255 - c.g;
c.b = 255 - c.b;
WinSetForeColorRGB( &c, NULL );
WinDrawPixel( x + 1, y );
}
static void GetBMPRow( UInt8* row, Coord x0, Coord y0, Coord width, Boolean emit )
{
Coord x;
if ( emit )
for ( x = x0 ; x < x0 + width ; x++ ) {
RGBColorType c;
WinGetPixelRGB( x, y0, &c );
*row++ = c.b;
*row++ = c.g;
*row++ = c.r;
}
Invert( x0, y0 );
}
static UInt16 GetVolRef( void )
{
UInt16 volRefNum;
UInt16 firstVolRefNum = 0xFFFF;
UInt32 volIterator;
volIterator = vfsIteratorStart;
while ( volIterator != vfsIteratorStop ) {
Err err;
VolumeInfoType info;
err = VFSVolumeEnumerate( &volRefNum, &volIterator );
if ( err != errNone )
return firstVolRefNum;
if ( firstVolRefNum == 0xFFFF )
firstVolRefNum = volRefNum;
if ( errNone == VFSVolumeInfo( volRefNum, &info ) &&
( info.mediaType == expMediaType_MemoryStick ||
info.mediaType == 0x49736472 ) ) {
return volRefNum;
}
}
return firstVolRefNum;
}
static void DumpBMP( Char* fname )
{
Coord y;
void* buf;
UInt16 bufLen;
UInt16 lineLen;
FileRef ref;
UInt16 volRef;
UInt16 linesInBuffer;
RectangleType viewRect144;
WinHandle oldW;
volRef = GetVolRef();
if ( volRef == 0xFFFF )
return;
oldW = WinSetDrawWindow( WinGetDisplayWindow() );
WinPushDrawState();
WinSetCoordinateSystem( 144 );
viewRect144.topLeft.x = 0;
viewRect144.topLeft.y = 0;
WinGetDisplayExtent( &viewRect144.extent.x, &viewRect144.extent.y );
lineLen = 3 * viewRect144.extent.x;
while ( lineLen % 4 )
lineLen++;
bufLen = lineLen * LINES_PER_BUFFER;
if ( bufLen < BMP_HEADER_LENGTH )
bufLen = BMP_HEADER_LENGTH;
buf = MemPtrNew( bufLen );
if ( buf == NULL ||
errNone != VFSFileCreate( volRef, fname ) ||
errNone != VFSFileOpen( volRef, fname, vfsModeWrite, &ref ) ) {
if ( buf != NULL )
MemPtrFree( buf );
WinPopDrawState();
return;
}
MakeBMPHeader( buf, viewRect144.extent.x, viewRect144.extent.y );
VFSFileWrite( ref, BMP_HEADER_LENGTH, buf, NULL );
MemSet( buf, bufLen, 0 );
linesInBuffer = 0;
for ( y = viewRect144.topLeft.y + viewRect144.extent.y - 1 ; y >= viewRect144.topLeft.y ; y-- ) {
GetBMPRow( buf + lineLen * linesInBuffer, viewRect144.topLeft.x, y, viewRect144.extent.x, true );
linesInBuffer++;
if ( LINES_PER_BUFFER <= linesInBuffer ) {
VFSFileWrite( ref, lineLen * linesInBuffer, buf, NULL );
linesInBuffer = 0;
}
}
if ( 0 < linesInBuffer )
VFSFileWrite( ref, lineLen * linesInBuffer, buf, NULL );
VFSFileClose( ref );
for ( y = viewRect144.topLeft.y ; y < viewRect144.topLeft.y + viewRect144.extent.y ; y++ ) {
GetBMPRow( buf, viewRect144.topLeft.x, y, viewRect144.extent.x, true );
}
WinPopDrawState();
WinSetDrawWindow( oldW );
MemPtrFree( buf );
}