Пример #1
0
void
camltk_setimgdata_native (value imgname, value pixmap, value x, value y, 
		   value w, value h) /* ML */
{
  Tk_PhotoHandle ph;
  Tk_PhotoImageBlock pib;
  int code;

#if (TK_MAJOR_VERSION < 8)
  if (NULL == (ph = Tk_FindPhoto(String_val(imgname)))) 
    tk_error("no such image");
#else
  if (NULL == (ph = Tk_FindPhoto(cltclinterp, String_val(imgname)))) 
    tk_error("no such image");
#endif

  pib.pixelPtr = String_val(pixmap);
  pib.width = Int_val(w);
  pib.height = Int_val(h);
  pib.pitch = pib.width * 3;
  pib.pixelSize = 3;
  pib.offset[0] = 0;
  pib.offset[1] = 1;
  pib.offset[2] = 2;
  Tk_PhotoPutBlock(
#if (TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION >= 5 || TK_MAJOR_VERSION > 8)
        NULL,
#endif
ph,&pib,Int_val(x),Int_val(y),Int_val(w),Int_val(h)
#if (TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION >= 4 || TK_MAJOR_VERSION > 8)
                   , TK_PHOTO_COMPOSITE_SET
#endif
    );
}
Пример #2
0
/*
 *---------------------------------------------------------------------------
 *
 * photoputblock --
 *
 *     This is a wrapper around Tk_PhotoPutBlock(). In tk 8.5, the 'interp'
 *     argument was added to the Tk_PhotoPutBlock() signature. This
 *     function deals with this API change.
 *
 *     Later: The trick is to define USE_COMPOSITELESS_PHOTO_PUT_BLOCK,
 *     which is now done in html.h.
 *
 * Results:
 *     None.
 *
 * Side effects:
 *     None.
 *
 *---------------------------------------------------------------------------
 */
static void 
photoputblock(
    Tcl_Interp *interp,
    Tk_PhotoHandle handle,
    Tk_PhotoImageBlock *blockPtr,
    int x,
    int y,
    int width,
    int height,
    int compRule
    )
{
    Tk_PhotoPutBlock(handle, blockPtr, x, y, width, height);
}
Пример #3
0
static int
PyAggImagePhoto(ClientData clientdata, Tcl_Interp* interp,
               int argc, char **argv)
{
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;
    PyObject* aggo;

    // vars for blitting
    PyObject* bboxo;
    Bbox* bbox;
    agg::int8u *destbuffer;
    double l,b,r,t;
    int destx, desty, destwidth, destheight, deststride;

    long mode;
    long nval;
    if (argc != 5) {
        Tcl_AppendResult(interp, "usage: ", argv[0],
                         " destPhoto srcImage", (char *) NULL);
        return TCL_ERROR;
    }

    /* get Tcl PhotoImage handle */
    photo = Tk_FindPhoto(interp, argv[1]);
    if (photo == NULL) {
        Tcl_AppendResult(interp, "destination photo must exist", (char *) NULL);
        return TCL_ERROR;
    }
    /* get array (or object that can be converted to array) pointer */
    aggo = (PyObject*)atol(argv[2]);
    RendererAgg *aggRenderer = (RendererAgg *)aggo;
    int srcheight = (int)aggRenderer->get_height();

    /* XXX insert aggRenderer type check */

    /* get array mode (0=mono, 1=rgb, 2=rgba) */
    mode = atol(argv[3]);
    if ((mode != 0) && (mode != 1) && (mode != 2)) {
        Tcl_AppendResult(interp, "illegal image mode", (char *) NULL);
        return TCL_ERROR;
    }

    /* check for bbox/blitting */
    bboxo = (PyObject*)atol(argv[4]);
    if (bboxo != Py_None) {
      bbox = (Bbox*)bboxo;
      l = bbox->ll_api()->x_api()->val();
      b = bbox->ll_api()->y_api()->val();
      r = bbox->ur_api()->x_api()->val();
      t = bbox->ur_api()->y_api()->val();

      destx = (int)l;
      desty = srcheight-(int)t;
      destwidth = (int)(r-l);
      destheight = (int)(t-b);
      deststride = 4*destwidth;

      destbuffer = new agg::int8u[deststride*destheight];
      if (destbuffer == NULL) {
	throw Py::MemoryError("_tkagg could not allocate memory for destbuffer");
      }

      agg::rendering_buffer destrbuf;
      destrbuf.attach(destbuffer, destwidth, destheight, deststride);
      pixfmt destpf(destrbuf);
      renderer_base destrb(destpf);

      agg::rect_base<int> region(destx, desty, (int)r, srcheight-(int)b);
      destrb.copy_from(*aggRenderer->renderingBuffer, &region,
		       -destx, -desty);
    } else {
      bbox = NULL;
      destbuffer = NULL;
      destx = desty = destwidth = destheight = deststride = 0;
    }

    /* setup tkblock */
    block.pixelSize = 1;
    if (mode == 0) {
        block.offset[0]= block.offset[1] = block.offset[2] =0;
        nval = 1;
    } else {
        block.offset[0] = 0;
        block.offset[1] = 1;
        block.offset[2] = 2;
        if (mode == 1) {
            block.offset[3] = 0;
            block.pixelSize = 3;
            nval = 3;
        } else {
            block.offset[3] = 3;
            block.pixelSize = 4;
            nval = 4;
        }
    }

    if (bbox) {

      block.width  = destwidth;
      block.height = destheight;
      block.pitch = deststride;
      block.pixelPtr = destbuffer;

      Tk_PhotoPutBlock(photo, &block, destx, desty, destwidth, destheight);
      delete [] destbuffer;

    } else {
      block.width  = aggRenderer->get_width();
      block.height = aggRenderer->get_height();
      block.pitch = block.width * nval;
      block.pixelPtr =  aggRenderer->pixBuffer;

      /* Clear current contents */
      Tk_PhotoBlank(photo);
      /* Copy opaque block to photo image, and leave the rest to TK */
      Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height);
    }

    return TCL_OK;
}
Пример #4
0
static int
PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
               int argc, char **argv)
{
    Imaging im;
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;

    if (argc != 3) {
        Tcl_AppendResult(interp, "usage: ", argv[0],
                         " destPhoto srcImage", (char *) NULL);
        return TCL_ERROR;
    }

    /* get Tcl PhotoImage handle */
    photo = Tk_FindPhoto(interp, argv[1]);
    if (photo == NULL) {
        Tcl_AppendResult(
            interp, "destination photo must exist", (char *) NULL
            );
        return TCL_ERROR;
    }

    /* get PIL Image handle */
    im = ImagingFind(argv[2]);
    if (!im) {
	Tcl_AppendResult(interp, "bad name", (char*) NULL);
	return TCL_ERROR;
    }
    if (!im->block) {
	Tcl_AppendResult(interp, "bad display memory", (char*) NULL);
	return TCL_ERROR;
    }

    /* Active region */
#if 0
    if (src_xoffset + xsize > im->xsize)
	xsize = im->xsize - src_xoffset;
    if (src_yoffset + ysize > im->ysize)
	ysize = im->ysize - src_yoffset;
    if (xsize < 0 || ysize < 0
	|| src_xoffset >= im->xsize
	|| src_yoffset >= im->ysize)
	return TCL_OK;
#endif

    /* Mode */

    if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
	block.pixelSize = 1;
	block.offset[0] = block.offset[1] = block.offset[2] = 0;
    } else if (strncmp(im->mode, "RGB", 3) == 0) {
	block.pixelSize = 4;
	block.offset[0] = 0;
	block.offset[1] = 1;
	block.offset[2] = 2;
        if (strcmp(im->mode, "RGBA") == 0)
            block.offset[3] = 3; /* alpha (or reserved, under 8.2) */
        else
            block.offset[3] = 0; /* no alpha */
    } else {
        Tcl_AppendResult(interp, "Bad mode", (char*) NULL);
	return TCL_ERROR;
    }

    block.width = im->xsize;
    block.height = im->ysize;
    block.pitch = im->linesize;
    block.pixelPtr = (unsigned char*) im->block;
