Actual source code: dsave.c

petsc-3.11.3 2019-06-26
Report Typos and Errors
  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