Пример #1
0
/*
 * Get a strip-organized image with
 *   SamplesPerPixel > 1
 *   PlanarConfiguration separated
 * We assume that all such images are RGB.
 */
static int
gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
{
    TIFF* tif = img->tif;
    tileSeparateRoutine put = img->put.separate;
    uint16 orientation;
    u_char *buf;
    u_char *r, *g, *b, *a;
    uint32 row, y, nrow;
    tsize_t scanline;
    uint32 rowsperstrip;
    uint32 imagewidth = img->width;
    tsize_t stripsize;
    int32 fromskew, toskew;
    int alpha = img->alpha;

    stripsize = TIFFStripSize(tif);
    r = buf = (u_char *)_TIFFmalloc(4*stripsize);
    if (buf == 0) {
    TIFFError(TIFFFileName(tif), "No space for tile buffer");
    return (0);
    }
    g = r + stripsize;
    b = g + stripsize;
    a = b + stripsize;
    if (!alpha)
    memset(a, 0xff, stripsize);
    y = setorientation(img, h);
    orientation = img->orientation;
    toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? w+w : w-w);
    TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    scanline = TIFFScanlineSize(tif);
    fromskew = (w < imagewidth ? imagewidth - w : 0);
    for (row = 0; row < h; row += rowsperstrip) {
    nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
    if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
    r, nrow*scanline) < 0 && img->stoponerr)
    break;
    if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1),
    g, nrow*scanline) < 0 && img->stoponerr)
    break;
    if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2),
    b, nrow*scanline) < 0 && img->stoponerr)
    break;
    if (alpha &&
    (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 3),
    a, nrow*scanline) < 0 && img->stoponerr))
    break;
    (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, r, g, b, a);
    y += (orientation == ORIENTATION_TOPLEFT ?
    -(int32) nrow : (int32) nrow);
    }
    _TIFFfree(buf);
    return (1);
}
Пример #2
0
/*
 * Get a strip-organized image with
 *	 SamplesPerPixel > 1
 *	 PlanarConfiguration separated
 * We assume that all such images are RGB.
 */
static int
gtStripSeparate(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
{
    TIFF* tif = img->tif;
    ImageIterTileSeparateRoutine callback = img->callback.separate;
    uint16 orientation;
    u_char *buf;
    u_char *r, *g, *b, *a;
    uint32 row, nrow;
    tsize_t scanline;
    uint32 rowsperstrip;
    uint32 imagewidth = img->width;
    tsize_t stripsize;
    int32 fromskew;
    int alpha = img->alpha;

    stripsize = TIFFStripSize(tif);
    r = buf = (u_char *)_TIFFmalloc(4*stripsize);
    if (buf == 0) {
	TIFFError(TIFFFileName(tif), "No space for tile buffer");
	return (0);
    }
    g = r + stripsize;
    b = g + stripsize;
    a = b + stripsize;
    if (!alpha)
	memset(a, 0xff, stripsize);
    orientation = img->orientation;
    TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    scanline = TIFFScanlineSize(tif);
    fromskew = (w < imagewidth ? imagewidth - w : 0);
    for (row = 0; row < h; row += rowsperstrip) {
	nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
	if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
	    r, nrow*scanline) < 0 && img->stoponerr)
	    break;
	if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 1),
	    g, nrow*scanline) < 0 && img->stoponerr)
	    break;
	if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 2),
	    b, nrow*scanline) < 0 && img->stoponerr)
	    break;
	if (alpha &&
	    (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 3),
	    a, nrow*scanline) < 0 && img->stoponerr))
	    break;
	(*callback)(img, udata, 0, row, w, nrow, fromskew, r, g, b, a);
    }
    _TIFFfree(buf);
    return (1);
}
Пример #3
0
int ReadStrip(TIFF* tiff, UINT32 row, UINT32* buffer) {
    uint16 photometric;
    TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);

    // To avoid dealing with YCbCr subsampling, let libtiff handle it
    if (photometric == PHOTOMETRIC_YCBCR) {
        TIFFRGBAImage img;
        char emsg[1024] = "";
        UINT32 rows_per_strip, rows_to_read;
        int ok;


        TIFFGetFieldDefaulted(tiff, TIFFTAG_ROWSPERSTRIP, &rows_per_strip);
        if ((row % rows_per_strip) != 0) {
            TRACE(("Row passed to ReadStrip() must be first in a strip."));
            return -1;
        }

        if (TIFFRGBAImageOK(tiff, emsg) && TIFFRGBAImageBegin(&img, tiff, 0, emsg)) {
            TRACE(("Initialized RGBAImage\n"));

            img.req_orientation = ORIENTATION_TOPLEFT;
            img.row_offset = row;
            img.col_offset = 0;

            rows_to_read = min(rows_per_strip, img.height - row);

            TRACE(("rows to read: %d\n", rows_to_read));
            ok = TIFFRGBAImageGet(&img, buffer, img.width, rows_to_read);

            TIFFRGBAImageEnd(&img);
        } else {
            ok = 0;
        }

        if (ok == 0) {
            TRACE(("Decode Error, row %d; msg: %s\n", row, emsg));
            return -1;
        }

        return 0;
    }

    if (TIFFReadEncodedStrip(tiff, TIFFComputeStrip(tiff, row, 0), (tdata_t)buffer, -1) == -1) {
        TRACE(("Decode Error, strip %d\n", TIFFComputeStrip(tiff, row, 0)));
        return -1;
    }

    return 0;
}
Пример #4
0
static void
svRGBContig(TIFF* tif, uint32* ss, int xsize, int ysize)
{
	register int x, y;
	tsize_t stripsize = TIFFStripSize(tif);
	unsigned char *strip = (unsigned char *)_TIFFmalloc(stripsize);

	for (y = 0; y <= ysize; y += rowsperstrip) {
		register unsigned char *pp = strip;
		register uint32 n;

		n = rowsperstrip;
		if (n > ysize-y+1)
			n = ysize-y+1;
		do {
			for (x = 0; x <= xsize; x++) {
				uint32 v = ss[x];
				pp[0] = v;
				pp[1] = v >> 8;
				pp[2] = v >> 16;
				pp += 3;
			}
			ss += xsize+1;
		} while (--n);
		if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,0),
		    strip, stripsize) < 0)
			break;
	}
	_TIFFfree(strip);
}
Пример #5
0
/*
 * Get a strip-organized image that has
 *	PlanarConfiguration contiguous if SamplesPerPixel > 1
 * or
 *	SamplesPerPixel == 1
 */	
static int
gtStripContig(TIFFImageIter* img, void *udata, uint32 w, uint32 h)
{
    TIFF* tif = img->tif;
    ImageIterTileContigRoutine callback = img->callback.contig;
    uint16 orientation;
    uint32 row, nrow;
    u_char* buf;
    uint32 rowsperstrip;
    uint32 imagewidth = img->width;
    tsize_t scanline;
    int32 fromskew;

    buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif));
    if (buf == 0) {
	TIFFError(TIFFFileName(tif), "No space for strip buffer");
	return (0);
    }
    orientation = img->orientation;
    TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    scanline = TIFFScanlineSize(tif);
    fromskew = (w < imagewidth ? imagewidth - w : 0);
    for (row = 0; row < h; row += rowsperstrip) {
	nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
	if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
	    buf, nrow*scanline) < 0 && img->stoponerr)
		break;
	(*callback)(img, udata, 0, row, w, nrow, fromskew, buf);
    }
    _TIFFfree(buf);
    return (1);
}
Пример #6
0
/*
 * Get a strip-organized image that has
 *    PlanarConfiguration contiguous if SamplesPerPixel > 1
 * or
 *    SamplesPerPixel == 1
 */    
boolean TIFFRasterImpl::gtStripContig(
    const RGBvalue* Map, u_long h, u_long w
) {
    u_char* buf = new u_char[TIFFStripSize(tif_)];
    if (buf == nil) {
	TIFFError(TIFFFileName(tif_), "No space for strip buffer");
	return (false);
    }
    tileContigRoutine put = pickTileContigCase(Map);
    u_long y = setorientation(h);
    int toskew = (int)(orientation_ == ORIENTATION_TOPLEFT ? -w + -w : -w + w);
    u_long rowsperstrip = (u_long) -1L;
    TIFFGetField(tif_, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    u_long imagewidth;
    TIFFGetField(tif_, TIFFTAG_IMAGEWIDTH, &imagewidth);
    int scanline = TIFFScanlineSize(tif_);
    int fromskew = (int)(w < imagewidth ? imagewidth - w : 0);
    for (u_long row = 0; row < h; row += rowsperstrip) {
	u_int nrow = u_int(row + rowsperstrip > h ? h - row : rowsperstrip);
	if (TIFFReadEncodedStrip(
	    tif_, TIFFComputeStrip(tif_, row, 0), buf, nrow*scanline) < 0
	) {
	    break;
	}
	(this->*put)(raster_ + y*w, buf, Map, w, nrow, fromskew, toskew);
	y += (orientation_ == ORIENTATION_TOPLEFT ? -nrow : nrow);
    }
    delete buf;
    return true;
}
Пример #7
0
/*
 * Get a strip-organized image with
 *     SamplesPerPixel > 1
 *     PlanarConfiguration separated
 * We assume that all such images are RGB.
 */
boolean TIFFRasterImpl::gtStripSeparate(
    const RGBvalue* Map, u_long h, u_long w
) {
    u_long stripsize = TIFFStripSize(tif_);
    u_char* buf = new u_char[3*stripsize];
    u_char* r = buf;
    u_char* g = r + stripsize;
    u_char* b = g + stripsize;
    tileSeparateRoutine put = pickTileSeparateCase(Map);
    u_long y = setorientation(h);
    int toskew = (int)(orientation_ == ORIENTATION_TOPLEFT ? -w + -w : -w + w);
    u_long rowsperstrip = (u_long) -1L;
    TIFFGetField(tif_, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    u_long imagewidth;
    TIFFGetField(tif_, TIFFTAG_IMAGEWIDTH, &imagewidth);
    int scanline = TIFFScanlineSize(tif_);
    int fromskew = (int)(w < imagewidth ? imagewidth - w : 0);
    for (u_long row = 0; row < h; row += rowsperstrip) {
	u_int nrow = u_int(row + rowsperstrip > h ? h - row : rowsperstrip);
	if (TIFFReadEncodedStrip(
	    tif_, TIFFComputeStrip(tif_, row, 0), r, nrow*scanline) < 0
	) {
	    break;
	}
	if (TIFFReadEncodedStrip(
	    tif_, TIFFComputeStrip(tif_, row, 1), g, nrow*scanline) < 0
	) {
	    break;
	}
	if (TIFFReadEncodedStrip(
	    tif_, TIFFComputeStrip(tif_, row, 2), b, nrow*scanline) < 0
	) {
	    break;
	}
	(this->*put)(raster_ + y*w, r, g, b, Map, w, nrow, fromskew, toskew);
	y += (orientation_ == ORIENTATION_TOPLEFT ? -nrow : nrow);
    }
    delete buf;
    return true;
}
Пример #8
0
static void
svRGBSeparate(TIFF* tif, uint32* ss, int xsize, int ysize)
{
	tsize_t stripsize = TIFFStripSize(tif);
	unsigned char *rbuf = (unsigned char *)_TIFFmalloc(3*stripsize);
	unsigned char *gbuf = rbuf + stripsize;
	unsigned char *bbuf = gbuf + stripsize;
	register int y;

	for (y = 0; y <= ysize; y += rowsperstrip) {
		unsigned char *rp, *gp, *bp;
		register int x;
		register uint32 n;

		n = rowsperstrip;
		if (n > ysize-y+1)
			n = ysize-y+1;
		rp = rbuf; gp = gbuf; bp = bbuf;
		do {
			for (x = 0; x <= xsize; x++) {
				uint32 v = ss[x];
				rp[x] = v;
				gp[x] = v >> 8;
				bp[x] = v >> 16;
			}
			rp += xsize+1, gp += xsize+1, bp += xsize+1;
			ss += xsize+1;
		} while (--n);
		if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,0),
		    rbuf, stripsize) < 0)
			break;
		if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,1),
		    gbuf, stripsize) < 0)
			break;
		if (TIFFWriteEncodedStrip(tif, TIFFComputeStrip(tif,y,2),
		    bbuf, stripsize) < 0)
			break;
	}
	_TIFFfree(rbuf);
}
Пример #9
0
/*
 * Get a strip-organized image that has
 *  PlanarConfiguration contiguous if SamplesPerPixel > 1
 * or
 *  SamplesPerPixel == 1
 *
 *  Hacked from the tif_getimage.c file.
 *
 *    This is set up to allow us to just copy the data to the raster
 *    for 1-bit bitmaps
 */
