cleanups in draw_image(), do not decode-reencode jpeg data

This commit is contained in:
stefan schippers 2024-03-16 12:50:42 +01:00
parent f84305930f
commit 6416df9733
9 changed files with 2637 additions and 2432 deletions

View File

@ -126,6 +126,21 @@
<Component Id="cmp5F2A45E78EBD02CB7779C16BF4C03932" Guid="{70B6880A-F335-434A-83AF-AA1CA96BE77B}">
<File Id="fil8EF2CE33BBBC466A43CBD7B77B17F725" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\commands1.png" />
</Component>
<Component Id="cmp3C2AB4925B1306E7CFBC2F46FE89BDAF" Guid="{6D07D7C3-6614-476F-8B85-4C97A724A8C9}">
<File Id="filC0FCD4F20A4DBA001A4341E0905B2747" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\commands10.png" />
</Component>
<Component Id="cmp648D5098787E8EC0C8547AC0DF5B339E" Guid="{AAD2FB2F-0184-4BFA-9C13-B50D7FFCC394}">
<File Id="filEF1FD053FEECBEF588DBA58BA7C10B8E" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\commands11.png" />
</Component>
<Component Id="cmp84B60C50A44DFE2D8F0121C9C242FC86" Guid="{E871EF43-2DB0-4CA3-A14F-39D7640E3EB2}">
<File Id="fil77BF466037C1C04928A7095A2035C1A5" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\commands12.png" />
</Component>
<Component Id="cmp47F7B1BA609C8374B9BA9B140BC3867B" Guid="{3F06EF3F-C775-446E-BFA9-CAD300452D6F}">
<File Id="filE931FD781DFDA5FEDE021F11DF666FCA" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\commands13.png" />
</Component>
<Component Id="cmp97D06DE87400946AFDDF51F3042AB7AF" Guid="{D94A649C-2E83-4410-B16A-7D36E001F01E}">
<File Id="fil5203C6CDF9157BDF3BF197D63D5455C9" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\commands14.png" />
</Component>
<Component Id="cmp35239CC60E8A28DF0814C1E2C8AED814" Guid="{9DA03C6E-6DB5-46BF-B6C7-6428B34DFFD5}">
<File Id="filE3F956C2E2CC4DF4A6D6798066F75F89" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\commands2.png" />
</Component>
@ -453,6 +468,12 @@
<Component Id="cmpA78C8D6823DB9F7E898D8016BD40E1F2" Guid="{D9EE6CA7-15FD-4DDE-A059-592559CBE2D3}">
<File Id="fil2A148FC6F10E4CD50F923332EE90DAA8" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\graphs20.png" />
</Component>
<Component Id="cmp625D2F5BCB3E2EBC29528813B3BD9B47" Guid="{C5787565-8D35-4CA4-A810-B8A4CF5B5184}">
<File Id="filA623141DA521B8058953290CF76F0D38" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\graphs21.png" />
</Component>
<Component Id="cmpC55E1C6560FA9273A1C807CC6556DC2A" Guid="{1B358D35-E968-41D7-B223-9BB9DB0C3948}">
<File Id="filD1D8B41D343379847BF7F895156183FE" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\graphs22.png" />
</Component>
<Component Id="cmp7D84114D6FDF0E09CB66A982B3C581C3" Guid="{06F4736F-88F7-459A-BF81-9F04C78C45B7}">
<File Id="fil00E7CE2F76CC18FC1618A1670E025C42" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\gschemtoxschem.png" />
</Component>
@ -474,6 +495,30 @@
<Component Id="cmpE415804152519EC8DE1A4531549F43A1" Guid="{2492BED0-6AB2-4FA7-BD75-85B29A2226C1}">
<File Id="fil257D69C3B519AEDA7869DB9500C1FE75" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\instance_based_implementation_04.png" />
</Component>
<Component Id="cmpEDAC1244E967444579C4681EB1E5D5A1" Guid="{901F4005-E768-4E7C-9A23-98EEC6FC2F60}">
<File Id="fil8BED5827C286DDB6B4B73C486D04122E" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\instance_based_implementation_05.png" />
</Component>
<Component Id="cmp4F8EBCFD3FCC2EE67599BD99BAF81196" Guid="{75667498-3FFE-4205-81C4-8B8D5F6E9CCD}">
<File Id="fil1BE4FBFFD73B48E7D89C50741B2DE121" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\instance_based_implementation_06.png" />
</Component>
<Component Id="cmp35CB7F24BA6C29E60BADCE9359242A3A" Guid="{1B754465-C082-40B0-A60B-E5BBCA4EB023}">
<File Id="filEBD3D384DBED0C5969236F3E3EB13072" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\instance_based_implementation_07.png" />
</Component>
<Component Id="cmp6084035E82570D640BF9FF87754F0E7C" Guid="{EB1EFF72-0545-47B8-B9E0-99AD110B3D6D}">
<File Id="filAB4008AB65841BD3A64172EFC07D322F" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\instance_based_implementation_08.png" />
</Component>
<Component Id="cmp0503EE00B33899016CEC48856BD7F184" Guid="{B351E189-2929-4EB6-B433-95310413B06A}">
<File Id="filAD359FE39EDBB818AB74D2059C4B891E" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\instance_based_implementation_09.png" />
</Component>
<Component Id="cmpDC6E8A887D9032EAE0B87F596925555D" Guid="{DB1EFC3F-D122-4BA2-90E4-F46E6E1AEE2C}">
<File Id="filFDD063242FFA510C6446B04290D04354" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\instance_based_implementation_10.png" />
</Component>
<Component Id="cmpCF93F0540C1DF04295C65AD62D3035FE" Guid="{5270D666-D80B-41BD-9ECB-28973579140E}">
<File Id="fil4D160B5732D51D0AE53D5A0637FC5D40" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\instance_based_implementation_11.png" />
</Component>
<Component Id="cmpC3F23EE0BA14BD2D6229990763D66D41" Guid="{195FB07B-4949-43DF-865C-52DC56F13F7B}">
<File Id="fil4F7320B80D70815E284D2B8337409E41" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\intuitive_interface_cheatsheet.svg" />
</Component>
<Component Id="cmp2DB8618704C7034B543BD78F8410CB70" Guid="{83F8DFAB-5FFC-4D6C-9CCD-89BF2D9D4B1F}">
<File Id="filABBDDFFF90735804749ED6C5727372C5" KeyPath="yes" Source="$(var.docSrcDir)\xschem_man\load_schematic.png" />
</Component>
@ -1172,6 +1217,11 @@
<ComponentRef Id="cmpE3D43CAAD367DC5DC13E04524A89C888" />
<ComponentRef Id="cmpA6AB78B04BBC707FE694C5FD48F835BB" />
<ComponentRef Id="cmp5F2A45E78EBD02CB7779C16BF4C03932" />
<ComponentRef Id="cmp3C2AB4925B1306E7CFBC2F46FE89BDAF" />
<ComponentRef Id="cmp648D5098787E8EC0C8547AC0DF5B339E" />
<ComponentRef Id="cmp84B60C50A44DFE2D8F0121C9C242FC86" />
<ComponentRef Id="cmp47F7B1BA609C8374B9BA9B140BC3867B" />
<ComponentRef Id="cmp97D06DE87400946AFDDF51F3042AB7AF" />
<ComponentRef Id="cmp35239CC60E8A28DF0814C1E2C8AED814" />
<ComponentRef Id="cmp2EA5ABF0232607FE2B60946F461AB4C8" />
<ComponentRef Id="cmpEF190926FE94250EAD5B7813D4CB078D" />
@ -1281,6 +1331,8 @@
<ComponentRef Id="cmp9F2896DC4627DF350F685875FC198171" />
<ComponentRef Id="cmp2E04033BEABEC724FC52D75E042EBBC6" />
<ComponentRef Id="cmpA78C8D6823DB9F7E898D8016BD40E1F2" />
<ComponentRef Id="cmp625D2F5BCB3E2EBC29528813B3BD9B47" />
<ComponentRef Id="cmpC55E1C6560FA9273A1C807CC6556DC2A" />
<ComponentRef Id="cmp7D84114D6FDF0E09CB66A982B3C581C3" />
<ComponentRef Id="cmpDB80566B13B66B2A92E91DA0585404A9" />
<ComponentRef Id="cmp8C7AB373FA963AF5F88C8B394FB28B19" />
@ -1288,6 +1340,14 @@
<ComponentRef Id="cmp72EFAE4CB2B8A2B5ED8A785D4C565C68" />
<ComponentRef Id="cmp5C04C95A67E090E0421B204F319D4216" />
<ComponentRef Id="cmpE415804152519EC8DE1A4531549F43A1" />
<ComponentRef Id="cmpEDAC1244E967444579C4681EB1E5D5A1" />
<ComponentRef Id="cmp4F8EBCFD3FCC2EE67599BD99BAF81196" />
<ComponentRef Id="cmp35CB7F24BA6C29E60BADCE9359242A3A" />
<ComponentRef Id="cmp6084035E82570D640BF9FF87754F0E7C" />
<ComponentRef Id="cmp0503EE00B33899016CEC48856BD7F184" />
<ComponentRef Id="cmpDC6E8A887D9032EAE0B87F596925555D" />
<ComponentRef Id="cmpCF93F0540C1DF04295C65AD62D3035FE" />
<ComponentRef Id="cmpC3F23EE0BA14BD2D6229990763D66D41" />
<ComponentRef Id="cmp2DB8618704C7034B543BD78F8410CB70" />
<ComponentRef Id="cmp8A2095B0FF09EA0F68B73AAAC60EA69B" />
<ComponentRef Id="cmp97047CA23E73FCF9A2A774BE2B268856" />

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -138,6 +138,12 @@
<Component Id="cmp041F77BDEB912A6C325624BA1E63A087" Guid="{3FDA57B2-B37C-493A-BECB-89F9AAC83831}">
<File Id="fil438408D952B8B1B35634D8CB6AC81953" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\devices\ind.sym" />
</Component>
<Component Id="cmpA7C868312AA2998E756C854174594924" Guid="{695C45A4-5659-4BAF-AA92-50B45BCA4DBA}">
<File Id="fil51671947E3935F0F431172320F498369" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\devices\intuitive_interface_cheatsheet.sch" />
</Component>
<Component Id="cmpA32CAC0A1DF3B7F35F538DA9C24D5D3A" Guid="{AEC5F1B9-21FC-45F2-9464-409048D28866}">
<File Id="fil9ACA0A21923E69D974EDA529D8F34E0D" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\devices\intuitive_interface_cheatsheet.sym" />
</Component>
<Component Id="cmp294341F9F86AB94C1B0AEAFD7FC6D566" Guid="{474EFB7C-0F16-4764-8354-760E88524DDA}">
<File Id="fil0430089F58EB9E836173E0DA2EDA3AB9" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\devices\iopin.sym" />
</Component>
@ -4879,6 +4885,9 @@
<Component Id="cmp55C89147C2FE0A38848E3A67E4223038" Guid="{A32BB583-AE43-4A9C-8C5C-7D4D3C259164}">
<File Id="fil4BFEDD19767B22A37C178444B7E8B0A9" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\inst_sch_select\comp3_parax.sch" />
</Component>
<Component Id="cmp8AA67096C32B80A0D2DA44B5EAF12BDB" Guid="{76929DB5-DE05-49B8-A0FF-22AF07756FAF}">
<File Id="fil87CEF08A95F6C3093D5A2F72BA6DDAF9" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\inst_sch_select\comp3_pex2.cir" />
</Component>
<Component Id="cmpBCFC92A50A3ACD13A1E5D3364E207668" Guid="{549CD6A0-4C49-48D6-83FA-839CD7B2A9F5}">
<File Id="filA8F6E71AE6F15F66F6223752DEAF3673" KeyPath="yes" Source="$(var.xschemLibrarySrcDir)\inst_sch_select\comp3_read.cir" />
</Component>
@ -5614,6 +5623,8 @@
<ComponentRef Id="cmp611EC17997E3C9AFEFC1A1647A44BE0F" />
<ComponentRef Id="cmp36A0BE2ECAFF9A958BAFB49A67D6D54C" />
<ComponentRef Id="cmp041F77BDEB912A6C325624BA1E63A087" />
<ComponentRef Id="cmpA7C868312AA2998E756C854174594924" />
<ComponentRef Id="cmpA32CAC0A1DF3B7F35F538DA9C24D5D3A" />
<ComponentRef Id="cmp294341F9F86AB94C1B0AEAFD7FC6D566" />
<ComponentRef Id="cmp87878EB0609215678260068375DC8B42" />
<ComponentRef Id="cmpCFFC8F19D59940D9AF5BD022B7F0AA17" />
@ -7191,6 +7202,7 @@
<ComponentRef Id="cmp46876B54A156835169D2D53153CCB721" />
<ComponentRef Id="cmp076623E243053854E2E7CAB7513C2F12" />
<ComponentRef Id="cmp55C89147C2FE0A38848E3A67E4223038" />
<ComponentRef Id="cmp8AA67096C32B80A0D2DA44B5EAF12BDB" />
<ComponentRef Id="cmpBCFC92A50A3ACD13A1E5D3364E207668" />
<ComponentRef Id="cmp3140A9EFC6CD4F9F63FDC7282532537C" />
<ComponentRef Id="cmp8907B142997C1E0613C32A1C536C5122" />

