/** * PDF images are handles as inline, not XObject streams... */ void PDF_PLOTTER::PlotImage( const wxImage & aImage, const wxPoint& aPos, double aScaleFactor ) { wxASSERT( workFile ); wxSize pix_size( aImage.GetWidth(), aImage.GetHeight() ); // Requested size (in IUs) DPOINT drawsize( aScaleFactor * pix_size.x, aScaleFactor * pix_size.y ); // calculate the bitmap start position wxPoint start( aPos.x - drawsize.x / 2, aPos.y + drawsize.y / 2); DPOINT dev_start = userToDeviceCoordinates( start ); /* PDF has an uhm... simplified coordinate system handling. There is *one* operator to do everything (the PS concat equivalent). At least they kept the matrix stack to save restore environments. Also images are always emitted at the origin with a size of 1x1 user units. What we need to do is: 1) save the CTM end estabilish the new one 2) plot the image 3) restore the CTM 4) profit */ fprintf( workFile, "q %g 0 0 %g %g %g cm\n", // Step 1 userToDeviceSize( drawsize.x ), userToDeviceSize( drawsize.y ), dev_start.x, dev_start.y ); /* An inline image is a cross between a dictionary and a stream. A real ugly construct (compared with the elegance of the PDF format). Also it accepts some 'abbreviations', which is stupid since the content stream is usually compressed anyway... */ fprintf( workFile, "BI\n" " /BPC 8\n" " /CS %s\n" " /W %d\n" " /H %d\n" "ID\n", colorMode ? "/RGB" : "/G", pix_size.x, pix_size.y ); /* Here comes the stream (in binary!). I *could* have hex or ascii84 encoded it, but who cares? I'll go through zlib anyway */ for( int y = 0; y < pix_size.y; y++ ) { for( int x = 0; x < pix_size.x; x++ ) { unsigned char r = aImage.GetRed( x, y ) & 0xFF; unsigned char g = aImage.GetGreen( x, y ) & 0xFF; unsigned char b = aImage.GetBlue( x, y ) & 0xFF; // As usual these days, stdio buffering has to suffeeeeerrrr if( colorMode ) { putc( r, workFile ); putc( g, workFile ); putc( b, workFile ); } else { // Grayscale conversion putc( (r + g + b) / 3, workFile ); } } } fputs( "EI Q\n", workFile ); // Finish step 2 and do step 3 }
/** * Postscript-likes at the moment are the only plot engines supporting bitmaps... */ void PS_PLOTTER::PlotImage( const wxImage & aImage, const wxPoint& aPos, double aScaleFactor ) { wxSize pix_size; // size of the bitmap in pixels pix_size.x = aImage.GetWidth(); pix_size.y = aImage.GetHeight(); DPOINT drawsize( aScaleFactor * pix_size.x, aScaleFactor * pix_size.y ); // requested size of image // calculate the bottom left corner position of bitmap wxPoint start = aPos; start.x -= drawsize.x / 2; // left start.y += drawsize.y / 2; // bottom (Y axis reversed) // calculate the top right corner position of bitmap wxPoint end; end.x = start.x + drawsize.x; end.y = start.y - drawsize.y; fprintf( outputFile, "/origstate save def\n" ); fprintf( outputFile, "/pix %d string def\n", pix_size.x ); // Locate lower-left corner of image DPOINT start_dev = userToDeviceCoordinates( start ); fprintf( outputFile, "%g %g translate\n", start_dev.x, start_dev.y ); // Map image size to device DPOINT end_dev = userToDeviceCoordinates( end ); fprintf( outputFile, "%g %g scale\n", std::abs(end_dev.x - start_dev.x), std::abs(end_dev.y - start_dev.y)); // Dimensions of source image (in pixels fprintf( outputFile, "%d %d 8", pix_size.x, pix_size.y ); // Map unit square to source fprintf( outputFile, " [%d 0 0 %d 0 %d]\n", pix_size.x, -pix_size.y , pix_size.y); // include image data in ps file fprintf( outputFile, "{currentfile pix readhexstring pop}\n" ); if( colorMode ) fputs( "false 3 colorimage\n", outputFile ); else fputs( "image\n", outputFile ); // Single data source, 3 colors, Output RGB data (hexadecimal) // (or the same downscaled to gray) int jj = 0; for( int yy = 0; yy < pix_size.y; yy ++ ) { for( int xx = 0; xx < pix_size.x; xx++, jj++ ) { if( jj >= 16 ) { jj = 0; fprintf( outputFile, "\n"); } int red, green, blue; red = aImage.GetRed( xx, yy) & 0xFF; green = aImage.GetGreen( xx, yy) & 0xFF; blue = aImage.GetBlue( xx, yy) & 0xFF; if( colorMode ) fprintf( outputFile, "%2.2X%2.2X%2.2X", red, green, blue ); else fprintf( outputFile, "%2.2X", (red + green + blue) / 3 ); } } fprintf( outputFile, "\n"); fprintf( outputFile, "origstate restore\n" ); }