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 PetscDrawImageCheckFormat(const char *[]); 5 PETSC_EXTERN PetscErrorCode PetscDrawMovieCheckFormat(const char *[]); 6 7 #if defined(PETSC_HAVE_SAWS) 8 static PetscErrorCode PetscDrawSave_SAWs(PetscDraw); 9 #endif 10 11 #undef __FUNCT__ 12 #define __FUNCT__ "PetscDrawSetSave" 13 /*@C 14 PetscDrawSetSave - Saves images produced in a PetscDraw into a file 15 16 Collective on PetscDraw 17 18 Input Parameter: 19 + draw - the graphics context 20 . filename - name of the file, if .ext then uses name of draw object plus .ext using .ext to determine the image type 21 - movieext - if not NULL, produces a movie of all the images 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_movie <.ext> - saves a movie to filename.ext 26 . -draw_save_final_image [optional filename] - saves the final image displayed in a window 27 - -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 28 29 Level: intermediate 30 31 Concepts: X windows^graphics 32 33 Notes: You should call this BEFORE creating your image and calling PetscDrawSave(). 34 The supported image types are .png, .gif, .jpg, and .ppm (PETSc chooses the default in that order). 35 Support for .png images requires configure --with-libpng. 36 Support for .gif images requires configure --with-giflib. 37 Support for .jpg images requires configure --with-libjpeg. 38 Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB). 39 The ffmpeg utility must be in your path to make the movie. 40 41 .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSaveFinalImage() 42 @*/ 43 PetscErrorCode PetscDrawSetSave(PetscDraw draw,const char filename[],const char movieext[]) 44 { 45 const char *savename = NULL; 46 const char *imageext = NULL; 47 char buf[PETSC_MAX_PATH_LEN]; 48 PetscErrorCode ierr; 49 50 PetscFunctionBegin; 51 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 52 if (filename) PetscValidCharPointer(filename,2); 53 if (movieext) PetscValidCharPointer(movieext,2); 54 55 /* determine save filename and image extension */ 56 if (filename && filename[0]) { 57 ierr = PetscStrchr(filename,'.',(char **)&imageext);CHKERRQ(ierr); 58 if (!imageext) savename = filename; 59 else if (imageext != filename) { 60 size_t l1 = 0,l2 = 0; 61 ierr = PetscStrlen(filename,&l1);CHKERRQ(ierr); 62 ierr = PetscStrlen(imageext,&l2);CHKERRQ(ierr); 63 ierr = PetscStrncpy(buf,filename,l1-l2+1);CHKERRQ(ierr); 64 savename = buf; 65 } 66 } 67 68 if (!savename) {ierr = PetscObjectGetName((PetscObject)draw,&savename);CHKERRQ(ierr);} 69 ierr = PetscDrawImageCheckFormat(&imageext);CHKERRQ(ierr); 70 if (movieext) {ierr = PetscDrawMovieCheckFormat(&movieext);CHKERRQ(ierr);} 71 if (movieext) draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */ 72 73 if (draw->savesinglefile) { 74 ierr = PetscInfo2(NULL,"Will save image to file %s%s\n",savename,imageext);CHKERRQ(ierr); 75 } else { 76 ierr = PetscInfo3(NULL,"Will save images to file %s/%s_%%d%s\n",savename,savename,imageext);CHKERRQ(ierr); 77 } 78 if (movieext) { 79 ierr = PetscInfo2(NULL,"Will save movie to file %s%s\n",savename,movieext);CHKERRQ(ierr); 80 } 81 82 draw->savefilecount = 0; 83 ierr = PetscFree(draw->savefilename);CHKERRQ(ierr); 84 ierr = PetscFree(draw->saveimageext);CHKERRQ(ierr); 85 ierr = PetscFree(draw->savemovieext);CHKERRQ(ierr); 86 ierr = PetscStrallocpy(savename,&draw->savefilename);CHKERRQ(ierr); 87 ierr = PetscStrallocpy(imageext,&draw->saveimageext);CHKERRQ(ierr); 88 ierr = PetscStrallocpy(movieext,&draw->savemovieext);CHKERRQ(ierr); 89 PetscFunctionReturn(0); 90 } 91 92 #undef __FUNCT__ 93 #define __FUNCT__ "PetscDrawSetSaveFinalImage" 94 /*@C 95 PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file 96 97 Collective on PetscDraw 98 99 Input Parameter: 100 + draw - the graphics context 101 - filename - name of the file, if NULL or empty uses name set with PetscDrawSetSave() or name of draw object 102 103 Options Database Command: 104 . -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) 105 106 Level: intermediate 107 108 Concepts: X windows^graphics 109 110 Notes: You should call this BEFORE creating your image and calling PetscDrawSave(). 111 The supported image types are .png, .gif, and .ppm (PETSc chooses the default in that order). 112 Support for .png images requires configure --with-libpng. 113 Support for .gif images requires configure --with-giflib. 114 Support for .jpg images requires configure --with-libjpeg. 115 Support for .ppm images is built-in. The PPM format has no compression (640x480 pixels ~ 900 KiB). 116 117 .seealso: PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy(), PetscDrawSetSave() 118 @*/ 119 PetscErrorCode PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[]) 120 { 121 char buf[PETSC_MAX_PATH_LEN]; 122 PetscErrorCode ierr; 123 124 PetscFunctionBegin; 125 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 126 if (!filename || !filename[0]) { 127 if (!draw->savefilename) { 128 ierr = PetscObjectGetName((PetscObject)draw,&filename);CHKERRQ(ierr); 129 } else { 130 ierr = PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);CHKERRQ(ierr); 131 filename = buf; 132 } 133 } 134 ierr = PetscFree(draw->savefinalfilename);CHKERRQ(ierr); 135 ierr = PetscStrallocpy(filename,&draw->savefinalfilename);CHKERRQ(ierr); 136 PetscFunctionReturn(0); 137 } 138 139 #undef __FUNCT__ 140 #define __FUNCT__ "PetscDrawSave" 141 /*@ 142 PetscDrawSave - Saves a drawn image 143 144 Collective on PetscDraw 145 146 Input Parameters: 147 . draw - the drawing context 148 149 Level: advanced 150 151 Notes: this is not normally called by the user, it is called by PetscDrawFlush() to save a sequence of images. 152 153 .seealso: PetscDrawSetSave() 154 155 @*/ 156 PetscErrorCode PetscDrawSave(PetscDraw draw) 157 { 158 PetscInt savecount; 159 char basename[PETSC_MAX_PATH_LEN]; 160 unsigned char palette[256][3]; 161 unsigned int w,h; 162 unsigned char *pixels = NULL; 163 PetscMPIInt rank; 164 PetscErrorCode ierr; 165 166 PetscFunctionBegin; 167 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 168 if (draw->ops->save) {ierr = (*draw->ops->save)(draw);CHKERRQ(ierr); goto finally;} 169 if (!draw->savefilename) PetscFunctionReturn(0); 170 if (!draw->ops->getimage) PetscFunctionReturn(0); 171 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); 172 173 savecount = draw->savefilecount++; 174 175 if (!rank && !savecount) { 176 char path[PETSC_MAX_PATH_LEN]; 177 if (draw->savesinglefile) { 178 ierr = PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);CHKERRQ(ierr); 179 (void)remove(path); 180 } else { 181 ierr = PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);CHKERRQ(ierr); 182 ierr = PetscRMTree(path);CHKERRQ(ierr); 183 ierr = PetscMkdir(path);CHKERRQ(ierr); 184 } 185 if (draw->savemovieext) { 186 ierr = PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);CHKERRQ(ierr); 187 (void)remove(path); 188 } 189 } 190 if (draw->savesinglefile) { 191 ierr = PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);CHKERRQ(ierr); 192 } else { 193 ierr = PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)savecount);CHKERRQ(ierr); 194 } 195 196 /* this call is collective, only the first process gets the image data */ 197 ierr = (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);CHKERRQ(ierr); 198 /* only the first process handles the saving business */ 199 if (!rank) {ierr = PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels);CHKERRQ(ierr);} 200 ierr = PetscFree(pixels);CHKERRQ(ierr); 201 ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr); 202 203 finally: 204 #if defined(PETSC_HAVE_SAWS) 205 ierr = PetscDrawSave_SAWs(draw);CHKERRQ(ierr); 206 #endif 207 PetscFunctionReturn(0); 208 } 209 210 #if defined(PETSC_HAVE_SAWS) 211 #include <petscviewersaws.h> 212 /* 213 The PetscImageList object and functions are used to maintain a list of file images 214 that can be displayed by the SAWs webserver. 215 */ 216 typedef struct _P_PetscImageList *PetscImageList; 217 struct _P_PetscImageList { 218 PetscImageList next; 219 char *filename; 220 char *ext; 221 PetscInt count; 222 } ; 223 224 static PetscImageList SAWs_images = NULL; 225 226 #undef __FUNCT__ 227 #define __FUNCT__ "PetscImageListDestroy" 228 static PetscErrorCode PetscImageListDestroy(void) 229 { 230 PetscErrorCode ierr; 231 PetscImageList image = SAWs_images; 232 233 PetscFunctionBegin; 234 while (image) { 235 PetscImageList next = image->next; 236 ierr = PetscFree(image->filename);CHKERRQ(ierr); 237 ierr = PetscFree(image->ext);CHKERRQ(ierr); 238 ierr = PetscFree(image);CHKERRQ(ierr); 239 image = next; 240 } 241 PetscFunctionReturn(0); 242 } 243 244 #undef __FUNCT__ 245 #define __FUNCT__ "PetscImageListAdd" 246 static PetscErrorCode PetscImageListAdd(const char filename[],const char ext[],PetscInt count) 247 { 248 PetscErrorCode ierr; 249 PetscImageList image,oimage = SAWs_images; 250 PetscBool flg; 251 252 PetscFunctionBegin; 253 if (oimage) { 254 ierr = PetscStrcmp(filename,oimage->filename,&flg);CHKERRQ(ierr); 255 if (flg) { 256 oimage->count = count; 257 PetscFunctionReturn(0); 258 } 259 while (oimage->next) { 260 oimage = oimage->next; 261 ierr = PetscStrcmp(filename,oimage->filename,&flg);CHKERRQ(ierr); 262 if (flg) { 263 oimage->count = count; 264 PetscFunctionReturn(0); 265 } 266 } 267 ierr = PetscNew(&image);CHKERRQ(ierr); 268 oimage->next = image; 269 } else { 270 ierr = PetscRegisterFinalize(PetscImageListDestroy);CHKERRQ(ierr); 271 ierr = PetscNew(&image);CHKERRQ(ierr); 272 SAWs_images = image; 273 } 274 ierr = PetscStrallocpy(filename,&image->filename);CHKERRQ(ierr); 275 ierr = PetscStrallocpy(ext,&image->ext);CHKERRQ(ierr); 276 image->count = count; 277 PetscFunctionReturn(0); 278 } 279 280 #undef __FUNCT__ 281 #define __FUNCT__ "PetscDrawSave_SAWs" 282 static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw) 283 { 284 PetscImageList image; 285 char body[4096]; 286 size_t len = 0; 287 PetscErrorCode ierr; 288 289 PetscFunctionBegin; 290 if (!draw->savefilename) PetscFunctionReturn(0); 291 ierr = PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);CHKERRQ(ierr); 292 image = SAWs_images; 293 while (image) { 294 const char *name = image->filename; 295 const char *ext = image->ext; 296 if (draw->savesinglefile) { 297 ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);CHKERRQ(ierr); 298 } else { 299 ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);CHKERRQ(ierr); 300 } 301 ierr = PetscStrlen(body,&len);CHKERRQ(ierr); 302 image = image->next; 303 } 304 ierr = PetscStrcat(body,"<br>\n");CHKERRQ(ierr); 305 if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1)); 306 PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body)); 307 PetscFunctionReturn(0); 308 } 309 310 #endif 311