Actual source code: dsave.c
petsc-3.7.7 2017-09-25
1: #include <petsc/private/drawimpl.h> /*I "petscdraw.h" I*/
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
14: /*@C
15: PetscDrawSetSave - Saves images produced in a PetscDraw into a file
17: Collective on PetscDraw
19: Input Parameter:
20: + draw - the graphics context
21: - filename - name of the file, if .ext then uses name of draw object plus .ext using .ext to determine the image type
23: Options Database Command:
24: + -draw_save <filename> - filename could be name.ext or .ext (where .ext determines the type of graphics file to save, for example .png)
25: . -draw_save_final_image [optional filename] - saves the final image displayed in a window
26: - -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
28: Level: intermediate
30: Concepts: X windows^graphics
32: Notes: You should call this BEFORE creating your image and calling PetscDrawSave().
33: The supported image types are .png, .gif, .jpg, and .ppm (PETSc chooses the default in that order).
34: Support for .png images requires configure --with-libpng.
35: Support for .gif images requires configure --with-giflib.
36: Support for .jpg images requires configure --with-libjpeg.
37: Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
39: .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSaveFinalImage()
40: @*/
41: PetscErrorCode PetscDrawSetSave(PetscDraw draw,const char filename[])
42: {
43: const char *savename = NULL;
44: const char *imageext = NULL;
45: char buf[PETSC_MAX_PATH_LEN];
52: /* determine save filename and image extension */
53: if (filename && filename[0]) {
54: PetscStrchr(filename,'.',(char **)&imageext);
55: if (!imageext) savename = filename;
56: else if (imageext != filename) {
57: size_t l1 = 0,l2 = 0;
58: PetscStrlen(filename,&l1);
59: PetscStrlen(imageext,&l2);
60: PetscStrncpy(buf,filename,l1-l2+1);
61: savename = buf;
62: }
63: }
65: if (!savename) {PetscObjectGetName((PetscObject)draw,&savename);}
66: PetscDrawImageCheckFormat(&imageext);
68: draw->savefilecount = 0;
69: PetscFree(draw->savefilename);
70: PetscFree(draw->saveimageext);
71: PetscStrallocpy(savename,&draw->savefilename);
72: PetscStrallocpy(imageext,&draw->saveimageext);
74: if (draw->savesinglefile) {
75: PetscInfo2(NULL,"Will save image to file %s%s\n",draw->savefilename,draw->saveimageext);
76: } else {
77: PetscInfo3(NULL,"Will save images to file %s/%s_%%d%s\n",draw->savefilename,draw->savefilename,draw->saveimageext);
78: }
79: return(0);
80: }
84: /*@C
85: PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file
87: Collective on PetscDraw
89: Input Parameter:
90: + draw - the graphics context
91: - movieext - optional extension defining the movie format
93: Options Database Command:
94: . -draw_save_movie <.ext> - saves a movie with extension .ext
96: Level: intermediate
98: Concepts: X windows^graphics
100: Notes: You should call this AFTER calling PetscDrawSetSave() and BEFORE creating your image with PetscDrawSave().
101: The ffmpeg utility must be in your path to make the movie.
103: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
104: @*/
105: PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])
106: {
114: if (!draw->savefilename) {PetscDrawSetSave(draw,"");}
115: PetscDrawMovieCheckFormat(&movieext);
116: PetscStrallocpy(movieext,&draw->savemovieext);
117: draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
119: PetscInfo2(NULL,"Will save movie to file %s%s\n",draw->savefilename,draw->savemovieext);
120: return(0);
121: }
125: /*@C
126: PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file
128: Collective on PetscDraw
130: Input Parameter:
131: + draw - the graphics context
132: - filename - name of the file, if NULL or empty uses name set with PetscDrawSetSave() or name of draw object
134: Options Database Command:
135: . -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)
137: Level: intermediate
139: Concepts: X windows^graphics
141: Notes: You should call this BEFORE creating your image and calling PetscDrawSave().
142: The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
143: Support for .png images requires configure --with-libpng.
144: Support for .gif images requires configure --with-giflib.
145: Support for .jpg images requires configure --with-libjpeg.
146: Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
148: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
149: @*/
150: PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
151: {
152: char buf[PETSC_MAX_PATH_LEN];
157: if (!filename || !filename[0]) {
158: if (!draw->savefilename) {
159: PetscObjectGetName((PetscObject)draw,&filename);
160: } else {
161: PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);
162: filename = buf;
163: }
164: }
165: PetscFree(draw->savefinalfilename);
166: PetscStrallocpy(filename,&draw->savefinalfilename);
167: return(0);
168: }
172: /*@
173: PetscDrawSave - Saves a drawn image
175: Collective on PetscDraw
177: Input Parameters:
178: . draw - the drawing context
180: Level: advanced
182: Notes: this is not normally called by the user.
184: .seealso: PetscDrawSetSave()
186: @*/
187: PetscErrorCode PetscDrawSave(PetscDraw draw)
188: {
189: PetscInt saveindex;
190: char basename[PETSC_MAX_PATH_LEN];
191: unsigned char palette[256][3];
192: unsigned int w,h;
193: unsigned char *pixels = NULL;
194: PetscMPIInt rank;
199: if (!draw->ops->save && !draw->ops->getimage) return(0);
200: if (draw->ops->save) {(*draw->ops->save)(draw); goto finally;}
201: if (!draw->savefilename || !draw->saveimageext) return(0);
202: MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
204: saveindex = draw->savefilecount++;
206: if (!rank && !saveindex) {
207: char path[PETSC_MAX_PATH_LEN];
208: if (draw->savesinglefile) {
209: PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);
210: (void)remove(path);
211: } else {
212: PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);
213: PetscRMTree(path);
214: PetscMkdir(path);
215: }
216: if (draw->savemovieext) {
217: PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);
218: (void)remove(path);
219: }
220: }
221: if (draw->savesinglefile) {
222: PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);
223: } else {
224: PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)saveindex);
225: }
227: /* this call is collective, only the first process gets the image data */
228: (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);
229: /* only the first process handles the saving business */
230: if (!rank) {PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels);}
231: PetscFree(pixels);
232: MPI_Barrier(PetscObjectComm((PetscObject)draw));
234: finally:
235: #if defined(PETSC_HAVE_SAWS)
236: PetscDrawSave_SAWs(draw);
237: #endif
238: return(0);
239: }
243: /*@
244: PetscDrawSaveMovie - Saves a movie from previously saved images
246: Collective on PetscDraw
248: Input Parameters:
249: . draw - the drawing context
251: Level: advanced
253: Notes: this is not normally called by the user.
254: The ffmpeg utility must be in your path to make the movie.
256: .seealso: PetscDrawSetSave(), PetscDrawSetSaveMovie()
258: @*/
259: PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
260: {
261: PetscMPIInt rank;
266: if (!draw->ops->save && !draw->ops->getimage) return(0);
267: if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) return(0);
268: MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
269: {
270: const char *fname = draw->savefilename;
271: const char *imext = draw->saveimageext;
272: const char *mvext = draw->savemovieext;
273: if (!rank) {PetscDrawMovieSave(fname,draw->savefilecount,imext,draw->savemoviefps,mvext);}
274: MPI_Barrier(PetscObjectComm((PetscObject)draw));
275: }
276: return(0);
277: }
280: #if defined(PETSC_HAVE_SAWS)
281: #include <petscviewersaws.h>
282: /*
283: The PetscImageList object and functions are used to maintain a list of file images
284: that can be displayed by the SAWs webserver.
285: */
286: typedef struct _P_PetscImageList *PetscImageList;
287: struct _P_PetscImageList {
288: PetscImageList next;
289: char *filename;
290: char *ext;
291: PetscInt count;
292: } ;
294: static PetscImageList SAWs_images = NULL;
298: static PetscErrorCode PetscImageListDestroy(void)
299: {
301: PetscImageList image = SAWs_images;
304: while (image) {
305: PetscImageList next = image->next;
306: PetscFree(image->filename);
307: PetscFree(image->ext);
308: PetscFree(image);
309: image = next;
310: }
311: return(0);
312: }
316: static PetscErrorCode PetscImageListAdd(const char filename[],const char ext[],PetscInt count)
317: {
318: PetscErrorCode ierr;
319: PetscImageList image,oimage = SAWs_images;
320: PetscBool flg;
323: if (oimage) {
324: PetscStrcmp(filename,oimage->filename,&flg);
325: if (flg) {
326: oimage->count = count;
327: return(0);
328: }
329: while (oimage->next) {
330: oimage = oimage->next;
331: PetscStrcmp(filename,oimage->filename,&flg);
332: if (flg) {
333: oimage->count = count;
334: return(0);
335: }
336: }
337: PetscNew(&image);
338: oimage->next = image;
339: } else {
340: PetscRegisterFinalize(PetscImageListDestroy);
341: PetscNew(&image);
342: SAWs_images = image;
343: }
344: PetscStrallocpy(filename,&image->filename);
345: PetscStrallocpy(ext,&image->ext);
346: image->count = count;
347: return(0);
348: }
352: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
353: {
354: PetscImageList image;
355: char body[4096];
356: size_t len = 0;
360: if (!draw->savefilename || !draw->saveimageext) return(0);
361: PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);
362: image = SAWs_images;
363: while (image) {
364: const char *name = image->filename;
365: const char *ext = image->ext;
366: if (draw->savesinglefile) {
367: PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);
368: } else {
369: PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);
370: }
371: PetscStrlen(body,&len);
372: image = image->next;
373: }
374: PetscStrcat(body,"<br>\n");
375: if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
376: PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
377: return(0);
378: }
380: #endif