⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tif_luv.c

📁 一款最完整的工业组态软源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	}
}

static void
Luv32toLuv48(LogLuvState* sp, tidata_t op, int n)
{
	uint32* luv = (uint32*) sp->tbuf;
	int16* luv3 = (int16*) op;

	while (n-- > 0) {
		double u, v;

		*luv3++ = (int16)(*luv >> 16);
		u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5);
		v = 1./UVSCALE * ((*luv & 0xff) + .5);
		*luv3++ = (int16)(u * (1L<<15));
		*luv3++ = (int16)(v * (1L<<15));
		luv++;
	}
}

static void
Luv32toRGB(LogLuvState* sp, tidata_t op, int n)
{
	uint32* luv = (uint32*) sp->tbuf;
	uint8* rgb = (uint8*) op;

	while (n-- > 0) {
		float xyz[3];

		LogLuv32toXYZ(*luv++, xyz);
		XYZtoRGB24(xyz, rgb);
		rgb += 3;
	}
}

static void
Luv32fromXYZ(LogLuvState* sp, tidata_t op, int n)
{
	uint32* luv = (uint32*) sp->tbuf;
	float* xyz = (float*) op;

	while (n-- > 0) {
		*luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth);
		xyz += 3;
	}
}

static void
Luv32fromLuv48(LogLuvState* sp, tidata_t op, int n)
{
	uint32* luv = (uint32*) sp->tbuf;
	int16* luv3 = (int16*) op;

	if (sp->encode_meth == SGILOGENCODE_NODITHER) {
		while (n-- > 0) {
			*luv++ = (uint32)luv3[0] << 16 |
				(luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) |
				(luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff);
			luv3 += 3;
		}
		return;
	}
	while (n-- > 0) {
		*luv++ = (uint32)luv3[0] << 16 |
	(itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) |
		(itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff);
		luv3 += 3;
	}
}

static void
_logLuvNop(LogLuvState* sp, tidata_t op, int n)
{
	(void) sp; (void) op; (void) n;
}

static int
LogL16GuessDataFmt(TIFFDirectory *td)
{
#define	PACK(s,b,f)	(((b)<<6)|((s)<<3)|(f))
	switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) {
	case PACK(1, 32, SAMPLEFORMAT_IEEEFP):
		return (SGILOGDATAFMT_FLOAT);
	case PACK(1, 16, SAMPLEFORMAT_VOID):
	case PACK(1, 16, SAMPLEFORMAT_INT):
	case PACK(1, 16, SAMPLEFORMAT_UINT):
		return (SGILOGDATAFMT_16BIT);
	case PACK(1,  8, SAMPLEFORMAT_VOID):
	case PACK(1,  8, SAMPLEFORMAT_UINT):
		return (SGILOGDATAFMT_8BIT);
	}
#undef PACK
	return (SGILOGDATAFMT_UNKNOWN);
}

static uint32
multiply(size_t m1, size_t m2)
{
	uint32	bytes = m1 * m2;

	if (m1 && bytes / m1 != m2)
		bytes = 0;

	return bytes;
}

static int
LogL16InitState(TIFF* tif)
{
	TIFFDirectory *td = &tif->tif_dir;
	LogLuvState* sp = DecoderState(tif);
	static const char module[] = "LogL16InitState";

	assert(sp != NULL);
	assert(td->td_photometric == PHOTOMETRIC_LOGL);

	/* for some reason, we can't do this in TIFFInitLogL16 */
	if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
		sp->user_datafmt = LogL16GuessDataFmt(td);
	switch (sp->user_datafmt) {
	case SGILOGDATAFMT_FLOAT:
		sp->pixel_size = sizeof (float);
		break;
	case SGILOGDATAFMT_16BIT:
		sp->pixel_size = sizeof (int16);
		break;
	case SGILOGDATAFMT_8BIT:
		sp->pixel_size = sizeof (uint8);
		break;
	default:
		TIFFError(tif->tif_name,
		    "No support for converting user data format to LogL");
		return (0);
	}
	sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip);
	if (multiply(sp->tbuflen, sizeof (int16)) == 0 ||
	    (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) {
		TIFFError(module, "%s: No space for SGILog translation buffer",
		    tif->tif_name);
		return (0);
	}
	return (1);
}