static int
getStripContig1Bit(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
{
    TIFF* tif = img->tif;
    tileContigRoutine put = img->put.contig;
    uint16 orientation;
    uint32 row, y, nrow, rowstoread;
    uint32 pos;
    u_char* buf;
    uint32 rowsperstrip;
    uint32 imagewidth = img->width;
    tsize_t scanline;
    int32 fromskew, toskew;
    tstrip_t strip;
    tsize_t  stripsize;
    u_char* braster = (u_char*)raster; // byte wide raster
    uint32  wb = WIDTHBYTES(w);
    int ret = 1;

    buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif));
    if (buf == 0) {
        TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer");
        return (0);
    }
    y = setorientation(img, h);
    orientation = img->orientation;
    toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? wb+wb : wb-wb);
    TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    scanline = TIFFScanlineSize(tif);
    fromskew = (w < imagewidth ? imagewidth - w : 0)/8;
    for (row = 0; row < h; row += nrow)
    {
        rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
        nrow = (row + rowstoread > h ? h - row : rowstoread);
        strip = TIFFComputeStrip(tif,row+img->row_offset, 0);
        stripsize = ((row + img->row_offset)%rowsperstrip + nrow) * scanline;
        if (TIFFReadEncodedStrip(tif, strip, buf, stripsize ) < 0
            && img->stoponerr)
        {
            ret = 0;
            break;
        }

        pos = ((row + img->row_offset) % rowsperstrip) * scanline;
        (*put)(img, (uint32*)(braster+y*wb), 0, y, w, nrow, fromskew, toskew, buf + pos);
        y += (orientation == ORIENTATION_TOPLEFT ?-(int32) nrow : (int32) nrow);
    }
    _TIFFfree(buf);
    return (ret);
}
Пример #10
0
/*
 * Get a strip-organized image that has
 *  PlanarConfiguration contiguous if SamplesPerPixel > 1
 * or
 *  SamplesPerPixel == 1
 */ 
static int
gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
{
    TIFF* tif = img->tif;
    tileContigRoutine put = img->put.contig;
    uint16 orientation;
    uint32 row, y, nrow;
    u_char* buf;
    uint32 rowsperstrip;
    uint32 imagewidth = img->width;
    tsize_t scanline;
    int32 fromskew, toskew;

    buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif));
    if (buf == 0) {
    TIFFError(TIFFFileName(tif), "No space for strip buffer");
    return (0);
    }
    y = setorientation(img, h);
    orientation = img->orientation;
    toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? w+w : w-w);
    TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
    scanline = TIFFScanlineSize(tif);
    fromskew = (w < imagewidth ? imagewidth - w : 0);
    for (row = 0; row < h; row += rowsperstrip) {
    nrow = (row + rowsperstrip > h ? h - row : rowsperstrip);
    if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
    buf, nrow*scanline) < 0 && img->stoponerr)
    break;
    (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf);
    y += (orientation == ORIENTATION_TOPLEFT ?
    -(int32) nrow : (int32) nrow);
    }
    _TIFFfree(buf);
    return (1);
}
Пример #11
0
int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_ssize_t bytes) {
    TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
    char *filename = "tempfile.tif";
    char *mode = "r";
    TIFF *tiff;

    /* buffer is the encoded file, bytes is the length of the encoded file */
    /*     it all ends up in state->buffer, which is a uint8* from Imaging.h */

    TRACE(("in decoder: bytes %d\n", bytes));
    TRACE(("State: count %d, state %d, x %d, y %d, ystep %d\n", state->count, state->state,
           state->x, state->y, state->ystep));
    TRACE(("State: xsize %d, ysize %d, xoff %d, yoff %d \n", state->xsize, state->ysize,
           state->xoff, state->yoff));
    TRACE(("State: bits %d, bytes %d \n", state->bits, state->bytes));
    TRACE(("Buffer: %p: %c%c%c%c\n", buffer, (char)buffer[0], (char)buffer[1],(char)buffer[2], (char)buffer[3]));
    TRACE(("State->Buffer: %c%c%c%c\n", (char)state->buffer[0], (char)state->buffer[1],(char)state->buffer[2], (char)state->buffer[3]));
    TRACE(("Image: mode %s, type %d, bands: %d, xsize %d, ysize %d \n",
           im->mode, im->type, im->bands, im->xsize, im->ysize));
    TRACE(("Image: image8 %p, image32 %p, image %p, block %p \n",
           im->image8, im->image32, im->image, im->block));
    TRACE(("Image: pixelsize: %d, linesize %d \n",
           im->pixelsize, im->linesize));

    dump_state(clientstate);
    clientstate->size = bytes;
    clientstate->eof = clientstate->size;
    clientstate->loc = 0;
    clientstate->data = (tdata_t)buffer;
    clientstate->flrealloc = 0;
    dump_state(clientstate);

    TIFFSetWarningHandler(NULL);
    TIFFSetWarningHandlerExt(NULL);

    if (clientstate->fp) {
        TRACE(("Opening using fd: %d\n",clientstate->fp));
        lseek(clientstate->fp,0,SEEK_SET); // Sometimes, I get it set to the end.
        tiff = TIFFFdOpen(clientstate->fp, filename, mode);
    } else {
        TRACE(("Opening from string\n"));
        tiff = TIFFClientOpen(filename, mode,
                              (thandle_t) clientstate,
                              _tiffReadProc, _tiffWriteProc,
                              _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
                              _tiffMapProc, _tiffUnmapProc);
    }

    if (!tiff){
        TRACE(("Error, didn't get the tiff\n"));
        state->errcode = IMAGING_CODEC_BROKEN;
        return -1;
    }

    if (clientstate->ifd){
        int rv;
        uint32 ifdoffset = clientstate->ifd;
        TRACE(("reading tiff ifd %u\n", ifdoffset));
        rv = TIFFSetSubDirectory(tiff, ifdoffset);
        if (!rv){
            TRACE(("error in TIFFSetSubDirectory"));
            return -1;
        }
    }

    if (TIFFIsTiled(tiff)) {
        UINT32 x, y, tile_y, row_byte_size;
        UINT32 tile_width, tile_length, current_tile_width;
        UINT8 *new_data;

        TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tile_width);
        TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tile_length);

        // We could use TIFFTileSize, but for YCbCr data it returns subsampled data size
        row_byte_size = (tile_width * state->bits + 7) / 8;
        state->bytes = row_byte_size * tile_length;

        /* overflow check for malloc */
        if (state->bytes > INT_MAX - 1) {
            state->errcode = IMAGING_CODEC_MEMORY;
            TIFFClose(tiff);
            return -1;
        }

        /* realloc to fit whole tile */
        new_data = realloc (state->buffer, state->bytes);
        if (!new_data) {
            state->errcode = IMAGING_CODEC_MEMORY;
            TIFFClose(tiff);
            return -1;
        }

        state->buffer = new_data;

        TRACE(("TIFFTileSize: %d\n", state->bytes));

        for (y = state->yoff; y < state->ysize; y += tile_length) {
            for (x = state->xoff; x < state->xsize; x += tile_width) {
                if (ReadTile(tiff, x, y, (UINT32*) state->buffer) == -1) {
                    TRACE(("Decode Error, Tile at %dx%d\n", x, y));
                    state->errcode = IMAGING_CODEC_BROKEN;
                    TIFFClose(tiff);
                    return -1;
                }

                TRACE(("Read tile at %dx%d; \n\n", x, y));

                current_tile_width = min(tile_width, state->xsize - x);

                // iterate over each line in the tile and stuff data into image
                for (tile_y = 0; tile_y < min(tile_length, state->ysize - y); tile_y++) {
                    TRACE(("Writing tile data at %dx%d using tile_width: %d; \n", tile_y + y, x, current_tile_width));

                    // UINT8 * bbb = state->buffer + tile_y * row_byte_size;
                    // TRACE(("chars: %x%x%x%x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3]));

                    state->shuffle((UINT8*) im->image[tile_y + y] + x * im->pixelsize,
                       state->buffer + tile_y * row_byte_size,
                       current_tile_width
                    );
                }
            }
        }
    } else {
        UINT32 strip_row, row_byte_size;
        UINT8 *new_data;
        UINT32 rows_per_strip;

        TIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &rows_per_strip);
        TRACE(("RowsPerStrip: %u \n", rows_per_strip));

        // We could use TIFFStripSize, but for YCbCr data it returns subsampled data size
        row_byte_size = (state->xsize * state->bits + 7) / 8;
        state->bytes = rows_per_strip * row_byte_size;

        TRACE(("StripSize: %d \n", state->bytes));

        /* realloc to fit whole strip */
        new_data = realloc (state->buffer, state->bytes);
        if (!new_data) {
            state->errcode = IMAGING_CODEC_MEMORY;
            TIFFClose(tiff);
            return -1;
        }

        state->buffer = new_data;

        for (; state->y < state->ysize; state->y += rows_per_strip) {
            if (ReadStrip(tiff, state->y, (UINT32 *)state->buffer) == -1) {
                TRACE(("Decode Error, strip %d\n", TIFFComputeStrip(tiff, state->y, 0)));
                state->errcode = IMAGING_CODEC_BROKEN;
                TIFFClose(tiff);
                return -1;
            }

            TRACE(("Decoded strip for row %d \n", state->y));

            // iterate over each row in the strip and stuff data into image
            for (strip_row = 0; strip_row < min(rows_per_strip, state->ysize - state->y); strip_row++) {
                TRACE(("Writing data into line %d ; \n", state->y + strip_row));

                // UINT8 * bbb = state->buffer + strip_row * (state->bytes / rows_per_strip);
                // TRACE(("chars: %x %x %x %x\n", ((UINT8 *)bbb)[0], ((UINT8 *)bbb)[1], ((UINT8 *)bbb)[2], ((UINT8 *)bbb)[3]));

                state->shuffle((UINT8*) im->image[state->y + state->yoff + strip_row] +
                               state->xoff * im->pixelsize,
                               state->buffer + strip_row * row_byte_size,
                               state->xsize);
            }
        }
    }

    TIFFClose(tiff);
    TRACE(("Done Decoding, Returning \n"));
    // Returning -1 here to force ImageFile.load to break, rather than
    // even think about looping back around.
    return -1;
}
Пример #12
0
	bool CxImageTIF::Decode(CxFile * hFile)
	{
		//Comment this line if you need more information on errors
		// TIFFSetErrorHandler(NULL);	//<Patrick Hoffmann>

		//Open file and fill the TIFF structure
		// m_tif = TIFFOpen(imageFileName,"rb");
		TIFF* m_tif = _TIFFOpenEx(hFile, "rb");

		uint32 height=0;
		uint32 width=0;
		uint16 bitspersample=1;
		uint16 samplesperpixel=1;
		uint32 rowsperstrip=(uint32_t)-1;
		uint16 photometric=0;
		uint16 compression=1;
		uint16 orientation=ORIENTATION_TOPLEFT; //<vho>
		uint16 res_unit; //<Trifon>
		uint32 x, y;
		float resolution, offset;
		bool isRGB;
		uint8_t *bits;		//pointer to source data
		uint8_t *bits2;	//pointer to destination data

	  cx_try
	  {
		//check if it's a tiff file
		if (!m_tif)
			cx_throw("Error encountered while opening TIFF file");

		// <Robert Abram> - 12/2002 : get NumFrames directly, instead of looping
		// info.nNumFrames=0;
		// while(TIFFSetDirectory(m_tif,(uint16)info.nNumFrames)) info.nNumFrames++;
		info.nNumFrames = TIFFNumberOfDirectories(m_tif);

		if (!TIFFSetDirectory(m_tif, (uint16)info.nFrame))
			cx_throw("Error: page not present in TIFF file");			

		//get image info
		TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width);
		TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height);
		TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
		TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
		TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);   
		TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric);
		TIFFGetField(m_tif, TIFFTAG_ORIENTATION, &orientation);

		if (info.nEscape == -1) {
			// Return output dimensions only
			head.biWidth = width;
			head.biHeight = height;
			info.dwType = CXIMAGE_FORMAT_TIF;
			cx_throw("output dimensions returned");
		}

		TIFFGetFieldDefaulted(m_tif, TIFFTAG_RESOLUTIONUNIT, &res_unit);
		if (TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &resolution))
		{
			if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);
			SetXDPI((int32_t)resolution);
		}
		if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution))
		{
			if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);
			SetYDPI((int32_t)resolution);
		}

		if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset))	info.xOffset = (int32_t)offset;
		if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset))	info.yOffset = (int32_t)offset;

		head.biClrUsed=0;
		info.nBkgndIndex =-1;

		if (rowsperstrip>height){
			rowsperstrip=height;
			TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
		}

		isRGB = /*(bitspersample >= 8) && (VK: it is possible so for RGB to have < 8 bpp!)*/
			(photometric == PHOTOMETRIC_RGB) ||
			(photometric == PHOTOMETRIC_YCBCR) ||
			(photometric == PHOTOMETRIC_SEPARATED) ||
			(photometric == PHOTOMETRIC_LOGL) ||
			(photometric == PHOTOMETRIC_LOGLUV);

		if (isRGB){
			head.biBitCount=24;
		}else{
			if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)||(photometric==PHOTOMETRIC_PALETTE)){
				if	(bitspersample == 1){
					head.biBitCount=1;		//B&W image
					head.biClrUsed =2;
				} else if (bitspersample == 4) {
					head.biBitCount=4;		//16 colors gray scale
					head.biClrUsed =16;
				} else {
					head.biBitCount=8;		//gray scale
					head.biClrUsed =256;
				}
			} else if (bitspersample == 4) {
				head.biBitCount=4;			// 16 colors
				head.biClrUsed=16;
			} else {
				head.biBitCount=8;			//256 colors
				head.biClrUsed=256;
			}

			if ((bitspersample > 8) && (photometric==PHOTOMETRIC_PALETTE))	// + VK + (BIG palette! => convert to RGB)
			{	head.biBitCount=24;
				head.biClrUsed =0;
			}
		}

		if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding

		Create(width,height,head.biBitCount,CXIMAGE_FORMAT_TIF);	//image creation
		if (!pDib) cx_throw("CxImageTIF can't create image");

	#if CXIMAGE_SUPPORT_ALPHA
		if (samplesperpixel==4) AlphaCreate();	//add alpha support for 32bpp tiffs
		if (samplesperpixel==2 && bitspersample==8) AlphaCreate();	//add alpha support for 8bpp + alpha
	#endif //CXIMAGE_SUPPORT_ALPHA

		TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression);
		SetCodecOption(compression); // <DPR> save original compression type

		if (isRGB) {
			// Read the whole image into one big RGBA buffer using
			// the traditional TIFFReadRGBAImage() API that we trust.
			uint32* raster;		// retrieve RGBA image
			uint32 *row;

			raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32));
			if (raster == NULL) cx_throw("No space for raster buffer");
				
			// Read the image in one chunk into an RGBA array
			if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) {
					_TIFFfree(raster);
					cx_throw("Corrupted TIFF file!");
			}

			// read the raster lines and save them in the DIB
			// with RGB mode, we have to change the order of the 3 samples RGB
			row = &raster[0];
			bits2 = info.pImage;
			for (y = 0; y < height; y++) {

				if (info.nEscape){ // <vho> - cancel decoding
					_TIFFfree(raster);
					cx_throw("Cancelled");
				}

				bits = bits2;
				for (x = 0; x < width; x++) {
					*bits++ = (uint8_t)TIFFGetB(row[x]);
					*bits++ = (uint8_t)TIFFGetG(row[x]);
					*bits++ = (uint8_t)TIFFGetR(row[x]);
	#if CXIMAGE_SUPPORT_ALPHA
					if (samplesperpixel==4) AlphaSet(x,y,(uint8_t)TIFFGetA(row[x]));
	#endif //CXIMAGE_SUPPORT_ALPHA
				}
				row += width;
				bits2 += info.dwEffWidth;
			}
			_TIFFfree(raster);
		} else {
			int32_t BIG_palette = (bitspersample > 8) &&	// + VK
							  (photometric==PHOTOMETRIC_PALETTE);		
			if (BIG_palette && (bitspersample > 24))	// + VK
				cx_throw("Too big palette to handle");		// + VK

			RGBQuad *pal;
			pal=(RGBQuad*)calloc(BIG_palette ? 1<<bitspersample : 256,sizeof(RGBQuad)); 
				// ! VK: it coasts nothing but more correct to use 256 as temp palette storage
				// ! VK: but for case of BIG palette it just copied
			if (pal==NULL) cx_throw("Unable to allocate TIFF palette");

			int32_t bpp = bitspersample <= 8 ? bitspersample : 8; // + VK (to use instead of bitspersample for case of > 8)

			// set up the colormap based on photometric	
			switch(photometric) {
				case PHOTOMETRIC_MINISBLACK:	// bitmap and greyscale image types
				case PHOTOMETRIC_MINISWHITE:
					if (bitspersample == 1) {	// Monochrome image
						if (photometric == PHOTOMETRIC_MINISBLACK) {
							pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
						} else {
							pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
						}
					} else {		// need to build the scale for greyscale images
						if (photometric == PHOTOMETRIC_MINISBLACK) {
							for (int32_t i=0; i<(1<<bpp); i++){
								pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (uint8_t)(i*(255/((1<<bpp)-1)));
							}
						} else {
							for (int32_t i=0; i<(1<<bpp); i++){
								pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (uint8_t)(255-i*(255/((1<<bpp)-1)));
							}
						}
					}
					break;
				case PHOTOMETRIC_PALETTE:	// color map indexed
					uint16 *red;
					uint16 *green;
					uint16 *blue;
					TIFFGetField(m_tif, TIFFTAG_COLORMAP, &red, &green, &blue); 

					// Is the palette 16 or 8 bits ?
					bool Palette16Bits = /*false*/ BIG_palette;
					if (!BIG_palette) {
						int32_t n= 1<<bpp;
						while (n-- > 0) {
							if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) {
								Palette16Bits=true;
								break;
							}
						}
					}

					// load the palette in the DIB
					for (int32_t i = (1 << ( BIG_palette ? bitspersample : bpp )) - 1; i >= 0; i--) {
						if (Palette16Bits) {
							pal[i].rgbRed =(uint8_t) CVT(red[i]);
							pal[i].rgbGreen = (uint8_t) CVT(green[i]);
							pal[i].rgbBlue = (uint8_t) CVT(blue[i]);           
						} else {
							pal[i].rgbRed = (uint8_t) red[i];
							pal[i].rgbGreen = (uint8_t) green[i];
							pal[i].rgbBlue = (uint8_t) blue[i];        
						}
					}
					break;
			}
			if (!BIG_palette) { // + VK (BIG palette is stored until image is ready)
				SetPalette(pal,/*head.biClrUsed*/ 1<<bpp);	//palette assign // * VK
				free(pal); 
				pal = NULL; 
			}

			// read the tiff lines and save them in the DIB
			uint32 nrow;
			uint32 ys;
			int32_t line = CalculateLine(width, bitspersample * samplesperpixel);
			
			int32_t bitsize = TIFFStripSize(m_tif);
			//verify bitsize: could be wrong if StripByteCounts is missing.
			if (bitsize>(int32_t)(head.biSizeImage*samplesperpixel))
				bitsize = head.biSizeImage*samplesperpixel;
			if (bitsize<(int32_t)(info.dwEffWidth*rowsperstrip))
				bitsize = info.dwEffWidth*rowsperstrip;

			if ((bitspersample > 8) && (bitspersample != 16))	// + VK (for bitspersample == 9..15,17..32..64
				bitsize *= (bitspersample + 7)/8; 

			int32_t tiled_image = TIFFIsTiled(m_tif);
			uint32 tw=0, tl=0;
			uint8_t* tilebuf=NULL;
			if (tiled_image){
				TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw);
				TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl);
				rowsperstrip = tl;
				bitsize = TIFFTileSize(m_tif) * (int32_t)(1+width/tw);
				tilebuf = (uint8_t*)malloc(TIFFTileSize(m_tif));
			}
			
			bits = (uint8_t*)malloc(bitspersample==16? bitsize*2 : bitsize); // * VK
			uint8_t * bits16 = NULL;										  // + VK
			int32_t line16    = 0;											  // + VK

			if (!tiled_image && bitspersample==16) {					  // + VK +
				line16 = line;
				line   = CalculateLine(width, 8 * samplesperpixel);
				bits16 = bits;
				bits   = (uint8_t*)malloc(bitsize);
			}

			if (bits==NULL){
				if (bits16) free(bits16);								  // + VK
				if (pal)	free(pal);									  // + VK
				if (tilebuf)free(tilebuf);								  // + VK	
				cx_throw("CxImageTIF can't allocate memory");
			}

	#ifdef FIX_16BPP_DARKIMG // + VK: for each line, store shift count bits used to fix it
			uint8_t* row_shifts = NULL;
			if (bits16) row_shifts = (uint8_t*)malloc(height); 
	#endif

			for (ys = 0; ys < height; ys += rowsperstrip) {

				if (info.nEscape){ // <vho> - cancel decoding
					free(bits);
					cx_throw("Cancelled");
				}

				nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip);

				if (tiled_image){
					uint32 imagew = TIFFScanlineSize(m_tif);
					uint32 tilew  = TIFFTileRowSize(m_tif);
					int32_t iskew = imagew - tilew;
					uint8* bufp = (uint8*) bits;

					uint32 colb = 0;
					for (uint32 col = 0; col < width; col += tw) {
						if (TIFFReadTile(m_tif, tilebuf, col, ys, 0, 0) < 0){
							free(tilebuf);
							free(bits);
							cx_throw("Corrupted tiled TIFF file!");
						}

						if (colb + tw > imagew) {
							uint32 owidth = imagew - colb;
							uint32 oskew = tilew - owidth;
							TileToStrip(bufp + colb, tilebuf, nrow, owidth, oskew + iskew, oskew );
						} else {
							TileToStrip(bufp + colb, tilebuf, nrow, tilew, iskew, 0);
						}
						colb += tilew;
					}

				} else {
					if (TIFFReadEncodedStrip(m_tif, TIFFComputeStrip(m_tif, ys, 0), 
						(bits16? bits16 : bits), nrow * (bits16 ? line16 : line)) == -1) { // * VK

	#ifdef NOT_IGNORE_CORRUPTED
						free(bits);
						if (bits16) free(bits16);  // + VK
						cx_throw("Corrupted TIFF file!");
	#else
						break;
	#endif
					}
				}

				for (y = 0; y < nrow; y++) {
					int32_t offset=(nrow-y-1)*line;
					if ((bitspersample==16) && !BIG_palette) {	// * VK
						int32_t offset16 = (nrow-y-1)*line16;		// + VK
						if (bits16)	{							// + VK +
	#ifdef FIX_16BPP_DARKIMG
							int32_t the_shift;
							uint8_t hi_byte, hi_max=0;
							uint32_t xi;
							for (xi=0;xi<(uint32)line;xi++) {
								hi_byte = bits16[xi*2+offset16+1];
								if(hi_byte>hi_max)
									hi_max = hi_byte;
							}
							the_shift = (hi_max == 0) ? 8 : 0;
							if (!the_shift)
								while( ! (hi_max & 0x80) ) {
									the_shift++;
									hi_max <<= 1;
								}
							row_shifts[height-ys-nrow+y] = the_shift;
							the_shift = 8 - the_shift;
							for (xi=0;xi<(uint32)line;xi++) 
								bits[xi+offset]= ((bits16[xi*2+offset16+1]<<8) | bits16[xi*2+offset16]) >> the_shift;
	#else
							for (uint32_t xi=0;xi<(uint32)line;xi++) 
								bits[xi+offset]=bits16[xi*2+offset16+1];
	#endif
						} else {
							for (uint32_t xi=0;xi<width;xi++)
								bits[xi+offset]=bits[xi*2+offset+1];
								}
					}
					if (samplesperpixel==1) { 
						if (BIG_palette)
							if (bits16) {
								int32_t offset16 = (nrow-y-1)*line16;		// + VK
								MoveBitsPal( info.pImage + info.dwEffWidth * (height-ys-nrow+y),
										 bits16 + offset16, width, bitspersample, pal );
							} else
								MoveBitsPal( info.pImage + info.dwEffWidth * (height-ys-nrow+y),
										 bits + offset, width, bitspersample, pal );
						else if ((bitspersample == head.biBitCount) || 
							(bitspersample == 16))	//simple 8bpp, 4bpp image or 16bpp
							memcpy(info.pImage+info.dwEffWidth*(height-ys-nrow+y),bits+offset,min((unsigned)line, info.dwEffWidth));
						else
							MoveBits( info.pImage + info.dwEffWidth * (height-ys-nrow+y),
									  bits + offset, width, bitspersample );
					} else if (samplesperpixel==2) { //8bpp image with alpha layer
						int32_t xi=0;
						int32_t ii=0;
						int32_t yi=height-ys-nrow+y;
	#if CXIMAGE_SUPPORT_ALPHA
						if (!pAlpha) AlphaCreate();			// + VK
	#endif //CXIMAGE_SUPPORT_ALPHA
						while (ii<line){
							SetPixelIndex(xi,yi,bits[ii+offset]);
	#if CXIMAGE_SUPPORT_ALPHA
							AlphaSet(xi,yi,bits[ii+offset+1]);
	#endif //CXIMAGE_SUPPORT_ALPHA
							ii+=2;
							xi++;
							if (xi>=(int32_t)width){
								yi--;
								xi=0;
							}
						}
					} else { //photometric==PHOTOMETRIC_CIELAB
						if (head.biBitCount!=24){ //fix image
							Create(width,height,24,CXIMAGE_FORMAT_TIF);
	#if CXIMAGE_SUPPORT_ALPHA
							if (samplesperpixel==4) AlphaCreate();
	#endif //CXIMAGE_SUPPORT_ALPHA
						}

						int32_t xi=0;
						uint32 ii=0;
						int32_t yi=height-ys-nrow+y;
						RGBQuad c;
						int32_t l,a,b,bitsoffset;
						double p,cx,cy,cz,cr,cg,cb;
						while (ii</*line*/width){		// * VK
							bitsoffset = ii*samplesperpixel+offset;
							l=bits[bitsoffset];
							a=bits[bitsoffset+1];
							b=bits[bitsoffset+2];
							if (a>127) a-=256;
							if (b>127) b-=256;
							// lab to xyz
							p = (l/2.55 + 16) / 116.0;
							cx = pow( p + a * 0.002, 3);
							cy = pow( p, 3);
							cz = pow( p - b * 0.005, 3);
							// white point
							cx*=0.95047;
							//cy*=1.000;
							cz*=1.0883;
							// xyz to rgb
							cr =  3.240479 * cx - 1.537150 * cy - 0.498535 * cz;
							cg = -0.969256 * cx + 1.875992 * cy + 0.041556 * cz;
							cb =  0.055648 * cx - 0.204043 * cy + 1.057311 * cz;

							if ( cr > 0.00304 ) cr = 1.055 * pow(cr,0.41667) - 0.055;
								else            cr = 12.92 * cr;
							if ( cg > 0.00304 ) cg = 1.055 * pow(cg,0.41667) - 0.055;
								else            cg = 12.92 * cg;
							if ( cb > 0.00304 ) cb = 1.055 * pow(cb,0.41667) - 0.055;
								else            cb = 12.92 * cb;

							c.rgbRed  =(uint8_t)max(0,min(255,(int32_t)(cr*255)));
							c.rgbGreen=(uint8_t)max(0,min(255,(int32_t)(cg*255)));
							c.rgbBlue =(uint8_t)max(0,min(255,(int32_t)(cb*255)));

							SetPixelColor(xi,yi,c);
	#if CXIMAGE_SUPPORT_ALPHA
							if (samplesperpixel==4) AlphaSet(xi,yi,bits[bitsoffset+3]);
	#endif //CXIMAGE_SUPPORT_ALPHA
							ii++;
							xi++;
							if (xi>=(int32_t)width){
								yi--;
								xi=0;
							}
						}
					}
				}
			}
			free(bits);
			if (bits16) free(bits16);

	#ifdef FIX_16BPP_DARKIMG
			if (row_shifts && (samplesperpixel == 1) && (bitspersample==16) && !BIG_palette) {
				// 1. calculate maximum necessary shift
				int32_t min_row_shift = 8;
				for( y=0; y<height; y++ ) {
					if (min_row_shift > row_shifts[y]) min_row_shift = row_shifts[y];
				}
				// 2. for rows having less shift value, correct such rows:
				for( y=0; y<height; y++ ) {
					if (min_row_shift < row_shifts[y]) {
						int32_t need_shift = row_shifts[y] - min_row_shift;
						uint8_t* data = info.pImage + info.dwEffWidth * y;
						for( x=0; x<width; x++, data++ )
							*data >>= need_shift;
					}
				}
static void TIFFWriteOvrRow( TIFFOvrCache * psCache )

{
    int		nRet, iTileX, iTileY = psCache->nBlockOffset;
    unsigned char *pabyData;
    uint32	nBaseDirOffset;
    uint32 RowsInStrip;

/* -------------------------------------------------------------------- */
/*      If the output cache is multi-byte per sample, and the file      */
/*      being written to is of a different byte order than the current  */
/*      platform, we will need to byte swap the data.                   */
/* -------------------------------------------------------------------- */
    if( TIFFIsByteSwapped(psCache->hTIFF) )
    {
        if( psCache->nBitsPerPixel == 16 )
            TIFFSwabArrayOfShort( (uint16 *) psCache->pabyRow1Blocks,
                      (psCache->nBytesPerBlock * psCache->nSamples) / 2 );

        else if( psCache->nBitsPerPixel == 32 )
            TIFFSwabArrayOfLong( (uint32 *) psCache->pabyRow1Blocks,
                         (psCache->nBytesPerBlock * psCache->nSamples) / 4 );

        else if( psCache->nBitsPerPixel == 64 )
            TIFFSwabArrayOfDouble( (double *) psCache->pabyRow1Blocks,
                         (psCache->nBytesPerBlock * psCache->nSamples) / 8 );
    }

/* -------------------------------------------------------------------- */
/*      Record original directory position, so we can restore it at     */
/*      end.                                                            */
/* -------------------------------------------------------------------- */
    nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF );
    nRet = TIFFSetSubDirectory( psCache->hTIFF, psCache->nDirOffset );
    assert( nRet == 1 );

/* -------------------------------------------------------------------- */
/*      Write blocks to TIFF file.                                      */
/* -------------------------------------------------------------------- */
	for( iTileX = 0; iTileX < psCache->nBlocksPerRow; iTileX++ )
	{
		int nTileID;

		if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE)
		{
			int iSample;

			for( iSample = 0; iSample < psCache->nSamples; iSample++ )
			{
				pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, iSample );

				if( psCache->bTiled )
				{
					nTileID = TIFFComputeTile( psCache->hTIFF,
					    iTileX * psCache->nBlockXSize,
					    iTileY * psCache->nBlockYSize,
					    0, (tsample_t) iSample );
					TIFFWriteEncodedTile( psCache->hTIFF, nTileID,
					    pabyData,
					    TIFFTileSize(psCache->hTIFF) );
				}
				else
				{
					nTileID = TIFFComputeStrip( psCache->hTIFF,
					    iTileY * psCache->nBlockYSize,
					    (tsample_t) iSample );
					RowsInStrip=psCache->nBlockYSize;
					if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize)
						RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize;
					TIFFWriteEncodedStrip( psCache->hTIFF, nTileID,
					    pabyData,
					    TIFFVStripSize(psCache->hTIFF,RowsInStrip) );
				}
			}

		}
		else
		{
			pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, 0 );

			if( psCache->bTiled )
			{
				nTileID = TIFFComputeTile( psCache->hTIFF,
				    iTileX * psCache->nBlockXSize,
				    iTileY * psCache->nBlockYSize,
				    0, 0 );
				TIFFWriteEncodedTile( psCache->hTIFF, nTileID,
				    pabyData,
				    TIFFTileSize(psCache->hTIFF) );
			}
			else
			{
				nTileID = TIFFComputeStrip( psCache->hTIFF,
				    iTileY * psCache->nBlockYSize,
				    0 );
				RowsInStrip=psCache->nBlockYSize;
				if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize)
					RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize;
				TIFFWriteEncodedStrip( psCache->hTIFF, nTileID,
				    pabyData,
				    TIFFVStripSize(psCache->hTIFF,RowsInStrip) );
			}
		}
	}
	/* TODO: add checks on error status return of TIFFWriteEncodedTile and TIFFWriteEncodedStrip */

