Logo Search packages:      
Sourcecode: fim version File versions  Download package

FbiStuffTiff.cpp

/* $Id: FbiStuffTiff.cpp 210 2009-02-15 17:53:08Z dezperado $ */
/*
 FbiStuffTiff.cpp : fbi functions for TIFF files, modified for fim

 (c) 2007-2009 Michele Martone
 (c) 1998-2006 Gerd Knorr <kraxel@bytesex.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
 * This file comes from fbi, and will undergo severe reorganization.
 * */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <tiffio.h>

//#include "loader.h"
#include "FbiStuff.h"
#include "FbiStuffLoader.h"
#ifdef USE_X11
# include "viewer.h"
#endif

namespace fim
{

struct tiff_state {
    TIFF*          tif;
    char           emsg[1024];
    tdir_t         ndirs;     /* Number of directories                     */
                              /* (could be interpreted as number of pages) */
    uint32         width,height;
    uint16         config,nsamples,depth,fillorder,photometric;
    uint32*        row;
    uint32*        image;
    uint16         resunit;
    float          xres,yres;
};

static void*
tiff_init(FILE *fp, char *filename, unsigned int page,
        struct ida_image_info *i, int thumbnail)
{
    struct tiff_state *h;

    fclose(fp);
    h = (struct tiff_state *) calloc(sizeof(*h),1);
    if(!h)goto oops;
    memset(h,0,sizeof(*h));

    TIFFSetWarningHandler(NULL);
    h->tif = TIFFOpen(filename,"r");
    if (NULL == h->tif)
      goto oops;
    /* Determine number of directories */
    h->ndirs = 1;
    while (TIFFReadDirectory(h->tif))
        h->ndirs++;
    i->npages = h->ndirs;
    /* Select requested directory (page) */
    if (!TIFFSetDirectory(h->tif, (tdir_t)page))
        goto oops;
    
    TIFFGetField(h->tif, TIFFTAG_IMAGEWIDTH,      &h->width);
    TIFFGetField(h->tif, TIFFTAG_IMAGELENGTH,     &h->height);
    TIFFGetField(h->tif, TIFFTAG_PLANARCONFIG,    &h->config);
    TIFFGetField(h->tif, TIFFTAG_SAMPLESPERPIXEL, &h->nsamples);
    TIFFGetField(h->tif, TIFFTAG_BITSPERSAMPLE,   &h->depth);
    TIFFGetField(h->tif, TIFFTAG_FILLORDER,       &h->fillorder);
    TIFFGetField(h->tif, TIFFTAG_PHOTOMETRIC,     &h->photometric);
    h->row = (uint32*)malloc(TIFFScanlineSize(h->tif));
    if(!h->row)goto oops;
    if (FbiStuff::fim_filereading_debug())
#ifndef PRId32
#define PRId32 "x"
#endif
      FIM_FBI_PRINTF("tiff: %" PRId32 "x%" PRId32 ", planar=%d, "
            "nsamples=%d, depth=%d fo=%d pm=%d scanline=%" PRId32 "\n",
//    FIM_FBI_PRINTF("tiff: %" "%d" "x%" "%d" ", planar=%d, "
//          "nsamples=%d, depth=%d fo=%d pm=%d scanline=%" "%d" "\n",
            h->width,h->height,h->config,h->nsamples,h->depth,
            h->fillorder,h->photometric,
            TIFFScanlineSize(h->tif));

    if (PHOTOMETRIC_PALETTE   == h->photometric  ||
      PHOTOMETRIC_YCBCR     == h->photometric  ||
      PHOTOMETRIC_SEPARATED == h->photometric  ||
      TIFFIsTiled(h->tif)                      ||
      (1 != h->depth  &&  8 != h->depth)) {
      /* for the more difficuilt cases we let libtiff
       * do all the hard work.  Drawback is that we lose
       * progressive loading and decode everything here */
      if (FbiStuff::fim_filereading_debug())
          FIM_FBI_PRINTF("tiff: reading whole image [TIFFReadRGBAImage]\n");
      h->image=(uint32*)malloc(4*h->width*h->height);
        if(!h->image)goto oops;
      TIFFReadRGBAImage(h->tif, h->width, h->height, h->image, 0);
    } else {
      if (FbiStuff::fim_filereading_debug())
          FIM_FBI_PRINTF("tiff: reading scanline by scanline\n");
      h->row = (uint32*)malloc(TIFFScanlineSize(h->tif));
        if(!h->row)goto oops;
    }

    i->width  = h->width;
    i->height = h->height;

    if (TIFFGetField(h->tif, TIFFTAG_RESOLUTIONUNIT,  &h->resunit) &&
      TIFFGetField(h->tif, TIFFTAG_XRESOLUTION,     &h->xres)    &&
      TIFFGetField(h->tif, TIFFTAG_YRESOLUTION,     &h->yres)) {
      switch (h->resunit) {
      case RESUNIT_NONE:
          break;
      case RESUNIT_INCH:
          i->dpi = (unsigned int)h->xres;
          break;
      case RESUNIT_CENTIMETER:
          i->dpi = (unsigned int)res_cm_to_inch(h->xres);
          break;
      }
    }