#if 0
    block.pixelPtr = (unsigned char*) im->block +
	             src_yoffset * im->linesize +
	             src_xoffset * im->pixelsize;
#endif

#if TK < 84 /* < 8.4.0 */
    if (strcmp(im->mode, "RGBA") == 0) {
        /* Copy non-transparent pixels to photo image */
        int x, y;
        Tk_PhotoImageBlock run;

        /* Clear current contents */
        Tk_PhotoBlank(photo);

        /* Setup run descriptor */
        run.height = 1;
        run.pitch = block.pitch;
        run.pixelSize = block.pixelSize;
        run.offset[0] = 0;
        run.offset[1] = 1;
        run.offset[2] = 2;
	run.offset[3] = 0; /* no alpha (or reserved, under 8.2) */

        /* Copy opaque runs to photo image */
        for (y = 0; y < block.height; y++) {
            unsigned char* p = block.pixelPtr + y*block.pitch;
            unsigned char* s = p;
            int   w = 0;
            for (x = 0; x < block.width; x++) {
                if (p[3]) {
                    /* opaque: add pixel to current run */
                    if (w == 0)
                        s = p;
                    w = w + 1;
                } else if (s) {
                    /* copy run to photo image */
                    if (w > 0) {
                        run.width = w;
                        run.pixelPtr = s;
                        Tk_PhotoPutBlock(photo, &run, x-w, y, run.width, 1);
                    }
                    w = 0;
                }
                p += block.pixelSize;
            }
            if (w > 0) {
                /* copy final run, if any */
                run.width = w;
                run.pixelPtr = s;
                Tk_PhotoPutBlock(photo, &run, x-w, y, run.width, 1);
          }
        }

    } else

        /* Copy opaque block to photo image, and leave the rest to TK */
        Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height);

#else /* Tk 8.4 and newer */
#if TK < 85 /* Tk 8.4 */
    Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height,
                     TK_PHOTO_COMPOSITE_SET);
    if (strcmp(im->mode, "RGBA") == 0)
        /* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */
        /* (fixed in Tk 8.5a3) */
        Tk_PhotoSetSize(photo, block.width, block.height);
#else /* Tk 8.5 */
    Tk_PhotoPutBlock(interp, photo, &block, 0, 0, block.width, block.height,
                     TK_PHOTO_COMPOSITE_SET);
