xref: /petsc/src/sys/classes/draw/interface/dsave.c (revision 8067a7d5d1c29607366ed2aff819d529007817c0)
15b399a63SLisandro Dalcin #include <petsc/private/drawimpl.h>  /*I "petscdraw.h" I*/
25b399a63SLisandro Dalcin 
3*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageSave(const char[],const char[],unsigned char[][3],unsigned int,unsigned int,const unsigned char[]);
4*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawImageCheckFormat(const char *[]);
5*8067a7d5SLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscDrawMovieCheckFormat(const char *[]);
6*8067a7d5SLisandro Dalcin 
7*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
8*8067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawSave_SAWs(PetscDraw);
9*8067a7d5SLisandro Dalcin #endif
10*8067a7d5SLisandro Dalcin 
115b399a63SLisandro Dalcin #undef __FUNCT__
125b399a63SLisandro Dalcin #define __FUNCT__ "PetscDrawSetSave"
135b399a63SLisandro Dalcin /*@C
14*8067a7d5SLisandro Dalcin    PetscDrawSetSave - Saves images produced in a PetscDraw into a file
155b399a63SLisandro Dalcin 
165b399a63SLisandro Dalcin    Collective on PetscDraw
175b399a63SLisandro Dalcin 
185b399a63SLisandro Dalcin    Input Parameter:
195b399a63SLisandro Dalcin +  draw      - the graphics context
20*8067a7d5SLisandro Dalcin .  filename  - name of the file, if .ext then uses name of draw object plus .ext using .ext to determine the image type
21*8067a7d5SLisandro Dalcin -  movieext  - if not NULL, produces a movie of all the images
225b399a63SLisandro Dalcin 
235b399a63SLisandro Dalcin    Options Database Command:
24*8067a7d5SLisandro Dalcin +  -draw_save  <filename>  - filename could be name.ext or .ext (where .ext determines the type of graphics file to save, for example .png)
25*8067a7d5SLisandro Dalcin .  -draw_save_movie <.ext> - saves a movie to filename.ext
26*8067a7d5SLisandro Dalcin .  -draw_save_final_image [optional filename] - saves the final image displayed in a window
27*8067a7d5SLisandro Dalcin -  -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
285b399a63SLisandro Dalcin 
295b399a63SLisandro Dalcin    Level: intermediate
305b399a63SLisandro Dalcin 
315b399a63SLisandro Dalcin    Concepts: X windows^graphics
325b399a63SLisandro Dalcin 
33*8067a7d5SLisandro Dalcin    Notes: You should call this BEFORE creating your image and calling PetscDrawSave().
34*8067a7d5SLisandro Dalcin    The supported image types are .png, .gif, .jpg, and .ppm (PETSc chooses the default in that order).
35*8067a7d5SLisandro Dalcin    Support for .png images requires configure --with-libpng.
36*8067a7d5SLisandro Dalcin    Support for .gif images requires configure --with-giflib.
37*8067a7d5SLisandro Dalcin    Support for .jpg images requires configure --with-libjpeg.
38*8067a7d5SLisandro Dalcin    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
3971ed57bfSLisandro Dalcin    The ffmpeg utility must be in your path to make the movie.
405b399a63SLisandro Dalcin 
415b399a63SLisandro Dalcin .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSaveFinalImage()
425b399a63SLisandro Dalcin @*/
43*8067a7d5SLisandro Dalcin PetscErrorCode  PetscDrawSetSave(PetscDraw draw,const char filename[],const char movieext[])
445b399a63SLisandro Dalcin {
45*8067a7d5SLisandro Dalcin   const char     *savename = NULL;
46*8067a7d5SLisandro Dalcin   const char     *imageext = NULL;
4771ed57bfSLisandro Dalcin   char           buf[PETSC_MAX_PATH_LEN];
485b399a63SLisandro Dalcin   PetscErrorCode ierr;
495b399a63SLisandro Dalcin 
505b399a63SLisandro Dalcin   PetscFunctionBegin;
515b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
5271ed57bfSLisandro Dalcin   if (filename) PetscValidCharPointer(filename,2);
53*8067a7d5SLisandro Dalcin   if (movieext) PetscValidCharPointer(movieext,2);
545b399a63SLisandro Dalcin 
55*8067a7d5SLisandro Dalcin   /* determine save filename and image extension */
565b399a63SLisandro Dalcin   if (filename && filename[0]) {
57*8067a7d5SLisandro Dalcin     ierr = PetscStrchr(filename,'.',(char **)&imageext);CHKERRQ(ierr);
58*8067a7d5SLisandro Dalcin     if (!imageext) savename = filename;
59*8067a7d5SLisandro Dalcin     else if (imageext != filename) {
6071ed57bfSLisandro Dalcin       size_t l1 = 0,l2 = 0;
615b399a63SLisandro Dalcin       ierr = PetscStrlen(filename,&l1);CHKERRQ(ierr);
62*8067a7d5SLisandro Dalcin       ierr = PetscStrlen(imageext,&l2);CHKERRQ(ierr);
6371ed57bfSLisandro Dalcin       ierr = PetscStrncpy(buf,filename,l1-l2+1);CHKERRQ(ierr);
64*8067a7d5SLisandro Dalcin       savename = buf;
655b399a63SLisandro Dalcin     }
6671ed57bfSLisandro Dalcin   }
6771ed57bfSLisandro Dalcin 
68*8067a7d5SLisandro Dalcin   if (!savename) {ierr = PetscObjectGetName((PetscObject)draw,&savename);CHKERRQ(ierr);}
69*8067a7d5SLisandro Dalcin   ierr = PetscDrawImageCheckFormat(&imageext);CHKERRQ(ierr);
70*8067a7d5SLisandro Dalcin   if (movieext) {ierr = PetscDrawMovieCheckFormat(&movieext);CHKERRQ(ierr);}
71*8067a7d5SLisandro Dalcin   if (movieext) draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */
7271ed57bfSLisandro Dalcin 
7371ed57bfSLisandro Dalcin   if (draw->savesinglefile) {
74*8067a7d5SLisandro Dalcin     ierr = PetscInfo2(NULL,"Will save image to file %s%s\n",savename,imageext);CHKERRQ(ierr);
7571ed57bfSLisandro Dalcin   } else {
76*8067a7d5SLisandro Dalcin     ierr = PetscInfo3(NULL,"Will save images to file %s/%s_%%d%s\n",savename,savename,imageext);CHKERRQ(ierr);
7771ed57bfSLisandro Dalcin   }
78*8067a7d5SLisandro Dalcin   if (movieext) {
79*8067a7d5SLisandro Dalcin     ierr = PetscInfo2(NULL,"Will save movie to file %s%s\n",savename,movieext);CHKERRQ(ierr);
8071ed57bfSLisandro Dalcin   }
81*8067a7d5SLisandro Dalcin 
82*8067a7d5SLisandro Dalcin   draw->savefilecount = 0;
83*8067a7d5SLisandro Dalcin   ierr = PetscFree(draw->savefilename);CHKERRQ(ierr);
84*8067a7d5SLisandro Dalcin   ierr = PetscFree(draw->saveimageext);CHKERRQ(ierr);
85*8067a7d5SLisandro Dalcin   ierr = PetscFree(draw->savemovieext);CHKERRQ(ierr);
86*8067a7d5SLisandro Dalcin   ierr = PetscStrallocpy(savename,&draw->savefilename);CHKERRQ(ierr);
87*8067a7d5SLisandro Dalcin   ierr = PetscStrallocpy(imageext,&draw->saveimageext);CHKERRQ(ierr);
88*8067a7d5SLisandro Dalcin   ierr = PetscStrallocpy(movieext,&draw->savemovieext);CHKERRQ(ierr);
895b399a63SLisandro Dalcin   PetscFunctionReturn(0);
905b399a63SLisandro Dalcin }
915b399a63SLisandro Dalcin 
925b399a63SLisandro Dalcin #undef __FUNCT__
935b399a63SLisandro Dalcin #define __FUNCT__ "PetscDrawSetSaveFinalImage"
945b399a63SLisandro Dalcin /*@C
95*8067a7d5SLisandro Dalcin    PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file
965b399a63SLisandro Dalcin 
975b399a63SLisandro Dalcin    Collective on PetscDraw
985b399a63SLisandro Dalcin 
995b399a63SLisandro Dalcin    Input Parameter:
1005b399a63SLisandro Dalcin +  draw      - the graphics context
101*8067a7d5SLisandro Dalcin -  filename  - name of the file, if NULL or empty uses name set with PetscDrawSetSave() or name of draw object
1025b399a63SLisandro Dalcin 
1035b399a63SLisandro Dalcin    Options Database Command:
104*8067a7d5SLisandro Dalcin .  -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)
1055b399a63SLisandro Dalcin 
1065b399a63SLisandro Dalcin    Level: intermediate
1075b399a63SLisandro Dalcin 
1085b399a63SLisandro Dalcin    Concepts: X windows^graphics
1095b399a63SLisandro Dalcin 
110*8067a7d5SLisandro Dalcin    Notes: You should call this BEFORE creating your image and calling PetscDrawSave().
111*8067a7d5SLisandro Dalcin    The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order).
112*8067a7d5SLisandro Dalcin    Support for .png images requires configure --with-libpng.
113*8067a7d5SLisandro Dalcin    Support for .gif images requires configure --with-giflib.
114*8067a7d5SLisandro Dalcin    Support for .jpg images requires configure --with-libjpeg.
115*8067a7d5SLisandro Dalcin    Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB).
1165b399a63SLisandro Dalcin 
1175b399a63SLisandro Dalcin .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSave()
1185b399a63SLisandro Dalcin @*/
119*8067a7d5SLisandro Dalcin PetscErrorCode  PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
1205b399a63SLisandro Dalcin {
121*8067a7d5SLisandro Dalcin   char           buf[PETSC_MAX_PATH_LEN];
1225b399a63SLisandro Dalcin   PetscErrorCode ierr;
1235b399a63SLisandro Dalcin 
1245b399a63SLisandro Dalcin   PetscFunctionBegin;
1255b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
126*8067a7d5SLisandro Dalcin   if (!filename || !filename[0]) {
127*8067a7d5SLisandro Dalcin     if (!draw->savefilename) {
128*8067a7d5SLisandro Dalcin       ierr = PetscObjectGetName((PetscObject)draw,&filename);CHKERRQ(ierr);
1295b399a63SLisandro Dalcin     } else {
130*8067a7d5SLisandro Dalcin       ierr = PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
131*8067a7d5SLisandro Dalcin       filename = buf;
1325b399a63SLisandro Dalcin     }
133*8067a7d5SLisandro Dalcin   }
134*8067a7d5SLisandro Dalcin   ierr = PetscFree(draw->savefinalfilename);CHKERRQ(ierr);
135*8067a7d5SLisandro Dalcin   ierr = PetscStrallocpy(filename,&draw->savefinalfilename);CHKERRQ(ierr);
1365b399a63SLisandro Dalcin   PetscFunctionReturn(0);
1375b399a63SLisandro Dalcin }
1385b399a63SLisandro Dalcin 
1395b399a63SLisandro Dalcin #undef __FUNCT__
1405b399a63SLisandro Dalcin #define __FUNCT__ "PetscDrawSave"
1415b399a63SLisandro Dalcin /*@
1425b399a63SLisandro Dalcin    PetscDrawSave - Saves a drawn image
1435b399a63SLisandro Dalcin 
1445b399a63SLisandro Dalcin    Collective on PetscDraw
1455b399a63SLisandro Dalcin 
1465b399a63SLisandro Dalcin    Input Parameters:
1475b399a63SLisandro Dalcin .  draw - the drawing context
1485b399a63SLisandro Dalcin 
1495b399a63SLisandro Dalcin    Level: advanced
1505b399a63SLisandro Dalcin 
1515b399a63SLisandro Dalcin    Notes: this is not normally called by the user, it is called by PetscDrawFlush() to save a sequence of images.
1525b399a63SLisandro Dalcin 
1535b399a63SLisandro Dalcin .seealso: PetscDrawSetSave()
1545b399a63SLisandro Dalcin 
1555b399a63SLisandro Dalcin @*/
1565b399a63SLisandro Dalcin PetscErrorCode  PetscDrawSave(PetscDraw draw)
1575b399a63SLisandro Dalcin {
158*8067a7d5SLisandro Dalcin   PetscInt       savecount;
159*8067a7d5SLisandro Dalcin   char           basename[PETSC_MAX_PATH_LEN];
160*8067a7d5SLisandro Dalcin   unsigned char  palette[256][3];
161*8067a7d5SLisandro Dalcin   unsigned int   w,h;
162*8067a7d5SLisandro Dalcin   unsigned char  *pixels = NULL;
163*8067a7d5SLisandro Dalcin   PetscMPIInt    rank;
1645b399a63SLisandro Dalcin   PetscErrorCode ierr;
1655b399a63SLisandro Dalcin 
1665b399a63SLisandro Dalcin   PetscFunctionBegin;
1675b399a63SLisandro Dalcin   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
168*8067a7d5SLisandro Dalcin   if (draw->ops->save) {ierr = (*draw->ops->save)(draw);CHKERRQ(ierr); goto finally;}
169*8067a7d5SLisandro Dalcin   if (!draw->savefilename) PetscFunctionReturn(0);
170*8067a7d5SLisandro Dalcin   if (!draw->ops->getimage) PetscFunctionReturn(0);
171*8067a7d5SLisandro Dalcin   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
172*8067a7d5SLisandro Dalcin 
173*8067a7d5SLisandro Dalcin   savecount = draw->savefilecount++;
174*8067a7d5SLisandro Dalcin 
175*8067a7d5SLisandro Dalcin   if (!rank && !savecount) {
176*8067a7d5SLisandro Dalcin     char path[PETSC_MAX_PATH_LEN];
177*8067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
178*8067a7d5SLisandro Dalcin       ierr = PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);CHKERRQ(ierr);
179*8067a7d5SLisandro Dalcin       (void)remove(path);
180*8067a7d5SLisandro Dalcin     } else {
181*8067a7d5SLisandro Dalcin       ierr = PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);CHKERRQ(ierr);
182*8067a7d5SLisandro Dalcin       ierr = PetscRMTree(path);CHKERRQ(ierr);
183*8067a7d5SLisandro Dalcin       ierr = PetscMkdir(path);CHKERRQ(ierr);
184*8067a7d5SLisandro Dalcin     }
185*8067a7d5SLisandro Dalcin     if (draw->savemovieext) {
186*8067a7d5SLisandro Dalcin       ierr = PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);CHKERRQ(ierr);
187*8067a7d5SLisandro Dalcin       (void)remove(path);
188*8067a7d5SLisandro Dalcin     }
189*8067a7d5SLisandro Dalcin   }
190*8067a7d5SLisandro Dalcin   if (draw->savesinglefile) {
191*8067a7d5SLisandro Dalcin     ierr = PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);CHKERRQ(ierr);
192*8067a7d5SLisandro Dalcin   } else {
193*8067a7d5SLisandro Dalcin     ierr = PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)savecount);CHKERRQ(ierr);
194*8067a7d5SLisandro Dalcin   }
195*8067a7d5SLisandro Dalcin 
196*8067a7d5SLisandro Dalcin   /* this call is collective, only the first process gets the image data */
197*8067a7d5SLisandro Dalcin   ierr = (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);CHKERRQ(ierr);
198*8067a7d5SLisandro Dalcin   /* only the first process handles the saving business */
199*8067a7d5SLisandro Dalcin   if (!rank) {ierr = PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels);CHKERRQ(ierr);}
200*8067a7d5SLisandro Dalcin   ierr = PetscFree(pixels);CHKERRQ(ierr);
201*8067a7d5SLisandro Dalcin   ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
202*8067a7d5SLisandro Dalcin 
203*8067a7d5SLisandro Dalcin finally:
204*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
205*8067a7d5SLisandro Dalcin   ierr = PetscDrawSave_SAWs(draw);CHKERRQ(ierr);
206*8067a7d5SLisandro Dalcin #endif
207*8067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
208*8067a7d5SLisandro Dalcin }
209*8067a7d5SLisandro Dalcin 
210*8067a7d5SLisandro Dalcin #if defined(PETSC_HAVE_SAWS)
211*8067a7d5SLisandro Dalcin #include <petscviewersaws.h>
212*8067a7d5SLisandro Dalcin /*
213*8067a7d5SLisandro Dalcin   The PetscImageList object and functions are used to maintain a list of file images
214*8067a7d5SLisandro Dalcin   that can be displayed by the SAWs webserver.
215*8067a7d5SLisandro Dalcin */
216*8067a7d5SLisandro Dalcin typedef struct _P_PetscImageList *PetscImageList;
217*8067a7d5SLisandro Dalcin struct _P_PetscImageList {
218*8067a7d5SLisandro Dalcin   PetscImageList next;
219*8067a7d5SLisandro Dalcin   char           *filename;
220*8067a7d5SLisandro Dalcin   char           *ext;
221*8067a7d5SLisandro Dalcin   PetscInt       count;
222*8067a7d5SLisandro Dalcin } ;
223*8067a7d5SLisandro Dalcin 
224*8067a7d5SLisandro Dalcin static PetscImageList SAWs_images = NULL;
225*8067a7d5SLisandro Dalcin 
226*8067a7d5SLisandro Dalcin #undef __FUNCT__
227*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscImageListDestroy"
228*8067a7d5SLisandro Dalcin static PetscErrorCode PetscImageListDestroy(void)
229*8067a7d5SLisandro Dalcin {
230*8067a7d5SLisandro Dalcin   PetscErrorCode ierr;
231*8067a7d5SLisandro Dalcin   PetscImageList image = SAWs_images;
232*8067a7d5SLisandro Dalcin 
233*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
234*8067a7d5SLisandro Dalcin   while (image) {
235*8067a7d5SLisandro Dalcin     PetscImageList next = image->next;
236*8067a7d5SLisandro Dalcin     ierr = PetscFree(image->filename);CHKERRQ(ierr);
237*8067a7d5SLisandro Dalcin     ierr = PetscFree(image->ext);CHKERRQ(ierr);
238*8067a7d5SLisandro Dalcin     ierr = PetscFree(image);CHKERRQ(ierr);
239*8067a7d5SLisandro Dalcin     image = next;
2405b399a63SLisandro Dalcin   }
2415b399a63SLisandro Dalcin   PetscFunctionReturn(0);
2425b399a63SLisandro Dalcin }
243*8067a7d5SLisandro Dalcin 
244*8067a7d5SLisandro Dalcin #undef __FUNCT__
245*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscImageListAdd"
246*8067a7d5SLisandro Dalcin static PetscErrorCode PetscImageListAdd(const char filename[],const char ext[],PetscInt count)
247*8067a7d5SLisandro Dalcin {
248*8067a7d5SLisandro Dalcin   PetscErrorCode  ierr;
249*8067a7d5SLisandro Dalcin   PetscImageList  image,oimage = SAWs_images;
250*8067a7d5SLisandro Dalcin   PetscBool       flg;
251*8067a7d5SLisandro Dalcin 
252*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
253*8067a7d5SLisandro Dalcin   if (oimage) {
254*8067a7d5SLisandro Dalcin     ierr = PetscStrcmp(filename,oimage->filename,&flg);CHKERRQ(ierr);
255*8067a7d5SLisandro Dalcin     if (flg) {
256*8067a7d5SLisandro Dalcin       oimage->count = count;
257*8067a7d5SLisandro Dalcin       PetscFunctionReturn(0);
258*8067a7d5SLisandro Dalcin     }
259*8067a7d5SLisandro Dalcin     while (oimage->next) {
260*8067a7d5SLisandro Dalcin       oimage = oimage->next;
261*8067a7d5SLisandro Dalcin       ierr = PetscStrcmp(filename,oimage->filename,&flg);CHKERRQ(ierr);
262*8067a7d5SLisandro Dalcin       if (flg) {
263*8067a7d5SLisandro Dalcin         oimage->count = count;
264*8067a7d5SLisandro Dalcin         PetscFunctionReturn(0);
265*8067a7d5SLisandro Dalcin       }
266*8067a7d5SLisandro Dalcin     }
267*8067a7d5SLisandro Dalcin     ierr = PetscNew(&image);CHKERRQ(ierr);
268*8067a7d5SLisandro Dalcin     oimage->next = image;
269*8067a7d5SLisandro Dalcin   } else {
270*8067a7d5SLisandro Dalcin     ierr = PetscRegisterFinalize(PetscImageListDestroy);CHKERRQ(ierr);
271*8067a7d5SLisandro Dalcin     ierr = PetscNew(&image);CHKERRQ(ierr);
272*8067a7d5SLisandro Dalcin     SAWs_images = image;
273*8067a7d5SLisandro Dalcin   }
274*8067a7d5SLisandro Dalcin   ierr = PetscStrallocpy(filename,&image->filename);CHKERRQ(ierr);
275*8067a7d5SLisandro Dalcin   ierr = PetscStrallocpy(ext,&image->ext);CHKERRQ(ierr);
276*8067a7d5SLisandro Dalcin   image->count = count;
277*8067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
278*8067a7d5SLisandro Dalcin }
279*8067a7d5SLisandro Dalcin 
280*8067a7d5SLisandro Dalcin #undef __FUNCT__
281*8067a7d5SLisandro Dalcin #define __FUNCT__ "PetscDrawSave_SAWs"
282*8067a7d5SLisandro Dalcin static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
283*8067a7d5SLisandro Dalcin {
284*8067a7d5SLisandro Dalcin   PetscImageList image;
285*8067a7d5SLisandro Dalcin   char           body[4096];
286*8067a7d5SLisandro Dalcin   size_t         len = 0;
287*8067a7d5SLisandro Dalcin   PetscErrorCode ierr;
288*8067a7d5SLisandro Dalcin 
289*8067a7d5SLisandro Dalcin   PetscFunctionBegin;
290*8067a7d5SLisandro Dalcin   if (!draw->savefilename) PetscFunctionReturn(0);
291*8067a7d5SLisandro Dalcin   ierr = PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);CHKERRQ(ierr);
292*8067a7d5SLisandro Dalcin   image = SAWs_images;
293*8067a7d5SLisandro Dalcin   while (image) {
294*8067a7d5SLisandro Dalcin     const char *name = image->filename;
295*8067a7d5SLisandro Dalcin     const char *ext  = image->ext;
296*8067a7d5SLisandro Dalcin     if (draw->savesinglefile) {
297*8067a7d5SLisandro Dalcin       ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);CHKERRQ(ierr);
298*8067a7d5SLisandro Dalcin     } else {
299*8067a7d5SLisandro Dalcin       ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);CHKERRQ(ierr);
300*8067a7d5SLisandro Dalcin     }
301*8067a7d5SLisandro Dalcin     ierr = PetscStrlen(body,&len);CHKERRQ(ierr);
302*8067a7d5SLisandro Dalcin     image = image->next;
303*8067a7d5SLisandro Dalcin   }
304*8067a7d5SLisandro Dalcin   ierr = PetscStrcat(body,"<br>\n");CHKERRQ(ierr);
305*8067a7d5SLisandro Dalcin   if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
306*8067a7d5SLisandro Dalcin   PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
307*8067a7d5SLisandro Dalcin   PetscFunctionReturn(0);
308*8067a7d5SLisandro Dalcin }
309*8067a7d5SLisandro Dalcin 
310*8067a7d5SLisandro Dalcin #endif
311