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