Ejemplo n.º 1
0
void TifReader::readLine(char *buffer, int x0, int x1, int shrink)
{
	if (this->m_info.m_bitsPerSample == 16 && this->m_info.m_samplePerPixel >= 3) {
		std::vector<short> app(4 * (m_info.m_lx));
		readLine(&app[0], x0, x1, shrink);

		TPixel64 *pixin = (TPixel64 *)&app[0];

		TPixel32 *pixout = (TPixel32 *)buffer;
		for (int j = 0; j < x0; j++) {
			pixout++;
			pixin++;
		}

		for (int i = 0; i < (x1 - x0) + 1; i++)
			*pixout++ = PixelConverter<TPixel32>::from(*pixin++);

		return;
	}

	assert(shrink > 0);

	const int pixelSize = 4;
	int stripRowSize = m_rowLength * pixelSize;

	if (m_row < m_info.m_y0 || m_row > m_info.m_y1) {
		memset(buffer, 0, (x1 - x0 + 1) * pixelSize);
		m_row++;
		return;
	}

	int stripIndex = m_row / m_rowsPerStrip;
	if (m_stripIndex != stripIndex) {
		m_stripIndex = stripIndex;

		if (TIFFIsTiled(m_tiff)) {
			uint32 tileWidth = 0, tileHeight = 0;
			TIFFGetField(m_tiff, TIFFTAG_TILEWIDTH, &tileWidth);
			TIFFGetField(m_tiff, TIFFTAG_TILELENGTH, &tileHeight);
			assert(tileWidth > 0 && tileHeight > 0);

			int tileSize = tileWidth * tileHeight;
			std::unique_ptr<uint32[]> tile(new uint32[tileSize]);

			int x = 0;
			int y = tileHeight * m_stripIndex;

			int lastTy = std::min((int)tileHeight, m_info.m_ly - y);

			while (x < m_info.m_lx) {
				int ret = TIFFReadRGBATile(m_tiff, x, y, tile.get());
				assert(ret);

				int tileRowSize = std::min((int)tileWidth, (int)(m_info.m_lx - x)) * pixelSize;

				for (int ty = 0; ty < lastTy; ++ty) {
					memcpy(
						m_stripBuffer + (ty * m_rowLength + x) * pixelSize,
						(UCHAR *)tile.get() + ty * tileWidth * pixelSize,
						tileRowSize);
				}

				x += tileWidth;
			}
		} else {
			int y = m_rowsPerStrip * m_stripIndex;
			int ok = TIFFReadRGBAStrip(m_tiff, y, (uint32 *)m_stripBuffer);
			assert(ok);
		}
	}

	uint16 orient = ORIENTATION_TOPLEFT;
	TIFFGetField(m_tiff, TIFFTAG_ORIENTATION, &orient);

	int r = m_rowsPerStrip - 1 - (m_row % m_rowsPerStrip);
	switch (orient) // Pretty weak check for top/bottom orientation
	{
	case ORIENTATION_TOPLEFT:
	case ORIENTATION_TOPRIGHT:
	case ORIENTATION_LEFTTOP:
	case ORIENTATION_RIGHTTOP:
		// We have to invert the fixed BOTTOM-UP returned by TIFF functions - since this function is
		// supposed to ignore orientation issues (which are managed outside).

		// The last tiles row will actually start at the END OF THE IMAGE (not necessarily at
		// m_rowsPerStrip multiples). So, we must adjust for that.

		r = std::min(m_rowsPerStrip, m_info.m_ly - m_rowsPerStrip * m_stripIndex) - 1 -
			(m_row % m_rowsPerStrip);
		break;

	case ORIENTATION_BOTRIGHT:
	case ORIENTATION_BOTLEFT:
	case ORIENTATION_RIGHTBOT:
	case ORIENTATION_LEFTBOT:
		r = m_row % m_rowsPerStrip;
		break;
	}

	TPixel32 *pix = (TPixel32 *)buffer;
	uint32 *v = (uint32 *)(m_stripBuffer + r * stripRowSize);

	pix += x0;
	v += x0;

	int width = (x1 < x0) ? (m_info.m_lx - 1) / shrink + 1 : (x1 - x0) / shrink + 1;

	for (int i = 0; i < width; i++) {
		uint32 c = *v;
		pix->r = (UCHAR)TIFFGetR(c);
		pix->g = (UCHAR)TIFFGetG(c);
		pix->b = (UCHAR)TIFFGetB(c);
		pix->m = (UCHAR)TIFFGetA(c);

		v += shrink;
		pix += shrink;
	}

	m_row++;
}
Ejemplo n.º 2
0
void TifReader::open(FILE *file)
{
	int fd = fileno(file);
#if 0
	m_tiff = TIFFFdOpenNoCloseProc(fd, "", "rb");
#else
	m_tiff = TIFFFdOpen(dup(fd), "", "rb");
#endif
	if (!m_tiff) {
		std::string str("Tiff file closed");
		throw(str);
	}

	uint32 w = 0, h = 0, rps = 0;
	uint16 bps = 0, spp = 0;
	uint32 tileWidth = 0, tileLength = 0;

	//TIFFSetDirectory(m_tiff,1);
	//TIFFGetField(m_tiff, TIFFTAG_PAGENUMBER, &pn);
	//int pn = TIFFNumberOfDirectories(m_tiff);
	//TIFFSetDirectory(m_tiff,1);
	TIFFGetField(m_tiff, TIFFTAG_IMAGEWIDTH, &w);
	TIFFGetField(m_tiff, TIFFTAG_IMAGELENGTH, &h);
	TIFFGetField(m_tiff, TIFFTAG_BITSPERSAMPLE, &bps);
	TIFFGetField(m_tiff, TIFFTAG_SAMPLESPERPIXEL, &spp);
	TIFFGetField(m_tiff, TIFFTAG_ROWSPERSTRIP, &rps);
	//int stripCount = TIFFNumberOfStrips(m_tiff);
	//int tileCount = TIFFNumberOfTiles(m_tiff);
	TIFFGetField(m_tiff, TIFFTAG_TILEWIDTH, &tileWidth);
	TIFFGetField(m_tiff, TIFFTAG_TILELENGTH, &tileLength);
	Tiio::TifWriterProperties *prop = new Tiio::TifWriterProperties();
	m_info.m_properties = prop;
	uint16 orient = Tiio::TOP2BOTTOM;
	if (TIFFGetField(m_tiff, TIFFTAG_ORIENTATION, &orient)) {
		switch (orient) {
		case ORIENTATION_TOPLEFT: /* row 0 top, col 0 lhs */
			prop->m_orientation.setValue(TNZ_INFO_ORIENT_TOPLEFT);
			m_rowOrder = Tiio::TOP2BOTTOM;
			break;
		case ORIENTATION_TOPRIGHT: /* row 0 top, col 0 rhs */
			prop->m_orientation.setValue(TNZ_INFO_ORIENT_TOPRIGHT);
			m_rowOrder = Tiio::TOP2BOTTOM;
			break;
		case ORIENTATION_LEFTTOP: /* row 0 lhs, col 0 top */
			prop->m_orientation.setValue(TNZ_INFO_ORIENT_LEFTTOP);
			m_rowOrder = Tiio::TOP2BOTTOM;
			break;
		case ORIENTATION_RIGHTTOP: /* row 0 rhs, col 0 top */
			prop->m_orientation.setValue(TNZ_INFO_ORIENT_RIGHTTOP);
			m_rowOrder = Tiio::TOP2BOTTOM;
			break;

		case ORIENTATION_BOTRIGHT: /* row 0 bottom, col 0 rhs */
			prop->m_orientation.setValue(TNZ_INFO_ORIENT_BOTRIGHT);
			m_rowOrder = Tiio::BOTTOM2TOP;
			break;
		case ORIENTATION_BOTLEFT: /* row 0 bottom, col 0 lhs */
			prop->m_orientation.setValue(TNZ_INFO_ORIENT_BOTLEFT);
			m_rowOrder = Tiio::BOTTOM2TOP;
			break;
		case ORIENTATION_RIGHTBOT: /* row 0 rhs, col 0 bottom */
			prop->m_orientation.setValue(TNZ_INFO_ORIENT_RIGHTBOT);
			m_rowOrder = Tiio::BOTTOM2TOP;
			break;
		case ORIENTATION_LEFTBOT: /* row 0 lhs, col 0 bottom */
			prop->m_orientation.setValue(TNZ_INFO_ORIENT_LEFTBOT);
			m_rowOrder = Tiio::BOTTOM2TOP;
			break;
		default:
			prop->m_orientation.setValue(TNZ_INFO_ORIENT_NONE);
			m_rowOrder = Tiio::TOP2BOTTOM;
			break;
		}
	}

	USHORT compression;
	TIFFGetField(m_tiff, TIFFTAG_COMPRESSION, &compression);
	switch (compression) {
	case COMPRESSION_LZW:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_LZW);
		break;
	case COMPRESSION_PACKBITS:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_PACKBITS);
		break;
	case COMPRESSION_THUNDERSCAN:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_THUNDERSCAN);
		break;
	case COMPRESSION_CCITTFAX3:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_CCITTFAX3);
		break;
	case COMPRESSION_CCITTFAX4:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_CCITTFAX4);
		break;
	case COMPRESSION_CCITTRLE:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_CCITTRLE);
		break;
	case COMPRESSION_JPEG:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_JPEG);
		break;
	case COMPRESSION_OJPEG:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_OJPEG);
		break;
	case COMPRESSION_NONE:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_NONE);
		break;
	case COMPRESSION_SGILOG:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_SGILOG);
		break;
	case COMPRESSION_SGILOG24:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_SGILOG24);
		break;
	case COMPRESSION_ADOBE_DEFLATE:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_ADOBE_DEFLATE);
		break;
	case COMPRESSION_DEFLATE:
		prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_DEFLATE);
		break;
	/*default :
      prop->m_compressionType.setValue(TNZ_INFO_COMPRESS_UNKNOWN);
      break;*/
	default:
		assert(0);
	}

	float xdpi = 0, ydpi = 0;
	TIFFGetField(m_tiff, TIFFTAG_XRESOLUTION, &xdpi);
	TIFFGetField(m_tiff, TIFFTAG_YRESOLUTION, &ydpi);

	bool swapxy = false; // orient == ORIENTATION_RIGHTTOP;

	if (swapxy) {
		tswap(w, h);
		tswap(xdpi, ydpi);
	}

	m_xdpi = xdpi;
	m_ydpi = ydpi;
	m_info.m_lx = w;
	m_info.m_ly = h;
	m_info.m_dpix = xdpi;
	m_info.m_dpiy = ydpi;

	m_info.m_samplePerPixel = spp;

	if (bps == 64 && spp == 3)
		bps = 16; //immagine con bpp = 192

	uint16 photometric; //codice di controllo
	TIFFGetField(m_tiff, TIFFTAG_PHOTOMETRIC, &photometric);
	if (photometric == 3 && (bps == 2 || bps == 4)) //immagini con PHOTOMATRIC_PALETTE
		bps = 8;

	if (photometric == 1 && (bps == 12 || bps == 24))
		bps = 16;

	if (bps == 6)
		bps = 4; //immagini con bps = 6

	if (bps == 10 || bps == 12 || bps == 14) //immagini con bps = 10 , 12 , 14 , 24 , 32
		bps = 8;
	if (bps == 24 || bps == 32)
		bps = 16;

	m_info.m_bitsPerSample = bps;

	if (bps == 8)
		switch (spp) {
		case 1: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L" 8(GREYTONES)");
			break;
		case 3: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"24(RGB)");
			break;
		case 4: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"32(RGBM)");
			break;
		}
	else if (bps == 16)
		switch (spp) {
		case 1: /* row 0 top, col 0 lhs */
			//prop->m_bitsPerPixel.setValue(L"16(GREYTONES)");
			break;
		case 3: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"48(RGB)");
			break;
		case 4: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"64(RGBM)");
			break;
		}

	else if (bps == 2)
		switch (spp) {
		case 1: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"32(RGBM)");
			break;
		case 3: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"32(RGBM)");
			break;
		case 4: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"32(RGBM)");
			break;
		}

	else if (bps == 1)
		switch (spp) {
		case 1: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L" 1(BW)");
			break;
		case 3: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"32(RGBM)");
			break;
		case 4: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"32(RGBM)");
			break;
		}

	else if (bps == 4)
		switch (spp) {
		case 1: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L" 8(GREYTONES)");
			break;
		case 3: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"32(RGBM)");
			break;
		case 4: /* row 0 top, col 0 lhs */
			prop->m_bitsPerPixel.setValue(L"32(RGBM)");
			break;
		}

	else if (bps == 64 && spp == 3)
		prop->m_bitsPerPixel.setValue(L"64(RGBM)");

	else
		assert(false);

	if (TIFFIsTiled(m_tiff)) {
		m_rowsPerStrip = tileLength;
		int tilesPerRow = (w + tileWidth - 1) / tileWidth;
		//m_rowLength = tileWidth * tilesPerRow;
		m_rowLength = m_info.m_lx;
		int pixelSize = bps == 16 ? 8 : 4;
		int stripSize = m_rowsPerStrip * m_rowLength * pixelSize;

		m_tmpRas = TRasterGR8P(stripSize, 1);
		m_tmpRas->lock();

		m_stripBuffer = m_tmpRas->getRawData();
	} else {
		m_rowsPerStrip = rps;
		//if(m_rowsPerStrip<=0) m_rowsPerStrip = 1;			//potrei mettere qualsiasi valore
		//purchè sia lo stesso in tif_getimage.c linea 2512
		//if(m_rowsPerStrip==-1) assert(0);

		if (m_rowsPerStrip <= 0)
			m_rowsPerStrip = m_info.m_ly;

		int stripSize = m_rowsPerStrip * w * 4; // + 4096;  TIFFStripSize(m_tiff);

		if (bps == 16)
			stripSize *= 2;

		m_tmpRas = TRasterGR8P(stripSize, 1);
		m_tmpRas->lock();

		m_stripBuffer = m_tmpRas->getRawData();

		m_rowLength = m_info.m_lx; //w;
	}

	/* 
  int TIFFTileRowSize(m_tiff);

  m_rowsPerStrip = 0;
  if(TIFFGetField(m_tiff, TIFFTAG_ROWSPERSTRIP, &rps) )
    {
     int stripSize = TIFFStripSize(m_tiff);
     if(stripSize>0)
       {
       }
    }
    */
	if (m_isTzi) {
		USHORT risCount = 0;
		USHORT *risArray = 0;

		if (TIFFGetField(m_tiff, TIFFTAG_TOONZWINDOW, &risCount, &risArray)) {
			if (m_info.m_lx == risArray[2] && m_info.m_ly == risArray[3]) //se sono diverse, la lettura tif crasha....
			{
				//m_info.m_lx = risArray[2];
				//m_info.m_ly = risArray[3];
				m_info.m_x0 = risArray[0];
				m_info.m_y0 = risArray[1];
			}
			//      USHORT extraMask = risArray[4];
			//bool isEduFile = risArray[TOONZWINDOW_COUNT - 1] & 1;
		} else {
			m_info.m_x0 = 0;
			m_info.m_y0 = 0;
		}
		if (swapxy) {
			tswap(m_info.m_x0, m_info.m_y0);
			tswap(m_info.m_lx, m_info.m_ly);
		}
		m_info.m_x1 = m_info.m_x0 + w;
		m_info.m_y1 = m_info.m_y0 + h;
	} else {
		m_info.m_x0 = m_info.m_y0 = 0;
		m_info.m_x1 = m_info.m_x0 + m_info.m_lx - 1;
		m_info.m_y1 = m_info.m_y0 + m_info.m_ly - 1;
	}
}
Ejemplo n.º 3
0
static int
tiffcp(TIFF* in, TIFF* out)
{
	uint16 bitspersample, samplesperpixel, compression, shortv, *shortav;
	uint32 w, l;
	float floatv;
	char *stringv;
	uint32 longv;

	CopyField(TIFFTAG_SUBFILETYPE, longv);
	CopyField(TIFFTAG_TILEWIDTH, w);
	CopyField(TIFFTAG_TILELENGTH, l);
	CopyField(TIFFTAG_IMAGEWIDTH, w);
	CopyField(TIFFTAG_IMAGELENGTH, l);
	CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample);
	CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
	CopyField(TIFFTAG_COMPRESSION, compression);
	if (compression == COMPRESSION_JPEG) {
		uint32 count = 0;
		void *table = NULL;
		if (TIFFGetField(in, TIFFTAG_JPEGTABLES, &count, &table)
		    && count > 0 && table) {
		    TIFFSetField(out, TIFFTAG_JPEGTABLES, count, table);
		}
	}
        CopyField(TIFFTAG_PHOTOMETRIC, shortv);
	CopyField(TIFFTAG_PREDICTOR, shortv);
	CopyField(TIFFTAG_THRESHHOLDING, shortv);
	CopyField(TIFFTAG_FILLORDER, shortv);
	CopyField(TIFFTAG_ORIENTATION, shortv);
	CopyField(TIFFTAG_MINSAMPLEVALUE, shortv);
	CopyField(TIFFTAG_MAXSAMPLEVALUE, shortv);
	CopyField(TIFFTAG_XRESOLUTION, floatv);
	CopyField(TIFFTAG_YRESOLUTION, floatv);
	CopyField(TIFFTAG_GROUP3OPTIONS, longv);
	CopyField(TIFFTAG_GROUP4OPTIONS, longv);
	CopyField(TIFFTAG_RESOLUTIONUNIT, shortv);
	CopyField(TIFFTAG_PLANARCONFIG, shortv);
	CopyField(TIFFTAG_ROWSPERSTRIP, longv);
	CopyField(TIFFTAG_XPOSITION, floatv);
	CopyField(TIFFTAG_YPOSITION, floatv);
	CopyField(TIFFTAG_IMAGEDEPTH, longv);
	CopyField(TIFFTAG_TILEDEPTH, longv);
	CopyField(TIFFTAG_SAMPLEFORMAT, shortv);
	CopyField2(TIFFTAG_EXTRASAMPLES, shortv, shortav);
	{ uint16 *red, *green, *blue;
	  CopyField3(TIFFTAG_COLORMAP, red, green, blue);
	}
	{ uint16 shortv2;
	  CopyField2(TIFFTAG_PAGENUMBER, shortv, shortv2);
	}
	CopyField(TIFFTAG_ARTIST, stringv);
	CopyField(TIFFTAG_IMAGEDESCRIPTION, stringv);
	CopyField(TIFFTAG_MAKE, stringv);
	CopyField(TIFFTAG_MODEL, stringv);
	CopyField(TIFFTAG_SOFTWARE, stringv);
	CopyField(TIFFTAG_DATETIME, stringv);
	CopyField(TIFFTAG_HOSTCOMPUTER, stringv);
	CopyField(TIFFTAG_PAGENAME, stringv);
	CopyField(TIFFTAG_DOCUMENTNAME, stringv);
	CopyField(TIFFTAG_BADFAXLINES, longv);
	CopyField(TIFFTAG_CLEANFAXDATA, longv);
	CopyField(TIFFTAG_CONSECUTIVEBADFAXLINES, longv);
	CopyField(TIFFTAG_FAXRECVPARAMS, longv);
	CopyField(TIFFTAG_FAXRECVTIME, longv);
	CopyField(TIFFTAG_FAXSUBADDRESS, stringv);
	CopyField(TIFFTAG_FAXDCS, stringv);
	if (TIFFIsTiled(in))
		return (cpTiles(in, out));
	else
		return (cpStrips(in, out));
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
Archivo: ximatif.cpp Proyecto: VNOC/XUI
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;
                    }
                }
