Actual source code: dsave.c
petsc-3.11.4 2019-09-28
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 on PetscDraw
17: Input Parameter:
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 Command:
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: Concepts: X windows^graphics
30: Notes:
31: You should call this BEFORE creating your image and calling PetscDrawSave().
32: The supported image types are .png, .gif, .jpg, and .ppm (PETSc chooses the default in that order).
33: Support for .png images requires configure --with-libpng.
34: Support for .gif images requires configure --with-giflib.
35: Support for .jpg images requires configure --with-libjpeg.
36: Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
38: .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSaveFinalImage()
39: @*/
40: PetscErrorCode PetscDrawSetSave(PetscDraw draw,const char filename[])
41: {
42: const char *savename = NULL;
43: const char *imageext = NULL;
44: char buf[PETSC_MAX_PATH_LEN];
51: /* determine save filename and image extension */
52: if (filename && filename[0]) {
53: PetscStrchr(filename,'.',(char **)&imageext);
54: if (!imageext) savename = filename;
55: else if (imageext != filename) {
56: size_t l1 = 0,l2 = 0;
57: PetscStrlen(filename,&l1);
58: PetscStrlen(imageext,&l2);
59: PetscStrncpy(buf,filename,l1-l2+1);
60: savename = buf;
61: }
62: }
64: if (!savename) {PetscObjectGetName((PetscObject)draw,&savename);}
65: PetscDrawImageCheckFormat(&imageext);
67: draw->savefilecount = 0;
68: PetscFree(draw->savefilename);
69: PetscFree(draw->saveimageext);
70: PetscStrallocpy(savename,&draw->savefilename);
71: PetscStrallocpy(imageext,&draw->saveimageext);
73: if (draw->savesinglefile) {
74: PetscInfo2(NULL,"Will save image to file %s%s\n",draw->savefilename,draw->saveimageext);
75: } else {
76: PetscInfo3(NULL,"Will save images to file %s/%s_%%d%s\n",draw->savefilename,draw->savefilename,draw->saveimageext);
77: }
78: return(0);
79: }
81: /*@C
82: PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file
84: Collective on PetscDraw
86: Input Parameter:
87: + draw - the graphics context
88: - movieext - optional extension defining the movie format
90: Options Database Command:
91: . -draw_save_movie <.ext> - saves a movie with extension .ext
93: Level: intermediate
95: Concepts: X windows^graphics
97: Notes:
98: You should call this AFTER calling PetscDrawSetSave() and BEFORE creating your image with PetscDrawSave().
99: The ffmpeg utility must be in your path to make the movie.
101: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
102: @*/
103: PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])
104: {
112: if (!draw->savefilename) {PetscDrawSetSave(draw,"");}
113: PetscDrawMovieCheckFormat(&movieext);
114: PetscStrallocpy(movieext,&draw->savemovieext);
115: draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
117: PetscInfo2(NULL,"Will save movie to file %s%s\n",draw->savefilename,draw->savemovieext);
118: return(0);
119: }
121: /*@C
122: PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file
124: Collective on PetscDraw
126: Input Parameter:
127: + draw - the graphics context
128: - filename - name of the file, if NULL or empty uses name set with PetscDrawSetSave() or name of draw object
130: Options Database Command:
131: . -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)
133: Level: intermediate
135: Concepts: X windows^graphics
137: Notes:
138: You should call this BEFORE creating your image and calling PetscDrawSave().
139: The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
140: Support for .png images requires configure --with-libpng.
141: Support for .gif images requires configure --with-giflib.
142: Support for .jpg images requires configure --with-libjpeg.
143: Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
145: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
146: @*/
147: PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
148: {
149: char buf[PETSC_MAX_PATH_LEN];
154: if (!filename || !filename[0]) {
155: if (!draw->savefilename) {
156: PetscObjectGetName((PetscObject)draw,&filename);
157: } else {
158: PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);
159: filename = buf;
160: }
161: }
162: PetscFree(draw->savefinalfilename);
163: PetscStrallocpy(filename,&draw->savefinalfilename);
164: return(0);
165: }
167: /*@
168: PetscDrawSave - Saves a drawn image
170: Collective on PetscDraw
172: Input Parameters:
173: . draw - the drawing context
175: Level: advanced
177: Notes:
178: this is not normally called by the user.
180: .seealso: PetscDrawSetSave()
182: @*/
183: PetscErrorCode PetscDrawSave(PetscDraw draw)
184: {
185: PetscInt saveindex;
186: char basename[PETSC_MAX_PATH_LEN];
187: unsigned char palette[256][3];
188: unsigned int w,h;
189: unsigned char *pixels = NULL;
190: PetscMPIInt rank;
195: if (!draw->ops->save && !draw->ops->getimage) return(0);
196: if (draw->ops->save) {(*draw->ops->save)(draw); goto finally;}
197: if (!draw->savefilename || !draw->saveimageext) return(0);
198: MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
200: saveindex = draw->savefilecount++;
202: if (!rank && !saveindex) {
203: char path[PETSC_MAX_PATH_LEN];
204: if (draw->savesinglefile) {
205: PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);
206: (void)remove(path);
207: } else {
208: PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);
209: PetscRMTree(path);
210: PetscMkdir(path);
211: }
212: if (draw->savemovieext) {
213: PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);
214: (void)remove(path);
215: }
216: }
217: if (draw->savesinglefile) {
218: PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);
219: } else {
220: PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)saveindex);
221: }
223: /* this call is collective, only the first process gets the image data */
224: (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);
225: /* only the first process handles the saving business */
226: if (!rank) {PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels);}
227: PetscFree(pixels);
228: MPI_Barrier(PetscObjectComm((PetscObject)draw));
230: finally:
231: #if defined(PETSC_HAVE_SAWS)
232: PetscDrawSave_SAWs(draw);
233: #endif
234: return(0);
235: }
237: /*@
238: PetscDrawSaveMovie - Saves a movie from previously saved images
240: Collective on PetscDraw
242: Input Parameters:
243: . draw - the drawing context
245: Level: advanced
247: Notes:
248: this is not normally called by the user.
249: The ffmpeg utility must be in your path to make the movie.
251: .seealso: PetscDrawSetSave(), PetscDrawSetSaveMovie()
253: @*/
254: PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
255: {
256: PetscMPIInt rank;
261: if (!draw->ops->save && !draw->ops->getimage) return(0);
262: if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) return(0);
263: MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
264: {
265: const char *fname = draw->savefilename;
266: const char *imext = draw->saveimageext;
267: const char *mvext = draw->savemovieext;
268: if (!rank) {PetscDrawMovieSave(fname,draw->savefilecount,imext,draw->savemoviefps,mvext);}
269: MPI_Barrier(PetscObjectComm((PetscObject)draw));
270: }
271: return(0);
272: }
275: #if defined(PETSC_HAVE_SAWS)
276: #include <petscviewersaws.h>
277: /*
278: The PetscImageList object and functions are used to maintain a list of file images
279: that can be displayed by the SAWs webserver.
280: */
281: typedef struct _P_PetscImageList *PetscImageList;
282: struct _P_PetscImageList {
283: PetscImageList next;
284: char *filename;
285: char *ext;
286: PetscInt count;
287: } ;
289: static PetscImageList SAWs_images = NULL;
291: static PetscErrorCode PetscImageListDestroy(void)
292: {
294: PetscImageList image = SAWs_images;
297: while (image) {
298: PetscImageList next = image->next;
299: PetscFree(image->filename);
300: PetscFree(image->ext);
301: PetscFree(image);
302: image = next;
303: }
304: return(0);
305: }
307: static PetscErrorCode PetscImageListAdd(const char filename[],const char ext[],PetscInt count)
308: {
309: PetscErrorCode ierr;
310: PetscImageList image,oimage = SAWs_images;
311: PetscBool flg;
314: if (oimage) {
315: PetscStrcmp(filename,oimage->filename,&flg);
316: if (flg) {
317: oimage->count = count;
318: return(0);
319: }
320: while (oimage->next) {
321: oimage = oimage->next;
322: PetscStrcmp(filename,oimage->filename,&flg);
323: if (flg) {
324: oimage->count = count;
325: return(0);
326: }
327: }
328: PetscNew(&image);
329: oimage->next = image;
330: } else {
331: PetscRegisterFinalize(PetscImageListDestroy);
332: PetscNew(&image);
333: SAWs_images = image;
334: }
335: PetscStrallocpy(filename,&image->filename);
336: PetscStrallocpy(ext,&image->ext);
337: image->count = count;
338: return(0);
339: }
341: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
342: {
343: PetscImageList image;
344: char body[4096];
345: size_t len = 0;
349: if (!draw->savefilename || !draw->saveimageext) return(0);
350: PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);
351: image = SAWs_images;
352: while (image) {
353: const char *name = image->filename;
354: const char *ext = image->ext;
355: if (draw->savesinglefile) {
356: PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);
357: } else {
358: PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);
359: }
360: PetscStrlen(body,&len);
361: image = image->next;
362: }
363: PetscStrlcat(body,"<br>\n",sizeof(body));
364: if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
365: PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
366: return(0);
367: }
369: #endif