diff --git a/src/psprint.c b/src/psprint.c index 9165fd5f..3d2a9797 100644 --- a/src/psprint.c +++ b/src/psprint.c @@ -82,7 +82,7 @@ int ps_embedded_image(xRect* r, double x1, double y1, double x2, double y2, int #if defined(HAS_LIBJPEG) && HAS_CAIRO==1 int i, jpg; int size_x, size_y; - unsigned char *img_data = NULL, BG_r, BG_g, BG_b; + unsigned char *ptr = NULL; int invertImage; unsigned char* ascii85EncodedJpeg; const char* attr; @@ -129,29 +129,30 @@ int ps_embedded_image(xRect* r, double x1, double y1, double x2, double y2, int cairo_paint(ct); cairo_destroy(ct); - img_data = cairo_image_surface_get_data(surface); + ptr = cairo_image_surface_get_data(surface); - /* jpeg has no alpha channel so blend transparency with white */ - BG_r = 0xFF; BG_g = 0xFF; BG_b = 0xFF; for (i = 0; i < (size_x * size_y * 4); i += 4) { - unsigned char png_r = img_data[i + 0]; - unsigned char png_g = img_data[i + 1]; - unsigned char png_b = img_data[i + 2]; - unsigned char png_a = img_data[i + 3]; - double ainv=((double)(0xFF - png_a)) / ((double)(0xFF)); - + unsigned char a = ptr[i + 3]; + unsigned char r = ptr[i + 2]; + unsigned char g = ptr[i + 1]; + unsigned char b = ptr[i + 0]; + /* invert colors */ if(invertImage) { - img_data[i + 0] = (unsigned char)(0xFF-png_r) + (unsigned char)((double)BG_r * ainv); - img_data[i + 1] = (unsigned char)(0xFF-png_g) + (unsigned char)((double)BG_g * ainv); - img_data[i + 2] = (unsigned char)(0xFF-png_b) + (unsigned char)((double)BG_b * ainv); - img_data[i + 3] = 0xFF; - } else { - img_data[i + 0] = png_r + (unsigned char)((double)BG_r * ainv); - img_data[i + 1] = png_g + (unsigned char)((double)BG_g * ainv); - img_data[i + 2] = png_b + (unsigned char)((double)BG_b * ainv); - img_data[i + 3] = 0xFF; + r = a - r; + g = a - g; + b = a - b; } + /* blend with white, remove alpha */ + r += (unsigned char)(0xff - a); + g += (unsigned char)(0xff - a); + b += (unsigned char)(0xff - a); + a = (unsigned char) 0xff; + /* write result back */ + ptr[i + 3] = a; + ptr[i + 2] = r; + ptr[i + 1] = g; + ptr[i + 0] = b; } cairo_surface_mark_dirty(surface); if(invertImage || jpg == 0) { diff --git a/src/scheduler.c b/src/scheduler.c index 08b015e4..8cbb8634 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -2033,13 +2033,17 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg break; case 'i': /*----------------------------------------------*/ #if HAS_CAIRO==1 - /* image [invert|white_transp|black_transp|transp_white|transp_black|write_back] + /* image [invert|white_transp|black_transp|transp_white|transp_black|write_back| + * blend_white|blend_black] * Apply required changes to selected images * invert: invert colors * white_transp: transform white to transparent color (alpha=0) after invert. * black_transp: transform black to transparent color (alpha=0) after invert. * transp_white: transform white to transparent color (alpha=0) after invert. * transp_black: transform black to transparent color (alpha=0) after invert. + * blend_white: blend with white background and remove alpha + * blend_black: blend with black background and remove alpha + * write_back: write resulting image back into `image_data` attribute */ if(!strcmp(argv[1], "image")) { @@ -2053,10 +2057,15 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg } if(!strcmp(argv[2], "help")) { Tcl_SetResult(interp, - "xschem image [invert|white_transp|black_transp|transp_white|transp_black|write_back]", + "xschem image [invert|white_transp|black_transp|transp_white|transp_black|\n" + " blend_white|blend_black|write_back]", TCL_STATIC); return TCL_OK; } + if(xctx->lastsel == 0) { + Tcl_SetResult(interp, "No images selected", TCL_STATIC); + return TCL_ERROR; + } for(i = 2; i < argc; i++) { if(!strcmp(argv[i], "invert")) what |= 1; if(!strcmp(argv[i], "white_transp")) what |= 2; diff --git a/src/svgdraw.c b/src/svgdraw.c index 7deaaa99..a49b3569 100644 --- a/src/svgdraw.c +++ b/src/svgdraw.c @@ -456,9 +456,10 @@ static void svg_drawgrid() } } -static void svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, double ry2, int rot, int flip) +static int svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, double ry2, int rot, int flip) { - const char *ptr; + const char *attr; + size_t attr_len; double x1, y1, x2, y2, w, h, scalex = 1.0, scaley = 1.0; int jpg = 0; char opacity[100]; @@ -479,20 +480,29 @@ static void svg_embedded_image(xRect *r, double rx1, double ry1, double rx2, dou if(flip && (rot == 0 || rot == 2)) scalex = -1.0; else if(flip && (rot == 1 || rot == 3)) scaley = -1.0; - ptr = get_tok_value(r->prop_ptr, "alpha", 0); - if(ptr[0]) alpha = atof(ptr); - ptr = get_tok_value(r->prop_ptr, "image_data", 0); + attr = get_tok_value(r->prop_ptr, "alpha", 0); + if(attr[0]) alpha = atof(attr); + attr = get_tok_value(r->prop_ptr, "image_data", 0); + attr_len = strlen(attr); + if(attr_len > 5) { + if(!strncmp(attr, "/9j/", 4)) jpg = 1; + else if(!strncmp(attr, "iVBOR", 5)) jpg = 0; + else jpg = -1; /* some invalid data */ + } else { + jpg = -1; + } + if(jpg == -1) { + return 0; + } my_snprintf(transform, S(transform), "transform=\"translate(%g,%g) scale(%g,%g) rotate(%d)\"", x1, y1, scalex, scaley, rot * 90); if(alpha == 1.0) strcpy(opacity, ""); else my_snprintf(opacity, S(opacity), "style=\"opacity:%g;\"", alpha); - if(ptr[0]) { - if(!strncmp(ptr, "/9j/", 4)) jpg = 1; /* jpeg base64 header (24 bits checked) */ - fprintf(fd, "\n", - 0.0, 0.0, w, h, transform, opacity, jpg ? "jpeg" : "png", ptr); - } + fprintf(fd, "\n", + 0.0, 0.0, w, h, transform, opacity, jpg ? "jpeg" : "png", attr); + return 1; } static void svg_draw_symbol(int c, int n,int layer,short tmp_flip, short rot,