Actual source code: dsave.c
1: #include <petsc/private/drawimpl.h>
3: PETSC_EXTERN PetscErrorCode PetscDrawImageSave(const char[], const char[], unsigned char[][3], unsigned int, unsigned int, const unsigned char[]);
4: PETSC_EXTERN PetscErrorCode PetscDrawMovieSave(const char[], PetscInt, const char[], PetscInt, const char[]);
5: PETSC_EXTERN PetscErrorCode PetscDrawImageCheckFormat(const char *[]);
6: PETSC_EXTERN PetscErrorCode PetscDrawMovieCheckFormat(const char *[]);
8: #if defined(PETSC_HAVE_SAWS)
9: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw);
10: #endif
12: /*@C
13: PetscDrawSetSave - Saves images produced in a `PetscDraw` into a file
15: Collective
17: Input Parameters:
18: + draw - the graphics context
19: - filename - name of the file, if .ext then uses name of draw object plus .ext using .ext to determine the image type
21: Options Database Keys:
22: + -draw_save <filename> - filename could be name.ext or .ext (where .ext determines the type of graphics file to save, for example .png)
23: . -draw_save_final_image [optional filename] - saves the final image displayed in a window
24: - -draw_save_single_file - saves each new image in the same file, normally each new image is saved in a new file with filename/filename_%d.ext
26: Level: intermediate
28: Note:
29: You should call this BEFORE creating your image and calling `PetscDrawSave()`.
30: The supported image types are .png, .gif, .jpg, and .ppm (PETSc chooses the default in that order).
31: Support for .png images requires configure --with-libpng.
32: Support for .gif images requires configure --with-giflib.
33: Support for .jpg images requires configure --with-libjpeg.
34: Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
36: .seealso: `PetscDraw`, `PetscDrawOpenX()`, `PetscDrawOpenImage()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`, `PetscDrawSetSaveFinalImage()`
37: @*/
38: PetscErrorCode PetscDrawSetSave(PetscDraw draw, const char filename[])
39: {
40: const char *savename = NULL;
41: const char *imageext = NULL;
42: char buf[PETSC_MAX_PATH_LEN];
47: /* determine save filename and image extension */
48: if (filename && filename[0]) {
49: PetscStrchr(filename, '.', (char **)&imageext);
50: if (!imageext) savename = filename;
51: else if (imageext != filename) {
52: size_t l1 = 0, l2 = 0;
53: PetscStrlen(filename, &l1);
54: PetscStrlen(imageext, &l2);
55: PetscStrncpy(buf, filename, l1 - l2 + 1);
56: savename = buf;
57: }
58: }
60: if (!savename) PetscObjectGetName((PetscObject)draw, &savename);
61: PetscDrawImageCheckFormat(&imageext);
63: draw->savefilecount = 0;
64: PetscFree(draw->savefilename);
65: PetscFree(draw->saveimageext);
66: PetscStrallocpy(savename, &draw->savefilename);
67: PetscStrallocpy(imageext, &draw->saveimageext);
69: if (draw->savesinglefile) {
70: PetscInfo(NULL, "Will save image to file %s%s\n", draw->savefilename, draw->saveimageext);
71: } else {
72: PetscInfo(NULL, "Will save images to file %s/%s_%%d%s\n", draw->savefilename, draw->savefilename, draw->saveimageext);
73: }
74: return 0;
75: }
77: /*@C
78: PetscDrawSetSaveMovie - Saves a movie produced from a `PetscDraw` into a file
80: Collective
82: Input Parameters:
83: + draw - the graphics context
84: - movieext - optional extension defining the movie format
86: Options Database Key:
87: . -draw_save_movie <.ext> - saves a movie with extension .ext
89: Level: intermediate
91: Note:
92: You should call this AFTER calling `PetscDrawSetSave()` and BEFORE creating your image with `PetscDrawSave()`.
93: The ffmpeg utility must be in your path to make the movie.
95: .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
96: @*/
97: PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw, const char movieext[])
98: {
102: if (!draw->savefilename) PetscDrawSetSave(draw, "");
103: PetscDrawMovieCheckFormat(&movieext);
104: PetscStrallocpy(movieext, &draw->savemovieext);
105: draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
107: PetscInfo(NULL, "Will save movie to file %s%s\n", draw->savefilename, draw->savemovieext);
108: return 0;
109: }
111: /*@C
112: PetscDrawSetSaveFinalImage - Saves the final image produced in a `PetscDraw` into a file
114: Collective
116: Input Parameters:
117: + draw - the graphics context
118: - filename - name of the file, if NULL or empty uses name set with `PetscDrawSetSave()` or the name of the draw object
120: Options Database Key:
121: . -draw_save_final_image <filename> - filename could be name.ext or .ext (where .ext determines the type of graphics file to save, for example .png)
123: Level: intermediate
125: Notes:
126: You should call this BEFORE creating your image and calling `PetscDrawSave()`.
128: The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
129: .vb
130: Support for .png images requires configure --with-libpng.
131: Support for .gif images requires configure --with-giflib.
132: Support for .jpg images requires configure --with-libjpeg.
133: Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
134: .ve
136: .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetFromOptions()`, `PetscDrawCreate()`, `PetscDrawDestroy()`
137: @*/
138: PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw, const char filename[])
139: {
140: char buf[PETSC_MAX_PATH_LEN];
143: if (!filename || !filename[0]) {
144: if (!draw->savefilename) {
145: PetscObjectGetName((PetscObject)draw, &filename);
146: } else {
147: PetscSNPrintf(buf, sizeof(buf), "%s%s", draw->savefilename, draw->saveimageext);
148: filename = buf;
149: }
150: }
151: PetscFree(draw->savefinalfilename);
152: PetscStrallocpy(filename, &draw->savefinalfilename);
153: return 0;
154: }
156: /*@
157: PetscDrawSave - Saves a drawn image
159: Collective
161: Input Parameters:
162: . draw - the drawing context
164: Level: advanced
166: Note:
167: this is not normally called by the user.
169: .seealso: `PetscDraw`, `PetscDrawSetSave()`
170: @*/
171: PetscErrorCode PetscDrawSave(PetscDraw draw)
172: {
173: PetscInt saveindex;
174: char basename[PETSC_MAX_PATH_LEN];
175: unsigned char palette[256][3];
176: unsigned int w, h;
177: unsigned char *pixels = NULL;
178: PetscMPIInt rank;
181: if (!draw->ops->save && !draw->ops->getimage) return 0;
182: if (draw->ops->save) {
183: PetscUseTypeMethod(draw, save);
184: goto finally;
185: }
186: if (!draw->savefilename || !draw->saveimageext) return 0;
187: MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank);
189: saveindex = draw->savefilecount++;
191: if (rank == 0 && !saveindex) {
192: char path[PETSC_MAX_PATH_LEN];
193: if (draw->savesinglefile) {
194: PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->saveimageext);
195: (void)remove(path);
196: } else {
197: PetscSNPrintf(path, sizeof(path), "%s", draw->savefilename);
198: PetscRMTree(path);
199: PetscMkdir(path);
200: }
201: if (draw->savemovieext) {
202: PetscSNPrintf(path, sizeof(path), "%s%s", draw->savefilename, draw->savemovieext);
203: (void)remove(path);
204: }
205: }
206: if (draw->savesinglefile) {
207: PetscSNPrintf(basename, sizeof(basename), "%s", draw->savefilename);
208: } else {
209: char *basefilename;
211: PetscStrrchr(draw->savefilename, '/', (char **)&basefilename);
212: if (basefilename != draw->savefilename) {
213: PetscSNPrintf(basename, sizeof(basename), "%s_%d", draw->savefilename, (int)saveindex);
214: } else {
215: PetscSNPrintf(basename, sizeof(basename), "%s/%s_%d", draw->savefilename, draw->savefilename, (int)saveindex);
216: }
217: }
219: /* this call is collective, only the first process gets the image data */
220: PetscUseTypeMethod(draw, getimage, palette, &w, &h, &pixels);
221: /* only the first process handles the saving business */
222: if (rank == 0) PetscDrawImageSave(basename, draw->saveimageext, palette, w, h, pixels);
223: PetscFree(pixels);
224: MPI_Barrier(PetscObjectComm((PetscObject)draw));
226: finally:
227: #if defined(PETSC_HAVE_SAWS)
228: PetscDrawSave_SAWs(draw);
229: #endif
230: return 0;
231: }
233: /*@
234: PetscDrawSaveMovie - Saves a movie from previously saved images
236: Collective
238: Input Parameters:
239: . draw - the drawing context
241: Level: advanced
243: Notes:
244: This is not normally called by the user.
246: The ffmpeg utility must be in your path to make the movie.
248: .seealso: `PetscDraw`, `PetscDrawSetSave()`, `PetscDrawSetSaveMovie()`
249: @*/
250: PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
251: {
252: PetscMPIInt rank;
255: if (!draw->ops->save && !draw->ops->getimage) return 0;
256: if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) return 0;
257: MPI_Comm_rank(PetscObjectComm((PetscObject)draw), &rank);
258: {
259: const char *fname = draw->savefilename;
260: const char *imext = draw->saveimageext;
261: const char *mvext = draw->savemovieext;
262: if (rank == 0) PetscDrawMovieSave(fname, draw->savefilecount, imext, draw->savemoviefps, mvext);
263: MPI_Barrier(PetscObjectComm((PetscObject)draw));
264: }
265: return 0;
266: }
268: #if defined(PETSC_HAVE_SAWS)
269: #include <petscviewersaws.h>
270: /*
271: The PetscImageList object and functions are used to maintain a list of file images
272: that can be displayed by the SAWs webserver.
273: */
274: typedef struct _P_PetscImageList *PetscImageList;
275: struct _P_PetscImageList {
276: PetscImageList next;
277: char *filename;
278: char *ext;
279: PetscInt count;
280: };
282: static PetscImageList SAWs_images = NULL;
284: static PetscErrorCode PetscImageListDestroy(void)
285: {
286: PetscImageList image = SAWs_images;
288: while (image) {
289: PetscImageList next = image->next;
290: PetscFree(image->filename);
291: PetscFree(image->ext);
292: PetscFree(image);
293: image = next;
294: }
295: return 0;
296: }
298: static PetscErrorCode PetscImageListAdd(const char filename[], const char ext[], PetscInt count)
299: {
300: PetscImageList image, oimage = SAWs_images;
301: PetscBool flg;
303: if (oimage) {
304: PetscStrcmp(filename, oimage->filename, &flg);
305: if (flg) {
306: oimage->count = count;
307: return 0;
308: }
309: while (oimage->next) {
310: oimage = oimage->next;
311: PetscStrcmp(filename, oimage->filename, &flg);
312: if (flg) {
313: oimage->count = count;
314: return 0;
315: }
316: }
317: PetscNew(&image);
318: oimage->next = image;
319: } else {
320: PetscRegisterFinalize(PetscImageListDestroy);
321: PetscNew(&image);
322: SAWs_images = image;
323: }
324: PetscStrallocpy(filename, &image->filename);
325: PetscStrallocpy(ext, &image->ext);
326: image->count = count;
327: return 0;
328: }
330: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
331: {
332: PetscImageList image;
333: char body[4096];
334: size_t len = 0;
336: if (!draw->savefilename || !draw->saveimageext) return 0;
337: PetscImageListAdd(draw->savefilename, draw->saveimageext, draw->savefilecount - 1);
338: image = SAWs_images;
339: while (image) {
340: const char *name = image->filename;
341: const char *ext = image->ext;
342: if (draw->savesinglefile) {
343: PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s%s\" alt=\"None\">", name, ext);
344: } else {
345: PetscSNPrintf(body + len, 4086 - len, "<img src=\"%s/%s_%d%s\" alt=\"None\">", name, name, image->count, ext);
346: }
347: PetscStrlen(body, &len);
348: image = image->next;
349: }
350: PetscStrlcat(body, "<br>\n", sizeof(body));
351: if (draw->savefilecount > 0) SAWs_Pop_Body, ("index.html", 1);
352: SAWs_Push_Body, ("index.html", 1, body);
353: return 0;
354: }
356: #endif