View File

@ -168,6 +168,9 @@
#### initial geometry of load /save / insert component file selector
# set file_dialog_default_geometry 800x600
#### display full path (1) or only name (0) for component directories. Default: 1
# set load_file_dialog_fullpath 1
#### if set to 0, when zooming out allow the viewport do drift toward the mouse position,
#### allowing to move away by zooming / unzooming with mouse wheel
#### default setting: 0
@ -186,6 +189,12 @@
#### default: 0
# set persistent_command 1
#### if set to 1 allow click & drag objects in the schematic
#### to move them without keyboard commands ('m')
#### default: enabled (1)
# set intuitive_interface 0
#### if set to 1 at end of a move operation that stretches wires attached to
#### moved objects these wires will be unselected.
#### default: not enabled (0)
@ -212,6 +221,13 @@
#### use the tclreadline package if available , Default: 1 (enabled).
# set use_tclreadline 1
#### use the dark color scheme (default: 1)
# set dark_colorscheme 1
#### use the dark color scheme for GUI widgets (default: 0)
#### *** This can not be changed after xschem startup ***
# set dark_gui_colorscheme 0
#### disable some symbol layers. Default: none, all layers are visible.
# set enable_layer(5) 0 ;# example to disable pin red boxes
@ -244,6 +260,10 @@
#### instead of looking only in symbol directory. Default: disabled (0).
# set search_schematic 0
#### keep symbols encountered while netlisting / descending the hierarchy.
#### Default: not enabled (0)
# set keep_symbols 0
#### focus the schematic window if mouse goes over it, even if a dialog box
#### is displayed, without needing to click.
#### This allows to move/zoom/pan the schematic while editing attributes.

