xref: /petsc/src/sys/classes/draw/utils/image.c (revision 3d242201b367197be0528dc78b79f34d6902871b)
18067a7d5SLisandro Dalcin #include <petsc/private/petscimpl.h>         /*I "petscsys.h" I*/
28067a7d5SLisandro Dalcin 
38067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSave(const char[],const char[],unsigned char[][3],unsigned int,unsigned int,const unsigned char[]);
4*3d242201SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieSave(const char[],PetscInt,const char[],PetscInt,const char[]);
58067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageCheckFormat(const char *[]);
68067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieCheckFormat(const char *[]);
78067a7d5SLisandro Dalcin 
88067a7d5SLisandro Dalcin /*
98067a7d5SLisandro Dalcin    Code to write images in PPM format
108067a7d5SLisandro Dalcin */
118067a7d5SLisandro Dalcin #undef __FUNCT__
128067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSavePPM"
138067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSavePPM(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
148067a7d5SLisandro Dalcin {
158067a7d5SLisandro Dalcin   int            fd;
168067a7d5SLisandro Dalcin   char           header[32];
178067a7d5SLisandro Dalcin   size_t         hdrlen;
188067a7d5SLisandro Dalcin   unsigned char  *rgb;
198067a7d5SLisandro Dalcin   PetscErrorCode ierr;
208067a7d5SLisandro Dalcin 
218067a7d5SLisandro Dalcin   PetscFunctionBegin;
228067a7d5SLisandro Dalcin   PetscValidCharPointer(filename,1);
238067a7d5SLisandro Dalcin   if (palette) PetscValidCharPointer(palette,2);
248067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,5);
258067a7d5SLisandro Dalcin   /* map pixels to RGB colors */
268067a7d5SLisandro Dalcin   if (palette) {
278067a7d5SLisandro Dalcin     int k,p,n = (int)(w*h);
288067a7d5SLisandro Dalcin     const unsigned char *colordef;
298067a7d5SLisandro Dalcin     ierr = PetscMalloc1(3*w*h,&rgb);CHKERRQ(ierr);
308067a7d5SLisandro Dalcin     for (k=p=0; k<n; k++) {
318067a7d5SLisandro Dalcin       colordef = palette[pixels[k]];
328067a7d5SLisandro Dalcin       rgb[p++] = colordef[0];
338067a7d5SLisandro Dalcin       rgb[p++] = colordef[1];
348067a7d5SLisandro Dalcin       rgb[p++] = colordef[2];
358067a7d5SLisandro Dalcin     }
368067a7d5SLisandro Dalcin   } else { /* assume pixels are RGB colors */
378067a7d5SLisandro Dalcin     rgb = (unsigned char*)pixels;
388067a7d5SLisandro Dalcin   }
398067a7d5SLisandro Dalcin   /* open file and write PPM header */
408067a7d5SLisandro Dalcin   ierr = PetscBinaryOpen(filename,FILE_MODE_WRITE,&fd);CHKERRQ(ierr);
418067a7d5SLisandro Dalcin   ierr = PetscSNPrintf(header,sizeof(header),"P6\n%d %d\n255\n\0",(int)w,(int)h);CHKERRQ(ierr);
428067a7d5SLisandro Dalcin   ierr = PetscStrlen(header,&hdrlen);CHKERRQ(ierr);
438067a7d5SLisandro Dalcin   ierr = PetscBinaryWrite(fd,header,hdrlen,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
448067a7d5SLisandro Dalcin   /* write image data and close file */
458067a7d5SLisandro Dalcin   ierr = PetscBinaryWrite(fd,rgb,3*w*h,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
468067a7d5SLisandro Dalcin   ierr = PetscBinaryClose(fd);CHKERRQ(ierr);
478067a7d5SLisandro Dalcin   if (palette) {ierr = PetscFree(rgb);CHKERRQ(ierr);}
488067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
498067a7d5SLisandro Dalcin }
508067a7d5SLisandro Dalcin 
518067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_PPM(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
528067a7d5SLisandro Dalcin { return PetscDrawImageSavePPM(filename,palette,w,h,pixels); }
538067a7d5SLisandro Dalcin 
548067a7d5SLisandro Dalcin 
558067a7d5SLisandro Dalcin /*
568067a7d5SLisandro Dalcin    Code to write images in PNG format
578067a7d5SLisandro Dalcin */
588067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG)
598067a7d5SLisandro Dalcin 
608067a7d5SLisandro Dalcin #include <png.h>
618067a7d5SLisandro Dalcin 
628067a7d5SLisandro Dalcin #if defined(PNG_SETJMP_SUPPORTED)
638067a7d5SLisandro Dalcin # ifndef png_jmpbuf
648067a7d5SLisandro Dalcin #   define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
658067a7d5SLisandro Dalcin # endif
668067a7d5SLisandro Dalcin #endif
678067a7d5SLisandro Dalcin 
688067a7d5SLisandro Dalcin #undef __FUNCT__
698067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSavePNG"
708067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSavePNG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
718067a7d5SLisandro Dalcin {
728067a7d5SLisandro Dalcin   FILE           *fp;
738067a7d5SLisandro Dalcin   png_struct     *png_ptr;
748067a7d5SLisandro Dalcin   png_info       *info_ptr;
758067a7d5SLisandro Dalcin   unsigned int   row, stride = palette ? w : 3*w;
768067a7d5SLisandro Dalcin   PetscErrorCode ierr;
778067a7d5SLisandro Dalcin 
788067a7d5SLisandro Dalcin   PetscFunctionBegin;
798067a7d5SLisandro Dalcin   PetscValidCharPointer(filename,1);
808067a7d5SLisandro Dalcin   if (palette) PetscValidCharPointer(palette,2);
818067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,5);
828067a7d5SLisandro Dalcin 
838067a7d5SLisandro Dalcin   /* open file and create libpng structures */
848067a7d5SLisandro Dalcin   ierr = PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp);CHKERRQ(ierr);
858067a7d5SLisandro Dalcin   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
868067a7d5SLisandro Dalcin   if (!png_ptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create PNG context");
878067a7d5SLisandro Dalcin   info_ptr = png_create_info_struct(png_ptr);
888067a7d5SLisandro Dalcin   if (!info_ptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create PNG context");
898067a7d5SLisandro Dalcin 
908067a7d5SLisandro Dalcin   /* setup libpng error handling */
918067a7d5SLisandro Dalcin #if defined(PNG_SETJMP_SUPPORTED)
928067a7d5SLisandro Dalcin   if (setjmp(png_jmpbuf(png_ptr))) {
938067a7d5SLisandro Dalcin     png_destroy_write_struct(&png_ptr,&info_ptr);
948067a7d5SLisandro Dalcin     (void)PetscFClose(PETSC_COMM_SELF,fp);
958067a7d5SLisandro Dalcin     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing PNG file %s",filename);
968067a7d5SLisandro Dalcin   }
978067a7d5SLisandro Dalcin #endif
988067a7d5SLisandro Dalcin 
998067a7d5SLisandro Dalcin   /* setup PNG image metadata */
1008067a7d5SLisandro Dalcin   png_init_io(png_ptr, fp);
1018067a7d5SLisandro Dalcin   png_set_IHDR(png_ptr, info_ptr, w, h, /*depth*/8,
1028067a7d5SLisandro Dalcin                palette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB,
1038067a7d5SLisandro Dalcin                PNG_INTERLACE_NONE,
1048067a7d5SLisandro Dalcin                PNG_COMPRESSION_TYPE_DEFAULT,
1058067a7d5SLisandro Dalcin                PNG_FILTER_TYPE_DEFAULT);
1068067a7d5SLisandro Dalcin   if (palette)
1078067a7d5SLisandro Dalcin     png_set_PLTE(png_ptr, info_ptr, (png_color*)palette, 256);
1088067a7d5SLisandro Dalcin 
1098067a7d5SLisandro Dalcin   /* write PNG image header and data */
1108067a7d5SLisandro Dalcin   png_write_info(png_ptr, info_ptr);
1118067a7d5SLisandro Dalcin   for (row = 0; row < h; row++)
1128067a7d5SLisandro Dalcin     png_write_row(png_ptr, pixels + row*stride);
1138067a7d5SLisandro Dalcin   png_write_end(png_ptr, NULL);
1148067a7d5SLisandro Dalcin 
1158067a7d5SLisandro Dalcin   /* destroy libpng structures and close file */
1168067a7d5SLisandro Dalcin   png_destroy_write_struct(&png_ptr, &info_ptr);
1178067a7d5SLisandro Dalcin   ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr);
1188067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
1198067a7d5SLisandro Dalcin }
1208067a7d5SLisandro Dalcin 
1218067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_PNG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
1228067a7d5SLisandro Dalcin { return PetscDrawImageSavePNG(filename,palette,w,h,pixels); }
1238067a7d5SLisandro Dalcin 
1248067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBPNG*/
1258067a7d5SLisandro Dalcin 
1268067a7d5SLisandro Dalcin 
1278067a7d5SLisandro Dalcin /*
1288067a7d5SLisandro Dalcin    Code to write images in GIF format
1298067a7d5SLisandro Dalcin */
1308067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB)
1318067a7d5SLisandro Dalcin 
1328067a7d5SLisandro Dalcin #include <gif_lib.h>
1338067a7d5SLisandro Dalcin 
1348067a7d5SLisandro Dalcin #if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5
1358067a7d5SLisandro Dalcin #define GifMakeMapObject          MakeMapObject
1368067a7d5SLisandro Dalcin #define GifFreeMapObject          FreeMapObject
1378067a7d5SLisandro Dalcin #define EGifOpenFileName(n,b,err) EGifOpenFileName(n,b)
1388067a7d5SLisandro Dalcin #define EGifOpenFileHandle(h,err) EGifOpenFileName(h)
1398067a7d5SLisandro Dalcin #define EGifCloseFile(f,err)      EGifCloseFile(f)
1408067a7d5SLisandro Dalcin #endif
1418067a7d5SLisandro Dalcin 
1428067a7d5SLisandro Dalcin #undef __FUNCT__
1438067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSaveGIF"
1448067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveGIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
1458067a7d5SLisandro Dalcin {
1468067a7d5SLisandro Dalcin   int            Row, Error;
1478067a7d5SLisandro Dalcin   int            Width  = (int)w;
1488067a7d5SLisandro Dalcin   int            Height = (int)h;
1498067a7d5SLisandro Dalcin   int            ColorRes   = 8;
1508067a7d5SLisandro Dalcin   int            ColorCount = 256;
1518067a7d5SLisandro Dalcin   ColorMapObject *GifCMap = NULL;
1528067a7d5SLisandro Dalcin   GifFileType    *GifFile = NULL;
1538067a7d5SLisandro Dalcin # define         SETERRGIF(msg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,msg", GIF file: %s",filename)
1548067a7d5SLisandro Dalcin # define         CHKERRGIF(msg) do {if (Error != GIF_OK) SETERRGIF(msg);} while(0)
1558067a7d5SLisandro Dalcin 
1568067a7d5SLisandro Dalcin   PetscFunctionBegin;
1578067a7d5SLisandro Dalcin   PetscValidCharPointer(filename,1);
1588067a7d5SLisandro Dalcin   PetscValidCharPointer(palette,2);
1598067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,5);
1608067a7d5SLisandro Dalcin 
1618067a7d5SLisandro Dalcin   GifCMap = GifMakeMapObject(ColorCount, (GifColorType*)palette); if (!GifCMap) SETERRGIF("Allocating colormap");
1628067a7d5SLisandro Dalcin   GifFile = EGifOpenFileName(filename, 0, NULL); if (!GifFile) SETERRGIF("Opening");
1638067a7d5SLisandro Dalcin   Error = EGifPutScreenDesc(GifFile, Width, Height, ColorRes, 0, GifCMap); CHKERRGIF("Writing screen descriptor");
1648067a7d5SLisandro Dalcin   Error = EGifPutImageDesc(GifFile, 0, 0, Width, Height, 0, NULL); CHKERRGIF("Writing image descriptor");
1658067a7d5SLisandro Dalcin   for (Row = 0; Row < Height; Row++) {
1668067a7d5SLisandro Dalcin     Error = EGifPutLine(GifFile, (GifPixelType*)pixels + Row*Width, Width); CHKERRGIF("Writing image pixels");
1678067a7d5SLisandro Dalcin   }
1688067a7d5SLisandro Dalcin   Error = EGifCloseFile(GifFile, NULL); CHKERRGIF("Closing");
1698067a7d5SLisandro Dalcin   GifFreeMapObject(GifCMap); GifCMap = NULL;
1708067a7d5SLisandro Dalcin 
1718067a7d5SLisandro Dalcin # undef SETERRGIF
1728067a7d5SLisandro Dalcin # undef CHKERRGIF
1738067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
1748067a7d5SLisandro Dalcin }
1758067a7d5SLisandro Dalcin 
1768067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_GIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
1778067a7d5SLisandro Dalcin { return PetscDrawImageSaveGIF(filename,palette,w,h,pixels); }
1788067a7d5SLisandro Dalcin 
1798067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_GIFLIB*/
1808067a7d5SLisandro Dalcin 
1818067a7d5SLisandro Dalcin /*
1828067a7d5SLisandro Dalcin    Code to write images in JPEG format
1838067a7d5SLisandro Dalcin */
1848067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG)
1858067a7d5SLisandro Dalcin 
1868067a7d5SLisandro Dalcin #include <jpeglib.h>
1878067a7d5SLisandro Dalcin 
1888067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H)
1898067a7d5SLisandro Dalcin #include <setjmp.h>
1908067a7d5SLisandro Dalcin static jmp_buf petsc_jpeg_jumpbuf;
1918067a7d5SLisandro Dalcin static void petsc_jpeg_error_longjmp (j_common_ptr cinfo) { (void)cinfo; longjmp(petsc_jpeg_jumpbuf,1); }
1928067a7d5SLisandro Dalcin #endif
1938067a7d5SLisandro Dalcin 
1948067a7d5SLisandro Dalcin #undef __FUNCT__
1958067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSaveJPG"
1968067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveJPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
1978067a7d5SLisandro Dalcin {
1988067a7d5SLisandro Dalcin   unsigned char               *rgbpixels;
1998067a7d5SLisandro Dalcin   FILE                        *fp;
2008067a7d5SLisandro Dalcin   struct jpeg_compress_struct cinfo;
2018067a7d5SLisandro Dalcin   struct jpeg_error_mgr       jerr;
2028067a7d5SLisandro Dalcin   PetscErrorCode              ierr;
2038067a7d5SLisandro Dalcin 
2048067a7d5SLisandro Dalcin   PetscFunctionBegin;
2058067a7d5SLisandro Dalcin   PetscValidCharPointer(filename,1);
2068067a7d5SLisandro Dalcin   if (palette) PetscValidCharPointer(palette,2);
2078067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,5);
2088067a7d5SLisandro Dalcin   /* map pixels to RGB colors */
2098067a7d5SLisandro Dalcin   if (palette) {
2108067a7d5SLisandro Dalcin     int k,p,n = (int)(w*h);
2118067a7d5SLisandro Dalcin     const unsigned char *colordef;
2128067a7d5SLisandro Dalcin     ierr = PetscMalloc1(3*w*h,&rgbpixels);CHKERRQ(ierr);
2138067a7d5SLisandro Dalcin     for (k=p=0; k<n; k++) {
2148067a7d5SLisandro Dalcin       colordef = palette[pixels[k]];
2158067a7d5SLisandro Dalcin       rgbpixels[p++] = colordef[0];
2168067a7d5SLisandro Dalcin       rgbpixels[p++] = colordef[1];
2178067a7d5SLisandro Dalcin       rgbpixels[p++] = colordef[2];
2188067a7d5SLisandro Dalcin     }
2198067a7d5SLisandro Dalcin   } else { /* assume pixels are RGB colors */
2208067a7d5SLisandro Dalcin     rgbpixels = (unsigned char*)pixels;
2218067a7d5SLisandro Dalcin   }
2228067a7d5SLisandro Dalcin   ierr = PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp);CHKERRQ(ierr);
2238067a7d5SLisandro Dalcin 
2248067a7d5SLisandro Dalcin   cinfo.err = jpeg_std_error(&jerr);
2258067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H)
2268067a7d5SLisandro Dalcin   jerr.error_exit = petsc_jpeg_error_longjmp;
2278067a7d5SLisandro Dalcin   if (setjmp(petsc_jpeg_jumpbuf)) {
2288067a7d5SLisandro Dalcin     char message[JMSG_LENGTH_MAX];
2298067a7d5SLisandro Dalcin     jerr.format_message((j_common_ptr)&cinfo,message);
2308067a7d5SLisandro Dalcin     jpeg_destroy_compress(&cinfo);
2318067a7d5SLisandro Dalcin     (void)PetscFClose(PETSC_COMM_SELF,fp);
2328067a7d5SLisandro Dalcin     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing JPEG file %s\n%s",filename,message);
2338067a7d5SLisandro Dalcin   }
2348067a7d5SLisandro Dalcin #endif
2358067a7d5SLisandro Dalcin   jpeg_create_compress(&cinfo);
2368067a7d5SLisandro Dalcin   jpeg_stdio_dest(&cinfo,fp);
2378067a7d5SLisandro Dalcin   cinfo.image_width      = w;
2388067a7d5SLisandro Dalcin   cinfo.image_height     = h;
2398067a7d5SLisandro Dalcin   cinfo.input_components = 3;
2408067a7d5SLisandro Dalcin   cinfo.in_color_space   = JCS_RGB;
2418067a7d5SLisandro Dalcin   jpeg_set_defaults(&cinfo);
2428067a7d5SLisandro Dalcin   jpeg_start_compress(&cinfo,TRUE);
2438067a7d5SLisandro Dalcin   while (cinfo.next_scanline < cinfo.image_height) {
2448067a7d5SLisandro Dalcin     unsigned char *rowptr = rgbpixels + cinfo.next_scanline * 3*w;
2458067a7d5SLisandro Dalcin     (void)jpeg_write_scanlines(&cinfo,&rowptr,1);
2468067a7d5SLisandro Dalcin   }
2478067a7d5SLisandro Dalcin   jpeg_finish_compress(&cinfo);
2488067a7d5SLisandro Dalcin   jpeg_destroy_compress(&cinfo);
2498067a7d5SLisandro Dalcin 
2508067a7d5SLisandro Dalcin   ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr);
2518067a7d5SLisandro Dalcin   if (palette) {ierr = PetscFree(rgbpixels);CHKERRQ(ierr);}
2528067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
2538067a7d5SLisandro Dalcin }
2548067a7d5SLisandro Dalcin 
2558067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_JPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
2568067a7d5SLisandro Dalcin { return PetscDrawImageSaveJPG(filename,palette,w,h,pixels); }
2578067a7d5SLisandro Dalcin 
2588067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBJPEG*/
2598067a7d5SLisandro Dalcin 
2608067a7d5SLisandro Dalcin static struct {
2618067a7d5SLisandro Dalcin   const char      *extension;
2628067a7d5SLisandro Dalcin   PetscErrorCode (*SaveImage)(const char[],unsigned char[][3],unsigned int,unsigned int,const unsigned char[]);
2638067a7d5SLisandro Dalcin } PetscDrawImageSaveTable[] = {
2648067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG)
2658067a7d5SLisandro Dalcin   {".png", PetscDrawImageSave_PNG},
2668067a7d5SLisandro Dalcin #endif
2678067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB)
2688067a7d5SLisandro Dalcin   {".gif", PetscDrawImageSave_GIF},
2698067a7d5SLisandro Dalcin #endif
2708067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG)
2718067a7d5SLisandro Dalcin   {".jpg", PetscDrawImageSave_JPG},
2728067a7d5SLisandro Dalcin #endif
2738067a7d5SLisandro Dalcin   {".ppm", PetscDrawImageSave_PPM}
2748067a7d5SLisandro Dalcin };
2758067a7d5SLisandro Dalcin 
2768067a7d5SLisandro Dalcin #undef __FUNCT__
2778067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageCheckFormat"
2788067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageCheckFormat(const char *ext[])
2798067a7d5SLisandro Dalcin {
2808067a7d5SLisandro Dalcin   size_t         k;
2818067a7d5SLisandro Dalcin   PetscBool      match = PETSC_FALSE;
2828067a7d5SLisandro Dalcin   PetscErrorCode ierr;
2838067a7d5SLisandro Dalcin 
2848067a7d5SLisandro Dalcin   PetscFunctionBegin;
2858067a7d5SLisandro Dalcin   /* if extension is empty, return default format to caller */
2868067a7d5SLisandro Dalcin   PetscValidPointer(ext,1);
2878067a7d5SLisandro Dalcin   if (!*ext || !**ext) {
2888067a7d5SLisandro Dalcin     *ext = PetscDrawImageSaveTable[0].extension;
2898067a7d5SLisandro Dalcin     PetscFunctionReturn(0);
2908067a7d5SLisandro Dalcin   }
2918067a7d5SLisandro Dalcin   /* check the extension mathes a supported format otherwise */
2928067a7d5SLisandro Dalcin   PetscValidCharPointer(*ext,1);
2938067a7d5SLisandro Dalcin   for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) {
2948067a7d5SLisandro Dalcin     ierr = PetscStrcasecmp(*ext,PetscDrawImageSaveTable[k].extension,&match);CHKERRQ(ierr);
2958067a7d5SLisandro Dalcin     if (match && PetscDrawImageSaveTable[k].SaveImage) PetscFunctionReturn(0);
2968067a7d5SLisandro Dalcin   }
2978067a7d5SLisandro Dalcin   SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",*ext);
2988067a7d5SLisandro Dalcin   PetscFunctionReturn(PETSC_ERR_SUP);
2998067a7d5SLisandro Dalcin }
3008067a7d5SLisandro Dalcin 
3018067a7d5SLisandro Dalcin #undef __FUNCT__
3028067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSave"
3038067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageSave(const char basename[],const char ext[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[])
3048067a7d5SLisandro Dalcin {
3058067a7d5SLisandro Dalcin   size_t         k;
3068067a7d5SLisandro Dalcin   PetscBool      match = PETSC_FALSE;
3078067a7d5SLisandro Dalcin   char           filename[PETSC_MAX_PATH_LEN];
3088067a7d5SLisandro Dalcin   PetscErrorCode ierr;
3098067a7d5SLisandro Dalcin 
3108067a7d5SLisandro Dalcin   PetscFunctionBegin;
3118067a7d5SLisandro Dalcin   PetscValidCharPointer(basename,1);
3128067a7d5SLisandro Dalcin   if (ext) PetscValidCharPointer(ext,2);
3138067a7d5SLisandro Dalcin   if (palette) PetscValidCharPointer(palette,3);
3148067a7d5SLisandro Dalcin   PetscValidCharPointer(pixels,6);
3158067a7d5SLisandro Dalcin 
3168067a7d5SLisandro Dalcin   ierr = PetscDrawImageCheckFormat(&ext);CHKERRQ(ierr);
3178067a7d5SLisandro Dalcin   ierr = PetscSNPrintf(filename,sizeof(filename),"%s%s",basename,ext);CHKERRQ(ierr);
3188067a7d5SLisandro Dalcin   for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) {
3198067a7d5SLisandro Dalcin     ierr = PetscStrcasecmp(ext,PetscDrawImageSaveTable[k].extension,&match);CHKERRQ(ierr);
3208067a7d5SLisandro Dalcin     if (match && PetscDrawImageSaveTable[k].SaveImage) {
3218067a7d5SLisandro Dalcin       ierr = PetscDrawImageSaveTable[k].SaveImage(filename,palette,w,h,pixels);CHKERRQ(ierr);
3228067a7d5SLisandro Dalcin       PetscFunctionReturn(0);
3238067a7d5SLisandro Dalcin     }
3248067a7d5SLisandro Dalcin   }
3258067a7d5SLisandro Dalcin   SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",ext);
3268067a7d5SLisandro Dalcin   PetscFunctionReturn(PETSC_ERR_SUP);
3278067a7d5SLisandro Dalcin }
3288067a7d5SLisandro Dalcin 
3298067a7d5SLisandro Dalcin #undef __FUNCT__
3308067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawMovieCheckFormat"
3318067a7d5SLisandro Dalcin PetscErrorCode PetscDrawMovieCheckFormat(const char *ext[])
3328067a7d5SLisandro Dalcin {
3338067a7d5SLisandro Dalcin   PetscFunctionBegin;
3348067a7d5SLisandro Dalcin   PetscValidPointer(ext,1);
3358067a7d5SLisandro Dalcin   if (!*ext || !**ext) *ext = ".m4v";
3368067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
3378067a7d5SLisandro Dalcin }
3388067a7d5SLisandro Dalcin 
3398067a7d5SLisandro Dalcin #undef __FUNCT__
3408067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawMovieSave"
341*3d242201SLisandro Dalcin PetscErrorCode PetscDrawMovieSave(const char basename[],PetscInt count,const char imext[],PetscInt fps,const char mvext[])
3428067a7d5SLisandro Dalcin {
3438067a7d5SLisandro Dalcin   PetscBool      imgif;
3448067a7d5SLisandro Dalcin   PetscErrorCode ierr;
3458067a7d5SLisandro Dalcin 
3468067a7d5SLisandro Dalcin   PetscFunctionBegin;
3478067a7d5SLisandro Dalcin   PetscValidCharPointer(basename,1);
3488067a7d5SLisandro Dalcin   PetscValidCharPointer(imext,3);
3498067a7d5SLisandro Dalcin   if (mvext) PetscValidCharPointer(mvext,4);
3508067a7d5SLisandro Dalcin   if (count < 1) PetscFunctionReturn(0);
3518067a7d5SLisandro Dalcin 
3528067a7d5SLisandro Dalcin   ierr = PetscStrcasecmp(imext,".gif",&imgif);CHKERRQ(ierr);
3538067a7d5SLisandro Dalcin   ierr = PetscDrawMovieCheckFormat(&mvext);CHKERRQ(ierr);
3548067a7d5SLisandro Dalcin 
3558067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_POPEN)
3568067a7d5SLisandro Dalcin   /* use ffmpeg to generate a movie */
3578067a7d5SLisandro Dalcin   {
3588067a7d5SLisandro Dalcin     PetscInt i;
3598067a7d5SLisandro Dalcin     FILE     *fd;
360*3d242201SLisandro Dalcin     char     ffmpeg[64] = "ffmpeg -loglevel error -y", framerate[24] = "";
361*3d242201SLisandro Dalcin     char     input[PETSC_MAX_PATH_LEN], output[PETSC_MAX_PATH_LEN];
362*3d242201SLisandro Dalcin     char     command[sizeof(ffmpeg)+sizeof(framerate)+PETSC_MAX_PATH_LEN*2];
363*3d242201SLisandro Dalcin     if (fps > 0 && !imgif) { /* ffmpeg seems to have trouble with non-animated GIF input */
364*3d242201SLisandro Dalcin       ierr = PetscSNPrintf(framerate,sizeof(framerate)," -framerate %d",(int)fps);CHKERRQ(ierr);
365*3d242201SLisandro Dalcin       ierr = PetscStrcat(ffmpeg,framerate);CHKERRQ(ierr);
366*3d242201SLisandro Dalcin     }
367*3d242201SLisandro Dalcin     ierr = PetscSNPrintf(input,sizeof(input),"%s/%s_%%d%s",basename,basename,imext);CHKERRQ(ierr);
368*3d242201SLisandro Dalcin     ierr = PetscSNPrintf(output,sizeof(output),"%s%s",basename,mvext);CHKERRQ(ierr);
3698067a7d5SLisandro Dalcin     if (imgif) {
370*3d242201SLisandro Dalcin       ierr = PetscStrcat(ffmpeg," -f concat");CHKERRQ(ierr);
371*3d242201SLisandro Dalcin       ierr = PetscSNPrintf(input,sizeof(input),"%s/%s.filelist",basename,basename);CHKERRQ(ierr);
372*3d242201SLisandro Dalcin       ierr = PetscFOpen(PETSC_COMM_SELF,input,"w",&fd);CHKERRQ(ierr);
373*3d242201SLisandro Dalcin       ierr = PetscFPrintf(PETSC_COMM_SELF,fd,"# ffmpeg%s -f concat -i \"%s.filelist\" \"%s\"\n",framerate,basename,output);CHKERRQ(ierr);
3748067a7d5SLisandro Dalcin       for (i=0; i<count; i++) {ierr = PetscFPrintf(PETSC_COMM_SELF,fd,"file '%s_%d%s'\n",basename,i,imext);CHKERRQ(ierr);}
3758067a7d5SLisandro Dalcin       ierr = PetscFClose(PETSC_COMM_SELF,fd);CHKERRQ(ierr);
3768067a7d5SLisandro Dalcin     }
377*3d242201SLisandro Dalcin     ierr = PetscSNPrintf(command,sizeof(command),"%s -i \"%s\" \"%s\"",ffmpeg,input,output);CHKERRQ(ierr);
3788067a7d5SLisandro Dalcin     ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr);
3798067a7d5SLisandro Dalcin     ierr = PetscPClose(PETSC_COMM_SELF,fd,NULL);CHKERRQ(ierr);
3808067a7d5SLisandro Dalcin   }
3818067a7d5SLisandro Dalcin #endif
3828067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
3838067a7d5SLisandro Dalcin }
384