static int
LogLuvGuessDataFmt(TIFFDirectory *td)
{
	int guess;

	/*
	 * If the user didn't tell us their datafmt,
	 * take our best guess from the bitspersample.
	 */
#define	PACK(a,b)	(((a)<<3)|(b))
	switch (PACK(td->td_bitspersample, td->td_sampleformat)) {
	case PACK(32, SAMPLEFORMAT_IEEEFP):
		guess = SGILOGDATAFMT_FLOAT;
		break;
	case PACK(32, SAMPLEFORMAT_VOID):
	case PACK(32, SAMPLEFORMAT_UINT):
	case PACK(32, SAMPLEFORMAT_INT):
		guess = SGILOGDATAFMT_RAW;
		break;
	case PACK(16, SAMPLEFORMAT_VOID):
	case PACK(16, SAMPLEFORMAT_INT):
	case PACK(16, SAMPLEFORMAT_UINT):
		guess = SGILOGDATAFMT_16BIT;
		break;
	case PACK( 8, SAMPLEFORMAT_VOID):
	case PACK( 8, SAMPLEFORMAT_UINT):
		guess = SGILOGDATAFMT_8BIT;
		break;
	default:
		guess = SGILOGDATAFMT_UNKNOWN;
		break;
#undef PACK
	}
	/*
	 * Double-check samples per pixel.
	 */
	switch (td->td_samplesperpixel) {
	case 1:
		if (guess != SGILOGDATAFMT_RAW)
			guess = SGILOGDATAFMT_UNKNOWN;
		break;
	case 3:
		if (guess == SGILOGDATAFMT_RAW)
			guess = SGILOGDATAFMT_UNKNOWN;
		break;
	default:
		guess = SGILOGDATAFMT_UNKNOWN;
		break;
	}
	return (guess);
}

static int
LogLuvInitState(TIFF* tif)
{
	TIFFDirectory* td = &tif->tif_dir;
	LogLuvState* sp = DecoderState(tif);
	static const char module[] = "LogLuvInitState";

	assert(sp != NULL);
	assert(td->td_photometric == PHOTOMETRIC_LOGLUV);

	/* for some reason, we can't do this in TIFFInitLogLuv */
	if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
		TIFFError(module,
		    "SGILog compression cannot handle non-contiguous data");
		return (0);
	}
	if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
		sp->user_datafmt = LogLuvGuessDataFmt(td);
	switch (sp->user_datafmt) {
	case SGILOGDATAFMT_FLOAT:
		sp->pixel_size = 3*sizeof (float);
		break;
	case SGILOGDATAFMT_16BIT:
		sp->pixel_size = 3*sizeof (int16);
		break;
	case SGILOGDATAFMT_RAW:
		sp->pixel_size = sizeof (uint32);
		break;
	case SGILOGDATAFMT_8BIT:
		sp->pixel_size = 3*sizeof (uint8);
		break;
	default:
		TIFFError(tif->tif_name,
		    "No support for converting user data format to LogLuv");
		return (0);
	}
	sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip);
	if (multiply(sp->tbuflen, sizeof (uint32)) == 0 ||
	    (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) {
		TIFFError(module, "%s: No space for SGILog translation buffer",
		    tif->tif_name);
		return (0);
	}
	return (1);
}

static int
LogLuvSetupDecode(TIFF* tif)
{
	LogLuvState* sp = DecoderState(tif);
	TIFFDirectory* td = &tif->tif_dir;

	tif->tif_postdecode = _TIFFNoPostDecode;
	switch (td->td_photometric) {
	case PHOTOMETRIC_LOGLUV:
		if (!LogLuvInitState(tif))
			break;
		if (td->td_compression == COMPRESSION_SGILOG24) {
			tif->tif_decoderow = LogLuvDecode24;
			switch (sp->user_datafmt) {
			case SGILOGDATAFMT_FLOAT:
				sp->tfunc = Luv24toXYZ;
				break;
			case SGILOGDATAFMT_16BIT:
				sp->tfunc = Luv24toLuv48;
				break;
			case SGILOGDATAFMT_8BIT:
				sp->tfunc = Luv24toRGB;
				break;
			}
		} else {
			tif->tif_decoderow = LogLuvDecode32;
			switch (sp->user_datafmt) {
			case SGILOGDATAFMT_FLOAT:
				sp->tfunc = Luv32toXYZ;
				break;
			case SGILOGDATAFMT_16BIT:
				sp->tfunc = Luv32toLuv48;
				break;
			case SGILOGDATAFMT_8BIT:
				sp->tfunc = Luv32toRGB;
				break;
			}
		}
		return (1);
	case PHOTOMETRIC_LOGL:
		if (!LogL16InitState(tif))
			break;
		tif->tif_decoderow = LogL16Decode;
		switch (sp->user_datafmt) {
		case SGILOGDATAFMT_FLOAT:
			sp->tfunc = L16toY;
			break;
		case SGILOGDATAFMT_8BIT:
			sp->tfunc = L16toGry;
			break;
		}
		return (1);
	default:
		TIFFError(tif->tif_name,
    "Inappropriate photometric interpretation %d for SGILog compression; %s",
		    td->td_photometric, "must be either LogLUV or LogL");
		break;
	}
	return (0);
}

