Actual source code: dsave.c
petsc-3.9.4 2018-09-11
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: You should call this BEFORE creating your image and calling PetscDrawSave().
31: The supported image types are .png, .gif, .jpg, and .ppm (PETSc chooses the default in that order).
32: Support for .png images requires configure --with-libpng.
33: Support for .gif images requires configure --with-giflib.
34: Support for .jpg images requires configure --with-libjpeg.
35: Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
37: .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSaveFinalImage()
38: @*/
39: PetscErrorCode PetscDrawSetSave(PetscDraw draw,const char filename[])
40: {
41: const char *savename = NULL;
42: const char *imageext = NULL;
43: char buf[PETSC_MAX_PATH_LEN];
50: /* determine save filename and image extension */
51: if (filename && filename[0]) {
52: PetscStrchr(filename,'.',(char **)&imageext);
53: if (!imageext) savename = filename;
54: else if (imageext != filename) {
55: size_t l1 = 0,l2 = 0;
56: PetscStrlen(filename,&l1);
57: PetscStrlen(imageext,&l2);
58: PetscStrncpy(buf,filename,l1-l2+1);
59: savename = buf;
60: }
61: }
63: if (!savename) {PetscObjectGetName((PetscObject)draw,&savename);}
64: PetscDrawImageCheckFormat(&imageext);
66: draw->savefilecount = 0;
67: PetscFree(draw->savefilename);
68: PetscFree(draw->saveimageext);
69: PetscStrallocpy(savename,&draw->savefilename);
70: PetscStrallocpy(imageext,&draw->saveimageext);
72: if (draw->savesinglefile) {
73: PetscInfo2(NULL,"Will save image to file %s%s\n",draw->savefilename,draw->saveimageext);
74: } else {
75: PetscInfo3(NULL,"Will save images to file %s/%s_%%d%s\n",draw->savefilename,draw->savefilename,draw->saveimageext);
76: }
77: return(0);
78: }
80: /*@C
81: PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file
83: Collective on PetscDraw
85: Input Parameter:
86: + draw - the graphics context
87: - movieext - optional extension defining the movie format
89: Options Database Command:
90: . -draw_save_movie <.ext> - saves a movie with extension .ext
92: Level: intermediate
94: Concepts: X windows^graphics
96: Notes: You should call this AFTER calling PetscDrawSetSave() and BEFORE creating your image with PetscDrawSave().
97: The ffmpeg utility must be in your path to make the movie.
99: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
100: @*/
101: PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])
102: {
110: if (!draw->savefilename) {PetscDrawSetSave(draw,"");}
111: PetscDrawMovieCheckFormat(&movieext);
112: PetscStrallocpy(movieext,&draw->savemovieext);
113: draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
115: PetscInfo2(NULL,"Will save movie to file %s%s\n",draw->savefilename,draw->savemovieext);
116: return(0);
117: }
119: /*@C
120: PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file
122: Collective on PetscDraw
124: Input Parameter:
125: + draw - the graphics context
126: - filename - name of the file, if NULL or empty uses name set with PetscDrawSetSave() or name of draw object
128: Options Database Command:
129: . -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)
131: Level: intermediate
133: Concepts: X windows^graphics
135: Notes: You should call this BEFORE creating your image and calling PetscDrawSave().
136: The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
137: Support for .png images requires configure --with-libpng.
138: Support for .gif images requires configure --with-giflib.
139: Support for .jpg images requires configure --with-libjpeg.
140: Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
142: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
143: @*/
144: PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
145: {
146: char buf[PETSC_MAX_PATH_LEN];
151: if (!filename || !filename[0]) {
152: if (!draw->savefilename) {
153: PetscObjectGetName((PetscObject)draw,&filename);
154: } else {
155: PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);
156: filename = buf;
157: }
158: }
159: PetscFree(draw->savefinalfilename);
160: PetscStrallocpy(filename,&draw->savefinalfilename);
161: return(0);
162: }
164: /*@
165: PetscDrawSave - Saves a drawn image
167: Collective on PetscDraw
169: Input Parameters:
170: . draw - the drawing context
172: Level: advanced
174: Notes: this is not normally called by the user.
176: .seealso: PetscDrawSetSave()
178: @*/
179: PetscErrorCode PetscDrawSave(PetscDraw draw)
180: {
181: PetscInt saveindex;
182: char basename[PETSC_MAX_PATH_LEN];
183: unsigned char palette[256][3];
184: unsigned int w,h;
185: unsigned char *pixels = NULL;
186: PetscMPIInt rank;
191: if (!draw->ops->save && !draw->ops->getimage) return(0);
192: if (draw->ops->save) {(*draw->ops->save)(draw); goto finally;}
193: if (!draw->savefilename || !draw->saveimageext) return(0);
194: MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
196: saveindex = draw->savefilecount++;
198: if (!rank && !saveindex) {
199: char path[PETSC_MAX_PATH_LEN];
200: if (draw->savesinglefile) {
201: PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);
202: (void)remove(path);
203: } else {
204: PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);
205: PetscRMTree(path);
206: PetscMkdir(path);
207: }
208: if (draw->savemovieext) {
209: PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);
210: (void)remove(path);
211: }
212: }
213: if (draw->savesinglefile) {
214: PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);
215: } else {
216: PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)saveindex);
217: }
219: /* this call is collective, only the first process gets the image data */
220: (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);
221: /* only the first process handles the saving business */
222: if (!rank) {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 on PetscDraw
238: Input Parameters:
239: . draw - the drawing context
241: Level: advanced
243: Notes: this is not normally called by the user.
244: The ffmpeg utility must be in your path to make the movie.
246: .seealso: PetscDrawSetSave(), PetscDrawSetSaveMovie()
248: @*/
249: PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
250: {
251: PetscMPIInt rank;
256: if (!draw->ops->save && !draw->ops->getimage) return(0);
257: if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) return(0);
258: MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
259: {
260: const char *fname = draw->savefilename;
261: const char *imext = draw->saveimageext;
262: const char *mvext = draw->savemovieext;
263: if (!rank) {PetscDrawMovieSave(fname,draw->savefilecount,imext,draw->savemoviefps,mvext);}
264: MPI_Barrier(PetscObjectComm((PetscObject)draw));
265: }
266: return(0);
267: }
270: #if defined(PETSC_HAVE_SAWS)
271: #include <petscviewersaws.h>
272: /*
273: The PetscImageList object and functions are used to maintain a list of file images
274: that can be displayed by the SAWs webserver.
275: */
276: typedef struct _P_PetscImageList *PetscImageList;
277: struct _P_PetscImageList {
278: PetscImageList next;
279: char *filename;
280: char *ext;
281: PetscInt count;
282: } ;
284: static PetscImageList SAWs_images = NULL;
286: static PetscErrorCode PetscImageListDestroy(void)
287: {
289: PetscImageList image = SAWs_images;
292: while (image) {
293: PetscImageList next = image->next;
294: PetscFree(image->filename);
295: PetscFree(image->ext);
296: PetscFree(image);
297: image = next;
298: }
299: return(0);
300: }
302: static PetscErrorCode PetscImageListAdd(const char filename[],const char ext[],PetscInt count)
303: {
304: PetscErrorCode ierr;
305: PetscImageList image,oimage = SAWs_images;
306: PetscBool flg;
309: if (oimage) {
310: PetscStrcmp(filename,oimage->filename,&flg);
311: if (flg) {
312: oimage->count = count;
313: return(0);
314: }
315: while (oimage->next) {
316: oimage = oimage->next;
317: PetscStrcmp(filename,oimage->filename,&flg);
318: if (flg) {
319: oimage->count = count;
320: return(0);
321: }
322: }
323: PetscNew(&image);
324: oimage->next = image;
325: } else {
326: PetscRegisterFinalize(PetscImageListDestroy);
327: PetscNew(&image);
328: SAWs_images = image;
329: }
330: PetscStrallocpy(filename,&image->filename);
331: PetscStrallocpy(ext,&image->ext);
332: image->count = count;
333: return(0);
334: }
336: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
337: {
338: PetscImageList image;
339: char body[4096];
340: size_t len = 0;
344: if (!draw->savefilename || !draw->saveimageext) return(0);
345: PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);
346: image = SAWs_images;
347: while (image) {
348: const char *name = image->filename;
349: const char *ext = image->ext;
350: if (draw->savesinglefile) {
351: PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);
352: } else {
353: PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);
354: }
355: PetscStrlen(body,&len);
356: image = image->next;
357: }
358: PetscStrlcat(body,"<br>\n",sizeof(body));
359: if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
360: PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
361: return(0);
362: }
364: #endif