Date: 2022-03-04T17:37:01+00:00

Actual source code: dsave.c

      1: #include <petsc/private/drawimpl.h>

      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 *[]);

      8: #if defined(PETSC_HAVE_SAWS)
      9: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw);
     10: #endif

     12: /*@C
     13:    PetscDrawSetSave - Saves images produced in a PetscDraw into a file

     15:    Collective on PetscDraw

     17:    Input Parameters:
     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

     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

     26:    Level: intermediate

     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).

     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];

     49:   /* determine save filename and image extension */
     50:   if (filename && filename[0]) {
     51:     PetscStrchr(filename,'.',(char **)&imageext);
     52:     if (!imageext) savename = filename;
     53:     else if (imageext != filename) {
     54:       size_t l1 = 0,l2 = 0;
     55:       PetscStrlen(filename,&l1);
     56:       PetscStrlen(imageext,&l2);
     57:       PetscStrncpy(buf,filename,l1-l2+1);
     58:       savename = buf;
     59:     }
     60:   }

     62:   if (!savename) {PetscObjectGetName((PetscObject)draw,&savename);}
     63:   PetscDrawImageCheckFormat(&imageext);

     65:   draw->savefilecount = 0;
     66:   PetscFree(draw->savefilename);
     67:   PetscFree(draw->saveimageext);
     68:   PetscStrallocpy(savename,&draw->savefilename);
     69:   PetscStrallocpy(imageext,&draw->saveimageext);

     71:   if (draw->savesinglefile) {
     72:     PetscInfo2(NULL,"Will save image to file %s%s\n",draw->savefilename,draw->saveimageext);
     73:   } else {
     74:     PetscInfo3(NULL,"Will save images to file %s/%s_%%d%s\n",draw->savefilename,draw->savefilename,draw->saveimageext);
     75:   }
     76:   return(0);
     77: }

     79: /*@C
     80:    PetscDrawSetSaveMovie - Saves a movie produced from a PetscDraw into a file

     82:    Collective on PetscDraw

     84:    Input Parameters:
     85: +  draw      - the graphics context
     86: -  movieext  - optional extension defining the movie format

     88:    Options Database Command:
     89: .  -draw_save_movie <.ext> - saves a movie with extension .ext

     91:    Level: intermediate

     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.

     97: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
     98: @*/
     99: PetscErrorCode  PetscDrawSetSaveMovie(PetscDraw draw,const char movieext[])
    100: {

    108:   if (!draw->savefilename) {PetscDrawSetSave(draw,"");}
    109:   PetscDrawMovieCheckFormat(&movieext);
    110:   PetscStrallocpy(movieext,&draw->savemovieext);
    111:   draw->savesinglefile = PETSC_FALSE; /* otherwise we cannot generage movies */

    113:   PetscInfo2(NULL,"Will save movie to file %s%s\n",draw->savefilename,draw->savemovieext);
    114:   return(0);
    115: }

    117: /*@C
    118:    PetscDrawSetSaveFinalImage - Saves the final image produced in a PetscDraw into a file

    120:    Collective on PetscDraw

    122:    Input Parameters:
    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

    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)

    129:    Level: intermediate

    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).

    139: .seealso: PetscDrawSetSave(), PetscDrawSetFromOptions(), PetscDrawCreate(), PetscDrawDestroy()
    140: @*/
    141: PetscErrorCode  PetscDrawSetSaveFinalImage(PetscDraw draw,const char filename[])
    142: {
    143:   char           buf[PETSC_MAX_PATH_LEN];

    148:   if (!filename || !filename[0]) {
    149:     if (!draw->savefilename) {
    150:       PetscObjectGetName((PetscObject)draw,&filename);
    151:     } else {
    152:       PetscSNPrintf(buf,sizeof(buf),"%s%s",draw->savefilename,draw->saveimageext);
    153:       filename = buf;
    154:     }
    155:   }
    156:   PetscFree(draw->savefinalfilename);
    157:   PetscStrallocpy(filename,&draw->savefinalfilename);
    158:   return(0);
    159: }

    161: /*@
    162:    PetscDrawSave - Saves a drawn image

    164:    Collective on PetscDraw

    166:    Input Parameters:
    167: .  draw - the drawing context

    169:    Level: advanced

    171:    Notes:
    172:     this is not normally called by the user.

    174: .seealso: PetscDrawSetSave()

    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;

    189:   if (!draw->ops->save && !draw->ops->getimage) return(0);
    190:   if (draw->ops->save) {(*draw->ops->save)(draw); goto finally;}
    191:   if (!draw->savefilename || !draw->saveimageext) return(0);
    192:   MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);

    194:   saveindex = draw->savefilecount++;

    196:   if (rank == 0 && !saveindex) {
    197:     char path[PETSC_MAX_PATH_LEN];
    198:     if (draw->savesinglefile) {
    199:       PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->saveimageext);
    200:       (void)remove(path);
    201:     } else {
    202:       PetscSNPrintf(path,sizeof(path),"%s",draw->savefilename);
    203:       PetscRMTree(path);
    204:       PetscMkdir(path);
    205:     }
    206:     if (draw->savemovieext) {
    207:       PetscSNPrintf(path,sizeof(path),"%s%s",draw->savefilename,draw->savemovieext);
    208:       (void)remove(path);
    209:     }
    210:   }
    211:   if (draw->savesinglefile) {
    212:     PetscSNPrintf(basename,sizeof(basename),"%s",draw->savefilename);
    213:   } else {
    214:     char *basefilename;

    216:     PetscStrrchr(draw->savefilename, '/', (char **) &basefilename);
    217:     if (basefilename != draw->savefilename) {
    218:       PetscSNPrintf(basename,sizeof(basename),"%s_%d",draw->savefilename,(int)saveindex);
    219:     } else {
    220:       PetscSNPrintf(basename,sizeof(basename),"%s/%s_%d",draw->savefilename,draw->savefilename,(int)saveindex);
    221:     }
    222:   }

    224:   /* this call is collective, only the first process gets the image data */
    225:   (*draw->ops->getimage)(draw,palette,&w,&h,&pixels);
    226:   /* only the first process handles the saving business */
    227:   if (rank == 0) {PetscDrawImageSave(basename,draw->saveimageext,palette,w,h,pixels);}
    228:   PetscFree(pixels);
    229:   MPI_Barrier(PetscObjectComm((PetscObject)draw));

    231: finally:
    232: #if defined(PETSC_HAVE_SAWS)
    233:   PetscDrawSave_SAWs(draw);
    234: #endif
    235:   return(0);
    236: }

    238: /*@
    239:    PetscDrawSaveMovie - Saves a movie from previously saved images

    241:    Collective on PetscDraw

    243:    Input Parameters:
    244: .  draw - the drawing context

    246:    Level: advanced

    248:    Notes:
    249:     this is not normally called by the user.
    250:    The ffmpeg utility must be in your path to make the movie.

    252: .seealso: PetscDrawSetSave(), PetscDrawSetSaveMovie()

    254: @*/
    255: PetscErrorCode PetscDrawSaveMovie(PetscDraw draw)
    256: {
    257:   PetscMPIInt    rank;

    262:   if (!draw->ops->save && !draw->ops->getimage) return(0);
    263:   if (!draw->savefilename || !draw->savemovieext || draw->savesinglefile) return(0);
    264:   MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);
    265:   {
    266:     const char *fname = draw->savefilename;
    267:     const char *imext = draw->saveimageext;
    268:     const char *mvext = draw->savemovieext;
    269:     if (rank == 0) {PetscDrawMovieSave(fname,draw->savefilecount,imext,draw->savemoviefps,mvext);}
    270:     MPI_Barrier(PetscObjectComm((PetscObject)draw));
    271:   }
    272:   return(0);
    273: }

    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: } ;

    289: static PetscImageList SAWs_images = NULL;

    291: static PetscErrorCode PetscImageListDestroy(void)
    292: {
    294:   PetscImageList image = SAWs_images;

    297:   while (image) {
    298:     PetscImageList next = image->next;
    299:     PetscFree(image->filename);
    300:     PetscFree(image->ext);
    301:     PetscFree(image);
    302:     image = next;
    303:   }
    304:   return(0);
    305: }

    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;

    314:   if (oimage) {
    315:     PetscStrcmp(filename,oimage->filename,&flg);
    316:     if (flg) {
    317:       oimage->count = count;
    318:       return(0);
    319:     }
    320:     while (oimage->next) {
    321:       oimage = oimage->next;
    322:       PetscStrcmp(filename,oimage->filename,&flg);
    323:       if (flg) {
    324:         oimage->count = count;
    325:         return(0);
    326:       }
    327:     }
    328:     PetscNew(&image);
    329:     oimage->next = image;
    330:   } else {
    331:     PetscRegisterFinalize(PetscImageListDestroy);
    332:     PetscNew(&image);
    333:     SAWs_images = image;
    334:   }
    335:   PetscStrallocpy(filename,&image->filename);
    336:   PetscStrallocpy(ext,&image->ext);
    337:   image->count = count;
    338:   return(0);
    339: }

    341: static PetscErrorCode PetscDrawSave_SAWs(PetscDraw draw)
    342: {
    343:   PetscImageList image;
    344:   char           body[4096];
    345:   size_t         len = 0;

    349:   if (!draw->savefilename || !draw->saveimageext) return(0);
    350:   PetscImageListAdd(draw->savefilename,draw->saveimageext,draw->savefilecount-1);
    351:   image = SAWs_images;
    352:   while (image) {
    353:     const char *name = image->filename;
    354:     const char *ext  = image->ext;
    355:     if (draw->savesinglefile) {
    356:       PetscSNPrintf(body+len,4086-len,"<img src=\"%s%s\" alt=\"None\">",name,ext);
    357:     } else {
    358:       PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",name,name,image->count,ext);
    359:     }
    360:     PetscStrlen(body,&len);
    361:     image = image->next;
    362:   }
    363:   PetscStrlcat(body,"<br>\n",sizeof(body));
    364:   if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
    365:   PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
    366:   return(0);
    367: }

    369: #endif