📄 tif_luv.c
字号:
static voidLuv32toXYZ(LogLuvState* sp, tidata_t op, int n){ uint32* luv = (uint32*) sp->tbuf; float* xyz = (float*) op; while (n-- > 0) { LogLuv32toXYZ(*luv++, xyz); xyz += 3; }}static voidLuv32toLuv48(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 voidLuv32toRGB(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 voidLuv32fromXYZ(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 voidLuv32fromLuv48(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 intLogL16GuessDataFmt(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 intLogL16InitState(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 = td->td_imagewidth * td->td_rowsperstrip; sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (int16)); if (sp->tbuf == NULL) { TIFFError(module, "%s: No space for SGILog translation buffer", tif->tif_name); return (0); } return (1);}static intLogLuvGuessDataFmt(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 intLogLuvInitState(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 = td->td_imagewidth * td->td_rowsperstrip; sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (uint32)); if (sp->tbuf == NULL) { TIFFError(module, "%s: No space for SGILog translation buffer", tif->tif_name); return (0); } return (1);}static intLogLuvSetupDecode(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 intLogLuvSetupEncode(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 voidLogLuvClose(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 voidLogLuvCleanup(TIFF* tif){ LogLuvState* sp = (LogLuvState *)tif->tif_data; if (sp) { if (sp->tbuf) _TIFFfree(sp->tbuf); _TIFFfree(sp); tif->tif_data = NULL; }}static intLogLuvVSetField(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 = TIFFTileSize(tif); 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 intLogLuvVGetField(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"}};intTIFFInitSGILog(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_vgetfield; tif->tif_vgetfield = LogLuvVGetField; /* hook for codec tags */ sp->vsetparent = tif->tif_vsetfield; tif->tif_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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -