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 #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) 140*75c73fc3SLisandro Dalcin #define DGifOpenFileName(n,err) DGifOpenFileName(n) 141*75c73fc3SLisandro Dalcin #define DGifOpenFileHandle(h,err) DGifOpenFileName(h) 142*75c73fc3SLisandro Dalcin #define DGifCloseFile(f,err) DGifCloseFile(f) 1438067a7d5SLisandro Dalcin #endif 1448067a7d5SLisandro Dalcin 1458067a7d5SLisandro Dalcin #undef __FUNCT__ 1468067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSaveGIF" 1478067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveGIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 1488067a7d5SLisandro Dalcin { 1498067a7d5SLisandro Dalcin int Row, Error; 1508067a7d5SLisandro Dalcin int Width = (int)w; 1518067a7d5SLisandro Dalcin int Height = (int)h; 1528067a7d5SLisandro Dalcin int ColorRes = 8; 1538067a7d5SLisandro Dalcin int ColorCount = 256; 1548067a7d5SLisandro Dalcin ColorMapObject *GifCMap = NULL; 1558067a7d5SLisandro Dalcin GifFileType *GifFile = NULL; 1568067a7d5SLisandro Dalcin # define SETERRGIF(msg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,msg", GIF file: %s",filename) 1578067a7d5SLisandro Dalcin # define CHKERRGIF(msg) do {if (Error != GIF_OK) SETERRGIF(msg);} while(0) 1588067a7d5SLisandro Dalcin 1598067a7d5SLisandro Dalcin PetscFunctionBegin; 1608067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 1618067a7d5SLisandro Dalcin PetscValidCharPointer(palette,2); 1628067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 1638067a7d5SLisandro Dalcin 1648067a7d5SLisandro Dalcin GifCMap = GifMakeMapObject(ColorCount, (GifColorType*)palette); if (!GifCMap) SETERRGIF("Allocating colormap"); 1658067a7d5SLisandro Dalcin GifFile = EGifOpenFileName(filename, 0, NULL); if (!GifFile) SETERRGIF("Opening"); 1668067a7d5SLisandro Dalcin Error = EGifPutScreenDesc(GifFile, Width, Height, ColorRes, 0, GifCMap); CHKERRGIF("Writing screen descriptor"); 1678067a7d5SLisandro Dalcin Error = EGifPutImageDesc(GifFile, 0, 0, Width, Height, 0, NULL); CHKERRGIF("Writing image descriptor"); 1688067a7d5SLisandro Dalcin for (Row = 0; Row < Height; Row++) { 1698067a7d5SLisandro Dalcin Error = EGifPutLine(GifFile, (GifPixelType*)pixels + Row*Width, Width); CHKERRGIF("Writing image pixels"); 1708067a7d5SLisandro Dalcin } 1718067a7d5SLisandro Dalcin Error = EGifCloseFile(GifFile, NULL); CHKERRGIF("Closing"); 1728067a7d5SLisandro Dalcin GifFreeMapObject(GifCMap); GifCMap = NULL; 1738067a7d5SLisandro Dalcin 1748067a7d5SLisandro Dalcin # undef SETERRGIF 1758067a7d5SLisandro Dalcin # undef CHKERRGIF 1768067a7d5SLisandro Dalcin PetscFunctionReturn(0); 1778067a7d5SLisandro Dalcin } 1788067a7d5SLisandro Dalcin 1798067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_GIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 1808067a7d5SLisandro Dalcin { return PetscDrawImageSaveGIF(filename,palette,w,h,pixels); } 1818067a7d5SLisandro Dalcin 182*75c73fc3SLisandro Dalcin #undef __FUNCT__ 183*75c73fc3SLisandro Dalcin #define __FUNCT__ "PetscDrawMovieSaveGIF" 184*75c73fc3SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieSaveGIF(const char pattern[],PetscInt count,const char movie[]) 185*75c73fc3SLisandro Dalcin { 186*75c73fc3SLisandro Dalcin int i,j,Row; 187*75c73fc3SLisandro Dalcin char image[PETSC_MAX_PATH_LEN]; 188*75c73fc3SLisandro Dalcin GifFileType *GifMovie = NULL; 189*75c73fc3SLisandro Dalcin GifFileType *GifImage = NULL; 190*75c73fc3SLisandro Dalcin PetscErrorCode ierr; 191*75c73fc3SLisandro Dalcin # define SETERRGIF(msg,fn) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,msg" GIF file %s",fn) 192*75c73fc3SLisandro Dalcin 193*75c73fc3SLisandro Dalcin PetscFunctionBegin; 194*75c73fc3SLisandro Dalcin PetscValidCharPointer(pattern,1); 195*75c73fc3SLisandro Dalcin PetscValidCharPointer(movie,3); 196*75c73fc3SLisandro Dalcin if (count < 1) PetscFunctionReturn(0); 197*75c73fc3SLisandro Dalcin 198*75c73fc3SLisandro Dalcin for (i = 0; i < count; i++) { 199*75c73fc3SLisandro Dalcin ierr = PetscSNPrintf(image,sizeof(image),pattern,(int)i);CHKERRQ(ierr); 200*75c73fc3SLisandro Dalcin /* open and read image file */ 201*75c73fc3SLisandro Dalcin if ((GifImage = DGifOpenFileName(image, NULL)) == NULL) SETERRGIF("Opening input",image); 202*75c73fc3SLisandro Dalcin if (DGifSlurp(GifImage) != GIF_OK) SETERRGIF("Reading input",image); 203*75c73fc3SLisandro Dalcin /* open movie file and write header */ 204*75c73fc3SLisandro Dalcin if (i == 0) { 205*75c73fc3SLisandro Dalcin if ((GifMovie = EGifOpenFileName(movie, 0, NULL)) == NULL) SETERRGIF("Opening output",movie); 206*75c73fc3SLisandro Dalcin if (EGifPutScreenDesc(GifMovie, 207*75c73fc3SLisandro Dalcin GifImage->SWidth, 208*75c73fc3SLisandro Dalcin GifImage->SHeight, 209*75c73fc3SLisandro Dalcin GifImage->SColorResolution, 210*75c73fc3SLisandro Dalcin GifImage->SBackGroundColor, 211*75c73fc3SLisandro Dalcin GifImage->SColorMap) != GIF_OK) SETERRGIF("Writing screen descriptor,",movie); 212*75c73fc3SLisandro Dalcin } 213*75c73fc3SLisandro Dalcin /* loop over all frames in image */ 214*75c73fc3SLisandro Dalcin for (j = 0; j < GifImage->ImageCount; j++) { 215*75c73fc3SLisandro Dalcin SavedImage *sp = &GifImage->SavedImages[j]; 216*75c73fc3SLisandro Dalcin GifImageDesc *GifFrame = &sp->ImageDesc; 217*75c73fc3SLisandro Dalcin ColorMapObject *FrameColorMap = GifFrame->ColorMap ? GifFrame->ColorMap : GifImage->SColorMap; 218*75c73fc3SLisandro Dalcin if (GifMovie->SColorMap && GifMovie->SColorMap->ColorCount == FrameColorMap->ColorCount && 219*75c73fc3SLisandro Dalcin !memcmp(GifMovie->SColorMap->Colors,FrameColorMap->Colors, 220*75c73fc3SLisandro Dalcin (size_t)FrameColorMap->ColorCount*sizeof(GifColorType))) 221*75c73fc3SLisandro Dalcin FrameColorMap = NULL; 222*75c73fc3SLisandro Dalcin /* add frame to movie */ 223*75c73fc3SLisandro Dalcin if (EGifPutImageDesc(GifMovie, 224*75c73fc3SLisandro Dalcin GifFrame->Left, 225*75c73fc3SLisandro Dalcin GifFrame->Top, 226*75c73fc3SLisandro Dalcin GifFrame->Width, 227*75c73fc3SLisandro Dalcin GifFrame->Height, 228*75c73fc3SLisandro Dalcin GifFrame->Interlace, 229*75c73fc3SLisandro Dalcin FrameColorMap) != GIF_OK) SETERRGIF("Writing image descriptor,",movie); 230*75c73fc3SLisandro Dalcin for (Row = 0; Row < GifFrame->Height; Row++) { 231*75c73fc3SLisandro Dalcin if (EGifPutLine(GifMovie, 232*75c73fc3SLisandro Dalcin sp->RasterBits + Row * GifFrame->Width, 233*75c73fc3SLisandro Dalcin GifFrame->Width) != GIF_OK) SETERRGIF("Writing image pixels,",movie); 234*75c73fc3SLisandro Dalcin } 235*75c73fc3SLisandro Dalcin } 236*75c73fc3SLisandro Dalcin if (DGifCloseFile(GifImage, NULL) != GIF_OK) SETERRGIF("Closing input",image); 237*75c73fc3SLisandro Dalcin } 238*75c73fc3SLisandro Dalcin if (EGifCloseFile(GifMovie, NULL) != GIF_OK) SETERRGIF("Closing output",movie); 239*75c73fc3SLisandro Dalcin 240*75c73fc3SLisandro Dalcin # undef SETERRGIF 241*75c73fc3SLisandro Dalcin PetscFunctionReturn(0); 242*75c73fc3SLisandro Dalcin } 243*75c73fc3SLisandro Dalcin 2448067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_GIFLIB*/ 2458067a7d5SLisandro Dalcin 2468067a7d5SLisandro Dalcin /* 2478067a7d5SLisandro Dalcin Code to write images in JPEG format 2488067a7d5SLisandro Dalcin */ 2498067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 2508067a7d5SLisandro Dalcin 2518067a7d5SLisandro Dalcin #include <jpeglib.h> 2528067a7d5SLisandro Dalcin 2538067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2548067a7d5SLisandro Dalcin #include <setjmp.h> 2558067a7d5SLisandro Dalcin static jmp_buf petsc_jpeg_jumpbuf; 2568067a7d5SLisandro Dalcin static void petsc_jpeg_error_longjmp (j_common_ptr cinfo) { (void)cinfo; longjmp(petsc_jpeg_jumpbuf,1); } 2578067a7d5SLisandro Dalcin #endif 2588067a7d5SLisandro Dalcin 2598067a7d5SLisandro Dalcin #undef __FUNCT__ 2608067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSaveJPG" 2618067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveJPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 2628067a7d5SLisandro Dalcin { 2638067a7d5SLisandro Dalcin unsigned char *rgbpixels; 2648067a7d5SLisandro Dalcin FILE *fp; 2658067a7d5SLisandro Dalcin struct jpeg_compress_struct cinfo; 2668067a7d5SLisandro Dalcin struct jpeg_error_mgr jerr; 2678067a7d5SLisandro Dalcin PetscErrorCode ierr; 2688067a7d5SLisandro Dalcin 2698067a7d5SLisandro Dalcin PetscFunctionBegin; 2708067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 2718067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,2); 2728067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 2738067a7d5SLisandro Dalcin /* map pixels to RGB colors */ 2748067a7d5SLisandro Dalcin if (palette) { 2758067a7d5SLisandro Dalcin int k,p,n = (int)(w*h); 2768067a7d5SLisandro Dalcin const unsigned char *colordef; 2778067a7d5SLisandro Dalcin ierr = PetscMalloc1(3*w*h,&rgbpixels);CHKERRQ(ierr); 2788067a7d5SLisandro Dalcin for (k=p=0; k<n; k++) { 2798067a7d5SLisandro Dalcin colordef = palette[pixels[k]]; 2808067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[0]; 2818067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[1]; 2828067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[2]; 2838067a7d5SLisandro Dalcin } 2848067a7d5SLisandro Dalcin } else { /* assume pixels are RGB colors */ 2858067a7d5SLisandro Dalcin rgbpixels = (unsigned char*)pixels; 2868067a7d5SLisandro Dalcin } 2878067a7d5SLisandro Dalcin ierr = PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp);CHKERRQ(ierr); 2888067a7d5SLisandro Dalcin 2898067a7d5SLisandro Dalcin cinfo.err = jpeg_std_error(&jerr); 2908067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2918067a7d5SLisandro Dalcin jerr.error_exit = petsc_jpeg_error_longjmp; 2928067a7d5SLisandro Dalcin if (setjmp(petsc_jpeg_jumpbuf)) { 2938067a7d5SLisandro Dalcin char message[JMSG_LENGTH_MAX]; 2948067a7d5SLisandro Dalcin jerr.format_message((j_common_ptr)&cinfo,message); 2958067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 2968067a7d5SLisandro Dalcin (void)PetscFClose(PETSC_COMM_SELF,fp); 2978067a7d5SLisandro Dalcin SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing JPEG file %s\n%s",filename,message); 2988067a7d5SLisandro Dalcin } 2998067a7d5SLisandro Dalcin #endif 3008067a7d5SLisandro Dalcin jpeg_create_compress(&cinfo); 3018067a7d5SLisandro Dalcin jpeg_stdio_dest(&cinfo,fp); 3028067a7d5SLisandro Dalcin cinfo.image_width = w; 3038067a7d5SLisandro Dalcin cinfo.image_height = h; 3048067a7d5SLisandro Dalcin cinfo.input_components = 3; 3058067a7d5SLisandro Dalcin cinfo.in_color_space = JCS_RGB; 3068067a7d5SLisandro Dalcin jpeg_set_defaults(&cinfo); 3078067a7d5SLisandro Dalcin jpeg_start_compress(&cinfo,TRUE); 3088067a7d5SLisandro Dalcin while (cinfo.next_scanline < cinfo.image_height) { 3098067a7d5SLisandro Dalcin unsigned char *rowptr = rgbpixels + cinfo.next_scanline * 3*w; 3108067a7d5SLisandro Dalcin (void)jpeg_write_scanlines(&cinfo,&rowptr,1); 3118067a7d5SLisandro Dalcin } 3128067a7d5SLisandro Dalcin jpeg_finish_compress(&cinfo); 3138067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 3148067a7d5SLisandro Dalcin 3158067a7d5SLisandro Dalcin ierr = PetscFClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr); 3168067a7d5SLisandro Dalcin if (palette) {ierr = PetscFree(rgbpixels);CHKERRQ(ierr);} 3178067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3188067a7d5SLisandro Dalcin } 3198067a7d5SLisandro Dalcin 3208067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_JPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 3218067a7d5SLisandro Dalcin { return PetscDrawImageSaveJPG(filename,palette,w,h,pixels); } 3228067a7d5SLisandro Dalcin 3238067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBJPEG*/ 3248067a7d5SLisandro Dalcin 3258067a7d5SLisandro Dalcin static struct { 3268067a7d5SLisandro Dalcin const char *extension; 3278067a7d5SLisandro Dalcin PetscErrorCode (*SaveImage)(const char[],unsigned char[][3],unsigned int,unsigned int,const unsigned char[]); 3288067a7d5SLisandro Dalcin } PetscDrawImageSaveTable[] = { 3298067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG) 3308067a7d5SLisandro Dalcin {".png", PetscDrawImageSave_PNG}, 3318067a7d5SLisandro Dalcin #endif 3328067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 3338067a7d5SLisandro Dalcin {".gif", PetscDrawImageSave_GIF}, 3348067a7d5SLisandro Dalcin #endif 3358067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 3368067a7d5SLisandro Dalcin {".jpg", PetscDrawImageSave_JPG}, 3378067a7d5SLisandro Dalcin #endif 3388067a7d5SLisandro Dalcin {".ppm", PetscDrawImageSave_PPM} 3398067a7d5SLisandro Dalcin }; 3408067a7d5SLisandro Dalcin 3418067a7d5SLisandro Dalcin #undef __FUNCT__ 3428067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageCheckFormat" 3438067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageCheckFormat(const char *ext[]) 3448067a7d5SLisandro Dalcin { 3458067a7d5SLisandro Dalcin size_t k; 3468067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3478067a7d5SLisandro Dalcin PetscErrorCode ierr; 3488067a7d5SLisandro Dalcin 3498067a7d5SLisandro Dalcin PetscFunctionBegin; 3508067a7d5SLisandro Dalcin /* if extension is empty, return default format to caller */ 3518067a7d5SLisandro Dalcin PetscValidPointer(ext,1); 3528067a7d5SLisandro Dalcin if (!*ext || !**ext) { 3538067a7d5SLisandro Dalcin *ext = PetscDrawImageSaveTable[0].extension; 3548067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3558067a7d5SLisandro Dalcin } 3568067a7d5SLisandro Dalcin /* check the extension mathes a supported format otherwise */ 3578067a7d5SLisandro Dalcin PetscValidCharPointer(*ext,1); 3588067a7d5SLisandro Dalcin for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) { 3598067a7d5SLisandro Dalcin ierr = PetscStrcasecmp(*ext,PetscDrawImageSaveTable[k].extension,&match);CHKERRQ(ierr); 3608067a7d5SLisandro Dalcin if (match && PetscDrawImageSaveTable[k].SaveImage) PetscFunctionReturn(0); 3618067a7d5SLisandro Dalcin } 3628067a7d5SLisandro Dalcin SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",*ext); 3638067a7d5SLisandro Dalcin PetscFunctionReturn(PETSC_ERR_SUP); 3648067a7d5SLisandro Dalcin } 3658067a7d5SLisandro Dalcin 3668067a7d5SLisandro Dalcin #undef __FUNCT__ 3678067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawImageSave" 3688067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageSave(const char basename[],const char ext[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 3698067a7d5SLisandro Dalcin { 3708067a7d5SLisandro Dalcin size_t k; 3718067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3728067a7d5SLisandro Dalcin char filename[PETSC_MAX_PATH_LEN]; 3738067a7d5SLisandro Dalcin PetscErrorCode ierr; 3748067a7d5SLisandro Dalcin 3758067a7d5SLisandro Dalcin PetscFunctionBegin; 3768067a7d5SLisandro Dalcin PetscValidCharPointer(basename,1); 3778067a7d5SLisandro Dalcin if (ext) PetscValidCharPointer(ext,2); 3788067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,3); 3798067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,6); 3808067a7d5SLisandro Dalcin 3818067a7d5SLisandro Dalcin ierr = PetscDrawImageCheckFormat(&ext);CHKERRQ(ierr); 3828067a7d5SLisandro Dalcin ierr = PetscSNPrintf(filename,sizeof(filename),"%s%s",basename,ext);CHKERRQ(ierr); 3838067a7d5SLisandro Dalcin for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) { 3848067a7d5SLisandro Dalcin ierr = PetscStrcasecmp(ext,PetscDrawImageSaveTable[k].extension,&match);CHKERRQ(ierr); 3858067a7d5SLisandro Dalcin if (match && PetscDrawImageSaveTable[k].SaveImage) { 3868067a7d5SLisandro Dalcin ierr = PetscDrawImageSaveTable[k].SaveImage(filename,palette,w,h,pixels);CHKERRQ(ierr); 3878067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3888067a7d5SLisandro Dalcin } 3898067a7d5SLisandro Dalcin } 3908067a7d5SLisandro Dalcin SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",ext); 3918067a7d5SLisandro Dalcin PetscFunctionReturn(PETSC_ERR_SUP); 3928067a7d5SLisandro Dalcin } 3938067a7d5SLisandro Dalcin 3948067a7d5SLisandro Dalcin #undef __FUNCT__ 3958067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawMovieCheckFormat" 3968067a7d5SLisandro Dalcin PetscErrorCode PetscDrawMovieCheckFormat(const char *ext[]) 3978067a7d5SLisandro Dalcin { 3988067a7d5SLisandro Dalcin PetscFunctionBegin; 3998067a7d5SLisandro Dalcin PetscValidPointer(ext,1); 4008067a7d5SLisandro Dalcin if (!*ext || !**ext) *ext = ".m4v"; 4018067a7d5SLisandro Dalcin PetscFunctionReturn(0); 4028067a7d5SLisandro Dalcin } 4038067a7d5SLisandro Dalcin 4048067a7d5SLisandro Dalcin #undef __FUNCT__ 4058067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawMovieSave" 4063d242201SLisandro Dalcin PetscErrorCode PetscDrawMovieSave(const char basename[],PetscInt count,const char imext[],PetscInt fps,const char mvext[]) 4078067a7d5SLisandro Dalcin { 408*75c73fc3SLisandro Dalcin char input[PETSC_MAX_PATH_LEN]; 409*75c73fc3SLisandro Dalcin char output[PETSC_MAX_PATH_LEN]; 410*75c73fc3SLisandro Dalcin PetscBool gifinput; 4118067a7d5SLisandro Dalcin PetscErrorCode ierr; 4128067a7d5SLisandro Dalcin 4138067a7d5SLisandro Dalcin PetscFunctionBegin; 4148067a7d5SLisandro Dalcin PetscValidCharPointer(basename,1); 4158067a7d5SLisandro Dalcin PetscValidCharPointer(imext,3); 4168067a7d5SLisandro Dalcin if (mvext) PetscValidCharPointer(mvext,4); 4178067a7d5SLisandro Dalcin if (count < 1) PetscFunctionReturn(0); 4188067a7d5SLisandro Dalcin 419*75c73fc3SLisandro Dalcin ierr = PetscStrcasecmp(imext,".gif",&gifinput);CHKERRQ(ierr); 4208067a7d5SLisandro Dalcin ierr = PetscDrawMovieCheckFormat(&mvext);CHKERRQ(ierr); 4213d242201SLisandro Dalcin ierr = PetscSNPrintf(input,sizeof(input),"%s/%s_%%d%s",basename,basename,imext);CHKERRQ(ierr); 4223d242201SLisandro Dalcin ierr = PetscSNPrintf(output,sizeof(output),"%s%s",basename,mvext);CHKERRQ(ierr); 423*75c73fc3SLisandro Dalcin 424*75c73fc3SLisandro Dalcin /* use GIFLIB to generate an intermediate GIF animation */ 425*75c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 426*75c73fc3SLisandro Dalcin if (gifinput) { 427*75c73fc3SLisandro Dalcin char gifmovie[PETSC_MAX_PATH_LEN]; 428*75c73fc3SLisandro Dalcin ierr = PetscSNPrintf(gifmovie,sizeof(gifmovie),"%s/%s_movie.gif",basename,basename);CHKERRQ(ierr); 429*75c73fc3SLisandro Dalcin ierr = PetscDrawMovieSaveGIF(input,count,gifmovie);CHKERRQ(ierr); 430*75c73fc3SLisandro Dalcin ierr = PetscStrcpy(input,gifmovie);CHKERRQ(ierr); 4318067a7d5SLisandro Dalcin } 432*75c73fc3SLisandro Dalcin #endif 433*75c73fc3SLisandro Dalcin 434*75c73fc3SLisandro Dalcin /* use FFmpeg to generate a movie */ 435*75c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_POPEN) 436*75c73fc3SLisandro Dalcin { 437*75c73fc3SLisandro Dalcin FILE *fd; int err; 438*75c73fc3SLisandro Dalcin char options[64] = "-loglevel error -y", extraopts[32] = "", framerate[24] = ""; 439*75c73fc3SLisandro Dalcin char command[sizeof(options)+sizeof(extraopts)+sizeof(framerate)+PETSC_MAX_PATH_LEN*2]; 440*75c73fc3SLisandro Dalcin if (fps > 0) {ierr = PetscSNPrintf(framerate,sizeof(framerate),"-r %d",(int)fps);CHKERRQ(ierr);} 441*75c73fc3SLisandro Dalcin if (gifinput) { 442*75c73fc3SLisandro Dalcin ierr = PetscStrcat(options," -f gif");CHKERRQ(ierr); 443*75c73fc3SLisandro Dalcin ierr = PetscSNPrintf(extraopts,sizeof(extraopts)," -default_delay %d",(fps > 0) ? 100/(int)fps : 4);CHKERRQ(ierr); 444*75c73fc3SLisandro Dalcin } else { 445*75c73fc3SLisandro Dalcin ierr = PetscStrcat(options," -f image2");CHKERRQ(ierr); 446*75c73fc3SLisandro Dalcin if (fps > 0) {ierr = PetscSNPrintf(extraopts,sizeof(extraopts)," -framerate %d",(int)fps);CHKERRQ(ierr);} 447*75c73fc3SLisandro Dalcin } 448*75c73fc3SLisandro Dalcin if (extraopts[0]) {ierr = PetscStrcat(options,extraopts);CHKERRQ(ierr);} 449*75c73fc3SLisandro Dalcin ierr = PetscSNPrintf(command,sizeof(command),"ffmpeg %s -i \"%s\" %s \"%s\"",options,input,framerate,output);CHKERRQ(ierr); 4508067a7d5SLisandro Dalcin ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr); 451*75c73fc3SLisandro Dalcin ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr); 4528067a7d5SLisandro Dalcin } 4538067a7d5SLisandro Dalcin #endif 4548067a7d5SLisandro Dalcin PetscFunctionReturn(0); 4558067a7d5SLisandro Dalcin } 456