    return h;

 oops:
    if (h && h->tif)
      TIFFClose(h->tif);
    if(h && h->row)free(h->row);
    if(h && h->image)free(h->image);
    if(h)free(h);
    return NULL;
}

static void
tiff_read(unsigned char *dst, unsigned int line, void *data)
{
    struct tiff_state *h = (struct tiff_state *) data;
    int s,on,off;

    if (h->image) {
      /* loaded whole image using TIFFReadRGBAImage() */
      uint32 *row = h->image + h->width * (h->height - line -1);
      load_rgba(dst,(unsigned char*)row,h->width);
      return;
    }
    
    if (h->config == PLANARCONFIG_CONTIG) {
      TIFFReadScanline(h->tif, h->row, line, 0);
    } else if (h->config == PLANARCONFIG_SEPARATE) {
      for (s = 0; s < h->nsamples; s++)
          TIFFReadScanline(h->tif, h->row, line, s);
    }

    switch (h->nsamples) {
    case 1:
      if (1 == h->depth) {
          /* black/white */
          on = 0, off = 0;
          if (PHOTOMETRIC_MINISWHITE == h->photometric)
            on = 0, off = 255;
          if (PHOTOMETRIC_MINISBLACK == h->photometric)
            on = 255, off = 0;
#if 0
          /* Huh?  Does TIFFReadScanline handle this already ??? */
          if (FILLORDER_MSB2LSB == h->fillorder)
            load_bits_msb(dst,(unsigned char*)(h->row),h->width,on,off);
          else
            load_bits_lsb(dst,(unsigned char*)(h->row),h->width,on,off);
#else
          load_bits_msb(dst,(unsigned char*)(h->row),h->width,on,off);
#endif
      } else {
          /* grayscaled */
          load_gray(dst,(unsigned char*)(h->row),h->width);
      }
      break;
    case 3:
      /* rgb */
      memcpy(dst,h->row,3*h->width);
      break;
    case 4:
      /* rgb+alpha */
      load_rgba(dst,(unsigned char*)(h->row),h->width);
      break;
    }
}

static void
tiff_done(void *data)
{
    struct tiff_state *h = (struct tiff_state *) data;

    TIFFClose(h->tif);
    if (h->row)
      free(h->row);
    if (h->image)
      free(h->image);
    free(h);
}

static struct ida_loader tiff1_loader = {
    magic: "MM\x00\x2a",
    moff:  0,
    mlen:  4,
    name:  "libtiff",
    init:  tiff_init,
    read:  tiff_read,
    done:  tiff_done,
};
static struct ida_loader tiff2_loader = {
    magic: "II\x2a\x00",
    moff:  0,
    mlen:  4,
    name:  "libtiff",
    init:  tiff_init,
    read:  tiff_read,
    done:  tiff_done,
};

static void __init init_rd(void)
{
    load_register(&tiff1_loader);
    load_register(&tiff2_loader);
}

#ifdef USE_X11
/* ---------------------------------------------------------------------- */
/* save                                                                   */

static int
tiff_write(FILE *fp, struct ida_image *img)
{
    TIFF          *TiffHndl;
    tdata_t       buf;
    unsigned int  y;

    TiffHndl = TIFFFdOpen(fileno(fp),"42.tiff","w");
    if (TiffHndl == NULL)
      return -1;
    TIFFSetField(TiffHndl, TIFFTAG_IMAGEWIDTH, img->i.width);
    TIFFSetField(TiffHndl, TIFFTAG_IMAGELENGTH, img->i.height);
    TIFFSetField(TiffHndl, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(TiffHndl, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
    TIFFSetField(TiffHndl, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(TiffHndl, TIFFTAG_SAMPLESPERPIXEL, 3);
    TIFFSetField(TiffHndl, TIFFTAG_ROWSPERSTRIP, 2);
    TIFFSetField(TiffHndl, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
#if 0 /* fixme: make this configureable */
    TIFFSetField(TiffHndl, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
    TIFFSetField(TiffHndl, TIFFTAG_PREDICTOR, 2);
#endif
    if (img->i.dpi) {
      float dpi = img->i.dpi;
      TIFFSetField(TiffHndl, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
      TIFFSetField(TiffHndl, TIFFTAG_XRESOLUTION,    dpi);
      TIFFSetField(TiffHndl, TIFFTAG_YRESOLUTION,    dpi);
    }

    for (y = 0; y < img->i.height; y++) {
      buf = img->data + 3*img->i.width*y;
      TIFFWriteScanline(TiffHndl, buf, y, 0);
    }
    TIFFClose(TiffHndl);
    return 0;
}

static struct ida_writer tiff_writer = {
    label:  "TIFF",
    ext:    { "tif", "tiff", NULL},
    write:  tiff_write,
};

static void __init init_wr(void)
{
    write_register(&tiff_writer);
}

#endif
}


Generated by  Doxygen 1.6.0   Back to index