xref: /petsc/src/sys/classes/draw/interface/dsave.c (revision 8556b5eb6d24048282742bdd6ce397a5c8264fe5)
1 #include <petsc/private/drawimpl.h>  /*I "petscdraw.h" I*/
2 
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 *[]);
7 
8 #if defined(PETSC_HAVE_SAWS)
9 static PetscErrorCode PetscDrawSave_SAWs(PetscDraw);
10 #endif
11 
12 #undef __FUNCT__
13 #define __FUNCT__ "PetscDrawSetSave"
14 /*@C
15    PetscDrawSetSave - Saves images produced in a PetscDraw into a file
16 
17    Collective on PetscDraw
18 
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
22 
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
27 
28    Level: intermediate
29 
30    Concepts: X windows^graphics
31 
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).
38 
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];
46   PetscErrorCode ierr;
47 
48   PetscFunctionBegin;
49   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
50   if (filename) PetscValidCharPointer(filename,2);
51 
52   /* determine save filename and image extension */
53   if (filename && filename[0]) {
54     ierr = PetscStrchr(filename,'.',(char **)&imageext);CHKERRQ(ierr);
55     if (!imageext) savename = filename;
56     else if (imageext != filename) {
57       size_t l1 = 0,l2 = 0;
58       ierr = PetscStrlen(filename,&l1);CHKERRQ(ierr);
59       ierr = PetscStrlen(imageext,&l2);CHKERRQ(ierr);
60       ierr = PetscStrncpy(buf,filename,l1-l2+1);CHKERRQ(ierr);
61       savename = buf;
62     }
63   }
64 
65   if (!savename) {ierr = PetscObjectGetName((PetscObject)draw,&savename);CHKERRQ(ierr);}
66   ierr = PetscDrawImageCheckFormat(&imageext);CHKERRQ(ierr);
67 
68   draw->savefilecount = 0;
69   ierr = PetscFree(draw->savefilename);CHKERRQ(ierr);
70   ierr = PetscFree(draw->saveimageext);CHKERRQ(ierr);
71   ierr = PetscStrallocpy(savename,&draw->savefilename);CHKERRQ(ierr);
72   ierr = PetscStrallocpy(imageext,&draw->saveimageext);CHKERRQ(ierr);
73 
74   if (draw->savesinglefile) {
75     ierr = PetscInfo2(NULL,"Will save image to file %s%s\n",draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
76   } else {
77     ierr = PetscInfo3(NULL,"Will save images to file %s/%s_%%d%s\n",draw->savefilename,draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
78   }
79   PetscFunctionReturn(0);
80 }
81 
82 #undef __FUNCT__
83 #define __FUNCT__ "PetscDrawSetSaveMovie"
84 /*@C
85    PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file
86 
87    Collective on PetscDraw
88 
89    Input Parameter:
90 +  draw      - the graphics context
91 -  movieext  - optional extension defining the movie format
92 
93    Options Database Command:
94 .  -draw_save_movie <.ext> - saves a movie with extension .ext
95 
96    Level: intermediate
97 
98    Concepts: X windows^graphics
99 
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.
102 
103 .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
104 @*/
105 PetscErrorCode  PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])
106 {
107 
108   PetscErrorCode ierr;
109 
110   PetscFunctionBegin;
111   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
112   if (movieext) PetscValidCharPointer(movieext,2);
113 
114   if (!draw->savefilename) {ierr = PetscDrawSetSave(draw,"");CHKERRQ(ierr);}
115   ierr = PetscDrawMovieCheckFormat(&movieext);CHKERRQ(ierr);
116   ierr = PetscStrallocpy(movieext,&draw->savemovieext);CHKERRQ(ierr);
117   draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
118 
119   ierr = PetscInfo2(NULL,"Will save movie to file %s%s\n",draw->savefilename,draw->savemovieext);CHKERRQ(ierr);
120   PetscFunctionReturn(0);
121 }
122 
123 #undef __FUNCT__
124 #define __FUNCT__ "PetscDrawSetSaveFinalImage"
125 /*@C
126    PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file
127 
128    Collective on PetscDraw
129 
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
133 
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)
136 
137    Level: intermediate
138 
139    Concepts: X windows^graphics
140 
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).
147 
148 .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
149 @*/
150 PetscErrorCode  PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
151 {
152   char           buf[PETSC_MAX_PATH_LEN];
153   PetscErrorCode ierr;
154 
155   PetscFunctionBegin;
156   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
157   if (!filename || !filename[0]) {
158     if (!draw->savefilename) {
159       ierr = PetscObjectGetName((PetscObject)draw,&filename);CHKERRQ(ierr);
160     } else {
161       ierr = PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
162       filename = buf;
163     }
164   }
165   ierr = PetscFree(draw->savefinalfilename);CHKERRQ(ierr);
166   ierr = PetscStrallocpy(filename,&draw->savefinalfilename);CHKERRQ(ierr);
167   PetscFunctionReturn(0);
168 }
169 
170 #undef __FUNCT__
171 #define __FUNCT__ "PetscDrawSave"
172 /*@
173    PetscDrawSave - Saves a drawn image
174 
175    Collective on PetscDraw
176 
177    Input Parameters:
178 .  draw - the drawing context
179 
180    Level: advanced
181 
182    Notes: this is not normally called by the user.
183 
184 .seealso: PetscDrawSetSave()
185 
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;
195   PetscErrorCode ierr;
196 
197   PetscFunctionBegin;
198   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
199   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
200   if (draw->ops->save) {ierr = (*draw->ops->save)(draw);CHKERRQ(ierr); goto finally;}
201   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
202   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
203 
204   saveindex = draw->savefilecount++;
205 
206   if (!rank && !saveindex) {
207     char path[PETSC_MAX_PATH_LEN];
208     if (draw->savesinglefile) {
209       ierr = PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
210       (void)remove(path);
211     } else {
212       ierr = PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);CHKERRQ(ierr);
213       ierr = PetscRMTree(path);CHKERRQ(ierr);
214       ierr = PetscMkdir(path);CHKERRQ(ierr);
215     }
216     if (draw->savemovieext) {
217       ierr = PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);CHKERRQ(ierr);
218       (void)remove(path);
219     }
220   }
221   if (draw->savesinglefile) {
222     ierr = PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);CHKERRQ(ierr);
223   } else {
224     ierr = PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)saveindex);CHKERRQ(ierr);
225   }
226 
227   /* this call is collective, only the first process gets the image data */
228   ierr = (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);CHKERRQ(ierr);
229   /* only the first process handles the saving business */
230   if (!rank) {ierr = PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels);CHKERRQ(ierr);}
231   ierr = PetscFree(pixels);CHKERRQ(ierr);
232   ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
233 
234 finally:
235 #if defined(PETSC_HAVE_SAWS)
236   ierr = PetscDrawSave_SAWs(draw);CHKERRQ(ierr);
237 #endif
238   PetscFunctionReturn(0);
239 }
240 
241 #undef __FUNCT__
242 #define __FUNCT__ "PetscDrawSaveMovie"
243 /*@
244    PetscDrawSaveMovie - Saves a movie from previously saved images
245 
246    Collective on PetscDraw
247 
248    Input Parameters:
249 .  draw - the drawing context
250 
251    Level: advanced
252 
253    Notes: this is not normally called by the user.
254    The ffmpeg utility must be in your path to make the movie.
255 
256 .seealso: PetscDrawSetSave(), PetscDrawSetSaveMovie()
257 
258 @*/
259 PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
260 {
261   PetscMPIInt    rank;
262   PetscErrorCode ierr;
263 
264   PetscFunctionBegin;
265   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
266   if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
267   if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) PetscFunctionReturn(0);
268   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
269   {
270     const char *fname = draw->savefilename;
271     const char *imext = draw->saveimageext;
272     const char *mvext = draw->savemovieext;
273     if (!rank) {ierr = PetscDrawMovieSave(fname,draw->savefilecount,imext,draw->savemoviefps,mvext);CHKERRQ(ierr);}
274     ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
275   }
276   PetscFunctionReturn(0);
277 }
278 
279 
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 } ;
293 
294 static PetscImageList SAWs_images = NULL;
295 
296 #undef __FUNCT__
297 #define __FUNCT__ "PetscImageListDestroy"
298 static PetscErrorCode PetscImageListDestroy(void)
299 {
300   PetscErrorCode ierr;
301   PetscImageList image = SAWs_images;
302 
303   PetscFunctionBegin;
304   while (image) {
305     PetscImageList next = image->next;
306     ierr = PetscFree(image->filename);CHKERRQ(ierr);
307     ierr = PetscFree(image->ext);CHKERRQ(ierr);
308     ierr = PetscFree(image);CHKERRQ(ierr);
309     image = next;
310   }
311   PetscFunctionReturn(0);
312 }
313 
314 #undef __FUNCT__
315 #define __FUNCT__ "PetscImageListAdd"
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;
321 
322   PetscFunctionBegin;
323   if (oimage) {
324     ierr = PetscStrcmp(filename,oimage->filename,&flg);CHKERRQ(ierr);
325     if (flg) {
326       oimage->count = count;
327       PetscFunctionReturn(0);
328     }
329     while (oimage->next) {
330       oimage = oimage->next;
331       ierr = PetscStrcmp(filename,oimage->filename,&flg);CHKERRQ(ierr);
332       if (flg) {
333         oimage->count = count;
334         PetscFunctionReturn(0);
335       }
336     }
337     ierr = PetscNew(&image);CHKERRQ(ierr);
338     oimage->next = image;
339   } else {
340     ierr = PetscRegisterFinalize(PetscImageListDestroy);CHKERRQ(ierr);
341     ierr = PetscNew(&image);CHKERRQ(ierr);
342     SAWs_images = image;
343   }
344   ierr = PetscStrallocpy(filename,&image->filename);CHKERRQ(ierr);
345   ierr = PetscStrallocpy(ext,&image->ext);CHKERRQ(ierr);
346   image->count = count;
347   PetscFunctionReturn(0);
348 }
349 
350 #undef __FUNCT__
351 #define __FUNCT__ "PetscDrawSave_SAWs"
352 static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
353 {
354   PetscImageList image;
355   char           body[4096];
356   size_t         len = 0;
357   PetscErrorCode ierr;
358 
359   PetscFunctionBegin;
360   if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
361   ierr = PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);CHKERRQ(ierr);
362   image = SAWs_images;
363   while (image) {
364     const char *name = image->filename;
365     const char *ext  = image->ext;
366     if (draw->savesinglefile) {
367       ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);CHKERRQ(ierr);
368     } else {
369       ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);CHKERRQ(ierr);
370     }
371     ierr = PetscStrlen(body,&len);CHKERRQ(ierr);
372     image = image->next;
373   }
374   ierr = PetscStrcat(body,"<br>\n");CHKERRQ(ierr);
375   if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
376   PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
377   PetscFunctionReturn(0);
378 }
379 
380 #endif
381