Merge pull request #100 from rafmag/master

Added Ascii85Encoding for better formatted & smaller PS files.
This commit is contained in:
StefanSchippers 2023-01-23 10:56:18 +01:00 committed by GitHub
commit 1069af750a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 155 additions and 83 deletions

9
.gitignore vendored
View File

@ -31,3 +31,12 @@ src/xschem
CMakeLists.txt
.vscode
src/Makefile
scconfig/sccbox
scconfig/configure
scconfig/config.log
scconfig/config.cache
doc/manpages/xschem.1
Makefile.conf
config.h
*.Identifier

View File

@ -104,24 +104,6 @@ typedef struct
size_t pos;
size_t size;
} 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)
{
#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];
* FILE* fp;
*/
unsigned char* hexEncodedJPG = NULL;
unsigned char* ascii85EncodedJpeg;
char* image_data64_ptr = NULL;
cairo_surface_t* surface = 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_image_surface_write_to_jpeg_mem(surface, &jpgData, &fileSize, quality);
/*
* my_snprintf(str, S(str), "%s%s", tclgetvar("XSCHEM_TMP_DIR"), "/temp.jpg");
* cairo_image_surface_write_to_jpeg(surface, str, 100);
* fp = fopen(str, "rb");
* fseek(fp, 0L, SEEK_END);
* fileSize = ftell(fp);
* rewind(fp);
* jpgData = my_malloc(1662, fileSize);
* fread(jpgData, sizeof(jpgData[0]), fileSize, fp);
* fclose(fp);
*/
hexEncodedJPG = bin2hex(jpgData, fileSize);
free(jpgData);
fprintf(fd, "gsave\n");
cairo_image_surface_write_to_jpeg_mem(surface, &jpgData, &fileSize, 100);
int oLength;
ascii85EncodedJpeg = ascii85_encode(jpgData, fileSize, &oLength, 0);
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, "%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");
fprintf(fd, "/DeviceRGB setcolorspace\n");
fprintf(fd, "{ << /ImageType 1\n");
fprintf(fd, " /Width %g\n", (double)png_size_x);
fprintf(fd, " /Height %g\n", (double)png_size_y);
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);
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, " /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, " /ImageMatrix [%g 0 0 %g %g 0]\n", (double)png_size_y, (double)png_size_x, (double)png_size_x);
else fprintf(fd, " /ImageMatrix [%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);
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, " /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, " /ImageMatrix [%g 0 0 %g 0 0]\n", -(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");
cairo_surface_destroy(surface);
my_free(1663, &hexEncodedJPG);
my_free(1663, &ascii85EncodedJpeg);
free(jpgData);
#endif
}
@ -273,7 +265,7 @@ void ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, double ry2)
* FILE* fp;
* static char str[PATH_MAX];
*/
unsigned char *hexEncodedJPG;
unsigned char *ascii85EncodedJpeg;
int quality=100;
const char *quality_attr;
@ -331,19 +323,9 @@ void ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, double ry2)
}
#endif
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);
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);
draw();
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 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, "%d\n", rhi);
fprintf(fd, "8\n");
fprintf(fd, "[%d 0 0 %d 0 0]\n", rwi, rhi);
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, "/DeviceRGB setcolorspace\n");
fprintf(fd, "{ << /ImageType 1\n");
fprintf(fd, " /Width %d\n", rwi);
fprintf(fd, " /Height %d\n", rhi);
fprintf(fd, " /ImageMatrix [%d 0 0 %d 0 0]\n", rwi, rhi);
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, "grestore\n");
my_free(1666, &hexEncodedJPG);
my_free(1666, &ascii85EncodedJpeg);
#endif
}
static void set_lw(void)
@ -993,6 +995,7 @@ void create_ps(char **psfile, int what)
return;
}
}
setbuf(fd, NULL); //To prevent buffer errors, still investigating cause.
ps_colors=my_calloc(311, cadlayers, sizeof(Ps_color));
if(ps_colors==NULL){
fprintf(errfp, "create_ps(): calloc error\n");

View File

@ -285,6 +285,65 @@ unsigned char *base64_decode(const char *data, const size_t input_length, size_t
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 */
/* read the binary portion of a ngspice raw simulation file
* data layout in memory arranged to maximize cache locality

View File

@ -1085,6 +1085,7 @@ extern int set_rect_flags(xRect *r);
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 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 void free_rawfile(int dr);
extern int raw_read(const char *f, const char *type);