/* -------------------------------------------------------------------- */
/*      Rotate buffers.                                                 */
/* -------------------------------------------------------------------- */
    pabyData = psCache->pabyRow1Blocks;
    psCache->pabyRow1Blocks = psCache->pabyRow2Blocks;
    psCache->pabyRow2Blocks = pabyData;

    _TIFFmemset( pabyData, 0, psCache->nBytesPerRow );

    psCache->nBlockOffset++;

/* -------------------------------------------------------------------- */
/*      Restore access to original directory.                           */
/* -------------------------------------------------------------------- */
    TIFFFlush( psCache->hTIFF );
    /* TODO: add checks on error status return of TIFFFlush */
    TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset );
    /* TODO: add checks on error status return of TIFFSetSubDirectory */
}
Пример #14
0
bool CxImageTIF::Decode(CxFile * hFile)
{
    //Comment this line if you need more information on errors
    // TIFFSetErrorHandler(NULL);	//<Patrick Hoffmann>

    //Open file and fill the TIFF structure
    // m_tif = TIFFOpen(imageFileName,"rb");
    TIFF* m_tif = _TIFFOpenEx(hFile, "rb");

    uint32 height=0;
    uint32 width=0;
    uint16 bitspersample=1;
    uint16 samplesperpixel=1;
    uint32 rowsperstrip=(DWORD)-1;
    uint16 photometric=0;
    uint16 compression=1;
    uint16 orientation=ORIENTATION_TOPLEFT; //<vho>
    uint16 res_unit; //<Trifon>
    uint32 x, y;
    float resolution, offset;
    BOOL isRGB;
    BYTE *bits;		//pointer to source data
    BYTE *bits2;	//pointer to destination data

  try{
    //check if it's a tiff file
    if (!m_tif)
        throw "Error encountered while opening TIFF file";

    // <Robert Abram> - 12/2002 : get NumFrames directly, instead of looping
    // info.nNumFrames=0;
    // while(TIFFSetDirectory(m_tif,(uint16)info.nNumFrames)) info.nNumFrames++;
    info.nNumFrames = TIFFNumberOfDirectories(m_tif);

    if (!TIFFSetDirectory(m_tif, (uint16)info.nFrame))
        throw "Error: page not present in TIFF file";			

    //get image info
    TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height);
    TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
    TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
    TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);   
    TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric);
    TIFFGetField(m_tif, TIFFTAG_ORIENTATION, &orientation);

    if (info.nEscape == -1) {
        // Return output dimensions only
        head.biWidth = width;
        head.biHeight = height;
        throw "output dimensions returned";
    }

    TIFFGetFieldDefaulted(m_tif, TIFFTAG_RESOLUTIONUNIT, &res_unit);
    if (TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &resolution))
    {
        if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);
        SetXDPI((long)resolution);
    }
    if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution))
    {
        if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);
        SetYDPI((long)resolution);
    }

    if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset))	info.xOffset = (long)offset;
    if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset))	info.yOffset = (long)offset;

    head.biClrUsed=0;
    info.nBkgndIndex =-1;

    if (rowsperstrip>height){
        rowsperstrip=height;
        TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
    }

    isRGB = (bitspersample >= 8) &&
        (photometric == PHOTOMETRIC_RGB) ||
        (photometric == PHOTOMETRIC_YCBCR) ||
        (photometric == PHOTOMETRIC_SEPARATED) ||
        (photometric == PHOTOMETRIC_LOGL) ||
        (photometric == PHOTOMETRIC_LOGLUV);

    if (isRGB){
        head.biBitCount=24;
    }else{
        if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)){
            if	(bitspersample == 1){
                head.biBitCount=1;		//B&W image
                head.biClrUsed =2;
            } else if (bitspersample == 4) {
                head.biBitCount=4;		//16 colors gray scale
                head.biClrUsed =16;
            } else {
                head.biBitCount=8;		//gray scale
                head.biClrUsed =256;
            }
        } else if (bitspersample == 4) {
            head.biBitCount=4;			// 16 colors
            head.biClrUsed=16;
        } else {
            head.biBitCount=8;			//256 colors
            head.biClrUsed=256;
        }
    }

    if (info.nEscape) throw "Cancelled"; // <vho> - cancel decoding

    Create(width,height,head.biBitCount,CXIMAGE_FORMAT_TIF);	//image creation
    if (!pDib) throw "CxImageTIF can't create image";

#if CXIMAGE_SUPPORT_ALPHA
    if (samplesperpixel==4) AlphaCreate();	//add alpha support for 32bpp tiffs
    if (samplesperpixel==2 && bitspersample==8) AlphaCreate();	//add alpha support for 8bpp + alpha
#endif //CXIMAGE_SUPPORT_ALPHA

    TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression);
    SetCodecOption(compression); // <DPR> save original compression type

    if (isRGB) {
        // Read the whole image into one big RGBA buffer using
        // the traditional TIFFReadRGBAImage() API that we trust.
        uint32* raster;		// retrieve RGBA image
        uint32 *row;

        raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32));
        if (raster == NULL) throw "No space for raster buffer";
            
        // Read the image in one chunk into an RGBA array
        if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) {
                _TIFFfree(raster);
                throw "Corrupted TIFF file!";
        }

        // read the raster lines and save them in the DIB
        // with RGB mode, we have to change the order of the 3 samples RGB
        row = &raster[0];
        bits2 = info.pImage;
        for (y = 0; y < height; y++) {

            if (info.nEscape){ // <vho> - cancel decoding
                _TIFFfree(raster);
                throw "Cancelled";
            }

            bits = bits2;
            for (x = 0; x < width; x++) {
                *bits++ = (BYTE)TIFFGetB(row[x]);
                *bits++ = (BYTE)TIFFGetG(row[x]);
                *bits++ = (BYTE)TIFFGetR(row[x]);
#if CXIMAGE_SUPPORT_ALPHA
                if (samplesperpixel==4) AlphaSet(x,y,(BYTE)TIFFGetA(row[x]));
#endif //CXIMAGE_SUPPORT_ALPHA
            }
            row += width;
            bits2 += info.dwEffWidth;
        }
        _TIFFfree(raster);
    } else {
        RGBQUAD *pal;
        pal=(RGBQUAD*)calloc(256,sizeof(RGBQUAD));
        if (pal==NULL) throw "Unable to allocate TIFF palette";

        // set up the colormap based on photometric	
        switch(photometric) {
            case PHOTOMETRIC_MINISBLACK:	// bitmap and greyscale image types
            case PHOTOMETRIC_MINISWHITE:
                if (bitspersample == 1) {	// Monochrome image
                    if (photometric == PHOTOMETRIC_MINISBLACK) {
                        pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
                    } else {
                        pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
                    }
                } else {		// need to build the scale for greyscale images
                    if (photometric == PHOTOMETRIC_MINISBLACK) {
                        for (DWORD i=0; i<head.biClrUsed; i++){
                            pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(i*(255/(head.biClrUsed-1)));
                        }
                    } else {
                        for (DWORD i=0; i<head.biClrUsed; i++){
                            pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(255-i*(255/(head.biClrUsed-1)));
                        }
                    }
                }
                break;
            case PHOTOMETRIC_PALETTE:	// color map indexed
                uint16 *red;
                uint16 *green;
                uint16 *blue;
                TIFFGetField(m_tif, TIFFTAG_COLORMAP, &red, &green, &blue); 

                // Is the palette 16 or 8 bits ?
                BOOL Palette16Bits = FALSE;
                int n=1<<bitspersample;
                while (n-- > 0) {
                    if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) {
                        Palette16Bits=TRUE;
                        break;
                    }
                }

                // load the palette in the DIB
                for (int i = (1 << bitspersample) - 1; i >= 0; i--) {
                    if (Palette16Bits) {
                        pal[i].rgbRed =(BYTE) CVT(red[i]);
                        pal[i].rgbGreen = (BYTE) CVT(green[i]);
                        pal[i].rgbBlue = (BYTE) CVT(blue[i]);           
                    } else {
                        pal[i].rgbRed = (BYTE) red[i];
                        pal[i].rgbGreen = (BYTE) green[i];
                        pal[i].rgbBlue = (BYTE) blue[i];        
                    }
                }
                break;
        }
        SetPalette(pal,head.biClrUsed);	//palette assign
        free(pal);

        // read the tiff lines and save them in the DIB
        uint32 nrow;
        uint32 ys;
        int line = CalculateLine(width, bitspersample * samplesperpixel);
        long bitsize= TIFFStripSize(m_tif);
        //verify bitsize: could be wrong if StripByteCounts is missing.
        if (bitsize>(long)(head.biSizeImage*samplesperpixel)) bitsize=head.biSizeImage*samplesperpixel;

        int tiled_image = TIFFIsTiled(m_tif);
        uint32 tw, tl;
        BYTE* tilebuf;
        if (tiled_image){
            TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw);
            TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl);
            rowsperstrip = tl;
            bitsize = TIFFTileSize(m_tif) * (int)(1+width/tw);
            tilebuf = (BYTE*)malloc(TIFFTileSize(m_tif));
        }
        
        bits = (BYTE*)malloc(bitsize);
        if (bits==NULL){
            throw "CxImageTIF can't allocate memory";
        }

        for (ys = 0; ys < height; ys += rowsperstrip) {

            if (info.nEscape){ // <vho> - cancel decoding
                free(bits);
                throw "Cancelled";
            }

            nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip);

            if (tiled_image){
                uint32 imagew = TIFFScanlineSize(m_tif);
                uint32 tilew  = TIFFTileRowSize(m_tif);
                int iskew = imagew - tilew;
                uint8* bufp = (uint8*) bits;

                uint32 colb = 0;
                for (uint32 col = 0; col < width; col += tw) {
                    if (TIFFReadTile(m_tif, tilebuf, col, ys, 0, 0) < 0){
                        free(tilebuf);
                        free(bits);
                        throw "Corrupted tiled TIFF file!";
                    }

                    if (colb + tw > imagew) {
                        uint32 owidth = imagew - colb;
                        uint32 oskew = tilew - owidth;
                        TileToStrip(bufp + colb, tilebuf, nrow, owidth, oskew + iskew, oskew );
                    } else {
                        TileToStrip(bufp + colb, tilebuf, nrow, tilew, iskew, 0);
                    }
                    colb += tilew;
                }

            } else {
                if (TIFFReadEncodedStrip(m_tif, TIFFComputeStrip(m_tif, ys, 0), bits, nrow * line) == -1) {
                    free(bits);
                    throw "Corrupted TIFF file!";
                }
            }

            for (y = 0; y < nrow; y++) {
                long offset=(nrow-y-1)*line;
                if (bitspersample==16) for (DWORD xi=0;xi<width;xi++) bits[xi+offset]=bits[xi*2+offset+1];
                if (samplesperpixel==1) { //simple 8bpp image
                    memcpy(info.pImage+info.dwEffWidth*(height-ys-nrow+y),bits+offset,info.dwEffWidth);
                } else if (samplesperpixel==2) { //8bpp image with alpha layer
                    int xi=0;
                    int ii=0;
                    int yi=height-ys-nrow+y;
                    while (ii<line){
                        SetPixelIndex(xi,yi,bits[ii+offset]);
#if CXIMAGE_SUPPORT_ALPHA
                        AlphaSet(xi,yi,bits[ii+offset+1]);
#endif //CXIMAGE_SUPPORT_ALPHA
                        ii+=2;
                        xi++;
                        if (xi>=(int)width){
                            yi--;
                            xi=0;
                        }
                    }
                } else { //photometric==PHOTOMETRIC_CIELAB
                    if (head.biBitCount!=24){ //fix image
                        Create(width,height,24,CXIMAGE_FORMAT_TIF);
#if CXIMAGE_SUPPORT_ALPHA
                        if (samplesperpixel==4) AlphaCreate();
#endif //CXIMAGE_SUPPORT_ALPHA
                    }

                    int xi=0;
                    int ii=0;
                    int yi=height-ys-nrow+y;
                    RGBQUAD c;
                    int l,a,b,bitsoffset;
                    double p,cx,cy,cz,cr,cg,cb;
                    while (ii<line){
                        bitsoffset = ii*samplesperpixel+offset;
                        l=bits[bitsoffset];
                        a=bits[bitsoffset+1];
                        b=bits[bitsoffset+2];
                        if (a>127) a-=256;
                        if (b>127) b-=256;
                        // lab to xyz
                        p = (l/2.55 + 16) / 116.0;
                        cx = pow( p + a * 0.002, 3);
                        cy = pow( p, 3);
                        cz = pow( p - b * 0.005, 3);
                        // white point
                        cx*=0.95047;
                        //cy*=1.000;
                        cz*=1.0883;
                        // xyz to rgb
                        cr =  3.240479 * cx - 1.537150 * cy - 0.498535 * cz;
                        cg = -0.969256 * cx + 1.875992 * cy + 0.041556 * cz;
                        cb =  0.055648 * cx - 0.204043 * cy + 1.057311 * cz;

                        if ( cr > 0.00304 ) cr = 1.055 * pow(cr,0.41667) - 0.055;
                            else            cr = 12.92 * cr;
                        if ( cg > 0.00304 ) cg = 1.055 * pow(cg,0.41667) - 0.055;
                            else            cg = 12.92 * cg;
                        if ( cb > 0.00304 ) cb = 1.055 * pow(cb,0.41667) - 0.055;
                            else            cb = 12.92 * cb;

                        c.rgbRed  =(BYTE)max(0,min(255,(int)(cr*255)));
                        c.rgbGreen=(BYTE)max(0,min(255,(int)(cg*255)));
                        c.rgbBlue =(BYTE)max(0,min(255,(int)(cb*255)));

                        SetPixelColor(xi,yi,c);
#if CXIMAGE_SUPPORT_ALPHA
                        if (samplesperpixel==4) AlphaSet(xi,yi,bits[bitsoffset+3]);
#endif //CXIMAGE_SUPPORT_ALPHA
                        ii++;
                        xi++;
                        if (xi>=(int)width){
                            yi--;
                            xi=0;
                        }
                    }
                }
            }
        }
        free(bits);
        if (tiled_image) free(tilebuf);

        switch(orientation){
        case ORIENTATION_TOPRIGHT: /* row 0 top, col 0 rhs */
            Mirror();
            break;
        case ORIENTATION_BOTRIGHT: /* row 0 bottom, col 0 rhs */
            Flip();
            Mirror();
            break;
        case ORIENTATION_BOTLEFT: /* row 0 bottom, col 0 lhs */
            Flip();
            break;
        case ORIENTATION_LEFTTOP: /* row 0 lhs, col 0 top */
            RotateRight();
            Mirror();
            break;
        case ORIENTATION_RIGHTTOP: /* row 0 rhs, col 0 top */
            RotateLeft();
            break;
        case ORIENTATION_RIGHTBOT: /* row 0 rhs, col 0 bottom */
            RotateLeft();
            Mirror();
            break;
        case ORIENTATION_LEFTBOT: /* row 0 lhs, col 0 bottom */
            RotateRight();
            break;
        }

    }
  } catch (char *message) {
      strncpy(info.szLastError,message,255);
      if (m_tif) TIFFClose(m_tif);
      if (info.nEscape==-1) return true;
      return false;
  }
    TIFFClose(m_tif);
    return true;
}
Пример #15
0
HDIB LoadTIFFinDIB(LPSTR lpFileName)
{
    TIFF          *tif;
    unsigned long imageLength;
    unsigned long imageWidth;
    unsigned int  BitsPerSample;
    unsigned long LineSize;
    unsigned int  SamplePerPixel;
    unsigned long RowsPerStrip;
    int           PhotometricInterpretation;
    long          nrow;
    unsigned long row;
    char          *buf;
    LPBITMAPINFOHEADER lpDIB;
    HDIB          hDIB;
    char          *lpBits;
    HGLOBAL       hStrip;
    int           i,l;
    int           Align;

    tif = TIFFOpen(lpFileName, "r");

    if (!tif)
        goto TiffOpenError;

    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
    TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample);
    TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);
    TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);
    TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation);

    LineSize = TIFFScanlineSize(tif); //Number of byte in ine line

    SamplePerPixel = (int) (LineSize/imageWidth);

    //Align = Number of byte to add at the end of each line of the DIB
    Align = 4 - (LineSize % 4);
    if (Align == 4)	Align = 0;


    //Create a new DIB
    hDIB = CreateDIB((DWORD) imageWidth, (DWORD) imageLength, (WORD)
                     (BitsPerSample*SamplePerPixel));
    lpDIB  = (LPBITMAPINFOHEADER) GlobalLock(hDIB);
    if (!lpDIB)
        goto OutOfDIBMemory;

    if (lpDIB)
        lpBits = FindDIBBits((LPSTR) lpDIB);

    //In the tiff file the lines are save from up to down
    //In a DIB the lines must be save from down to up
    if (lpBits)
    {
        lpBits = FindDIBBits((LPSTR) lpDIB);
        lpBits+=((imageWidth*SamplePerPixel)+Align)*(imageLength-1);
        //now lpBits pointe on the bottom line

        hStrip = GlobalAlloc(GHND,TIFFStripSize(tif));
        buf = GlobalLock(hStrip);

        if (!buf)
            goto OutOfBufMemory;

        //PhotometricInterpretation = 2 image is RGB
        //PhotometricInterpretation = 3 image have a color palette
        if (PhotometricInterpretation == 3)
        {
            uint16* red;
            uint16* green;
            uint16* blue;
            int16 i;
            LPBITMAPINFO lpbmi;
            int   Palette16Bits;

            TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue);

            //Is the palette 16 or 8 bits ?
            if (checkcmap(1<<BitsPerSample, red, green, blue) == 16)
                Palette16Bits = TRUE;
            else
                Palette16Bits = FALSE;

            lpbmi = (LPBITMAPINFO)lpDIB;

            //load the palette in the DIB
            for (i = (1<<BitsPerSample)-1; i >= 0; i--)
            {
                if (Palette16Bits)
                {
                    lpbmi->bmiColors[i].rgbRed =(BYTE) CVT(red[i]);
                    lpbmi->bmiColors[i].rgbGreen = (BYTE) CVT(green[i]);
                    lpbmi->bmiColors[i].rgbBlue = (BYTE) CVT(blue[i]);
                }
                else
                {
                    lpbmi->bmiColors[i].rgbRed = (BYTE) red[i];
                    lpbmi->bmiColors[i].rgbGreen = (BYTE) green[i];
                    lpbmi->bmiColors[i].rgbBlue = (BYTE) blue[i];
                }
            }

        }

        //read the tiff lines and save them in the DIB
        //with RGB mode, we have to change the order of the 3 samples RGB
        <=> BGR
        for (row = 0; row < imageLength; row += RowsPerStrip)
        {
            nrow = (row + RowsPerStrip > imageLength ? imageLength - row :
                    RowsPerStrip);
            if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0),
                                     buf, nrow*LineSize)==-1)
            {
                goto TiffReadError;
            }
            else
            {
                for (l = 0; l < nrow; l++)
                {
                    if (SamplePerPixel  == 3)
                        for (i=0; i< (int) (imageWidth); i++)
                        {
                            lpBits[i*SamplePerPixel+0]=buf[l*LineSize+i*Sample
                                                           PerPixel+2];
                            lpBits[i*SamplePerPixel+1]=buf[l*LineSize+i*Sample
                                                           PerPixel+1];
                            lpBits[i*SamplePerPixel+2]=buf[l*LineSize+i*Sample
                                                           PerPixel+0];
                        }
                    else
                        memcpy(lpBits, &buf[(int) (l*LineSize)], (int)
                               imageWidth*SamplePerPixel);

                    lpBits-=imageWidth*SamplePerPixel+Align;

                }
            }
        }
        GlobalUnlock(hStrip);
        GlobalFree(hStrip);
        GlobalUnlock(hDIB);
        TIFFClose(tif);
    }
