📄 tif_luv.c
字号:
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"#ifndef UVSCALE#define U_NEU 0.210526316#define V_NEU 0.473684211#define UVSCALE 410.#endif#ifndef M_LN2#define M_LN2 0.69314718055994530942#endif#ifndef M_PI#define M_PI 3.14159265358979323846#endif#define log2(x) ((1./M_LN2)*log(x))#define exp2(x) exp(M_LN2*(x))#define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \ (int)(x) : \ (int)((x) + rand()*(1./RAND_MAX) - .5))#if !LOGLUV_PUBLICstatic#endifdoubleLogL16toY(int p16) /* compute luminance from 16-bit LogL */{ int Le = p16 & 0x7fff; double Y; if (!Le) return (0.); Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.); return (!(p16 & 0x8000) ? Y : -Y);}#if !LOGLUV_PUBLICstatic#endifintLogL16fromY(double Y, int em) /* get 16-bit LogL from Y */{ if (Y >= 1.8371976e19) return (0x7fff); if (Y <= -1.8371976e19) return (0xffff); if (Y > 5.4136769e-20) return itrunc(256.*(log2(Y) + 64.), em); if (Y < -5.4136769e-20) return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em)); 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)LogL16toY(*l16++);}static voidL16toGry(LogLuvState* sp, tidata_t op, int n){ int16* l16 = (int16*) sp->tbuf; uint8* gp = (uint8*) op; while (n-- > 0) { double Y = LogL16toY(*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++ = LogL16fromY(*yp++, sp->encode_meth);}#if !LOGLUV_PUBLICstatic#endifvoidXYZtoRGB24(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));}#if !LOGLUV_PUBLICstatic#endifdoubleLogL10toY(int p10) /* compute luminance from 10-bit LogL */{ if (p10 == 0) return (0.); return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.));}#if !LOGLUV_PUBLICstatic#endifintLogL10fromY(double Y, int em) /* get 10-bit LogL from Y */{ if (Y >= 15.742) return (0x3ff); else if (Y <= .00024283) return (0); else return itrunc(64.*(log2(Y) + 12.), em);}#define NANGLES 100#define uv2ang(u, v) ( (NANGLES*.499999999/M_PI) \ * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES )static intoog_encode(double u, double v) /* encode out-of-gamut chroma */{ static int oog_table[NANGLES]; static int initialized = 0; register int i; if (!initialized) { /* set up perimeter table */ double eps[NANGLES], ua, va, ang, epsa; int ui, vi, ustep; for (i = NANGLES; i--; ) eps[i] = 2.; for (vi = UV_NVS; vi--; ) { va = UV_VSTART + (vi+.5)*UV_SQSIZ; ustep = uv_row[vi].nus-1; if (vi == UV_NVS-1 || vi == 0 || ustep <= 0) ustep = 1; for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) { ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; ang = uv2ang(ua, va); i = (int) ang; epsa = fabs(ang - (i+.5)); if (epsa < eps[i]) { oog_table[i] = uv_row[vi].ncum + ui; eps[i] = epsa; } } } for (i = NANGLES; i--; ) /* fill any holes */ if (eps[i] > 1.5) { int i1, i2; for (i1 = 1; i1 < NANGLES/2; i1++) if (eps[(i+i1)%NANGLES] < 1.5) break; for (i2 = 1; i2 < NANGLES/2; i2++) if (eps[(i+NANGLES-i2)%NANGLES] < 1.5) break; if (i1 < i2) oog_table[i] = oog_table[(i+i1)%NANGLES]; else oog_table[i] = oog_table[(i+NANGLES-i2)%NANGLES]; } initialized = 1; } i = (int) uv2ang(u, v); /* look up hue angle */ return (oog_table[i]);}#undef uv2ang#undef NANGLES#if !LOGLUV_PUBLICstatic#endifintuv_encode(double u, double v, int em) /* encode (u',v') coordinates */{ register int vi, ui; if (v < UV_VSTART) return oog_encode(u, v); vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em); if (vi >= UV_NVS) return oog_encode(u, v); if (u < uv_row[vi].ustart) return oog_encode(u, v); ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em); if (ui >= uv_row[vi].nus) return oog_encode(u, v); return (uv_row[vi].ncum + ui);}#if !LOGLUV_PUBLICstatic#endifintuv_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; while (upper - lower > 1) { vi = (lower + upper) >> 1; ui = c - uv_row[vi].ncum; if (ui > 0) lower = vi; else if (ui < 0) upper = vi; else { lower = vi; break; } } 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);}#if !LOGLUV_PUBLICstatic#endifvoidLogLuv24toXYZ(uint32 p, float XYZ[3]){ int Ce; double L, u, v, s, x, y; /* decode luminance */ L = LogL10toY(p>>14 & 0x3ff); if (L <= 0.) { XYZ[0] = XYZ[1] = XYZ[2] = 0.; return; } /* 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);}#if !LOGLUV_PUBLICstatic#endifuint32LogLuv24fromXYZ(float XYZ[3], int em){ int Le, Ce; double u, v, s; /* encode luminance */ Le = LogL10fromY(XYZ[1], em); /* encode color */ s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; if (!Le || s <= 0.) { u = U_NEU; v = V_NEU; } else { u = 4.*XYZ[0] / s; v = 9.*XYZ[1] / s; } Ce = uv_encode(u, v, em); if (Ce < 0) /* never happens */ Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); /* 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) { LogLuv24toXYZ(*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]; LogLuv24toXYZ(*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++ = LogLuv24fromXYZ(xyz, sp->encode_meth); 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 if (sp->encode_meth == SGILOGENCODE_NODITHER) Le = (luv3[0]-3314) >> 2; else Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth); Ce = uv_encode((luv[1]+.5)/(1<<15), (luv[2]+.5)/(1<<15), sp->encode_meth); if (Ce < 0) /* never happens */ Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER); *luv++ = (uint32)Le << 14 | Ce; luv3 += 3; }}#if !LOGLUV_PUBLICstatic#endifvoidLogLuv32toXYZ(uint32 p, float XYZ[3]){ double L, u, v, s, x, y; /* decode luminance */ L = LogL16toY((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);}#if !LOGLUV_PUBLICstatic#endifuint32LogLuv32fromXYZ(float XYZ[3], int em){ unsigned int Le, ue, ve; double u, v, s; /* encode luminance */ Le = (unsigned int)LogL16fromY(XYZ[1], em); /* encode color */ s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; if (!Le || 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 = itrunc(UVSCALE*u, em); if (ue > 255) ue = 255; if (v <= 0.) ve = 0; else ve = itrunc(UVSCALE*v, em); if (ve > 255) ve = 255; /* combine encodings */ return (Le << 16 | ue << 8 | ve);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -