Actual source code: dsave.c

petsc-3.7.7 2017-09-25
Report Typos and Errors
  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