allow embedding all image formats if a xxx-->png filter shell command is provided as attribute

This commit is contained in:
Stefan Frederik 2022-01-23 04:51:41 +01:00
parent 90f1a00a6f
commit c8ec7a77f2
5 changed files with 74 additions and 30 deletions

View File

@ -2421,6 +2421,7 @@ int draw_images_all(void)
double sx1, sy1, sx2, sy2, alpha;
const char *ptr;
int save_bbx1, save_bby1, save_bbx2, save_bby2;
char filename[PATH_MAX];
if(xctx->draw_single_layer==-1 || GRIDLAYER == xctx->draw_single_layer) {
if(xctx->enable_layer[GRIDLAYER]) for(i = 0; i < xctx->rects[GRIDLAYER]; i++) {
@ -2428,11 +2429,13 @@ int draw_images_all(void)
if(r->flags & 1024) {
struct stat buf;
const char *attr;
const char *filename;
double scalex, scaley;
char *filter = NULL;
png_to_byte_closure_t closure;
xEmb_image *emb_ptr;
my_strncpy(filename, get_tok_value(r->prop_ptr, "image", 0), S(filename));
my_strdup(1484, &filter, get_tok_value(r->prop_ptr, "filter", 0));
if(xctx->sem) {
bbox_set = 1;
save_bbx1 = xctx->bbx1;
@ -2461,7 +2464,16 @@ int draw_images_all(void)
/* ... or read PNG from image_data attribute */
} else if( (attr = get_tok_value(r->prop_ptr, "image_data", 0))[0] ) {
size_t data_size;
closure.buffer = base64_decode(attr, strlen(attr), &data_size);
if(filter) {
size_t filtersize = 0;
char *filterdata = NULL;
closure.buffer = NULL;
filterdata = (char *)base64_decode(attr, strlen(attr), &filtersize);
filter_data(filterdata, filtersize, (char **)&closure.buffer, &data_size, filter);
my_free(1488, &filterdata);
} else {
closure.buffer = base64_decode(attr, strlen(attr), &data_size);
}
closure.pos = 0;
closure.size = data_size; /* should not be necessary */
emb_ptr->image = cairo_image_surface_create_from_png_stream(png_reader, &closure);
@ -2469,22 +2481,51 @@ int draw_images_all(void)
my_free(1467, &closure.buffer);
dbg(1, "draw_images_all(): length2 = %d\n", closure.pos);
/* ... or read PNG from file (image attribute) */
} else if( (filename = get_tok_value(r->prop_ptr, "image", 0))[0] && !stat(filename, &buf)) {
} else if(filename[0] && !stat(filename, &buf)) {
char *image_data = NULL;
size_t olength;
emb_ptr->image = cairo_image_surface_create_from_png(filename);
if(cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) return 1;
/* write PNG to in-memory buffer */
closure.buffer = NULL;
closure.size = 0;
closure.pos = 0;
cairo_surface_write_to_png_stream(emb_ptr->image, png_writer, &closure);
dbg(1, "draw_images_all(): length3 = %d\n", closure.pos);
/* put base64 encoded data to rect image_data attrinute */
image_data = base64_encode(closure.buffer, closure.pos, &olength, 0);
if(filter) {
size_t filtersize = 0;
char *filterdata = NULL;
size_t pngsize = 0;
char *pngdata = NULL;
struct stat st;
if(stat(filename, &st) == 0 /* && ( (st.st_mode & S_IFMT) == S_IFREG)*/ ) {
FILE *fd;
filtersize = st.st_size;
if(filtersize) {
fd = fopen(filename, "r");
if(fd) {
filterdata = my_malloc(1490, filtersize);
fread(filterdata, filtersize, 1, fd);
fclose(fd);
}
}
}
filter_data(filterdata, filtersize, &pngdata, &pngsize, filter);
closure.buffer = (unsigned char *)pngdata;
closure.size = pngsize;
closure.pos = 0;
emb_ptr->image = cairo_image_surface_create_from_png_stream(png_reader, &closure);
image_data = base64_encode((unsigned char *)filterdata, filtersize, &olength, 0);
my_free(1489, &filterdata);
} else {
closure.buffer = NULL;
closure.size = 0;
closure.pos = 0;
emb_ptr->image = cairo_image_surface_create_from_png(filename);
/* write PNG to in-memory buffer */
cairo_surface_write_to_png_stream(emb_ptr->image, png_writer, &closure);
image_data = base64_encode(closure.buffer, closure.pos, &olength, 0);
}
my_free(1468, &closure.buffer);
/* put base64 encoded data to rect image_data attrinute */
my_strdup2(1473, &r->prop_ptr, subst_token(r->prop_ptr, "image_data", image_data));
my_free(1474, &image_data);
if(cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) return 1;
dbg(1, "draw_images_all(): length3 = %d\n", closure.pos);
} else {
return 1;
}
@ -2532,6 +2573,7 @@ int draw_images_all(void)
if(rescaled) bbox(ADD, r->x1, r->y1, r->x2, r->y2);
bbox(SET, 0.0, 0.0, 0.0, 0.0);
}
my_free(1486, &filter);
}
}
}

View File

@ -38,6 +38,12 @@ int filter_data(const char *din, const size_t ilen,
int ret = 0;
pid_t pid;
size_t bufsize = 1024, oalloc = 0, n = 0;
if(!din || !ilen || !cmd) { /* basic check */
*dout = NULL;
*olen = 0;
return 1;
}
pipe(p1);
pipe(p2);
signal(SIGPIPE, SIG_IGN); /* so attempting write/read a broken pipe won't kill program */
@ -87,7 +93,7 @@ int filter_data(const char *din, const size_t ilen,
close(p2[0]);
if(n < 0 || !*olen) {
if(oalloc) {
my_free(1483, *dout);
my_free(1483, dout);
*olen = 0;
}
fprintf(stderr, "no data read\n");
@ -99,7 +105,7 @@ int filter_data(const char *din, const size_t ilen,
}
/* Caller should free returned buffer */
char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length, int brk) {
char *base64_encode(const unsigned char *data, const size_t input_length, size_t *output_length, int brk) {
static const char b64_enc[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
@ -150,7 +156,7 @@ char *base64_encode(const unsigned char *data, size_t input_length, size_t *outp
}
/* Caller should free returned buffer */
unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length) {
unsigned char *base64_decode(const char *data, const size_t input_length, size_t *output_length) {
static const unsigned char b64_dec[256] = {
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,

View File

@ -2670,12 +2670,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(argv[1][0] == 't') {
if(!strcmp(argv[1],"test"))
{
char *odata = NULL;
size_t olen;
cmd_found = 1;
if(!filter_data("stefan.", 7, &odata, &olen, "base64")) {
dbg(0, "odata=%s, olen=%d\n", odata, olen);
}
Tcl_ResetResult(interp);
}

View File

@ -1008,8 +1008,8 @@ extern int read_embedded_rawfile(void);
extern char *base64_from_file(const char *f, size_t *length);
extern int set_rect_flags(xRect *r);
extern int set_rect_extraptr(int what, xRect *drptr, xRect *srptr);
extern unsigned char *base64_decode(const char *data, size_t input_length, size_t *output_length);
extern char *base64_encode(const unsigned char *data, size_t input_length, size_t *output_length, int brk);
extern unsigned char *base64_decode(const char *data, const size_t input_length, size_t *output_length);
extern char *base64_encode(const unsigned char *data, const size_t input_length, size_t *output_length, int brk);
extern int get_raw_index(const char *node);
extern void free_rawfile(int dr);
extern int read_rawfile(const char *f);

File diff suppressed because one or more lines are too long