xref: /petsc/src/sys/classes/draw/utils/image.c (revision 8067a7d5d1c29607366ed2aff819d529007817c0)
1*8067a7d5SLisandro Dalcin #include <petsc/private/petscimpl.h>         /*I "petscsys.h" I*/
2*8067a7d5SLisandro Dalcin 
3*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSave(const char[],const char[],unsigned char[][3],unsigned int,unsigned int,const unsigned char[]);
4*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieSave(const char[],PetscInt,const char[],const char[]);
5*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageCheckFormat(const char *[]);
6*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieCheckFormat(const char *[]);
7*8067a7d5SLisandro Dalcin 
8*8067a7d5SLisandro Dalcin /*
9*8067a7d5SLisandro Dalcin    Code to write images in PPM format
10*8067a7d5SLisandro Dalcin */
11*8067a7d5SLisandro Dalcin #undef __FUNCT__
12*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSavePPM"
13*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSavePPM(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
14*8067a7d5SLisandro Dalcin {
15*8067a7d5SLisandro Dalcin   int            fd;
16*8067a7d5SLisandro Dalcin   char           header[32];
17*8067a7d5SLisandro Dalcin   size_t         hdrlen;
18*8067a7d5SLisandro Dalcin   unsigned char  *rgb;
19*8067a7d5SLisandro Dalcin   PetscErrorCode ierr;
20*8067a7d5SLisandro Dalcin 
21*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
22*8067a7d5SLisandro Dalcin   PetscValidCharPointer(filename,1);
23*8067a7d5SLisandro Dalcin   if (palette) PetscValidCharPointer(palette,2);
24*8067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,5);
25*8067a7d5SLisandro Dalcin   /* map pixels to RGB colors */
26*8067a7d5SLisandro Dalcin   if (palette) {
27*8067a7d5SLisandro Dalcin     int k,p,n = (int)(w*h);
28*8067a7d5SLisandro Dalcin     const unsigned char *colordef;
29*8067a7d5SLisandro Dalcin     ierr = PetscMalloc1(3*w*h,&rgb);CHKERRQ(ierr);
30*8067a7d5SLisandro Dalcin     for (k=p=0; k<n; k++) {
31*8067a7d5SLisandro Dalcin       colordef = palette[pixels[k]];
32*8067a7d5SLisandro Dalcin       rgb[p++] = colordef[0];
33*8067a7d5SLisandro Dalcin       rgb[p++] = colordef[1];
34*8067a7d5SLisandro Dalcin       rgb[p++] = colordef[2];
35*8067a7d5SLisandro Dalcin     }
36*8067a7d5SLisandro Dalcin   } else { /* assume pixels are RGB colors */
37*8067a7d5SLisandro Dalcin     rgb = (unsigned char*)pixels;
38*8067a7d5SLisandro Dalcin   }
39*8067a7d5SLisandro Dalcin   /* open file and write PPM header */
40*8067a7d5SLisandro Dalcin   ierr = PetscBinaryOpen(filename,FILE_MODE_WRITE,&fd);CHKERRQ(ierr);
41*8067a7d5SLisandro Dalcin   ierr = PetscSNPrintf(header,sizeof(header),"P6\n%d %d\n255\n\0",(int)w,(int)h);CHKERRQ(ierr);
42*8067a7d5SLisandro Dalcin   ierr = PetscStrlen(header,&hdrlen);CHKERRQ(ierr);
43*8067a7d5SLisandro Dalcin   ierr = PetscBinaryWrite(fd,header,hdrlen,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
44*8067a7d5SLisandro Dalcin   /* write image data and close file */
45*8067a7d5SLisandro Dalcin   ierr = PetscBinaryWrite(fd,rgb,3*w*h,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
46*8067a7d5SLisandro Dalcin   ierr = PetscBinaryClose(fd);CHKERRQ(ierr);
47*8067a7d5SLisandro Dalcin   if (palette) {ierr = PetscFree(rgb);CHKERRQ(ierr);}
48*8067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
49*8067a7d5SLisandro Dalcin }
50*8067a7d5SLisandro Dalcin 
51*8067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_PPM(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
52*8067a7d5SLisandro Dalcin { return PetscDrawImageSavePPM(filename,palette,w,h,pixels); }
53*8067a7d5SLisandro Dalcin 
54*8067a7d5SLisandro Dalcin 
55*8067a7d5SLisandro Dalcin /*
56*8067a7d5SLisandro Dalcin    Code to write images in PNG format
57*8067a7d5SLisandro Dalcin */
58*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG)
59*8067a7d5SLisandro Dalcin 
60*8067a7d5SLisandro Dalcin #include <png.h>
61*8067a7d5SLisandro Dalcin 
62*8067a7d5SLisandro Dalcin #if defined(PNG_SETJMP_SUPPORTED)
63*8067a7d5SLisandro Dalcin # ifndef png_jmpbuf
64*8067a7d5SLisandro Dalcin #   define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
65*8067a7d5SLisandro Dalcin # endif
66*8067a7d5SLisandro Dalcin #endif
67*8067a7d5SLisandro Dalcin 
68*8067a7d5SLisandro Dalcin #undef __FUNCT__
69*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSavePNG"
70*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSavePNG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
71*8067a7d5SLisandro Dalcin {
72*8067a7d5SLisandro Dalcin   FILE           *fp;
73*8067a7d5SLisandro Dalcin   png_struct     *png_ptr;
74*8067a7d5SLisandro Dalcin   png_info       *info_ptr;
75*8067a7d5SLisandro Dalcin   unsigned int   row, stride = palette ? w : 3*w;
76*8067a7d5SLisandro Dalcin   PetscErrorCode ierr;
77*8067a7d5SLisandro Dalcin 
78*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
79*8067a7d5SLisandro Dalcin   PetscValidCharPointer(filename,1);
80*8067a7d5SLisandro Dalcin   if (palette) PetscValidCharPointer(palette,2);
81*8067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,5);
82*8067a7d5SLisandro Dalcin 
83*8067a7d5SLisandro Dalcin   /* open file and create libpng structures */
84*8067a7d5SLisandro Dalcin   ierr = PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp);CHKERRQ(ierr);
85*8067a7d5SLisandro Dalcin   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
86*8067a7d5SLisandro Dalcin   if (!png_ptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create PNG context");
87*8067a7d5SLisandro Dalcin   info_ptr = png_create_info_struct(png_ptr);
88*8067a7d5SLisandro Dalcin   if (!info_ptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create PNG context");
89*8067a7d5SLisandro Dalcin 
90*8067a7d5SLisandro Dalcin   /* setup libpng error handling */
91*8067a7d5SLisandro Dalcin #if defined(PNG_SETJMP_SUPPORTED)
92*8067a7d5SLisandro Dalcin   if (setjmp(png_jmpbuf(png_ptr))) {
93*8067a7d5SLisandro Dalcin     png_destroy_write_struct(&png_ptr,&info_ptr);
94*8067a7d5SLisandro Dalcin     (void)PetscFClose(PETSC_COMM_SELF,fp);
95*8067a7d5SLisandro Dalcin     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing PNG file %s",filename);
96*8067a7d5SLisandro Dalcin   }
97*8067a7d5SLisandro Dalcin #endif
98*8067a7d5SLisandro Dalcin 
99*8067a7d5SLisandro Dalcin   /* setup PNG image metadata */
100*8067a7d5SLisandro Dalcin   png_init_io(png_ptr, fp);
101*8067a7d5SLisandro Dalcin   png_set_IHDR(png_ptr, info_ptr, w, h, /*depth*/8,
102*8067a7d5SLisandro Dalcin                palette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB,
103*8067a7d5SLisandro Dalcin                PNG_INTERLACE_NONE,
104*8067a7d5SLisandro Dalcin                PNG_COMPRESSION_TYPE_DEFAULT,
105*8067a7d5SLisandro Dalcin                PNG_FILTER_TYPE_DEFAULT);
106*8067a7d5SLisandro Dalcin   if (palette)
107*8067a7d5SLisandro Dalcin     png_set_PLTE(png_ptr, info_ptr, (png_color*)palette, 256);
108*8067a7d5SLisandro Dalcin 
109*8067a7d5SLisandro Dalcin   /* write PNG image header and data */
110*8067a7d5SLisandro Dalcin   png_write_info(png_ptr, info_ptr);
111*8067a7d5SLisandro Dalcin   for (row = 0; row < h; row++)
112*8067a7d5SLisandro Dalcin     png_write_row(png_ptr, pixels + row*stride);
113*8067a7d5SLisandro Dalcin   png_write_end(png_ptr, NULL);
114*8067a7d5SLisandro Dalcin 
115*8067a7d5SLisandro Dalcin   /* destroy libpng structures and close file */
116*8067a7d5SLisandro Dalcin   png_destroy_write_struct(&png_ptr, &info_ptr);
117*8067a7d5SLisandro Dalcin   ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr);
118*8067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
119*8067a7d5SLisandro Dalcin }
120*8067a7d5SLisandro Dalcin 
121*8067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_PNG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
122*8067a7d5SLisandro Dalcin { return PetscDrawImageSavePNG(filename,palette,w,h,pixels); }
123*8067a7d5SLisandro Dalcin 
124*8067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBPNG*/
125*8067a7d5SLisandro Dalcin 
126*8067a7d5SLisandro Dalcin 
127*8067a7d5SLisandro Dalcin /*
128*8067a7d5SLisandro Dalcin    Code to write images in GIF format
129*8067a7d5SLisandro Dalcin */
130*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB)
131*8067a7d5SLisandro Dalcin 
132*8067a7d5SLisandro Dalcin #include <gif_lib.h>
133*8067a7d5SLisandro Dalcin 
134*8067a7d5SLisandro Dalcin #if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5
135*8067a7d5SLisandro Dalcin #define GifMakeMapObject          MakeMapObject
136*8067a7d5SLisandro Dalcin #define GifFreeMapObject          FreeMapObject
137*8067a7d5SLisandro Dalcin #define EGifOpenFileName(n,b,err) EGifOpenFileName(n,b)
138*8067a7d5SLisandro Dalcin #define EGifOpenFileHandle(h,err) EGifOpenFileName(h)
139*8067a7d5SLisandro Dalcin #define EGifCloseFile(f,err)      EGifCloseFile(f)
140*8067a7d5SLisandro Dalcin #endif
141*8067a7d5SLisandro Dalcin 
142*8067a7d5SLisandro Dalcin #undef __FUNCT__
143*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSaveGIF"
144*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveGIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
145*8067a7d5SLisandro Dalcin {
146*8067a7d5SLisandro Dalcin   int            Row, Error;
147*8067a7d5SLisandro Dalcin   int            Width  = (int)w;
148*8067a7d5SLisandro Dalcin   int            Height = (int)h;
149*8067a7d5SLisandro Dalcin   int            ColorRes   = 8;
150*8067a7d5SLisandro Dalcin   int            ColorCount = 256;
151*8067a7d5SLisandro Dalcin   ColorMapObject *GifCMap = NULL;
152*8067a7d5SLisandro Dalcin   GifFileType    *GifFile = NULL;
153*8067a7d5SLisandro Dalcin # define         SETERRGIF(msg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,msg", GIF file: %s",filename)
154*8067a7d5SLisandro Dalcin # define         CHKERRGIF(msg) do {if (Error != GIF_OK) SETERRGIF(msg);} while(0)
155*8067a7d5SLisandro Dalcin 
156*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
157*8067a7d5SLisandro Dalcin   PetscValidCharPointer(filename,1);
158*8067a7d5SLisandro Dalcin   PetscValidCharPointer(palette,2);
159*8067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,5);
160*8067a7d5SLisandro Dalcin 
161*8067a7d5SLisandro Dalcin   GifCMap = GifMakeMapObject(ColorCount, (GifColorType*)palette); if (!GifCMap) SETERRGIF("Allocating colormap");
162*8067a7d5SLisandro Dalcin   GifFile = EGifOpenFileName(filename, 0, NULL); if (!GifFile) SETERRGIF("Opening");
163*8067a7d5SLisandro Dalcin   Error = EGifPutScreenDesc(GifFile, Width, Height, ColorRes, 0, GifCMap); CHKERRGIF("Writing screen descriptor");
164*8067a7d5SLisandro Dalcin   Error = EGifPutImageDesc(GifFile, 0, 0, Width, Height, 0, NULL); CHKERRGIF("Writing image descriptor");
165*8067a7d5SLisandro Dalcin   for (Row = 0; Row < Height; Row++) {
166*8067a7d5SLisandro Dalcin     Error = EGifPutLine(GifFile, (GifPixelType*)pixels + Row*Width, Width); CHKERRGIF("Writing image pixels");
167*8067a7d5SLisandro Dalcin   }
168*8067a7d5SLisandro Dalcin   Error = EGifCloseFile(GifFile, NULL); CHKERRGIF("Closing");
169*8067a7d5SLisandro Dalcin   GifFreeMapObject(GifCMap); GifCMap = NULL;
170*8067a7d5SLisandro Dalcin 
171*8067a7d5SLisandro Dalcin # undef SETERRGIF
172*8067a7d5SLisandro Dalcin # undef CHKERRGIF
173*8067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
174*8067a7d5SLisandro Dalcin }
175*8067a7d5SLisandro Dalcin 
176*8067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_GIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
177*8067a7d5SLisandro Dalcin { return PetscDrawImageSaveGIF(filename,palette,w,h,pixels); }
178*8067a7d5SLisandro Dalcin 
179*8067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_GIFLIB*/
180*8067a7d5SLisandro Dalcin 
181*8067a7d5SLisandro Dalcin /*
182*8067a7d5SLisandro Dalcin    Code to write images in JPEG format
183*8067a7d5SLisandro Dalcin */
184*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG)
185*8067a7d5SLisandro Dalcin 
186*8067a7d5SLisandro Dalcin #include <jpeglib.h>
187*8067a7d5SLisandro Dalcin 
188*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H)
189*8067a7d5SLisandro Dalcin #include <setjmp.h>
190*8067a7d5SLisandro Dalcin static jmp_buf petsc_jpeg_jumpbuf;
191*8067a7d5SLisandro Dalcin static void petsc_jpeg_error_longjmp (j_common_ptr cinfo) { (void)cinfo; longjmp(petsc_jpeg_jumpbuf,1); }
192*8067a7d5SLisandro Dalcin #endif
193*8067a7d5SLisandro Dalcin 
194*8067a7d5SLisandro Dalcin #undef __FUNCT__
195*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSaveJPG"
196*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveJPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
197*8067a7d5SLisandro Dalcin {
198*8067a7d5SLisandro Dalcin   unsigned char               *rgbpixels;
199*8067a7d5SLisandro Dalcin   FILE                        *fp;
200*8067a7d5SLisandro Dalcin   struct jpeg_compress_struct cinfo;
201*8067a7d5SLisandro Dalcin   struct jpeg_error_mgr       jerr;
202*8067a7d5SLisandro Dalcin   PetscErrorCode              ierr;
203*8067a7d5SLisandro Dalcin 
204*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
205*8067a7d5SLisandro Dalcin   PetscValidCharPointer(filename,1);
206*8067a7d5SLisandro Dalcin   if (palette) PetscValidCharPointer(palette,2);
207*8067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,5);
208*8067a7d5SLisandro Dalcin   /* map pixels to RGB colors */
209*8067a7d5SLisandro Dalcin   if (palette) {
210*8067a7d5SLisandro Dalcin     int k,p,n = (int)(w*h);
211*8067a7d5SLisandro Dalcin     const unsigned char *colordef;
212*8067a7d5SLisandro Dalcin     ierr = PetscMalloc1(3*w*h,&rgbpixels);CHKERRQ(ierr);
213*8067a7d5SLisandro Dalcin     for (k=p=0; k<n; k++) {
214*8067a7d5SLisandro Dalcin       colordef = palette[pixels[k]];
215*8067a7d5SLisandro Dalcin       rgbpixels[p++] = colordef[0];
216*8067a7d5SLisandro Dalcin       rgbpixels[p++] = colordef[1];
217*8067a7d5SLisandro Dalcin       rgbpixels[p++] = colordef[2];
218*8067a7d5SLisandro Dalcin     }
219*8067a7d5SLisandro Dalcin   } else { /* assume pixels are RGB colors */
220*8067a7d5SLisandro Dalcin     rgbpixels = (unsigned char*)pixels;
221*8067a7d5SLisandro Dalcin   }
222*8067a7d5SLisandro Dalcin   ierr = PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp);CHKERRQ(ierr);
223*8067a7d5SLisandro Dalcin 
224*8067a7d5SLisandro Dalcin   cinfo.err = jpeg_std_error(&jerr);
225*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H)
226*8067a7d5SLisandro Dalcin   jerr.error_exit = petsc_jpeg_error_longjmp;
227*8067a7d5SLisandro Dalcin   if (setjmp(petsc_jpeg_jumpbuf)) {
228*8067a7d5SLisandro Dalcin     char message[JMSG_LENGTH_MAX];
229*8067a7d5SLisandro Dalcin     jerr.format_message((j_common_ptr)&cinfo,message);
230*8067a7d5SLisandro Dalcin     jpeg_destroy_compress(&cinfo);
231*8067a7d5SLisandro Dalcin     (void)PetscFClose(PETSC_COMM_SELF,fp);
232*8067a7d5SLisandro Dalcin     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing JPEG file %s\n%s",filename,message);
233*8067a7d5SLisandro Dalcin   }
234*8067a7d5SLisandro Dalcin #endif
235*8067a7d5SLisandro Dalcin   jpeg_create_compress(&cinfo);
236*8067a7d5SLisandro Dalcin   jpeg_stdio_dest(&cinfo,fp);
237*8067a7d5SLisandro Dalcin   cinfo.image_width      = w;
238*8067a7d5SLisandro Dalcin   cinfo.image_height     = h;
239*8067a7d5SLisandro Dalcin   cinfo.input_components = 3;
240*8067a7d5SLisandro Dalcin   cinfo.in_color_space   = JCS_RGB;
241*8067a7d5SLisandro Dalcin   jpeg_set_defaults(&cinfo);
242*8067a7d5SLisandro Dalcin   jpeg_start_compress(&cinfo,TRUE);
243*8067a7d5SLisandro Dalcin   while (cinfo.next_scanline < cinfo.image_height) {
244*8067a7d5SLisandro Dalcin     unsigned char *rowptr = rgbpixels + cinfo.next_scanline * 3*w;
245*8067a7d5SLisandro Dalcin     (void)jpeg_write_scanlines(&cinfo,&rowptr,1);
246*8067a7d5SLisandro Dalcin   }
247*8067a7d5SLisandro Dalcin   jpeg_finish_compress(&cinfo);
248*8067a7d5SLisandro Dalcin   jpeg_destroy_compress(&cinfo);
249*8067a7d5SLisandro Dalcin 
250*8067a7d5SLisandro Dalcin   ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr);
251*8067a7d5SLisandro Dalcin   if (palette) {ierr = PetscFree(rgbpixels);CHKERRQ(ierr);}
252*8067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
253*8067a7d5SLisandro Dalcin }
254*8067a7d5SLisandro Dalcin 
255*8067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_JPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
256*8067a7d5SLisandro Dalcin { return PetscDrawImageSaveJPG(filename,palette,w,h,pixels); }
257*8067a7d5SLisandro Dalcin 
258*8067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBJPEG*/
259*8067a7d5SLisandro Dalcin 
260*8067a7d5SLisandro Dalcin static struct {
261*8067a7d5SLisandro Dalcin   const char      *extension;
262*8067a7d5SLisandro Dalcin   PetscErrorCode (*SaveImage)(const char[],unsigned char[][3],unsigned int,unsigned int,const unsigned char[]);
263*8067a7d5SLisandro Dalcin } PetscDrawImageSaveTable[] = {
264*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG)
265*8067a7d5SLisandro Dalcin   {".png", PetscDrawImageSave_PNG},
266*8067a7d5SLisandro Dalcin #endif
267*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB)
268*8067a7d5SLisandro Dalcin   {".gif", PetscDrawImageSave_GIF},
269*8067a7d5SLisandro Dalcin #endif
270*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG)
271*8067a7d5SLisandro Dalcin   {".jpg", PetscDrawImageSave_JPG},
272*8067a7d5SLisandro Dalcin #endif
273*8067a7d5SLisandro Dalcin   {".ppm", PetscDrawImageSave_PPM}
274*8067a7d5SLisandro Dalcin };
275*8067a7d5SLisandro Dalcin 
276*8067a7d5SLisandro Dalcin #undef __FUNCT__
277*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageCheckFormat"
278*8067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageCheckFormat(const char *ext[])
279*8067a7d5SLisandro Dalcin {
280*8067a7d5SLisandro Dalcin   size_t         k;
281*8067a7d5SLisandro Dalcin   PetscBool      match = PETSC_FALSE;
282*8067a7d5SLisandro Dalcin   PetscErrorCode ierr;
283*8067a7d5SLisandro Dalcin 
284*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
285*8067a7d5SLisandro Dalcin   /* if extension is empty, return default format to caller */
286*8067a7d5SLisandro Dalcin   PetscValidPointer(ext,1);
287*8067a7d5SLisandro Dalcin   if (!*ext || !**ext) {
288*8067a7d5SLisandro Dalcin     *ext = PetscDrawImageSaveTable[0].extension;
289*8067a7d5SLisandro Dalcin     PetscFunctionReturn(0);
290*8067a7d5SLisandro Dalcin   }
291*8067a7d5SLisandro Dalcin   /* check the extension mathes a supported format otherwise */
292*8067a7d5SLisandro Dalcin   PetscValidCharPointer(*ext,1);
293*8067a7d5SLisandro Dalcin   for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) {
294*8067a7d5SLisandro Dalcin     ierr = PetscStrcasecmp(*ext,PetscDrawImageSaveTable[k].extension,&match);CHKERRQ(ierr);
295*8067a7d5SLisandro Dalcin     if (match && PetscDrawImageSaveTable[k].SaveImage) PetscFunctionReturn(0);
296*8067a7d5SLisandro Dalcin   }
297*8067a7d5SLisandro Dalcin   SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",*ext);
298*8067a7d5SLisandro Dalcin   PetscFunctionReturn(PETSC_ERR_SUP);
299*8067a7d5SLisandro Dalcin }
300*8067a7d5SLisandro Dalcin 
301*8067a7d5SLisandro Dalcin #undef __FUNCT__
302*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSave"
303*8067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageSave(const char basename[],const char ext[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
304*8067a7d5SLisandro Dalcin {
305*8067a7d5SLisandro Dalcin   size_t         k;
306*8067a7d5SLisandro Dalcin   PetscBool      match = PETSC_FALSE;
307*8067a7d5SLisandro Dalcin   char           filename[PETSC_MAX_PATH_LEN];
308*8067a7d5SLisandro Dalcin   PetscErrorCode ierr;
309*8067a7d5SLisandro Dalcin 
310*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
311*8067a7d5SLisandro Dalcin   PetscValidCharPointer(basename,1);
312*8067a7d5SLisandro Dalcin   if (ext) PetscValidCharPointer(ext,2);
313*8067a7d5SLisandro Dalcin   if (palette) PetscValidCharPointer(palette,3);
314*8067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,6);
315*8067a7d5SLisandro Dalcin 
316*8067a7d5SLisandro Dalcin   ierr = PetscDrawImageCheckFormat(&ext);CHKERRQ(ierr);
317*8067a7d5SLisandro Dalcin   ierr = PetscSNPrintf(filename,sizeof(filename),"%s%s",basename,ext);CHKERRQ(ierr);
318*8067a7d5SLisandro Dalcin   for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) {
319*8067a7d5SLisandro Dalcin     ierr = PetscStrcasecmp(ext,PetscDrawImageSaveTable[k].extension,&match);CHKERRQ(ierr);
320*8067a7d5SLisandro Dalcin     if (match && PetscDrawImageSaveTable[k].SaveImage) {
321*8067a7d5SLisandro Dalcin       ierr = PetscDrawImageSaveTable[k].SaveImage(filename,palette,w,h,pixels);CHKERRQ(ierr);
322*8067a7d5SLisandro Dalcin       PetscFunctionReturn(0);
323*8067a7d5SLisandro Dalcin     }
324*8067a7d5SLisandro Dalcin   }
325*8067a7d5SLisandro Dalcin   SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",ext);
326*8067a7d5SLisandro Dalcin   PetscFunctionReturn(PETSC_ERR_SUP);
327*8067a7d5SLisandro Dalcin }
328*8067a7d5SLisandro Dalcin 
329*8067a7d5SLisandro Dalcin #undef __FUNCT__
330*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawMovieCheckFormat"
331*8067a7d5SLisandro Dalcin PetscErrorCode PetscDrawMovieCheckFormat(const char *ext[])
332*8067a7d5SLisandro Dalcin {
333*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
334*8067a7d5SLisandro Dalcin   PetscValidPointer(ext,1);
335*8067a7d5SLisandro Dalcin   if (!*ext || !**ext) *ext = ".m4v";
336*8067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
337*8067a7d5SLisandro Dalcin }
338*8067a7d5SLisandro Dalcin 
339*8067a7d5SLisandro Dalcin #undef __FUNCT__
340*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawMovieSave"
341*8067a7d5SLisandro Dalcin PetscErrorCode PetscDrawMovieSave(const char basename[],PetscInt count,const char imext[],const char mvext[])
342*8067a7d5SLisandro Dalcin {
343*8067a7d5SLisandro Dalcin   PetscBool      imgif;
344*8067a7d5SLisandro Dalcin   PetscErrorCode ierr;
345*8067a7d5SLisandro Dalcin 
346*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
347*8067a7d5SLisandro Dalcin   PetscValidCharPointer(basename,1);
348*8067a7d5SLisandro Dalcin   PetscValidCharPointer(imext,3);
349*8067a7d5SLisandro Dalcin   if (mvext) PetscValidCharPointer(mvext,4);
350*8067a7d5SLisandro Dalcin   if (count < 1) PetscFunctionReturn(0);
351*8067a7d5SLisandro Dalcin 
352*8067a7d5SLisandro Dalcin   ierr = PetscStrcasecmp(imext,".gif",&imgif);CHKERRQ(ierr);
353*8067a7d5SLisandro Dalcin   ierr = PetscDrawMovieCheckFormat(&mvext);CHKERRQ(ierr);
354*8067a7d5SLisandro Dalcin 
355*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_POPEN)
356*8067a7d5SLisandro Dalcin   /* use ffmpeg to generate a movie */
357*8067a7d5SLisandro Dalcin   {
358*8067a7d5SLisandro Dalcin     PetscInt i;
359*8067a7d5SLisandro Dalcin     char     filelist[PETSC_MAX_PATH_LEN];
360*8067a7d5SLisandro Dalcin     char     command[64+PETSC_MAX_PATH_LEN*2];
361*8067a7d5SLisandro Dalcin     FILE     *fd;
362*8067a7d5SLisandro Dalcin     if (imgif) {
363*8067a7d5SLisandro Dalcin       ierr = PetscSNPrintf(filelist,sizeof(filelist),"%s/%s.filelist",basename,basename);CHKERRQ(ierr);
364*8067a7d5SLisandro Dalcin       ierr = PetscFOpen(PETSC_COMM_SELF,filelist,"w",&fd);CHKERRQ(ierr);
365*8067a7d5SLisandro Dalcin       ierr = PetscFPrintf(PETSC_COMM_SELF,fd,"# ffmpeg -f concat -i \"%s.filelist\" \"%s%s\"\n",basename,basename,mvext);CHKERRQ(ierr);
366*8067a7d5SLisandro Dalcin       for (i=0; i<count; i++) {ierr = PetscFPrintf(PETSC_COMM_SELF,fd,"file '%s_%d%s'\n",basename,i,imext);CHKERRQ(ierr);}
367*8067a7d5SLisandro Dalcin       ierr = PetscFClose(PETSC_COMM_SELF,fd);CHKERRQ(ierr);
368*8067a7d5SLisandro Dalcin       ierr = PetscSNPrintf(command,sizeof(command),"ffmpeg -loglevel error -f concat -i \"%s/%s.filelist\" \"%s%s\"",basename,basename,basename,mvext);CHKERRQ(ierr);
369*8067a7d5SLisandro Dalcin     } else {
370*8067a7d5SLisandro Dalcin       ierr = PetscSNPrintf(command,sizeof(command),"ffmpeg -loglevel error -i \"%s/%s_%%d%s\" \"%s%s\"",basename,basename,imext,basename,mvext);CHKERRQ(ierr);
371*8067a7d5SLisandro Dalcin     }
372*8067a7d5SLisandro Dalcin     ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr);
373*8067a7d5SLisandro Dalcin     ierr = PetscPClose(PETSC_COMM_SELF,fd,NULL);CHKERRQ(ierr);
374*8067a7d5SLisandro Dalcin   }
375*8067a7d5SLisandro Dalcin #endif
376*8067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
377*8067a7d5SLisandro Dalcin }
378