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[]); 43d242201SLisandro 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 PETSC_EXTERN PetscErrorCode PetscDrawImageSavePPM(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 128067a7d5SLisandro Dalcin { 138067a7d5SLisandro Dalcin int fd; 148067a7d5SLisandro Dalcin char header[32]; 158067a7d5SLisandro Dalcin size_t hdrlen; 168067a7d5SLisandro Dalcin unsigned char *rgb; 178067a7d5SLisandro Dalcin PetscErrorCode ierr; 188067a7d5SLisandro Dalcin 198067a7d5SLisandro Dalcin PetscFunctionBegin; 208067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 218067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,2); 228067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 238067a7d5SLisandro Dalcin /* map pixels to RGB colors */ 248067a7d5SLisandro Dalcin if (palette) { 258067a7d5SLisandro Dalcin int k,p,n = (int)(w*h); 268067a7d5SLisandro Dalcin const unsigned char *colordef; 278067a7d5SLisandro Dalcin ierr = PetscMalloc1(3*w*h,&rgb);CHKERRQ(ierr); 288067a7d5SLisandro Dalcin for (k=p=0; k<n; k++) { 298067a7d5SLisandro Dalcin colordef = palette[pixels[k]]; 308067a7d5SLisandro Dalcin rgb[p++] = colordef[0]; 318067a7d5SLisandro Dalcin rgb[p++] = colordef[1]; 328067a7d5SLisandro Dalcin rgb[p++] = colordef[2]; 338067a7d5SLisandro Dalcin } 348067a7d5SLisandro Dalcin } else { /* assume pixels are RGB colors */ 358067a7d5SLisandro Dalcin rgb = (unsigned char*)pixels; 368067a7d5SLisandro Dalcin } 378067a7d5SLisandro Dalcin /* open file and write PPM header */ 388067a7d5SLisandro Dalcin ierr = PetscBinaryOpen(filename,FILE_MODE_WRITE,&fd);CHKERRQ(ierr); 398067a7d5SLisandro Dalcin ierr = PetscSNPrintf(header,sizeof(header),"P6\n%d %d\n255\n\0",(int)w,(int)h);CHKERRQ(ierr); 408067a7d5SLisandro Dalcin ierr = PetscStrlen(header,&hdrlen);CHKERRQ(ierr); 41*f253e43cSLisandro Dalcin ierr = PetscBinaryWrite(fd,header,hdrlen,PETSC_CHAR);CHKERRQ(ierr); 428067a7d5SLisandro Dalcin /* write image data and close file */ 43*f253e43cSLisandro Dalcin ierr = PetscBinaryWrite(fd,rgb,3*w*h,PETSC_CHAR);CHKERRQ(ierr); 448067a7d5SLisandro Dalcin ierr = PetscBinaryClose(fd);CHKERRQ(ierr); 458067a7d5SLisandro Dalcin if (palette) {ierr = PetscFree(rgb);CHKERRQ(ierr);} 468067a7d5SLisandro Dalcin PetscFunctionReturn(0); 478067a7d5SLisandro Dalcin } 488067a7d5SLisandro Dalcin 498067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_PPM(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 508067a7d5SLisandro Dalcin { return PetscDrawImageSavePPM(filename,palette,w,h,pixels); } 518067a7d5SLisandro Dalcin 528067a7d5SLisandro Dalcin 538067a7d5SLisandro Dalcin /* 548067a7d5SLisandro Dalcin Code to write images in PNG format 558067a7d5SLisandro Dalcin */ 568067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG) 578067a7d5SLisandro Dalcin 588067a7d5SLisandro Dalcin #include <png.h> 598067a7d5SLisandro Dalcin 608067a7d5SLisandro Dalcin #if defined(PNG_SETJMP_SUPPORTED) 618067a7d5SLisandro Dalcin # ifndef png_jmpbuf 628067a7d5SLisandro Dalcin # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 638067a7d5SLisandro Dalcin # endif 648067a7d5SLisandro Dalcin #endif 658067a7d5SLisandro Dalcin 668067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSavePNG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 678067a7d5SLisandro Dalcin { 688067a7d5SLisandro Dalcin FILE *fp; 698067a7d5SLisandro Dalcin png_struct *png_ptr; 708067a7d5SLisandro Dalcin png_info *info_ptr; 718067a7d5SLisandro Dalcin unsigned int row, stride = palette ? w : 3*w; 728067a7d5SLisandro Dalcin PetscErrorCode ierr; 738067a7d5SLisandro Dalcin 748067a7d5SLisandro Dalcin PetscFunctionBegin; 758067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 768067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,2); 778067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 788067a7d5SLisandro Dalcin 798067a7d5SLisandro Dalcin /* open file and create libpng structures */ 808067a7d5SLisandro Dalcin ierr = PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp);CHKERRQ(ierr); 818067a7d5SLisandro Dalcin png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); 828067a7d5SLisandro Dalcin if (!png_ptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create PNG context"); 838067a7d5SLisandro Dalcin info_ptr = png_create_info_struct(png_ptr); 848067a7d5SLisandro Dalcin if (!info_ptr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create PNG context"); 858067a7d5SLisandro Dalcin 868067a7d5SLisandro Dalcin /* setup libpng error handling */ 878067a7d5SLisandro Dalcin #if defined(PNG_SETJMP_SUPPORTED) 888067a7d5SLisandro Dalcin if (setjmp(png_jmpbuf(png_ptr))) { 898067a7d5SLisandro Dalcin png_destroy_write_struct(&png_ptr,&info_ptr); 908067a7d5SLisandro Dalcin (void)PetscFClose(PETSC_COMM_SELF,fp); 918067a7d5SLisandro Dalcin SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing PNG file %s",filename); 928067a7d5SLisandro Dalcin } 938067a7d5SLisandro Dalcin #endif 948067a7d5SLisandro Dalcin 958067a7d5SLisandro Dalcin /* setup PNG image metadata */ 968067a7d5SLisandro Dalcin png_init_io(png_ptr, fp); 978067a7d5SLisandro Dalcin png_set_IHDR(png_ptr, info_ptr, w, h, /*depth*/8, 988067a7d5SLisandro Dalcin palette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB, 998067a7d5SLisandro Dalcin PNG_INTERLACE_NONE, 1008067a7d5SLisandro Dalcin PNG_COMPRESSION_TYPE_DEFAULT, 1018067a7d5SLisandro Dalcin PNG_FILTER_TYPE_DEFAULT); 1028067a7d5SLisandro Dalcin if (palette) 1038067a7d5SLisandro Dalcin png_set_PLTE(png_ptr, info_ptr, (png_color*)palette, 256); 1048067a7d5SLisandro Dalcin 1058067a7d5SLisandro Dalcin /* write PNG image header and data */ 1068067a7d5SLisandro Dalcin png_write_info(png_ptr, info_ptr); 1078067a7d5SLisandro Dalcin for (row = 0; row < h; row++) 1088067a7d5SLisandro Dalcin png_write_row(png_ptr, pixels + row*stride); 1098067a7d5SLisandro Dalcin png_write_end(png_ptr, NULL); 1108067a7d5SLisandro Dalcin 1118067a7d5SLisandro Dalcin /* destroy libpng structures and close file */ 1128067a7d5SLisandro Dalcin png_destroy_write_struct(&png_ptr, &info_ptr); 1138067a7d5SLisandro Dalcin ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr); 1148067a7d5SLisandro Dalcin PetscFunctionReturn(0); 1158067a7d5SLisandro Dalcin } 1168067a7d5SLisandro Dalcin 1178067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_PNG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 1188067a7d5SLisandro Dalcin { return PetscDrawImageSavePNG(filename,palette,w,h,pixels); } 1198067a7d5SLisandro Dalcin 1208067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBPNG*/ 1218067a7d5SLisandro Dalcin 1228067a7d5SLisandro Dalcin 1238067a7d5SLisandro Dalcin /* 1248067a7d5SLisandro Dalcin Code to write images in GIF format 1258067a7d5SLisandro Dalcin */ 1268067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 1278067a7d5SLisandro Dalcin 1288067a7d5SLisandro Dalcin #include <gif_lib.h> 1298067a7d5SLisandro Dalcin 1308067a7d5SLisandro Dalcin #if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5 1318067a7d5SLisandro Dalcin #define GifMakeMapObject MakeMapObject 1328067a7d5SLisandro Dalcin #define GifFreeMapObject FreeMapObject 1338067a7d5SLisandro Dalcin #define EGifOpenFileName(n,b,err) EGifOpenFileName(n,b) 1348067a7d5SLisandro Dalcin #define EGifOpenFileHandle(h,err) EGifOpenFileName(h) 1358067a7d5SLisandro Dalcin #define EGifCloseFile(f,err) EGifCloseFile(f) 13675c73fc3SLisandro Dalcin #define DGifOpenFileName(n,err) DGifOpenFileName(n) 13775c73fc3SLisandro Dalcin #define DGifOpenFileHandle(h,err) DGifOpenFileName(h) 13875c73fc3SLisandro Dalcin #define DGifCloseFile(f,err) DGifCloseFile(f) 1398067a7d5SLisandro Dalcin #endif 1408067a7d5SLisandro Dalcin 1418067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveGIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 1428067a7d5SLisandro Dalcin { 1438067a7d5SLisandro Dalcin int Row, Error; 1448067a7d5SLisandro Dalcin int Width = (int)w; 1458067a7d5SLisandro Dalcin int Height = (int)h; 1468067a7d5SLisandro Dalcin int ColorRes = 8; 1478067a7d5SLisandro Dalcin int ColorCount = 256; 1488067a7d5SLisandro Dalcin ColorMapObject *GifCMap = NULL; 1498067a7d5SLisandro Dalcin GifFileType *GifFile = NULL; 1508067a7d5SLisandro Dalcin # define SETERRGIF(msg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,msg", GIF file: %s",filename) 1518067a7d5SLisandro Dalcin # define CHKERRGIF(msg) do {if (Error != GIF_OK) SETERRGIF(msg);} while(0) 1528067a7d5SLisandro Dalcin 1538067a7d5SLisandro Dalcin PetscFunctionBegin; 1548067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 1558067a7d5SLisandro Dalcin PetscValidCharPointer(palette,2); 1568067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 1578067a7d5SLisandro Dalcin 1588067a7d5SLisandro Dalcin GifCMap = GifMakeMapObject(ColorCount, (GifColorType*)palette); if (!GifCMap) SETERRGIF("Allocating colormap"); 1598067a7d5SLisandro Dalcin GifFile = EGifOpenFileName(filename, 0, NULL); if (!GifFile) SETERRGIF("Opening"); 1608067a7d5SLisandro Dalcin Error = EGifPutScreenDesc(GifFile, Width, Height, ColorRes, 0, GifCMap); CHKERRGIF("Writing screen descriptor"); 1618067a7d5SLisandro Dalcin Error = EGifPutImageDesc(GifFile, 0, 0, Width, Height, 0, NULL); CHKERRGIF("Writing image descriptor"); 1628067a7d5SLisandro Dalcin for (Row = 0; Row < Height; Row++) { 1638067a7d5SLisandro Dalcin Error = EGifPutLine(GifFile, (GifPixelType*)pixels + Row*Width, Width); CHKERRGIF("Writing image pixels"); 1648067a7d5SLisandro Dalcin } 1658067a7d5SLisandro Dalcin Error = EGifCloseFile(GifFile, NULL); CHKERRGIF("Closing"); 1668067a7d5SLisandro Dalcin GifFreeMapObject(GifCMap); GifCMap = NULL; 1678067a7d5SLisandro Dalcin 1688067a7d5SLisandro Dalcin # undef SETERRGIF 1698067a7d5SLisandro Dalcin # undef CHKERRGIF 1708067a7d5SLisandro Dalcin PetscFunctionReturn(0); 1718067a7d5SLisandro Dalcin } 1728067a7d5SLisandro Dalcin 1738067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_GIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 1748067a7d5SLisandro Dalcin { return PetscDrawImageSaveGIF(filename,palette,w,h,pixels); } 1758067a7d5SLisandro Dalcin 17675c73fc3SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieSaveGIF(const char pattern[],PetscInt count,const char movie[]) 17775c73fc3SLisandro Dalcin { 17875c73fc3SLisandro Dalcin int i,j,Row; 17975c73fc3SLisandro Dalcin char image[PETSC_MAX_PATH_LEN]; 18075c73fc3SLisandro Dalcin GifFileType *GifMovie = NULL; 18175c73fc3SLisandro Dalcin GifFileType *GifImage = NULL; 18275c73fc3SLisandro Dalcin PetscErrorCode ierr; 18375c73fc3SLisandro Dalcin # define SETERRGIF(msg,fn) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,msg" GIF file %s",fn) 18475c73fc3SLisandro Dalcin 18575c73fc3SLisandro Dalcin PetscFunctionBegin; 18675c73fc3SLisandro Dalcin PetscValidCharPointer(pattern,1); 18775c73fc3SLisandro Dalcin PetscValidCharPointer(movie,3); 18875c73fc3SLisandro Dalcin if (count < 1) PetscFunctionReturn(0); 18975c73fc3SLisandro Dalcin 19075c73fc3SLisandro Dalcin for (i = 0; i < count; i++) { 19175c73fc3SLisandro Dalcin ierr = PetscSNPrintf(image,sizeof(image),pattern,(int)i);CHKERRQ(ierr); 19275c73fc3SLisandro Dalcin /* open and read image file */ 19375c73fc3SLisandro Dalcin if ((GifImage = DGifOpenFileName(image, NULL)) == NULL) SETERRGIF("Opening input",image); 19475c73fc3SLisandro Dalcin if (DGifSlurp(GifImage) != GIF_OK) SETERRGIF("Reading input",image); 19575c73fc3SLisandro Dalcin /* open movie file and write header */ 19675c73fc3SLisandro Dalcin if (i == 0) { 19775c73fc3SLisandro Dalcin if ((GifMovie = EGifOpenFileName(movie, 0, NULL)) == NULL) SETERRGIF("Opening output",movie); 19875c73fc3SLisandro Dalcin if (EGifPutScreenDesc(GifMovie, 19975c73fc3SLisandro Dalcin GifImage->SWidth, 20075c73fc3SLisandro Dalcin GifImage->SHeight, 20175c73fc3SLisandro Dalcin GifImage->SColorResolution, 20275c73fc3SLisandro Dalcin GifImage->SBackGroundColor, 20375c73fc3SLisandro Dalcin GifImage->SColorMap) != GIF_OK) SETERRGIF("Writing screen descriptor,",movie); 20475c73fc3SLisandro Dalcin } 20575c73fc3SLisandro Dalcin /* loop over all frames in image */ 20675c73fc3SLisandro Dalcin for (j = 0; j < GifImage->ImageCount; j++) { 20775c73fc3SLisandro Dalcin SavedImage *sp = &GifImage->SavedImages[j]; 20875c73fc3SLisandro Dalcin GifImageDesc *GifFrame = &sp->ImageDesc; 20975c73fc3SLisandro Dalcin ColorMapObject *FrameColorMap = GifFrame->ColorMap ? GifFrame->ColorMap : GifImage->SColorMap; 21075c73fc3SLisandro Dalcin if (GifMovie->SColorMap && GifMovie->SColorMap->ColorCount == FrameColorMap->ColorCount && 21175c73fc3SLisandro Dalcin !memcmp(GifMovie->SColorMap->Colors,FrameColorMap->Colors, 21275c73fc3SLisandro Dalcin (size_t)FrameColorMap->ColorCount*sizeof(GifColorType))) 21375c73fc3SLisandro Dalcin FrameColorMap = NULL; 21475c73fc3SLisandro Dalcin /* add frame to movie */ 21575c73fc3SLisandro Dalcin if (EGifPutImageDesc(GifMovie, 21675c73fc3SLisandro Dalcin GifFrame->Left, 21775c73fc3SLisandro Dalcin GifFrame->Top, 21875c73fc3SLisandro Dalcin GifFrame->Width, 21975c73fc3SLisandro Dalcin GifFrame->Height, 22075c73fc3SLisandro Dalcin GifFrame->Interlace, 22175c73fc3SLisandro Dalcin FrameColorMap) != GIF_OK) SETERRGIF("Writing image descriptor,",movie); 22275c73fc3SLisandro Dalcin for (Row = 0; Row < GifFrame->Height; Row++) { 22375c73fc3SLisandro Dalcin if (EGifPutLine(GifMovie, 22475c73fc3SLisandro Dalcin sp->RasterBits + Row * GifFrame->Width, 22575c73fc3SLisandro Dalcin GifFrame->Width) != GIF_OK) SETERRGIF("Writing image pixels,",movie); 22675c73fc3SLisandro Dalcin } 22775c73fc3SLisandro Dalcin } 22875c73fc3SLisandro Dalcin if (DGifCloseFile(GifImage, NULL) != GIF_OK) SETERRGIF("Closing input",image); 22975c73fc3SLisandro Dalcin } 23075c73fc3SLisandro Dalcin if (EGifCloseFile(GifMovie, NULL) != GIF_OK) SETERRGIF("Closing output",movie); 23175c73fc3SLisandro Dalcin 23275c73fc3SLisandro Dalcin # undef SETERRGIF 23375c73fc3SLisandro Dalcin PetscFunctionReturn(0); 23475c73fc3SLisandro Dalcin } 23575c73fc3SLisandro Dalcin 2368067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_GIFLIB*/ 2378067a7d5SLisandro Dalcin 2388067a7d5SLisandro Dalcin /* 2398067a7d5SLisandro Dalcin Code to write images in JPEG format 2408067a7d5SLisandro Dalcin */ 2418067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 2428067a7d5SLisandro Dalcin 2438067a7d5SLisandro Dalcin #include <jpeglib.h> 2448067a7d5SLisandro Dalcin 2458067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2468067a7d5SLisandro Dalcin #include <setjmp.h> 2478067a7d5SLisandro Dalcin static jmp_buf petsc_jpeg_jumpbuf; 2488067a7d5SLisandro Dalcin static void petsc_jpeg_error_longjmp (j_common_ptr cinfo) { (void)cinfo; longjmp(petsc_jpeg_jumpbuf,1); } 2498067a7d5SLisandro Dalcin #endif 2508067a7d5SLisandro Dalcin 2518067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveJPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 2528067a7d5SLisandro Dalcin { 2538067a7d5SLisandro Dalcin unsigned char *rgbpixels; 2548067a7d5SLisandro Dalcin FILE *fp; 2558067a7d5SLisandro Dalcin struct jpeg_compress_struct cinfo; 2568067a7d5SLisandro Dalcin struct jpeg_error_mgr jerr; 2578067a7d5SLisandro Dalcin PetscErrorCode ierr; 2588067a7d5SLisandro Dalcin 2598067a7d5SLisandro Dalcin PetscFunctionBegin; 2608067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 2618067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,2); 2628067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 2638067a7d5SLisandro Dalcin /* map pixels to RGB colors */ 2648067a7d5SLisandro Dalcin if (palette) { 2658067a7d5SLisandro Dalcin int k,p,n = (int)(w*h); 2668067a7d5SLisandro Dalcin const unsigned char *colordef; 2678067a7d5SLisandro Dalcin ierr = PetscMalloc1(3*w*h,&rgbpixels);CHKERRQ(ierr); 2688067a7d5SLisandro Dalcin for (k=p=0; k<n; k++) { 2698067a7d5SLisandro Dalcin colordef = palette[pixels[k]]; 2708067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[0]; 2718067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[1]; 2728067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[2]; 2738067a7d5SLisandro Dalcin } 2748067a7d5SLisandro Dalcin } else { /* assume pixels are RGB colors */ 2758067a7d5SLisandro Dalcin rgbpixels = (unsigned char*)pixels; 2768067a7d5SLisandro Dalcin } 2778067a7d5SLisandro Dalcin ierr = PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp);CHKERRQ(ierr); 2788067a7d5SLisandro Dalcin 2798067a7d5SLisandro Dalcin cinfo.err = jpeg_std_error(&jerr); 2808067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2818067a7d5SLisandro Dalcin jerr.error_exit = petsc_jpeg_error_longjmp; 2828067a7d5SLisandro Dalcin if (setjmp(petsc_jpeg_jumpbuf)) { 2838067a7d5SLisandro Dalcin char message[JMSG_LENGTH_MAX]; 2848067a7d5SLisandro Dalcin jerr.format_message((j_common_ptr)&cinfo,message); 2858067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 2868067a7d5SLisandro Dalcin (void)PetscFClose(PETSC_COMM_SELF,fp); 2878067a7d5SLisandro Dalcin SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing JPEG file %s\n%s",filename,message); 2888067a7d5SLisandro Dalcin } 2898067a7d5SLisandro Dalcin #endif 2908067a7d5SLisandro Dalcin jpeg_create_compress(&cinfo); 2918067a7d5SLisandro Dalcin jpeg_stdio_dest(&cinfo,fp); 2928067a7d5SLisandro Dalcin cinfo.image_width = w; 2938067a7d5SLisandro Dalcin cinfo.image_height = h; 2948067a7d5SLisandro Dalcin cinfo.input_components = 3; 2958067a7d5SLisandro Dalcin cinfo.in_color_space = JCS_RGB; 2968067a7d5SLisandro Dalcin jpeg_set_defaults(&cinfo); 2978067a7d5SLisandro Dalcin jpeg_start_compress(&cinfo,TRUE); 2988067a7d5SLisandro Dalcin while (cinfo.next_scanline < cinfo.image_height) { 2998067a7d5SLisandro Dalcin unsigned char *rowptr = rgbpixels + cinfo.next_scanline * 3*w; 3008067a7d5SLisandro Dalcin (void)jpeg_write_scanlines(&cinfo,&rowptr,1); 3018067a7d5SLisandro Dalcin } 3028067a7d5SLisandro Dalcin jpeg_finish_compress(&cinfo); 3038067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 3048067a7d5SLisandro Dalcin 3058067a7d5SLisandro Dalcin ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr); 3068067a7d5SLisandro Dalcin if (palette) {ierr = PetscFree(rgbpixels);CHKERRQ(ierr);} 3078067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3088067a7d5SLisandro Dalcin } 3098067a7d5SLisandro Dalcin 3108067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_JPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 3118067a7d5SLisandro Dalcin { return PetscDrawImageSaveJPG(filename,palette,w,h,pixels); } 3128067a7d5SLisandro Dalcin 3138067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBJPEG*/ 3148067a7d5SLisandro Dalcin 3158067a7d5SLisandro Dalcin static struct { 3168067a7d5SLisandro Dalcin const char *extension; 3178067a7d5SLisandro Dalcin PetscErrorCode (*SaveImage)(const char[],unsigned char[][3],unsigned int,unsigned int,const unsigned char[]); 3188067a7d5SLisandro Dalcin } PetscDrawImageSaveTable[] = { 3198067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG) 3208067a7d5SLisandro Dalcin {".png", PetscDrawImageSave_PNG}, 3218067a7d5SLisandro Dalcin #endif 3228067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 3238067a7d5SLisandro Dalcin {".gif", PetscDrawImageSave_GIF}, 3248067a7d5SLisandro Dalcin #endif 3258067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 3268067a7d5SLisandro Dalcin {".jpg", PetscDrawImageSave_JPG}, 3278067a7d5SLisandro Dalcin #endif 3288067a7d5SLisandro Dalcin {".ppm", PetscDrawImageSave_PPM} 3298067a7d5SLisandro Dalcin }; 3308067a7d5SLisandro Dalcin 3318067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageCheckFormat(const char *ext[]) 3328067a7d5SLisandro Dalcin { 3338067a7d5SLisandro Dalcin size_t k; 3348067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3358067a7d5SLisandro Dalcin PetscErrorCode ierr; 3368067a7d5SLisandro Dalcin 3378067a7d5SLisandro Dalcin PetscFunctionBegin; 3388067a7d5SLisandro Dalcin /* if extension is empty, return default format to caller */ 3398067a7d5SLisandro Dalcin PetscValidPointer(ext,1); 3408067a7d5SLisandro Dalcin if (!*ext || !**ext) { 3418067a7d5SLisandro Dalcin *ext = PetscDrawImageSaveTable[0].extension; 3428067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3438067a7d5SLisandro Dalcin } 3448067a7d5SLisandro Dalcin /* check the extension mathes a supported format otherwise */ 3458067a7d5SLisandro Dalcin PetscValidCharPointer(*ext,1); 3468067a7d5SLisandro Dalcin for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) { 3478067a7d5SLisandro Dalcin ierr = PetscStrcasecmp(*ext,PetscDrawImageSaveTable[k].extension,&match);CHKERRQ(ierr); 3488067a7d5SLisandro Dalcin if (match && PetscDrawImageSaveTable[k].SaveImage) PetscFunctionReturn(0); 3498067a7d5SLisandro Dalcin } 3508067a7d5SLisandro Dalcin SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",*ext); 3513cbbc5ffSBarry Smith PetscFunctionReturn(0); 3528067a7d5SLisandro Dalcin } 3538067a7d5SLisandro Dalcin 3548067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageSave(const char basename[],const char ext[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 3558067a7d5SLisandro Dalcin { 3568067a7d5SLisandro Dalcin size_t k; 3578067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3588067a7d5SLisandro Dalcin char filename[PETSC_MAX_PATH_LEN]; 3598067a7d5SLisandro Dalcin PetscErrorCode ierr; 3608067a7d5SLisandro Dalcin 3618067a7d5SLisandro Dalcin PetscFunctionBegin; 3628067a7d5SLisandro Dalcin PetscValidCharPointer(basename,1); 3638067a7d5SLisandro Dalcin if (ext) PetscValidCharPointer(ext,2); 3648067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,3); 3658067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,6); 3668067a7d5SLisandro Dalcin 3678067a7d5SLisandro Dalcin ierr = PetscDrawImageCheckFormat(&ext);CHKERRQ(ierr); 3688067a7d5SLisandro Dalcin ierr = PetscSNPrintf(filename,sizeof(filename),"%s%s",basename,ext);CHKERRQ(ierr); 3698067a7d5SLisandro Dalcin for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) { 3708067a7d5SLisandro Dalcin ierr = PetscStrcasecmp(ext,PetscDrawImageSaveTable[k].extension,&match);CHKERRQ(ierr); 3718067a7d5SLisandro Dalcin if (match && PetscDrawImageSaveTable[k].SaveImage) { 3728067a7d5SLisandro Dalcin ierr = PetscDrawImageSaveTable[k].SaveImage(filename,palette,w,h,pixels);CHKERRQ(ierr); 3738067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3748067a7d5SLisandro Dalcin } 3758067a7d5SLisandro Dalcin } 3768067a7d5SLisandro Dalcin SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",ext); 3773cbbc5ffSBarry Smith PetscFunctionReturn(0); 3788067a7d5SLisandro Dalcin } 3798067a7d5SLisandro Dalcin 3808067a7d5SLisandro Dalcin PetscErrorCode PetscDrawMovieCheckFormat(const char *ext[]) 3818067a7d5SLisandro Dalcin { 3828067a7d5SLisandro Dalcin PetscFunctionBegin; 3838067a7d5SLisandro Dalcin PetscValidPointer(ext,1); 3848067a7d5SLisandro Dalcin if (!*ext || !**ext) *ext = ".m4v"; 3858067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3868067a7d5SLisandro Dalcin } 3878067a7d5SLisandro Dalcin 3883d242201SLisandro Dalcin PetscErrorCode PetscDrawMovieSave(const char basename[],PetscInt count,const char imext[],PetscInt fps,const char mvext[]) 3898067a7d5SLisandro Dalcin { 39075c73fc3SLisandro Dalcin char input[PETSC_MAX_PATH_LEN]; 39175c73fc3SLisandro Dalcin char output[PETSC_MAX_PATH_LEN]; 39275c73fc3SLisandro Dalcin PetscBool gifinput; 3938067a7d5SLisandro Dalcin PetscErrorCode ierr; 3948067a7d5SLisandro Dalcin 3958067a7d5SLisandro Dalcin PetscFunctionBegin; 3968067a7d5SLisandro Dalcin PetscValidCharPointer(basename,1); 3978067a7d5SLisandro Dalcin PetscValidCharPointer(imext,3); 3988067a7d5SLisandro Dalcin if (mvext) PetscValidCharPointer(mvext,4); 3998067a7d5SLisandro Dalcin if (count < 1) PetscFunctionReturn(0); 4008067a7d5SLisandro Dalcin 40175c73fc3SLisandro Dalcin ierr = PetscStrcasecmp(imext,".gif",&gifinput);CHKERRQ(ierr); 4028067a7d5SLisandro Dalcin ierr = PetscDrawMovieCheckFormat(&mvext);CHKERRQ(ierr); 4033d242201SLisandro Dalcin ierr = PetscSNPrintf(input,sizeof(input),"%s/%s_%%d%s",basename,basename,imext);CHKERRQ(ierr); 4043d242201SLisandro Dalcin ierr = PetscSNPrintf(output,sizeof(output),"%s%s",basename,mvext);CHKERRQ(ierr); 40575c73fc3SLisandro Dalcin 40675c73fc3SLisandro Dalcin /* use GIFLIB to generate an intermediate GIF animation */ 40775c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 40875c73fc3SLisandro Dalcin if (gifinput) { 40975c73fc3SLisandro Dalcin char gifmovie[PETSC_MAX_PATH_LEN]; 41075c73fc3SLisandro Dalcin ierr = PetscSNPrintf(gifmovie,sizeof(gifmovie),"%s/%s_movie.gif",basename,basename);CHKERRQ(ierr); 41175c73fc3SLisandro Dalcin ierr = PetscDrawMovieSaveGIF(input,count,gifmovie);CHKERRQ(ierr); 41275c73fc3SLisandro Dalcin ierr = PetscStrcpy(input,gifmovie);CHKERRQ(ierr); 4138067a7d5SLisandro Dalcin } 41475c73fc3SLisandro Dalcin #endif 41575c73fc3SLisandro Dalcin 41675c73fc3SLisandro Dalcin /* use FFmpeg to generate a movie */ 41775c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_POPEN) 41875c73fc3SLisandro Dalcin { 419016831caSBarry Smith FILE *fd; 42075c73fc3SLisandro Dalcin char options[64] = "-loglevel error -y", extraopts[32] = "", framerate[24] = ""; 42175c73fc3SLisandro Dalcin char command[sizeof(options)+sizeof(extraopts)+sizeof(framerate)+PETSC_MAX_PATH_LEN*2]; 42275c73fc3SLisandro Dalcin if (fps > 0) {ierr = PetscSNPrintf(framerate,sizeof(framerate),"-r %d",(int)fps);CHKERRQ(ierr);} 42375c73fc3SLisandro Dalcin if (gifinput) { 424a126751eSBarry Smith ierr = PetscStrlcat(options," -f gif",sizeof(options));CHKERRQ(ierr); 42575c73fc3SLisandro Dalcin ierr = PetscSNPrintf(extraopts,sizeof(extraopts)," -default_delay %d",(fps > 0) ? 100/(int)fps : 4);CHKERRQ(ierr); 42675c73fc3SLisandro Dalcin } else { 427a126751eSBarry Smith ierr = PetscStrlcat(options," -f image2",sizeof(options));CHKERRQ(ierr); 42875c73fc3SLisandro Dalcin if (fps > 0) {ierr = PetscSNPrintf(extraopts,sizeof(extraopts)," -framerate %d",(int)fps);CHKERRQ(ierr);} 42975c73fc3SLisandro Dalcin } 430a126751eSBarry Smith if (extraopts[0]) {ierr = PetscStrlcat(options,extraopts,sizeof(options));CHKERRQ(ierr);} 43175c73fc3SLisandro Dalcin ierr = PetscSNPrintf(command,sizeof(command),"ffmpeg %s -i \"%s\" %s \"%s\"",options,input,framerate,output);CHKERRQ(ierr); 4328067a7d5SLisandro Dalcin ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr); 433016831caSBarry Smith ierr = PetscPClose(PETSC_COMM_SELF,fd);CHKERRQ(ierr); 4348067a7d5SLisandro Dalcin } 4358067a7d5SLisandro Dalcin #endif 4368067a7d5SLisandro Dalcin PetscFunctionReturn(0); 4378067a7d5SLisandro Dalcin } 438