Merge pull request #100 from rafmag/master
Added Ascii85Encoding for better formatted & smaller PS files.
This commit is contained in:
commit
1069af750a
|
|
@ -31,3 +31,12 @@ src/xschem
|
||||||
CMakeLists.txt
|
CMakeLists.txt
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
|
src/Makefile
|
||||||
|
scconfig/sccbox
|
||||||
|
scconfig/configure
|
||||||
|
scconfig/config.log
|
||||||
|
scconfig/config.cache
|
||||||
|
doc/manpages/xschem.1
|
||||||
|
Makefile.conf
|
||||||
|
config.h
|
||||||
|
*.Identifier
|
||||||
169
src/psprint.c
169
src/psprint.c
|
|
@ -104,24 +104,6 @@ typedef struct
|
||||||
size_t pos;
|
size_t pos;
|
||||||
size_t size;
|
size_t size;
|
||||||
} png_to_byte_closure_t;
|
} png_to_byte_closure_t;
|
||||||
|
|
||||||
unsigned char* bin2hex(const unsigned char* bin, size_t len)
|
|
||||||
{
|
|
||||||
unsigned char* out;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (bin == NULL || len == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
out = my_malloc(1665, len * 2 + 1);
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
out[i * 2] = "0123456789abcdef"[bin[i] >> 4];
|
|
||||||
out[i * 2 + 1] = "0123456789abcdef"[bin[i] & 0x0F];
|
|
||||||
}
|
|
||||||
out[len * 2] = '\0';
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, int flip)
|
void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, int flip)
|
||||||
{
|
{
|
||||||
#if defined(HAS_LIBJPEG) && defined(HAS_CAIRO)
|
#if defined(HAS_LIBJPEG) && defined(HAS_CAIRO)
|
||||||
|
|
@ -135,7 +117,7 @@ void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, i
|
||||||
/* static char str[PATH_MAX];
|
/* static char str[PATH_MAX];
|
||||||
* FILE* fp;
|
* FILE* fp;
|
||||||
*/
|
*/
|
||||||
unsigned char* hexEncodedJPG = NULL;
|
unsigned char* ascii85EncodedJpeg;
|
||||||
char* image_data64_ptr = NULL;
|
char* image_data64_ptr = NULL;
|
||||||
cairo_surface_t* surface = NULL;
|
cairo_surface_t* surface = NULL;
|
||||||
unsigned char* jpgData = NULL;
|
unsigned char* jpgData = NULL;
|
||||||
|
|
@ -205,57 +187,67 @@ void ps_drawPNG(xRect* r, double x1, double y1, double x2, double y2, int rot, i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cairo_surface_mark_dirty(surface);
|
cairo_surface_mark_dirty(surface);
|
||||||
cairo_image_surface_write_to_jpeg_mem(surface, &jpgData, &fileSize, quality);
|
cairo_image_surface_write_to_jpeg_mem(surface, &jpgData, &fileSize, 100);
|
||||||
/*
|
|
||||||
* my_snprintf(str, S(str), "%s%s", tclgetvar("XSCHEM_TMP_DIR"), "/temp.jpg");
|
int oLength;
|
||||||
* cairo_image_surface_write_to_jpeg(surface, str, 100);
|
ascii85EncodedJpeg = ascii85_encode(jpgData, fileSize, &oLength, 0);
|
||||||
* fp = fopen(str, "rb");
|
|
||||||
* fseek(fp, 0L, SEEK_END);
|
fprintf(fd, "gsave\n");
|
||||||
* fileSize = ftell(fp);
|
fprintf(fd, "save\n");
|
||||||
* rewind(fp);
|
fprintf(fd, "/RawData currentfile /ASCII85Decode filter def\n");
|
||||||
* jpgData = my_malloc(1662, fileSize);
|
fprintf(fd, "/Data RawData << >> /DCTDecode filter def\n");
|
||||||
* fread(jpgData, sizeof(jpgData[0]), fileSize, fp);
|
|
||||||
* fclose(fp);
|
|
||||||
*/
|
|
||||||
hexEncodedJPG = bin2hex(jpgData, fileSize);
|
|
||||||
free(jpgData);
|
|
||||||
fprintf(fd, "gsave\n");
|
|
||||||
fprintf(fd, "%g %g translate\n", X_TO_PS(x1), Y_TO_PS(y1));
|
fprintf(fd, "%g %g translate\n", X_TO_PS(x1), Y_TO_PS(y1));
|
||||||
if(rot==1) fprintf(fd, "90 rotate\n");
|
if(rot==1) fprintf(fd, "90 rotate\n");
|
||||||
if(rot==2) fprintf(fd, "180 rotate\n");
|
if(rot==2) fprintf(fd, "180 rotate\n");
|
||||||
if(rot==3) fprintf(fd, "270 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 %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, "/DeviceRGB setcolorspace\n");
|
||||||
fprintf(fd, "%g\n", (double)png_size_y);
|
fprintf(fd, "{ << /ImageType 1\n");
|
||||||
fprintf(fd, "8\n");
|
fprintf(fd, " /Width %g\n", (double)png_size_x);
|
||||||
|
fprintf(fd, " /Height %g\n", (double)png_size_y);
|
||||||
|
|
||||||
if(!flip)
|
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);
|
if(rot==1) fprintf(fd, " /ImageMatrix [%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==2) fprintf(fd, " /ImageMatrix [%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 if(rot==3) fprintf(fd, " /ImageMatrix [%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 fprintf(fd, " /ImageMatrix [%g 0 0 %g 0 0]\n", (double)png_size_x, (double)png_size_y);
|
||||||
}
|
}
|
||||||
else
|
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);
|
if(rot==1) fprintf(fd, " /ImageMatrix [%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==2) fprintf(fd, " /ImageMatrix [%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 if(rot==3) fprintf(fd, " /ImageMatrix [%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);
|
else fprintf(fd, " /ImageMatrix [%g 0 0 %g %g 0]\n", -(double)png_size_x, (double)png_size_y, (double)png_size_x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(fd, " /DataSource Data\n");
|
||||||
|
fprintf(fd, " /BitsPerComponent 8\n");
|
||||||
|
fprintf(fd, " /Decode [0 1 0 1 0 1]\n");
|
||||||
|
fprintf(fd, " >> image\n");
|
||||||
|
fprintf(fd, " Data closefile\n");
|
||||||
|
fprintf(fd, " RawData flushfile\n");
|
||||||
|
fprintf(fd, " restore\n");
|
||||||
|
fprintf(fd, "} exec\n");
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (int i = 0; i < oLength; i++)
|
||||||
|
{
|
||||||
|
fputc(ascii85EncodedJpeg[i],fd);
|
||||||
|
idx++;
|
||||||
|
if(idx==64)
|
||||||
|
{
|
||||||
|
idx=0;
|
||||||
|
fputc('\n',fd);
|
||||||
|
//if (ascii85Encode[i+1]=='%') idx=63; imageMagic does this for some reason?! Doesn't seem to be necesary.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(fd, "~>\n");
|
||||||
|
|
||||||
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, "grestore\n");
|
||||||
cairo_surface_destroy(surface);
|
cairo_surface_destroy(surface);
|
||||||
my_free(1663, &hexEncodedJPG);
|
my_free(1663, &ascii85EncodedJpeg);
|
||||||
|
free(jpgData);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,7 +265,7 @@ void ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, double ry2)
|
||||||
* FILE* fp;
|
* FILE* fp;
|
||||||
* static char str[PATH_MAX];
|
* static char str[PATH_MAX];
|
||||||
*/
|
*/
|
||||||
unsigned char *hexEncodedJPG;
|
unsigned char *ascii85EncodedJpeg;
|
||||||
int quality=100;
|
int quality=100;
|
||||||
const char *quality_attr;
|
const char *quality_attr;
|
||||||
|
|
||||||
|
|
@ -331,19 +323,9 @@ void ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, double ry2)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
cairo_image_surface_write_to_jpeg_mem(png_sfc, &jpgData, &fileSize, quality);
|
cairo_image_surface_write_to_jpeg_mem(png_sfc, &jpgData, &fileSize, quality);
|
||||||
/*
|
|
||||||
* my_snprintf(str, S(str), "%s%s", tclgetvar("XSCHEM_TMP_DIR"), "/temp.jpg");
|
|
||||||
* cairo_image_surface_write_to_jpeg(png_sfc, str, 100);
|
|
||||||
* fp = fopen(str, "rb");
|
|
||||||
* fseek(fp, 0L, SEEK_END);
|
|
||||||
* fileSize = ftell(fp);
|
|
||||||
* rewind(fp);
|
|
||||||
* jpgData = my_malloc(1668, fileSize);
|
|
||||||
* fread(jpgData, sizeof(jpgData[0]), fileSize, fp);
|
|
||||||
* fclose(fp);
|
|
||||||
*/
|
|
||||||
|
|
||||||
hexEncodedJPG = bin2hex(jpgData, fileSize);
|
int oLength;
|
||||||
|
ascii85EncodedJpeg = ascii85_encode(jpgData, fileSize, &oLength, 0);
|
||||||
free(jpgData);
|
free(jpgData);
|
||||||
|
|
||||||
cairo_surface_destroy(png_sfc);
|
cairo_surface_destroy(png_sfc);
|
||||||
|
|
@ -358,23 +340,43 @@ void ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, double ry2)
|
||||||
build_colors(0, 0);
|
build_colors(0, 0);
|
||||||
draw();
|
draw();
|
||||||
fprintf(fd, "gsave\n");
|
fprintf(fd, "gsave\n");
|
||||||
|
fprintf(fd, "save\n");
|
||||||
|
fprintf(fd, "/RawData currentfile /ASCII85Decode filter def\n");
|
||||||
|
fprintf(fd, "/Data RawData << >> /DCTDecode filter def\n");
|
||||||
fprintf(fd, "%f %f translate\n", X_TO_PS(rx1), Y_TO_PS(ry1));
|
fprintf(fd, "%f %f translate\n", X_TO_PS(rx1), Y_TO_PS(ry1));
|
||||||
fprintf(fd, "%f %f scale\n", X_TO_PS(rx2) - X_TO_PS(rx1), Y_TO_PS(ry2) - Y_TO_PS(ry1));
|
fprintf(fd, "%f %f scale\n", X_TO_PS(rx2) - X_TO_PS(rx1), Y_TO_PS(ry2) - Y_TO_PS(ry1));
|
||||||
fprintf(fd, "%d\n", rwi);
|
fprintf(fd, "/DeviceRGB setcolorspace\n");
|
||||||
fprintf(fd, "%d\n", rhi);
|
fprintf(fd, "{ << /ImageType 1\n");
|
||||||
fprintf(fd, "8\n");
|
fprintf(fd, " /Width %d\n", rwi);
|
||||||
fprintf(fd, "[%d 0 0 %d 0 0]\n", rwi, rhi);
|
fprintf(fd, " /Height %d\n", rhi);
|
||||||
fprintf(fd, "(%s)\n", hexEncodedJPG);
|
fprintf(fd, " /ImageMatrix [%d 0 0 %d 0 0]\n", rwi, rhi);
|
||||||
fprintf(fd, "/ASCIIHexDecode\n");
|
fprintf(fd, " /DataSource Data\n");
|
||||||
fprintf(fd, "filter\n");
|
fprintf(fd, " /BitsPerComponent 8\n");
|
||||||
fprintf(fd, "0 dict\n");
|
fprintf(fd, " /Decode [0 1 0 1 0 1]\n");
|
||||||
fprintf(fd, "/DCTDecode\n");
|
fprintf(fd, " >> image\n");
|
||||||
fprintf(fd, "filter\n");
|
fprintf(fd, " Data closefile\n");
|
||||||
fprintf(fd, "false\n");
|
fprintf(fd, " RawData flushfile\n");
|
||||||
fprintf(fd, "3\n");
|
fprintf(fd, " restore\n");
|
||||||
fprintf(fd, "colorimage\n");
|
fprintf(fd, "} exec\n");
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for (int i = 0; i < oLength; i++)
|
||||||
|
{
|
||||||
|
fputc(ascii85EncodedJpeg[i],fd);
|
||||||
|
idx++;
|
||||||
|
if(idx==64)
|
||||||
|
{
|
||||||
|
idx=0;
|
||||||
|
fputc('\n',fd);
|
||||||
|
//if (ascii85Encode[i+1]=='%') idx=63; imageMagic does this for some reason?! Doesn't seem to be necesary.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(fd, "~>\n");
|
||||||
|
|
||||||
fprintf(fd, "grestore\n");
|
fprintf(fd, "grestore\n");
|
||||||
my_free(1666, &hexEncodedJPG);
|
|
||||||
|
my_free(1666, &ascii85EncodedJpeg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
static void set_lw(void)
|
static void set_lw(void)
|
||||||
|
|
@ -993,6 +995,7 @@ void create_ps(char **psfile, int what)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setbuf(fd, NULL); //To prevent buffer errors, still investigating cause.
|
||||||
ps_colors=my_calloc(311, cadlayers, sizeof(Ps_color));
|
ps_colors=my_calloc(311, cadlayers, sizeof(Ps_color));
|
||||||
if(ps_colors==NULL){
|
if(ps_colors==NULL){
|
||||||
fprintf(errfp, "create_ps(): calloc error\n");
|
fprintf(errfp, "create_ps(): calloc error\n");
|
||||||
|
|
|
||||||
59
src/save.c
59
src/save.c
|
|
@ -285,6 +285,65 @@ unsigned char *base64_decode(const char *data, const size_t input_length, size_t
|
||||||
return decoded_data;
|
return decoded_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Caller should free returned buffer */
|
||||||
|
/* set brk to 1 if you want newlines added */
|
||||||
|
char *ascii85_encode(const unsigned char *data, const size_t input_length, size_t *output_length, int brk) {
|
||||||
|
static const char b85_enc[] = {
|
||||||
|
'!', '"', '#', '$', '%', '&', '\'', '(',
|
||||||
|
')', '*', '+', ',', '-', '.', '/', '0',
|
||||||
|
'1', '2', '3', '4', '5', '6', '7', '8',
|
||||||
|
'9', ':', ';', '<', '=', '>', '?', '@',
|
||||||
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||||
|
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||||
|
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||||
|
'Y', 'Z', '[', '\\', ']', '^', '_', '`',
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
||||||
|
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
|
||||||
|
'q', 'r', 's', 't', 'u'
|
||||||
|
};
|
||||||
|
|
||||||
|
int padding = (4-(input_length % 4))%4;
|
||||||
|
unsigned char *paddedData = my_calloc(1469, input_length+padding, 1);
|
||||||
|
memcpy( paddedData, data, input_length);
|
||||||
|
*output_length = 5*(input_length+padding)/4;
|
||||||
|
char *encoded_data = my_malloc(1469, *output_length +1);
|
||||||
|
encoded_data[*output_length]=0;
|
||||||
|
int idx = 0;
|
||||||
|
for (int i = 0; i < input_length+padding; i+=4)
|
||||||
|
{
|
||||||
|
u_int32_t val = ((u_int32_t)(paddedData[i])<<24) + ((u_int32_t)(paddedData[i+1])<<16) + ((u_int32_t)(paddedData[i+2])<<8) + ((u_int32_t)(paddedData[i+3]));
|
||||||
|
if (val==0)
|
||||||
|
{
|
||||||
|
encoded_data[idx]='z';
|
||||||
|
*output_length-=4;
|
||||||
|
idx++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
encoded_data[idx] = val / pow(85,4);
|
||||||
|
val = val - encoded_data[idx] * pow(85,4);
|
||||||
|
encoded_data[idx]=b85_enc[encoded_data[idx]];
|
||||||
|
idx++;
|
||||||
|
encoded_data[idx] = val / pow(85,3);
|
||||||
|
val = val - encoded_data[idx] * pow(85,3);
|
||||||
|
encoded_data[idx]=b85_enc[encoded_data[idx]];
|
||||||
|
idx++;
|
||||||
|
encoded_data[idx] = val / pow(85,2);
|
||||||
|
val = val - encoded_data[idx] * pow(85,2);
|
||||||
|
encoded_data[idx]=b85_enc[encoded_data[idx]];
|
||||||
|
idx++;
|
||||||
|
encoded_data[idx] = val / pow(85,1);
|
||||||
|
val = val - encoded_data[idx] * pow(85,1);
|
||||||
|
encoded_data[idx]=b85_enc[encoded_data[idx]];
|
||||||
|
idx++;
|
||||||
|
encoded_data[idx] = val;
|
||||||
|
encoded_data[idx]=b85_enc[encoded_data[idx]];
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
*output_length-=padding;
|
||||||
|
encoded_data[*output_length]=0;
|
||||||
|
return encoded_data;
|
||||||
|
}
|
||||||
|
|
||||||
/* SPICE RAWFILE ROUTINES */
|
/* SPICE RAWFILE ROUTINES */
|
||||||
/* read the binary portion of a ngspice raw simulation file
|
/* read the binary portion of a ngspice raw simulation file
|
||||||
* data layout in memory arranged to maximize cache locality
|
* data layout in memory arranged to maximize cache locality
|
||||||
|
|
|
||||||
|
|
@ -1085,6 +1085,7 @@ extern int set_rect_flags(xRect *r);
|
||||||
extern int set_rect_extraptr(int what, xRect *drptr);
|
extern int set_rect_extraptr(int what, xRect *drptr);
|
||||||
extern unsigned char *base64_decode(const char *data, const size_t input_length, size_t *output_length);
|
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 char *base64_encode(const unsigned char *data, const size_t input_length, size_t *output_length, int brk);
|
||||||
|
extern char *ascii85_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 int get_raw_index(const char *node);
|
||||||
extern void free_rawfile(int dr);
|
extern void free_rawfile(int dr);
|
||||||
extern int raw_read(const char *f, const char *type);
|
extern int raw_read(const char *f, const char *type);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue