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 /*@C
13 PetscDrawSetSave - Saves images produced in a PetscDraw into a file
14
15 Collective on PetscDraw
16
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
20
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
25
26 Level: intermediate
27
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).
35
36 .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSaveFinalImage()
37 @*/
PetscDrawSetSave(PetscDraw draw,const char filename[])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];
43 PetscErrorCode ierr;
44
45 PetscFunctionBegin;
46 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
47 if (filename) PetscValidCharPointer(filename,2);
48
49 /* determine save filename and image extension */
50 if (filename && filename[0]) {
51 ierr = PetscStrchr(filename,'.',(char **)&imageext);CHKERRQ(ierr);
52 if (!imageext) savename = filename;
53 else if (imageext != filename) {
54 size_t l1 = 0,l2 = 0;
55 ierr = PetscStrlen(filename,&l1);CHKERRQ(ierr);
56 ierr = PetscStrlen(imageext,&l2);CHKERRQ(ierr);
57 ierr = PetscStrncpy(buf,filename,l1-l2+1);CHKERRQ(ierr);
58 savename = buf;
59 }
60 }
61
62 if (!savename) {ierr = PetscObjectGetName((PetscObject)draw,&savename);CHKERRQ(ierr);}
63 ierr = PetscDrawImageCheckFormat(&imageext);CHKERRQ(ierr);
64
65 draw->savefilecount = 0;
66 ierr = PetscFree(draw->savefilename);CHKERRQ(ierr);
67 ierr = PetscFree(draw->saveimageext);CHKERRQ(ierr);
68 ierr = PetscStrallocpy(savename,&draw->savefilename);CHKERRQ(ierr);
69 ierr = PetscStrallocpy(imageext,&draw->saveimageext);CHKERRQ(ierr);
70
71 if (draw->savesinglefile) {
72 ierr = PetscInfo2(NULL,"Will save image to file %s%s\n",draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
73 } else {
74 ierr = PetscInfo3(NULL,"Will save images to file %s/%s_%%d%s\n",draw->savefilename,draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
75 }
76 PetscFunctionReturn(0);
77 }
78
79 /*@C
80 PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file
81
82 Collective on PetscDraw
83
84 Input Parameter:
85 + draw - the graphics context
86 - movieext - optional extension defining the movie format
87
88 Options Database Command:
89 . -draw_save_movie <.ext> - saves a movie with extension .ext
90
91 Level: intermediate
92
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.
96
97 .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
98 @*/
PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])99 PetscErrorCode PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])
100 {
101
102 PetscErrorCode ierr;
103
104 PetscFunctionBegin;
105 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
106 if (movieext) PetscValidCharPointer(movieext,2);
107
108 if (!draw->savefilename) {ierr = PetscDrawSetSave(draw,"");CHKERRQ(ierr);}
109 ierr = PetscDrawMovieCheckFormat(&movieext);CHKERRQ(ierr);
110 ierr = PetscStrallocpy(movieext,&draw->savemovieext);CHKERRQ(ierr);
111 draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
112
113 ierr = PetscInfo2(NULL,"Will save movie to file %s%s\n",draw->savefilename,draw->savemovieext);CHKERRQ(ierr);
114 PetscFunctionReturn(0);
115 }
116
117 /*@C
118 PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file
119
120 Collective on PetscDraw
121
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
125
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)
128
129 Level: intermediate
130
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).
138
139 .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
140 @*/
PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])141 PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
142 {
143 char buf[PETSC_MAX_PATH_LEN];
144 PetscErrorCode ierr;
145
146 PetscFunctionBegin;
147 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
148 if (!filename || !filename[0]) {
149 if (!draw->savefilename) {
150 ierr = PetscObjectGetName((PetscObject)draw,&filename);CHKERRQ(ierr);
151 } else {
152 ierr = PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
153 filename = buf;
154 }
155 }
156 ierr = PetscFree(draw->savefinalfilename);CHKERRQ(ierr);
157 ierr = PetscStrallocpy(filename,&draw->savefinalfilename);CHKERRQ(ierr);
158 PetscFunctionReturn(0);
159 }
160
161 /*@
162 PetscDrawSave - Saves a drawn image
163
164 Collective on PetscDraw
165
166 Input Parameters:
167 . draw - the drawing context
168
169 Level: advanced
170
171 Notes:
172 this is not normally called by the user.
173
174 .seealso: PetscDrawSetSave()
175
176 @*/
PetscDrawSave(PetscDraw draw)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;
185 PetscErrorCode ierr;
186
187 PetscFunctionBegin;
188 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
189 if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
190 if (draw->ops->save) {ierr = (*draw->ops->save)(draw);CHKERRQ(ierr); goto finally;}
191 if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
192 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
193
194 saveindex = draw->savefilecount++;
195
196 if (!rank && !saveindex) {
197 char path[PETSC_MAX_PATH_LEN];
198 if (draw->savesinglefile) {
199 ierr = PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
200 (void)remove(path);
201 } else {
202 ierr = PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);CHKERRQ(ierr);
203 ierr = PetscRMTree(path);CHKERRQ(ierr);
204 ierr = PetscMkdir(path);CHKERRQ(ierr);
205 }
206 if (draw->savemovieext) {
207 ierr = PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);CHKERRQ(ierr);
208 (void)remove(path);
209 }
210 }
211 if (draw->savesinglefile) {
212 ierr = PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);CHKERRQ(ierr);
213 } else {
214 ierr = PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)saveindex);CHKERRQ(ierr);
215 }
216
217 /* this call is collective, only the first process gets the image data */
218 ierr = (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);CHKERRQ(ierr);
219 /* only the first process handles the saving business */
220 if (!rank) {ierr = PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels);CHKERRQ(ierr);}
221 ierr = PetscFree(pixels);CHKERRQ(ierr);
222 ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
223
224 finally:
225 #if defined(PETSC_HAVE_SAWS)
226 ierr = PetscDrawSave_SAWs(draw);CHKERRQ(ierr);
227 #endif
228 PetscFunctionReturn(0);
229 }
230
231 /*@
232 PetscDrawSaveMovie - Saves a movie from previously saved images
233
234 Collective on PetscDraw
235
236 Input Parameters:
237 . draw - the drawing context
238
239 Level: advanced
240
241 Notes:
242 this is not normally called by the user.
243 The ffmpeg utility must be in your path to make the movie.
244
245 .seealso: PetscDrawSetSave(), PetscDrawSetSaveMovie()
246
247 @*/
PetscDrawSaveMovie(PetscDraw draw)248 PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
249 {
250 PetscMPIInt rank;
251 PetscErrorCode ierr;
252
253 PetscFunctionBegin;
254 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
255 if (!draw->ops->save && !draw->ops->getimage) PetscFunctionReturn(0);
256 if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) PetscFunctionReturn(0);
257 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
258 {
259 const char *fname = draw->savefilename;
260 const char *imext = draw->saveimageext;
261 const char *mvext = draw->savemovieext;
262 if (!rank) {ierr = PetscDrawMovieSave(fname,draw->savefilecount,imext,draw->savemoviefps,mvext);CHKERRQ(ierr);}
263 ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
264 }
265 PetscFunctionReturn(0);
266 }
267
268
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 } ;
282
283 static PetscImageList SAWs_images = NULL;
284
PetscImageListDestroy(void)285 static PetscErrorCode PetscImageListDestroy(void)
286 {
287 PetscErrorCode ierr;
288 PetscImageList image = SAWs_images;
289
290 PetscFunctionBegin;
291 while (image) {
292 PetscImageList next = image->next;
293 ierr = PetscFree(image->filename);CHKERRQ(ierr);
294 ierr = PetscFree(image->ext);CHKERRQ(ierr);
295 ierr = PetscFree(image);CHKERRQ(ierr);
296 image = next;
297 }
298 PetscFunctionReturn(0);
299 }
300
PetscImageListAdd(const char filename[],const char ext[],PetscInt count)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;
306
307 PetscFunctionBegin;
308 if (oimage) {
309 ierr = PetscStrcmp(filename,oimage->filename,&flg);CHKERRQ(ierr);
310 if (flg) {
311 oimage->count = count;
312 PetscFunctionReturn(0);
313 }
314 while (oimage->next) {
315 oimage = oimage->next;
316 ierr = PetscStrcmp(filename,oimage->filename,&flg);CHKERRQ(ierr);
317 if (flg) {
318 oimage->count = count;
319 PetscFunctionReturn(0);
320 }
321 }
322 ierr = PetscNew(&image);CHKERRQ(ierr);
323 oimage->next = image;
324 } else {
325 ierr = PetscRegisterFinalize(PetscImageListDestroy);CHKERRQ(ierr);
326 ierr = PetscNew(&image);CHKERRQ(ierr);
327 SAWs_images = image;
328 }
329 ierr = PetscStrallocpy(filename,&image->filename);CHKERRQ(ierr);
330 ierr = PetscStrallocpy(ext,&image->ext);CHKERRQ(ierr);
331 image->count = count;
332 PetscFunctionReturn(0);
333 }
334
PetscDrawSave_SAWs(PetscDraw draw)335 static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
336 {
337 PetscImageList image;
338 char body[4096];
339 size_t len = 0;
340 PetscErrorCode ierr;
341
342 PetscFunctionBegin;
343 if (!draw->savefilename || !draw->saveimageext) PetscFunctionReturn(0);
344 ierr = PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);CHKERRQ(ierr);
345 image = SAWs_images;
346 while (image) {
347 const char *name = image->filename;
348 const char *ext = image->ext;
349 if (draw->savesinglefile) {
350 ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);CHKERRQ(ierr);
351 } else {
352 ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);CHKERRQ(ierr);
353 }
354 ierr = PetscStrlen(body,&len);CHKERRQ(ierr);
355 image = image->next;
356 }
357 ierr = PetscStrlcat(body,"<br>\n",sizeof(body));CHKERRQ(ierr);
358 if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
359 PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
360 PetscFunctionReturn(0);
361 }
362
363 #endif
364