Пример #16
0
// Internal function used to load the Tiff.
ILboolean iLoadTiffInternal()
{
	TIFF	 *tif;
	uint16	 photometric, planarconfig, orientation;
	uint16	 samplesperpixel, bitspersample, *sampleinfo, extrasamples;
	uint32	 w, h, d, linesize, tilewidth, tilelength;
	ILubyte  *pImageData;
	ILuint	 i, ProfileLen, DirCount = 0;
	void	 *Buffer;
	ILimage  *Image, *TempImage;
	ILushort si;
        ILfloat  x_position, x_resolution, y_position, y_resolution;
	//TIFFRGBAImage img;
	//char emsg[1024];

	// to avoid high order bits garbage when used as shorts
	w = h = d = linesize = tilewidth = tilelength = 0;

	if (iCurImage == NULL) {
		ilSetError(IL_ILLEGAL_OPERATION);
		return IL_FALSE;
	}

	TIFFSetWarningHandler (NULL);
	TIFFSetErrorHandler   (NULL);

	//for debugging only
	//TIFFSetWarningHandler(warningHandler);
	//TIFFSetErrorHandler(errorHandler);

	tif = iTIFFOpen("r");
	if (tif == NULL) {
		ilSetError(IL_COULD_NOT_OPEN_FILE);
		return IL_FALSE;
	}

	do {
		DirCount++;
	} while (TIFFReadDirectory(tif));

	/*
	 if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
		 TIFFClose(tif);
		 return IL_FALSE;
	}
	Image = iCurImage;
	for (i = 1; i < DirCount; i++) {
		 Image->Next = ilNewImage(1, 1, 1, 1, 1);
		if (Image->Next == NULL) {
			TIFFClose(tif);
			return IL_FALSE;
		}
		Image = Image->Next;
	}
	iCurImage->NumNext = DirCount - 1;
	*/
	Image = NULL;
	for (i = 0; i < DirCount; i++) {
		TIFFSetDirectory(tif, (tdir_t)i);
		TIFFGetField(tif, TIFFTAG_IMAGEWIDTH,  &w);
		TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);

		TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH,		&d); //TODO: d is ignored...
		TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
		TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE,	&bitspersample);
		TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,	&extrasamples, &sampleinfo);
		TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, 	&orientation);

		linesize = TIFFScanlineSize(tif);
		
		//added 2003-08-31
		//1 bpp tiffs are not neccessarily greyscale, they can
		//have a palette (photometric == 3)...get this information
		TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC,  &photometric);
		TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);

		//special-case code for frequent data cases that may be read more
		//efficiently than with the TIFFReadRGBAImage() interface.
		
		//added 2004-05-12
		//Get tile sizes and use TIFFReadRGBAImage() for tiled images for now
		tilewidth = w; tilelength = h;
		TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH,  &tilewidth);
		TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tilelength);


		if (extrasamples == 0
			&& samplesperpixel == 1  //luminance or palette
			&& (bitspersample == 8 || bitspersample == 1 || bitspersample == 16)
			&& (photometric == PHOTOMETRIC_MINISWHITE
				|| photometric == PHOTOMETRIC_MINISBLACK
				|| photometric == PHOTOMETRIC_PALETTE)
			&& (orientation == ORIENTATION_TOPLEFT || orientation == ORIENTATION_BOTLEFT)
			&& tilewidth == w && tilelength == h
			) {
			ILubyte* strip;
			tsize_t stripsize;
			ILuint y;
			uint32 rowsperstrip, j, linesread;

			//TODO: 1 bit/pixel images should not be stored as 8 bits...
			//(-> add new format)
			if (!Image) {
				int type = IL_UNSIGNED_BYTE;
				if (bitspersample == 16) type = IL_UNSIGNED_SHORT;
				if (!ilTexImage(w, h, 1, 1, IL_LUMINANCE, type, NULL)) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = iCurImage;
			}
			else {
				Image->Next = ilNewImage(w, h, 1, 1, 1);
				if (Image->Next == NULL) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = Image->Next;
			}

			if (photometric == PHOTOMETRIC_PALETTE) { //read palette
				uint16 *red, *green, *blue;
				//ILboolean is16bitpalette = IL_FALSE;
				ILubyte *entry;
				uint32 count = 1 << bitspersample, j;
		
				TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue);

				Image->Format = IL_COLOUR_INDEX;
				Image->Pal.PalSize = (count)*3;
				Image->Pal.PalType = IL_PAL_RGB24;
				Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize);
				entry = Image->Pal.Palette;
				for (j = 0; j < count; ++j) {
					entry[0] = (ILubyte)(red[j] >> 8);
					entry[1] = (ILubyte)(green[j] >> 8);
					entry[2] = (ILubyte)(blue[j] >> 8);

					entry += 3;
				}
			}

			TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
			stripsize = TIFFStripSize(tif);

			strip = (ILubyte*)ialloc(stripsize);

			if (bitspersample == 8 || bitspersample == 16) {
				ILubyte *dat = Image->Data;
				for (y = 0; y < h; y += rowsperstrip) {
					//the last strip may contain less data if the image
					//height is not evenly divisible by rowsperstrip
					if (y + rowsperstrip > h) {
						stripsize = linesize*(h - y);
						linesread = h - y;
					}
					else
						linesread = rowsperstrip;

					if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) {
						ilSetError(IL_LIB_TIFF_ERROR);
						ifree(strip);
						TIFFClose(tif);
						return IL_FALSE;
					}

					if (photometric == PHOTOMETRIC_MINISWHITE) { //invert channel
						uint32 k, t2;
						for (j = 0; j < linesread; ++j) {
							t2 = j*linesize;
							//this works for 16bit images as well: the two bytes
							//making up a pixel can be inverted independently
							for (k = 0; k < Image->Bps; ++k)
								dat[k] = ~strip[t2 + k];
							dat += w;
						}
					}
					else
						for(j = 0; j < linesread; ++j)
							memcpy(&Image->Data[(y + j)*Image->Bps], &strip[j*linesize], Image->Bps);
				}
			}
			else if (bitspersample == 1) {
				//TODO: add a native format to devil, so we don't have to
				//unpack the values here
				ILubyte mask, curr, *dat = Image->Data;
				uint32 k, sx, t2;
				for (y = 0; y < h; y += rowsperstrip) {
					//the last strip may contain less data if the image
					//height is not evenly divisible by rowsperstrip
					if (y + rowsperstrip > h) {
						stripsize = linesize*(h - y);
						linesread = h - y;
					}
					else
						linesread = rowsperstrip;

					if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) {
						ilSetError(IL_LIB_TIFF_ERROR);
						ifree(strip);
						TIFFClose(tif);
						return IL_FALSE;
					}

					for (j = 0; j < linesread; ++j) {
						k = 0;
						sx = 0;
						t2 = j*linesize;
						while (k < w) {
							curr = strip[t2 + sx];
							if (photometric == PHOTOMETRIC_MINISWHITE)
								curr = ~curr;
							for (mask = 0x80; mask != 0 && k < w; mask >>= 1){
								if((curr & mask) != 0)
									dat[k] = 255;
								else
									dat[k] = 0;
								++k;
							}
							++sx;
						}
						dat += w;
					}
				}
			}
Пример #17
0
void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
                               int nOverviews, int * panOvList,
                               int nBitsPerPixel, 
                               int nSamples, TIFFOvrCache ** papoRawBIs,
                               int nSXOff, int nSYOff,
                               unsigned char *pabySrcTile,
                               int nBlockXSize, int nBlockYSize,
                               int nSampleFormat, const char * pszResampling )
    