static int
LogLuvSetupEncode(TIFF* tif)
{
	LogLuvState* sp = EncoderState(tif);
	TIFFDirectory* td = &tif->tif_dir;

	switch (td->td_photometric) {
	case PHOTOMETRIC_LOGLUV:
		if (!LogLuvInitState(tif))
			break;
		if (td->td_compression == COMPRESSION_SGILOG24) {
			tif->tif_encoderow = LogLuvEncode24;
			switch (sp->user_datafmt) {
			case SGILOGDATAFMT_FLOAT:
				sp->tfunc = Luv24fromXYZ;
				break;
			case SGILOGDATAFMT_16BIT:
				sp->tfunc = Luv24fromLuv48;
				break;
			case SGILOGDATAFMT_RAW:
				break;
			default:
				goto notsupported;
			}
		} else {
			tif->tif_encoderow = LogLuvEncode32;
			switch (sp->user_datafmt) {
			case SGILOGDATAFMT_FLOAT:
				sp->tfunc = Luv32fromXYZ;
				break;
			case SGILOGDATAFMT_16BIT:
				sp->tfunc = Luv32fromLuv48;
				break;
			case SGILOGDATAFMT_RAW:
				break;
			default:
				goto notsupported;
			}
		}
		break;
	case PHOTOMETRIC_LOGL:
		if (!LogL16InitState(tif))
			break;
		tif->tif_encoderow = LogL16Encode;
		switch (sp->user_datafmt) {
		case SGILOGDATAFMT_FLOAT:
			sp->tfunc = L16fromY;
			break;
		case SGILOGDATAFMT_16BIT:
			break;
		default:
			goto notsupported;
		}
		break;
	default:
		TIFFError(tif->tif_name,
    "Inappropriate photometric interpretation %d for SGILog compression; %s",
    		    td->td_photometric, "must be either LogLUV or LogL");
		break;
	}
	return (1);
notsupported:
	TIFFError(tif->tif_name,
	    "SGILog compression supported only for %s, or raw data",
	    td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv");
	return (0);
}

static void
LogLuvClose(TIFF* tif)
{
	TIFFDirectory *td = &tif->tif_dir;

	/*
	 * For consistency, we always want to write out the same
	 * bitspersample and sampleformat for our TIFF file,
	 * regardless of the data format being used by the application.
	 * Since this routine is called after tags have been set but
	 * before they have been recorded in the file, we reset them here.
	 */
	td->td_samplesperpixel =
	    (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
	td->td_bitspersample = 16;
	td->td_sampleformat = SAMPLEFORMAT_INT;
}

static void
LogLuvCleanup(TIFF* tif)
{
	LogLuvState* sp = (LogLuvState *)tif->tif_data;

	if (sp) {
		if (sp->tbuf)
			_TIFFfree(sp->tbuf);
		_TIFFfree(sp);
		tif->tif_data = NULL;
	}
}

static int
LogLuvVSetField(TIFF* tif, ttag_t tag, va_list ap)
{
	LogLuvState* sp = DecoderState(tif);
	int bps, fmt;

	switch (tag) {
	case TIFFTAG_SGILOGDATAFMT:
		sp->user_datafmt = va_arg(ap, int);
		/*
		 * Tweak the TIFF header so that the rest of libtiff knows what
		 * size of data will be passed between app and library, and
		 * assume that the app knows what it is doing and is not
		 * confused by these header manipulations...
		 */
		switch (sp->user_datafmt) {
		case SGILOGDATAFMT_FLOAT:
			bps = 32, fmt = SAMPLEFORMAT_IEEEFP;
			break;
		case SGILOGDATAFMT_16BIT:
			bps = 16, fmt = SAMPLEFORMAT_INT;
			break;
		case SGILOGDATAFMT_RAW:
			bps = 32, fmt = SAMPLEFORMAT_UINT;
			TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
			break;
		case SGILOGDATAFMT_8BIT:
			bps = 8, fmt = SAMPLEFORMAT_UINT;
			break;
		default:
			TIFFError(tif->tif_name,
			    "Unknown data format %d for LogLuv compression",
			    sp->user_datafmt);
			return (0);
		}
		TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
		TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt);
		/*
		 * Must recalculate sizes should bits/sample change.
		 */
		tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
		tif->tif_scanlinesize = TIFFScanlineSize(tif);
		return (1);
	case TIFFTAG_SGILOGENCODE:
		sp->encode_meth = va_arg(ap, int);
		if (sp->encode_meth != SGILOGENCODE_NODITHER &&
				sp->encode_meth != SGILOGENCODE_RANDITHER) {
			TIFFError(tif->tif_name,
				"Unknown encoding %d for LogLuv compression",
				sp->encode_meth);
			return (0);
		}
		return (1);
	default:
		return (*sp->vsetparent)(tif, tag, ap);
	}
}

static int
LogLuvVGetField(TIFF* tif, ttag_t tag, va_list ap)
{
	LogLuvState *sp = (LogLuvState *)tif->tif_data;

	switch (tag) {
	case TIFFTAG_SGILOGDATAFMT:
		*va_arg(ap, int*) = sp->user_datafmt;
		return (1);
	default:
		return (*sp->vgetparent)(tif, tag, ap);
	}
}

static const TIFFFieldInfo LogLuvFieldInfo[] = {
    { TIFFTAG_SGILOGDATAFMT,	  0, 0,	TIFF_SHORT,	FIELD_PSEUDO,
      TRUE,	FALSE,	"SGILogDataFmt"},
    { TIFFTAG_SGILOGENCODE,	  0, 0, TIFF_SHORT,	FIELD_PSEUDO,
      TRUE,	FALSE,	"SGILogEncode"}
};

int
TIFFInitSGILog(TIFF* tif, int scheme)
{
	static const char module[] = "TIFFInitSGILog";
	LogLuvState* sp;

	assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG);

	/*
	 * Allocate state block so tag methods have storage to record values.
	 */
	tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LogLuvState));
	if (tif->tif_data == NULL)
		goto bad;
	sp = (LogLuvState*) tif->tif_data;
	_TIFFmemset((tdata_t)sp, 0, sizeof (*sp));
	sp->user_datafmt = SGILOGDATAFMT_UNKNOWN;
	sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ?
				SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER;
	sp->tfunc = _logLuvNop;

	/*
	 * Install codec methods.
	 * NB: tif_decoderow & tif_encoderow are filled
	 *     in at setup time.
	 */
	tif->tif_setupdecode = LogLuvSetupDecode;
	tif->tif_decodestrip = LogLuvDecodeStrip;
	tif->tif_decodetile = LogLuvDecodeTile;
	tif->tif_setupencode = LogLuvSetupEncode;
	tif->tif_encodestrip = LogLuvEncodeStrip;
	tif->tif_encodetile = LogLuvEncodeTile;
	tif->tif_close = LogLuvClose;
	tif->tif_cleanup = LogLuvCleanup;

	/* override SetField so we can handle our private pseudo-tag */
	_TIFFMergeFieldInfo(tif, LogLuvFieldInfo, N(LogLuvFieldInfo));
	sp->vgetparent = tif->tif_tagmethods.vgetfield;
	tif->tif_tagmethods.vgetfield = LogLuvVGetField;   /* hook for codec tags */
	sp->vsetparent = tif->tif_tagmethods.vsetfield;
	tif->tif_tagmethods.vsetfield = LogLuvVSetField;   /* hook for codec tags */

	return (1);
bad:
	TIFFError(module, "%s: No space for LogLuv state block", tif->tif_name);
	return (0);
}
#endif /* LOGLUV_SUPPORT */

/* vim: set ts=8 sts=8 sw=8 noet: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -