コード例 #1
0
/**
 * 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
}
コード例 #2
0
/**
 * 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" );
}