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