{
    int		iOverview, iSample;

    for( iSample = 0; iSample < nSamples; iSample++ )
    {
        /*
         * We have to read a tile/strip for each sample for
         * PLANARCONFIG_SEPARATE.  Otherwise, we just read all the samples
         * at once when handling the first sample.
         */
        if( nPlanarConfig == PLANARCONFIG_SEPARATE || iSample == 0 )
        {
            if( TIFFIsTiled(hTIFF) )
            {
                TIFFReadEncodedTile( hTIFF,
                                     TIFFComputeTile(hTIFF, nSXOff, nSYOff,
                                                     0, iSample ),
                                     pabySrcTile,
                                     TIFFTileSize(hTIFF));
            }
            else
            {
                TIFFReadEncodedStrip( hTIFF,
                                      TIFFComputeStrip(hTIFF, nSYOff, iSample),
                                      pabySrcTile,
                                      TIFFStripSize(hTIFF) );
            }
        }

        /*        
         * Loop over destination overview layers
         */
        for( iOverview = 0; iOverview < nOverviews; iOverview++ )
        {
            TIFFOvrCache *poRBI = papoRawBIs[iOverview];
            unsigned char *pabyOTile;
            int	nTXOff, nTYOff, nOXOff, nOYOff, nOMult;
            int	nOBlockXSize = poRBI->nBlockXSize;
            int	nOBlockYSize = poRBI->nBlockYSize;
            int	nSkewBits, nSampleByteOffset; 

            /*
             * Fetch the destination overview tile
             */
            nOMult = panOvList[iOverview];
            nOXOff = (nSXOff/nOMult) / nOBlockXSize;
            nOYOff = (nSYOff/nOMult) / nOBlockYSize;
            pabyOTile = TIFFGetOvrBlock( poRBI, nOXOff, nOYOff, iSample );
                
            /*
             * Establish the offset into this tile at which we should
             * start placing data.
             */
            nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
            nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;

            /*
             * Figure out the skew (extra space between ``our samples'') and
             * the byte offset to the first sample.
             */
            assert( (nBitsPerPixel % 8) == 0 );
            if( nPlanarConfig == PLANARCONFIG_SEPARATE )
            {
                nSkewBits = 0;
                nSampleByteOffset = 0;
            }
            else
            {
                nSkewBits = nBitsPerPixel * (nSamples-1);
                nSampleByteOffset = (nBitsPerPixel/8) * iSample;
            }
            
            /*
             * Perform the downsampling.
             */
#ifdef DBMALLOC
            malloc_chain_check( 1 );
#endif
            TIFF_DownSample( pabySrcTile + nSampleByteOffset,
                             nBlockXSize, nBlockYSize,
                             nSkewBits, nBitsPerPixel, pabyOTile,
                             poRBI->nBlockXSize, poRBI->nBlockYSize,
                             nTXOff, nTYOff,
                             nOMult, nSampleFormat, pszResampling );
#ifdef DBMALLOC
            malloc_chain_check( 1 );
#endif            
        }
    }
}
Пример #18
0
static
void TIFF_WriteOverview( TIFF *hTIFF, int nSamples, RawBlockedImage **papoRBI,
                         int bTiled, int nCompressFlag, int nPhotometric,
                         unsigned short *panRed,
                         unsigned short *panGreen,
                         unsigned short *panBlue,
                         int bUseSubIFDs )

{
    int		iSample;
    RawBlockedImage	*poRBI = papoRBI[0];

    /* -------------------------------------------------------------------- */
    /*      Setup TIFF fields.                                              */
    /* -------------------------------------------------------------------- */
    TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, poRBI->GetXSize() );
    TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, poRBI->GetYSize() );
    TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG,
                  PLANARCONFIG_SEPARATE );

    TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, poRBI->GetBitsPerPixel() );
    TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
    TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );

    if( bTiled )
    {
        TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, poRBI->GetBlockXSize() );
        TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, poRBI->GetBlockYSize() );
    }
    else
        TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, poRBI->GetBlockYSize() );

    TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE );

    /* -------------------------------------------------------------------- */
    /*	Write color table if one is present.				*/
    /* -------------------------------------------------------------------- */
    if( panRed != NULL )
    {
        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
    }

    /* -------------------------------------------------------------------- */
    /*      Write blocks to TIFF file.                                      */
    /* -------------------------------------------------------------------- */
    for( iSample = 0; iSample < nSamples; iSample++ )
    {
        int		iTileX, iTileY;

        poRBI = papoRBI[iSample];

        for( iTileY = 0;
                iTileY*poRBI->GetBlockYSize() < poRBI->GetYSize();
                iTileY++ )
        {
            for( iTileX = 0;
                    iTileX*poRBI->GetBlockXSize() < poRBI->GetXSize();
                    iTileX++ )
            {
                unsigned char	*pabyData = poRBI->GetTile( iTileX, iTileY );
                int	nTileID;

                if( bTiled )
                {
                    nTileID =
                        TIFFComputeTile(hTIFF,
                                        iTileX * poRBI->GetBlockXSize(),
                                        iTileY * poRBI->GetBlockYSize(),
                                        0, iSample );
                    TIFFWriteEncodedTile( hTIFF, nTileID,
                                          pabyData, TIFFTileSize(hTIFF) );
                }
                else
                {
                    nTileID =
                        TIFFComputeStrip(hTIFF, iTileY*poRBI->GetBlockYSize(),
                                         iSample);

                    TIFFWriteEncodedStrip( hTIFF, nTileID,
                                           pabyData, TIFFStripSize( hTIFF ) );
                }
            }
        }
    }

    TIFFWriteDirectory( hTIFF );
}
Пример #19
0
Image *Read (IStream *file, const Image::ReadOptions& options)
{
    int                   nrow;
    int                   result = 0;
    long                  LineSize;
    TIFF                  *tif;
    Image                 *image ;
    uint16                BitsPerSample;
    uint16                BytesPerSample = 1;
    uint16                PhotometricInterpretation;
    uint16                SamplePerPixel;
    uint16                Orientation;
    uint32                RowsPerStrip;
    unsigned int          width;
    unsigned int          height;

    // TODO - TIFF files probably have some gamma info in them by default, but we're currently ignorant about that.
    // Until that is fixed, use whatever the user has chosen as default.
    GammaCurvePtr gamma;
    if (options.gammacorrect && options.defaultGamma)
        gamma = TranscodingGammaCurve::Get(options.workingGamma, options.defaultGamma);

    // [CLi] TIFF is specified to use associated (= premultiplied) alpha, so that's the preferred mode to use for the image container unless the user overrides
    // (e.g. to handle a non-compliant file).
    bool premul = true;
    if (options.premultiplyOverride)
        premul = options.premultiply;

    // Rather than have libTIFF complain about tags it doesn't understand,
    // we just suppress all the warnings.
    TIFFSetWarningHandler(SuppressTIFFWarnings);
    TIFFSetErrorHandler(SuppressTIFFWarnings);

    // Open and do initial processing
    tif = TIFFClientOpen("Dummy File Name", "r", file,
        Tiff_Read, Tiff_Write, Tiff_Seek, Tiff_Close,
        Tiff_Size, Tiff_Map, Tiff_Unmap);
    if (!tif)
        return (NULL) ;

    // Get basic information about the image
    int ExtraSamples, ExtraSampleInfo;
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
    TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample);
    TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);
    TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation);
    TIFFGetField(tif, TIFFTAG_ORIENTATION, &Orientation);
    TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &SamplePerPixel);
    TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &ExtraSamples, &ExtraSampleInfo);

    // don't support more than 16 bits per sample
    if (BitsPerSample == 16)
    {
        BytesPerSample = 2 ;
        options.warnings.push_back ("Warning: reading 16 bits/sample TIFF file; components crunched to 8");
    }

    LineSize = TIFFScanlineSize(tif);
    assert (SamplePerPixel == (int) (LineSize / width) / BytesPerSample);
    // SamplePerPixel = (int)(LineSize / width);

#if 0
    // For now we are ignoring the orientation of the image...
    switch (Orientation)
    {
    case ORIENTATION_TOPLEFT:
        break;
    case ORIENTATION_TOPRIGHT:
        break;
    case ORIENTATION_BOTRIGHT:
        break;
    case ORIENTATION_BOTLEFT:
        break;
    case ORIENTATION_LEFTTOP:
        break;
    case ORIENTATION_RIGHTTOP:
        break;
    case ORIENTATION_RIGHTBOT:
        break;
    case ORIENTATION_LEFTBOT:
        break;
    default:
        break;
    }
#endif

    //PhotometricInterpretation = 2 image is RGB
    //PhotometricInterpretation = 3 image have a color palette
    if (PhotometricInterpretation == PHOTOMETRIC_PALETTE && (TIFFIsTiled(tif) == 0))
    {
        uint16 *red, *green, *blue;

        //load the palette
        int cmap_len = (1 << BitsPerSample);

        TIFFGetField(tif, TIFFTAG_COLORMAP, &red, &green, &blue);

        vector<Image::RGBMapEntry> colormap ;
        Image::RGBMapEntry entry;

        // I may be mistaken, but it appears that alpha/opacity information doesn't
        // appear in a Paletted Tiff image.  Well - if it does, it's not as easy to
        // get at as RGB.
        // Read the palette
        // Is the palette 16 or 8 bits ?
        if (checkcmap(cmap_len, red, green, blue) == 16)
        {
            for (int i=0;i<cmap_len;i++)
            {
                entry.red   = IntDecode(gamma, red[i],   65535);
                entry.green = IntDecode(gamma, green[i], 65535);
                entry.blue  = IntDecode(gamma, blue[i],  65535);
                colormap.push_back (entry);
            }
        }
        else
        {
            for (int i=0;i<cmap_len;i++)
            {
                entry.red   = IntDecode(gamma, red[i],   255);
                entry.green = IntDecode(gamma, green[i], 255);
                entry.blue  = IntDecode(gamma, blue[i],  255);
                colormap.push_back (entry);
            }
        }

        Image::ImageDataType imagetype = options.itype;
        if (imagetype == Image::Undefined)
            imagetype = Image::Colour_Map;
        image = Image::Create (width, height, imagetype, colormap) ;
        image->SetPremultiplied(premul); // specify whether the color map data has premultiplied alpha

        boost::scoped_array<unsigned char> buf (new unsigned char [TIFFStripSize(tif)]);

        //read the tiff lines and save them in the image
        //with RGB mode, we have to change the order of the 3 samples RGB <=> BGR
        for (int row=0;row<height;row+=RowsPerStrip)
        {
            nrow = (row + (int)RowsPerStrip > height ? height - row : RowsPerStrip);
            TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, row, 0), buf.get(), nrow * LineSize);
            for (int l = 0, offset = 0; l < nrow ; l++, offset += LineSize)
                for (int x = 0 ; x < width ; x++)
                    image->SetIndexedValue (x, row+l, buf[offset+x]) ;
        }
    }
    else
    {
        // Allocate the row buffers for the image
        boost::scoped_array<uint32> buf (new uint32 [width * height]) ;

        Image::ImageDataType imagetype = options.itype;
        if (imagetype == Image::Undefined)
            imagetype = ( GammaCurve::IsNeutral(gamma) ? Image::RGBA_Int8 : Image::RGBA_Gamma8 );
        image = Image::Create (width, height, imagetype) ;
        image->SetPremultiplied(premul); // set desired storage mode regarding alpha premultiplication
        image->TryDeferDecoding(gamma, 255); // try to have gamma adjustment being deferred until image evaluation.

        TIFFReadRGBAImage(tif, width, height, buf.get(), 0);
        uint32 abgr, *tbuf = buf.get();
        for (int i=height-1;i>=0;i--)
        {
            for (int j=0;j<width;j++)
            {
                abgr = *tbuf++;
                unsigned int b = (unsigned char)TIFFGetB(abgr);
                unsigned int g = (unsigned char)TIFFGetG(abgr);
                unsigned int r = (unsigned char)TIFFGetR(abgr);
                unsigned int a = (unsigned char)TIFFGetA(abgr);
                SetEncodedRGBAValue(image, j, i, gamma, 255, r, g, b, a, premul) ;
            }
        }
    }

    TIFFClose(tif);

    return (image) ;
}
Пример #20
0
BOOL CImageTIFF::Read(FILE* stream)
{
	TIFF* m_tif = TIFFOpenEx(stream, "rb");

	uint32 height=0;
	uint32 width=0;
	uint16 bitspersample=1;
	uint16 samplesperpixel=1;
	uint32 rowsperstrip=-1;
	uint16 photometric=0;
	uint16 compression=1;
	uint32 x, y;
	BOOL isRGB;
	BYTE *bits;		//pointer to source data
	BYTE *bits2;	//pointer to destination data

  try{
	//check if it's a tiff file
	if (!m_tif)
		throw "Error encountered while opening TIFF file";

	m_info.nNumFrames=0;
	while(TIFFSetDirectory(m_tif,(uint16)m_info.nNumFrames)) m_info.nNumFrames++;


	if (!TIFFSetDirectory(m_tif, (uint16)m_info.nFrame))
		throw "Error: page not present in TIFF file";			

	//get image m_info
	TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression);
	if (compression == COMPRESSION_LZW)
		throw "LZW compression is no longer supported due to Unisys patent enforcement";			

	TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width);
	TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height);
	TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
	TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
	TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);   
	TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric);

	m_header.biWidth  = width;
	m_header.biHeight = height;
	m_header.biClrUsed=0;
	m_info.nBkgndIndex =-1;

	isRGB = (bitspersample >= 8) &&
		(photometric == PHOTOMETRIC_RGB) ||
		(photometric == PHOTOMETRIC_YCBCR) ||
		(photometric == PHOTOMETRIC_SEPARATED) ||
		(photometric == PHOTOMETRIC_LOGLUV);

	if (isRGB){
		m_header.biBitCount=24;
		m_info.bColorType = COLORTYPE_COLOR;
	}else{
		m_info.bColorType = COLORTYPE_PALETTE;
		if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)){
			if	(bitspersample == 1){
				m_header.biBitCount=1;		//B&W image
				m_header.biClrUsed =2;
			} else {
				m_header.biBitCount=8;		//gray scale
				m_header.biClrUsed =256;
			}
		} else if (bitspersample == 4) {
			m_header.biBitCount=4;			// 16 colors
			m_header.biClrUsed=16;
		} else {
			m_header.biBitCount=8;			//256 colors
			m_header.biClrUsed=256;
		}
	}

	Create(m_header.biWidth,m_header.biHeight,m_header.biBitCount);	//image creation

	if (isRGB) {
		// Read the whole image into one big RGBA buffer using
		// the traditional TIFFReadRGBAImage() API that we trust.
		uint32* raster;		// retrieve RGBA image
		uint32 *row;

		raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32));
		if (raster == NULL) throw "No space for raster buffer";
			
		// Read the image in one chunk into an RGBA array
		if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) {
				_TIFFfree(raster);
				throw "Corrupted TIFF file!";
		}

		// read the raster lines and save them in the DIB
		// with RGB mode, we have to change the order of the 3 samples RGB
		row = &raster[0];
		bits2 = m_info.pImage;
		for (y = 0; y < height; y++) {
			bits = bits2;
			for (x = 0; x < width; x++) {
				*bits++ = (BYTE)TIFFGetB(row[x]);
				*bits++ = (BYTE)TIFFGetG(row[x]);
				*bits++ = (BYTE)TIFFGetR(row[x]);
			}
			row += width;
			bits2 += m_info.dwEffWidth;
		}
		_TIFFfree(raster);
	} else {
		RGBQUAD *pal;
		pal=(RGBQUAD*)calloc(256,sizeof(RGBQUAD));
		if (pal==NULL) throw "Unable to allocate TIFF palette";

		// set up the colormap based on photometric	
		switch(photometric) {
			case PHOTOMETRIC_MINISBLACK:	// bitmap and greyscale image types
			case PHOTOMETRIC_MINISWHITE:
				if (bitspersample == 1) {	// Monochrome image
					if (photometric == PHOTOMETRIC_MINISBLACK) {
						pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
					} else {
						pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
					}
				} else {		// need to build the scale for greyscale images
					if (photometric == PHOTOMETRIC_MINISBLACK) {
						for (int i = 0; i < 256; i++) {
							pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = i;
						}
					} else {
						for (int i = 0; i < 256; i++) {
							pal[i].rgbRed =	pal[i].rgbGreen = pal[i].rgbBlue = 255 - i;
						}
					}
				}
				break;
			case PHOTOMETRIC_PALETTE:	// color map indexed
				uint16 *red;
				uint16 *green;
				uint16 *blue;
				TIFFGetField(m_tif, TIFFTAG_COLORMAP, &red, &green, &blue); 

				// Is the palette 16 or 8 bits ?
				BOOL Palette16Bits = FALSE;
				int n=1<<bitspersample;
				while (n-- > 0) {
					if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) {
						Palette16Bits=TRUE;
						break;
					}
				}

				// load the palette in the DIB
				for (int i = (1 << bitspersample) - 1; i >= 0; i--) {
					if (Palette16Bits) {
						pal[i].rgbRed =(BYTE) CVT(red[i]);
						pal[i].rgbGreen = (BYTE) CVT(green[i]);
						pal[i].rgbBlue = (BYTE) CVT(blue[i]);           
					} else {
						pal[i].rgbRed = (BYTE) red[i];
						pal[i].rgbGreen = (BYTE) green[i];
						pal[i].rgbBlue = (BYTE) blue[i];        
					}
				}
				break;
		}
		SetPalette(pal,m_header.biClrUsed);	//palette assign
		free(pal);

		// read the tiff lines and save them in the DIB
		uint32 nrow;
		uint32 ys;
		int line = CalculateLine(width, bitspersample * samplesperpixel);
