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