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
|
||||
.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 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");
|
||||
|
|
|
|||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue