//================================================================ // ppmgraph.h // PPM形式で絵を描いてGIFで出力するためのライブラリ // Copyright (C) Naoki Watanabe. 1995-1999. All rights reserved. //================================================================ #include #include #include #include #include //#define PATH_OF_PPMTOGIF "/usr/local/bin/ppmtogif" #define PATH_OF_PPMTOGIF "/usr/X11R6/bin/ppmtogif" //---- Structure for color and a pixel in VRAM. struct Color{ u_char R, G, B; Color( void ){ R = G = B = 0; } Color( u_char _r, u_char _g, u_char _b ){ R = _r; G = _g; B = _b; } }; //---- Class for the memory of the image and associated manipulations. class Vram { u_int width, height; Color* vram; Color color; int pid, pipefds[2]; public: Vram( u_int _width, u_int _height ); ~Vram(); void SetColor( u_char R, u_char G, u_char B ); void DrawPoint( int x, int y ); void DrawLine( int x1, int y1, int x2, int y2 ); void DrawCircle( int xc, int yc, u_int r ); int PastePPM( int xo, int yo, char* fname ); }; //---- Constructor; Fork a ppmtogif process, allocate the memory. Vram::Vram( u_int _width, u_int _height ) : width(_width), height(_height), color(0xff,0xff,0xff) { pipe(pipefds); if( (pid=fork()) == 0 ){ dup2( pipefds[0], 0 ); close(pipefds[1]); close(2); write( 1, "Content-Type: image/gif\n\n", 25 ); execl( PATH_OF_PPMTOGIF, "ppmtogif", 0 ); exit(1); }else{ close(pipefds[0]); } vram = new Color [width*height]; } //---- Destructor; Send the data to the ppmtogif process, release the memory. Vram::~Vram() { char head[32]; int size = sprintf( head, "P6\n%3d %3d\n255\n", width, height ); write( pipefds[1], head, size ); write( pipefds[1], vram, sizeof(Color)*width*height ); close( pipefds[1] ); delete [] vram; waitpid( pid, 0, 0 ); } //---- Change the current drawing color. void Vram::SetColor( u_char R, u_char G, u_char B ) { color = Color(R,G,B); } //---- Draw a dot on the VRAM. void Vram::DrawPoint( int x, int y ) { if( x<0 || (int)width<=x || y<0 || (int)height<=y ) return; vram[y*width+x] = color; } //---- Draw a segment on the VRAM. void Vram::DrawLine( int x1, int y1, int x2, int y2 ) { int dx=x2-x1, dy=y2-y1, sx=1, sy=1; if( dx<0 ){ dx *= -1; sx *= -1; } if( dy<0 ){ dy *= -1; sy *= -1; } DrawPoint( x1, y1 ); if( dx>dy ){ for( int i=dx, de=i/2; i; i-- ){ x1 += sx; de += dy; if( de>dx ){ de -= dx; y1 += sy; } DrawPoint( x1, y1 ); } }else{ for( int i=dy, de=i/2; i; i-- ){ y1 += sy; de += dx; if( de>dy ){ de -= dy; x1 += sx; } DrawPoint( x1, y1 ); } } } //---- Draw a circle on the VRAM. void Vram::DrawCircle( int xc, int yc, u_int r ) { int i=0, j=r, de=1-2*r; while( i<=j ){ DrawPoint( xc+i, yc+j ); DrawPoint( xc-i, yc+j ); DrawPoint( xc+j, yc+i ); DrawPoint( xc-j, yc+i ); DrawPoint( xc+i, yc-j ); DrawPoint( xc-i, yc-j ); DrawPoint( xc+j, yc-i ); DrawPoint( xc-j, yc-i ); if( de<0 ){ de += 4*i+6; i++; }else{ de += 4*(i-j)+10; i++; j--; } } } //---- Paste a ppm file onto the VRAM. int Vram::PastePPM( int xo, int yo, char* fname ) { FILE* fptr; char buf[64]; int dx, dy; if( (fptr = fopen( fname, "r" ))==NULL ) return 1; fgets( buf, 64, fptr ); // read P6 do{ fgets( buf, 64, fptr ); }while( buf[0] =='#' ); // Skip comments sscanf( buf, "%d %d", &dx, &dy ); // read width and height fgets( buf, 64, fptr ); // read maximam bright for( int j=0; j