Actual source code: dsave.c

petsc-3.14.6 2021-03-30
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:    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