Actual source code: dsave.c

  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 Parameters:
 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];


 47:   /* determine save filename and image extension */
 48:   if (filename && filename[0]) {
 49:     PetscStrchr(filename,'.',(char **)&imageext);
 50:     if (!imageext) savename = filename;
 51:     else if (imageext != filename) {
 52:       size_t l1 = 0,l2 = 0;
 53:       PetscStrlen(filename,&l1);
 54:       PetscStrlen(imageext,&l2);
 55:       PetscStrncpy(buf,filename,l1-l2+1);
 56:       savename = buf;
 57:     }
 58:   }

 60:   if (!savename) PetscObjectGetName((PetscObject)draw,&savename);
 61:   PetscDrawImageCheckFormat(&imageext);

 63:   draw->savefilecount = 0;
 64:   PetscFree(draw->savefilename);
 65:   PetscFree(draw->saveimageext);
 66:   PetscStrallocpy(savename,&draw->savefilename);
 67:   PetscStrallocpy(imageext,&draw->saveimageext);

 69:   if (draw->savesinglefile) {
 70:     PetscInfo(NULL,"Will save image to file %s%s\n",draw->savefilename,draw->saveimageext);
 71:   } else {
 72:     PetscInfo(NULL,"Will save images to file %s/%s_%%d%s\n",draw->savefilename,draw->savefilename,draw->saveimageext);
 73:   }
 74:   return 0;
 75: }

 77: /*@C
 78:    PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file

 80:    Collective on PetscDraw

 82:    Input Parameters:
 83: +  draw      - the graphics context
 84: -  movieext  - optional extension defining the movie format

 86:    Options Database Command:
 87: .  -draw_save_movie <.ext> - saves a movie with extension .ext

 89:    Level: intermediate

 91:    Notes:
 92:     You should call this AFTER calling PetscDrawSetSave() and BEFORE creating your image with PetscDrawSave().
 93:    The ffmpeg utility must be in your path to make the movie.

 95: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
 96: @*/
 97: PetscErrorCode  PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])
 98: {

102:   if (!draw->savefilename) PetscDrawSetSave(draw,"");
103:   PetscDrawMovieCheckFormat(&movieext);
104:   PetscStrallocpy(movieext,&draw->savemovieext);
105:   draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */

107:   PetscInfo(NULL,"Will save movie to file %s%s\n",draw->savefilename,draw->savemovieext);
108:   return 0;
109: }

111: /*@C
112:    PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file

114:    Collective on PetscDraw

116:    Input Parameters:
117: +  draw      - the graphics context
118: -  filename  - name of the file, if NULL or empty uses name set with PetscDrawSetSave() or name of draw object

120:    Options Database Command:
121: .  -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)

123:    Level: intermediate

125:    Notes:
126:     You should call this BEFORE creating your image and calling PetscDrawSave().
127:    The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
128:    Support for .png images requires configure --with-libpng.
129:    Support for .gif images requires configure --with-giflib.
130:    Support for .jpg images requires configure --with-libjpeg.
131:    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).

133: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
134: @*/
135: PetscErrorCode  PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
136: {
137:   char           buf[PETSC_MAX_PATH_LEN];

140:   if (!filename || !filename[0]) {
141:     if (!draw->savefilename) {
142:       PetscObjectGetName((PetscObject)draw,&filename);
143:     } else {
144:       PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);
145:       filename = buf;
146:     }
147:   }
148:   PetscFree(draw->savefinalfilename);
149:   PetscStrallocpy(filename,&draw->savefinalfilename);
150:   return 0;
151: }

153: /*@
154:    PetscDrawSave - Saves a drawn image

156:    Collective on PetscDraw

158:    Input Parameters:
159: .  draw - the drawing context

161:    Level: advanced

163:    Notes:
164:     this is not normally called by the user.

166: .seealso: PetscDrawSetSave()

168: @*/
169: PetscErrorCode  PetscDrawSave(PetscDraw draw)
170: {
171:   PetscInt       saveindex;
172:   char           basename[PETSC_MAX_PATH_LEN];
173:   unsigned char  palette[256][3];
174:   unsigned int   w,h;
175:   unsigned char  *pixels = NULL;
176:   PetscMPIInt    rank;

179:   if (!draw->ops->save && !draw->ops->getimage) return 0;
180:   if (draw->ops->save) {(*draw->ops->save)(draw); goto finally;}
181:   if (!draw->savefilename || !draw->saveimageext) return 0;
182:   MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);

184:   saveindex = draw->savefilecount++;