#endif
#endif

    return TCL_OK;
}
Пример #5
0
int FileReadTIF(Tcl_Interp *interp,
		Tcl_Channel chan,
		CONST char *fileName,
		Tcl_Obj *format,
		Tk_PhotoHandle imageHandle,
		int destX, int destY,
		int width, int height,
		int srcX, int srcY)
{
    int nBytes, h;
    int nLines;                   /* actual number of scan lines read
                                   * for each image block pointed at
                                   * by pixelPtr */
    int nDefBlockLines;           /* default number of scan lines to be read
                                   * for each image block pointed at
                                   * by pixelPtr */
    unsigned char *pixelPtr;
    Tk_PhotoImageBlock block;
    unsigned long fileImgHeight, fileImgWidth;
    unsigned short bitspersample;
    unsigned short photometrictype;

    short n;
    unsigned long row;
    unsigned long startrow;
    unsigned long pixelPtrIndex;
    TIFF *tif;
    TIFFErrorHandler prev_handler; /* Current TIFF error handler  */
    static TIFFErrorHandler temp_handler = tkTIFFErrorHandler;
                                   /* Temporary TIFF error handler
                                      (is used to avoid output of
                                       libtiff error messages to stderr) */

    prev_handler = TIFFSetErrorHandler(temp_handler);

    tif = TIFFOpen(fileName, "r");
    if (tif == NULL) {
        printf("FileReadTIF: Problem reading TIF file !");
	Tcl_AppendResult(interp, "couldn't read TIF header from file \"",
		fileName, "\"", NULL);
        TIFFSetErrorHandler(prev_handler);
        return TCL_ERROR;
    }

    /* test entry !!! */
    /*
    printf("\nFileReadTIF: file name     = %s", fileName);
    printf("\nFileReadTIF: height        = %d", height);
    printf("\nFileReadTIF: width         = %d", width);
    */
    /* obtain dimensions of (first) image in TIFF file */
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &fileImgHeight);
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &fileImgWidth);
    /* test entry !!! */
    /*
     printf("\nFileReadTIF: image height  = %d", fileImgHeight);
     printf("\nFileReadTIF: image width   = %d\n", fileImgWidth);
    */


    if ((fileImgWidth <= 0) || (fileImgHeight <= 0)) {
	Tcl_AppendResult(interp, "TIF image file \"", fileName,
		"\" has dimension(s) <= 0", (char *) NULL);
	return TCL_ERROR;
    }

    if ((srcX + width) > (int)fileImgWidth) {
	width = fileImgWidth - srcX;
    }
    if ((srcY + height) > (int)fileImgHeight) {
	height = fileImgHeight - srcY;
    }
    if ((width <= 0) || (height <= 0)
	|| (srcX >= (int)fileImgWidth) || (srcY >= (int)fileImgHeight)) {
	return TCL_OK;
    }


    /*
       determine type of TIFF image: PhotometricInterpretation
       WhiteIsZero       => 0 (bw or grayscale image)
       BlackIsZero       => 1 (bw or grayscale image)
       RGB Model         => 2 (RGB full color model)
       Color Palette     => 3
       Transparency Mask => 4
    */
    TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometrictype);
    /* test entry !!! */
    if ((photometrictype == 0) || (photometrictype == 1) || (photometrictype == 3)) {
        /*
           bw or grayscale image
        */
        TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
        /* test entry !!! */
	/*
        printf("\nFileReadTIF: bits / sample = %d", bitspersample);
	*/
        block.pixelSize = 1;
        block.offset[0] = 0;
        block.offset[1] = 0;
        block.offset[2] = 0;
    } else if (photometrictype == 2) {
        /*
           RGB full color image

           note: - bitspersample is always = 8
                 - there is no color map
        */
        block.pixelSize = 3;
        block.offset[0] = 0;
        block.offset[1] = 1;
        block.offset[2] = 2;
    } else {
        Tcl_AppendResult(interp, "photometric interpretation >2 ",
            "(palette color and transparency mask) ",
            "not yet supported", NULL);
        TIFFSetErrorHandler(prev_handler);
        return TCL_ERROR;
    }

    /* block.width = width; */
    height = fileImgHeight;
    width = fileImgWidth;
    block.width = fileImgWidth;
    block.pitch = block.pixelSize * fileImgWidth;
    /* test entry !!! */
    /*
    printf("\nFileReadTIF: height        = %d", height);
    printf("\nFileReadTIF: width         = %d", width);
    printf("\nFileReadTIF: fileImgWidth         = %d", fileImgWidth);
    */
    /* the following two values should be identical */
    /*
    printf("\nFileReadTIF: block.pitch     = %d", block.pitch);
    printf("\nFileReadTIF: block.pixelSize = %d", block.pixelSize);
    printf("\nFileReadTIF: scanline size   = %d", TIFFScanlineSize(tif));
    */
    Tk_PhotoExpand(imageHandle, destX + width, destY + height);

    /*
    if (srcY > 0) {
	fseek(f, (long) (srcY * block.pitch), SEEK_CUR);
    }
    */

    nDefBlockLines = (MAX_MEMORY + block.pitch - 1) / block.pitch;
    nLines = nDefBlockLines;
    nLines = height;
    if (nLines > height) {
        nLines = height;
    }
    if (nLines <= 0) {
        nLines = 1;
    }

    /* determine the required buffer size by calling TIFFScanlineSize */
    nBytes = nLines * block.pitch;
    /*
    printf("\nFileReadTIF: nLines        = %d", nLines);
    printf("\nFileReadTIF: nBytes        = %d", nBytes);
    */
    pixelPtr = (unsigned char *) ckalloc((unsigned)nBytes);
    block.pixelPtr = pixelPtr + srcX * block.pixelSize;

    n = 0;
    for (h = height; h > 0; h -= nLines) {
        n++;
        startrow = (n-1) * nLines;
        if (nLines > h) {
            nLines = h;
            nBytes = nLines * block.pitch;
        }
        for (row = startrow; row < (startrow + nLines); row++) {
            /* read the data for the spezified row into the buffer */
            pixelPtrIndex = row*block.pitch - (n-1)*nDefBlockLines*block.pitch;
            /* test entry !!! */
            /* printf("\nFileReadTIF: pixelPtr_Indx = %d", pixelPtrIndex); */
            TIFFReadScanline(tif, &(pixelPtr[pixelPtrIndex]), row, 1);
        }
	block.height = nLines;

	Tk_PhotoPutBlock(imageHandle, &block, destX, destY, width, nLines, TK_PHOTO_COMPOSITE_SET);
	destY += nLines;
    }


    ckfree((char *) pixelPtr);

    TIFFClose(tif);
    /* test entry !!! */
    /*
    printf("\nFileReadTIF: TIF file closed !");
    */
    TIFFSetErrorHandler(prev_handler);

    return TCL_OK;



}
Пример #6
0
static int PyAggImagePhoto(ClientData clientdata, Tcl_Interp *interp, int argc, char **argv)
{
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;
    PyObject *aggo;

    // vars for blitting
    PyObject *bboxo;

    size_t aggl, bboxl;
    bool has_bbox;
    agg::int8u *destbuffer;
    int destx, desty, destwidth, destheight, deststride;
    //unsigned long tmp_ptr;

    long mode;
    long nval;
    if (Tk_MainWindow(interp) == NULL) {
        // Will throw a _tkinter.TclError with "this isn't a Tk application"
        return TCL_ERROR;
    }

    if (argc != 5) {
        Tcl_AppendResult(interp, "usage: ", argv[0], " destPhoto srcImage", (char *)NULL);
        return TCL_ERROR;
    }

    /* get Tcl PhotoImage handle */
    photo = Tk_FindPhoto(interp, argv[1]);
    if (photo == NULL) {
        Tcl_AppendResult(interp, "destination photo must exist", (char *)NULL);
        return TCL_ERROR;
    }
    /* get array (or object that can be converted to array) pointer */
    if (sscanf(argv[2], SIZE_T_FORMAT, &aggl) != 1) {
        Tcl_AppendResult(interp, "error casting pointer", (char *)NULL);
        return TCL_ERROR;
    }
    aggo = (PyObject *)aggl;

    // TODO: This is really brittle and will break when RendererAgg
    // comes in multiple flavors
    RendererAgg *aggRenderer = ((PyRendererAgg *)(aggo))->x;
    int srcheight = (int)aggRenderer->get_height();

    /* XXX insert aggRenderer type check */

    /* get array mode (0=mono, 1=rgb, 2=rgba) */
    mode = atol(argv[3]);
    if ((mode != 0) && (mode != 1) && (mode != 2)) {
        Tcl_AppendResult(interp, "illegal image mode", (char *)NULL);
        return TCL_ERROR;
    }

    /* check for bbox/blitting */
    if (sscanf(argv[4], SIZE_T_FORMAT, &bboxl) != 1) {
        Tcl_AppendResult(interp, "error casting pointer", (char *)NULL);
        return TCL_ERROR;
    }
    bboxo = (PyObject *)bboxl;

    if (bboxo != NULL && bboxo != Py_None) {
        agg::rect_d rect;
        if (!convert_rect(bboxo, &rect)) {
            return TCL_ERROR;
        }

        has_bbox = true;

        destx = (int)rect.x1;
        desty = srcheight - (int)rect.y2;
        destwidth = (int)(rect.x2 - rect.x1);
        destheight = (int)(rect.y2 - rect.y1);
        deststride = 4 * destwidth;

        destbuffer = new agg::int8u[deststride * destheight];
        if (destbuffer == NULL) {
            Tcl_AppendResult(interp, "could not allocate memory", (char *)NULL);
            return TCL_ERROR;
        }

        agg::rendering_buffer destrbuf;
        destrbuf.attach(destbuffer, destwidth, destheight, deststride);
        pixfmt destpf(destrbuf);
        renderer_base destrb(destpf);

        agg::rect_base<int> region(destx, desty, (int)rect.x2, srcheight - (int)rect.y1);
        destrb.copy_from(aggRenderer->renderingBuffer, &region, -destx, -desty);
    } else {
        has_bbox = false;
        destbuffer = NULL;
        destx = desty = destwidth = destheight = deststride = 0;
    }

    /* setup tkblock */
    block.pixelSize = 1;
    if (mode == 0) {
        block.offset[0] = block.offset[1] = block.offset[2] = 0;
        nval = 1;
    } else {
        block.offset[0] = 0;
        block.offset[1] = 1;
        block.offset[2] = 2;
        if (mode == 1) {
            block.offset[3] = 0;
            block.pixelSize = 3;
            nval = 3;
        } else {
            block.offset[3] = 3;
            block.pixelSize = 4;
            nval = 4;
        }
    }

    if (has_bbox) {
        block.width = destwidth;
        block.height = destheight;
        block.pitch = deststride;
        block.pixelPtr = destbuffer;

        Tk_PhotoPutBlock(photo, &block, destx, desty, destwidth, destheight);
        delete[] destbuffer;

    } else {
        block.width = aggRenderer->get_width();
        block.height = aggRenderer->get_height();
        block.pitch = (int)block.width * nval;
        block.pixelPtr = aggRenderer->pixBuffer;

        /* Clear current contents */
        Tk_PhotoBlank(photo);
        /* Copy opaque block to photo image, and leave the rest to TK */
        Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height);
    }

    return TCL_OK;
}
Пример #7
0
static int
RasterizeSVG(
    Tcl_Interp *interp,
    Tk_PhotoHandle imageHandle,
    NSVGimage *nsvgImage,
    int destX, int destY,
    int width, int height,
    int srcX, int srcY,
    RastOpts *ropts)
{
    int w, h, c;
    NSVGrasterizer *rast;
    unsigned char *imgData;
    Tk_PhotoImageBlock svgblock;

    w = (int) ceil(nsvgImage->width * ropts->scale);
    h = (int) ceil(nsvgImage->height * ropts->scale);
    rast = nsvgCreateRasterizer();
    if (rast == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot initialize rasterizer", -1));
	Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "RASTERIZER_ERROR",
		NULL);
	goto cleanAST;
    }
    imgData = attemptckalloc(w * h *4);
    if (imgData == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot alloc image buffer", -1));
	Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "OUT_OF_MEMORY", NULL);
	goto cleanRAST;
    }
    nsvgRasterize(rast, nsvgImage, (float) ropts->x, (float) ropts->y,
	    (float) ropts->scale, imgData, w, h, w * 4);
    /* transfer the data to a photo block */
    svgblock.pixelPtr = imgData;
    svgblock.width = w;
    svgblock.height = h;
    svgblock.pitch = w * 4;
    svgblock.pixelSize = 4;
    for (c = 0; c <= 3; c++) {
	svgblock.offset[c] = c;
    }
    if (Tk_PhotoExpand(interp, imageHandle,
		destX + width, destY + height) != TCL_OK) {
	goto cleanRAST;
    }
    if (Tk_PhotoPutBlock(interp, imageHandle, &svgblock, destX, destY,
		width, height, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {
	goto cleanimg;
    }
    ckfree(imgData);
    nsvgDeleteRasterizer(rast);
    nsvgDelete(nsvgImage);
    return TCL_OK;

cleanimg:
    ckfree(imgData);

cleanRAST:
    nsvgDeleteRasterizer(rast);

cleanAST:
    nsvgDelete(nsvgImage);
    return TCL_ERROR;
}
static int
PyAggImagePhoto(ClientData clientdata, Tcl_Interp* interp,
                int argc, char **argv)
{
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;
    PyObject* aggo;

    // vars for blitting
    PyObject* bboxo;

    unsigned long aggl, bboxl;
    bool has_bbox;
    agg::int8u *destbuffer;
    double l, b, r, t;
    int destx, desty, destwidth, destheight, deststride;
    //unsigned long tmp_ptr;

    long mode;
    long nval;
    if (Tk_MainWindow(interp) == NULL)
    {
        // Will throw a _tkinter.TclError with "this isn't a Tk application"
        return TCL_ERROR;
    }

    if (argc != 5)
    {
        Tcl_AppendResult(interp, "usage: ", argv[0],
                         " destPhoto srcImage", (char *) NULL);
        return TCL_ERROR;
    }

    /* get Tcl PhotoImage handle */
    photo = Tk_FindPhoto(interp, argv[1]);
    if (photo == NULL)
    {
        Tcl_AppendResult(interp, "destination photo must exist", (char *) NULL);
        return TCL_ERROR;
    }
    /* get array (or object that can be converted to array) pointer */
    if (sscanf(argv[2], "%lu", &aggl) != 1)
    {
        Tcl_AppendResult(interp, "error casting pointer", (char *) NULL);
        return TCL_ERROR;
    }
    aggo = (PyObject*)aggl;
    //aggo = (PyObject*)atol(argv[2]);

    //std::stringstream agg_ptr_ss;
    //agg_ptr_ss.str(argv[2]);
    //agg_ptr_ss >> tmp_ptr;
    //aggo = (PyObject*)tmp_ptr;
    RendererAgg *aggRenderer = (RendererAgg *)aggo;
    int srcheight = (int)aggRenderer->get_height();

    /* XXX insert aggRenderer type check */

    /* get array mode (0=mono, 1=rgb, 2=rgba) */
    mode = atol(argv[3]);
    if ((mode != 0) && (mode != 1) && (mode != 2))
    {
        Tcl_AppendResult(interp, "illegal image mode", (char *) NULL);
        return TCL_ERROR;
    }

    /* check for bbox/blitting */
    if (sscanf(argv[4], "%lu", &bboxl) != 1)
    {
        Tcl_AppendResult(interp, "error casting pointer", (char *) NULL);
        return TCL_ERROR;
    }
    bboxo = (PyObject*)bboxl;

    //bboxo = (PyObject*)atol(argv[4]);
    //std::stringstream bbox_ptr_ss;
    //bbox_ptr_ss.str(argv[4]);
    //bbox_ptr_ss >> tmp_ptr;
    //bboxo = (PyObject*)tmp_ptr;
    if (py_convert_bbox(bboxo, l, b, r, t))
    {
        has_bbox = true;

        destx = (int)l;
        desty = srcheight - (int)t;
        destwidth = (int)(r - l);
        destheight = (int)(t - b);
        deststride = 4 * destwidth;

        destbuffer = new agg::int8u[deststride*destheight];
        if (destbuffer == NULL)
        {
            throw Py::MemoryError("_tkagg could not allocate memory for destbuffer");
        }

        agg::rendering_buffer destrbuf;
        destrbuf.attach(destbuffer, destwidth, destheight, deststride);
        pixfmt destpf(destrbuf);
        renderer_base destrb(destpf);

        agg::rect_base<int> region(destx, desty, (int)r, srcheight - (int)b);
        destrb.copy_from(aggRenderer->renderingBuffer, &region,
                         -destx, -desty);
    }
    else
    {
        has_bbox = false;
        destbuffer = NULL;
        destx = desty = destwidth = destheight = deststride = 0;
    }

    /* setup tkblock */
    block.pixelSize = 1;
    if (mode == 0)
    {
        block.offset[0] = block.offset[1] = block.offset[2] = 0;
        nval = 1;
    }
    else
    {
        block.offset[0] = 0;
        block.offset[1] = 1;
        block.offset[2] = 2;
        if (mode == 1)
        {
            block.offset[3] = 0;
            block.pixelSize = 3;
            nval = 3;
        }
        else
        {
            block.offset[3] = 3;
            block.pixelSize = 4;
            nval = 4;
        }
    }

    if (has_bbox)
    {
        block.width  = destwidth;
        block.height = destheight;
        block.pitch = deststride;
        block.pixelPtr = destbuffer;

        Tk_PhotoPutBlock(photo, &block, destx, desty, destwidth, destheight);
        delete [] destbuffer;

    }
    else
    {
        block.width  = aggRenderer->get_width();
        block.height = aggRenderer->get_height();
        block.pitch = block.width * nval;
        block.pixelPtr =  aggRenderer->pixBuffer;

        /* Clear current contents */
        Tk_PhotoBlank(photo);
        /* Copy opaque block to photo image, and leave the rest to TK */
        Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height);
    }

    return TCL_OK;
}
Пример #9
0
static int
PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
               int argc, char **argv)
{
    Imaging im;
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;

    if (argc != 3) {
        Tcl_AppendResult(interp, "usage: ", argv[0],
                         " destPhoto srcImage", (char *) NULL);
        return TCL_ERROR;
    }

    /* get Tcl PhotoImage handle */
    photo = Tk_FindPhoto(interp, argv[1]);
    if (photo == NULL) {
        Tcl_AppendResult(
            interp, "destination photo must exist", (char *) NULL
            );
        return TCL_ERROR;
    }

    /* get PIL Image handle */
    im = ImagingFind(argv[2]);
    if (!im) {
	Tcl_AppendResult(interp, "bad name", (char*) NULL);
	return TCL_ERROR;
    }
    if (!im->block) {
	Tcl_AppendResult(interp, "bad display memory", (char*) NULL);
	return TCL_ERROR;
    }

    /* Active region */
#if 0
    if (src_xoffset + xsize > im->xsize)
	xsize = im->xsize - src_xoffset;
    if (src_yoffset + ysize > im->ysize)
	ysize = im->ysize - src_yoffset;
    if (xsize < 0 || ysize < 0
	|| src_xoffset >= im->xsize
	|| src_yoffset >= im->ysize)
	return TCL_OK;
#endif

    /* Mode */

    if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
	block.pixelSize = 1;
	block.offset[0] = block.offset[1] = block.offset[2] = 0;
    } else if (strncmp(im->mode, "RGB", 3) == 0) {
	block.pixelSize = 4;
	block.offset[0] = 0;
	block.offset[1] = 1;
	block.offset[2] = 2;
        if (strcmp(im->mode, "RGBA") == 0)
            block.offset[3] = 3; /* alpha (or reserved, under 8.2) */
        else
            block.offset[3] = 0; /* no alpha */
    } else {
        Tcl_AppendResult(interp, "Bad mode", (char*) NULL);
	return TCL_ERROR;
    }

    block.width = im->xsize;
    block.height = im->ysize;
    block.pitch = im->linesize;
    block.pixelPtr = (unsigned char*) im->block;
