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 */ 11d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDrawImageSavePPM(const char filename[], unsigned char palette[][3], unsigned int w, unsigned int h, const unsigned char pixels[]) 12d71ae5a4SJacob Faibussowitsch { 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); 20cff5ee94SJacob Faibussowitsch if (palette) PetscValidPointer(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)); 453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 468067a7d5SLisandro Dalcin } 478067a7d5SLisandro Dalcin 48d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawImageSave_PPM(const char filename[], unsigned char palette[][3], unsigned int w, unsigned int h, const unsigned char pixels[]) 49d71ae5a4SJacob Faibussowitsch { 509371c9d4SSatish Balay return PetscDrawImageSavePPM(filename, palette, w, h, pixels); 519371c9d4SSatish Balay } 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 66d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDrawImageSavePNG(const char filename[], unsigned char palette[][3], unsigned int w, unsigned int h, const unsigned char pixels[]) 67d71ae5a4SJacob Faibussowitsch { 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 738067a7d5SLisandro Dalcin PetscFunctionBegin; 748067a7d5SLisandro Dalcin PetscValidCharPointer(filename, 1); 758067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette, 2); 768067a7d5SLisandro Dalcin PetscValidCharPointer(pixels, 5); 778067a7d5SLisandro Dalcin 788067a7d5SLisandro Dalcin /* open file and create libpng structures */ 799566063dSJacob Faibussowitsch PetscCall(PetscFOpen(PETSC_COMM_SELF, filename, "wb", &fp)); 808067a7d5SLisandro Dalcin png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); 8128b400f6SJacob Faibussowitsch PetscCheck(png_ptr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot create PNG context"); 828067a7d5SLisandro Dalcin info_ptr = png_create_info_struct(png_ptr); 8328b400f6SJacob Faibussowitsch PetscCheck(info_ptr, PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot create PNG context"); 848067a7d5SLisandro Dalcin 858067a7d5SLisandro Dalcin /* setup libpng error handling */ 868067a7d5SLisandro Dalcin #if defined(PNG_SETJMP_SUPPORTED) 878067a7d5SLisandro Dalcin if (setjmp(png_jmpbuf(png_ptr))) { 888067a7d5SLisandro Dalcin png_destroy_write_struct(&png_ptr, &info_ptr); 898067a7d5SLisandro Dalcin (void)PetscFClose(PETSC_COMM_SELF, fp); 9098921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error writing PNG file %s", filename); 918067a7d5SLisandro Dalcin } 928067a7d5SLisandro Dalcin #endif 938067a7d5SLisandro Dalcin 948067a7d5SLisandro Dalcin /* setup PNG image metadata */ 958067a7d5SLisandro Dalcin png_init_io(png_ptr, fp); 969371c9d4SSatish Balay png_set_IHDR(png_ptr, info_ptr, w, h, /*depth*/ 8, palette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 979371c9d4SSatish Balay if (palette) png_set_PLTE(png_ptr, info_ptr, (png_color *)palette, 256); 988067a7d5SLisandro Dalcin 998067a7d5SLisandro Dalcin /* write PNG image header and data */ 1008067a7d5SLisandro Dalcin png_write_info(png_ptr, info_ptr); 1019371c9d4SSatish Balay for (row = 0; row < h; row++) png_write_row(png_ptr, pixels + row * stride); 1028067a7d5SLisandro Dalcin png_write_end(png_ptr, NULL); 1038067a7d5SLisandro Dalcin 1048067a7d5SLisandro Dalcin /* destroy libpng structures and close file */ 1058067a7d5SLisandro Dalcin png_destroy_write_struct(&png_ptr, &info_ptr); 1069566063dSJacob Faibussowitsch PetscCall(PetscFClose(PETSC_COMM_SELF, fp)); 1073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1088067a7d5SLisandro Dalcin } 1098067a7d5SLisandro Dalcin 110d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawImageSave_PNG(const char filename[], unsigned char palette[][3], unsigned int w, unsigned int h, const unsigned char pixels[]) 111d71ae5a4SJacob Faibussowitsch { 1129371c9d4SSatish Balay return PetscDrawImageSavePNG(filename, palette, w, h, pixels); 1139371c9d4SSatish Balay } 1148067a7d5SLisandro Dalcin 1158067a7d5SLisandro Dalcin #endif /*!PETSC_HAVE_LIBPNG*/ 1168067a7d5SLisandro Dalcin 1178067a7d5SLisandro Dalcin /* 1188067a7d5SLisandro Dalcin Code to write images in GIF format 1198067a7d5SLisandro Dalcin */ 1208067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 1218067a7d5SLisandro Dalcin 1228067a7d5SLisandro Dalcin #include <gif_lib.h> 1238067a7d5SLisandro Dalcin 1248067a7d5SLisandro Dalcin #if !defined(GIFLIB_MAJOR) || GIFLIB_MAJOR < 5 1258067a7d5SLisandro Dalcin #define GifMakeMapObject MakeMapObject 1268067a7d5SLisandro Dalcin #define GifFreeMapObject FreeMapObject 1278067a7d5SLisandro Dalcin #define EGifOpenFileName(n, b, err) EGifOpenFileName(n, b) 1288067a7d5SLisandro Dalcin #define EGifOpenFileHandle(h, err) EGifOpenFileName(h) 1298067a7d5SLisandro Dalcin #define EGifCloseFile(f, err) EGifCloseFile(f) 13075c73fc3SLisandro Dalcin #define DGifOpenFileName(n, err) DGifOpenFileName(n) 13175c73fc3SLisandro Dalcin #define DGifOpenFileHandle(h, err) DGifOpenFileName(h) 13275c73fc3SLisandro Dalcin #define DGifCloseFile(f, err) DGifCloseFile(f) 1338067a7d5SLisandro Dalcin #endif 1348067a7d5SLisandro Dalcin 135d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDrawImageSaveGIF(const char filename[], unsigned char palette[][3], unsigned int w, unsigned int h, const unsigned char pixels[]) 136d71ae5a4SJacob Faibussowitsch { 1379566063dSJacob Faibussowitsch int Row; 1388067a7d5SLisandro Dalcin int Width = (int)w; 1398067a7d5SLisandro Dalcin int Height = (int)h; 1408067a7d5SLisandro Dalcin int ColorRes = 8; 1418067a7d5SLisandro Dalcin int ColorCount = 256; 1428067a7d5SLisandro Dalcin ColorMapObject *GifCMap = NULL; 1438067a7d5SLisandro Dalcin GifFileType *GifFile = NULL; 14498921bdaSJacob Faibussowitsch #define SETERRGIF(msg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, msg ", GIF file: %s", filename) 1459371c9d4SSatish Balay #define PetscCallGIF(msg, ...) \ 1469371c9d4SSatish Balay do { \ 1479566063dSJacob Faibussowitsch int Error = __VA_ARGS__; \ 1489566063dSJacob Faibussowitsch if (PetscUnlikely(Error != GIF_OK)) SETERRGIF(msg); \ 1499566063dSJacob Faibussowitsch } while (0) 1508067a7d5SLisandro Dalcin 1518067a7d5SLisandro Dalcin PetscFunctionBegin; 1528067a7d5SLisandro Dalcin PetscValidCharPointer(filename, 1); 1538067a7d5SLisandro Dalcin PetscValidCharPointer(palette, 2); 1548067a7d5SLisandro Dalcin PetscValidCharPointer(pixels, 5); 1558067a7d5SLisandro Dalcin 1569371c9d4SSatish Balay GifCMap = GifMakeMapObject(ColorCount, (GifColorType *)palette); 1579371c9d4SSatish Balay if (!GifCMap) SETERRGIF("Allocating colormap"); 1589371c9d4SSatish Balay GifFile = EGifOpenFileName(filename, 0, NULL); 1599371c9d4SSatish Balay if (!GifFile) SETERRGIF("Opening"); 1609566063dSJacob Faibussowitsch PetscCallGIF("Writing screen descriptor", EGifPutScreenDesc(GifFile, Width, Height, ColorRes, 0, GifCMap)); 1619566063dSJacob Faibussowitsch PetscCallGIF("Writing image descriptor", EGifPutImageDesc(GifFile, 0, 0, Width, Height, 0, NULL)); 16248a46eb9SPierre Jolivet for (Row = 0; Row < Height; Row++) PetscCallGIF("Writing image pixels", EGifPutLine(GifFile, (GifPixelType *)pixels + Row * Width, Width)); 1639566063dSJacob Faibussowitsch PetscCallGIF("Closing", EGifCloseFile(GifFile, NULL)); 1649371c9d4SSatish Balay GifFreeMapObject(GifCMap); 1659371c9d4SSatish Balay GifCMap = NULL; 1668067a7d5SLisandro Dalcin 1678067a7d5SLisandro Dalcin #undef SETERRGIF 1688067a7d5SLisandro Dalcin #undef CHKERRGIF 1693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1708067a7d5SLisandro Dalcin } 1718067a7d5SLisandro Dalcin 172d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawImageSave_GIF(const char filename[], unsigned char palette[][3], unsigned int w, unsigned int h, const unsigned char pixels[]) 173d71ae5a4SJacob Faibussowitsch { 1749371c9d4SSatish Balay return PetscDrawImageSaveGIF(filename, palette, w, h, pixels); 1759371c9d4SSatish Balay } 1768067a7d5SLisandro Dalcin 177d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDrawMovieSaveGIF(const char pattern[], PetscInt count, const char movie[]) 178d71ae5a4SJacob Faibussowitsch { 17975c73fc3SLisandro Dalcin int i, j, Row; 18075c73fc3SLisandro Dalcin char image[PETSC_MAX_PATH_LEN]; 18175c73fc3SLisandro Dalcin GifFileType *GifMovie = NULL; 18275c73fc3SLisandro Dalcin GifFileType *GifImage = NULL; 18398921bdaSJacob Faibussowitsch #define SETERRGIF(msg, fn) SETERRQ(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); 1883ba16761SJacob Faibussowitsch if (count < 1) PetscFunctionReturn(PETSC_SUCCESS); 18975c73fc3SLisandro Dalcin 19075c73fc3SLisandro Dalcin for (i = 0; i < count; i++) { 1919566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(image, sizeof(image), pattern, (int)i)); 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); 1989371c9d4SSatish Balay if (EGifPutScreenDesc(GifMovie, GifImage->SWidth, GifImage->SHeight, GifImage->SColorResolution, GifImage->SBackGroundColor, 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; 2059371c9d4SSatish Balay if (GifMovie->SColorMap && GifMovie->SColorMap->ColorCount == FrameColorMap->ColorCount && !memcmp(GifMovie->SColorMap->Colors, FrameColorMap->Colors, (size_t)FrameColorMap->ColorCount * sizeof(GifColorType))) FrameColorMap = NULL; 20675c73fc3SLisandro Dalcin /* add frame to movie */ 2079371c9d4SSatish Balay if (EGifPutImageDesc(GifMovie, GifFrame->Left, GifFrame->Top, GifFrame->Width, GifFrame->Height, GifFrame->Interlace, FrameColorMap) != GIF_OK) SETERRGIF("Writing image descriptor,", movie); 20875c73fc3SLisandro Dalcin for (Row = 0; Row < GifFrame->Height; Row++) { 2099371c9d4SSatish Balay if (EGifPutLine(GifMovie, sp->RasterBits + Row * GifFrame->Width, GifFrame->Width) != GIF_OK) SETERRGIF("Writing image pixels,", movie); 21075c73fc3SLisandro Dalcin } 21175c73fc3SLisandro Dalcin } 21275c73fc3SLisandro Dalcin if (DGifCloseFile(GifImage, NULL) != GIF_OK) SETERRGIF("Closing input", image); 21375c73fc3SLisandro Dalcin } 21475c73fc3SLisandro Dalcin if (EGifCloseFile(GifMovie, NULL) != GIF_OK) SETERRGIF("Closing output", movie); 21575c73fc3SLisandro Dalcin 21675c73fc3SLisandro Dalcin #undef SETERRGIF 2173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21875c73fc3SLisandro Dalcin } 21975c73fc3SLisandro Dalcin 2208067a7d5SLisandro Dalcin #endif /*!PETSC_HAVE_GIFLIB*/ 2218067a7d5SLisandro Dalcin 2228067a7d5SLisandro Dalcin /* 2238067a7d5SLisandro Dalcin Code to write images in JPEG format 2248067a7d5SLisandro Dalcin */ 2258067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 2268067a7d5SLisandro Dalcin 2278067a7d5SLisandro Dalcin #include <jpeglib.h> 2288067a7d5SLisandro Dalcin 2298067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2308067a7d5SLisandro Dalcin #include <setjmp.h> 2318067a7d5SLisandro Dalcin static jmp_buf petsc_jpeg_jumpbuf; 232d71ae5a4SJacob Faibussowitsch static void petsc_jpeg_error_longjmp(j_common_ptr cinfo) 233d71ae5a4SJacob Faibussowitsch { 2349371c9d4SSatish Balay (void)cinfo; 2359371c9d4SSatish Balay longjmp(petsc_jpeg_jumpbuf, 1); 2369371c9d4SSatish Balay } 2378067a7d5SLisandro Dalcin #endif 2388067a7d5SLisandro Dalcin 239d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDrawImageSaveJPG(const char filename[], unsigned char palette[][3], unsigned int w, unsigned int h, const unsigned char pixels[]) 240d71ae5a4SJacob Faibussowitsch { 2418067a7d5SLisandro Dalcin unsigned char *rgbpixels; 2428067a7d5SLisandro Dalcin FILE *fp; 2438067a7d5SLisandro Dalcin struct jpeg_compress_struct cinfo; 2448067a7d5SLisandro Dalcin struct jpeg_error_mgr jerr; 2458067a7d5SLisandro Dalcin 2468067a7d5SLisandro Dalcin PetscFunctionBegin; 2478067a7d5SLisandro Dalcin PetscValidCharPointer(filename, 1); 2488067a7d5SLisandro Dalcin if (palette) PetscValidCharPointer(palette, 2); 2498067a7d5SLisandro Dalcin PetscValidCharPointer(pixels, 5); 2508067a7d5SLisandro Dalcin /* map pixels to RGB colors */ 2518067a7d5SLisandro Dalcin if (palette) { 2528067a7d5SLisandro Dalcin int k, p, n = (int)(w * h); 2538067a7d5SLisandro Dalcin const unsigned char *colordef; 2549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * w * h, &rgbpixels)); 2558067a7d5SLisandro Dalcin for (k = p = 0; k < n; k++) { 2568067a7d5SLisandro Dalcin colordef = palette[pixels[k]]; 2578067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[0]; 2588067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[1]; 2598067a7d5SLisandro Dalcin rgbpixels[p++] = colordef[2]; 2608067a7d5SLisandro Dalcin } 2618067a7d5SLisandro Dalcin } else { /* assume pixels are RGB colors */ 2628067a7d5SLisandro Dalcin rgbpixels = (unsigned char *)pixels; 2638067a7d5SLisandro Dalcin } 2649566063dSJacob Faibussowitsch PetscCall(PetscFOpen(PETSC_COMM_SELF, filename, "wb", &fp)); 2658067a7d5SLisandro Dalcin 2668067a7d5SLisandro Dalcin cinfo.err = jpeg_std_error(&jerr); 2678067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 2688067a7d5SLisandro Dalcin jerr.error_exit = petsc_jpeg_error_longjmp; 2698067a7d5SLisandro Dalcin if (setjmp(petsc_jpeg_jumpbuf)) { 2708067a7d5SLisandro Dalcin char message[JMSG_LENGTH_MAX]; 2718067a7d5SLisandro Dalcin jerr.format_message((j_common_ptr)&cinfo, message); 2728067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 2738067a7d5SLisandro Dalcin (void)PetscFClose(PETSC_COMM_SELF, fp); 27498921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error writing JPEG file %s\n%s", filename, message); 2758067a7d5SLisandro Dalcin } 2768067a7d5SLisandro Dalcin #endif 2778067a7d5SLisandro Dalcin jpeg_create_compress(&cinfo); 2788067a7d5SLisandro Dalcin jpeg_stdio_dest(&cinfo, fp); 2798067a7d5SLisandro Dalcin cinfo.image_width = w; 2808067a7d5SLisandro Dalcin cinfo.image_height = h; 2818067a7d5SLisandro Dalcin cinfo.input_components = 3; 2828067a7d5SLisandro Dalcin cinfo.in_color_space = JCS_RGB; 2838067a7d5SLisandro Dalcin jpeg_set_defaults(&cinfo); 2848067a7d5SLisandro Dalcin jpeg_start_compress(&cinfo, TRUE); 2858067a7d5SLisandro Dalcin while (cinfo.next_scanline < cinfo.image_height) { 2868067a7d5SLisandro Dalcin unsigned char *rowptr = rgbpixels + cinfo.next_scanline * 3 * w; 2878067a7d5SLisandro Dalcin (void)jpeg_write_scanlines(&cinfo, &rowptr, 1); 2888067a7d5SLisandro Dalcin } 2898067a7d5SLisandro Dalcin jpeg_finish_compress(&cinfo); 2908067a7d5SLisandro Dalcin jpeg_destroy_compress(&cinfo); 2918067a7d5SLisandro Dalcin 2929566063dSJacob Faibussowitsch PetscCall(PetscFClose(PETSC_COMM_SELF, fp)); 2939566063dSJacob Faibussowitsch if (palette) PetscCall(PetscFree(rgbpixels)); 2943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2958067a7d5SLisandro Dalcin } 2968067a7d5SLisandro Dalcin 297d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawImageSave_JPG(const char filename[], unsigned char palette[][3], unsigned int w, unsigned int h, const unsigned char pixels[]) 298d71ae5a4SJacob Faibussowitsch { 2999371c9d4SSatish Balay return PetscDrawImageSaveJPG(filename, palette, w, h, pixels); 3009371c9d4SSatish Balay } 3018067a7d5SLisandro Dalcin 3028067a7d5SLisandro Dalcin #endif /*!PETSC_HAVE_LIBJPEG*/ 3038067a7d5SLisandro Dalcin 3048067a7d5SLisandro Dalcin static struct { 3058067a7d5SLisandro Dalcin const char *extension; 3068067a7d5SLisandro Dalcin PetscErrorCode (*SaveImage)(const char[], unsigned char[][3], unsigned int, unsigned int, const unsigned char[]); 3078067a7d5SLisandro Dalcin } PetscDrawImageSaveTable[] = { 3088067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBPNG) 3098067a7d5SLisandro Dalcin {".png", PetscDrawImageSave_PNG}, 3108067a7d5SLisandro Dalcin #endif 3118067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 3128067a7d5SLisandro Dalcin {".gif", PetscDrawImageSave_GIF}, 3138067a7d5SLisandro Dalcin #endif 3148067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_LIBJPEG) 3158067a7d5SLisandro Dalcin {".jpg", PetscDrawImageSave_JPG}, 3168067a7d5SLisandro Dalcin #endif 3178067a7d5SLisandro Dalcin {".ppm", PetscDrawImageSave_PPM} 3188067a7d5SLisandro Dalcin }; 3198067a7d5SLisandro Dalcin 320d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawImageCheckFormat(const char *ext[]) 321d71ae5a4SJacob Faibussowitsch { 3228067a7d5SLisandro Dalcin size_t k; 3238067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3248067a7d5SLisandro Dalcin 3258067a7d5SLisandro Dalcin PetscFunctionBegin; 3268067a7d5SLisandro Dalcin /* if extension is empty, return default format to caller */ 3278067a7d5SLisandro Dalcin PetscValidPointer(ext, 1); 3288067a7d5SLisandro Dalcin if (!*ext || !**ext) { 3298067a7d5SLisandro Dalcin *ext = PetscDrawImageSaveTable[0].extension; 3303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3318067a7d5SLisandro Dalcin } 332a9db196aSBarry Smith /* check the extension matches a supported format */ 3338067a7d5SLisandro Dalcin PetscValidCharPointer(*ext, 1); 334dd39110bSPierre Jolivet for (k = 0; k < PETSC_STATIC_ARRAY_LENGTH(PetscDrawImageSaveTable); k++) { 3359566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(*ext, PetscDrawImageSaveTable[k].extension, &match)); 3363ba16761SJacob Faibussowitsch if (match && PetscDrawImageSaveTable[k].SaveImage) PetscFunctionReturn(PETSC_SUCCESS); 3378067a7d5SLisandro Dalcin } 33898921bdaSJacob 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); 3398067a7d5SLisandro Dalcin } 3408067a7d5SLisandro Dalcin 341d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawImageSave(const char basename[], const char ext[], unsigned char palette[][3], unsigned int w, unsigned int h, const unsigned char pixels[]) 342d71ae5a4SJacob Faibussowitsch { 3438067a7d5SLisandro Dalcin size_t k; 3448067a7d5SLisandro Dalcin PetscBool match = PETSC_FALSE; 3458067a7d5SLisandro Dalcin char filename[PETSC_MAX_PATH_LEN]; 3468067a7d5SLisandro Dalcin 3478067a7d5SLisandro Dalcin PetscFunctionBegin; 3488067a7d5SLisandro Dalcin PetscValidCharPointer(basename, 1); 3498067a7d5SLisandro Dalcin if (ext) PetscValidCharPointer(ext, 2); 350dadcf809SJacob Faibussowitsch if (palette) PetscValidPointer(palette, 3); 3518067a7d5SLisandro Dalcin PetscValidCharPointer(pixels, 6); 3528067a7d5SLisandro Dalcin 3539566063dSJacob Faibussowitsch PetscCall(PetscDrawImageCheckFormat(&ext)); 3549566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, sizeof(filename), "%s%s", basename, ext)); 355dd39110bSPierre Jolivet for (k = 0; k < PETSC_STATIC_ARRAY_LENGTH(PetscDrawImageSaveTable); k++) { 3569566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(ext, PetscDrawImageSaveTable[k].extension, &match)); 3578067a7d5SLisandro Dalcin if (match && PetscDrawImageSaveTable[k].SaveImage) { 3589566063dSJacob Faibussowitsch PetscCall(PetscDrawImageSaveTable[k].SaveImage(filename, palette, w, h, pixels)); 3593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3608067a7d5SLisandro Dalcin } 3618067a7d5SLisandro Dalcin } 36298921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Image extension %s not supported, use .ppm", ext); 3638067a7d5SLisandro Dalcin } 3648067a7d5SLisandro Dalcin 365d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawMovieCheckFormat(const char *ext[]) 366d71ae5a4SJacob Faibussowitsch { 3678067a7d5SLisandro Dalcin PetscFunctionBegin; 3688067a7d5SLisandro Dalcin PetscValidPointer(ext, 1); 3698067a7d5SLisandro Dalcin if (!*ext || !**ext) *ext = ".m4v"; 3703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3718067a7d5SLisandro Dalcin } 3728067a7d5SLisandro Dalcin 373d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawMovieSave(const char basename[], PetscInt count, const char imext[], PetscInt fps, const char mvext[]) 374d71ae5a4SJacob Faibussowitsch { 37575c73fc3SLisandro Dalcin char input[PETSC_MAX_PATH_LEN]; 37675c73fc3SLisandro Dalcin char output[PETSC_MAX_PATH_LEN]; 37775c73fc3SLisandro Dalcin PetscBool gifinput; 3788067a7d5SLisandro Dalcin 3798067a7d5SLisandro Dalcin PetscFunctionBegin; 3808067a7d5SLisandro Dalcin PetscValidCharPointer(basename, 1); 3818067a7d5SLisandro Dalcin PetscValidCharPointer(imext, 3); 382064a246eSJacob Faibussowitsch if (mvext) PetscValidCharPointer(mvext, 5); 3833ba16761SJacob Faibussowitsch if (count < 1) PetscFunctionReturn(PETSC_SUCCESS); 3848067a7d5SLisandro Dalcin 3859566063dSJacob Faibussowitsch PetscCall(PetscStrcasecmp(imext, ".gif", &gifinput)); 3869566063dSJacob Faibussowitsch PetscCall(PetscDrawMovieCheckFormat(&mvext)); 3879566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(input, sizeof(input), "%s/%s_%%d%s", basename, basename, imext)); 3889566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(output, sizeof(output), "%s%s", basename, mvext)); 38975c73fc3SLisandro Dalcin 39075c73fc3SLisandro Dalcin /* use GIFLIB to generate an intermediate GIF animation */ 39175c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_GIFLIB) 39275c73fc3SLisandro Dalcin if (gifinput) { 39375c73fc3SLisandro Dalcin char gifmovie[PETSC_MAX_PATH_LEN]; 3949566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(gifmovie, sizeof(gifmovie), "%s/%s_movie.gif", basename, basename)); 3959566063dSJacob Faibussowitsch PetscCall(PetscDrawMovieSaveGIF(input, count, gifmovie)); 396*c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(input, gifmovie, sizeof(input))); 3978067a7d5SLisandro Dalcin } 39875c73fc3SLisandro Dalcin #endif 39975c73fc3SLisandro Dalcin 40075c73fc3SLisandro Dalcin /* use FFmpeg to generate a movie */ 40175c73fc3SLisandro Dalcin #if defined(PETSC_HAVE_POPEN) 40275c73fc3SLisandro Dalcin { 403016831caSBarry Smith FILE *fd; 40475c73fc3SLisandro Dalcin char options[64] = "-loglevel error -y", extraopts[32] = "", framerate[24] = ""; 40575c73fc3SLisandro Dalcin char command[sizeof(options) + sizeof(extraopts) + sizeof(framerate) + PETSC_MAX_PATH_LEN * 2]; 4069566063dSJacob Faibussowitsch if (fps > 0) PetscCall(PetscSNPrintf(framerate, sizeof(framerate), "-r %d", (int)fps)); 40775c73fc3SLisandro Dalcin if (gifinput) { 4089566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(options, " -f gif", sizeof(options))); 4099566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(extraopts, sizeof(extraopts), " -default_delay %d", (fps > 0) ? 100 / (int)fps : 4)); 41075c73fc3SLisandro Dalcin } else { 4119566063dSJacob Faibussowitsch PetscCall(PetscStrlcat(options, " -f image2", sizeof(options))); 4129566063dSJacob Faibussowitsch if (fps > 0) PetscCall(PetscSNPrintf(extraopts, sizeof(extraopts), " -framerate %d", (int)fps)); 41375c73fc3SLisandro Dalcin } 4149566063dSJacob Faibussowitsch if (extraopts[0]) PetscCall(PetscStrlcat(options, extraopts, sizeof(options))); 4159566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(command, sizeof(command), "ffmpeg %s -i \"%s\" %s \"%s\"", options, input, framerate, output)); 4169566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", &fd)); 4179566063dSJacob Faibussowitsch PetscCall(PetscPClose(PETSC_COMM_SELF, fd)); 4188067a7d5SLisandro Dalcin } 4198067a7d5SLisandro Dalcin #endif 4203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4218067a7d5SLisandro Dalcin } 422