📄 tif_luv.c
字号:
}/* * Encode a row of 32-bit pixels. */static intLogLuvEncode32(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s){ LogLuvState* sp = EncoderState(tif); int shft, i, j, npixels; tidata_t op; uint32* tp; uint32 b; int occ, rc=0, mask, beg; assert(s == 0); assert(sp != NULL); npixels = cc / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_RAW) tp = (uint32*) bp; else { tp = (uint32*) sp->tbuf; assert(sp->tbuflen >= npixels); (*sp->tfunc)(sp, bp, npixels); } /* compress each byte string */ op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; for (shft = 4*8; (shft -= 8) >= 0; ) for (i = 0; i < npixels; i += rc) { if (occ < 4) { tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) return (-1); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } mask = 0xff << shft; /* find next run */ for (beg = i; beg < npixels; beg += rc) { b = tp[beg] & mask; rc = 1; while (rc < 127+2 && beg+rc < npixels && (tp[beg+rc] & mask) == b) rc++; if (rc >= MINRUN) break; /* long enough */ } if (beg-i > 1 && beg-i < MINRUN) { b = tp[i] & mask; /* check short run */ j = i+1; while ((tp[j++] & mask) == b) if (j == beg) { *op++ = (tidataval_t)(128-2+j-i); *op++ = (tidataval_t)(b >> shft); occ -= 2; i = beg; break; } } while (i < beg) { /* write out non-run */ if ((j = beg-i) > 127) j = 127; if (occ < j+3) { tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) return (-1); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } *op++ = j; occ--; while (j--) { *op++ = (tidataval_t)(tp[i++] >> shft & 0xff); occ--; } } if (rc >= MINRUN) { /* write out run */ *op++ = 128-2+rc; *op++ = (tidataval_t)(tp[beg] >> shft & 0xff); occ -= 2; } else rc = 0; } tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; return (0);}/* * Encode a strip of pixels. We break it into rows to * avoid encoding runs across row boundaries. */static intLogLuvEncodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s){ tsize_t rowlen = TIFFScanlineSize(tif); assert(cc%rowlen == 0); while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0) bp += rowlen, cc -= rowlen; return (cc == 0);}/* * Encode a tile of pixels. We break it into rows to * avoid encoding runs across row boundaries. */static intLogLuvEncodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s){ tsize_t rowlen = TIFFTileRowSize(tif); assert(cc%rowlen == 0); while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0) bp += rowlen, cc -= rowlen; return (cc == 0);}/* * Encode/Decode functions for converting to and from user formats. */#include "uvcode.h"#define U_NEU 0.210526316#define V_NEU 0.473684211#ifdef M_LN2#define LOGOF2 M_LN2#else#define LOGOF2 0.69314718055994530942#endif#define log2(x) ((1./LOGOF2)*log(x))#define exp2(x) exp(LOGOF2*(x))#define UVSCALE 410.static doublepix16toY(int p16){ int Le = p16 & 0x7fff; double Y; if (!Le) return (0.); Y = exp(LOGOF2/256.*(Le+.5) - LOGOF2*64.); if (p16 & 0x8000) return (-Y); return (Y);}static intpix16fromY(double Y){ if (Y >= 1.84467e19) return (0x7fff); if (Y <= -1.84467e19) return (0xffff); if (Y > 5.43571e-20) return (int)(256.*(log2(Y) + 64.)); if (Y < -5.43571e-20) return (~0x7fff | (int)(256.*(log2(-Y) + 64.))); return (0);}static voidL16toY(LogLuvState* sp, tidata_t op, int n){ int16* l16 = (int16*) sp->tbuf; float* yp = (float*) op; while (n-- > 0) *yp++ = (float)pix16toY(*l16++);}static voidL16toGry(LogLuvState* sp, tidata_t op, int n){ int16* l16 = (int16*) sp->tbuf; uint8* gp = (uint8*) op; while (n-- > 0) { double Y = pix16toY(*l16++); *gp++ = (Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y)); }}static voidL16fromY(LogLuvState* sp, tidata_t op, int n){ int16* l16 = (int16*) sp->tbuf; float* yp = (float*) op; while (n-- > 0) *l16++ = pix16fromY(*yp++);}static voidXYZtoRGB24(float xyz[3], uint8 rgb[3]){ double r, g, b; /* assume CCIR-709 primaries */ r = 2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2]; g = -1.022*xyz[0] + 1.978*xyz[1] + 0.044*xyz[2]; b = 0.061*xyz[0] + -0.224*xyz[1] + 1.163*xyz[2]; /* assume 2.0 gamma for speed */ /* could use integer sqrt approx., but this is probably faster */ rgb[0] = (r <= 0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r)); rgb[1] = (g <= 0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g)); rgb[2] = (b <= 0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b));}static intuv_encode(double u, double v) /* encode (u',v') coordinates */{ register int vi, ui; if (v < UV_VSTART) return(-1); vi = (int)((v - UV_VSTART)*(1./UV_SQSIZ)); if (vi >= UV_NVS) return(-1); if (u < uv_row[vi].ustart) return(-1); ui = (int)((u - uv_row[vi].ustart)*(1./UV_SQSIZ)); if (ui >= uv_row[vi].nus) return(-1); return(uv_row[vi].ncum + ui);}static intuv_decode(double *up, double *vp, int c) /* decode (u',v') index */{ int upper, lower; register int ui, vi; if (c < 0 || c >= UV_NDIVS) return(-1); lower = 0; /* binary search */ upper = UV_NVS; do { vi = (lower + upper) >> 1; ui = c - uv_row[vi].ncum; if (ui > 0) lower = vi; else if (ui < 0) upper = vi; else break; } while (upper - lower > 1); vi = lower; ui = c - uv_row[vi].ncum; *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; *vp = UV_VSTART + (vi+.5)*UV_SQSIZ; return(0);}static voidpix24toXYZ(uint32 p, float XYZ[3]){ int Le, Ce; double L, u, v, s, x, y; /* decode luminance */ Le = p >> 14 & 0x3ff; if (Le == 0) { XYZ[0] = XYZ[1] = XYZ[2] = 0.; return; } L = exp(LOGOF2/64.*(Le+.5) - LOGOF2*12.); /* decode color */ Ce = p & 0x3fff; if (uv_decode(&u, &v, Ce) < 0) { u = U_NEU; v = V_NEU; } s = 1./(6.*u - 16.*v + 12.); x = 9.*u * s; y = 4.*v * s; /* convert to XYZ */ XYZ[0] = (float)(x/y * L); XYZ[1] = (float)L; XYZ[2] = (float)((1.-x-y)/y * L);}static uint32pix24fromXYZ(float XYZ[3]){ int Le, Ce; double L, u, v, s; /* encode luminance */ L = XYZ[1]; if (L >= 16.) Le = 0x3ff; else if (L <= 1./4096.) Le = 0; else Le = (int)(64.*(log2(L) + 12.)); /* encode color */ s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; if (s == 0.) { u = U_NEU; v = V_NEU; } else { u = 4.*XYZ[0] / s; v = 9.*XYZ[1] / s; } Ce = uv_encode(u, v); if (Ce < 0) Ce = uv_encode(U_NEU, V_NEU); /* combine encodings */ return (Le << 14 | Ce);}static voidLuv24toXYZ(LogLuvState* sp, tidata_t op, int n){ uint32* luv = (uint32*) sp->tbuf; float* xyz = (float*) op; while (n-- > 0) { pix24toXYZ(*luv, xyz); xyz += 3; luv++; }}static voidLuv24toLuv48(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 >> 12 & 0xffd) + 13314); if (uv_decode(&u, &v, *luv&0x3fff) < 0) { u = U_NEU; v = V_NEU; } *luv3++ = (int16)(u * (1L<<15)); *luv3++ = (int16)(v * (1L<<15)); luv++; }}static voidLuv24toRGB(LogLuvState* sp, tidata_t op, int n){ uint32* luv = (uint32*) sp->tbuf; uint8* rgb = (uint8*) op; while (n-- > 0) { float xyz[3]; pix24toXYZ(*luv++, xyz); XYZtoRGB24(xyz, rgb); rgb += 3; }}static voidLuv24fromXYZ(LogLuvState* sp, tidata_t op, int n){ uint32* luv = (uint32*) sp->tbuf; float* xyz = (float*) op; while (n-- > 0) { *luv++ = pix24fromXYZ(xyz); xyz += 3; }}static voidLuv24fromLuv48(LogLuvState* sp, tidata_t op, int n){ uint32* luv = (uint32*) sp->tbuf; int16* luv3 = (int16*) op; while (n-- > 0) { int Le, Ce; if (luv3[0] <= 0) Le = 0; else if (luv3[0] >= (1<<12)+3314) Le = (1<<10) - 1; else Le = (luv3[0]-3314) >> 2; Ce = uv_encode((luv[1]+.5)/(1<<15), (luv[2]+.5)/(1<<15)); if (Ce < 0) Ce = uv_encode(U_NEU, V_NEU); *luv++ = (uint32)Le << 14 | Ce; luv3 += 3; }}static voidpix32toXYZ(uint32 p, float XYZ[3]){ double L, u, v, s, x, y; /* decode luminance */ L = pix16toY((int)p >> 16); if (L == 0.) { XYZ[0] = XYZ[1] = XYZ[2] = 0.; return; } /* decode color */ u = 1./UVSCALE * ((p>>8 & 0xff) + .5); v = 1./UVSCALE * ((p & 0xff) + .5); s = 1./(6.*u - 16.*v + 12.); x = 9.*u * s; y = 4.*v * s; /* convert to XYZ */ XYZ[0] = (float)(x/y * L); XYZ[1] = (float)L; XYZ[2] = (float)((1.-x-y)/y * L);}static uint32pix32fromXYZ(float XYZ[3]){ unsigned int Le, ue, ve; double u, v, s; /* encode luminance */ Le = (unsigned int)pix16fromY(XYZ[1]); /* encode color */ s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; if (s == 0.) { u = U_NEU; v = V_NEU; } else { u = 4.*XYZ[0] / s; v = 9.*XYZ[1] / s; } if (u <= 0.) ue = 0; else ue = (unsigned int)(UVSCALE * u); if (ue > 255) ue = 255; if (v <= 0.) ve = 0; else ve = (unsigned int)(UVSCALE * v); if (ve > 255) ve = 255; /* combine encodings */ return (Le << 16 | ue << 8 | ve);}static voidLuv32toXYZ(LogLuvState* sp, tidata_t op, int n){ uint32* luv = (uint32*) sp->tbuf; float* xyz = (float*) op; while (n-- > 0) { pix32toXYZ(*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 void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -