Actual source code: dsave.c
petsc-3.14.6 2021-03-30
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: Notes:
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: 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];
49: /* determine save filename and image extension */
50: if (filename && filename[0]) {
51: PetscStrchr(filename,'.',(char **)&imageext);
52: if (!imageext) savename = filename;
53: else if (imageext != filename) {
54: size_t l1 = 0,l2 = 0;
55: PetscStrlen(filename,&l1);
56: PetscStrlen(imageext,&l2);
57: PetscStrncpy(buf,filename,l1-l2+1);
58: savename = buf;
59: }
60: }
62: if (!savename) {PetscObjectGetName((PetscObject)draw,&savename);}
63: PetscDrawImageCheckFormat(&imageext);
65: draw->savefilecount = 0;
66: PetscFree(draw->savefilename);
67: PetscFree(draw->saveimageext);
68: PetscStrallocpy(savename,&draw->savefilename);
69: PetscStrallocpy(imageext,&draw->saveimageext);
71: if (draw->savesinglefile) {
72: PetscInfo2(NULL,"Will save image to file %s%s\n",draw->savefilename,draw->saveimageext);
73: } else {
74: PetscInfo3(NULL,"Will save images to file %s/%s_%%d%s\n",draw->savefilename,draw->savefilename,draw->saveimageext);
75: }
76: return(0);
77: }
79: /*@C
80: PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file
82: Collective on PetscDraw
84: Input Parameter:
85: + draw - the graphics context
86: - movieext - optional extension defining the movie format
88: Options Database Command:
89: . -draw_save_movie <.ext> - saves a movie with extension .ext
91: Level: intermediate
93: Notes:
94: You should call this AFTER calling PetscDrawSetSave() and BEFORE creating your image with PetscDrawSave().
95: The ffmpeg utility must be in your path to make the movie.
97: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
98: @*/
99: PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])
100: {
108: if (!draw->savefilename) {PetscDrawSetSave(draw,"");}
109: PetscDrawMovieCheckFormat(&movieext);
110: PetscStrallocpy(movieext,&draw->savemovieext);
111: draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
113: PetscInfo2(NULL,"Will save movie to file %s%s\n",draw->savefilename,draw->savemovieext);
114: return(0);
115: }
117: /*@C
118: PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file
120: Collective on PetscDraw
122: Input Parameter:
123: + draw - the graphics context
124: - filename - name of the file, if NULL or empty uses name set with PetscDrawSetSave() or name of draw object
126: Options Database Command:
127: . -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)
129: Level: intermediate
131: Notes:
132: You should call this BEFORE creating your image and calling PetscDrawSave().
133: The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
134: Support for .png images requires configure --with-libpng.
135: Support for .gif images requires configure --with-giflib.
136: Support for .jpg images requires configure --with-libjpeg.
137: Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
139: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
140: @*/
141: PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
142: {
143: char buf[PETSC_MAX_PATH_LEN];
148: if (!filename || !filename[0]) {
149: if (!draw->savefilename) {
150: PetscObjectGetName((PetscObject)draw,&filename);
151: } else {
152: PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);
153: filename = buf;
154: }
155: }
156: PetscFree(draw->savefinalfilename);
157: PetscStrallocpy(filename,&draw->savefinalfilename);
158: return(0);
159: }
161: /*@
162: PetscDrawSave - Saves a drawn image
164: Collective on PetscDraw
166: Input Parameters:
167: . draw - the drawing context
169: Level: advanced
171: Notes:
172: this is not normally called by the user.
174: .seealso: PetscDrawSetSave()
176: @*/
177: PetscErrorCode PetscDrawSave(PetscDraw draw)
178: {
179: PetscInt saveindex;
180: char basename[PETSC_MAX_PATH_LEN];
181: unsigned char palette[256][3];
182: unsigned int w,h;
183: unsigned char *pixels = NULL;
184: PetscMPIInt rank;
189: if (!draw->ops->save && !draw->ops->getimage) return(0);
190: if (draw->ops->save) {(*draw->ops->save)(draw); goto finally;}
191: if (!draw->savefilename || !draw->saveimageext) return(0);
192: MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
194: saveindex = draw->savefilecount++;
196: if (!rank && !saveindex) {
197: char path[PETSC_MAX_PATH_LEN];
198: if (draw->savesinglefile) {
199: PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);
200: (void)remove(path);
201: } else {
202: PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);
203: PetscRMTree(path);
204: PetscMkdir(path);
205: }
206: if (draw->savemovieext) {
207: PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);
208: (void)remove(path);
209: }
210: }
211: if (draw->savesinglefile) {
212: PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);
213: } else {
214: PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)saveindex);
215: }
217: /* this call is collective, only the first process gets the image data */
218: (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);
219: /* only the first process handles the saving business */
220: if (!rank) {PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels);}
221: PetscFree(pixels);
222: MPI_Barrier(PetscObjectComm((PetscObject)draw));
224: finally:
225: #if defined(PETSC_HAVE_SAWS)
226: PetscDrawSave_SAWs(draw);
227: #endif
228: return(0);
229: }
231: /*@
232: PetscDrawSaveMovie - Saves a movie from previously saved images
234: Collective on PetscDraw
236: Input Parameters:
237: . draw - the drawing context
239: Level: advanced
241: Notes:
242: this is not normally called by the user.
243: The ffmpeg utility must be in your path to make the movie.
245: .seealso: PetscDrawSetSave(), PetscDrawSetSaveMovie()
247: @*/
248: PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
249: {
250: 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) {PetscDrawMovieSave(fname,draw->savefilecount,imext,draw->savemoviefps,mvext);}
263: MPI_Barrier(PetscObjectComm((PetscObject)draw));
264: }
265: return(0);
266: }
269: #if defined(PETSC_HAVE_SAWS)
270: #include <petscviewersaws.h>
271: /*
272: The PetscImageList object and functions are used to maintain a list of file images
273: that can be displayed by the SAWs webserver.
274: */
275: typedef struct _P_PetscImageList *PetscImageList;
276: struct _P_PetscImageList {
277: PetscImageList next;
278: char *filename;
279: char *ext;
280: PetscInt count;
281: } ;
283: static PetscImageList SAWs_images = NULL;
285: static PetscErrorCode PetscImageListDestroy(void)
286: {
288: PetscImageList image = SAWs_images;
291: while (image) {
292: PetscImageList next = image->next;
293: PetscFree(image->filename);
294: PetscFree(image->ext);
295: PetscFree(image);
296: image = next;
297: }
298: return(0);
299: }
301: static PetscErrorCode PetscImageListAdd(const char filename[],const char ext[],PetscInt count)
302: {
303: PetscErrorCode ierr;
304: PetscImageList image,oimage = SAWs_images;
305: PetscBool flg;
308: if (oimage) {
309: PetscStrcmp(filename,oimage->filename,&flg);
310: if (flg) {
311: oimage->count = count;
312: return(0);
313: }
314: while (oimage->next) {
315: oimage = oimage->next;
316: PetscStrcmp(filename,oimage->filename,&flg);
317: if (flg) {
318: oimage->count = count;
319: return(0);
320: }
321: }
322: PetscNew(&image);
323: oimage->next = image;
324: } else {
325: PetscRegisterFinalize(PetscImageListDestroy);
326: PetscNew(&image);
327: SAWs_images = image;
328: }
329: PetscStrallocpy(filename,&image->filename);
330: PetscStrallocpy(ext,&image->ext);
331: image->count = count;
332: return(0);
333: }
335: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
336: {
337: PetscImageList image;
338: char body[4096];
339: size_t len = 0;
343: if (!draw->savefilename || !draw->saveimageext) return(0);
344: PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);
345: image = SAWs_images;
346: while (image) {
347: const char *name = image->filename;
348: const char *ext = image->ext;
349: if (draw->savesinglefile) {
350: PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);
351: } else {
352: PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);
353: }
354: PetscStrlen(body,&len);
355: image = image->next;
356: }
357: PetscStrlcat(body,"<br>\n",sizeof(body));
358: if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
359: PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
360: return(0);
361: }
363: #endif