View File

@ -3880,40 +3880,83 @@ cairo_status_t png_writer(void *in_closure, const unsigned char *in_data, unsign
#endif
#if HAS_CAIRO==1
void inspect_image(cairo_surface_t* surface)
void inspect_image(cairo_surface_t **surface)
{
unsigned char *data, *ptr;
cairo_t *ct;
unsigned char *data;
cairo_surface_t *newsfc;
cairo_format_t format;
int size_x, size_y, stride, x, y;
cairo_surface_flush(surface);
data = cairo_image_surface_get_data(surface);
size_x = cairo_image_surface_get_width(surface);
size_y = cairo_image_surface_get_height(surface);
stride = cairo_image_surface_get_stride(surface);
cairo_surface_flush(*surface);
format = cairo_image_surface_get_format(*surface);
size_x = cairo_image_surface_get_width(*surface);
size_y = cairo_image_surface_get_height(*surface);
stride = cairo_image_surface_get_stride(*surface);
/* add alpha channel if missing */
if(format != CAIRO_FORMAT_ARGB32) {
newsfc = cairo_surface_create_similar_image(*surface, CAIRO_FORMAT_ARGB32, size_x, size_y);
ct = cairo_create(newsfc);
cairo_set_source_surface(ct, *surface, 0, 0);
cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
cairo_paint(ct);
cairo_destroy(ct);
cairo_surface_destroy(*surface);
*surface = newsfc;
}
data = cairo_image_surface_get_data(*surface);
for(x = 0; x < size_x; x++) {
for(y = 0; y < size_y; y++) {
ptr = data + y *stride + x * 4;
unsigned char *ptr = data + y * stride + x * 4;
unsigned int a = ptr[3];
unsigned int r = ptr[2];
unsigned int g = ptr[1];
unsigned int b = ptr[0];
if(x == 0) {
dbg(0, "R=%d G=%d B=%d A=%d\n", ptr[2], ptr[1], ptr[0], ptr[3]);
if(0 && x == 100) {
dbg(0, "R=%d G=%d B=%d A=%d\n", r, g, b, a);
}
#if 1 /* premultiplied data invert*/
r = a - r;
g = a - g;
b = a - b;
#endif
#if 1 /* set (almost) white to transparent */
if(r > 245 && g > 245 && b >245) {r = g = b = a = 0;}
#endif
#if 0 /* set (almost) black to transparent */
if(r < 10 && g < 10 && b < 10) {r = g = b = a = 0;}
#endif
/* write result back */
#if 1
ptr[3] = (unsigned char) a;
ptr[2] = (unsigned char) r;
ptr[1] = (unsigned char) g;
ptr[0] = (unsigned char) b;
#endif
}
}
dbg(0, "size_x = %d, size_y = %d, stride = %d\n", size_x, size_y, stride);
cairo_surface_mark_dirty(*surface);
dbg(1, "size_x = %d, size_y = %d, stride = %d\n", size_x, size_y, stride);
}
#endif
/* rot and flip for rotated / flipped symbols
* dr: 1 draw image
* 0 only load image and build base64
* 0 only load image and build base64
*/
void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip)
int draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip)
{
#if HAS_CAIRO==1
#if defined(HAS_LIBJPEG)
#ifdef INSPECT_IMAGE
int jpeg_quality=75;
#endif
#endif
const char *ptr;
int w,h;
double x, y, rw, rh;
@ -3921,13 +3964,11 @@ void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2
char filename[PATH_MAX];
struct stat buf;
const char *attr ;
char *filter = NULL;
double xx1, yy1, scalex, scaley;
png_to_byte_closure_t closure;
xEmb_image *emb_ptr;
int jpg = 0; /* set to 1 if image_data attribute contains base64 encoded JPEG */
if(xctx->only_probes) return;
if(xctx->only_probes) return 0;
xx1 = *x1; yy1 = *y1; /* image anchor point */
RECTORDER(*x1, *y1, *x2, *y2);
@ -3937,7 +3978,7 @@ void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2
sx2=X_TO_SCREEN(*x2);
sy2=Y_TO_SCREEN(*y2);
if(RECT_OUTSIDE(sx1, sy1, sx2, sy2,
xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2)) return;
xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2)) return 0;
set_rect_extraptr(1, r); /* create r->extraptr pointing to a xEmb_image struct */
emb_ptr = r->extraptr;
if(dr) {
@ -3945,24 +3986,31 @@ void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2
cairo_save(xctx->cairo_save_ctx);
}
my_strncpy(filename, get_tok_value(r->prop_ptr, "image", 0), S(filename));
my_strdup(_ALLOC_ID_, &filter, get_tok_value(r->prop_ptr, "filter", 0));
#if defined(HAS_LIBJPEG)
#ifdef INSPECT_IMAGE
ptr = get_tok_value(r->prop_ptr, "quality", 0);
jpeg_quality = 75;
if(ptr[0]) jpeg_quality = atoi(ptr);
#endif
/* read image from in-memory buffer ... */
#endif
/******* read image from in-memory buffer ... *******/
if(emb_ptr && emb_ptr->image) {
; /* nothing to do, image is already created */
/* ... or read PNG from image_data attribute */
/* nothing to do, image is already created */
/******* ... or read PNG from image_data attribute *******/
} else if( (attr = get_tok_value(r->prop_ptr, "image_data", 0))[0] ) {
png_to_byte_closure_t closure;
size_t data_size;
if(!strncmp(attr, "/9j/", 4)) jpg = 1;
else if(!strncmp(attr, "iVBOR", 5)) jpg = 0;
else jpg = -1; /* some invalid data */
closure.buffer = base64_decode(attr, strlen(attr), &data_size);
closure.pos = 0;
closure.size = data_size; /* should not be necessary */
if(closure.buffer == NULL) {
dbg(0, "draw_image(): image creation failed\n");
return 0;
}
if(jpg == 0) {
emb_ptr->image = cairo_image_surface_create_from_png_stream(png_reader, &closure);
} else if(jpg == 1) {
@ -3970,119 +4018,111 @@ void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2
emb_ptr->image = cairo_image_surface_create_from_jpeg_mem(closure.buffer, closure.size);
#endif
}
if(! emb_ptr->image || cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) {
if(!emb_ptr->image || cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) {
if(jpg != 1)
dbg(0, "draw_image(): failure creating image surface from \"image_data\" attribute\n");
my_free(_ALLOC_ID_, &filter);
my_free(_ALLOC_ID_, &closure.buffer);
return;
return 0;
}
if(closure.buffer == NULL) dbg(0, "draw_image(): image creation failed\n");
my_free(_ALLOC_ID_, &closure.buffer);
dbg(1, "draw_image(): length2 = %d\n", closure.pos);
/* ... or read PNG from file (image attribute) */
/******* ... or read PNG from file (image attribute) *******/
} else if(filename[0] && !stat(filename, &buf)) {
png_to_byte_closure_t closure;
char *encoded_data = NULL;
size_t olength;
if(filter) {
size_t filesize = 0;
char *filedata = NULL;
size_t filtered_img_size = 0;
char *filtered_img_data = NULL;
FILE *fd;
size_t filesize = 0;
char *filedata = NULL;
FILE *fd;
char *filter = NULL;
filesize = (size_t)buf.st_size;
if(filesize) {
fd = fopen(filename, "r");
if(fd) {
size_t bytes_read;
filedata = my_malloc(_ALLOC_ID_, filesize);
if((bytes_read = fread(filedata, 1, filesize, fd)) < filesize) {
filesize = bytes_read;
dbg(0, "draw_image(): less bytes read than expected from %s, got %ld bytes\n", filename, bytes_read);
}
fclose(fd);
}
}
filter_data(filedata, filesize, &filtered_img_data, &filtered_img_size, filter);
if(!strncmp(filtered_img_data, "\x89PNG", 4)) jpg = 0;
else if(!strncmp(filtered_img_data, "\xFF\xD8\xFF", 3)) jpg = 1;
else jpg = -1;
closure.buffer = (unsigned char *)filtered_img_data;
closure.size = filtered_img_size;
closure.pos = 0;
if(jpg == 0) {
emb_ptr->image = cairo_image_surface_create_from_png_stream(png_reader, &closure);
} else if(jpg == 1) {
#if defined(HAS_LIBJPEG)
emb_ptr->image = cairo_image_surface_create_from_jpeg_mem(closure.buffer, closure.size);
#endif
}
if(! emb_ptr->image || cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) {
if(jpg != 1)
dbg(0, "draw_image(): failure creating image surface with filtered data from %s\n", filename);
my_free(_ALLOC_ID_, &filter);
my_free(_ALLOC_ID_, &filedata);
my_free(_ALLOC_ID_, &filtered_img_data);
return;
}
encoded_data = base64_encode((unsigned char *)filtered_img_data, filtered_img_size, &olength, 0);
my_free(_ALLOC_ID_, &filedata);
} else {
FILE *fd;
size_t size = (size_t)buf.st_size >= 5 ? 5 : (size_t)buf.st_size;
char header[5];
header[0] = '\0';
filesize = (size_t)buf.st_size;
if(filesize > 0) {
fd = fopen(filename, "r");
if(fd) {
size_t bytes_read;
if((bytes_read = fread(header, 1, size, fd)) < size) {
size = bytes_read;
filedata = my_malloc(_ALLOC_ID_, filesize);
if((bytes_read = fread(filedata, 1, filesize, fd)) < filesize) {
filesize = bytes_read;
dbg(0, "draw_image(): less bytes read than expected from %s, got %ld bytes\n", filename, bytes_read);
}
fclose(fd);
}
if(!strncmp(header, "\x89PNG", 4)) jpg = 0;
else if(!strncmp(header, "\xFF\xD8\xFF", 3)) jpg = 1;
} else {
dbg(0, "draw_image(): file %s has zero size\n", filename);
return 0;
}
my_strdup(_ALLOC_ID_, &filter, get_tok_value(r->prop_ptr, "filter", 0));
if(filter) {
size_t filtered_img_size = 0;
char *filtered_img_data = NULL;
filter_data(filedata, filesize, &filtered_img_data, &filtered_img_size, filter);
my_free(_ALLOC_ID_, &filedata);
closure.buffer = (unsigned char *)filtered_img_data;
closure.size = filtered_img_size;
closure.pos = 0;
my_free(_ALLOC_ID_, &filter);
} else { /* no filter attribute */
closure.buffer = (unsigned char *)filedata;
filedata = NULL;
closure.size = filesize;
closure.pos = 0;
}
if(closure.size > 4) {
if(!strncmp((char *)closure.buffer, "\x89PNG", 4)) jpg = 0;
else if(!strncmp((char *)closure.buffer, "\xFF\xD8\xFF", 3)) jpg = 1;
else jpg = -1;
closure.buffer = NULL;
} else {
jpg = -1;
}
if(jpg == 0) {
emb_ptr->image = cairo_image_surface_create_from_png_stream(png_reader, &closure);
} else if(jpg == 1) {
#if defined(HAS_LIBJPEG)
emb_ptr->image = cairo_image_surface_create_from_jpeg_mem(closure.buffer, closure.size);
#endif
}
if(!emb_ptr->image || cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) {
if(jpg != 1) dbg(0, "draw_image(): failure creating image surface from %s\n", filename);
my_free(_ALLOC_ID_, &closure.buffer);
return 0;
}
/* this code can be used to transfer an image surface back to a memory buffer
* closure.buffer will hold the data, closure.pos wil be set to the size */
#ifdef INSPECT_IMAGE
inspect_image(&emb_ptr->image);
if(jpg == 0) {
/* write PNG to in-memory buffer */
my_free(_ALLOC_ID_, &closure.buffer);
closure.size = 0;
closure.pos = 0;
if(jpg == 0) {
emb_ptr->image = cairo_image_surface_create_from_png(filename);
} else if(jpg == 1) {
#if defined(HAS_LIBJPEG)
emb_ptr->image = cairo_image_surface_create_from_jpeg(filename);
#endif
}
if(! emb_ptr->image || cairo_surface_status(emb_ptr->image) != CAIRO_STATUS_SUCCESS) {
if(jpg != 1) dbg(0, "draw_image(): failure creating image surface from %s\n", filename);
my_free(_ALLOC_ID_, &filter);
return;
}
if(jpg == 0) {
/* write PNG to in-memory buffer */
cairo_surface_write_to_png_stream(emb_ptr->image, png_writer, &closure);
} else if(jpg == 1) {
/* write JPG to in-memory buffer */
#if defined(HAS_LIBJPEG)
cairo_image_surface_write_to_jpeg_mem(emb_ptr->image, &closure.buffer, &closure.pos, jpeg_quality);
#endif
}
encoded_data = base64_encode(closure.buffer, closure.pos, &olength, 0);
cairo_surface_write_to_png_stream(emb_ptr->image, png_writer, &closure);
closure.size = closure.pos;
} else if(jpg == 1) {
/* write JPG to in-memory buffer */
#if defined(HAS_LIBJPEG)
my_free(_ALLOC_ID_, &closure.buffer);
closure.size = 0;
closure.pos = 0;
cairo_image_surface_write_to_jpeg_mem(emb_ptr->image, &closure.buffer, &closure.pos, jpeg_quality);
closure.size = closure.pos;
#endif
}
#endif
/* put base64 encoded data to rect image_data attribute */
encoded_data = base64_encode((unsigned char *)closure.buffer, closure.size, &olength, 0);
my_strdup2(_ALLOC_ID_, &r->prop_ptr, subst_token(r->prop_ptr, "image_data", encoded_data));
my_free(_ALLOC_ID_, &encoded_data);
dbg(1, "draw_image(): length3 = %d\n", closure.pos);
my_free(_ALLOC_ID_, &closure.buffer);
} else {
my_free(_ALLOC_ID_, &filter);
return;
return 0;
}
my_free(_ALLOC_ID_, &filter);
ptr = get_tok_value(r->prop_ptr, "alpha", 0);
alpha = 1.0;
if(ptr[0]) alpha = atof(ptr);
@ -4141,6 +4181,7 @@ void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2
cairo_restore(xctx->cairo_save_ctx);
}
#endif
return 1;
}
static void draw_images_all(void)

View File

@ -460,7 +460,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(!strcmp(argv[1], "closest_object"))
{
char res[100];
const char *type;
const char *type=NULL;
Selected sel;
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}

View File

@ -2131,13 +2131,13 @@ void resetwin(int create_pixmap, int clear_pixmap, int force, int w, int h)
{
unsigned int width = 0, height = 0;
int status;
#ifndef __unix__
HWND hwnd = Tk_GetHWND(xctx->window);
RECT rct;
#else
XWindowAttributes wattr;
#endif
if(has_x) {
#ifndef __unix__
HWND hwnd = Tk_GetHWND(xctx->window);
RECT rct;
#else
XWindowAttributes wattr;
#endif
if(w && h) {
width = w;
height = h;

View File

@ -1227,7 +1227,7 @@ extern int cli_opt_load_initfile;
extern Xschem_ctx *xctx;
/* FUNCTIONS */
extern void draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip);
extern int draw_image(int dr, xRect *r, double *x1, double *y1, double *x2, double *y2, int rot, int flip);
extern int filter_data(const char *din, const size_t ilen,
char **dout, size_t *olen, const char *cmd);
extern int embed_rawfile(const char *rawfile);