//		int pitch = CalculatePitch(line);
		long bitsize= TIFFStripSize(m_tif);
		bits = (BYTE*)malloc(bitsize);

		for (ys = 0; ys < height; ys += rowsperstrip) {
			nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip);
			if (TIFFReadEncodedStrip(m_tif, TIFFComputeStrip(m_tif, ys, 0), bits, nrow * line) == -1) {
				free(bits);
				throw "Corrupted TIFF file!";
			}
			for (y = 0; y < nrow; y++) {
				memcpy(m_info.pImage+m_info.dwEffWidth*(height-ys-nrow+y),bits+(nrow-y-1)*line,line);
			}
			/*if (m_header.biClrUsed==2){
				for (y = 0; y < nrow; y++) { for (x = 0; x < width; x++) {
					SetPixelIndex(x,y+ys,(bits[y*line+(x>>3)]>>(7-x%8))&0x01);
			}}}*/
		}
		free(bits);
	}
  } catch (char *message) {
	  strncpy(m_info.szLastError,message,255);
	  if (m_tif)	TIFFClose(m_tif);
	  return FALSE;
  }
	TIFFClose(m_tif);
	return TRUE;
}
Пример #21
0
// Internal function used to load the Tiff.
ILboolean iLoadTiffInternal()
{
	TIFF		*tif;
	uint16	w, h, d, photometric, planarconfig;
	uint16	samplesperpixel, bitspersample, *sampleinfo, extrasamples;
	ILubyte		*pImageData;
	ILuint		i, ProfileLen, DirCount = 0;
	ILvoid		*Buffer;
	ILimage		*Image;
	ILushort	si;
//TIFFRGBAImage img;
//char emsg[1024];


	if (iCurImage == NULL) {
		ilSetError(IL_ILLEGAL_OPERATION);
		return IL_FALSE;
	}

	TIFFSetWarningHandler(NULL);
	TIFFSetErrorHandler(NULL);

	//for debugging only
	//TIFFSetWarningHandler(warningHandler);
	//TIFFSetErrorHandler(errorHandler);

		tif = iTIFFOpen("r");
		if (tif == NULL) {
		ilSetError(IL_COULD_NOT_OPEN_FILE);
		return IL_FALSE;
	}

	do {
		DirCount++;
	} while (TIFFReadDirectory(tif));

/*
	if (!ilTexImage(1, 1, 1, 1, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
		TIFFClose(tif);
		return IL_FALSE;
	}
	Image = iCurImage;
	for (i = 1; i < DirCount; i++) {
		Image->Next = ilNewImage(1, 1, 1, 1, 1);
		if (Image->Next == NULL) {
			TIFFClose(tif);
			return IL_FALSE;
		}
		Image = Image->Next;
	}
	iCurImage->NumNext = DirCount - 1;
*/
	Image = NULL;
	for (i = 0; i < DirCount; i++) {
		TIFFSetDirectory(tif, (tdir_t)i);
		TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
		TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
		TIFFGetFieldDefaulted(tif, TIFFTAG_IMAGEDEPTH, &d);
		TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
		TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &bitspersample);
		TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo);

		//added 2003-08-31
		//1 bpp tiffs are not neccessarily greyscale, they can
		//have a palette (photometric == 3)...get this information
		TIFFGetFieldDefaulted(tif, TIFFTAG_PHOTOMETRIC, &photometric);
		TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);

		if (samplesperpixel - extrasamples == 1) { //luminance or palette
			ILubyte* strip;
			tsize_t stripsize;
			ILuint y;
			uint32 rowsperstrip;

			if(!Image) {
				if(!ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				iCurImage->NumNext = 0;
				Image = iCurImage;
			}
			else {
				Image->Next = ilNewImage(w, h, 1, 1, 1);
				if(Image->Next == NULL) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = Image->Next;
				iCurImage->NumNext++;
			}

			TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
			stripsize = TIFFStripSize(tif);

			strip = ialloc(stripsize);

			for(y = 0; y < h; y += rowsperstrip) {
				//if(y + rowsperstrip > h)
				//	stripsize = (stripsize*(h - y))/rowsperstrip;
				if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), strip, stripsize) == -1) {
					ilSetError(IL_LIB_TIFF_ERROR);
					ifree(strip);
					TIFFClose(tif);
					return IL_FALSE;
				}
			}

			ifree(strip);
		}
		else {//rgb or rgba

			if(!Image) {
				if(!ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				iCurImage->NumNext = 0;
				Image = iCurImage;
			}
			else {
				Image->Next = ilNewImage(w, h, 1, 4, 1);
				if(Image->Next == NULL) {
					TIFFClose(tif);
					return IL_FALSE;
				}
				Image = Image->Next;
				iCurImage->NumNext++;
			}

			if (samplesperpixel == 4) {
				TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo);
				if (!sampleinfo || sampleinfo[0] == EXTRASAMPLE_UNSPECIFIED) {
					si = EXTRASAMPLE_ASSOCALPHA;
					TIFFSetField(tif, TIFFTAG_EXTRASAMPLES, 1, &si);
				}
			}
/*
			if (!ilResizeImage(Image, Image->Width, Image->Height, 1, 4, 1)) {
				TIFFClose(tif);
				return IL_FALSE;
			}*/
			Image->Format = IL_RGBA;
			Image->Type = IL_UNSIGNED_BYTE;

			// Siigron: added u_long cast to shut up compiler warning
			//2003-08-31: changed flag from 1 (exit on error) to 0 (keep decoding)
			//this lets me view text.tif, but can give crashes with unsupported
			//tiffs...
			//2003-09-04: keep flag 1 for official version for now
			if (!TIFFReadRGBAImage(tif, Image->Width, Image->Height, (uint32*)Image->Data, 1)) {
				TIFFClose(tif);
				ilSetError(IL_LIB_TIFF_ERROR);
				return IL_FALSE;
			}
		} //else rgb or rgba

		if (TIFFGetField(tif, TIFFTAG_ICCPROFILE, &ProfileLen, &Buffer)) {
			if (Image->Profile && Image->ProfileSize)
				ifree(Image->Profile);
			Image->Profile = (ILubyte*)ialloc(ProfileLen);
			if (Image->Profile == NULL) {
				TIFFClose(tif);
				return IL_FALSE;
			}

			memcpy(Image->Profile, Buffer, ProfileLen);
			Image->ProfileSize = ProfileLen;

			//removed on 2003-08-24 as explained in bug 579574 on sourceforge
			//_TIFFfree(Buffer);
		}

		Image->Origin = IL_ORIGIN_LOWER_LEFT;  // eiu...dunno if this is right
/*
		Image = Image->Next;
		if (Image == NULL)  // Should never happen except when we reach the end, but check anyway.
			break;*/
	} //for tiff directories

	//TODO: put switch into the loop??
	switch (samplesperpixel)
	{
		case 1:
			//added 2003-08-31 to keep palettized tiffs colored
			/*
			if(photometric != 3)
				ilConvertImage(IL_LUMINANCE, IL_UNSIGNED_BYTE);
			else //strip alpha as tiff supports no alpha palettes
				ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);*/
			break;

		case 3:
			//TODO: why the ifdef??
#ifdef __LITTLE_ENDIAN__
			ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
#endif			
			break; 

		case 4:
			pImageData = iCurImage->Data;
//removed on 2003-08-26...why was this here? libtiff should and does
//take care of these things???
/*			
			//invert alpha
			#ifdef __LITTLE_ENDIAN__
			pImageData += 3;
#endif			
			for (i = iCurImage->Width * iCurImage->Height; i > 0; i--) {
				*pImageData ^= 255;
				pImageData += 4;
			}
*/
			break;
	}

	TIFFClose(tif);

	ilFixImage();

	return IL_TRUE;
}