/* * usage: ppmview * * displays on the screen a PGM or PPM image (raw mode only). */ #include #include #include #include #define USE_ISPRINTF LPSTR ___isprintfbuf=(char*)_alloca(1024) #define __ (sprintf(___isprintfbuf, #define _ ),___isprintfbuf) typedef struct _imageinfo { int width; int height; BITMAPINFOHEADER* bmihBitmap; unsigned char* data; HWND hWnd; } imageinfo; int windowcount = 0; long WINAPI WndProc( HWND hWnd, WORD message, WORD wParam, LONG lParam ); imageinfo* LoadPPM( LPSTR filename ); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow ) { USE_ISPRINTF; static char szAppName[] = "PPMView"; HWND hWnd; MSG msg; WNDCLASSEX wndclass; char* token; if ( !hPrevInstance ) { wndclass.cbSize = sizeof( WNDCLASSEX ); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = (WNDPROC)WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH ); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; wndclass.hIconSm = NULL; int j = RegisterClassEx( &wndclass ); int k = GetLastError(); } for( token = strtok( lpszCmdParam, " " ); token; token = strtok( NULL, " " ) ) { imageinfo* currimage; if ( *token == 0 ) continue; currimage = LoadPPM( token ); if ( currimage == NULL ) continue; hWnd = CreateWindowEx( 0, szAppName, __ "%s (%d x %d)", token, currimage->width, currimage->height _, WS_OVERLAPPED | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, currimage->width + 2 * GetSystemMetrics( SM_CXFIXEDFRAME ), currimage->height + 2 * GetSystemMetrics( SM_CYFIXEDFRAME ) + GetSystemMetrics( SM_CYCAPTION ), NULL, NULL, hInstance, NULL ); int i = GetLastError(); currimage->hWnd = hWnd; SetWindowLong( hWnd, GWL_USERDATA, (LONG)currimage ); ShowWindow( hWnd, nCmdShow ); UpdateWindow( hWnd ); ++windowcount; } if ( windowcount == 0 ) return 1; while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return msg.wParam; } long WINAPI WndProc( HWND hWnd, WORD message, WORD wParam, LONG lParam ) { HDC hdc; PAINTSTRUCT ps; imageinfo* currimage; switch( message ) { case WM_PAINT: if ( GetUpdateRect( hWnd, NULL, false ) == 0 ) return 0; currimage = (imageinfo*)GetWindowLong( hWnd, GWL_USERDATA ); hdc = BeginPaint( hWnd, &ps ); if ( ps.rcPaint.right > currimage->width ) { FillRect( hdc, &(ps.rcPaint), ( struct HBRUSH__ * ) GetStockObject( GRAY_BRUSH ) ); } SetDIBitsToDevice( hdc, 0, 0, currimage->width, currimage->height, 0, 0, 0, currimage->height, currimage->data, (BITMAPINFO*)(currimage->bmihBitmap), DIB_RGB_COLORS ); EndPaint( hWnd, &ps ); return 0; case WM_DESTROY: currimage = (imageinfo*)GetWindowLong( hWnd, GWL_USERDATA ); free( currimage->bmihBitmap ); --windowcount; if ( windowcount == 0 ) PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, message, wParam, lParam ); } imageinfo* LoadPPM( LPSTR filename ) { USE_ISPRINTF; FILE* f; int i, j; char buffer[80]; int phase = 0; int type; int maxval; imageinfo* currimage = NULL; f = fopen( filename, "rb" ); if ( f == NULL ) return NULL; currimage = (imageinfo*)malloc( sizeof(imageinfo) ); while(phase < 4) { fgets( buffer, 80, f ); if ( buffer[0] == '#' ) continue; switch( phase ) { case 0: j = sscanf( buffer, "P%d %d %d %d\n", &type, &(currimage->width), &(currimage->height), &maxval ); break; case 1: j = sscanf( buffer, "%d %d %d\n", &(currimage->width), &(currimage->height), &maxval ); break; case 2: j = sscanf( buffer, "%d %d\n", &(currimage->height), &maxval ); break; case 3: j = sscanf( buffer, "%d\n", &maxval ); break; case 4: j = 0; break; } phase += j; } OutputDebugString( __ "type is %d; picture is %d x %d; maxval is %d\n", type, currimage->width, currimage->height, maxval _ ); BITMAPINFOHEADER* bmihBitmap = NULL; unsigned char* data; int height = currimage->height; int width = currimage->width; int rowwidth = (width*3) + (((width*3)%4) ? (4-((width*3)%4)) : 0); switch ( type ) { case 5: bmihBitmap = (BITMAPINFOHEADER*)malloc( sizeof(BITMAPINFOHEADER) + rowwidth*height ); data = ((unsigned char *)bmihBitmap) + sizeof(BITMAPINFOHEADER); for ( i = 0; i < height; ++i ) { fread( data + (height-1-i)*rowwidth, 1, width, f ); } for ( i = 0; i < height; ++i ) { for ( j = width-1; j >= 0; --j ) { (data+i*rowwidth)[j*3+2] = (data+i*rowwidth)[j]; (data+i*rowwidth)[j*3+1] = (data+i*rowwidth)[j]; (data+i*rowwidth)[j*3] = (data+i*rowwidth)[j]; } } break; case 6: bmihBitmap = (BITMAPINFOHEADER*)malloc( sizeof(BITMAPINFOHEADER) + rowwidth*height ); data = ((unsigned char *)bmihBitmap) + sizeof(BITMAPINFOHEADER); for ( i = 0; i < height; ++i ) fread( data + (height-1-i)*rowwidth, 1, width * 3, f ); for ( i = 0; i < height; ++i ) for ( j = 0; j < width; ++j ) { int k = (data+i*rowwidth)[j*3]; (data+i*rowwidth)[j*3] = (data+i*rowwidth)[j*3+2]; (data+i*rowwidth)[j*3+2] = k; } break; default: return NULL; } if ( bmihBitmap ) { bmihBitmap->biSize = sizeof( BITMAPINFOHEADER ); bmihBitmap->biWidth = width; bmihBitmap->biHeight = height; bmihBitmap->biPlanes = 1; bmihBitmap->biBitCount = 24; bmihBitmap->biCompression = 0; bmihBitmap->biSizeImage = 0; bmihBitmap->biXPelsPerMeter = 0; bmihBitmap->biYPelsPerMeter = 0; bmihBitmap->biClrUsed = 0; bmihBitmap->biClrImportant = 0; } currimage->data = data; currimage->bmihBitmap = bmihBitmap; fclose( f ); return currimage; }