Tk_PhotoGetImage

Tk library function.

Man page from TCL 8.6

A tk photo is returned using the following structure:

typedef struct {
    unsigned char *pixelPtr; /* the pixel data */
    int width;               /* image width in pixels */
    int height;              /* image height in pixels */
    int pitch;               /* byte offset between image rows in memory */
    int pixelSize;           /* byte count for each pixel */
    int offset[4];           /* array of offsets to get to the red, green, blue and transparent value */
} Tk_PhotoImageBlock;

What is the format of the returned image data

HaO 2018-11-29 (See CLT thread "Tk_PhotoGetImage: whivh block parameter are constant" started 2018-11-28 8:05)

The returned format is currently always:

  • width: image width
  • height: image height
  • pitch: 4 * width
  • pixelSize: 4
  • offset: 0,1,2,3

Example code to put a tk image to a printer device context on MS Windows

HaO 2018-11-29: The following example is derived from the code of "wm icon" in tk8.6.9 win/tkWinWm.c, proc WmIconphotoCmd.

// Paint a photo image to the printer DC
// @param interp tcl interpreter
// @param hDC is a printer device context
// @param oImageName tcl object with tk imsge name
// @param DestPosX Destination X position
// @param DestPosY Destination Y position
// @param DestWidth Width of destination image, or 0 to use original size
// @param DestHeight Height of destination image or 0 to use original size
static int PaintPhoto( Tcl_Interp *interp, HDC hDC, Tcl_Obj *CONST oImageName,
    int DestPosX, int DestPosY, int DestWidth, int DestHeight)
{
    Tk_PhotoImageBlock sImageBlock;
    Tk_PhotoHandle hPhoto;
    HBITMAP hDIB;
    int IndexCur;
    // Access bgraPixel as void ptr or unsigned char ptr
    union {unsigned char *ptr; void *voidPtr;} bgraPixel;
    BITMAPINFO bmInfo;

    // The creation of the DIP is from
    // tk8.6.9 win/tkWinWm.c, proc WmIconphotoCmd
    if ( NULL == (hPhoto = Tk_FindPhoto(interp, Tcl_GetString(oImageName)))) {
        Tcl_SetStringObj( Tcl_GetObjResult(interp), "No photo",-1);
        return TCL_ERROR;
    }
    Tk_PhotoGetImage(hPhoto, &sImageBlock);
    // pixelSize = 4
    // pitch = width * 4
    // offset = 0:0,1:1,2:2,3:3

    // Create device-independant color bitmap.
    ZeroMemory(&bmInfo, sizeof bmInfo);
    bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmInfo.bmiHeader.biWidth = sImageBlock.width;
    bmInfo.bmiHeader.biHeight = -sImageBlock.height;
    bmInfo.bmiHeader.biPlanes = 1;
    bmInfo.bmiHeader.biBitCount = 32;
    bmInfo.bmiHeader.biCompression = BI_RGB;
    
    // the first parameter is the dc, which may be 0.
    // no difference to specify it
    hDIB = CreateDIBSection(NULL, &bmInfo, DIB_RGB_COLORS,
        &bgraPixel.voidPtr, NULL, 0);
    if (!hDIB) {
        Tcl_SetStringObj( Tcl_GetObjResult(interp), "No memory",-1);
        return TCL_ERROR;
    }
    // Convert the photo image data into BGRA format (RGBQUAD).
    for (IndexCur = 0 ;
        IndexCur < sImageBlock.height * sImageBlock.width * 4 ;
        IndexCur += 4)
    {
        bgraPixel.ptr[IndexCur] = sImageBlock.pixelPtr[IndexCur+2];
        bgraPixel.ptr[IndexCur+1] = sImageBlock.pixelPtr[IndexCur+1];
        bgraPixel.ptr[IndexCur+2] = sImageBlock.pixelPtr[IndexCur+0];
        bgraPixel.ptr[IndexCur+3] = sImageBlock.pixelPtr[IndexCur+3];
    }
    // Use original width and height if not given
    if (DestWidth == 0) { DestWidth = sImageBlock.width; }
    if (DestHeight == 0) { DestHeight = sImageBlock.height; }
    // Use StretchDIBits with full image.
    // The printer driver may use additional color info to do better
    // interpolation
    if (GDI_ERROR == StretchDIBits(
        pdlg.hDC,               // handle to DC
        DestPosX,               // x-coord of destination upper-left corner
        DestPosY,               // y-coord of destination upper-left corner
        DestWidth,              // width of destination rectangle
        DestHeight,             // height of destination rectangle
        0,                      // x-coord of source upper-left corner
        0,                      // y-coord of source upper-left corner
        sImageBlock.width,      // width of source rectangle
        sImageBlock.height,     // height of source rectangle
        bgraPixel.voidPtr,      // bitmap bits
        &bmInfo,                // bitmap data
        DIB_RGB_COLORS,         // usage options
        SRCCOPY                 // raster operation code
        ) )
    {
        DeleteObject(hDIB);
        // As this is invoked within the driver, return a driver error
        Tcl_SetStringObj( Tcl_GetObjResult(interp), "Printer driver error",-1);
        return TCL_ERROR;
    }
    DeleteObject(hDIB);
    return TCL_OK;
}