Coin Logo Coin3D is Free Software,
published under the BSD 3-clause license.
https://coin3d.github.io
https://www.kongsberg.com/en/kogt/
simage_eps.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) Kongsberg Oil & Gas Technologies
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif /* HAVE_CONFIG_H */
20 
21 #ifdef SIMAGE_EPS_SUPPORT
22 
23 #include <simage_eps.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <math.h>
27 
28 #define ERR_NO_ERROR 0
29 #define ERR_OPEN_WRITE 1
30 
31 static int epserror = ERR_NO_ERROR;
32 
33 int
34 simage_eps_error(char * buffer, int buflen)
35 {
36  switch (epserror) {
37  case ERR_OPEN_WRITE:
38  strncpy(buffer, "EPS loader: Error opening file for writing", buflen);
39  break;
40  }
41  return epserror;
42 }
43 
44 static int
45 encode_ascii85(const unsigned char * in, unsigned char * out)
46 {
47  unsigned int data =
48  ((unsigned int)(in[0])<<24) |
49  ((unsigned int)(in[1])<<16) |
50  ((unsigned int)(in[2])<< 8) |
51  ((unsigned int)(in[3]));
52 
53  if (data == 0) {
54  out[0] = 'z';
55  return 1;
56  }
57  out[4] = (unsigned char) (data%85 + '!');
58  data /= 85;
59  out[3] = (unsigned char) (data%85 + '!');
60  data /= 85;
61  out[2] = (unsigned char) (data%85 + '!');
62  data /= 85;
63  out[1] = (unsigned char) (data%85 + '!');
64  data /= 85;
65  out[0] = (unsigned char) (data%85 + '!');
66  return 5;
67 }
68 
69 static void
70 output_ascii85(FILE * fp,
71  const unsigned char val,
72  unsigned char * tuple,
73  unsigned char * linebuf,
74  int * tuplecnt, int * linecnt,
75  int rowlen,
76  int flush)
77 {
78  int i;
79  if (flush) {
80  /* fill up tuple */
81  for (i = *tuplecnt; i < 4; i++) tuple[i] = 0;
82  }
83  else {
84  tuple[*tuplecnt] = val;
85  (*tuplecnt)++;
86  }
87  if (flush || *tuplecnt == 4) {
88  if (*tuplecnt) {
89  int add = encode_ascii85(tuple, linebuf + *linecnt);
90  if (flush) {
91  if (add == 1) {
92  for (i = 0; i < 5; i++) linebuf[*linecnt+i] = '!';
93  }
94  *linecnt += *tuplecnt + 1;
95  }
96  else *linecnt += add;
97  *tuplecnt = 0;
98  }
99  if (*linecnt >= rowlen) {
100  unsigned char store = linebuf[rowlen];
101  linebuf[rowlen] = 0;
102  fprintf(fp, "%s\n", linebuf);
103  linebuf[rowlen] = store;
104  for (i = rowlen; i < *linecnt; i++) {
105  linebuf[i-rowlen] = linebuf[i];
106  }
107  *linecnt -= rowlen;
108  }
109  if (flush && *linecnt) {
110  linebuf[*linecnt] = 0;
111  fprintf(fp, "%s\n", linebuf);
112  }
113  }
114 }
115 
116 static void
117 flush_ascii85(FILE * fp,
118  unsigned char * tuple,
119  unsigned char * linebuf,
120  int * tuplecnt, int * linecnt,
121  int rowlen)
122 {
123  output_ascii85(fp, 0, tuple, linebuf, tuplecnt, linecnt, rowlen, 1);
124 }
125 
126 int
127 simage_eps_save(const char *filename,
128  const unsigned char * src,
129  int width,
130  int height,
131  int nc)
132 
133 {
134  /*
135  Code adapted from Coin's SoOffscreenRenderer::writeToPostscript().
136  If you find a bug here, remember to correct it in Coin also.
137  */
138 
139 #define ROWLEN 72
140 
141  int size[2];
142  float inchsize[2];
143  int pixelsize[2];
144  int scaledsize[2];
145  float defaultdpi;
146  float dpi;
147  int num;
148  int chan;
149  unsigned char tuple[4];
150  unsigned char linebuf[ROWLEN+5];
151  int tuplecnt;
152  int linecnt;
153  int cnt;
154  FILE * fp = fopen(filename, "wb");
155 
156  if (fp == NULL) {
157  epserror = ERR_OPEN_WRITE;
158  return 0;
159  }
160 
161  size[0] = width;
162  size[1] = height;
163  defaultdpi = 72.0f;
164  dpi = 75.0f;
165  inchsize[0] = 8.5f;
166  inchsize[1] = 11.0f;
167  pixelsize[0] = (int) (inchsize[0]*defaultdpi);
168  pixelsize[1] = (int) (inchsize[1]*defaultdpi);
169 
170  chan = nc <= 2 ? 1 : 3;
171  scaledsize[0] = (int) ceil(((double)size[0])*defaultdpi/dpi);
172  scaledsize[1] = (int) ceil(((double)size[1])*defaultdpi/dpi);
173 
174  fprintf(fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
175  fprintf(fp, "%%%%Pages: 1\n");
176  fprintf(fp, "%%%%PageOrder: Ascend\n");
177  fprintf(fp, "%%%%BoundingBox: 0 %d %d %d\n",
178  pixelsize[1]-scaledsize[1],
179  scaledsize[0],
180  pixelsize[1]);
181  fprintf(fp, "%%%%Creator: simage <https://coin3d.github.io>\n");
182  fprintf(fp, "%%%%EndComments\n");
183 
184  fprintf(fp, "\n");
185  fprintf(fp, "/origstate save def\n");
186  fprintf(fp, "\n");
187  fprintf(fp, "%% workaround for bug in some PS interpreters\n");
188  fprintf(fp, "%% which doesn't skip the ASCII85 EOD marker.\n");
189  fprintf(fp, "/~ {currentfile read pop pop} def\n\n");
190  fprintf(fp, "/image_wd %d def\n", size[0]);
191  fprintf(fp, "/image_ht %d def\n", size[1]);
192  fprintf(fp, "/pos_wd %d def\n", size[0]);
193  fprintf(fp, "/pos_ht %d def\n", size[1]);
194  fprintf(fp, "/image_dpi %g def\n", dpi);
195  fprintf(fp, "/image_scale %g image_dpi div def\n", defaultdpi);
196  fprintf(fp, "/image_chan %d def\n", chan);
197  fprintf(fp, "/xpos_offset 0 image_scale mul def\n");
198  fprintf(fp, "/ypos_offset 0 image_scale mul def\n");
199  fprintf(fp, "/pix_buf_size %d def\n\n", size[0]*chan);
200  fprintf(fp, "/page_ht %g %g mul def\n", inchsize[1], defaultdpi);
201  fprintf(fp, "/page_wd %g %g mul def\n", inchsize[0], defaultdpi);
202  fprintf(fp, "/image_xpos 0 def\n");
203  fprintf(fp, "/image_ypos page_ht pos_ht image_scale mul sub def\n");
204  fprintf(fp, "image_xpos xpos_offset add image_ypos ypos_offset add translate\n");
205  fprintf(fp, "\n");
206  fprintf(fp, "/pix pix_buf_size string def\n");
207  fprintf(fp, "image_wd image_scale mul image_ht image_scale mul scale\n");
208  fprintf(fp, "\n");
209  fprintf(fp, "image_wd image_ht 8\n");
210  fprintf(fp, "[image_wd 0 0 image_ht 0 0]\n");
211  fprintf(fp, "currentfile\n");
212  fprintf(fp, "/ASCII85Decode filter\n");
213  /* fprintf(fp, "/RunLengthDecode filter\n"); FIXME: add later */
214  if (chan == 3) fprintf(fp, "false 3\ncolorimage\n");
215  else fprintf(fp,"image\n");
216 
217  num = size[0] * size[1];
218  tuplecnt = 0;
219  linecnt = 0;
220  cnt = 0;
221 
222  while (cnt < num) {
223  switch (nc) {
224  default: /* avoid warning */
225  case 1:
226  output_ascii85(fp, src[cnt], tuple, linebuf, &tuplecnt, &linecnt, ROWLEN, 0);
227  break;
228  case 2:
229  output_ascii85(fp, src[cnt*2], tuple, linebuf, &tuplecnt, &linecnt, ROWLEN, 0);
230  break;
231  case 3:
232  output_ascii85(fp, src[cnt*3], tuple, linebuf, &tuplecnt, &linecnt, ROWLEN, 0);
233  output_ascii85(fp, src[cnt*3+1], tuple, linebuf, &tuplecnt, &linecnt, ROWLEN, 0);
234  output_ascii85(fp, src[cnt*3+2], tuple, linebuf, &tuplecnt, &linecnt, ROWLEN, 0);
235  break;
236  case 4:
237  output_ascii85(fp, src[cnt*4], tuple, linebuf, &tuplecnt, &linecnt, ROWLEN, 0);
238  output_ascii85(fp, src[cnt*4+1], tuple, linebuf, &tuplecnt, &linecnt, ROWLEN, 0);
239  output_ascii85(fp, src[cnt*4+2], tuple, linebuf, &tuplecnt, &linecnt, ROWLEN, 0);
240  break;
241  }
242  cnt++;
243  }
244 
245  /* flush data in ascii85 encoder */
246  flush_ascii85(fp, tuple, linebuf, &tuplecnt, &linecnt, ROWLEN);
247 
248  fprintf(fp, "~>\n\n"); /* ASCII85 EOD marker */
249  fprintf(fp, "origstate restore\n");
250  fprintf(fp, "\n");
251  fprintf(fp, "%%%%Trailer\n");
252  fprintf(fp, "\n");
253  fprintf(fp, "%%%%EOF\n");
254 
255  fclose(fp);
256  return 1;
257 
258 #undef ROWLEN
259 }
260 
261 
262 #endif /* SIMAGE_EPS_SUPPORT */
char * filename
Definition: stream.c:38
int simage_eps_error(char *buffer, int bufferlen)
int simage_eps_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents)
#define ERR_NO_ERROR