IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 29309


Ignore:
Timestamp:
Oct 4, 2010, 2:47:01 PM (16 years ago)
Author:
eugene
Message:

some rework on the jpeg functions to allow for overlays and a scale bar with labels (psLib now requires libkapa)

Location:
branches/eam_branches/ipp-20100823/psLib
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/ipp-20100823/psLib/configure.ac

    r24322 r29309  
    202202CPPFLAGS=${TMP_CPPFLAGS}
    203203
     204dnl ------------------ kapa,libkapa options -------------------------
     205dnl -- libkapa implies the requirement for libpng, libjpeg as well --
     206
     207dnl save LIBS/CFLAGS/LDFLAGS
     208TMP_LIBS=${LIBS}
     209TMP_CFLAGS=${CFLAGS}
     210TMP_LDFLAGS=${LDFLAGS}
     211TMP_CPPFLAGS=${CPPFLAGS}
     212
     213dnl test for command-line options: use ohana-config if not supplied
     214KAPA_CFLAGS_CONFIG="true"
     215KAPA_LIBS_CONFIG="true"
     216AC_ARG_WITH(kapa,
     217[AS_HELP_STRING(--with-kapa=DIR,Specify location of libkapa)],
     218[KAPA_CFLAGS="-I$withval/include" KAPA_LIBS="-L$withval/lib"
     219 KAPA_CFLAGS_CONFIG="false"       KAPA_LIBS_CONFIG="false"])
     220AC_ARG_WITH(kapa-include,
     221[AS_HELP_STRING(--with-kapa-include=DIR,Specify libkapa include directory.)],
     222[KAPA_CFLAGS="-I$withval" KAPA_CFLAGS_CONFIG="false"])
     223AC_ARG_WITH(kapa-lib,
     224[AS_HELP_STRING(--with-kapa-lib=DIR,Specify libkapa library directory.)],
     225[KAPA_LIBS="-L$withval" KAPA_LIBS_CONFIG="false"])
     226
     227echo "KAPA_CFLAGS_CONFIG: $KAPA_CFLAGS_CONFIG"
     228echo "KAPA_LIBS_CONFIG: $KAPA_LIBS_CONFIG"
     229echo "KAPA_CFLAGS: $KAPA_CFLAGS"
     230echo "KAPA_LIBS: $KAPA_LIBS"
     231
     232dnl HAVE_KAPA is set to false if any of the tests fail
     233HAVE_KAPA="true"
     234AC_MSG_NOTICE([checking for libkapa])
     235if test "$KAPA_CFLAGS_CONFIG" = "true" -o "$KAPA_LIBS_CONFIG" = "true"; then
     236  AC_MSG_NOTICE([kapa info supplied by ohana-config])
     237  KAPA_CONFIG=`which ohana-config`
     238  AC_CHECK_FILE($KAPA_CONFIG,[],
     239    [HAVE_KAPA="false"; AC_MSG_WARN([libkapa is not found: output plots disabled.  Obtain libkapa at http://kiawe.ifa.hawaii.edu/Elixir/Ohana or use --with-kapa to specify location])])
     240 
     241  echo "HAVE_KAPA: $HAVE_KAPA"
     242  echo "KAPA_CFLAGS_CONFIG: $KAPA_CFLAGS_CONFIG"
     243
     244  if test "$HAVE_KAPA" = "true" -a "$KAPA_CFLAGS_CONFIG" = "true" ; then
     245   AC_MSG_NOTICE([libkapa cflags info supplied by ohana-config])
     246   AC_MSG_CHECKING([libkapa cflags])
     247   KAPA_CFLAGS="`${KAPA_CONFIG} --cflags`"
     248   AC_MSG_RESULT([${KAPA_CFLAGS}])
     249  fi
     250
     251  if test "$HAVE_KAPA" = "true" -a "$KAPA_LIBS_CONFIG" = "true" ; then
     252   AC_PATH_X
     253   if test "$no_x" = "yes" ; then
     254      AC_MSG_WARN([X11 not found: output plots using kapa disabled.  Use --x-includes and --x-libraries if required.])
     255      HAVE_KAPA="false"
     256   else
     257      AC_MSG_NOTICE([libkapa ldflags info supplied by ohana-config])
     258      AC_MSG_CHECKING([libkapa ldflags])
     259      if test -n "$x_libraries" ; then
     260            KAPA_LIBS="`${KAPA_CONFIG} --libs` -L$x_libraries -lX11"
     261      else
     262            KAPA_LIBS="`${KAPA_CONFIG} --libs` -lX11"
     263      fi
     264      if test -n "$x_includes" ; then
     265            KAPA_CFLAGS="${KAPA_CFLAGS} -I$x_includes"
     266      else
     267            KAPA_CFLAGS="${KAPA_CFLAGS}"
     268      fi
     269      AC_MSG_RESULT([${KAPA_LIBS}])
     270   fi
     271  fi
     272fi
     273
     274if test "$HAVE_KAPA" = "true" ; then
     275 AC_MSG_NOTICE([libkapa supplied])
     276 PSLIB_CFLAGS="${PSLIB_CFLAGS} ${KAPA_CFLAGS}"
     277 PSLIB_LIBS="${PSLIB_LIBS} ${KAPA_LIBS}"
     278else
     279 AC_MSG_NOTICE([libkapa ignored])
     280fi
     281
    204282dnl ------------------ libjpeg options ---------------------
    205283
     
    239317LDFLAGS=${TMP_LDFLAGS}
    240318CPPFLAGS=${TMP_CPPFLAGS}
     319
     320dnl ------------------ libpng options ---------------------
     321
     322dnl save LIBS/CFLAGS/LDFLAGS
     323TMP_LIBS=${LIBS}
     324TMP_CFLAGS=${CFLAGS}
     325TMP_LDFLAGS=${LDFLAGS}
     326TMP_CPPFLAGS=${CPPFLAGS}
     327
     328AC_ARG_WITH(png,
     329[AS_HELP_STRING(--with-png=DIR,Specify location of libpng.)],
     330[PNG_CFLAGS="-I$withval/include"
     331 PNG_LDFLAGS="-L$withval/lib"])
     332AC_ARG_WITH(png-include,
     333[AS_HELP_STRING(--with-png-include=DIR,Specify libpng include directory.)],
     334[PNG_CFLAGS="-I$withval"])
     335AC_ARG_WITH(png-lib,
     336[AS_HELP_STRING(--with-png-lib=DIR,Specify libpng library directory.)],
     337[PNG_LDFLAGS="-L$withval"])
     338
     339CFLAGS="${CFLAGS} ${PNG_CFLAGS}"
     340CPPFLAGS=${CFLAGS}
     341LDFLAGS="${LDFLAGS} ${PNG_LDFLAGS}"
     342
     343AC_CHECK_HEADERS([png.h],
     344  [PSLIB_CFLAGS="$PSLIB_CFLAGS $PNG_CFLAGS" AC_SUBST(PNG_CFLAGS)],
     345  [HAVE_KAPA=false; AC_MSG_WARN([libpng headers not found: output plots disabled.  Obtain libpng from http://www.ijg.org/ or use --with-png to specify location.])]
     346)
     347
     348AC_CHECK_LIB(png,png_init_io,
     349  [PSLIB_LIBS="$PSLIB_LIBS $PNG_LDFLAGS -lpng"],
     350  [HAVE_KAPA=false; AC_MSG_WARN([libpng library not found: output plots disabled.  Obtain libpng from http://www.ijg.org/ or use --with-png to specify location.])]
     351)
     352
     353dnl restore the CFLAGS/LDFLAGS
     354LIBS=${TMP_LIBS}
     355CFLAGS=${TMP_CFLAGS}
     356LDFLAGS=${TMP_LDFLAGS}
     357CPPFLAGS=${TMP_CPPFLAGS}
     358
     359dnl ------------------ use kapa or not? ---------------------
     360
     361if test "$HAVE_KAPA" == "true" ; then
     362  AC_MSG_RESULT([including plotting functions])
     363  AC_DEFINE([HAVE_KAPA],[1],[enable use of libkapa])
     364else
     365  AC_MSG_RESULT([skipping plotting functions])
     366  AC_DEFINE([HAVE_KAPA],[0],[disable use of libkapa])
     367fi
    241368
    242369dnl ------------------- SWIG options ---------------------
  • branches/eam_branches/ipp-20100823/psLib/src/jpeg/psImageJpeg.c

    r28998 r29309  
    1515#include "psImageJpeg.h"
    1616
     17/* XXX this to do to make this reasonably complete
     18 * update bDraw APIs to accept a bDrawBuffer structure as an input operand
     19 */
     20
    1721#ifdef HAVE_STDLIB_H
    1822// jpeglib.h includes jconfig.h which is full of autoconf generated HAVE_*
    1923// defines. This is a hack to work around CPP redefinition errors.  Arrrrrgh!!!
    2024// -JH
     25
     26// XXX specifically, jconfig.h has defines like the following.  these
     27// could be individually tested here and specifically undefed. EAM.
     28// #define HAVE_PROTOTYPES
     29// #define HAVE_UNSIGNED_CHAR
     30// #define HAVE_UNSIGNED_SHORT
     31
    2132# undef HAVE_STDLIB_H
    2233# include <jpeglib.h>
    2334#endif // ifdef HAVE_STDLIB_H
    2435
    25 static void imageJpegColormapFree(psImageJpegColormap *map)
     36static void imageJpegOptionsFree(psImageJpegOptions *options)
    2637{
    2738
    28     if (!map) {
    29         return;
    30     }
    31 
    32     psFree(map->red);
    33     psFree(map->green);
    34     psFree(map->blue);
     39  if (!options) {
    3540    return;
    36 }
    37 
    38 psImageJpegColormap *psImageJpegColormapAlloc(void)
     41  }
     42
     43  psFree(options->red);
     44  psFree(options->green);
     45  psFree(options->blue);
     46  return;
     47}
     48
     49psImageJpegOptions *psImageJpegOptionsAlloc(void)
    3950{
    40     psImageJpegColormap *map = psAlloc(sizeof(psImageJpegColormap));
    41     psMemSetDeallocator(map, (psFreeFunc)imageJpegColormapFree);
    42 
    43     map->red   = psVectorAlloc(256, PS_TYPE_U8);
    44     map->blue  = psVectorAlloc(256, PS_TYPE_U8);
    45     map->green = psVectorAlloc(256, PS_TYPE_U8);
    46 
    47     return map;
    48 }
    49 
    50 psImageJpegColormap *psImageJpegColormapSet(psImageJpegColormap *map, const char *name)
     51  psImageJpegOptions *options = psAlloc(sizeof(psImageJpegOptions));
     52  psMemSetDeallocator(options, (psFreeFunc)imageJpegOptionsFree);
     53
     54  options->red   = psVectorAlloc(256, PS_TYPE_U8);
     55  options->blue  = psVectorAlloc(256, PS_TYPE_U8);
     56  options->green = psVectorAlloc(256, PS_TYPE_U8);
     57
     58  options->min = 0.0;
     59  options->max = 1000.0;
     60
     61  options->xFlip = false;
     62  options->yFlip = false;
     63  options->showScale = PS_JPEG_SHOWSCALE_BOTTOM;
     64
     65  psImageJpegColormapSet(options, "greyscale");
     66
     67  return options;
     68}
     69
     70bool psImageJpegColormapSet(psImageJpegOptions *options, const char *name)
    5171{
    52 
    53     if (!map) {
    54         map = psImageJpegColormapAlloc ();
    55     }
    56 
    57     /* grayscale */
    58     if ((!strcasecmp (name, "grayscale")) || (!strcasecmp (name, "greyscale"))) {
    59         for (int i = 0; i < map->red->n; i++) {
    60             map->red->data.U8[i]   = PS_JPEG_RANGELIM(i);
    61             map->green->data.U8[i] = PS_JPEG_RANGELIM(i);
    62             map->blue->data.U8[i]  = PS_JPEG_RANGELIM(i);
    63         }
    64         return map;
    65     }
    66 
    67     /* -grayscale */
    68     if ((!strcasecmp (name, "-grayscale")) || (!strcasecmp (name, "-greyscale"))) {
    69         for (int i = 0; i < map->red->n; i++) {
    70             map->red->data.U8[i]   = PS_JPEG_RANGELIM(256 - i);
    71             map->green->data.U8[i] = PS_JPEG_RANGELIM(256 - i);
    72             map->blue->data.U8[i]  = PS_JPEG_RANGELIM(256 - i);
    73         }
    74         return map;
    75     }
    76 
    77     /* rainbow */
    78     if (!strcasecmp (name, "rainbow")) {
    79         int I1 = 0.25*map->red->n;
    80         int I2 = 0.50*map->red->n;
    81         int I3 = 0.75*map->red->n;
    82         for (int i = 0; i < I1; i++) {
    83             map->red->data.U8[i]   = 0;
    84             map->green->data.U8[i] = 0;
    85             map->blue->data.U8[i]  = PS_JPEG_RANGELIM(4*i);
    86         }
    87         for (int i = I1; i < I2; i++) {
    88             map->red->data.U8[i]   = PS_JPEG_RANGELIM(4*(i - I1));
    89             map->green->data.U8[i] = 0;
    90             map->blue->data.U8[i]  = PS_JPEG_RANGELIM(4*(I2 - i));
    91         }
    92         for (int i = I2; i < I3; i++) {
    93             map->red->data.U8[i]   = 255;
    94             map->green->data.U8[i] = 4*(i - I2);
    95             map->blue->data.U8[i]  = 0;
    96         }
    97         for (int i = I3; i < map->red->n; i++) {
    98             map->red->data.U8[i]   = 255;
    99             map->green->data.U8[i] = 255;
    100             map->blue->data.U8[i]  = PS_JPEG_RANGELIM(4*(i - I3));
    101         }
    102         return map;
    103     }
    104 
    105     /* heat */
    106     if (!strcasecmp (name, "heat")) {
    107         int I1 = 0.25*map->red->n;
    108         int I2 = 0.50*map->red->n;
    109         int I3 = 0.75*map->red->n;
    110         for (int i = 0; i < I1; i++) {
    111             map->red->data.U8[i]   = PS_JPEG_RANGELIM(2*i);
    112             map->green->data.U8[i] = 0;
    113             map->blue->data.U8[i]  = 0;
    114         }
    115         for (int i = I1; i < I2; i++) {
    116             map->red->data.U8[i]   = PS_JPEG_RANGELIM(2*i);
    117             map->green->data.U8[i] = PS_JPEG_RANGELIM(2*(i - I1));
    118             map->blue->data.U8[i]  = 0;
    119         }
    120         for (int i = I2; i < I3; i++) {
    121             map->red->data.U8[i]   = 255;
    122             map->green->data.U8[i] = PS_JPEG_RANGELIM(2*(i - I1));
    123             map->blue->data.U8[i]  = PS_JPEG_RANGELIM(2*(i - I2));
    124         }
    125         for (int i = I3; i < map->red->n; i++) {
    126             map->red->data.U8[i]   = 255;
    127             map->green->data.U8[i] = 255;
    128             map->blue->data.U8[i]  = PS_JPEG_RANGELIM(2*(i - I2));
    129         }
    130         return map;
    131     }
    132 
    133     // invalid colormap: warn user
    134     psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Invalid colormap name: %s --- using greyscale\n", name);
    135     return psImageJpegColormapSet (map, "greyscale");
    136 }
    137 
    138 // XXX need to fix library references for this (psLib does not depend on libkapa)
    139 # if (0)
    140 // XXX Add colormap bar with scale (min -> max)
    141 // XXX Add option to plot the source overlay (pass in bDrawBuffer populated with points?)
     72  PS_ASSERT_PTR_NON_NULL(options, false);
     73
     74  /* grayscale */
     75  if ((!strcasecmp (name, "grayscale")) || (!strcasecmp (name, "greyscale"))) {
     76    for (int i = 0; i < options->red->n; i++) {
     77      options->red->data.U8[i]   = PS_JPEG_RANGELIM(i);
     78      options->green->data.U8[i] = PS_JPEG_RANGELIM(i);
     79      options->blue->data.U8[i]  = PS_JPEG_RANGELIM(i);
     80    }
     81    options->white = 255;
     82    options->black = 0;
     83    return options;
     84  }
     85
     86  /* -grayscale */
     87  if ((!strcasecmp (name, "-grayscale")) || (!strcasecmp (name, "-greyscale"))) {
     88    for (int i = 0; i < options->red->n; i++) {
     89      options->red->data.U8[i]   = PS_JPEG_RANGELIM(256 - i);
     90      options->green->data.U8[i] = PS_JPEG_RANGELIM(256 - i);
     91      options->blue->data.U8[i]  = PS_JPEG_RANGELIM(256 - i);
     92    }
     93    options->white = 0;
     94    options->black = 255;
     95    return options;
     96  }
     97
     98  /* rainbow */
     99  if (!strcasecmp (name, "rainbow")) {
     100    int I1 = 0.25*options->red->n;
     101    int I2 = 0.50*options->red->n;
     102    int I3 = 0.75*options->red->n;
     103    for (int i = 0; i < I1; i++) {
     104      options->red->data.U8[i]   = 0;
     105      options->green->data.U8[i] = 0;
     106      options->blue->data.U8[i]  = PS_JPEG_RANGELIM(4*i);
     107    }
     108    for (int i = I1; i < I2; i++) {
     109      options->red->data.U8[i]   = PS_JPEG_RANGELIM(4*(i - I1));
     110      options->green->data.U8[i] = 0;
     111      options->blue->data.U8[i]  = PS_JPEG_RANGELIM(4*(I2 - i));
     112    }
     113    for (int i = I2; i < I3; i++) {
     114      options->red->data.U8[i]   = 255;
     115      options->green->data.U8[i] = 4*(i - I2);
     116      options->blue->data.U8[i]  = 0;
     117    }
     118    for (int i = I3; i < options->red->n; i++) {
     119      options->red->data.U8[i]   = 255;
     120      options->green->data.U8[i] = 255;
     121      options->blue->data.U8[i]  = PS_JPEG_RANGELIM(4*(i - I3));
     122    }
     123    options->white = 255;
     124    options->black = 0;
     125    return options;
     126  }
     127
     128  /* heat */
     129  if (!strcasecmp (name, "heat")) {
     130    int I1 = 0.25*options->red->n;
     131    int I2 = 0.50*options->red->n;
     132    int I3 = 0.75*options->red->n;
     133    for (int i = 0; i < I1; i++) {
     134      options->red->data.U8[i]   = PS_JPEG_RANGELIM(2*i);
     135      options->green->data.U8[i] = 0;
     136      options->blue->data.U8[i]  = 0;
     137    }
     138    for (int i = I1; i < I2; i++) {
     139      options->red->data.U8[i]   = PS_JPEG_RANGELIM(2*i);
     140      options->green->data.U8[i] = PS_JPEG_RANGELIM(2*(i - I1));
     141      options->blue->data.U8[i]  = 0;
     142    }
     143    for (int i = I2; i < I3; i++) {
     144      options->red->data.U8[i]   = 255;
     145      options->green->data.U8[i] = PS_JPEG_RANGELIM(2*(i - I1));
     146      options->blue->data.U8[i]  = PS_JPEG_RANGELIM(2*(i - I2));
     147    }
     148    for (int i = I3; i < options->red->n; i++) {
     149      options->red->data.U8[i]   = 255;
     150      options->green->data.U8[i] = 255;
     151      options->blue->data.U8[i]  = PS_JPEG_RANGELIM(2*(i - I2));
     152    }
     153    options->white = 255;
     154    options->black = 0;
     155    return options;
     156  }
     157
     158  // invalid colormap: warn user
     159  psWarning("Invalid colormap name: %s --- using greyscale\n", name);
     160  return psImageJpegColormapSet (options, "greyscale");
     161}
     162
     163bDrawBuffer *psImageJpegOverlayInit (const psImage *image) {
     164
     165  int dx = image->numCols;
     166  int dy = image->numRows;
     167 
     168  bDrawBuffer *bdbuf = bDrawBufferCreate(dx, dy);
     169
     170  return bdbuf;
     171}
     172
     173// copy the buffer pixels which are not white (probably should be "not blank")
     174bool psImageJpegOverlayDraw (JSAMPLE *jpegImage, bDrawBuffer *bdbuf, int offX, int offY) {
     175
     176  // XXX check valid limits
     177
     178  int dx = bdbuf->Nx;
     179  int dy = bdbuf->Ny;
     180
     181  int Npalette;
     182  png_color *palette = KapaPNGPalette (&Npalette);
     183  bDrawColor white = KapaColorByName ("white");
     184  for (int j = 0; j < dy; j++) {
     185    for (int i = 0; i < dx; i++) {
     186      bDrawColor color = bdbuf->pixels[j][i];
     187      if (color == white) continue;
     188      jpegImage[(j + offY)*3*dx + 3*(i + offX) + 0] = palette[color].red;
     189      jpegImage[(j + offY)*3*dx + 3*(i + offX) + 1] = palette[color].green;
     190      jpegImage[(j + offY)*3*dx + 3*(i + offX) + 2] = palette[color].blue;
     191    }
     192  }
     193  return true;
     194}
     195
    142196// XXX need to update bDraw APIs to pass in/out structure and avoid the local static
    143 bool psImageJpegNew(const psImageJpegColormap *map, const psImage *image, const char *filename,
    144                  float min, float max)
     197bool psImageJpeg(const psImageJpegOptions *options, const psImage *image, bDrawBuffer *bdbuf, const char *filename)
    145198{
    146     PS_ASSERT_PTR_NON_NULL(map, false);
    147     PS_ASSERT_IMAGE_NON_NULL(image, false);
    148     PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false);
    149     PS_ASSERT_VECTOR_NON_NULL(map->red, false);
    150     PS_ASSERT_VECTOR_NON_NULL(map->green, false);
    151     PS_ASSERT_VECTOR_NON_NULL(map->blue, false);
    152     PS_ASSERT_PTR_NON_NULL(filename, false);
    153     PS_ASSERT_INT_POSITIVE(strlen(filename), false);
    154     PS_ASSERT_FLOAT_REAL(min, false);
    155     PS_ASSERT_FLOAT_REAL(max, false);
    156 
    157     float zero, scale;
    158     struct jpeg_compress_struct cinfo;
    159     struct jpeg_error_mgr jerr;
    160 
    161     long pixel;
    162     JSAMPLE *jpegLine;   // Points to data for current line
    163     JSAMPROW jpegLineList[1];  // pointer to JSAMPLE row[s]
    164     JSAMPLE *jpegImage;
    165     JSAMPLE *outPix;
    166 
    167     /* JPEG init calls */
    168     cinfo.err = jpeg_std_error (&jerr);
    169     jpeg_create_compress (&cinfo);
    170 
    171     /* open file, prep for jpeg */
    172     FILE *f = fopen(filename, "w");
    173     if (!f) {
    174         psError(PS_ERR_IO, true, "failed to open %s for output\n", filename);
    175         return false;
    176     }
    177     jpeg_stdio_dest(&cinfo, f);
    178 
    179     /* set up color jpeg buffers */
    180     int quality = 75;
    181     cinfo.image_width = image->numCols; // image width and height, in pixels
    182     cinfo.image_height = image->numRows;
    183     cinfo.input_components = 3;
    184     cinfo.in_color_space = JCS_RGB;
    185     jpeg_set_defaults (&cinfo);
    186     jpeg_set_quality (&cinfo, quality, true); // limit to baseline-JPEG values
    187     jpeg_start_compress (&cinfo, true);
    188 
    189     psU8 *Rpix = map->red->data.U8;
    190     psU8 *Gpix = map->green->data.U8;
    191     psU8 *Bpix = map->blue->data.U8;
    192 
    193     if (max == min) {
    194         zero = min - 0.1;
    195         scale = 256.0/0.2;
    196     } else {
    197         zero = min;
    198         scale = 256.0/(max - min);
    199     }
    200 
    201     int dx = image->numCols;
    202     int dy = image->numRows;
    203 
    204     // output image buffer and line buffer
    205     jpegLine = psAlloc (3*dx*sizeof(JSAMPLE));
    206     jpegImage = psAlloc (3*dx*dy*sizeof(JSAMPLE));
    207 
    208     // first copy the image data into the output buffer
    209     for (int j = 0; j < dy; j++) {
    210         psF32 *row = image->data.F32[j];
    211 
    212         outPix = jpegLine;
    213         for (int i = 0; i < dx; i++, outPix += 3) {
    214             if (isfinite(row[i])) {
    215                 pixel = PS_JPEG_SCALEVALUE(row[i],zero,scale);
    216                 outPix[0] = Rpix[pixel];
    217                 outPix[1] = Gpix[pixel];
    218                 outPix[2] = Bpix[pixel];
    219             } else {
    220                 // XXX NAN value should be set per-color map
    221                 outPix[0] = 0x00;
    222                 outPix[1] = 0xff;
    223                 outPix[2] = 0x00;
    224             }
    225         }
    226         memcpy (&jpegImage[j*3*dx], jpegLine, 3*dx);
    227     }
    228 
    229     bDrawBuffer *bdbuf = bDrawBufferCreate(dx, dy);
    230     bDrawSetBuffer(bdbuf);
    231     bDrawColor red = KapaColorByName("red");
    232     bDrawSetStyle (red, 1, 0);
    233     bDrawCircle(40.0, 20.0, 3.0);
    234 
    235     {
    236         int Npalette;
    237         png_color *palette = KapaPNGPalette (&Npalette);
    238         bDrawColor white = KapaColorByName ("white");
    239         for (int j = 0; j < dy; j++) {
    240             for (int i = 0; i < dx; i++) {
    241                 bDrawColor color = bdbuf[0].pixels[j][i];
    242                 if (color == white) continue;
    243                 jpegImage[j*3*dx + 3*i + 0] = palette[color].red;
    244                 jpegImage[j*3*dx + 3*i + 1] = palette[color].green;
    245                 jpegImage[j*3*dx + 3*i + 2] = palette[color].blue;
    246             }
    247         }
    248     }
    249     bDrawBufferFree (bdbuf);
    250 
    251     // write out the image buffer
    252     for (int j = 0; j < image->numRows; j++) {
    253         jpegLineList[0] = &jpegImage[j*3*dx];
    254         if (jpeg_write_scanlines(&cinfo, jpegLineList, 1) == 0) {
    255             psError(PS_ERR_IO, true, "Unable to write line %d to JPEG", j);
    256             psFree(jpegLine);
    257             psFree(jpegImage);
    258             fclose(f);
    259             return false;
    260         }
    261     }
    262 
    263     jpeg_finish_compress(&cinfo);
    264     if (fclose(f) == EOF) {
    265         psError(PS_ERR_IO, true, "Failed to close %s", filename);
    266         psFree(jpegLine);
    267         psFree(jpegImage);
    268         return false;
    269     }
    270     jpeg_destroy_compress(&cinfo);
    271 
     199  PS_ASSERT_PTR_NON_NULL(options, false);
     200  PS_ASSERT_VECTOR_NON_NULL(options->red, false);
     201  PS_ASSERT_VECTOR_NON_NULL(options->green, false);
     202  PS_ASSERT_VECTOR_NON_NULL(options->blue, false);
     203  PS_ASSERT_FLOAT_REAL(options->min, false);
     204  PS_ASSERT_FLOAT_REAL(options->max, false);
     205  PS_ASSERT_IMAGE_NON_NULL(image, false);
     206  PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false);
     207  PS_ASSERT_PTR_NON_NULL(filename, false);
     208  PS_ASSERT_INT_POSITIVE(strlen(filename), false);
     209
     210  float zero, scale;
     211  struct jpeg_compress_struct cinfo;
     212  struct jpeg_error_mgr jerr;
     213
     214  long pixel;
     215  JSAMPLE *jpegLine;   // Points to data for current line
     216  JSAMPROW jpegLineList[1];  // pointer to JSAMPLE row[s]
     217  JSAMPLE *jpegImage;
     218  JSAMPLE *outPix;
     219
     220  /* JPEG init calls */
     221  cinfo.err = jpeg_std_error (&jerr);
     222  jpeg_create_compress (&cinfo);
     223
     224  /* open file, prep for jpeg */
     225  FILE *f = fopen(filename, "w");
     226  if (!f) {
     227    psError(PS_ERR_IO, true, "failed to open %s for output\n", filename);
     228    return false;
     229  }
     230  jpeg_stdio_dest(&cinfo, f);
     231
     232  /* set up color jpeg buffers */
     233  int quality = 75;
     234  cinfo.image_width = image->numCols; // image width and height, in pixels
     235  cinfo.image_height = image->numRows;
     236
     237  if (options->showScale != PS_JPEG_SHOWSCALE_NONE) {
     238    cinfo.image_height += PS_JPEG_COLORPAD + PS_JPEG_LABELPAD;
     239  }
     240
     241  cinfo.input_components = 3;
     242  cinfo.in_color_space = JCS_RGB;
     243  jpeg_set_defaults (&cinfo);
     244  jpeg_set_quality (&cinfo, quality, true); // limit to baseline-JPEG values
     245  jpeg_start_compress (&cinfo, true);
     246
     247  psU8 *Rpix = options->red->data.U8;
     248  psU8 *Gpix = options->green->data.U8;
     249  psU8 *Bpix = options->blue->data.U8;
     250
     251  if (options->max == options->min) {
     252    zero = options->min - 0.1;
     253    scale = 256.0/0.2;
     254  } else {
     255    zero = options->min;
     256    scale = 256.0/(options->max - options->min);
     257  }
     258
     259  // dx,dy is the size of the image itself.  the drawing window may be larger
     260  // by the size of the scalebar (depending on the location)
     261
     262  int dx = image->numCols;
     263  int dy = image->numRows;
     264  int Nx = cinfo.image_width;
     265  int Ny = cinfo.image_height;
     266
     267  // output image buffer and line buffer
     268  jpegLine = psAlloc (3*Nx*sizeof(JSAMPLE));
     269  jpegImage = psAlloc (3*Nx*Ny*sizeof(JSAMPLE));
     270
     271  // first copy the image data into the output buffer
     272  // output image ranges from offset to offset + dy
     273  int offset = (options->showScale == PS_JPEG_SHOWSCALE_TOP) ? PS_JPEG_COLORPAD + PS_JPEG_LABELPAD : 0;
     274  for (int j = 0; j < dy; j++) {
     275
     276    psF32 *row = options->yFlip ? image->data.F32[j] : image->data.F32[dy - j - 1];
     277
     278    outPix = options->xFlip ?  jpegLine + 3*(dx - 1) : jpegLine;
     279    int delta = options->xFlip ? -3 : 3;
     280    for (int i = 0; i < dx; i++, outPix += delta) {
     281      if (isfinite(row[i])) {
     282        pixel = PS_JPEG_SCALEVALUE(row[i],zero,scale);
     283        outPix[0] = Rpix[pixel];
     284        outPix[1] = Gpix[pixel];
     285        outPix[2] = Bpix[pixel];
     286      } else {
     287        // XXX NAN value should be set per-color map
     288        outPix[0] = 0x00;
     289        outPix[1] = 0xff;
     290        outPix[2] = 0x00;
     291      }
     292    }
     293    memcpy (&jpegImage[(j + offset)*3*dx], jpegLine, 3*dx);
     294  }
     295
     296  if (options->showScale != PS_JPEG_SHOWSCALE_NONE) {
     297    offset = (options->showScale == PS_JPEG_SHOWSCALE_TOP) ? 0 : dy;
     298    zero = 0;
     299    scale = 256.0 / dx;
     300    for (int j = 0; j < PS_JPEG_COLORPAD; j++) {
     301      outPix = jpegLine;
     302      for (int i = 0; i < dx; i++, outPix += 3) {
     303        pixel = PS_JPEG_SCALEVALUE(i, zero, scale);
     304        outPix[0] = Rpix[pixel];
     305        outPix[1] = Gpix[pixel];
     306        outPix[2] = Bpix[pixel];
     307      }
     308      memcpy (&jpegImage[(j + offset)*3*dx], jpegLine, 3*dx);
     309    }
     310
     311    // set the LABEL region to white
     312    psU8 white = options->white;
     313    offset = (options->showScale == PS_JPEG_SHOWSCALE_TOP) ? PS_JPEG_COLORPAD : PS_JPEG_COLORPAD + dy;
     314    for (int j = 0; j < PS_JPEG_LABELPAD; j++) {
     315      outPix = jpegLine;
     316      for (int i = 0; i < dx; i++, outPix += 3) {
     317        outPix[0] = Rpix[white];
     318        outPix[1] = Gpix[white];
     319        outPix[2] = Bpix[white];
     320      }
     321      memcpy (&jpegImage[(j + offset)*3*dx], jpegLine, 3*dx);
     322    }
     323
     324    // set the scalebar labels
     325    char string[64];
     326    bDrawBuffer *labels = bDrawBufferCreate(dx, PS_JPEG_LABELPAD);
     327    SetRotFont ("helvetica", 8);
     328    bDrawSetBuffer(labels);
     329    sprintf (string, "%g", options->min);
     330    bDrawRotText(2, 2, string, 2, 0.0);
     331    sprintf (string, "%g", options->max);
     332    bDrawRotText(dx - 2, 2, string, 0, 0.0);
     333    sprintf (string, "%g", 0.5*(options->min + options->max));
     334    bDrawRotText(0.5*dx, 2, string, 1, 0.0);
     335    psImageJpegOverlayDraw(jpegImage, labels, 0, offset);
     336  }
     337   
     338  if (bdbuf) {
     339    offset = (options->showScale == PS_JPEG_SHOWSCALE_TOP) ? PS_JPEG_COLORPAD + PS_JPEG_LABELPAD : 0;
     340    psImageJpegOverlayDraw(jpegImage, bdbuf, 0, offset);
     341  }
     342
     343  // write out the image buffer
     344  for (int j = 0; j < Ny; j++) {
     345    jpegLineList[0] = &jpegImage[j*3*dx];
     346    if (jpeg_write_scanlines(&cinfo, jpegLineList, 1) == 0) {
     347      psError(PS_ERR_IO, true, "Unable to write line %d to JPEG", j);
     348      psFree(jpegLine);
     349      psFree(jpegImage);
     350      fclose(f);
     351      return false;
     352    }
     353  }
     354
     355  jpeg_finish_compress(&cinfo);
     356  if (fclose(f) == EOF) {
     357    psError(PS_ERR_IO, true, "Failed to close %s", filename);
    272358    psFree(jpegLine);
    273359    psFree(jpegImage);
    274     return true;
    275 }
    276 # endif
    277 
    278 bool psImageJpeg(const psImageJpegColormap *map, const psImage *image, const char *filename,
    279                  float min, float max)
    280 {
    281     PS_ASSERT_PTR_NON_NULL(map, false);
    282     PS_ASSERT_IMAGE_NON_NULL(image, false);
    283     PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false);
    284     PS_ASSERT_VECTOR_NON_NULL(map->red, false);
    285     PS_ASSERT_VECTOR_NON_NULL(map->green, false);
    286     PS_ASSERT_VECTOR_NON_NULL(map->blue, false);
    287     PS_ASSERT_PTR_NON_NULL(filename, false);
    288     PS_ASSERT_INT_POSITIVE(strlen(filename), false);
    289     PS_ASSERT_FLOAT_REAL(min, false);
    290     PS_ASSERT_FLOAT_REAL(max, false);
    291 
    292     float zero, scale;
    293     struct jpeg_compress_struct cinfo;
    294     struct jpeg_error_mgr jerr;
    295 
    296     long pixel;
    297     JSAMPLE *jpegLine;   // Points to data for current line
    298     JSAMPROW jpegLineList[1];  // pointer to JSAMPLE row[s]
    299     JSAMPLE *outPix;
    300 
    301     /* JPEG init calls */
    302     cinfo.err = jpeg_std_error (&jerr);
    303     jpeg_create_compress (&cinfo);
    304 
    305     /* open file, prep for jpeg */
    306     FILE *f = fopen(filename, "w");
    307     if (!f) {
    308         psError(PS_ERR_IO, true, "failed to open %s for output\n", filename);
    309         return false;
    310     }
    311     jpeg_stdio_dest(&cinfo, f);
    312 
    313     /* set up color jpeg buffers */
    314     int quality = 75;
    315     cinfo.image_width = image->numCols; // image width and height, in pixels
    316     cinfo.image_height = image->numRows;
    317     cinfo.input_components = 3;
    318     cinfo.in_color_space = JCS_RGB;
    319     jpeg_set_defaults (&cinfo);
    320     jpeg_set_quality (&cinfo, quality, true); // limit to baseline-JPEG values
    321     jpeg_start_compress (&cinfo, true);
    322 
    323     jpegLine = psAlloc (3*image->numCols*sizeof(JSAMPLE));
    324     jpegLineList[0] = jpegLine;
    325 
    326     psU8 *Rpix = map->red->data.U8;
    327     psU8 *Gpix = map->green->data.U8;
    328     psU8 *Bpix = map->blue->data.U8;
    329 
    330     if (max == min) {
    331         zero = min - 0.1;
    332         scale = 256.0/0.2;
    333     } else {
    334         zero = min;
    335         scale = 256.0/(max - min);
    336     }
    337 
    338     for (int j = 0; j < image->numRows; j++) {
    339         psF32 *row = image->data.F32[j];
    340 
    341         outPix = jpegLine;
    342         for (int i = 0; i < image->numCols; i++, outPix += 3) {
    343             if (isfinite(row[i])) {
    344                 pixel = PS_JPEG_SCALEVALUE(row[i],zero,scale);
    345                 outPix[0] = Rpix[pixel];
    346                 outPix[1] = Gpix[pixel];
    347                 outPix[2] = Bpix[pixel];
    348             } else {
    349                 // XXX NAN value should be set per-color map
    350                 outPix[0] = 0xff;
    351                 outPix[1] = 0x00;
    352                 outPix[2] = 0xff;
    353             }
    354         }
    355         if (jpeg_write_scanlines(&cinfo, jpegLineList, 1) == 0) {
    356             psError(PS_ERR_IO, true, "Unable to write line %d to JPEG", j);
    357             psFree(jpegLine);
    358             return false;
    359         }
    360     }
    361 
    362     jpeg_finish_compress(&cinfo);
    363     if (fclose(f) == EOF) {
    364         psError(PS_ERR_IO, true, "Failed to close %s", filename);
    365         psFree(jpegLine);
    366         return false;
    367     }
    368     jpeg_destroy_compress(&cinfo);
    369 
    370     psFree(jpegLine);
    371 
    372     return true;
    373 }
     360    return false;
     361  }
     362  jpeg_destroy_compress(&cinfo);
     363
     364  psFree(jpegLine);
     365  psFree(jpegImage);
     366  return true;
     367}
  • branches/eam_branches/ipp-20100823/psLib/src/jpeg/psImageJpeg.h

    r23486 r29309  
    1515#include "psImage.h"
    1616
    17 typedef struct
    18 {
    19     psVector *red;                      // Red colormap
    20     psVector *green;                    // Green colormap
    21     psVector *blue;                     // Blue colormap
    22 }
    23 psImageJpegColormap;
     17typedef enum {
     18  PS_JPEG_SHOWSCALE_NONE,
     19  PS_JPEG_SHOWSCALE_TOP,
     20  PS_JPEG_SHOWSCALE_BOTTOM
     21} psImageJpegShowScaleOption; 
     22
     23typedef struct {
     24  psVector *red;                      // Red colormap
     25  psVector *green;                    // Green colormap
     26  psVector *blue;                     // Blue colormap
     27  psU8 white;                         // colormap-independent values
     28  psU8 black;
     29  float min;
     30  float max;
     31  bool xFlip;
     32  bool yFlip;
     33  psImageJpegShowScaleOption showScale;
     34  // XXX include bDrawBuffer in here?
     35} psImageJpegOptions;
    2436
    2537#define PS_JPEG_RANGELIM(A)(PS_MAX(0,PS_MIN(255,(A))))
    26 
    2738#define PS_JPEG_SCALEVALUE(VALUE,ZERO,SCALE)(PS_MAX(0,PS_MIN(255,(SCALE*(VALUE-ZERO)))))
    2839
     40#define PS_JPEG_COLORPAD 10
     41#define PS_JPEG_LABELPAD 12
     42
    2943// allocate a colormap (does not define the map values)
    30 psImageJpegColormap *psImageJpegColormapAlloc(void) PS_ATTR_MALLOC;
     44psImageJpegOptions *psImageJpegOptionsAlloc(void) PS_ATTR_MALLOC;
    3145
    3246// set the colormap values using the supplied name
    33 psImageJpegColormap *psImageJpegColormapSet(psImageJpegColormap *map, // Colormap to set
    34         const char *name // Name of colormap
    35                                            );
     47bool psImageJpegColormapSet(psImageJpegOptions *options, // Colormap to set
     48                            const char *name // Name of colormap
     49                            );
    3650
    3751// write out a JPEG file using the supplied image and colormap
    3852// output goes to the specified filename
    39 bool psImageJpeg(const psImageJpegColormap *map, // Color map
     53bool psImageJpeg(const psImageJpegOptions *options, // Color map
    4054                 const psImage *image,  // Image to write
    41                  const char *filename,  // Filename of JPEG
    42                  float min, float max   // Minimum and maximum values
    43                 );
     55                 bDrawBuffer *bdbuf,
     56                 const char *filename  // Filename of JPEG
     57                 );
     58
     59bDrawBuffer *psImageJpegOverlayInit (const psImage *image);
    4460
    4561/// @}
  • branches/eam_branches/ipp-20100823/psLib/src/pslib.h

    r4162 r29309  
    1717#define PS_LIB_H
    1818
     19#include <kapa.h>
    1920#include "pslib_strict.h"
    2021
Note: See TracChangeset for help on using the changeset viewer.