Ejemplo n.º 6
0
int
read_image_striped(const char *name, uint32 width, uint32 length,
                   uint32 rowsperstrip, uint16 compression,
                   uint16 spp, uint16 bps, uint16 photometric,
                   uint16 sampleformat, uint16 planarconfig,
                   const tdata_t array, const tsize_t size)
{
    TIFF		*tif;
    uint16		value_u16;
    uint32		value_u32;

    /* Test whether we can read written values. */
    tif = TIFFOpen(name, "r");
    if (!tif)
        goto openfailure;

    if (TIFFIsTiled(tif)) {
        fprintf (stderr, "Can't read image %s, it is tiled.\n",
                 name);
        goto failure;
    }
    if (!TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &value_u32)
            || value_u32 != width) {
        fprintf (stderr, "Can't get tag %d.\n", TIFFTAG_IMAGEWIDTH);
        goto failure;
    }
    if (!TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &value_u32)
            || value_u32 != length) {
        fprintf (stderr, "Can't get tag %d.\n", TIFFTAG_IMAGELENGTH);
        goto failure;
    }
    if (!TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &value_u16)
            || value_u16 != bps) {
        fprintf (stderr, "Can't get tag %d.\n", TIFFTAG_BITSPERSAMPLE);
        goto failure;
    }
    if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &value_u16)
            || value_u16 != photometric) {
        fprintf (stderr, "Can't get tag %d.\n", TIFFTAG_PHOTOMETRIC);
        goto failure;
    }
    if (!TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &value_u16)
            || value_u16 != spp) {
        fprintf (stderr, "Can't get tag %d.\n", TIFFTAG_SAMPLESPERPIXEL);
        goto failure;
    }
    if (!TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &value_u32)
            || value_u32 != rowsperstrip) {
        fprintf (stderr, "Can't get tag %d.\n", TIFFTAG_ROWSPERSTRIP);
        goto failure;
    }
    if (!TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &value_u16)
            || value_u16 != planarconfig) {
        fprintf (stderr, "Can't get tag %d.\n", TIFFTAG_PLANARCONFIG);
        goto failure;
    }

    if (read_strips(tif, array, size) < 0) {
        fprintf (stderr, "Can't read image data.\n");
        goto failure;
    }

    TIFFClose(tif);
    return 0;

failure:
    TIFFClose(tif);
openfailure:
    fprintf (stderr, "Can't read test TIFF file %s:\n"
             "    ImageWidth=%u, ImageLength=%u, RowsPerStrip=%u, Compression=%d,\n"
             "    BitsPerSample=%d, SamplesPerPixel=%d, SampleFormat=%d,\n"
             "    PlanarConfiguration=%d, PhotometricInterpretation=%d.\n",
             name, width, length, rowsperstrip, compression,
             bps, spp, sampleformat, planarconfig,
             photometric);
    return -1;
}
Ejemplo n.º 7
0
boolean TIFFRasterImpl::gt(u_long w, u_long h) {
    u_short minsamplevalue;
    u_short maxsamplevalue;
    u_short planarconfig;
    RGBvalue* Map = nil;

    if (!TIFFGetField(tif_, TIFFTAG_MINSAMPLEVALUE, &minsamplevalue)) {
	minsamplevalue = 0;
    }
    if (!TIFFGetField(tif_, TIFFTAG_MAXSAMPLEVALUE, &maxsamplevalue)) {
	maxsamplevalue = (1<<bitspersample_)-1;
    }
    switch (photometric_) {
    case PHOTOMETRIC_RGB:
	if (minsamplevalue == 0 && maxsamplevalue == 255) {
	    break;
	}
	/* fall thru... */
    case PHOTOMETRIC_MINISBLACK:
    case PHOTOMETRIC_MINISWHITE: {
	register int x, range;

	range = maxsamplevalue - minsamplevalue;
	Map = new RGBvalue[range + 1];
	if (Map == nil) {
	    TIFFError(
		TIFFFileName(tif_),
		"No space for photometric conversion table"
	    );
	    return false;
	}
	if (photometric_ == PHOTOMETRIC_MINISWHITE) {
	    for (x = 0; x <= range; x++) {
		Map[x] = ((range - x) * 255) / range;
	    }
	} else {
	    for (x = 0; x <= range; x++) {
		Map[x] = (x * 255) / range;
	    }
	}
	if (photometric_ != PHOTOMETRIC_RGB && bitspersample_ != 8) {
	    /*
	     * Use photometric mapping table to construct
	     * unpacking tables for samples < 8 bits.
	     */
	    if (!makebwmap(Map)) {
		return false;
	    }
	    delete Map;			/* no longer need Map, free it */
	    Map = nil;
	}
	break;
    }
    case PHOTOMETRIC_PALETTE:
	if (!TIFFGetField(
	    tif_, TIFFTAG_COLORMAP, &redcmap_, &greencmap_, &bluecmap_)
	) {
	    TIFFError(TIFFFileName(tif_), "Missing required \"Colormap\" tag");
	    return (false);
	}
	/*
	 * Convert 16-bit colormap to 8-bit (unless it looks
	 * like an old-style 8-bit colormap).
	 */
	if (
	    checkcmap(
		1 << bitspersample_, redcmap_, greencmap_, bluecmap_
	    ) == 16
	) {
	    int i;
	    for (i = (1 << bitspersample_) - 1; i > 0; i--) {
#define	CVT(x)		(((x) * 255) / ((1L<<16)-1))
		redcmap_[i] = (u_short) CVT(redcmap_[i]);
		greencmap_[i] = (u_short) CVT(greencmap_[i]);
		bluecmap_[i] = (u_short) CVT(bluecmap_[i]);
	    }
	}
	if (bitspersample_ <= 8) {
	    /*
	     * Use mapping table and colormap to construct
	     * unpacking tables for samples < 8 bits.
	     */
	    if (!makecmap(redcmap_, greencmap_, bluecmap_)) {
		return false;
	    }
	}
	break;
    }
    TIFFGetField(tif_, TIFFTAG_PLANARCONFIG, &planarconfig);
    boolean e;
    if (planarconfig == PLANARCONFIG_SEPARATE && samplesperpixel_ > 1) {
	e = TIFFIsTiled(tif_) ?
	    gtTileSeparate(Map, h, w) : gtStripSeparate(Map, h, w);
    } else {
	e = TIFFIsTiled(tif_) ? 
	    gtTileContig(Map, h, w) : gtStripContig(Map, h, w);
    }
    delete Map;
    return e;
}
Ejemplo n.º 8
0
TIFFOvrCache *TIFFCreateOvrCache( TIFF *hTIFF, int nDirOffset )

{
    TIFFOvrCache	*psCache;
    uint32		nBaseDirOffset;

    psCache = (TIFFOvrCache *) _TIFFmalloc(sizeof(TIFFOvrCache));
    psCache->nDirOffset = nDirOffset;
    psCache->hTIFF = hTIFF;
    
/* -------------------------------------------------------------------- */
/*      Get definition of this raster from the TIFF file itself.        */
/* -------------------------------------------------------------------- */
    nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF );
    TIFFSetSubDirectory( hTIFF, nDirOffset );
    
    TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &(psCache->nXSize) );
    TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &(psCache->nYSize) );

    TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &(psCache->nBitsPerPixel) );
    TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &(psCache->nSamples) );
    TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(psCache->nPlanarConfig) );

    if( !TIFFIsTiled( hTIFF ) )
    {
        TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(psCache->nBlockYSize) );
        psCache->nBlockXSize = psCache->nXSize;
        psCache->nBytesPerBlock = TIFFStripSize(hTIFF);
        psCache->bTiled = FALSE;
    }
    else
    {
        TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(psCache->nBlockXSize) );
        TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(psCache->nBlockYSize) );
        psCache->nBytesPerBlock = TIFFTileSize(hTIFF);
        psCache->bTiled = TRUE;
    }

/* -------------------------------------------------------------------- */
/*      Compute some values from this.                                  */
/* -------------------------------------------------------------------- */

    psCache->nBlocksPerRow = (psCache->nXSize + psCache->nBlockXSize - 1)
        		/ psCache->nBlockXSize;
    psCache->nBlocksPerColumn = (psCache->nYSize + psCache->nBlockYSize - 1)
        		/ psCache->nBlockYSize;

    if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE)
        psCache->nBytesPerRow = psCache->nBytesPerBlock
            * psCache->nBlocksPerRow * psCache->nSamples;
    else
        psCache->nBytesPerRow =
            psCache->nBytesPerBlock * psCache->nBlocksPerRow;


/* -------------------------------------------------------------------- */
/*      Allocate and initialize the data buffers.                       */
/* -------------------------------------------------------------------- */

    psCache->pabyRow1Blocks =
        (unsigned char *) _TIFFmalloc(psCache->nBytesPerRow);
    psCache->pabyRow2Blocks =
        (unsigned char *) _TIFFmalloc(psCache->nBytesPerRow);

    if( psCache->pabyRow1Blocks == NULL
        || psCache->pabyRow2Blocks == NULL )
    {
		TIFFErrorExt( hTIFF->tif_clientdata, hTIFF->tif_name,
					  "Can't allocate memory for overview cache." );
        /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
        return NULL;
    }

    _TIFFmemset( psCache->pabyRow1Blocks, 0, psCache->nBytesPerRow );
    _TIFFmemset( psCache->pabyRow2Blocks, 0, psCache->nBytesPerRow );

    psCache->nBlockOffset = 0;

    TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset );
    
    return psCache;
}
Ejemplo n.º 9
0
int
PS_Lvl2page(FILE* fd, TIFF* tif, uint32 w, uint32 h)
{
	uint16 fillorder;
	int use_rawdata, tiled_image, breaklen;
	uint32 chunk_no, num_chunks, *bc;
	unsigned char *buf_data, *cp;
	tsize_t chunk_size, byte_count;

#if defined( EXP_ASCII85ENCODER )
	int			ascii85_l;		/* Length, in bytes, of ascii85_p[] data */
	uint8		*	ascii85_p = 0;		/* Holds ASCII85 encoded data */
#endif

	PS_Lvl2colorspace(fd, tif);
	use_rawdata = PS_Lvl2ImageDict(fd, tif, w, h);

	fputs("%%BeginData:\n", fd);
	fputs("exec\n", fd);

	tiled_image = TIFFIsTiled(tif);
	if (tiled_image) {
		num_chunks = TIFFNumberOfTiles(tif);
		TIFFGetField(tif, TIFFTAG_TILEBYTECOUNTS, &bc);
	} else {
		num_chunks = TIFFNumberOfStrips(tif);
		TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc);
	}

	if (use_rawdata) {
		chunk_size = bc[0];
		for (chunk_no = 1; chunk_no < num_chunks; chunk_no++)
			if (bc[chunk_no] > chunk_size)
				chunk_size = bc[chunk_no];
	} else {
		if (tiled_image)
			chunk_size = TIFFTileSize(tif);
		else
			chunk_size = TIFFStripSize(tif);
	}
	buf_data = (unsigned char *)_TIFFmalloc(chunk_size);
	if (!buf_data) {
		TIFFError(filename, "Can't alloc %u bytes for %s.",
			chunk_size, tiled_image ? "tiles" : "strips");
		return(FALSE);
	}

#if defined( EXP_ASCII85ENCODER )
	if ( ascii85 ) {
	    /*
	     * Allocate a buffer to hold the ASCII85 encoded data.  Note
	     * that it is allocated with sufficient room to hold the
	     * encoded data (5*chunk_size/4) plus the EOD marker (+8)
	     * and formatting line breaks.  The line breaks are more
	     * than taken care of by using 6*chunk_size/4 rather than
	     * 5*chunk_size/4.
	     */

	    ascii85_p = _TIFFmalloc( (chunk_size+(chunk_size/2)) + 8 );

	    if ( !ascii85_p ) {
		_TIFFfree( buf_data );

		TIFFError( filename, "Cannot allocate ASCII85 encoding buffer." );
		return ( FALSE );
	    }
	}
#endif

	TIFFGetFieldDefaulted(tif, TIFFTAG_FILLORDER, &fillorder);
	for (chunk_no = 0; chunk_no < num_chunks; chunk_no++) {
		if (ascii85)
			Ascii85Init();
		else
			breaklen = 36;
		if (use_rawdata) {
			if (tiled_image)
				byte_count = TIFFReadRawTile(tif, chunk_no,
						  buf_data, chunk_size);
			else
				byte_count = TIFFReadRawStrip(tif, chunk_no,
						  buf_data, chunk_size);
			if (fillorder == FILLORDER_LSB2MSB)
			    TIFFReverseBits(buf_data, byte_count);
		} else {
			if (tiled_image)
				byte_count = TIFFReadEncodedTile(tif,
						chunk_no, buf_data,
						chunk_size);
			else
				byte_count = TIFFReadEncodedStrip(tif,
						chunk_no, buf_data,
						chunk_size);
		}
		if (byte_count < 0) {
			TIFFError(filename, "Can't read %s %d.",
				tiled_image ? "tile" : "strip", chunk_no);
			if (ascii85)
				Ascii85Put('\0', fd);
		}

		if (ascii85) {
#if defined( EXP_ASCII85ENCODER )
			ascii85_l = Ascii85EncodeBlock(ascii85_p, 1, buf_data, byte_count );

			if ( ascii85_l > 0 )
				fwrite( ascii85_p, ascii85_l, 1, fd );
#else
			for (cp = buf_data; byte_count > 0; byte_count--)
				Ascii85Put(*cp++, fd);
#endif
		}
		else
		{
			for (cp = buf_data; byte_count > 0; byte_count--) {
				putc(hex[((*cp)>>4)&0xf], fd);
				putc(hex[(*cp)&0xf], fd);
				cp++;

				if (--breaklen <= 0) {
					putc('\n', fd);
					breaklen = 36;
				}
			}
		}

		if ( !ascii85 ) {
			if ( level2 )
				putc( '>', fd );
			putc('\n', fd);
		}
#if !defined( EXP_ASCII85ENCODER )
		else
			Ascii85Flush(fd);
#endif
	}

#if defined( EXP_ASCII85ENCODER )
	if ( ascii85_p )
	    _TIFFfree( ascii85_p );
