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