Re: Help in using gsapi_set_stdio() to capture stdout into a memory buffer
"Joaquim Luis" <[email protected]>
| Newsgroups | gmane.comp.printing.ghostscript.devel |
|---|---|
| Organization | UALG |
| Message-ID | <op.yeg8v3crdbaoe8@macmarilu> |
Ken & Chris Thanks for your replies. Because Chris suggestions sent me to unfamiliar grounds it took me a bit to digest that. I've came out with a solution based on pipes that seam to work. I'm using here the pbmraw device because it's a simple non compressed format so I know how big is the buffer and also because ultimately that's how I want the raster. One question still, where can I learn about the 'bitrgb' device structure? NOTE: the code file is attached, as it was in my first message. Thanks Joaquim > On 16/03/16 01:13, Joaquim Luis wrote: >> Hi, >> >> I am trying to learn how to capture the raster conversion of a PS file >> into memory but it's not being easy. >> The following example (adapted from one posted here before) correctly >> prints in stdout a png version of the small PS embedded in code. I know >> it's correct because I save it into a file I see it is. But my goal is >> to save it in a memory buffer so, as an intermediate step, I wanted to >> save it in file via gsapi_set_stdio. > > This is *known* not to work and there is, in fact, a bug open to that > effect (with a summary of why it doesn't work): > > http://bugs.ghostscript.com/show_bug.cgi?id=694993 > > The trouble is, without changing a fundamental assumption of the device > API, it's unlikely to be possible. > > FWIW, your best solution would be to write your own device. If you are > not doing high resolution or large page work, you could look at using > the "display device". > > Lastly, a possible workable solution would be to use a named pipe: pass > the named pipe to gs for output, and have your code read back from it - > depending on the amount of buffering Windows does on named pipes, you > might need to do some fiddling (maybe theads, maybe separate processes) > to read as data is being written.... if it were me, I'd spawn a separate > process for gs. > > Chris > _______________________________________________ > gs-devel mailing list > [email protected] > http://ghostscript.com/cgi-bin/mailman/listinfo/gs-devel _______________________________________________ gs-devel mailing list [email protected] http://ghostscript.com/cgi-bin/mailman/listinfo/gs-devel
gstest.c
(application/octet-stream, 3.5 KB)
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <process.h>
#include "ierrors.h"
#include "iapi.h"
#ifdef _WIN32
# define dup2 _dup2
# define fileno _fileno
# define close _close
#else
#include <unistd.h>
#endif
char *ps = "newpath\n"
"100 600 moveto 200 650 lineto 100 700 lineto\n"
"closepath\n"
"gsave\n"
"0.5 setgray\n"
"fill\n"
"grestore\n"
"4 setlinewidth\n"
"stroke\n"
"/Times-Roman findfont\n"
"18 scalefont\n"
"setfont\n"
"newpath\n"
"150 600 moveto\n"
"(Julia-Ghostscript in action) show\n"
"/csquare {\n"
"newpath\n"
"0 26 moveto\n"
"0 1 rlineto\n"
"1 0 rlineto\n"
"0 -1 rlineto\n"
"closepath\n"
"setrgbcolor\n"
"fill\n"
"} def\n"
"\n"
"20 20 scale\n"
"\n"
"1 5 translate\n"
"1 0 0 csquare\n"
"\n"
"1 0 translate\n"
"0 1 0 csquare\n"
"\n"
"1 0 translate\n"
"0 0 1 csquare\n"
"showpage";
void *gs_rasterize_free(char *img) {
/* Free memory allocated in this file. Needed because the croos boundary dll on Windows */
free(img);
}
/* stdio functions */
static int GSDLLCALL gsdll_stdin(void *instance, char *buf, int len) {
return 0;
}
static int GSDLLCALL gsdll_stdout(void *instance, const char *str, int len) {
//fprintf(stderr, "MERDA out\n");
//fwrite(str, 1, len, fp);
//fflush(fp);
return len;
}
static int GSDLLCALL gsdll_stderr(void *instance, const char *str, int len) {
fwrite(str, 1, len, stderr);
fflush(stderr);
return len;
}
int main(int argc, char *argv[]) {
int GScode = 0, GSexitCode, n, l2, l3, n_rows, n_cols;
int fd[2];
char buf[1025], t[16] = { "" }, *img;
void *GSinst;
char *GSargs[] = {
//argv[0], "-sDEVICE=pngalpha", "-dBATCH", "-dNOPAUSE", "-sOutputFile=-", "-q"
//argv[0], "-sDEVICE=pbmraw", "-dBATCH", "-dNOPAUSE", "-sOutputFile=-", "-q -r300"
"", "-sDEVICE=pbmraw", "-dBATCH", "-dNOPAUSE", "-sOutputFile=-", "-q -r300"
};
if ((GScode = gsapi_new_instance(&GSinst, NULL )) < 0 ) {
fprintf(stderr, "Ghostscript gsapi_new_instance fail (%d)\n", GScode);
exit(0);
}
gsapi_set_stdio(GSinst, gsdll_stdin, gsdll_stdout, gsdll_stderr);
if ((GScode = gsapi_init_with_args(GSinst, 5, GSargs)) < 0) {
fprintf(stderr, "Ghostscript gsapi_init_with_args fail (%d)\n", GScode);
exit(0);
}
#ifdef _WIN32
_pipe(fd, 104857600000, O_BINARY);
#else
pipe(fd);
#endif
if (dup2(fd[1], fileno(stdout)) != 0)
return 2;
close(fd[1]); // Close original write end of pipe
if (gsapi_run_string(GSinst, ps, 0, &GSexitCode) < 0 ) {
fprintf (stderr, "Error: Could not run gsapi_run_string()\n");
}
n = read(fd[0], buf, 3); /* Consume first header line */
while (read(fd[0], buf, 1) && buf[0] != '\n'); /* OK, by the end of this we are at the end of second header line*/
n = 0;
while (read(fd[0], buf, 1) && buf[0] != ' ') /* Get string with number of columns from 3rth header line */
t[n++] = buf[0];
n_cols = atoi(t);
n = 0;
while (read(fd[0], buf, 1) && buf[0] != '\n') /* Get string with number of rows from 3rth header line */
t[n++] = buf[0];
t[n] = '\0'; /* Make sure no character is left from previous usage */
n_rows = atoi(t);
img = malloc(n_rows * n_cols * 3);
if ((n = read(fd[0], img, n_rows * n_cols * 3)) >= 0) {
fprintf(stderr, "read %d bytes from the pipe:\n %s\n", n, buf);
}
else
perror("read");
fprintf (stderr, "Ghostscript gsapi_run_file OK\n");
}