#if 0
    block.pixelPtr = (unsigned char*) im->block +
	             src_yoffset * im->linesize +
	             src_xoffset * im->pixelsize;
#endif

#if TK < 85 /* Tk 8.4 */
    Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height,
                     TK_PHOTO_COMPOSITE_SET);
    if (strcmp(im->mode, "RGBA") == 0)
        /* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */
        /* (fixed in Tk 8.5a3) */
        Tk_PhotoSetSize(photo, block.width, block.height);
#else /* Tk 8.5 */
    Tk_PhotoPutBlock(interp, photo, &block, 0, 0, block.width, block.height,
                     TK_PHOTO_COMPOSITE_SET);
#endif

    return TCL_OK;
}
Пример #10
0
static int
StringReadNAO(
    Tcl_Interp		*interp,
    Tcl_Obj		*nap_expr,	/* string containing NAP expression */
    Tcl_Obj		*format,	/* format string not used */
    Tk_PhotoHandle	imageHandle,
    int			destX,
    int			destY,
    int			width,
    int			height,
    int			srcX,
    int			srcY)
{
    int			naoWidth;
    int			naoHeight;
    int			naoDepth;
    Nap_NAO		*naoPtr;
    Nap_NAO		*naoPtr0;
    int			rank;
    Tk_PhotoImageBlock	block;
    NapClientData	*nap_cd = Nap_GetClientData(interp);

    naoPtr0 = Nap_GetNaoFromObj(nap_cd, nap_expr);
    CHECK2(naoPtr0, "StringReadNAO: error calling Nap_GetNaoFromObj");
    Nap_IncrRefCount(nap_cd, naoPtr0);
    naoPtr = Nap_CastNAO(nap_cd, naoPtr0, NAP_U8);
    Nap_IncrRefCount(nap_cd, naoPtr);
    Nap_DecrRefCount(nap_cd, naoPtr0);
    rank = naoPtr->rank;
    switch (rank) {
    case 2:
        naoWidth = naoPtr->shape[1]; 
        naoHeight = naoPtr->shape[0]; 
	break;
    case 3:
        naoWidth = naoPtr->shape[2]; 
        naoHeight = naoPtr->shape[1]; 
        naoDepth = naoPtr->shape[0];
	break;
    default:
	CHECK2(0, "StringReadNAO: Rank is not 1 or 2");
    }

/*
 * Setup the dimensions for the display
 */

    if ((srcX + width) > naoWidth) {
        width = naoWidth - srcX;
    }  
    if ((srcY + height) > naoHeight) {
        height = naoHeight - srcY;
    }
    if ((width <= 0) || (height <= 0)
            || (srcX >= naoWidth) || (srcY >= naoHeight)) {
        return TCL_OK;
    }

/*
 * Get the output window open to the correct size
 */

    Tk_PhotoExpand(imageHandle, destX + width, destY + height);


/*
 * setup the supporting image data structure
 */

    block.width = naoWidth;
    block.height = naoHeight;
    block.pitch = naoWidth;     /* Address difference between corresponding
                                 * pixels in successive lines */
    block.pixelSize = 1;	/* Address difference successive pixels
                                 * in the same line */
      /* Address differences between the red, green
                                 * and blue components of the pixel and the
                                 * pixel as a whole. */

    block.offset[0] = 0;  
    block.offset[1] = 0;
    block.offset[2] = 0;
    if (rank == 3) {
        if(naoDepth >= 3) {
            block.offset[1] = naoHeight*naoWidth;
            block.offset[2] = 2 * naoWidth*naoHeight;
        } else if(naoDepth == 2) {
            block.offset[2] =  naoWidth*naoHeight;
        }
    }   

    /* Pointer to the first part of the first pixel */
    block.pixelPtr = (unsigned char *) naoPtr->data.U8;

    Tk_PhotoPutBlock(imageHandle, &block, destX, destY, naoWidth, naoHeight,
	    TK_PHOTO_COMPOSITE_OVERLAY);
    Nap_DecrRefCount(nap_cd, naoPtr);
    return TCL_OK;
}
Пример #11
0
static int
StringReadPPM(
    Tcl_Interp *interp,		/* Interpreter to use for reporting errors. */
    Tcl_Obj *dataObj,		/* The image data. */
    Tcl_Obj *format,		/* User-specified format string, or NULL. */
    Tk_PhotoHandle imageHandle,	/* The photo image to write into. */
    int destX, int destY,	/* Coordinates of top-left pixel in photo
				 * image to be written to. */
    int width, int height,	/* Dimensions of block of photo image to be
				 * written to. */
    int srcX, int srcY)		/* Coordinates of top-left pixel to be used in
				 * image being read. */
{
    int fileWidth, fileHeight, maxIntensity;
    int nLines, nBytes, h, type, count, dataSize;
    unsigned char *pixelPtr, *dataBuffer;
    Tk_PhotoImageBlock block;

    type = ReadPPMStringHeader(dataObj, &fileWidth, &fileHeight,
	    &maxIntensity, &dataBuffer, &dataSize);
    if (type == 0) {
	Tcl_AppendResult(interp, "couldn't read raw PPM header from string",
		NULL);
	return TCL_ERROR;
    }
    if ((fileWidth <= 0) || (fileHeight <= 0)) {
	Tcl_AppendResult(interp, "PPM image data has dimension(s) <= 0",
		NULL);
	return TCL_ERROR;
    }
    if ((maxIntensity <= 0) || (maxIntensity >= 256)) {
	char buffer[TCL_INTEGER_SPACE];

	sprintf(buffer, "%d", maxIntensity);
	Tcl_AppendResult(interp,
		"PPM image data has bad maximum intensity value ", buffer,
		NULL);
	return TCL_ERROR;
    }

    if ((srcX + width) > fileWidth) {
	width = fileWidth - srcX;
    }
    if ((srcY + height) > fileHeight) {
	height = fileHeight - srcY;
    }
    if ((width <= 0) || (height <= 0)
	|| (srcX >= fileWidth) || (srcY >= fileHeight)) {
	return TCL_OK;
    }

    if (type == PGM) {
	block.pixelSize = 1;
	block.offset[0] = 0;
	block.offset[1] = 0;
	block.offset[2] = 0;
    } else {
	block.pixelSize = 3;
	block.offset[0] = 0;
	block.offset[1] = 1;
	block.offset[2] = 2;
    }
    block.offset[3] = 0;
    block.width = width;
    block.pitch = block.pixelSize * fileWidth;

    if (srcY > 0) {
	dataBuffer += srcY * block.pitch;
	dataSize -= srcY * block.pitch;
    }

    if (maxIntensity == 255) {
	/*
	 * We have all the data in memory, so write everything in one go.
	 */

	if (block.pitch*height > dataSize) {
	    Tcl_AppendResult(interp, "truncated PPM data", NULL);
	    return TCL_ERROR;
	}
	block.pixelPtr = dataBuffer + srcX * block.pixelSize;
	block.height = height;
	return Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,
		width, height, TK_PHOTO_COMPOSITE_SET);
    }

    if (Tk_PhotoExpand(interp, imageHandle,
	    destX + width, destY + height) != TCL_OK) {
	return TCL_ERROR;
    }

    nLines = (MAX_MEMORY + block.pitch - 1) / block.pitch;
    if (nLines > height) {
	nLines = height;
    }
    if (nLines <= 0) {
	nLines = 1;
    }
    nBytes = nLines * block.pitch;
    pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes);
    block.pixelPtr = pixelPtr + srcX * block.pixelSize;

    for (h = height; h > 0; h -= nLines) {
	unsigned char *p;

	if (nLines > h) {
	    nLines = h;
	    nBytes = nLines * block.pitch;
	}
	if (dataSize < nBytes) {
	    ckfree((char *) pixelPtr);
	    Tcl_AppendResult(interp, "truncated PPM data", NULL);
	    return TCL_ERROR;
	}
	for (p=pixelPtr,count=nBytes ; count>0 ; count--,p++,dataBuffer++) {
	    *p = (((int) *dataBuffer) * 255)/maxIntensity;
	}
	dataSize -= nBytes;
	block.height = nLines;
	if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,
		width, nLines, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {
	    ckfree((char *) pixelPtr);
	    return TCL_ERROR;
	}
	destY += nLines;
    }

    ckfree((char *) pixelPtr);
    return TCL_OK;
}
Пример #12
0
static int
FileReadPPM(
    Tcl_Interp *interp,		/* Interpreter to use for reporting errors. */
    Tcl_Channel chan,		/* The image file, open for reading. */
    CONST char *fileName,	/* The name of the image file. */
    Tcl_Obj *format,		/* User-specified format string, or NULL. */
    Tk_PhotoHandle imageHandle,	/* The photo image to write into. */
    int destX, int destY,	/* Coordinates of top-left pixel in photo
				 * image to be written to. */
    int width, int height,	/* Dimensions of block of photo image to be
				 * written to. */
    int srcX, int srcY)		/* Coordinates of top-left pixel to be used in
				 * image being read. */
{
    int fileWidth, fileHeight, maxIntensity;
    int nLines, nBytes, h, type, count;
    unsigned char *pixelPtr;
    Tk_PhotoImageBlock block;

    type = ReadPPMFileHeader(chan, &fileWidth, &fileHeight, &maxIntensity);
    if (type == 0) {
	Tcl_AppendResult(interp, "couldn't read raw PPM header from file \"",
		fileName, "\"", NULL);
	return TCL_ERROR;
    }
    if ((fileWidth <= 0) || (fileHeight <= 0)) {
	Tcl_AppendResult(interp, "PPM image file \"", fileName,
		"\" has dimension(s) <= 0", NULL);
	return TCL_ERROR;
    }
    if ((maxIntensity <= 0) || (maxIntensity >= 256)) {
	char buffer[TCL_INTEGER_SPACE];

	sprintf(buffer, "%d", maxIntensity);
	Tcl_AppendResult(interp, "PPM image file \"", fileName,
		"\" has bad maximum intensity value ", buffer, NULL);
	return TCL_ERROR;
    }

    if ((srcX + width) > fileWidth) {
	width = fileWidth - srcX;
    }
    if ((srcY + height) > fileHeight) {
	height = fileHeight - srcY;
    }
    if ((width <= 0) || (height <= 0)
	|| (srcX >= fileWidth) || (srcY >= fileHeight)) {
	return TCL_OK;
    }

    if (type == PGM) {
	block.pixelSize = 1;
	block.offset[0] = 0;
	block.offset[1] = 0;
	block.offset[2] = 0;
    } else {
	block.pixelSize = 3;
	block.offset[0] = 0;
	block.offset[1] = 1;
	block.offset[2] = 2;
    }
    block.offset[3] = 0;
    block.width = width;
    block.pitch = block.pixelSize * fileWidth;

    if (Tk_PhotoExpand(interp, imageHandle,
	    destX + width, destY + height) != TCL_OK) {
	return TCL_ERROR;
    }

    if (srcY > 0) {
	Tcl_Seek(chan, (Tcl_WideInt)(srcY * block.pitch), SEEK_CUR);
    }

    nLines = (MAX_MEMORY + block.pitch - 1) / block.pitch;
    if (nLines > height) {
	nLines = height;
    }
    if (nLines <= 0) {
	nLines = 1;
    }
    nBytes = nLines * block.pitch;
    pixelPtr = (unsigned char *) ckalloc((unsigned) nBytes);
    block.pixelPtr = pixelPtr + srcX * block.pixelSize;

    for (h = height; h > 0; h -= nLines) {
	if (nLines > h) {
	    nLines = h;
	    nBytes = nLines * block.pitch;
	}
	count = Tcl_Read(chan, (char *) pixelPtr, nBytes);
	if (count != nBytes) {
	    Tcl_AppendResult(interp, "error reading PPM image file \"",
		    fileName, "\": ",
		    Tcl_Eof(chan) ? "not enough data" : Tcl_PosixError(interp),
		    NULL);
	    ckfree((char *) pixelPtr);
	    return TCL_ERROR;
	}
	if (maxIntensity != 255) {
	    unsigned char *p;

	    for (p = pixelPtr; count > 0; count--, p++) {
		*p = (((int) *p) * 255)/maxIntensity;
	    }
	}
	block.height = nLines;
	if (Tk_PhotoPutBlock(interp, imageHandle, &block, destX, destY,
		width, nLines, TK_PHOTO_COMPOSITE_SET) != TCL_OK) {
	    ckfree((char *) pixelPtr);
	    return TCL_ERROR;
	}
	destY += nLines;
    }

    ckfree((char *) pixelPtr);
    return TCL_OK;
}