#endif
       
	_TIFFfree(buf_data);
	fputs("%%EndData\n", fd);
	return(TRUE);
}
Ejemplo n.º 10
0
bool  TiffDecoder::readData( Mat& img )
{
    bool result = false;
    bool color = img.channels() > 1;
    uchar* data = img.data;
    int step = img.step;

    if( m_tif && m_width && m_height )
    {
        TIFF* tif = (TIFF*)m_tif;
        int tile_width0 = m_width, tile_height0 = 0;
        int x, y, i;
        int is_tiled = TIFFIsTiled(tif);

        if( (!is_tiled &&
            TIFFGetField( tif, TIFFTAG_ROWSPERSTRIP, &tile_height0 )) ||
            (is_tiled &&
            TIFFGetField( tif, TIFFTAG_TILEWIDTH, &tile_width0 ) &&
            TIFFGetField( tif, TIFFTAG_TILELENGTH, &tile_height0 )))
        {
            if( tile_width0 <= 0 )
                tile_width0 = m_width;

            if( tile_height0 <= 0 )
                tile_height0 = m_height;

            AutoBuffer<uchar> _buffer(tile_height0*tile_width0*4);
            uchar* buffer = _buffer;

            for( y = 0; y < m_height; y += tile_height0, data += step*tile_height0 )
            {
                int tile_height = tile_height0;

                if( y + tile_height > m_height )
                    tile_height = m_height - y;

                for( x = 0; x < m_width; x += tile_width0 )
                {
                    int tile_width = tile_width0, ok;

                    if( x + tile_width > m_width )
                        tile_width = m_width - x;

                    if( !is_tiled )
                        ok = TIFFReadRGBAStrip( tif, y, (uint32*)buffer );
                    else
                        ok = TIFFReadRGBATile( tif, x, y, (uint32*)buffer );

                    if( !ok )
                    {
                        close();
                        return false;
                    }

                    for( i = 0; i < tile_height; i++ )
                        if( color )
                            icvCvt_BGRA2BGR_8u_C4C3R( buffer + i*tile_width*4, 0,
                                          data + x*3 + step*(tile_height - i - 1), 0,
                                          cvSize(tile_width,1), 2 );
                        else
                            icvCvt_BGRA2Gray_8u_C4C1R( buffer + i*tile_width*4, 0,
                                           data + x + step*(tile_height - i - 1), 0,
                                           cvSize(tile_width,1), 2 );
                }
            }

            result = true;
        }
    }

    close();
    return result;
}
Ejemplo n.º 11
0
static int
PS_Lvl2ImageDict(FILE* fd, TIFF* tif, uint32 w, uint32 h)
{
	int use_rawdata;
	uint32 tile_width, tile_height;
	uint16 predictor, minsamplevalue, maxsamplevalue;
	int repeat_count;
	char im_h[64], im_x[64], im_y[64];
	char * imageOp = "image";

	if ( useImagemask && (bitspersample == 1) )
		imageOp = "imagemask";

	(void)strcpy(im_x, "0");
	(void)sprintf(im_y, "%lu", (long) h);
	(void)sprintf(im_h, "%lu", (long) h);
	tile_width = w;
	tile_height = h;
	if (TIFFIsTiled(tif)) {
		repeat_count = TIFFNumberOfTiles(tif);
		TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width);
		TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height);
		if (tile_width > w || tile_height > h ||
		    (w % tile_width) != 0 || (h % tile_height != 0)) {
			/*
			 * The tiles does not fit image width and height.
			 * Set up a clip rectangle for the image unit square.
			 */
			fputs("0 0 1 1 rectclip\n", fd);
		}
		if (tile_width < w) {
			fputs("/im_x 0 def\n", fd);
			(void)strcpy(im_x, "im_x neg");
		}
		if (tile_height < h) {
			fputs("/im_y 0 def\n", fd);
			(void)sprintf(im_y, "%lu im_y sub", (unsigned long) h);
		}
	} else {
		repeat_count = tf_numberstrips;
		tile_height = tf_rowsperstrip;
		if (tile_height > h)
			tile_height = h;
		if (repeat_count > 1) {
			fputs("/im_y 0 def\n", fd);
			fprintf(fd, "/im_h %lu def\n",
			    (unsigned long) tile_height);
			(void)strcpy(im_h, "im_h");
			(void)sprintf(im_y, "%lu im_y sub", (unsigned long) h);
		}
	}

	/*
	 * Output start of exec block
	 */
	fputs("{ % exec\n", fd);

	if (repeat_count > 1)
		fprintf(fd, "%d { %% repeat\n", repeat_count);

	/*
	 * Output filter options and image dictionary.
	 */
	if (ascii85)
		fputs(" /im_stream currentfile /ASCII85Decode filter def\n",
		    fd);
	fputs(" <<\n", fd);
	fputs("  /ImageType 1\n", fd);
	fprintf(fd, "  /Width %lu\n", (unsigned long) tile_width);
	fprintf(fd, "  /Height %lu\n", (unsigned long) tile_height);
	if (planarconfiguration == PLANARCONFIG_SEPARATE && samplesperpixel > 1)
		fputs("  /MultipleDataSources true\n", fd);
	fprintf(fd, "  /ImageMatrix [ %lu 0 0 %ld %s %s ]\n",
	    (unsigned long) w, - (long)h, im_x, im_y);
	fprintf(fd, "  /BitsPerComponent %d\n", bitspersample);
	fprintf(fd, "  /Interpolate %s\n", interpolate ? "true" : "false");

	switch (samplesperpixel) {
	case 1:
		switch (photometric) {
		case PHOTOMETRIC_MINISBLACK:
			fputs("  /Decode [0 1]\n", fd);
			break;
		case PHOTOMETRIC_MINISWHITE:
			switch (compression) {
			case COMPRESSION_CCITTRLE:
			case COMPRESSION_CCITTRLEW:
			case COMPRESSION_CCITTFAX3:
			case COMPRESSION_CCITTFAX4:
				/*
				 * Manage inverting with /Blackis1 flag
				 * since there migth be uncompressed parts
				 */
				fputs("  /Decode [0 1]\n", fd);
				break;
			default:
				/*
				 * ERROR...
				 */
				fputs("  /Decode [1 0]\n", fd);
				break;
			}
			break;
		case PHOTOMETRIC_PALETTE:
			TIFFGetFieldDefaulted(tif, TIFFTAG_MINSAMPLEVALUE,
			    &minsamplevalue);
			TIFFGetFieldDefaulted(tif, TIFFTAG_MAXSAMPLEVALUE,
			    &maxsamplevalue);
			fprintf(fd, "  /Decode [%u %u]\n",
				    minsamplevalue, maxsamplevalue);
			break;
		default:
			/*
			 * ERROR ?
			 */
			fputs("  /Decode [0 1]\n", fd);
			break;
		}
		break;
	case 3:
		switch (photometric) {
		case PHOTOMETRIC_RGB:
			fputs("  /Decode [0 1 0 1 0 1]\n", fd);
			break;
		case PHOTOMETRIC_MINISWHITE:
		case PHOTOMETRIC_MINISBLACK:
		default:
			/*
			 * ERROR??
			 */
			fputs("  /Decode [0 1 0 1 0 1]\n", fd);
			break;
		}
		break;
	case 4:
		/*
		 * ERROR??
		 */
		fputs("  /Decode [0 1 0 1 0 1 0 1]\n", fd);
		break;
	}
	fputs("  /DataSource", fd);
	if (planarconfiguration == PLANARCONFIG_SEPARATE &&
	    samplesperpixel > 1)
		fputs(" [", fd);
	if (ascii85)
		fputs(" im_stream", fd);
	else
		fputs(" currentfile /ASCIIHexDecode filter", fd);

	use_rawdata = TRUE;
	switch (compression) {
	case COMPRESSION_NONE:		/* 1: uncompressed */
		break;
	case COMPRESSION_CCITTRLE:	/* 2: CCITT modified Huffman RLE */
	case COMPRESSION_CCITTRLEW:	/* 32771: #1 w/ word alignment */
	case COMPRESSION_CCITTFAX3:	/* 3: CCITT Group 3 fax encoding */
	case COMPRESSION_CCITTFAX4:	/* 4: CCITT Group 4 fax encoding */
		fputs("\n\t<<\n", fd);
		if (compression == COMPRESSION_CCITTFAX3) {
			uint32 g3_options;

			fputs("\t /EndOfLine true\n", fd);
			fputs("\t /EndOfBlock false\n", fd);
			if (!TIFFGetField(tif, TIFFTAG_GROUP3OPTIONS,
					    &g3_options))
				g3_options = 0;
			if (g3_options & GROUP3OPT_2DENCODING)
				fprintf(fd, "\t /K %s\n", im_h);
			if (g3_options & GROUP3OPT_UNCOMPRESSED)
				fputs("\t /Uncompressed true\n", fd);
			if (g3_options & GROUP3OPT_FILLBITS)
				fputs("\t /EncodedByteAlign true\n", fd);
		}
		if (compression == COMPRESSION_CCITTFAX4) {
			uint32 g4_options;

			fputs("\t /K -1\n", fd);
			TIFFGetFieldDefaulted(tif, TIFFTAG_GROUP4OPTIONS,
					       &g4_options);
			if (g4_options & GROUP4OPT_UNCOMPRESSED)
				fputs("\t /Uncompressed true\n", fd);
		}
		if (!(tile_width == w && w == 1728U))
			fprintf(fd, "\t /Columns %lu\n",
			    (unsigned long) tile_width);
		fprintf(fd, "\t /Rows %s\n", im_h);
		if (compression == COMPRESSION_CCITTRLE ||
		    compression == COMPRESSION_CCITTRLEW) {
			fputs("\t /EncodedByteAlign true\n", fd);
			fputs("\t /EndOfBlock false\n", fd);
		}
		if (photometric == PHOTOMETRIC_MINISBLACK)
			fputs("\t /BlackIs1 true\n", fd);
		fprintf(fd, "\t>> /CCITTFaxDecode filter");
		break;
	case COMPRESSION_LZW:	/* 5: Lempel-Ziv  & Welch */
		TIFFGetFieldDefaulted(tif, TIFFTAG_PREDICTOR, &predictor);
		if (predictor == 2) {
			fputs("\n\t<<\n", fd);
			fprintf(fd, "\t /Predictor %u\n", predictor);
			fprintf(fd, "\t /Columns %lu\n",
			    (unsigned long) tile_width);
			fprintf(fd, "\t /Colors %u\n", samplesperpixel);
			fprintf(fd, "\t /BitsPerComponent %u\n",
			    bitspersample);
			fputs("\t>>", fd);
		}
		fputs(" /LZWDecode filter", fd);
		break;
	case COMPRESSION_PACKBITS:	/* 32773: Macintosh RLE */
		fputs(" /RunLengthDecode filter", fd);
		use_rawdata = TRUE;
	    break;
	case COMPRESSION_OJPEG:		/* 6: !6.0 JPEG */
	case COMPRESSION_JPEG:		/* 7: %JPEG DCT compression */
#ifdef notdef
		/*
		 * Code not tested yet
		 */
		fputs(" /DCTDecode filter", fd);
		use_rawdata = TRUE;
#else
		use_rawdata = FALSE;
#endif
		break;
	case COMPRESSION_NEXT:		/* 32766: NeXT 2-bit RLE */
	case COMPRESSION_THUNDERSCAN:	/* 32809: ThunderScan RLE */
	case COMPRESSION_PIXARFILM:	/* 32908: Pixar companded 10bit LZW */
	case COMPRESSION_DEFLATE:	/* 32946: Deflate compression */
	case COMPRESSION_JBIG:		/* 34661: ISO JBIG */
		use_rawdata = FALSE;
		break;
	case COMPRESSION_SGILOG:	/* 34676: SGI LogL or LogLuv */
	case COMPRESSION_SGILOG24:	/* 34677: SGI 24-bit LogLuv */
		use_rawdata = FALSE;
		break;
	default:
		/*
		 * ERROR...
		 */
		use_rawdata = FALSE;
		break;
	}
	if (planarconfiguration == PLANARCONFIG_SEPARATE &&
	    samplesperpixel > 1) {
		uint16 i;

		/*
		 * NOTE: This code does not work yet...
		 */
		for (i = 1; i < samplesperpixel; i++)
			fputs(" dup", fd);
		fputs(" ]", fd);
	}

	fprintf( fd, "\n >> %s\n", imageOp );
	if (ascii85)
		fputs(" im_stream status { im_stream flushfile } if\n", fd);
	if (repeat_count > 1) {
		if (tile_width < w) {
			fprintf(fd, " /im_x im_x %lu add def\n",
			    (unsigned long) tile_width);
			if (tile_height < h) {
				fprintf(fd, " im_x %lu ge {\n",
				    (unsigned long) w);
				fputs("  /im_x 0 def\n", fd);
				fprintf(fd, " /im_y im_y %lu add def\n",
				    (unsigned long) tile_height);
				fputs(" } if\n", fd);
			}
		}
		if (tile_height < h) {
			if (tile_width >= w) {
				fprintf(fd, " /im_y im_y %lu add def\n",
				    (unsigned long) tile_height);
				if (!TIFFIsTiled(tif)) {
					fprintf(fd, " /im_h %lu im_y sub",
					    (unsigned long) h);
					fprintf(fd, " dup %lu gt { pop",
					    (unsigned long) tile_height);
					fprintf(fd, " %lu } if def\n",
					    (unsigned long) tile_height);
				}
			}
		}
		fputs("} repeat\n", fd);
	}
	/*
	 * End of exec function
	 */
	fputs("}\n", fd);

	return(use_rawdata);
}
Ejemplo n.º 12
0
static int
tiffcp(TIFF* in, TIFF* out)
{
	uint16 bitspersample, samplesperpixel, shortv;
	copyFunc cf;
	uint32 w, l;

	CopyField(TIFFTAG_IMAGEWIDTH, w);
	CopyField(TIFFTAG_IMAGELENGTH, l);
        if( convert_8_to_4 )
        {
            TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, 4);
        }
        else
        {
            CopyField(TIFFTAG_BITSPERSAMPLE, bitspersample);
        }
	if (compression != (uint16)-1)
		TIFFSetField(out, TIFFTAG_COMPRESSION, compression);
	else
		CopyField(TIFFTAG_COMPRESSION, compression);
	if (compression == COMPRESSION_JPEG && jpegcolormode == JPEGCOLORMODE_RGB)
		TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
	else
		CopyField(TIFFTAG_PHOTOMETRIC, shortv);
	if (fillorder != 0)
		TIFFSetField(out, TIFFTAG_FILLORDER, fillorder);
	else
		CopyField(TIFFTAG_FILLORDER, shortv);
	CopyField(TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
	/*
	 * Choose tiles/strip for the output image according to
	 * the command line arguments (-tiles, -strips) and the
	 * structure of the input image.
	 */
	if (outtiled == -1)
		outtiled = TIFFIsTiled(in);
	if (outtiled) {
		/*
		 * Setup output file's tile width&height.  If either
		 * is not specified, use either the value from the
		 * input image or, if nothing is defined, use the
		 * library default.
		 */
		if (tilewidth == (uint32) -1)
			TIFFGetField(in, TIFFTAG_TILEWIDTH, &tilewidth);
		if (tilelength == (uint32) -1)
			TIFFGetField(in, TIFFTAG_TILELENGTH, &tilelength);
		TIFFDefaultTileSize(out, &tilewidth, &tilelength);
		TIFFSetField(out, TIFFTAG_TILEWIDTH, tilewidth);
		TIFFSetField(out, TIFFTAG_TILELENGTH, tilelength);
	} else {
		/*
		 * RowsPerStrip is left unspecified: use either the
		 * value from the input image or, if nothing is defined,
		 * use the library default.
		 */
		if (rowsperstrip == (uint32) -1)
			TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
		rowsperstrip = TIFFDefaultStripSize(out, rowsperstrip);
		TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
	}
	if (config != (uint16) -1)
		TIFFSetField(out, TIFFTAG_PLANARCONFIG, config);
	else
		CopyField(TIFFTAG_PLANARCONFIG, config);
	if (g3opts != (uint32) -1)
		TIFFSetField(out, TIFFTAG_GROUP3OPTIONS, g3opts);
	else
		CopyField(TIFFTAG_GROUP3OPTIONS, g3opts);
	if (samplesperpixel <= 4) {
		uint16 *tr, *tg, *tb, *ta;
		CopyField4(TIFFTAG_TRANSFERFUNCTION, tr, tg, tb, ta);
	}
	{ uint16 *red, *green, *blue;
	  if (TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue)) {
		CheckAndCorrectColormap(in, 1<<bitspersample, red, green, blue);
		TIFFSetField(out, TIFFTAG_COLORMAP, red, green, blue);
	  }
	}
/* SMinSampleValue & SMaxSampleValue */
	switch (compression) {
	case COMPRESSION_JPEG:
		TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
		TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
		break;
	case COMPRESSION_LZW:
	case COMPRESSION_DEFLATE:
		if (predictor != (uint16)-1)
			TIFFSetField(out, TIFFTAG_PREDICTOR, predictor);
		else
			CopyField(TIFFTAG_PREDICTOR, predictor);
		break;
	}
	cpOtherTags(in, out);

	if (geofile || proj4_string )
            InstallGeoTIFF(out);
        else
            CopyGeoTIFF(in,out);

        if( worldfile )
            ApplyWorldFile( worldfile, out);

	cf = pickCopyFunc(in, out, bitspersample, samplesperpixel);
	return (cf ? (*cf)(in, out, l, w, samplesperpixel) : FALSE);
}
Ejemplo n.º 13
0
int vglPrintTiffInfo(char* inFilename, char* msg){
  if (msg){
    printf("====== %s:\n", msg);
  }
  else
  {
    printf("====== vglPrintTiffInfo:\n");
  }

  TIFF* tif = TIFFOpen(inFilename, "r"); 

  if (tif == NULL){
    fprintf(stderr, "%s:%s: Error: File %s not found.\n", __FILE__, __FUNCTION__, inFilename);
    return 1;
  }
  if (tif) { 
    uint32 w, h; 
    uint16 bps, spp, photo, config, pageNumber, numberPages;
    uint32 subfileType;

    tdir_t dirCount;

    tstrip_t stripMax;
    tstrip_t istrip; 
    tsize_t stripSize;

    tsize_t npixels; 
    tsize_t pixelSize; 
    
    tdata_t raster; 
    tsize_t result, offset;
    char* rasterc;

    uint32    iw, ih; 
    int i;

    do{
      TIFFPrintDirectory(tif, stdout, 255);
    }
    while(TIFFReadDirectory(tif));

    printf("TIFFScanlineSize = %ld\n", (long int) TIFFScanlineSize(tif));
    printf("TIFFRasterScanlineSize = %ld\n", (long int) TIFFRasterScanlineSize(tif));
    printf("TIFFStripSize = %ld\n", (long int) TIFFStripSize(tif));
    printf("TIFFNumberOfStrips = %d\n", TIFFNumberOfStrips(tif));
    printf("TIFFVStripSize = %ld\n", (long int) TIFFVStripSize(tif,0));

    printf("TIFFTileRowSize = %ld\n", (long int) TIFFTileRowSize(tif));
    printf("TIFFTileSize = %ld\n", (long int) TIFFTileSize(tif));
    printf("TIFFNumberOfTiles = %d\n", TIFFNumberOfTiles(tif));
    printf("TIFFVTileSize = %ld\n", (long int) TIFFVTileSize(tif,0));

    printf("TIFFDefaultStripSize = %d\n", TIFFDefaultStripSize(tif,0));

    printf("TIFFFileno = %d\n", TIFFFileno(tif));
    printf("TIFFGetMode = %d\n", TIFFGetMode(tif));
    printf("TIFFIsTiled = %d\n", TIFFIsTiled(tif));
    printf("TIFFIsByteSwapped = %d\n", TIFFIsByteSwapped(tif));
    printf("TIFFRGBAImageOK = %d\n", TIFFRGBAImageOK(tif, (char*)"TIFFRGBAImageOK mesg\n"));



    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); 
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); 
    TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bps);
    TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
    TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photo); 
    TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &config);
    TIFFGetField(tif, TIFFTAG_PAGENUMBER, &pageNumber, &numberPages);
    TIFFGetField(tif, TIFFTAG_SUBFILETYPE, &subfileType);

    stripSize = TIFFStripSize(tif);
    stripMax = TIFFNumberOfStrips(tif);
    switch(bps){
      case 8:
        pixelSize = 1;
        break;
      case 16:
        pixelSize = 2;
        break;
      default:
        pixelSize = 0;
        break;
    }
    dirCount = tif_DirCount(tif);

    printf("size = %lu, w = %d, h = %d, spp = %d, bps = %d, pixelSize = %ld\n", sizeof(w), w, h, spp, bps, (long int) pixelSize);
    printf("Page Number = %d\n", pageNumber);
    printf("Number Pages = %d\n", numberPages);
    printf("Photometric interpretation = %d\n", photo);
    printf("Planar configuration = %d\n", config);
    printf("stripSize = %ld, stripMax = %d\n", (long int) stripSize, stripMax);
    printf("Number of directories = %d\n", dirCount);
    printf("Subfile type = %d\n", subfileType);

    //printbin((char*)&w, sizeof(w));
    //printbin((char*)&h, sizeof(h));


    //raster = tif_ReadData(tif);
    //tif_PrintAsc(tif, raster, (char*)"ascimg.txt");

    TIFFClose(tif); 
  } 
  return 0;
}
Ejemplo n.º 14
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            
        }
    }
}
bool _openslide_try_aperio(openslide_t *osr, TIFF *tiff,
			   struct _openslide_hash *quickhash1,
			   GError **err) {
  int32_t level_count = 0;
  int32_t *levels = NULL;
  int32_t i = 0;

  if (!TIFFIsTiled(tiff)) {
    g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED,
                "TIFF is not tiled");
    goto FAIL;
  }

  char *tagval;
  int tiff_result;
  tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval);
  if (!tiff_result ||
      (strncmp(APERIO_DESCRIPTION, tagval, strlen(APERIO_DESCRIPTION)) != 0)) {
    g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_FORMAT_NOT_SUPPORTED,
                "Not an Aperio slide");
    goto FAIL;
  }

  /*
   * http://www.aperio.com/documents/api/Aperio_Digital_Slides_and_Third-party_data_interchange.pdf
   * page 14:
   *
   * The first image in an SVS file is always the baseline image (full
   * resolution). This image is always tiled, usually with a tile size
   * of 240 x 240 pixels. The second image is always a thumbnail,
   * typically with dimensions of about 1024 x 768 pixels. Unlike the
   * other slide images, the thumbnail image is always
   * stripped. Following the thumbnail there may be one or more
   * intermediate "pyramid" images. These are always compressed with
   * the same type of compression as the baseline image, and have a
   * tiled organization with the same tile size.
   *
   * Optionally at the end of an SVS file there may be a slide label
   * image, which is a low resolution picture taken of the slide’s
   * label, and/or a macro camera image, which is a low resolution
   * picture taken of the entire slide. The label and macro images are
   * always stripped.
   */

  // for aperio, the tiled directories are the ones we want
  do {
    if (TIFFIsTiled(tiff)) {
      level_count++;
    }
  } while (TIFFReadDirectory(tiff));
  levels = g_new(int32_t, level_count);

  TIFFSetDirectory(tiff, 0);
  i = 0;
  do {
    tdir_t dir = TIFFCurrentDirectory(tiff);
    if (TIFFIsTiled(tiff)) {
      levels[i++] = dir;
      //g_debug("tiled directory: %d", dir);
    } else {
      // associated image
      const char *name = (dir == 1) ? "thumbnail" : NULL;
      if (!add_associated_image(osr ? osr->associated_images : NULL,
                                name, tiff, err)) {
	g_prefix_error(err, "Can't read associated image: ");
	goto FAIL;
      }
      //g_debug("associated image: %d", dir);
    }

    // check depth
    uint32_t depth;
    tiff_result = TIFFGetField(tiff, TIFFTAG_IMAGEDEPTH, &depth);
    if (tiff_result && depth != 1) {
      // we can't handle depth != 1
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Cannot handle ImageDepth=%d", depth);
      goto FAIL;
    }

    // check compression
    uint16_t compression;
    if (!TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression)) {
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Can't read compression scheme");
      goto FAIL;
    }
    if ((compression != APERIO_COMPRESSION_JP2K_YCBCR) &&
        (compression != APERIO_COMPRESSION_JP2K_RGB) &&
        !TIFFIsCODECConfigured(compression)) {
      g_set_error(err, OPENSLIDE_ERROR, OPENSLIDE_ERROR_BAD_DATA,
                  "Unsupported TIFF compression: %u", compression);
      goto FAIL;
    }
  } while (TIFFReadDirectory(tiff));

  // read properties
  if (osr) {
    TIFFSetDirectory(tiff, 0);
    TIFFGetField(tiff, TIFFTAG_IMAGEDESCRIPTION, &tagval); // XXX? should be safe, we just did it
    char **props = g_strsplit(tagval, "|", -1);
    add_properties(osr->properties, props);
    g_strfreev(props);
  }

  // special jpeg 2000 aperio thing (with fallback)
  _openslide_add_tiff_ops(osr, tiff, 0, 0, NULL, level_count, levels,
			  aperio_tiff_tilereader,
			  quickhash1);
  return true;

 FAIL:
  g_free(levels);
  return false;
}
Ejemplo n.º 16
0
/**
 * Loads a TIFF file.
 *
 *
 * \param mem:   Memory containing the TIFF file.
 * \param size:  Size of the mem buffer.
 * \param flags: If flags has IB_test set then the file is not actually loaded,
 *                but all other operations take place.
 *
 * \return: A newly allocated ImBuf structure if successful, otherwise NULL.
 */
