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; 265f80ce2aSJacob Faibussowitsch CHKERRQ(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 */ 375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBinaryOpen(filename,FILE_MODE_WRITE,&fd)); 385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(header,sizeof(header),"P6\n%d %d\n255\n%c",(int)w,(int)h,'\0')); 395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlen(header,&hdrlen)); 405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBinaryWrite(fd,header,hdrlen,PETSC_CHAR)); 418067a7d5SLisandro Dalcin /* write image data and close file */ 425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBinaryWrite(fd,rgb,3*w*h,PETSC_CHAR)); 435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscBinaryClose(fd)); 445f80ce2aSJacob Faibussowitsch if (palette) CHKERRQ(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 */ 775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp)); 788067a7d5SLisandro Dalcin png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); 79*28b400f6SJacob Faibussowitsch PetscCheck(png_ptr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot create PNG context"); 808067a7d5SLisandro Dalcin info_ptr = png_create_info_struct(png_ptr); 81*28b400f6SJacob 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); 1105f80ce2aSJacob Faibussowitsch CHKERRQ(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 { 1398067a7d5SLisandro Dalcin int Row, Error; 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) 1478067a7d5SLisandro Dalcin # define CHKERRGIF(msg) do {if (Error != GIF_OK) SETERRGIF(msg);} while (0) 1488067a7d5SLisandro Dalcin 1498067a7d5SLisandro Dalcin PetscFunctionBegin; 1508067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 1518067a7d5SLisandro Dalcin PetscValidCharPointer(palette,2); 1528067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 1538067a7d5SLisandro Dalcin 1548067a7d5SLisandro Dalcin GifCMap = GifMakeMapObject(ColorCount, (GifColorType*)palette); if (!GifCMap) SETERRGIF("Allocating colormap"); 1558067a7d5SLisandro Dalcin GifFile = EGifOpenFileName(filename, 0, NULL); if (!GifFile) SETERRGIF("Opening"); 1568067a7d5SLisandro Dalcin Error = EGifPutScreenDesc(GifFile, Width, Height, ColorRes, 0, GifCMap); CHKERRGIF("Writing screen descriptor"); 1578067a7d5SLisandro Dalcin Error = EGifPutImageDesc(GifFile, 0, 0, Width, Height, 0, NULL); CHKERRGIF("Writing image descriptor"); 1588067a7d5SLisandro Dalcin for (Row = 0; Row < Height; Row++) { 1598067a7d5SLisandro Dalcin Error = EGifPutLine(GifFile, (GifPixelType*)pixels + Row*Width, Width); CHKERRGIF("Writing image pixels"); 1608067a7d5SLisandro Dalcin } 1618067a7d5SLisandro Dalcin Error = EGifCloseFile(GifFile, NULL); CHKERRGIF("Closing"); 1628067a7d5SLisandro Dalcin GifFreeMapObject(GifCMap); GifCMap = NULL; 1638067a7d5SLisandro Dalcin 1648067a7d5SLisandro Dalcin # undef SETERRGIF 1658067a7d5SLisandro Dalcin # undef CHKERRGIF 1668067a7d5SLisandro Dalcin PetscFunctionReturn(0); 1678067a7d5SLisandro Dalcin } 1688067a7d5SLisandro Dalcin 1698067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_GIF(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 1708067a7d5SLisandro Dalcin { return PetscDrawImageSaveGIF(filename,palette,w,h,pixels); } 1718067a7d5SLisandro Dalcin 17275c73fc3SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieSaveGIF(const char pattern[],PetscInt count,const char movie[]) 17375c73fc3SLisandro Dalcin { 17475c73fc3SLisandro Dalcin int i,j,Row; 17575c73fc3SLisandro Dalcin char image[PETSC_MAX_PATH_LEN]; 17675c73fc3SLisandro Dalcin GifFileType *GifMovie = NULL; 17775c73fc3SLisandro Dalcin GifFileType *GifImage = NULL; 17898921bdaSJacob Faibussowitsch # define SETERRGIF(msg,fn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,msg" GIF file %s",fn) 17975c73fc3SLisandro Dalcin 18075c73fc3SLisandro Dalcin PetscFunctionBegin; 18175c73fc3SLisandro Dalcin PetscValidCharPointer(pattern,1); 18275c73fc3SLisandro Dalcin PetscValidCharPointer(movie,3); 18375c73fc3SLisandro Dalcin if (count < 1) PetscFunctionReturn(0); 18475c73fc3SLisandro Dalcin 18575c73fc3SLisandro Dalcin for (i = 0; i < count; i++) { 1865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(image,sizeof(image),pattern,(int)i)); 18775c73fc3SLisandro Dalcin /* open and read image file */ 18875c73fc3SLisandro Dalcin if ((GifImage = DGifOpenFileName(image, NULL)) == NULL) SETERRGIF("Opening input",image); 18975c73fc3SLisandro Dalcin if (DGifSlurp(GifImage) != GIF_OK) SETERRGIF("Reading input",image); 19075c73fc3SLisandro Dalcin /* open movie file and write header */ 19175c73fc3SLisandro Dalcin if (i == 0) { 19275c73fc3SLisandro Dalcin if ((GifMovie = EGifOpenFileName(movie, 0, NULL)) == NULL) SETERRGIF("Opening output",movie); 19375c73fc3SLisandro Dalcin if (EGifPutScreenDesc(GifMovie, 19475c73fc3SLisandro Dalcin GifImage->SWidth, 19575c73fc3SLisandro Dalcin GifImage->SHeight, 19675c73fc3SLisandro Dalcin GifImage->SColorResolution, 19775c73fc3SLisandro Dalcin GifImage->SBackGroundColor, 19875c73fc3SLisandro Dalcin GifImage->SColorMap) != GIF_OK) SETERRGIF("Writing screen descriptor,",movie); 19975c73fc3SLisandro Dalcin } 20075c73fc3SLisandro Dalcin /* loop over all frames in image */ 20175c73fc3SLisandro Dalcin for (j = 0; j < GifImage->ImageCount; j++) { 20275c73fc3SLisandro Dalcin SavedImage *sp = &GifImage->SavedImages[j]; 20375c73fc3SLisandro Dalcin GifImageDesc *GifFrame = &sp->ImageDesc; 20475c73fc3SLisandro Dalcin ColorMapObject *FrameColorMap = GifFrame->ColorMap ? GifFrame->ColorMap : GifImage->SColorMap; 20575c73fc3SLisandro Dalcin if (GifMovie->SColorMap && GifMovie->SColorMap->ColorCount == FrameColorMap->ColorCount && 20675c73fc3SLisandro Dalcin !memcmp(GifMovie->SColorMap->Colors,FrameColorMap->Colors, 20775c73fc3SLisandro Dalcin (size_t)FrameColorMap->ColorCount*sizeof(GifColorType))) 20875c73fc3SLisandro Dalcin FrameColorMap = NULL; 20975c73fc3SLisandro Dalcin /* add frame to movie */ 21075c73fc3SLisandro Dalcin if (EGifPutImageDesc(GifMovie, 21175c73fc3SLisandro Dalcin GifFrame->Left, 21275c73fc3SLisandro Dalcin GifFrame->Top, 21375c73fc3SLisandro Dalcin GifFrame->Width, 21475c73fc3SLisandro Dalcin GifFrame->Height, 21575c73fc3SLisandro Dalcin GifFrame->Interlace, 21675c73fc3SLisandro Dalcin FrameColorMap) != GIF_OK) SETERRGIF("Writing image descriptor,",movie); 21775c73fc3SLisandro Dalcin for (Row = 0; Row < GifFrame->Height; Row++) { 21875c73fc3SLisandro Dalcin if (EGifPutLine(GifMovie, 21975c73fc3SLisandro Dalcin sp->RasterBits + Row * GifFrame->Width, 22075c73fc3SLisandro Dalcin GifFrame->Width) != GIF_OK) SETERRGIF("Writing image pixels,",movie); 22175c73fc3SLisandro Dalcin } 22275c73fc3SLisandro Dalcin } 22375c73fc3SLisandro Dalcin if (DGifCloseFile(GifImage, NULL) != GIF_OK) SETERRGIF("Closing input",image); 22475c73fc3SLisandro Dalcin } 22575c73fc3SLisandro Dalcin if (EGifCloseFile(GifMovie, NULL) != GIF_OK) SETERRGIF("Closing output",movie); 22675c73fc3SLisandro Dalcin 22775c73fc3SLisandro Dalcin # undef SETERRGIF 22875c73fc3SLisandro Dalcin PetscFunctionReturn(0); 22975c73fc3SLisandro Dalcin } 23075c73fc3SLisandro Dalcin 2318067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_GIFLIB*/ 2328067a7d5SLisandro Dalcin 2338067a7d5SLisandro Dalcin /* 2348067a7d5SLisandro Dalcin Code to write images in JPEG format 2358067a7d5SLisandro Dalcin */ 2368067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 2378067a7d5SLisandro Dalcin 2388067a7d5SLisandro Dalcin #include <jpeglib.h> 2398067a7d5SLisandro Dalcin 2408067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2418067a7d5SLisandro Dalcin #include <setjmp.h> 2428067a7d5SLisandro Dalcin static jmp_buf petsc_jpeg_jumpbuf; 2438067a7d5SLisandro Dalcin static void petsc_jpeg_error_longjmp (j_common_ptr cinfo) { (void)cinfo; longjmp(petsc_jpeg_jumpbuf,1); } 2448067a7d5SLisandro Dalcin #endif 2458067a7d5SLisandro Dalcin 2468067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSaveJPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 2478067a7d5SLisandro Dalcin { 2488067a7d5SLisandro Dalcin unsigned char *rgbpixels; 2498067a7d5SLisandro Dalcin FILE *fp; 2508067a7d5SLisandro Dalcin struct jpeg_compress_struct cinfo; 2518067a7d5SLisandro Dalcin struct jpeg_error_mgr jerr; 2528067a7d5SLisandro Dalcin 2538067a7d5SLisandro Dalcin PetscFunctionBegin; 2548067a7d5SLisandro Dalcin PetscValidCharPointer(filename,1); 2558067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,2); 2568067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,5); 2578067a7d5SLisandro Dalcin /* map pixels to RGB colors */ 2588067a7d5SLisandro Dalcin if (palette) { 2598067a7d5SLisandro Dalcin int k,p,n = (int)(w*h); 2608067a7d5SLisandro Dalcin const unsigned char *colordef; 2615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(3*w*h,&rgbpixels)); 2628067a7d5SLisandro Dalcin for (k=p=0; k<n; k++) { 2638067a7d5SLisandro Dalcin colordef = palette[pixels[k]]; 2648067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[0]; 2658067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[1]; 2668067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[2]; 2678067a7d5SLisandro Dalcin } 2688067a7d5SLisandro Dalcin } else { /* assume pixels are RGB colors */ 2698067a7d5SLisandro Dalcin rgbpixels = (unsigned char*)pixels; 2708067a7d5SLisandro Dalcin } 2715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFOpen(PETSC_COMM_SELF,filename,"wb",&fp)); 2728067a7d5SLisandro Dalcin 2738067a7d5SLisandro Dalcin cinfo.err = jpeg_std_error(&jerr); 2748067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2758067a7d5SLisandro Dalcin jerr.error_exit = petsc_jpeg_error_longjmp; 2768067a7d5SLisandro Dalcin if (setjmp(petsc_jpeg_jumpbuf)) { 2778067a7d5SLisandro Dalcin char message[JMSG_LENGTH_MAX]; 2788067a7d5SLisandro Dalcin jerr.format_message((j_common_ptr)&cinfo,message); 2798067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 2808067a7d5SLisandro Dalcin (void)PetscFClose(PETSC_COMM_SELF,fp); 28198921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error writing JPEG file %s\n%s",filename,message); 2828067a7d5SLisandro Dalcin } 2838067a7d5SLisandro Dalcin #endif 2848067a7d5SLisandro Dalcin jpeg_create_compress(&cinfo); 2858067a7d5SLisandro Dalcin jpeg_stdio_dest(&cinfo,fp); 2868067a7d5SLisandro Dalcin cinfo.image_width = w; 2878067a7d5SLisandro Dalcin cinfo.image_height = h; 2888067a7d5SLisandro Dalcin cinfo.input_components = 3; 2898067a7d5SLisandro Dalcin cinfo.in_color_space = JCS_RGB; 2908067a7d5SLisandro Dalcin jpeg_set_defaults(&cinfo); 2918067a7d5SLisandro Dalcin jpeg_start_compress(&cinfo,TRUE); 2928067a7d5SLisandro Dalcin while (cinfo.next_scanline < cinfo.image_height) { 2938067a7d5SLisandro Dalcin unsigned char *rowptr = rgbpixels + cinfo.next_scanline * 3*w; 2948067a7d5SLisandro Dalcin (void)jpeg_write_scanlines(&cinfo,&rowptr,1); 2958067a7d5SLisandro Dalcin } 2968067a7d5SLisandro Dalcin jpeg_finish_compress(&cinfo); 2978067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 2988067a7d5SLisandro Dalcin 2995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFClose(PETSC_COMM_SELF,fp)); 3005f80ce2aSJacob Faibussowitsch if (palette) CHKERRQ(PetscFree(rgbpixels)); 3018067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3028067a7d5SLisandro Dalcin } 3038067a7d5SLisandro Dalcin 3048067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawImageSave_JPG(const char filename[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 3058067a7d5SLisandro Dalcin { return PetscDrawImageSaveJPG(filename,palette,w,h,pixels); } 3068067a7d5SLisandro Dalcin 3078067a7d5SLisandro Dalcin #endif/*!PETSC_HAVE_LIBJPEG*/ 3088067a7d5SLisandro Dalcin 3098067a7d5SLisandro Dalcin static struct { 3108067a7d5SLisandro Dalcin const char *extension; 3118067a7d5SLisandro Dalcin PetscErrorCode (*SaveImage)(const char[],unsigned char[][3],unsigned int,unsigned int,const unsigned char[]); 3128067a7d5SLisandro Dalcin } PetscDrawImageSaveTable[] = { 3138067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG) 3148067a7d5SLisandro Dalcin {".png", PetscDrawImageSave_PNG}, 3158067a7d5SLisandro Dalcin #endif 3168067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 3178067a7d5SLisandro Dalcin {".gif", PetscDrawImageSave_GIF}, 3188067a7d5SLisandro Dalcin #endif 3198067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 3208067a7d5SLisandro Dalcin {".jpg", PetscDrawImageSave_JPG}, 3218067a7d5SLisandro Dalcin #endif 3228067a7d5SLisandro Dalcin {".ppm", PetscDrawImageSave_PPM} 3238067a7d5SLisandro Dalcin }; 3248067a7d5SLisandro Dalcin 3258067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageCheckFormat(const char *ext[]) 3268067a7d5SLisandro Dalcin { 3278067a7d5SLisandro Dalcin size_t k; 3288067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3298067a7d5SLisandro Dalcin 3308067a7d5SLisandro Dalcin PetscFunctionBegin; 3318067a7d5SLisandro Dalcin /* if extension is empty, return default format to caller */ 3328067a7d5SLisandro Dalcin PetscValidPointer(ext,1); 3338067a7d5SLisandro Dalcin if (!*ext || !**ext) { 3348067a7d5SLisandro Dalcin *ext = PetscDrawImageSaveTable[0].extension; 3358067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3368067a7d5SLisandro Dalcin } 337a9db196aSBarry Smith /* check the extension matches a supported format */ 3388067a7d5SLisandro Dalcin PetscValidCharPointer(*ext,1); 3398067a7d5SLisandro Dalcin for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) { 3405f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcasecmp(*ext,PetscDrawImageSaveTable[k].extension,&match)); 3418067a7d5SLisandro Dalcin if (match && PetscDrawImageSaveTable[k].SaveImage) PetscFunctionReturn(0); 3428067a7d5SLisandro Dalcin } 34398921bdaSJacob 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); 3448067a7d5SLisandro Dalcin } 3458067a7d5SLisandro Dalcin 3468067a7d5SLisandro Dalcin PetscErrorCode PetscDrawImageSave(const char basename[],const char ext[],unsigned char palette[][3],unsigned int w,unsigned int h,const unsigned char pixels[]) 3478067a7d5SLisandro Dalcin { 3488067a7d5SLisandro Dalcin size_t k; 3498067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3508067a7d5SLisandro Dalcin char filename[PETSC_MAX_PATH_LEN]; 3518067a7d5SLisandro Dalcin 3528067a7d5SLisandro Dalcin PetscFunctionBegin; 3538067a7d5SLisandro Dalcin PetscValidCharPointer(basename,1); 3548067a7d5SLisandro Dalcin if (ext) PetscValidCharPointer(ext,2); 3558067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette,3); 3568067a7d5SLisandro Dalcin PetscValidCharPointer(pixels,6); 3578067a7d5SLisandro Dalcin 3585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawImageCheckFormat(&ext)); 3595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(filename,sizeof(filename),"%s%s",basename,ext)); 3608067a7d5SLisandro Dalcin for (k=0; k<sizeof(PetscDrawImageSaveTable)/sizeof(PetscDrawImageSaveTable[0]); k++) { 3615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcasecmp(ext,PetscDrawImageSaveTable[k].extension,&match)); 3628067a7d5SLisandro Dalcin if (match && PetscDrawImageSaveTable[k].SaveImage) { 3635f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawImageSaveTable[k].SaveImage(filename,palette,w,h,pixels)); 3648067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3658067a7d5SLisandro Dalcin } 3668067a7d5SLisandro Dalcin } 36798921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Image extension %s not supported, use .ppm",ext); 3688067a7d5SLisandro Dalcin } 3698067a7d5SLisandro Dalcin 3708067a7d5SLisandro Dalcin PetscErrorCode PetscDrawMovieCheckFormat(const char *ext[]) 3718067a7d5SLisandro Dalcin { 3728067a7d5SLisandro Dalcin PetscFunctionBegin; 3738067a7d5SLisandro Dalcin PetscValidPointer(ext,1); 3748067a7d5SLisandro Dalcin if (!*ext || !**ext) *ext = ".m4v"; 3758067a7d5SLisandro Dalcin PetscFunctionReturn(0); 3768067a7d5SLisandro Dalcin } 3778067a7d5SLisandro Dalcin 3783d242201SLisandro Dalcin PetscErrorCode PetscDrawMovieSave(const char basename[],PetscInt count,const char imext[],PetscInt fps,const char mvext[]) 3798067a7d5SLisandro Dalcin { 38075c73fc3SLisandro Dalcin char input[PETSC_MAX_PATH_LEN]; 38175c73fc3SLisandro Dalcin char output[PETSC_MAX_PATH_LEN]; 38275c73fc3SLisandro Dalcin PetscBool gifinput; 3838067a7d5SLisandro Dalcin 3848067a7d5SLisandro Dalcin PetscFunctionBegin; 3858067a7d5SLisandro Dalcin PetscValidCharPointer(basename,1); 3868067a7d5SLisandro Dalcin PetscValidCharPointer(imext,3); 387064a246eSJacob Faibussowitsch if (mvext) PetscValidCharPointer(mvext,5); 3888067a7d5SLisandro Dalcin if (count < 1) PetscFunctionReturn(0); 3898067a7d5SLisandro Dalcin 3905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcasecmp(imext,".gif",&gifinput)); 3915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawMovieCheckFormat(&mvext)); 3925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(input,sizeof(input),"%s/%s_%%d%s",basename,basename,imext)); 3935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(output,sizeof(output),"%s%s",basename,mvext)); 39475c73fc3SLisandro Dalcin 39575c73fc3SLisandro Dalcin /* use GIFLIB to generate an intermediate GIF animation */ 39675c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 39775c73fc3SLisandro Dalcin if (gifinput) { 39875c73fc3SLisandro Dalcin char gifmovie[PETSC_MAX_PATH_LEN]; 3995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(gifmovie,sizeof(gifmovie),"%s/%s_movie.gif",basename,basename)); 4005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDrawMovieSaveGIF(input,count,gifmovie)); 4015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(input,gifmovie)); 4028067a7d5SLisandro Dalcin } 40375c73fc3SLisandro Dalcin #endif 40475c73fc3SLisandro Dalcin 40575c73fc3SLisandro Dalcin /* use FFmpeg to generate a movie */ 40675c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_POPEN) 40775c73fc3SLisandro Dalcin { 408016831caSBarry Smith FILE *fd; 40975c73fc3SLisandro Dalcin char options[64] = "-loglevel error -y", extraopts[32] = "", framerate[24] = ""; 41075c73fc3SLisandro Dalcin char command[sizeof(options)+sizeof(extraopts)+sizeof(framerate)+PETSC_MAX_PATH_LEN*2]; 4115f80ce2aSJacob Faibussowitsch if (fps > 0) CHKERRQ(PetscSNPrintf(framerate,sizeof(framerate),"-r %d",(int)fps)); 41275c73fc3SLisandro Dalcin if (gifinput) { 4135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(options," -f gif",sizeof(options))); 4145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(extraopts,sizeof(extraopts)," -default_delay %d",(fps > 0) ? 100/(int)fps : 4)); 41575c73fc3SLisandro Dalcin } else { 4165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrlcat(options," -f image2",sizeof(options))); 4175f80ce2aSJacob Faibussowitsch if (fps > 0) CHKERRQ(PetscSNPrintf(extraopts,sizeof(extraopts)," -framerate %d",(int)fps)); 41875c73fc3SLisandro Dalcin } 4195f80ce2aSJacob Faibussowitsch if (extraopts[0]) CHKERRQ(PetscStrlcat(options,extraopts,sizeof(options))); 4205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(command,sizeof(command),"ffmpeg %s -i \"%s\" %s \"%s\"",options,input,framerate,output)); 4215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd)); 4225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPClose(PETSC_COMM_SELF,fd)); 4238067a7d5SLisandro Dalcin } 4248067a7d5SLisandro Dalcin #endif 4258067a7d5SLisandro Dalcin PetscFunctionReturn(0); 4268067a7d5SLisandro Dalcin } 427