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 188067a7d5SLisandro Dalcin PetscFunctionBegin; 198067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 208067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,2); 218067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 228067a7d5SLisandro Dalcin /* map pixels to RGB colors */ 238067a7d5SLisandro Dalcin if (palette) { 248067a7d5SLisandro Dalcin int k,p,n = (int)(w*h); 258067a7d5SLisandro Dalcin const unsigned char *colordef; 269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3*w*h,&rgb)); 278067a7d5SLisandro Dalcin for (k=p=0; k<n; k++) { 288067a7d5SLisandro Dalcin colordef = palette[pixels[k]]; 298067a7d5SLisandro Dalcin rgb[p++] = colordef[0]; 308067a7d5SLisandro Dalcin rgb[p++] = colordef[1]; 318067a7d5SLisandro Dalcin rgb[p++] = colordef[2]; 328067a7d5SLisandro Dalcin } 338067a7d5SLisandro Dalcin } else { /* assume pixels are RGB colors */ 348067a7d5SLisandro Dalcin rgb = (unsigned char*)pixels; 358067a7d5SLisandro Dalcin } 368067a7d5SLisandro Dalcin /* open file and write PPM header */ 379566063dSJacob Faibussowitsch PetscCall(PetscBinaryOpen(filename,FILE_MODE_WRITE,&fd)); 389566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(header,sizeof(header),"P6\n%d %d\n255\n%c",(int)w,(int)h,'\0')); 399566063dSJacob Faibussowitsch PetscCall(PetscStrlen(header,&hdrlen)); 409566063dSJacob Faibussowitsch PetscCall(PetscBinaryWrite(fd,header,hdrlen,PETSC_CHAR)); 418067a7d5SLisandro Dalcin /* write image data and close file */ 429566063dSJacob Faibussowitsch PetscCall(PetscBinaryWrite(fd,rgb,3*w*h,PETSC_CHAR)); 439566063dSJacob Faibussowitsch PetscCall(PetscBinaryClose(fd)); 449566063dSJacob Faibussowitsch if (palette) PetscCall(PetscFree(rgb)); 458067a7d5SLisandro Dalcin PetscFunctionReturn(0); 468067a7d5SLisandro Dalcin } 478067a7d5SLisandro Dalcin 488067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_PPM(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 498067a7d5SLisandro Dalcin { return PetscDrawImageSavePPM(filename,palette,w,h,pixels); } 508067a7d5SLisandro Dalcin 518067a7d5SLisandro Dalcin /* 528067a7d5SLisandro Dalcin Code to write images in PNG format 538067a7d5SLisandro Dalcin */ 548067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG) 558067a7d5SLisandro Dalcin 568067a7d5SLisandro Dalcin #include <png.h> 578067a7d5SLisandro Dalcin 588067a7d5SLisandro Dalcin #if defined(PNG_SETJMP_SUPPORTED) 598067a7d5SLisandro Dalcin # ifndef png_jmpbuf 608067a7d5SLisandro Dalcin # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 618067a7d5SLisandro Dalcin # endif 628067a7d5SLisandro Dalcin #endif 638067a7d5SLisandro Dalcin 648067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSavePNG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 658067a7d5SLisandro Dalcin { 668067a7d5SLisandro Dalcin FILE *fp; 678067a7d5SLisandro Dalcin png_struct *png_ptr; 688067a7d5SLisandro Dalcin png_info *info_ptr; 698067a7d5SLisandro Dalcin unsigned int row, stride = palette ? w : 3*w; 708067a7d5SLisandro Dalcin 718067a7d5SLisandro Dalcin PetscFunctionBegin; 728067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 738067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,2); 748067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 758067a7d5SLisandro Dalcin 768067a7d5SLisandro Dalcin /* open file and create libpng structures */ 779566063dSJacob Faibussowitsch PetscCall(PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp)); 788067a7d5SLisandro Dalcin png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); 7928b400f6SJacob Faibussowitsch PetscCheck(png_ptr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create PNG context"); 808067a7d5SLisandro Dalcin info_ptr = png_create_info_struct(png_ptr); 8128b400f6SJacob Faibussowitsch PetscCheck(info_ptr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create PNG context"); 828067a7d5SLisandro Dalcin 838067a7d5SLisandro Dalcin /* setup libpng error handling */ 848067a7d5SLisandro Dalcin #if defined(PNG_SETJMP_SUPPORTED) 858067a7d5SLisandro Dalcin if (setjmp(png_jmpbuf(png_ptr))) { 868067a7d5SLisandro Dalcin png_destroy_write_struct(&png_ptr,&info_ptr); 878067a7d5SLisandro Dalcin (void)PetscFClose(PETSC_COMM_SELF,fp); 8898921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing PNG file %s",filename); 898067a7d5SLisandro Dalcin } 908067a7d5SLisandro Dalcin #endif 918067a7d5SLisandro Dalcin 928067a7d5SLisandro Dalcin /* setup PNG image metadata */ 938067a7d5SLisandro Dalcin png_init_io(png_ptr, fp); 948067a7d5SLisandro Dalcin png_set_IHDR(png_ptr, info_ptr, w, h, /*depth*/8, 958067a7d5SLisandro Dalcin palette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB, 968067a7d5SLisandro Dalcin PNG_INTERLACE_NONE, 978067a7d5SLisandro Dalcin PNG_COMPRESSION_TYPE_DEFAULT, 988067a7d5SLisandro Dalcin PNG_FILTER_TYPE_DEFAULT); 998067a7d5SLisandro Dalcin if (palette) 1008067a7d5SLisandro Dalcin png_set_PLTE(png_ptr, info_ptr, (png_color*)palette, 256); 1018067a7d5SLisandro Dalcin 1028067a7d5SLisandro Dalcin /* write PNG image header and data */ 1038067a7d5SLisandro Dalcin png_write_info(png_ptr, info_ptr); 1048067a7d5SLisandro Dalcin for (row = 0; row < h; row++) 1058067a7d5SLisandro Dalcin png_write_row(png_ptr, pixels + row*stride); 1068067a7d5SLisandro Dalcin png_write_end(png_ptr, NULL); 1078067a7d5SLisandro Dalcin 1088067a7d5SLisandro Dalcin /* destroy libpng structures and close file */ 1098067a7d5SLisandro Dalcin png_destroy_write_struct(&png_ptr, &info_ptr); 1109566063dSJacob Faibussowitsch PetscCall(PetscFClose(PETSC_COMM_SELF,fp)); 1118067a7d5SLisandro Dalcin PetscFunctionReturn(0); 1128067a7d5SLisandro Dalcin } 1138067a7d5SLisandro Dalcin 1148067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_PNG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 1158067a7d5SLisandro Dalcin { return PetscDrawImageSavePNG(filename,palette,w,h,pixels); } 1168067a7d5SLisandro Dalcin 1178067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBPNG*/ 1188067a7d5SLisandro Dalcin 1198067a7d5SLisandro Dalcin /* 1208067a7d5SLisandro Dalcin Code to write images in GIF format 1218067a7d5SLisandro Dalcin */ 1228067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 1238067a7d5SLisandro Dalcin 1248067a7d5SLisandro Dalcin #include <gif_lib.h> 1258067a7d5SLisandro Dalcin 1268067a7d5SLisandro Dalcin #if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5 1278067a7d5SLisandro Dalcin #define GifMakeMapObject MakeMapObject 1288067a7d5SLisandro Dalcin #define GifFreeMapObject FreeMapObject 1298067a7d5SLisandro Dalcin #define EGifOpenFileName(n,b,err) EGifOpenFileName(n,b) 1308067a7d5SLisandro Dalcin #define EGifOpenFileHandle(h,err) EGifOpenFileName(h) 1318067a7d5SLisandro Dalcin #define EGifCloseFile(f,err) EGifCloseFile(f) 13275c73fc3SLisandro Dalcin #define DGifOpenFileName(n,err) DGifOpenFileName(n) 13375c73fc3SLisandro Dalcin #define DGifOpenFileHandle(h,err) DGifOpenFileName(h) 13475c73fc3SLisandro Dalcin #define DGifCloseFile(f,err) DGifCloseFile(f) 1358067a7d5SLisandro Dalcin #endif 1368067a7d5SLisandro Dalcin 1378067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveGIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 1388067a7d5SLisandro Dalcin { 1399566063dSJacob Faibussowitsch int Row; 1408067a7d5SLisandro Dalcin int Width = (int)w; 1418067a7d5SLisandro Dalcin int Height = (int)h; 1428067a7d5SLisandro Dalcin int ColorRes = 8; 1438067a7d5SLisandro Dalcin int ColorCount = 256; 1448067a7d5SLisandro Dalcin ColorMapObject *GifCMap = NULL; 1458067a7d5SLisandro Dalcin GifFileType *GifFile = NULL; 14698921bdaSJacob Faibussowitsch # define SETERRGIF(msg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,msg", GIF file: %s",filename) 1479566063dSJacob Faibussowitsch # define PetscCallGIF(msg,...) do { \ 1489566063dSJacob Faibussowitsch int Error = __VA_ARGS__; \ 1499566063dSJacob Faibussowitsch if (PetscUnlikely(Error != GIF_OK)) SETERRGIF(msg); \ 1509566063dSJacob Faibussowitsch } while (0) 1518067a7d5SLisandro Dalcin 1528067a7d5SLisandro Dalcin PetscFunctionBegin; 1538067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 1548067a7d5SLisandro Dalcin PetscValidCharPointer(palette,2); 1558067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 1568067a7d5SLisandro Dalcin 1578067a7d5SLisandro Dalcin GifCMap = GifMakeMapObject(ColorCount, (GifColorType*)palette); if (!GifCMap) SETERRGIF("Allocating colormap"); 1588067a7d5SLisandro Dalcin GifFile = EGifOpenFileName(filename, 0, NULL); if (!GifFile) SETERRGIF("Opening"); 1599566063dSJacob Faibussowitsch PetscCallGIF("Writing screen descriptor", EGifPutScreenDesc(GifFile, Width, Height, ColorRes, 0, GifCMap)); 1609566063dSJacob Faibussowitsch PetscCallGIF("Writing image descriptor", EGifPutImageDesc(GifFile, 0, 0, Width, Height, 0, NULL)); 1618067a7d5SLisandro Dalcin for (Row = 0; Row < Height; Row++) { 1629566063dSJacob Faibussowitsch PetscCallGIF("Writing image pixels", EGifPutLine(GifFile, (GifPixelType*)pixels + Row*Width, Width)); 1638067a7d5SLisandro Dalcin } 1649566063dSJacob Faibussowitsch PetscCallGIF("Closing", EGifCloseFile(GifFile, NULL)); 1658067a7d5SLisandro Dalcin GifFreeMapObject(GifCMap); GifCMap = NULL; 1668067a7d5SLisandro Dalcin 1678067a7d5SLisandro Dalcin # undef SETERRGIF 1688067a7d5SLisandro Dalcin # undef CHKERRGIF 1698067a7d5SLisandro Dalcin PetscFunctionReturn(0); 1708067a7d5SLisandro Dalcin } 1718067a7d5SLisandro Dalcin 1728067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_GIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 1738067a7d5SLisandro Dalcin { return PetscDrawImageSaveGIF(filename,palette,w,h,pixels); } 1748067a7d5SLisandro Dalcin 17575c73fc3SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieSaveGIF(const char pattern[],PetscInt count,const char movie[]) 17675c73fc3SLisandro Dalcin { 17775c73fc3SLisandro Dalcin int i,j,Row; 17875c73fc3SLisandro Dalcin char image[PETSC_MAX_PATH_LEN]; 17975c73fc3SLisandro Dalcin GifFileType *GifMovie = NULL; 18075c73fc3SLisandro Dalcin GifFileType *GifImage = NULL; 18198921bdaSJacob Faibussowitsch # define SETERRGIF(msg,fn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,msg" GIF file %s",fn) 18275c73fc3SLisandro Dalcin 18375c73fc3SLisandro Dalcin PetscFunctionBegin; 18475c73fc3SLisandro Dalcin PetscValidCharPointer(pattern,1); 18575c73fc3SLisandro Dalcin PetscValidCharPointer(movie,3); 18675c73fc3SLisandro Dalcin if (count < 1) PetscFunctionReturn(0); 18775c73fc3SLisandro Dalcin 18875c73fc3SLisandro Dalcin for (i = 0; i < count; i++) { 1899566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(image,sizeof(image),pattern,(int)i)); 19075c73fc3SLisandro Dalcin /* open and read image file */ 19175c73fc3SLisandro Dalcin if ((GifImage = DGifOpenFileName(image, NULL)) == NULL) SETERRGIF("Opening input",image); 19275c73fc3SLisandro Dalcin if (DGifSlurp(GifImage) != GIF_OK) SETERRGIF("Reading input",image); 19375c73fc3SLisandro Dalcin /* open movie file and write header */ 19475c73fc3SLisandro Dalcin if (i == 0) { 19575c73fc3SLisandro Dalcin if ((GifMovie = EGifOpenFileName(movie, 0, NULL)) == NULL) SETERRGIF("Opening output",movie); 19675c73fc3SLisandro Dalcin if (EGifPutScreenDesc(GifMovie, 19775c73fc3SLisandro Dalcin GifImage->SWidth, 19875c73fc3SLisandro Dalcin GifImage->SHeight, 19975c73fc3SLisandro Dalcin GifImage->SColorResolution, 20075c73fc3SLisandro Dalcin GifImage->SBackGroundColor, 20175c73fc3SLisandro Dalcin GifImage->SColorMap) != GIF_OK) SETERRGIF("Writing screen descriptor,",movie); 20275c73fc3SLisandro Dalcin } 20375c73fc3SLisandro Dalcin /* loop over all frames in image */ 20475c73fc3SLisandro Dalcin for (j = 0; j < GifImage->ImageCount; j++) { 20575c73fc3SLisandro Dalcin SavedImage *sp = &GifImage->SavedImages[j]; 20675c73fc3SLisandro Dalcin GifImageDesc *GifFrame = &sp->ImageDesc; 20775c73fc3SLisandro Dalcin ColorMapObject *FrameColorMap = GifFrame->ColorMap ? GifFrame->ColorMap : GifImage->SColorMap; 20875c73fc3SLisandro Dalcin if (GifMovie->SColorMap && GifMovie->SColorMap->ColorCount == FrameColorMap->ColorCount && 20975c73fc3SLisandro Dalcin !memcmp(GifMovie->SColorMap->Colors,FrameColorMap->Colors, 21075c73fc3SLisandro Dalcin (size_t)FrameColorMap->ColorCount*sizeof(GifColorType))) 21175c73fc3SLisandro Dalcin FrameColorMap = NULL; 21275c73fc3SLisandro Dalcin /* add frame to movie */ 21375c73fc3SLisandro Dalcin if (EGifPutImageDesc(GifMovie, 21475c73fc3SLisandro Dalcin GifFrame->Left, 21575c73fc3SLisandro Dalcin GifFrame->Top, 21675c73fc3SLisandro Dalcin GifFrame->Width, 21775c73fc3SLisandro Dalcin GifFrame->Height, 21875c73fc3SLisandro Dalcin GifFrame->Interlace, 21975c73fc3SLisandro Dalcin FrameColorMap) != GIF_OK) SETERRGIF("Writing image descriptor,",movie); 22075c73fc3SLisandro Dalcin for (Row = 0; Row < GifFrame->Height; Row++) { 22175c73fc3SLisandro Dalcin if (EGifPutLine(GifMovie, 22275c73fc3SLisandro Dalcin sp->RasterBits + Row * GifFrame->Width, 22375c73fc3SLisandro Dalcin GifFrame->Width) != GIF_OK) SETERRGIF("Writing image pixels,",movie); 22475c73fc3SLisandro Dalcin } 22575c73fc3SLisandro Dalcin } 22675c73fc3SLisandro Dalcin if (DGifCloseFile(GifImage, NULL) != GIF_OK) SETERRGIF("Closing input",image); 22775c73fc3SLisandro Dalcin } 22875c73fc3SLisandro Dalcin if (EGifCloseFile(GifMovie, NULL) != GIF_OK) SETERRGIF("Closing output",movie); 22975c73fc3SLisandro Dalcin 23075c73fc3SLisandro Dalcin # undef SETERRGIF 23175c73fc3SLisandro Dalcin PetscFunctionReturn(0); 23275c73fc3SLisandro Dalcin } 23375c73fc3SLisandro Dalcin 2348067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_GIFLIB*/ 2358067a7d5SLisandro Dalcin 2368067a7d5SLisandro Dalcin /* 2378067a7d5SLisandro Dalcin Code to write images in JPEG format 2388067a7d5SLisandro Dalcin */ 2398067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 2408067a7d5SLisandro Dalcin 2418067a7d5SLisandro Dalcin #include <jpeglib.h> 2428067a7d5SLisandro Dalcin 2438067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2448067a7d5SLisandro Dalcin #include <setjmp.h> 2458067a7d5SLisandro Dalcin static jmp_buf petsc_jpeg_jumpbuf; 2468067a7d5SLisandro Dalcin static void petsc_jpeg_error_longjmp (j_common_ptr cinfo) { (void)cinfo; longjmp(petsc_jpeg_jumpbuf,1); } 2478067a7d5SLisandro Dalcin #endif 2488067a7d5SLisandro Dalcin 2498067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveJPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 2508067a7d5SLisandro Dalcin { 2518067a7d5SLisandro Dalcin unsigned char *rgbpixels; 2528067a7d5SLisandro Dalcin FILE *fp; 2538067a7d5SLisandro Dalcin struct jpeg_compress_struct cinfo; 2548067a7d5SLisandro Dalcin struct jpeg_error_mgr jerr; 2558067a7d5SLisandro Dalcin 2568067a7d5SLisandro Dalcin PetscFunctionBegin; 2578067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 2588067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,2); 2598067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 2608067a7d5SLisandro Dalcin /* map pixels to RGB colors */ 2618067a7d5SLisandro Dalcin if (palette) { 2628067a7d5SLisandro Dalcin int k,p,n = (int)(w*h); 2638067a7d5SLisandro Dalcin const unsigned char *colordef; 2649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3*w*h,&rgbpixels)); 2658067a7d5SLisandro Dalcin for (k=p=0; k<n; k++) { 2668067a7d5SLisandro Dalcin colordef = palette[pixels[k]]; 2678067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[0]; 2688067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[1]; 2698067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[2]; 2708067a7d5SLisandro Dalcin } 2718067a7d5SLisandro Dalcin } else { /* assume pixels are RGB colors */ 2728067a7d5SLisandro Dalcin rgbpixels = (unsigned char*)pixels; 2738067a7d5SLisandro Dalcin } 2749566063dSJacob Faibussowitsch PetscCall(PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp)); 2758067a7d5SLisandro Dalcin 2768067a7d5SLisandro Dalcin cinfo.err = jpeg_std_error(&jerr); 2778067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2788067a7d5SLisandro Dalcin jerr.error_exit = petsc_jpeg_error_longjmp; 2798067a7d5SLisandro Dalcin if (setjmp(petsc_jpeg_jumpbuf)) { 2808067a7d5SLisandro Dalcin char message[JMSG_LENGTH_MAX]; 2818067a7d5SLisandro Dalcin jerr.format_message((j_common_ptr)&cinfo,message); 2828067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 2838067a7d5SLisandro Dalcin (void)PetscFClose(PETSC_COMM_SELF,fp); 28498921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing JPEG file %s\n%s",filename,message); 2858067a7d5SLisandro Dalcin } 2868067a7d5SLisandro Dalcin #endif 2878067a7d5SLisandro Dalcin jpeg_create_compress(&cinfo); 2888067a7d5SLisandro Dalcin jpeg_stdio_dest(&cinfo,fp); 2898067a7d5SLisandro Dalcin cinfo.image_width = w; 2908067a7d5SLisandro Dalcin cinfo.image_height = h; 2918067a7d5SLisandro Dalcin cinfo.input_components = 3; 2928067a7d5SLisandro Dalcin cinfo.in_color_space = JCS_RGB; 2938067a7d5SLisandro Dalcin jpeg_set_defaults(&cinfo); 2948067a7d5SLisandro Dalcin jpeg_start_compress(&cinfo,TRUE); 2958067a7d5SLisandro Dalcin while (cinfo.next_scanline < cinfo.image_height) { 2968067a7d5SLisandro Dalcin unsigned char *rowptr = rgbpixels + cinfo.next_scanline * 3*w; 2978067a7d5SLisandro Dalcin (void)jpeg_write_scanlines(&cinfo,&rowptr,1); 2988067a7d5SLisandro Dalcin } 2998067a7d5SLisandro Dalcin jpeg_finish_compress(&cinfo); 3008067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 3018067a7d5SLisandro Dalcin 3029566063dSJacob Faibussowitsch PetscCall(PetscFClose(PETSC_COMM_SELF,fp)); 3039566063dSJacob Faibussowitsch if (palette) PetscCall(PetscFree(rgbpixels)); 3048067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3058067a7d5SLisandro Dalcin } 3068067a7d5SLisandro Dalcin 3078067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_JPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 3088067a7d5SLisandro Dalcin { return PetscDrawImageSaveJPG(filename,palette,w,h,pixels); } 3098067a7d5SLisandro Dalcin 3108067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBJPEG*/ 3118067a7d5SLisandro Dalcin 3128067a7d5SLisandro Dalcin static struct { 3138067a7d5SLisandro Dalcin const char *extension; 3148067a7d5SLisandro Dalcin PetscErrorCode (*SaveImage)(const char[],unsigned char[][3],unsigned int,unsigned int,const unsigned char[]); 3158067a7d5SLisandro Dalcin } PetscDrawImageSaveTable[] = { 3168067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG) 3178067a7d5SLisandro Dalcin {".png", PetscDrawImageSave_PNG}, 3188067a7d5SLisandro Dalcin #endif 3198067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 3208067a7d5SLisandro Dalcin {".gif", PetscDrawImageSave_GIF}, 3218067a7d5SLisandro Dalcin #endif 3228067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 3238067a7d5SLisandro Dalcin {".jpg", PetscDrawImageSave_JPG}, 3248067a7d5SLisandro Dalcin #endif 3258067a7d5SLisandro Dalcin {".ppm", PetscDrawImageSave_PPM} 3268067a7d5SLisandro Dalcin }; 3278067a7d5SLisandro Dalcin 3288067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageCheckFormat(const char *ext[]) 3298067a7d5SLisandro Dalcin { 3308067a7d5SLisandro Dalcin size_t k; 3318067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3328067a7d5SLisandro Dalcin 3338067a7d5SLisandro Dalcin PetscFunctionBegin; 3348067a7d5SLisandro Dalcin /* if extension is empty, return default format to caller */ 3358067a7d5SLisandro Dalcin PetscValidPointer(ext,1); 3368067a7d5SLisandro Dalcin if (!*ext || !**ext) { 3378067a7d5SLisandro Dalcin *ext = PetscDrawImageSaveTable[0].extension; 3388067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3398067a7d5SLisandro Dalcin } 340a9db196aSBarry Smith /* check the extension matches a supported format */ 3418067a7d5SLisandro Dalcin PetscValidCharPointer(*ext,1); 342*dd39110bSPierre Jolivet for (k=0; k<PETSC_STATIC_ARRAY_LENGTH(PetscDrawImageSaveTable); k++) { 3439566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(*ext,PetscDrawImageSaveTable[k].extension,&match)); 3448067a7d5SLisandro Dalcin if (match && PetscDrawImageSaveTable[k].SaveImage) PetscFunctionReturn(0); 3458067a7d5SLisandro Dalcin } 34698921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm or see PetscDrawSetSave() for what ./configure option you may need",*ext); 3478067a7d5SLisandro Dalcin } 3488067a7d5SLisandro Dalcin 3498067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageSave(const char basename[],const char ext[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 3508067a7d5SLisandro Dalcin { 3518067a7d5SLisandro Dalcin size_t k; 3528067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3538067a7d5SLisandro Dalcin char filename[PETSC_MAX_PATH_LEN]; 3548067a7d5SLisandro Dalcin 3558067a7d5SLisandro Dalcin PetscFunctionBegin; 3568067a7d5SLisandro Dalcin PetscValidCharPointer(basename,1); 3578067a7d5SLisandro Dalcin if (ext) PetscValidCharPointer(ext,2); 358dadcf809SJacob Faibussowitsch if (palette) PetscValidPointer(palette,3); 3598067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,6); 3608067a7d5SLisandro Dalcin 3619566063dSJacob Faibussowitsch PetscCall(PetscDrawImageCheckFormat(&ext)); 3629566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename,sizeof(filename),"%s%s",basename,ext)); 363*dd39110bSPierre Jolivet for (k=0; k<PETSC_STATIC_ARRAY_LENGTH(PetscDrawImageSaveTable); k++) { 3649566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(ext,PetscDrawImageSaveTable[k].extension,&match)); 3658067a7d5SLisandro Dalcin if (match && PetscDrawImageSaveTable[k].SaveImage) { 3669566063dSJacob Faibussowitsch PetscCall(PetscDrawImageSaveTable[k].SaveImage(filename,palette,w,h,pixels)); 3678067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3688067a7d5SLisandro Dalcin } 3698067a7d5SLisandro Dalcin } 37098921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",ext); 3718067a7d5SLisandro Dalcin } 3728067a7d5SLisandro Dalcin 3738067a7d5SLisandro Dalcin PetscErrorCode PetscDrawMovieCheckFormat(const char *ext[]) 3748067a7d5SLisandro Dalcin { 3758067a7d5SLisandro Dalcin PetscFunctionBegin; 3768067a7d5SLisandro Dalcin PetscValidPointer(ext,1); 3778067a7d5SLisandro Dalcin if (!*ext || !**ext) *ext = ".m4v"; 3788067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3798067a7d5SLisandro Dalcin } 3808067a7d5SLisandro Dalcin 3813d242201SLisandro Dalcin PetscErrorCode PetscDrawMovieSave(const char basename[],PetscInt count,const char imext[],PetscInt fps,const char mvext[]) 3828067a7d5SLisandro Dalcin { 38375c73fc3SLisandro Dalcin char input[PETSC_MAX_PATH_LEN]; 38475c73fc3SLisandro Dalcin char output[PETSC_MAX_PATH_LEN]; 38575c73fc3SLisandro Dalcin PetscBool gifinput; 3868067a7d5SLisandro Dalcin 3878067a7d5SLisandro Dalcin PetscFunctionBegin; 3888067a7d5SLisandro Dalcin PetscValidCharPointer(basename,1); 3898067a7d5SLisandro Dalcin PetscValidCharPointer(imext,3); 390064a246eSJacob Faibussowitsch if (mvext) PetscValidCharPointer(mvext,5); 3918067a7d5SLisandro Dalcin if (count < 1) PetscFunctionReturn(0); 3928067a7d5SLisandro Dalcin 3939566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(imext,".gif",&gifinput)); 3949566063dSJacob Faibussowitsch PetscCall(PetscDrawMovieCheckFormat(&mvext)); 3959566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(input,sizeof(input),"%s/%s_%%d%s",basename,basename,imext)); 3969566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(output,sizeof(output),"%s%s",basename,mvext)); 39775c73fc3SLisandro Dalcin 39875c73fc3SLisandro Dalcin /* use GIFLIB to generate an intermediate GIF animation */ 39975c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 40075c73fc3SLisandro Dalcin if (gifinput) { 40175c73fc3SLisandro Dalcin char gifmovie[PETSC_MAX_PATH_LEN]; 4029566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(gifmovie,sizeof(gifmovie),"%s/%s_movie.gif",basename,basename)); 4039566063dSJacob Faibussowitsch PetscCall(PetscDrawMovieSaveGIF(input,count,gifmovie)); 4049566063dSJacob Faibussowitsch PetscCall(PetscStrcpy(input,gifmovie)); 4058067a7d5SLisandro Dalcin } 40675c73fc3SLisandro Dalcin #endif 40775c73fc3SLisandro Dalcin 40875c73fc3SLisandro Dalcin /* use FFmpeg to generate a movie */ 40975c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_POPEN) 41075c73fc3SLisandro Dalcin { 411016831caSBarry Smith FILE *fd; 41275c73fc3SLisandro Dalcin char options[64] = "-loglevel error -y", extraopts[32] = "", framerate[24] = ""; 41375c73fc3SLisandro Dalcin char command[sizeof(options)+sizeof(extraopts)+sizeof(framerate)+PETSC_MAX_PATH_LEN*2]; 4149566063dSJacob Faibussowitsch if (fps > 0) PetscCall(PetscSNPrintf(framerate,sizeof(framerate),"-r %d",(int)fps)); 41575c73fc3SLisandro Dalcin if (gifinput) { 4169566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(options," -f gif",sizeof(options))); 4179566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(extraopts,sizeof(extraopts)," -default_delay %d",(fps > 0) ? 100/(int)fps : 4)); 41875c73fc3SLisandro Dalcin } else { 4199566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(options," -f image2",sizeof(options))); 4209566063dSJacob Faibussowitsch if (fps > 0) PetscCall(PetscSNPrintf(extraopts,sizeof(extraopts)," -framerate %d",(int)fps)); 42175c73fc3SLisandro Dalcin } 4229566063dSJacob Faibussowitsch if (extraopts[0]) PetscCall(PetscStrlcat(options,extraopts,sizeof(options))); 4239566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(command,sizeof(command),"ffmpeg %s -i \"%s\" %s \"%s\"",options,input,framerate,output)); 4249566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd)); 4259566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF,fd)); 4268067a7d5SLisandro Dalcin } 4278067a7d5SLisandro Dalcin #endif 4288067a7d5SLisandro Dalcin PetscFunctionReturn(0); 4298067a7d5SLisandro Dalcin } 430