ImBuf *imb_loadtiff(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
{
	TIFF *image = NULL;
	ImBuf *ibuf = NULL, *hbuf;
	ImbTIFFMemFile memFile;
	uint32 width, height;
	char *format = NULL;
	int level;
	short spp;
	int ib_depth;

	/* check whether or not we have a TIFF file */
	if (size < IMB_TIFF_NCB) {
		fprintf(stderr, "imb_loadtiff: size < IMB_TIFF_NCB\n");
		return NULL;
	}
	if (imb_is_a_tiff(mem) == 0)
		return NULL;

	/* both 8 and 16 bit PNGs are default to standard byte colorspace */
	colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);

	image = imb_tiff_client_open(&memFile, mem, size);

	if (image == NULL) {
		printf("imb_loadtiff: could not open TIFF IO layer.\n");
		return NULL;
	}

	/* allocate the image buffer */
	TIFFGetField(image, TIFFTAG_IMAGEWIDTH,  &width);
	TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);
	TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp);
	
	ib_depth = (spp == 3) ? 24 : 32;
	
	ibuf = IMB_allocImBuf(width, height, ib_depth, 0);
	if (ibuf) {
		ibuf->ftype = TIF;
	}
	else {
		fprintf(stderr, 
		        "imb_loadtiff: could not allocate memory for TIFF "
		        "image.\n");
		TIFFClose(image);
		return NULL;
	}

	/* get alpha mode from file header */
	if (flags & IB_alphamode_detect) {
		if (spp == 4) {
			unsigned short extra, *extraSampleTypes;

			TIFFGetField(image, TIFFTAG_EXTRASAMPLES, &extra, &extraSampleTypes);

			if (extraSampleTypes[0] == EXTRASAMPLE_ASSOCALPHA)
				ibuf->flags |= IB_alphamode_premul;
		}
	}

	/* if testing, we're done */
	if (flags & IB_test) {
		TIFFClose(image);
		return ibuf;
	}

	/* detect if we are reading a tiled/mipmapped texture, in that case
	 * we don't read pixels but leave it to the cache to load tiles */
	if (flags & IB_tilecache) {
		format = NULL;
		TIFFGetField(image, TIFFTAG_PIXAR_TEXTUREFORMAT, &format);

		if (format && strcmp(format, "Plain Texture") == 0 && TIFFIsTiled(image)) {
			int numlevel = TIFFNumberOfDirectories(image);

			/* create empty mipmap levels in advance */
			for (level = 0; level < numlevel; level++) {
				if (!TIFFSetDirectory(image, level))
					break;

				if (level > 0) {
					width = (width > 1) ? width / 2 : 1;
					height = (height > 1) ? height / 2 : 1;

					hbuf = IMB_allocImBuf(width, height, 32, 0);
					hbuf->miplevel = level;
					hbuf->ftype = ibuf->ftype;
					ibuf->mipmap[level - 1] = hbuf;
				}
				else
					hbuf = ibuf;

				hbuf->flags |= IB_tilecache;

				TIFFGetField(image, TIFFTAG_TILEWIDTH, &hbuf->tilex);
				TIFFGetField(image, TIFFTAG_TILELENGTH, &hbuf->tiley);

				hbuf->xtiles = ceil(hbuf->x / (float)hbuf->tilex);
				hbuf->ytiles = ceil(hbuf->y / (float)hbuf->tiley);

				imb_addtilesImBuf(hbuf);

				ibuf->miptot++;
			}
		}
	}

	/* read pixels */
	if (!(ibuf->flags & IB_tilecache) && !imb_read_tiff_pixels(ibuf, image)) {
		fprintf(stderr, "imb_loadtiff: Failed to read tiff image.\n");
		TIFFClose(image);
		return NULL;
	}

	/* close the client layer interface to the in-memory file */
	TIFFClose(image);

	/* return successfully */
	return ibuf;
}
Ejemplo n.º 17
0
void
TIFFInput::readspec (bool read_meta)
{
    uint32 width = 0, height = 0, depth = 0;
    unsigned short nchans = 1;
    TIFFGetField (m_tif, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField (m_tif, TIFFTAG_IMAGELENGTH, &height);
    TIFFGetFieldDefaulted (m_tif, TIFFTAG_IMAGEDEPTH, &depth);
    TIFFGetFieldDefaulted (m_tif, TIFFTAG_SAMPLESPERPIXEL, &nchans);

    if (read_meta) {
        // clear the whole m_spec and start fresh
        m_spec = ImageSpec ((int)width, (int)height, (int)nchans);
    } else {
        // assume m_spec is valid, except for things that might differ
        // between MIP levels
        m_spec.width = (int)width;
        m_spec.height = (int)height;
        m_spec.depth = (int)depth;
        m_spec.full_x = 0;
        m_spec.full_y = 0;
        m_spec.full_z = 0;
        m_spec.full_width = (int)width;
        m_spec.full_height = (int)height;
        m_spec.full_depth = (int)depth;
        m_spec.nchannels = (int)nchans;
    }

    float x = 0, y = 0;
    TIFFGetField (m_tif, TIFFTAG_XPOSITION, &x);
    TIFFGetField (m_tif, TIFFTAG_YPOSITION, &y);
    m_spec.x = (int)x;
    m_spec.y = (int)y;
    m_spec.z = 0;
    // FIXME? - TIFF spec describes the positions as in resolutionunit.
    // What happens if this is not unitless pixels?  Are we interpreting
    // it all wrong?

    if (TIFFGetField (m_tif, TIFFTAG_PIXAR_IMAGEFULLWIDTH, &width) == 1
          && width > 0)
        m_spec.full_width = width;
    if (TIFFGetField (m_tif, TIFFTAG_PIXAR_IMAGEFULLLENGTH, &height) == 1
          && height > 0)
        m_spec.full_height = height;

    if (TIFFIsTiled (m_tif)) {
        TIFFGetField (m_tif, TIFFTAG_TILEWIDTH, &m_spec.tile_width);
        TIFFGetField (m_tif, TIFFTAG_TILELENGTH, &m_spec.tile_height);
        TIFFGetFieldDefaulted (m_tif, TIFFTAG_TILEDEPTH, &m_spec.tile_depth);
    } else {
        m_spec.tile_width = 0;
        m_spec.tile_height = 0;
        m_spec.tile_depth = 0;
    }

    m_bitspersample = 8;
    TIFFGetField (m_tif, TIFFTAG_BITSPERSAMPLE, &m_bitspersample);
    m_spec.attribute ("oiio:BitsPerSample", (int)m_bitspersample);

    unsigned short sampleformat = SAMPLEFORMAT_UINT;
    TIFFGetFieldDefaulted (m_tif, TIFFTAG_SAMPLEFORMAT, &sampleformat);
    switch (m_bitspersample) {
    case 1:
    case 2:
    case 4:
    case 6:
        // Make 1, 2, 4, 6 bpp look like byte images
    case 8:
        if (sampleformat == SAMPLEFORMAT_UINT)
            m_spec.set_format (TypeDesc::UINT8);
        else if (sampleformat == SAMPLEFORMAT_INT)
            m_spec.set_format (TypeDesc::INT8);
        else m_spec.set_format (TypeDesc::UINT8);  // punt
        break;
    case 10:
    case 12:
    case 14:
        // Make 10, 12, 14 bpp look like 16 bit images
    case 16:
        if (sampleformat == SAMPLEFORMAT_UINT)
            m_spec.set_format (TypeDesc::UINT16);
        else if (sampleformat == SAMPLEFORMAT_INT)
            m_spec.set_format (TypeDesc::INT16);
        else if (sampleformat == SAMPLEFORMAT_IEEEFP)
            m_spec.set_format (TypeDesc::HALF); // not to spec, but why not?
        else
            m_spec.set_format (TypeDesc::UNKNOWN);
        break;
    case 32:
        if (sampleformat == SAMPLEFORMAT_IEEEFP)
            m_spec.set_format (TypeDesc::FLOAT);
        else if (sampleformat == SAMPLEFORMAT_UINT)
            m_spec.set_format (TypeDesc::UINT32);
        else if (sampleformat == SAMPLEFORMAT_INT)
            m_spec.set_format (TypeDesc::INT32);
        else
            m_spec.set_format (TypeDesc::UNKNOWN);
        break;
    case 64:
        if (sampleformat == SAMPLEFORMAT_IEEEFP)
            m_spec.set_format (TypeDesc::DOUBLE);
        else
            m_spec.set_format (TypeDesc::UNKNOWN);
        break;
    default:
        m_spec.set_format (TypeDesc::UNKNOWN);
        break;
    }

    // If we've been instructed to skip reading metadata, because it is
    // guaranteed to be identical to what we already have in m_spec,
    // skip everything following.
    if (! read_meta)
        return;

    // Use the table for all the obvious things that can be mindlessly
    // shoved into the image spec.
    for (int i = 0;  tiff_tag_table[i].name;  ++i)
        find_tag (tiff_tag_table[i].tifftag,
                  tiff_tag_table[i].tifftype, tiff_tag_table[i].name);

    // Now we need to get fields "by hand" for anything else that is less
    // straightforward...

    m_photometric = (m_spec.nchannels == 1 ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB);
    TIFFGetField (m_tif, TIFFTAG_PHOTOMETRIC, &m_photometric);
    m_spec.attribute ("tiff:PhotometricInterpretation", (int)m_photometric);
    if (m_photometric == PHOTOMETRIC_PALETTE) {
        // Read the color map
        unsigned short *r = NULL, *g = NULL, *b = NULL;
        TIFFGetField (m_tif, TIFFTAG_COLORMAP, &r, &g, &b);
        ASSERT (r != NULL && g != NULL && b != NULL);
        m_colormap.clear ();
        m_colormap.insert (m_colormap.end(), r, r + (1 << m_bitspersample));
        m_colormap.insert (m_colormap.end(), g, g + (1 << m_bitspersample));
        m_colormap.insert (m_colormap.end(), b, b + (1 << m_bitspersample));
        // Palette TIFF images are always 3 channels (to the client)
        m_spec.nchannels = 3;
        m_spec.default_channel_names ();
        // FIXME - what about palette + extra (alpha?) channels?  Is that
        // allowed?  And if so, ever encountered in the wild?
    }

    TIFFGetFieldDefaulted (m_tif, TIFFTAG_PLANARCONFIG, &m_planarconfig);
    m_separate = (m_planarconfig == PLANARCONFIG_SEPARATE &&
                  m_spec.nchannels > 1 &&
                  m_photometric != PHOTOMETRIC_PALETTE);
    m_spec.attribute ("tiff:PlanarConfiguration", (int)m_planarconfig);
    if (m_planarconfig == PLANARCONFIG_SEPARATE)
        m_spec.attribute ("planarconfig", "separate");
    else
        m_spec.attribute ("planarconfig", "contig");

    int compress = 0;
    TIFFGetFieldDefaulted (m_tif, TIFFTAG_COMPRESSION, &compress);
    m_spec.attribute ("tiff:Compression", compress);
    switch (compress) {
    case COMPRESSION_NONE :
        m_spec.attribute ("compression", "none");
        break;
    case COMPRESSION_LZW :
        m_spec.attribute ("compression", "lzw");
        break;
    case COMPRESSION_CCITTRLE :
        m_spec.attribute ("compression", "ccittrle");
        break;
    case COMPRESSION_DEFLATE :
    case COMPRESSION_ADOBE_DEFLATE :
        m_spec.attribute ("compression", "zip");
        break;
    case COMPRESSION_PACKBITS :
        m_spec.attribute ("compression", "packbits");
        break;
    default:
        break;
    }

    int rowsperstrip = -1;
    if (! m_spec.tile_width) {
        TIFFGetField (m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
        if (rowsperstrip > 0)
            m_spec.attribute ("tiff:RowsPerStrip", rowsperstrip);
    }

    // The libtiff docs say that only uncompressed images, or those with
    // rowsperstrip==1, support random access to scanlines.
    m_no_random_access = (compress != COMPRESSION_NONE && rowsperstrip != 1);

    short resunit = -1;
    TIFFGetField (m_tif, TIFFTAG_RESOLUTIONUNIT, &resunit);
    switch (resunit) {
    case RESUNIT_NONE : m_spec.attribute ("ResolutionUnit", "none"); break;
    case RESUNIT_INCH : m_spec.attribute ("ResolutionUnit", "in"); break;
    case RESUNIT_CENTIMETER : m_spec.attribute ("ResolutionUnit", "cm"); break;
    }

    get_matrix_attribute ("worldtocamera", TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA);
    get_matrix_attribute ("worldtoscreen", TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN);
    get_int_attribute ("tiff:subfiletype", TIFFTAG_SUBFILETYPE);
    // FIXME -- should subfiletype be "conventionized" and used for all
    // plugins uniformly? 

    // Do we care about fillorder?  No, the TIFF spec says, "We
    // recommend that FillOrder=2 (lsb-to-msb) be used only in
    // special-purpose applications".  So OIIO will assume msb-to-lsb
    // convention until somebody finds a TIFF file in the wild that
    // breaks this assumption.

    // Special names for shadow maps
    char *s = NULL;
    TIFFGetField (m_tif, TIFFTAG_PIXAR_TEXTUREFORMAT, &s);
    if (s)
        m_emulate_mipmap = true;
    if (s && ! strcmp (s, "Shadow")) {
        for (int c = 0;  c < m_spec.nchannels;  ++c)
            m_spec.channelnames[c] = "z";
    }

    unsigned short *sampleinfo = NULL;
    unsigned short extrasamples = 0;
    TIFFGetFieldDefaulted (m_tif, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampleinfo);
    // std::cerr << "Extra samples = " << extrasamples << "\n";
    bool alpha_is_unassociated = false;  // basic assumption
    if (extrasamples) {
        // If the TIFF ExtraSamples tag was specified, use that to figure
        // out the meaning of alpha.
        int colorchannels = 3;
        if (m_photometric == PHOTOMETRIC_MINISWHITE ||
              m_photometric == PHOTOMETRIC_MINISBLACK ||
              m_photometric == PHOTOMETRIC_PALETTE ||
              m_photometric == PHOTOMETRIC_MASK)
            colorchannels = 1;
        for (int i = 0, c = colorchannels;
             i < extrasamples && c < m_spec.nchannels;  ++i, ++c) {
            // std::cerr << "   extra " << i << " " << sampleinfo[i] << "\n";
            if (sampleinfo[i] == EXTRASAMPLE_ASSOCALPHA) {
                // This is the alpha channel, associated as usual
                m_spec.alpha_channel = c;
            } else if (sampleinfo[i] == EXTRASAMPLE_UNASSALPHA) {
                // This is the alpha channel, but color is unassociated
                m_spec.alpha_channel = c;
                alpha_is_unassociated = true;
                m_spec.attribute ("oiio:UnassociatedAlpha", 1);
            } else {
                DASSERT (sampleinfo[i] == EXTRASAMPLE_UNSPECIFIED);
                // This extra channel is not alpha at all.  Undo any
                // assumptions we previously made about this channel.
                if (m_spec.alpha_channel == c) {
                    m_spec.channelnames[c] = Strutil::format("channel%d", c);
                    m_spec.alpha_channel = -1;
                }
            }
        }
        if (m_spec.alpha_channel >= 0)
            m_spec.channelnames[m_spec.alpha_channel] = "A";
    }
    // Will we need to do alpha conversions?
    m_convert_alpha = (m_spec.alpha_channel >= 0 && alpha_is_unassociated &&
                       ! m_keep_unassociated_alpha);

    // N.B. we currently ignore the following TIFF fields:
    // GrayResponseCurve GrayResponseUnit
    // MaxSampleValue MinSampleValue
    // NewSubfileType SubfileType(deprecated)
    // Colorimetry fields

    // Search for an EXIF IFD in the TIFF file, and if found, rummage 
    // around for Exif fields.
#if TIFFLIB_VERSION > 20050912    /* compat with old TIFF libs - skip Exif */
    int exifoffset = 0;
    if (TIFFGetField (m_tif, TIFFTAG_EXIFIFD, &exifoffset) &&
            TIFFReadEXIFDirectory (m_tif, exifoffset)) {
        for (int i = 0;  exif_tag_table[i].name;  ++i)
            find_tag (exif_tag_table[i].tifftag, exif_tag_table[i].tifftype,
                      exif_tag_table[i].name);
        // I'm not sure what state TIFFReadEXIFDirectory leaves us.
        // So to be safe, close and re-seek.
        TIFFClose (m_tif);
#ifdef _WIN32
        std::wstring wfilename = Filesystem::path_to_windows_native (m_filename);
        m_tif = TIFFOpenW (wfilename.c_str(), "rm");
#else
        m_tif = TIFFOpen (m_filename.c_str(), "rm");
#endif
        TIFFSetDirectory (m_tif, m_subimage);

        // A few tidbits to look for
        ImageIOParameter *p;
        if ((p = m_spec.find_attribute ("Exif:ColorSpace", TypeDesc::INT))) {
            // Exif spec says that anything other than 0xffff==uncalibrated
            // should be interpreted to be sRGB.
            if (*(const int *)p->data() != 0xffff)
                m_spec.attribute ("oiio::ColorSpace", "sRGB");
        }
    }
#endif

#if TIFFLIB_VERSION >= 20051230
    // Search for IPTC metadata in IIM form -- but older versions of
    // libtiff botch the size, so ignore it for very old libtiff.
    int iptcsize = 0;
    const void *iptcdata = NULL;
    if (TIFFGetField (m_tif, TIFFTAG_RICHTIFFIPTC, &iptcsize, &iptcdata)) {
        std::vector<uint32> iptc ((uint32 *)iptcdata, (uint32 *)iptcdata+iptcsize);
        if (TIFFIsByteSwapped (m_tif))
            TIFFSwabArrayOfLong ((uint32*)&iptc[0], iptcsize);
        decode_iptc_iim (&iptc[0], iptcsize*4, m_spec);
    }
#endif

    // Search for an XML packet containing XMP (IPTC, Exif, etc.)
    int xmlsize = 0;
    const void *xmldata = NULL;
    if (TIFFGetField (m_tif, TIFFTAG_XMLPACKET, &xmlsize, &xmldata)) {
        // std::cerr << "Found XML data, size " << xmlsize << "\n";
        if (xmldata && xmlsize) {
            std::string xml ((const char *)xmldata, xmlsize);
            decode_xmp (xml, m_spec);
        }
    }

#if 0
    // Experimental -- look for photoshop data
    int photoshopsize = 0;
    const void *photoshopdata = NULL;
    if (TIFFGetField (m_tif, TIFFTAG_PHOTOSHOP, &photoshopsize, &photoshopdata)) {
        std::cerr << "Found PHOTOSHOP data, size " << photoshopsize << "\n";
        if (photoshopdata && photoshopsize) {
//            std::string photoshop ((const char *)photoshopdata, photoshopsize);
//            std::cerr << "PHOTOSHOP:\n" << photoshop << "\n---\n";
        }
    }
#endif
}
Ejemplo n.º 18
0
bool  TiffDecoder::readData( Mat& img )
{
    bool result = false;
    bool color = img.channels() > 1;
    uchar* data = img.data;

    if( img.depth() != CV_8U && img.depth() != CV_16U && img.depth() != CV_32F && img.depth() != CV_64F )
        return false;

    if( m_tif && m_width && m_height )
    {
        TIFF* tif = (TIFF*)m_tif;
        uint32 tile_width0 = m_width, tile_height0 = 0;
        int x, y, i;
        int is_tiled = TIFFIsTiled(tif);
        uint16 photometric;
        TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric );
        uint16 bpp = 8, ncn = photometric > 1 ? 3 : 1;
        TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bpp );
        TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &ncn );
        const int bitsPerByte = 8;
        int dst_bpp = (int)(img.elemSize1() * bitsPerByte);

        if(dst_bpp == 8)
        {
            char errmsg[1024];
            if(!TIFFRGBAImageOK( tif, errmsg ))
            {
                close();
                return false;
            }
        }

        if( (!is_tiled) ||
            (is_tiled &&
            TIFFGetField( tif, TIFFTAG_TILEWIDTH, &tile_width0 ) &&
            TIFFGetField( tif, TIFFTAG_TILELENGTH, &tile_height0 )))
        {
            if(!is_tiled)
                TIFFGetField( tif, TIFFTAG_ROWSPERSTRIP, &tile_height0 );

            if( tile_width0 <= 0 )
                tile_width0 = m_width;

            if( tile_height0 <= 0 )
                tile_height0 = m_height;

            AutoBuffer<uchar> _buffer( size_t(8) * tile_height0*tile_width0);
            uchar* buffer = _buffer;
            ushort* buffer16 = (ushort*)buffer;
            float* buffer32 = (float*)buffer;
            double* buffer64 = (double*)buffer;
            int tileidx = 0;

            for( y = 0; y < m_height; y += tile_height0, data += img.step*tile_height0 )
            {
                int tile_height = tile_height0;

                if( y + tile_height > m_height )
                    tile_height = m_height - y;

                for( x = 0; x < m_width; x += tile_width0, tileidx++ )
                {
                    int tile_width = tile_width0, ok;

                    if( x + tile_width > m_width )
                        tile_width = m_width - x;

                    switch(dst_bpp)
                    {
                        case 8:
                        {
                            uchar * bstart = buffer;
                            if( !is_tiled )
                                ok = TIFFReadRGBAStrip( tif, y, (uint32*)buffer );
                            else
                            {
                                ok = TIFFReadRGBATile( tif, x, y, (uint32*)buffer );
                                //Tiles fill the buffer from the bottom up
                                bstart += (tile_height0 - tile_height) * tile_width0 * 4;
                            }
                            if( !ok )
                            {
                                close();
                                return false;
                            }

                            for( i = 0; i < tile_height; i++ )
                                if( color )
                                    icvCvt_BGRA2BGR_8u_C4C3R( bstart + i*tile_width0*4, 0,
                                                             data + x*3 + img.step*(tile_height - i - 1), 0,
                                                             cvSize(tile_width,1), 2 );
                                else
                                    icvCvt_BGRA2Gray_8u_C4C1R( bstart + i*tile_width0*4, 0,
                                                              data + x + img.step*(tile_height - i - 1), 0,
                                                              cvSize(tile_width,1), 2 );
                            break;
                        }

                        case 16:
                        {
                            if( !is_tiled )
                                ok = (int)TIFFReadEncodedStrip( tif, tileidx, (uint32*)buffer, (tsize_t)-1 ) >= 0;
                            else
                                ok = (int)TIFFReadEncodedTile( tif, tileidx, (uint32*)buffer, (tsize_t)-1 ) >= 0;

                            if( !ok )
                            {
                                close();
                                return false;
                            }

                            for( i = 0; i < tile_height; i++ )
                            {
                                if( color )
                                {
                                    if( ncn == 1 )
                                    {
                                        icvCvt_Gray2BGR_16u_C1C3R(buffer16 + i*tile_width0*ncn, 0,
                                                                  (ushort*)(data + img.step*i) + x*3, 0,
                                                                  cvSize(tile_width,1) );
                                    }
                                    else if( ncn == 3 )
                                    {
                                        icvCvt_RGB2BGR_16u_C3R(buffer16 + i*tile_width0*ncn, 0,
                                                               (ushort*)(data + img.step*i) + x*3, 0,
                                                               cvSize(tile_width,1) );
                                    }
                                    else
                                    {
                                        icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width0*ncn, 0,
                                                               (ushort*)(data + img.step*i) + x*3, 0,
                                                               cvSize(tile_width,1), 2 );
                                    }
                                }
                                else
                                {
                                    if( ncn == 1 )
                                    {
                                        memcpy((ushort*)(data + img.step*i)+x,
                                               buffer16 + i*tile_width0*ncn,
                                               tile_width*sizeof(buffer16[0]));
                                    }
                                    else
                                    {
                                        icvCvt_BGRA2Gray_16u_CnC1R(buffer16 + i*tile_width0*ncn, 0,
                                                               (ushort*)(data + img.step*i) + x, 0,
                                                               cvSize(tile_width,1), ncn, 2 );
                                    }
                                }
                            }
                            break;
                        }

                        case 32:
                        case 64:
                        {
                            if( !is_tiled )
                                ok = (int)TIFFReadEncodedStrip( tif, tileidx, buffer, (tsize_t)-1 ) >= 0;
                            else
                                ok = (int)TIFFReadEncodedTile( tif, tileidx, buffer, (tsize_t)-1 ) >= 0;

                            if( !ok || ncn != 1 )
                            {
                                close();
                                return false;
                            }

                            for( i = 0; i < tile_height; i++ )
                            {
                                if(dst_bpp == 32)
                                {
                                    memcpy((float*)(data + img.step*i)+x,
                                           buffer32 + i*tile_width0*ncn,
                                           tile_width*sizeof(buffer32[0]));
                                }
                                else
                                {
                                    memcpy((double*)(data + img.step*i)+x,
                                         buffer64 + i*tile_width0*ncn,
                                         tile_width*sizeof(buffer64[0]));
                                }
                            }

                            break;
                        }
                        default:
                        {
                            close();
                            return false;
                        }
                    }
                }
            }

            result = true;
        }
    }

    close();
    return result;
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
0
int
TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
{
    uint16* sampleinfo;
    uint16 extrasamples;
    uint16 planarconfig;
    int colorchannels;

    img->tif = tif;
    img->stoponerr = stop;
    TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
    switch (img->bitspersample) {
    case 1: case 2: case 4:
    case 8: case 16:
    break;
    default:
    sprintf(emsg, "Sorry, can not image with %d-bit samples",
    img->bitspersample);
    return (0);
    }
    img->alpha = 0;
    TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
    TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
    &extrasamples, &sampleinfo);
    if (extrasamples == 1)
    switch (sampleinfo[0]) {
    case EXTRASAMPLE_ASSOCALPHA:    /* data is pre-multiplied */
    case EXTRASAMPLE_UNASSALPHA:    /* data is not pre-multiplied */
    img->alpha = sampleinfo[0];
    break;
    }
    colorchannels = img->samplesperpixel - extrasamples;
    TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
    if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) {
    switch (colorchannels) {
    case 1:
    if (isCCITTCompression(tif))
    img->photometric = PHOTOMETRIC_MINISWHITE;
    else
    img->photometric = PHOTOMETRIC_MINISBLACK;
    break;
    case 3:
    img->photometric = PHOTOMETRIC_RGB;
    break;
    default:
    sprintf(emsg, "Missing needed %s tag", photoTag);
    return (0);
    }
    }
    switch (img->photometric) {
    case PHOTOMETRIC_PALETTE:
    if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
    &img->redcmap, &img->greencmap, &img->bluecmap)) {
    TIFFError(TIFFFileName(tif), "Missing required \"Colormap\" tag");
    return (0);
    }
    /* fall thru... */
    case PHOTOMETRIC_MINISWHITE:
    case PHOTOMETRIC_MINISBLACK:
    if (planarconfig == PLANARCONFIG_CONTIG && img->samplesperpixel != 1) {
    sprintf(emsg,
    "Sorry, can not handle contiguous data with %s=%d, and %s=%d",
    photoTag, img->photometric,
    "Samples/pixel", img->samplesperpixel);
    return (0);
    }
    break;
    case PHOTOMETRIC_YCBCR:
    if (planarconfig != PLANARCONFIG_CONTIG) {
    sprintf(emsg, "Sorry, can not handle YCbCr images with %s=%d",
    "Planarconfiguration", planarconfig);
    return (0);
    }
    /* It would probably be nice to have a reality check here. */
    { uint16 compress;
      TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
      if (compress == COMPRESSION_JPEG && planarconfig == PLANARCONFIG_CONTIG) {
    /* can rely on libjpeg to convert to RGB */
    /* XXX should restore current state on exit */
    TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
    img->photometric = PHOTOMETRIC_RGB;
      }
    }
    break;
    case PHOTOMETRIC_RGB:
    if (colorchannels < 3) {
    sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
    "Color channels", colorchannels);
    return (0);
    }
    break;
    case PHOTOMETRIC_SEPARATED: {
    uint16 inkset;
    TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
    if (inkset != INKSET_CMYK) {
    sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
    "InkSet", inkset);
    return (0);
    }
    if (img->samplesperpixel != 4) {
    sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
    "Samples/pixel", img->samplesperpixel);
    return (0);
    }
    break;
    }
    default:
    sprintf(emsg, "Sorry, can not handle image with %s=%d",
    photoTag, img->photometric);
    return (0);
    }
    img->Map = NULL;
    img->BWmap = NULL;
    img->PALmap = NULL;
    img->ycbcr = NULL;
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
    TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
    img->isContig =
    !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1);
    if (img->isContig) {
    img->get = TIFFIsTiled(tif) ? gtTileContig : gtStripContig;
    (void) pickTileContigCase(img);
    } else {
    img->get = TIFFIsTiled(tif) ? gtTileSeparate : gtStripSeparate;
    (void) pickTileSeparateCase(img);
    }
    return (1);
}
Ejemplo n.º 21
0
static void*
tiff_init(FILE *fp, char *filename, unsigned int page,
	  struct ida_image_info *i, int thumbnail)
{
    struct tiff_state *h;