186:   if (rank == 0 && !saveindex) {
187:     char path[PETSC_MAX_PATH_LEN];
188:     if (draw->savesinglefile) {
189:       PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);
190:       (void)remove(path);
191:     } else {
192:       PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);
193:       PetscRMTree(path);
194:       PetscMkdir(path);
195:     }
196:     if (draw->savemovieext) {
197:       PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);
198:       (void)remove(path);
199:     }
200:   }
201:   if (draw->savesinglefile) {
202:     PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);
203:   } else {
204:     char *basefilename;

206:     PetscStrrchr(draw->savefilename, '/', (char **) &basefilename);
207:     if (basefilename != draw->savefilename) {
208:       PetscSNPrintf(basename,sizeof(basename),"%s_%d",draw->savefilename,(int)saveindex);
209:     } else {
210:       PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)saveindex);
211:     }
212:   }

214:   /* this call is collective, only the first process gets the image data */
215:   (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);
216:   /* only the first process handles the saving business */
217:   if (rank == 0) PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels);
218:   PetscFree(pixels);
219:   MPI_Barrier(PetscObjectComm((PetscObject)draw));

221: finally:
222: #if defined(PETSC_HAVE_SAWS)
223:   PetscDrawSave_SAWs(draw);
224: #endif
225:   return 0;
226: }

228: /*@
229:    PetscDrawSaveMovie - Saves a movie from previously saved images

231:    Collective on PetscDraw

233:    Input Parameters:
234: .  draw - the drawing context

236:    Level: advanced

238:    Notes:
239:     this is not normally called by the user.
240:    The ffmpeg utility must be in your path to make the movie.

242: .seealso: PetscDrawSetSave(), PetscDrawSetSaveMovie()

244: @*/
245: PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
246: {
247:   PetscMPIInt    rank;

250:   if (!draw->ops->save && !draw->ops->getimage) return 0;
251:   if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) return 0;
252:   MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
253:   {
254:     const char *fname = draw->savefilename;
255:     const char *imext = draw->saveimageext;
256:     const char *mvext = draw->savemovieext;
257:     if (rank == 0) PetscDrawMovieSave(fname,draw->savefilecount,imext,draw->savemoviefps,mvext);
258:     MPI_Barrier(PetscObjectComm((PetscObject)draw));
259:   }
260:   return 0;
261: }

263: #if defined(PETSC_HAVE_SAWS)
264: #include <petscviewersaws.h>
265: /*
266:   The PetscImageList object and functions are used to maintain a list of file images
267:   that can be displayed by the SAWs webserver.
268: */
269: typedef struct _P_PetscImageList *PetscImageList;
270: struct _P_PetscImageList {
271:   PetscImageList next;
272:   char           *filename;
273:   char           *ext;
274:   PetscInt       count;
275: } ;

277: static PetscImageList SAWs_images = NULL;

279: static PetscErrorCode PetscImageListDestroy(void)
280: {
281:   PetscImageList image = SAWs_images;

283:   while (image) {
284:     PetscImageList next = image->next;
285:     PetscFree(image->filename);
286:     PetscFree(image->ext);
287:     PetscFree(image);
288:     image = next;
289:   }
290:   return 0;
291: }

293: static PetscErrorCode PetscImageListAdd(const char filename[],const char ext[],PetscInt count)
294: {
295:   PetscImageList image,oimage = SAWs_images;
296:   PetscBool      flg;

298:   if (oimage) {
299:     PetscStrcmp(filename,oimage->filename,&flg);
300:     if (flg) {
301:       oimage->count = count;
302:       return 0;
303:     }
304:     while (oimage->next) {
305:       oimage = oimage->next;
306:       PetscStrcmp(filename,oimage->filename,&flg);
307:       if (flg) {
308:         oimage->count = count;
309:         return 0;
310:       }
311:     }
312:     PetscNew(&image);
313:     oimage->next = image;
314:   } else {
315:     PetscRegisterFinalize(PetscImageListDestroy);
316:     PetscNew(&image);
317:     SAWs_images = image;
318:   }
319:   PetscStrallocpy(filename,&image->filename);
320:   PetscStrallocpy(ext,&image->ext);
321:   image->count = count;
322:   return 0;
323: }

325: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
326: {
327:   PetscImageList image;
328:   char           body[4096];
329:   size_t         len = 0;

331:   if (!draw->savefilename || !draw->saveimageext) return 0;
332:   PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);
333:   image = SAWs_images;
334:   while (image) {
335:     const char *name = image->filename;
336:     const char *ext  = image->ext;
337:     if (draw->savesinglefile) {
338:       PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);
339:     } else {
340:       PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);
341:     }
342:     PetscStrlen(body,&len);
343:     image = image->next;
344:   }
345:   PetscStrlcat(body,"<br>\n",sizeof(body));
346:   if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
347:   PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
348:   return 0;
349: }

351: #endif