Fixed issues with rotating and fliping images + other bugs

This commit is contained in:
rafmag 2023-01-16 11:33:59 -07:00
parent 5faefbdf8d
commit 9105bef5f5
3 changed files with 121 additions and 88 deletions

3
.gitignore vendored
View File

@ -27,4 +27,7 @@ src/parselabel.h
src/rawtovcd
src/xschem
/build
CMakeLists.txt
.vscode

View File

@ -3215,15 +3215,23 @@ void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2
} else { /* resize image to fit in rectangle */
rw = abs((int)(*x2 - *x1));
rh = abs((int)(*y2 - *y1));
scalex = rw/w * xctx->mooz;
scaley = rh/h * xctx->mooz;
if (rot == 1 || rot == 3)
{
scalex = rh/w * xctx->mooz;
scaley = rw/h * xctx->mooz;
}else
{
scalex = rw/w * xctx->mooz;
scaley = rh/h * xctx->mooz;
}
}
if(dr && xctx->draw_pixmap) {
cairo_translate(xctx->cairo_save_ctx, x, y);
if(flip && (rot == 0 || rot == 2)) cairo_scale(xctx->cairo_save_ctx, -scalex, scaley);
else if(flip && (rot == 1 || rot == 3)) cairo_scale(xctx->cairo_save_ctx, scalex, -scaley);
else cairo_scale(xctx->cairo_save_ctx, scalex, scaley);
cairo_rotate(xctx->cairo_save_ctx, rot * XSCH_PI * 0.5);
if(flip && (rot == 0 || rot == 2)) cairo_scale(xctx->cairo_save_ctx, -scalex, scaley);
else if(flip && (rot == 1 || rot == 3)) cairo_scale(xctx->cairo_save_ctx, -scalex, scaley);
else cairo_scale(xctx->cairo_save_ctx, scalex, scaley);
cairo_set_source_surface(xctx->cairo_save_ctx, emb_ptr->image, 0. , 0.);
cairo_rectangle(xctx->cairo_save_ctx, 0, 0, w , h );
/* cairo_fill(xctx->cairo_save_ctx);
@ -3233,10 +3241,10 @@ void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2
}
if(dr && xctx->draw_window) {
cairo_translate(xctx->cairo_ctx, x, y);
cairo_rotate(xctx->cairo_ctx, rot * XSCH_PI * 0.5);
if(flip && (rot == 0 || rot == 2)) cairo_scale(xctx->cairo_ctx, -scalex, scaley);
else if(flip && (rot == 1 || rot == 3)) cairo_scale(xctx->cairo_ctx, scalex, -scaley);
else cairo_scale(xctx->cairo_ctx, scalex, scaley);
cairo_rotate(xctx->cairo_ctx, rot * XSCH_PI * 0.5);
cairo_set_source_surface(xctx->cairo_ctx, emb_ptr->image, 0. , 0.);
cairo_rectangle(xctx->cairo_ctx, 0, 0, w , h );
/* cairo_fill(xctx->cairo_ctx);

View File

@ -132,97 +132,117 @@ char* bin2hex(const unsigned char* bin, size_t len)
return out;
}
void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2)
void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, int flip)
{
int i;
size_t data_size;
png_to_byte_closure_t closure;
char* filter = NULL;
my_strdup(1484, &filter, get_tok_value(r->prop_ptr, "filter", 0));
unsigned char* image_data64_ptr = get_tok_value(r->prop_ptr, "image_data", 0);
int i;
size_t data_size;
png_to_byte_closure_t closure;
char* filter = NULL;
my_strdup(1484, &filter, get_tok_value(r->prop_ptr, "filter", 0));
unsigned char* image_data64_ptr = get_tok_value(r->prop_ptr, "image_data", 0);
if (filter) {
size_t filtersize = 0;
char* filterdata = NULL;
closure.buffer = NULL;
filterdata = (char*)base64_decode(image_data64_ptr, strlen(image_data64_ptr), &filtersize);
filter_data(filterdata, filtersize, (char**)&closure.buffer, &data_size, filter);
my_free(1488, &filterdata);
}
else {
closure.buffer = base64_decode(image_data64_ptr, strlen(image_data64_ptr), &data_size);
}
closure.pos = 0;
closure.size = data_size; /* should not be necessary */
cairo_surface_t* surface = cairo_image_surface_create_from_png_stream(png_reader, &closure);
int png_size_x = cairo_image_surface_get_width(surface);
int png_size_y = cairo_image_surface_get_height(surface);
if (filter) {
size_t filtersize = 0;
char* filterdata = NULL;
closure.buffer = NULL;
filterdata = (char*)base64_decode(image_data64_ptr, strlen(image_data64_ptr), &filtersize);
filter_data(filterdata, filtersize, (char**)&closure.buffer, &data_size, filter);
my_free(1488, &filterdata);
}
else {
closure.buffer = base64_decode(image_data64_ptr, strlen(image_data64_ptr), &data_size);
}
closure.pos = 0;
closure.size = data_size; /* should not be necessary */
cairo_surface_t* surface = cairo_image_surface_create_from_png_stream(png_reader, &closure);
cairo_surface_flush(surface);
unsigned char* png_data = cairo_image_surface_get_data(surface);
int png_size_x = cairo_image_surface_get_width(surface);
int png_size_y = cairo_image_surface_get_height(surface);
unsigned char* invertImage = get_tok_value(r->prop_ptr, "InvertOnExport", 0);
unsigned char BG_r = 0xFF, BG_g = 0xFF, BG_b = 0xFF;
for (i = 0; i < (png_size_x * png_size_y * 4); i += 4)
{
cairo_surface_flush(surface);
unsigned char* png_data = cairo_image_surface_get_data(surface);
unsigned char png_r = png_data[i + 0];
unsigned char png_g = png_data[i + 1];
unsigned char png_b = png_data[i + 2];
unsigned char png_a = png_data[i + 3];
unsigned char* invertImage = get_tok_value(r->prop_ptr, "InvertOnExport", 0);
unsigned char BG_r = 0xFF, BG_g = 0xFF, BG_b = 0xFF;
for (i = 0; i < (png_size_x * png_size_y * 4); i += 4)
{
unsigned char png_r = png_data[i + 0];
unsigned char png_g = png_data[i + 1];
unsigned char png_b = png_data[i + 2];
unsigned char png_a = png_data[i + 3];
double ainv=((double)(0xFF - png_a)) / ((double)(0xFF));
if(invertImage[0]=='1')
{
png_data[i + 0] = (0xFF-png_r) + (unsigned char)((double)BG_r * ((double)(0xFF - png_a)) / ((double)(0xFF)));
png_data[i + 1] = (0xFF-png_g) + (unsigned char)((double)BG_g * ((double)(0xFF - png_a)) / ((double)(0xFF)));
png_data[i + 2] = (0xFF-png_b) + (unsigned char)((double)BG_b * ((double)(0xFF - png_a)) / ((double)(0xFF)));
png_data[i + 0] = (0xFF-png_r) + (unsigned char)((double)BG_r * ainv);
png_data[i + 1] = (0xFF-png_g) + (unsigned char)((double)BG_g * ainv);
png_data[i + 2] = (0xFF-png_b) + (unsigned char)((double)BG_b * ainv);
png_data[i + 3] = 0xFF;
}else
{
png_data[i + 0] = png_r + (unsigned char)((double)BG_r * ((double)(0xFF - png_a)) / ((double)(0xFF)));
png_data[i + 1] = png_g + (unsigned char)((double)BG_g * ((double)(0xFF - png_a)) / ((double)(0xFF)));
png_data[i + 2] = png_b + (unsigned char)((double)BG_b * ((double)(0xFF - png_a)) / ((double)(0xFF)));
png_data[i + 0] = png_r + (unsigned char)((double)BG_r * ainv);
png_data[i + 1] = png_g + (unsigned char)((double)BG_g * ainv);
png_data[i + 2] = png_b + (unsigned char)((double)BG_b * ainv);
png_data[i + 3] = 0xFF;
}
}
cairo_surface_mark_dirty(surface);
}
cairo_surface_mark_dirty(surface);
static char str[PATH_MAX];
my_snprintf(str, S(str), "%s%s", tclgetvar("XSCHEM_TMP_DIR"), "/temp.jpg");
cairo_image_surface_write_to_jpeg(surface, str, 100);
unsigned char* jpgData;
FILE* fp;
fp = fopen(str, "rb"); /* Open the file for reading */
fseek(fp, 0L, SEEK_END);
int fileSize = ftell(fp);
rewind(fp);
jpgData = malloc(fileSize);
fread(jpgData, sizeof(jpgData[0]), fileSize, fp);
fclose(fp);
cairo_image_surface_write_to_jpeg(surface, str, 100);
unsigned char* jpgData;
FILE* fp;
fp = fopen(str, "rb"); /* Open the file for reading */
fseek(fp, 0L, SEEK_END);
int fileSize = ftell(fp);
rewind(fp);
jpgData = malloc(fileSize);
fread(jpgData, sizeof(jpgData[0]), fileSize, fp);
fclose(fp);
unsigned char* hexEncodedJPG = bin2hex(jpgData, fileSize);
unsigned char* hexEncodedJPG = bin2hex(jpgData, fileSize);
fprintf(fd, "gsave\n");
fprintf(fd, "%g %g translate\n", X_TO_PS(x1), Y_TO_PS(y1));
fprintf(fd, "%g %g scale\n", X_TO_PS(x2) - X_TO_PS(x1), Y_TO_PS(y2) - Y_TO_PS(y1));
fprintf(fd, "%d\n", png_size_x);
fprintf(fd, "%d\n", png_size_y);
fprintf(fd, "8\n");
fprintf(fd, "[%d 0 0 %d 0 0]\n", png_size_x, png_size_y);
fprintf(fd, "(%s)\n", hexEncodedJPG);
fprintf(fd, "/ASCIIHexDecode\n");
fprintf(fd, "filter\n");
fprintf(fd, "0 dict\n");
fprintf(fd, "/DCTDecode\n");
fprintf(fd, "filter\n");
fprintf(fd, "false\n");
fprintf(fd, "3\n");
fprintf(fd, "colorimage\n");
fprintf(fd, "grestore\n");
fprintf(fd, "gsave\n");
fprintf(fd, "%g %g translate\n", X_TO_PS(x1), Y_TO_PS(y1));
if(rot==1) fprintf(fd, "90 rotate\n");
if(rot==2) fprintf(fd, "180 rotate\n");
if(rot==3) fprintf(fd, "270 rotate\n");
fprintf(fd, "%g %g scale\n", (X_TO_PS(x2) - X_TO_PS(x1))*0.97, (Y_TO_PS(y2) - Y_TO_PS(y1))*0.97);
fprintf(fd, "%g\n", (double)png_size_x);
fprintf(fd, "%g\n", (double)png_size_y);
fprintf(fd, "8\n");
if(!flip)
{
if(rot==1) fprintf(fd, "[%g 0 0 %g 0 %g]\n", (double)png_size_y, (double)png_size_x, (double)png_size_y);
else if(rot==2) fprintf(fd, "[%g 0 0 %g %g %g]\n", (double)png_size_x, (double)png_size_y, (double)png_size_x, (double)png_size_y);
else if(rot==3) fprintf(fd, "[%g 0 0 %g %g 0]\n", (double)png_size_y, (double)png_size_x, (double)png_size_x);
else fprintf(fd, "[%g 0 0 %g 0 0]\n", (double)png_size_x, (double)png_size_y);
}
else
{
if(rot==1) fprintf(fd, "[%g 0 0 %g %g %g]\n", -(double)png_size_y, (double)png_size_x, (double)png_size_x, (double)png_size_y);
else if(rot==2) fprintf(fd, "[%g 0 0 %g 0 %g]\n", -(double)png_size_x, (double)png_size_y, (double)png_size_y);
else if(rot==3) fprintf(fd, "[%g 0 0 %g 0 0]\n", -(double)png_size_y, (double)png_size_x);
else fprintf(fd, "[%g 0 0 %g %g 0]\n", -(double)png_size_x, (double)png_size_y, (double)png_size_x);
}
fprintf(fd, "(%s)\n", hexEncodedJPG);
fprintf(fd, "/ASCIIHexDecode\n");
fprintf(fd, "filter\n");
fprintf(fd, "0 dict\n");
fprintf(fd, "/DCTDecode\n");
fprintf(fd, "filter\n");
fprintf(fd, "false\n");
fprintf(fd, "3\n");
fprintf(fd, "colorimage\n");
fprintf(fd, "grestore\n");
fflush(fd);
free(hexEncodedJPG); free(jpgData);
free(hexEncodedJPG); free(jpgData);
}
@ -845,7 +865,7 @@ static void ps_draw_symbol(int n,int layer, int what, short tmp_flip, short rot,
RECTORDER(x1,y1,x2,y2);
if (rect.flags & 1024) /* image */
{
ps_drawPNG(&rect, x0 + x1, y0 + y1, x0 + x2, y0 + y2);
ps_drawPNG(&rect, x0 + x1, y0 + y1, x0 + x2, y0 + y2, rot, flip);
continue;
}
ps_filledrect(layer, x0+x1, y0+y1, x0+x2, y0+y2, rect.dash, rect.fill);
@ -1112,19 +1132,21 @@ void create_ps(char **psfile, int what)
xctx->line[c][i].x2, xctx->line[c][i].y2, xctx->line[c][i].dash);
for(i=0;i<xctx->rects[c];i++)
{
if (c == GRIDLAYER && (xctx->rect[c][i].flags & 1024)) { /* image */
xRect* r = &xctx->rect[c][i];
/* PNG Code Here */
ps_drawPNG(r, r->x1, r->y1, r->x2, r->y2,0 ,0);
continue;
}
if (c == GRIDLAYER && (xctx->rect[c][i].flags & 1)) { /* graph */
xRect* r = &xctx->rect[c][i];
ps_embedded_graph(r, r->x1, r->y1, r->x2, r->y2);
}
if(c != GRIDLAYER || !(xctx->rect[c][i].flags & 1) ) {
ps_filledrect(c, xctx->rect[c][i].x1, xctx->rect[c][i].y1,
xctx->rect[c][i].x2, xctx->rect[c][i].y2, xctx->rect[c][i].dash, xctx->rect[c][i].fill);
}
if (c == GRIDLAYER && (xctx->rect[c][i].flags & 1024)) { /* image */
xRect* r = &xctx->rect[c][i];
/* PNG Code Here */
ps_drawPNG(r, r->x1, r->y1, r->x2, r->y2);
}
if (c == GRIDLAYER && (xctx->rect[c][i].flags & 1)) { /* graph */
xRect* r = &xctx->rect[c][i];
ps_embedded_graph(r, r->x1, r->y1, r->x2, r->y2);
}
}
for(i=0;i<xctx->arcs[c];i++)
{