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,