    fclose(fp);
    h = malloc(sizeof(*h));
    memset(h,0,sizeof(*h));

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

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

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

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

    return h;

 oops:
    if (h->tif)
	TIFFClose(h->tif);
    free(h);
    return NULL;
}
bool _openslide_try_generic_tiff(openslide_t *osr, TIFF *tiff,
				 struct _openslide_hash *quickhash1) {
  GList *layer_list = NULL;
  int32_t layer_count = 0;
  int32_t *layers = NULL;
  int32_t current_layer = 0;

  if (!TIFFIsTiled(tiff)) {
    goto FAIL; // not tiled
  }

  if (osr) {
    g_hash_table_insert(osr->properties,
			g_strdup(OPENSLIDE_PROPERTY_NAME_VENDOR),
			g_strdup("generic-tiff"));
  }

  // accumulate tiled layers
  current_layer = 0;
  layer_count = 0;
  do {
    if (TIFFIsTiled(tiff)) {
      // get width
      uint32_t width;
      if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width)) {
	// oh no
	continue;
      }

      // confirm it is either the first image, or reduced-resolution
      if (current_layer != 0) {
	uint32_t subfiletype;
	if (!TIFFGetField(tiff, TIFFTAG_SUBFILETYPE, &subfiletype)) {
	  continue;
	}

	if (!(subfiletype & FILETYPE_REDUCEDIMAGE)) {
	  continue;
	}
      }

      // verify that we can read this compression (hard fail if not)
      uint16_t compression;
      if (!TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression)) {
	g_warning("Can't read compression scheme");
	goto FAIL;
      };
      if (!TIFFIsCODECConfigured(compression)) {
	g_warning("Unsupported TIFF compression: %u", compression);
	goto FAIL;
      }

      // push into list
      struct layer *l = g_slice_new(struct layer);
      l->layer_number = current_layer;
      l->width = width;
      layer_list = g_list_prepend(layer_list, l);
      layer_count++;
    }
    current_layer++;
  } while (TIFFReadDirectory(tiff));

  // sort tiled layers
  layer_list = g_list_sort(layer_list, width_compare);

  // copy layers in, while deleting the list
  layers = g_new(int32_t, layer_count);
  for (int i = 0; i < layer_count; i++) {
    struct layer *l = (struct layer *)layer_list->data;
    layer_list = g_list_delete_link(layer_list, layer_list);

    layers[i] = l->layer_number;
    g_slice_free(struct layer, l);
  }

  g_assert(layer_list == NULL);

  // all set, load up the TIFF-specific ops
  _openslide_add_tiff_ops(osr, tiff,
			  0, NULL,
			  layer_count, layers,
			  _openslide_generic_tiff_tilereader,
			  quickhash1);


  return true;

 FAIL:
  // free the layer list
  for (GList *i = layer_list; i != NULL; i = g_list_delete_link(i, i)) {
    g_slice_free(struct layer, i->data);
  }

  return false;
}
Ejemplo n.º 23
0
void TifReader::readLine(short *buffer, int x0, int x1, int shrink)
{
	assert(shrink > 0);

	const int pixelSize = 8;
	int stripRowSize = m_rowLength * pixelSize;

	if (m_row < m_info.m_y0 || m_row > m_info.m_y1) {
		memset(buffer, 0, (x1 - x0 + 1) * pixelSize);
		m_row++;
		return;
	}

	int stripIndex = m_row / m_rowsPerStrip;
	if (m_stripIndex != stripIndex) {
		// Retrieve the strip holding current row. Please, observe that
		// TIFF functions will return the strip buffer in the BOTTOM-UP orientation,
		// no matter the internal tif's orientation storage

		m_stripIndex = stripIndex;

		if (TIFFIsTiled(m_tiff)) {
			// Retrieve tiles size
			uint32 tileWidth = 0, tileHeight = 0;
			TIFFGetField(m_tiff, TIFFTAG_TILEWIDTH, &tileWidth);
			TIFFGetField(m_tiff, TIFFTAG_TILELENGTH, &tileHeight);
			assert(tileWidth > 0 && tileHeight > 0);

			// Allocate a sufficient buffer to store a single tile
			int tileSize = tileWidth * tileHeight;
			std::unique_ptr<uint64[]> tile(new uint64[tileSize]);

			int x = 0;
			int y = tileHeight * m_stripIndex;

			// In case it's the last tiles row, the tile size might exceed the image bounds
			int lastTy = std::min((int)tileHeight, m_info.m_ly - y);

			// Traverse the tiles row
			while (x < m_info.m_lx) {
				int ret = TIFFReadRGBATile_64(m_tiff, x, y, tile.get());
				assert(ret);

				int tileRowSize = std::min((int)tileWidth, m_info.m_lx - x) * pixelSize;

				// Copy the tile rows in the corresponding output strip rows
				for (int ty = 0; ty < lastTy; ++ty) {
					memcpy(
						m_stripBuffer + (ty * m_rowLength + x) * pixelSize,
						(UCHAR *)tile.get() + ty * tileWidth * pixelSize,
						tileRowSize);
				}

				x += tileWidth;
			}
		} else {
			int y = m_rowsPerStrip * m_stripIndex;
			int ok = TIFFReadRGBAStrip_64(m_tiff, y, (uint64 *)m_stripBuffer);
			assert(ok);
		}
	}

	uint16 orient = ORIENTATION_TOPLEFT;
	TIFFGetField(m_tiff, TIFFTAG_ORIENTATION, &orient);

	int r = m_rowsPerStrip - 1 - (m_row % m_rowsPerStrip);
	switch (orient) // Pretty weak check for top/bottom orientation
	{
	case ORIENTATION_TOPLEFT:
	case ORIENTATION_TOPRIGHT:
	case ORIENTATION_LEFTTOP:
	case ORIENTATION_RIGHTTOP:
		// We have to invert the fixed BOTTOM-UP returned by TIFF functions - since this function is
		// supposed to ignore orientation issues (which are managed outside).

		// The last tiles row will actually start at the END OF THE IMAGE (not necessarily at
		// m_rowsPerStrip multiples). So, we must adjust for that.

		r = std::min(m_rowsPerStrip, m_info.m_ly - m_rowsPerStrip * m_stripIndex) - 1 -
			(m_row % m_rowsPerStrip);
		break;

	case ORIENTATION_BOTRIGHT:
	case ORIENTATION_BOTLEFT:
	case ORIENTATION_RIGHTBOT:
	case ORIENTATION_LEFTBOT:
		r = m_row % m_rowsPerStrip;
		break;
	}

	// Finally, copy the strip row to the output row buffer
	TPixel64 *pix = (TPixel64 *)buffer;
	USHORT *v = (USHORT *)(m_stripBuffer + r * stripRowSize);

	pix += x0;
	v += 4 * x0;

	int width = (x1 < x0) ? (m_info.m_lx - 1) / shrink + 1 : (x1 - x0) / shrink + 1;

	for (int i = 0; i < width; i++) {
		USHORT c = *v++;
		pix->r = c;
		c = *v++;
		pix->g = c;
		c = *v++;
		pix->b = c;
		c = *v++;
		pix->m = c;

		pix += shrink;
		v += 4 * (shrink - 1);
	}

	m_row++;
}
Ejemplo n.º 24
0
/*
 * Select the appropriate copy function to use.
 */
static copyFunc
pickCopyFunc(TIFF* in, TIFF* out, uint16 bitspersample, uint16 samplesperpixel)
{
	uint16 shortv;
	uint32 w, l, tw, tl;
	int bychunk;

	(void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
	if (shortv != config && bitspersample != 8 && samplesperpixel > 1) {
		fprintf(stderr,
"%s: Can not handle different planar configuration w/ bits/sample != 8\n",
		    TIFFFileName(in));
		return (NULL);
	}
	TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w);
	TIFFGetField(in, TIFFTAG_IMAGELENGTH, &l);
	if (TIFFIsTiled(out)) {
		if (!TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw))
			tw = w;
		if (!TIFFGetField(in, TIFFTAG_TILELENGTH, &tl))
			tl = l;
		bychunk = (tw == tilewidth && tl == tilelength);
	} else if (TIFFIsTiled(in)) {
		TIFFGetField(in, TIFFTAG_TILEWIDTH, &tw);
		TIFFGetField(in, TIFFTAG_TILELENGTH, &tl);
		bychunk = (tw == w && tl == rowsperstrip);
	} else {
		uint32 irps = (uint32) -1L;
		TIFFGetField(in, TIFFTAG_ROWSPERSTRIP, &irps);
		bychunk = (rowsperstrip == irps);
	}
#define	T 1
#define	F 0
#define pack(a,b,c,d,e)	((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
	switch(pack(shortv,config,TIFFIsTiled(in),TIFFIsTiled(out),bychunk)) {
/* Strips -> Tiles */
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,F):
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,T,T):
		return cpContigStrips2ContigTiles;
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,F):
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, F,T,T):
		return cpContigStrips2SeparateTiles;
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,F):
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,T,T):
		return cpSeparateStrips2ContigTiles;
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,F):
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,T,T):
		return cpSeparateStrips2SeparateTiles;
/* Tiles -> Tiles */
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,F):
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,T,T):
		return cpContigTiles2ContigTiles;
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,F):
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,T,T):
		return cpContigTiles2SeparateTiles;
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,F):
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,T,T):
		return cpSeparateTiles2ContigTiles;
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,F):
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,T,T):
		return cpSeparateTiles2SeparateTiles;
/* Tiles -> Strips */
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,F):
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   T,F,T):
		return cpContigTiles2ContigStrips;
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,F):
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_SEPARATE, T,F,T):
		return cpContigTiles2SeparateStrips;
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,F):
        case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   T,F,T):
		return cpSeparateTiles2ContigStrips;
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,F):
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, T,F,T):
		return cpSeparateTiles2SeparateStrips;
/* Strips -> Strips */
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,F):
		return cpContig2ContigByRow;
	case pack(PLANARCONFIG_CONTIG,   PLANARCONFIG_CONTIG,   F,F,T):
		return cpDecodedStrips;
	case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,F):
	case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE,   F,F,T):
		return cpContig2SeparateByRow;
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,F):
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG,   F,F,T):
		return cpSeparate2ContigByRow;
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,F):
	case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,T):
		return cpSeparate2SeparateByRow;
	}
#undef pack
#undef F
#undef T
	fprintf(stderr, "tiffcp: %s: Don't know how to copy/convert image.\n",
	    TIFFFileName(in));
	return (NULL);
}
Ejemplo n.º 25
0
void
TIFFInput::readspec ()
{
    uint32 width = 0, height = 0, depth = 0;
    unsigned short nchans = 1;
    TIFFGetField (m_tif, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField (m_tif, TIFFTAG_IMAGELENGTH, &height);
    TIFFGetFieldDefaulted (m_tif, TIFFTAG_IMAGEDEPTH, &depth);
    TIFFGetFieldDefaulted (m_tif, TIFFTAG_SAMPLESPERPIXEL, &nchans);

    m_spec = ImageSpec ((int)width, (int)height, (int)nchans);

    float x = 0, y = 0;
    TIFFGetField (m_tif, TIFFTAG_XPOSITION, &x);
    TIFFGetField (m_tif, TIFFTAG_YPOSITION, &y);
    m_spec.x = (int)x;
    m_spec.y = (int)y;
    m_spec.z = 0;
    // FIXME? - TIFF spec describes the positions as in resolutionunit.
    // What happens if this is not unitless pixels?  Are we interpreting
    // it all wrong?

    if (TIFFGetField (m_tif, TIFFTAG_PIXAR_IMAGEFULLWIDTH, &width) == 1
          && width > 0)
        m_spec.full_width = width;
    if (TIFFGetField (m_tif, TIFFTAG_PIXAR_IMAGEFULLLENGTH, &height) == 1
          && height > 0)
        m_spec.full_height = height;

    if (TIFFIsTiled (m_tif)) {
        TIFFGetField (m_tif, TIFFTAG_TILEWIDTH, &m_spec.tile_width);
        TIFFGetField (m_tif, TIFFTAG_TILELENGTH, &m_spec.tile_height);
        TIFFGetFieldDefaulted (m_tif, TIFFTAG_TILEDEPTH, &m_spec.tile_depth);
    } else {
        m_spec.tile_width = 0;
        m_spec.tile_height = 0;
        m_spec.tile_depth = 0;
    }

    m_bitspersample = 8;
    TIFFGetField (m_tif, TIFFTAG_BITSPERSAMPLE, &m_bitspersample);
    m_spec.attribute ("oiio:BitsPerSample", (int)m_bitspersample);

    unsigned short sampleformat = SAMPLEFORMAT_UINT;
    TIFFGetFieldDefaulted (m_tif, TIFFTAG_SAMPLEFORMAT, &sampleformat);
    switch (m_bitspersample) {
    case 1:
    case 2:
    case 4:
        // Make 1, 2, 4 bpp look like byte images
    case 8:
        if (sampleformat == SAMPLEFORMAT_UINT)
            m_spec.set_format (TypeDesc::UINT8);
        else if (sampleformat == SAMPLEFORMAT_INT)
            m_spec.set_format (TypeDesc::INT8);
        else m_spec.set_format (TypeDesc::UINT8);  // punt
        break;
    case 16:
        if (sampleformat == SAMPLEFORMAT_UINT)
            m_spec.set_format (TypeDesc::UINT16);
        else if (sampleformat == SAMPLEFORMAT_INT)
            m_spec.set_format (TypeDesc::INT16);
        break;
    case 32:
        if (sampleformat == SAMPLEFORMAT_IEEEFP)
            m_spec.set_format (TypeDesc::FLOAT);
        break;
    case 64:
        if (sampleformat == SAMPLEFORMAT_IEEEFP)
            m_spec.set_format (TypeDesc::DOUBLE);
        break;
    default:
        m_spec.set_format (TypeDesc::UNKNOWN);
        break;
    }

    // Use the table for all the obvious things that can be mindlessly
    // shoved into the image spec.
    for (int i = 0;  tiff_tag_table[i].name;  ++i)
        find_tag (tiff_tag_table[i].tifftag,
                  tiff_tag_table[i].tifftype, tiff_tag_table[i].name);

    // Now we need to get fields "by hand" for anything else that is less
    // straightforward...

    m_photometric = (m_spec.nchannels == 1 ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB);
    TIFFGetField (m_tif, TIFFTAG_PHOTOMETRIC, &m_photometric);
    m_spec.attribute ("tiff:PhotometricInterpretation", (int)m_photometric);
    if (m_photometric == PHOTOMETRIC_PALETTE) {
        // Read the color map
        unsigned short *r = NULL, *g = NULL, *b = NULL;
        TIFFGetField (m_tif, TIFFTAG_COLORMAP, &r, &g, &b);
        ASSERT (r != NULL && g != NULL && b != NULL);
        m_colormap.clear ();
        m_colormap.insert (m_colormap.end(), r, r + (1 << m_bitspersample));
        m_colormap.insert (m_colormap.end(), g, g + (1 << m_bitspersample));
        m_colormap.insert (m_colormap.end(), b, b + (1 << m_bitspersample));
        // Palette TIFF images are always 3 channels (to the client)
        m_spec.nchannels = 3;
        m_spec.default_channel_names ();
    }

    TIFFGetFieldDefaulted (m_tif, TIFFTAG_PLANARCONFIG, &m_planarconfig);
    m_spec.attribute ("tiff:PlanarConfiguration", (int)m_planarconfig);
    if (m_planarconfig == PLANARCONFIG_SEPARATE)
        m_spec.attribute ("planarconfig", "separate");
    else
        m_spec.attribute ("planarconfig", "contig");

    int compress = 0;
    TIFFGetFieldDefaulted (m_tif, TIFFTAG_COMPRESSION, &compress);
    m_spec.attribute ("tiff:Compression", compress);
    switch (compress) {
    case COMPRESSION_NONE :
        m_spec.attribute ("compression", "none");
        break;
    case COMPRESSION_LZW :
        m_spec.attribute ("compression", "lzw");
        break;
    case COMPRESSION_CCITTRLE :
        m_spec.attribute ("compression", "ccittrle");
        break;
    case COMPRESSION_DEFLATE :
    case COMPRESSION_ADOBE_DEFLATE :
        m_spec.attribute ("compression", "zip");
        break;
    case COMPRESSION_PACKBITS :
        m_spec.attribute ("compression", "packbits");
        break;
    default:
        break;
    }

    int rowsperstrip = -1;
    if (! m_spec.tile_width) {
        TIFFGetField (m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
        if (rowsperstrip > 0)
            m_spec.attribute ("tiff:RowsPerStrip", rowsperstrip);
    }

    // The libtiff docs say that only uncompressed images, or those with
    // rowsperstrip==1, support random access to scanlines.
    m_no_random_access = (compress != COMPRESSION_NONE && rowsperstrip != 1);

    short resunit = -1;
    TIFFGetField (m_tif, TIFFTAG_RESOLUTIONUNIT, &resunit);
    switch (resunit) {
    case RESUNIT_NONE : m_spec.attribute ("ResolutionUnit", "none"); break;
    case RESUNIT_INCH : m_spec.attribute ("ResolutionUnit", "in"); break;
    case RESUNIT_CENTIMETER : m_spec.attribute ("ResolutionUnit", "cm"); break;
    }

    get_matrix_attribute ("worldtocamera", TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA);
    get_matrix_attribute ("worldtoscreen", TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN);
    get_int_attribute ("tiff:subfiletype", TIFFTAG_SUBFILETYPE);
    // FIXME -- should subfiletype be "conventionized" and used for all
    // plugins uniformly? 

    // FIXME: do we care about fillorder for 1-bit and 4-bit images?

    // Special names for shadow maps
    char *s = NULL;
    TIFFGetField (m_tif, TIFFTAG_PIXAR_TEXTUREFORMAT, &s);
    if (s)
        m_emulate_mipmap = true;
    if (s && ! strcmp (s, "Shadow")) {
        for (int c = 0;  c < m_spec.nchannels;  ++c)
            m_spec.channelnames[c] = "z";
    }

    // N.B. we currently ignore the following TIFF fields:
    // ExtraSamples
    // GrayResponseCurve GrayResponseUnit
    // MaxSampleValue MinSampleValue
    // NewSubfileType SubfileType(deprecated)
    // Colorimetry fields

    // Search for an EXIF IFD in the TIFF file, and if found, rummage 
    // around for Exif fields.
#if TIFFLIB_VERSION > 20050912    /* compat with old TIFF libs - skip Exif */
    int exifoffset = 0;
    if (TIFFGetField (m_tif, TIFFTAG_EXIFIFD, &exifoffset) &&
            TIFFReadEXIFDirectory (m_tif, exifoffset)) {
        for (int i = 0;  exif_tag_table[i].name;  ++i)
            find_tag (exif_tag_table[i].tifftag, exif_tag_table[i].tifftype,
                      exif_tag_table[i].name);
        // I'm not sure what state TIFFReadEXIFDirectory leaves us.
        // So to be safe, close and re-seek.
        TIFFClose (m_tif);
        m_tif = TIFFOpen (m_filename.c_str(), "rm");
        TIFFSetDirectory (m_tif, m_subimage);

        // A few tidbits to look for
        ImageIOParameter *p;
        if ((p = m_spec.find_attribute ("Exif:ColorSpace", TypeDesc::INT))) {
            // Exif spec says that anything other than 0xffff==uncalibrated
            // should be interpreted to be sRGB.
            if (*(const int *)p->data() != 0xffff)
                m_spec.attribute ("oiio::ColorSpace", "sRGB");
        }
    }
#endif

#if TIFFLIB_VERSION >= 20051230
    // Search for IPTC metadata in IIM form -- but older versions of
    // libtiff botch the size, so ignore it for very old libtiff.
    int iptcsize = 0;
    const void *iptcdata = NULL;
    if (TIFFGetField (m_tif, TIFFTAG_RICHTIFFIPTC, &iptcsize, &iptcdata)) {
        std::vector<uint32> iptc ((uint32 *)iptcdata, (uint32 *)iptcdata+iptcsize);
        if (TIFFIsByteSwapped (m_tif))
            TIFFSwabArrayOfLong ((uint32*)&iptc[0], iptcsize);
        decode_iptc_iim (&iptc[0], iptcsize*4, m_spec);
    }
#endif

    // Search for an XML packet containing XMP (IPTC, Exif, etc.)
    int xmlsize = 0;
    const void *xmldata = NULL;
    if (TIFFGetField (m_tif, TIFFTAG_XMLPACKET, &xmlsize, &xmldata)) {
        // std::cerr << "Found XML data, size " << xmlsize << "\n";
        if (xmldata && xmlsize) {
            std::string xml ((const char *)xmldata, xmlsize);
            decode_xmp (xml, m_spec);
        }
    }

#if 0
    // Experimental -- look for photoshop data
    int photoshopsize = 0;
    const void *photoshopdata = NULL;
    if (TIFFGetField (m_tif, TIFFTAG_PHOTOSHOP, &photoshopsize, &photoshopdata)) {
        std::cerr << "Found PHOTOSHOP data, size " << photoshopsize << "\n";
        if (photoshopdata && photoshopsize) {
//            std::string photoshop ((const char *)photoshopdata, photoshopsize);
//            std::cerr << "PHOTOSHOP:\n" << photoshop << "\n---\n";
        }
    }
#endif
}