| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683 |
- // Copyright (C) 2004-2021 Artifex Software, Inc.
- //
- // This file is part of MuPDF.
- //
- // MuPDF is free software: you can redistribute it and/or modify it under the
- // terms of the GNU Affero General Public License as published by the Free
- // Software Foundation, either version 3 of the License, or (at your option)
- // any later version.
- //
- // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
- // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- // details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
- //
- // Alternative licensing terms are available from the licensor.
- // For commercial licensing, see <https://www.artifex.com/> or contact
- // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
- // CA 94129, USA, for further information.
- #include "mupdf/fitz.h"
- #include <math.h>
- #include <string.h>
- /* Table stolen from LibTiff */
- #define UV_SQSIZ 0.003500f
- #define UV_NDIVS 16289
- #define UV_VSTART 0.016940f
- #define UV_NVS 163
- #define U_NEU 0.210526316f
- #define V_NEU 0.473684211f
- #define UVSCALE 410
- static struct {
- float ustart;
- short nus, ncum;
- } uv_row[UV_NVS] = {
- { 0.247663f, 4, 0 },
- { 0.243779f, 6, 4 },
- { 0.241684f, 7, 10 },
- { 0.237874f, 9, 17 },
- { 0.235906f, 10, 26 },
- { 0.232153f, 12, 36 },
- { 0.228352f, 14, 48 },
- { 0.226259f, 15, 62 },
- { 0.222371f, 17, 77 },
- { 0.220410f, 18, 94 },
- { 0.214710f, 21, 112 },
- { 0.212714f, 22, 133 },
- { 0.210721f, 23, 155 },
- { 0.204976f, 26, 178 },
- { 0.202986f, 27, 204 },
- { 0.199245f, 29, 231 },
- { 0.195525f, 31, 260 },
- { 0.193560f, 32, 291 },
- { 0.189878f, 34, 323 },
- { 0.186216f, 36, 357 },
- { 0.186216f, 36, 393 },
- { 0.182592f, 38, 429 },
- { 0.179003f, 40, 467 },
- { 0.175466f, 42, 507 },
- { 0.172001f, 44, 549 },
- { 0.172001f, 44, 593 },
- { 0.168612f, 46, 637 },
- { 0.168612f, 46, 683 },
- { 0.163575f, 49, 729 },
- { 0.158642f, 52, 778 },
- { 0.158642f, 52, 830 },
- { 0.158642f, 52, 882 },
- { 0.153815f, 55, 934 },
- { 0.153815f, 55, 989 },
- { 0.149097f, 58, 1044 },
- { 0.149097f, 58, 1102 },
- { 0.142746f, 62, 1160 },
- { 0.142746f, 62, 1222 },
- { 0.142746f, 62, 1284 },
- { 0.138270f, 65, 1346 },
- { 0.138270f, 65, 1411 },
- { 0.138270f, 65, 1476 },
- { 0.132166f, 69, 1541 },
- { 0.132166f, 69, 1610 },
- { 0.126204f, 73, 1679 },
- { 0.126204f, 73, 1752 },
- { 0.126204f, 73, 1825 },
- { 0.120381f, 77, 1898 },
- { 0.120381f, 77, 1975 },
- { 0.120381f, 77, 2052 },
- { 0.120381f, 77, 2129 },
- { 0.112962f, 82, 2206 },
- { 0.112962f, 82, 2288 },
- { 0.112962f, 82, 2370 },
- { 0.107450f, 86, 2452 },
- { 0.107450f, 86, 2538 },
- { 0.107450f, 86, 2624 },
- { 0.107450f, 86, 2710 },
- { 0.100343f, 91, 2796 },
- { 0.100343f, 91, 2887 },
- { 0.100343f, 91, 2978 },
- { 0.095126f, 95, 3069 },
- { 0.095126f, 95, 3164 },
- { 0.095126f, 95, 3259 },
- { 0.095126f, 95, 3354 },
- { 0.088276f, 100, 3449 },
- { 0.088276f, 100, 3549 },
- { 0.088276f, 100, 3649 },
- { 0.088276f, 100, 3749 },
- { 0.081523f, 105, 3849 },
- { 0.081523f, 105, 3954 },
- { 0.081523f, 105, 4059 },
- { 0.081523f, 105, 4164 },
- { 0.074861f, 110, 4269 },
- { 0.074861f, 110, 4379 },
- { 0.074861f, 110, 4489 },
- { 0.074861f, 110, 4599 },
- { 0.068290f, 115, 4709 },
- { 0.068290f, 115, 4824 },
- { 0.068290f, 115, 4939 },
- { 0.068290f, 115, 5054 },
- { 0.063573f, 119, 5169 },
- { 0.063573f, 119, 5288 },
- { 0.063573f, 119, 5407 },
- { 0.063573f, 119, 5526 },
- { 0.057219f, 124, 5645 },
- { 0.057219f, 124, 5769 },
- { 0.057219f, 124, 5893 },
- { 0.057219f, 124, 6017 },
- { 0.050985f, 129, 6141 },
- { 0.050985f, 129, 6270 },
- { 0.050985f, 129, 6399 },
- { 0.050985f, 129, 6528 },
- { 0.050985f, 129, 6657 },
- { 0.044859f, 134, 6786 },
- { 0.044859f, 134, 6920 },
- { 0.044859f, 134, 7054 },
- { 0.044859f, 134, 7188 },
- { 0.040571f, 138, 7322 },
- { 0.040571f, 138, 7460 },
- { 0.040571f, 138, 7598 },
- { 0.040571f, 138, 7736 },
- { 0.036339f, 142, 7874 },
- { 0.036339f, 142, 8016 },
- { 0.036339f, 142, 8158 },
- { 0.036339f, 142, 8300 },
- { 0.032139f, 146, 8442 },
- { 0.032139f, 146, 8588 },
- { 0.032139f, 146, 8734 },
- { 0.032139f, 146, 8880 },
- { 0.027947f, 150, 9026 },
- { 0.027947f, 150, 9176 },
- { 0.027947f, 150, 9326 },
- { 0.023739f, 154, 9476 },
- { 0.023739f, 154, 9630 },
- { 0.023739f, 154, 9784 },
- { 0.023739f, 154, 9938 },
- { 0.019504f, 158, 10092 },
- { 0.019504f, 158, 10250 },
- { 0.019504f, 158, 10408 },
- { 0.016976f, 161, 10566 },
- { 0.016976f, 161, 10727 },
- { 0.016976f, 161, 10888 },
- { 0.016976f, 161, 11049 },
- { 0.012639f, 165, 11210 },
- { 0.012639f, 165, 11375 },
- { 0.012639f, 165, 11540 },
- { 0.009991f, 168, 11705 },
- { 0.009991f, 168, 11873 },
- { 0.009991f, 168, 12041 },
- { 0.009016f, 170, 12209 },
- { 0.009016f, 170, 12379 },
- { 0.009016f, 170, 12549 },
- { 0.006217f, 173, 12719 },
- { 0.006217f, 173, 12892 },
- { 0.005097f, 175, 13065 },
- { 0.005097f, 175, 13240 },
- { 0.005097f, 175, 13415 },
- { 0.003909f, 177, 13590 },
- { 0.003909f, 177, 13767 },
- { 0.002340f, 177, 13944 },
- { 0.002389f, 170, 14121 },
- { 0.001068f, 164, 14291 },
- { 0.001653f, 157, 14455 },
- { 0.000717f, 150, 14612 },
- { 0.001614f, 143, 14762 },
- { 0.000270f, 136, 14905 },
- { 0.000484f, 129, 15041 },
- { 0.001103f, 123, 15170 },
- { 0.001242f, 115, 15293 },
- { 0.001188f, 109, 15408 },
- { 0.001011f, 103, 15517 },
- { 0.000709f, 97, 15620 },
- { 0.000301f, 89, 15717 },
- { 0.002416f, 82, 15806 },
- { 0.003251f, 76, 15888 },
- { 0.003246f, 69, 15964 },
- { 0.004141f, 62, 16033 },
- { 0.005963f, 55, 16095 },
- { 0.008839f, 47, 16150 },
- { 0.010490f, 40, 16197 },
- { 0.016994f, 31, 16237 },
- { 0.023659f, 21, 16268 },
- };
- /* SGI Log 16bit (greyscale) */
- typedef struct
- {
- fz_stream *chain;
- int run, n, c, w;
- uint16_t *temp;
- } fz_sgilog16;
- static inline int
- sgilog16val(fz_context *ctx, uint16_t v)
- {
- int Le;
- float Y;
- Le = v & 0x7fff;
- if (!Le)
- Y = 0;
- else
- {
- Y = expf(FZ_LN2/256 * (Le + .5f) - FZ_LN2*64);
- if (v & 0x8000)
- Y = -Y;
- }
- return ((Y <= 0) ? 0 : (Y >= 1) ? 255 : (int)(256*sqrtf(Y)));
- }
- static int
- next_sgilog16(fz_context *ctx, fz_stream *stm, size_t max)
- {
- fz_sgilog16 *state = stm->state;
- uint16_t *p;
- uint16_t *ep;
- uint8_t *q;
- int shift;
- (void)max;
- if (state->run < 0)
- return EOF;
- memset(state->temp, 0, state->w * sizeof(uint16_t));
- for (shift = 8; shift >= 0; shift -= 8)
- {
- p = state->temp;
- ep = p + state->w;
- while (p < ep)
- {
- if (state->n == 0)
- {
- state->run = fz_read_byte(ctx, state->chain);
- if (state->run < 0)
- {
- state->run = -1;
- fz_throw(ctx, FZ_ERROR_FORMAT, "premature end of data in run length decode");
- }
- if (state->run < 128)
- state->n = state->run;
- else
- {
- state->n = state->run - 126;
- state->c = fz_read_byte(ctx, state->chain);
- if (state->c < 0)
- {
- state->run = -1;
- fz_throw(ctx, FZ_ERROR_FORMAT, "premature end of data in run length decode");
- }
- }
- }
- if (state->run < 128)
- {
- while (p < ep && state->n)
- {
- int c = fz_read_byte(ctx, state->chain);
- if (c < 0)
- {
- state->run = -1;
- fz_throw(ctx, FZ_ERROR_FORMAT, "premature end of data in run length decode");
- }
- *p++ |= c<<shift;
- state->n--;
- }
- }
- else
- {
- while (p < ep && state->n)
- {
- *p++ |= state->c<<shift;
- state->n--;
- }
- }
- }
- }
- p = state->temp;
- q = (uint8_t *)p;
- ep = p + state->w;
- while (p < ep)
- {
- *q++ = sgilog16val(ctx, *p++);
- }
- stm->rp = (uint8_t *)(state->temp);
- stm->wp = q;
- stm->pos += q - stm->rp;
- if (q == stm->rp)
- return EOF;
- return *stm->rp++;
- }
- static void
- close_sgilog16(fz_context *ctx, void *state_)
- {
- fz_sgilog16 *state = (fz_sgilog16 *)state_;
- fz_stream *chain = state->chain;
- fz_free(ctx, state->temp);
- fz_free(ctx, state);
- fz_drop_stream(ctx, chain);
- }
- fz_stream *
- fz_open_sgilog16(fz_context *ctx, fz_stream *chain, int w)
- {
- fz_sgilog16 *state = fz_malloc_struct(ctx, fz_sgilog16);
- fz_try(ctx)
- {
- state->run = 0;
- state->n = 0;
- state->c = 0;
- state->w = w;
- state->temp = Memento_label(fz_malloc(ctx, w * sizeof(uint16_t)), "sgilog16_temp");
- state->chain = fz_keep_stream(ctx, chain);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, state->temp);
- fz_free(ctx, state);
- fz_rethrow(ctx);
- }
- return fz_new_stream(ctx, state, next_sgilog16, close_sgilog16);
- }
- /* SGI Log 24bit (LUV) */
- typedef struct
- {
- fz_stream *chain;
- int err, w;
- uint8_t *temp;
- } fz_sgilog24;
- static int
- uv_decode(float *up, float *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+.5f)*UV_SQSIZ;
- *vp = UV_VSTART + (vi+.5f)*UV_SQSIZ;
- return (0);
- }
- static inline int
- sgilog24val(fz_context *ctx, fz_stream *chain, uint8_t *rgb)
- {
- int b0, b1, b2;
- int luv, p;
- float u, v, s, x, y, X, Y, Z;
- float r, g, b;
- b0 = fz_read_byte(ctx, chain);
- if (b0 < 0)
- return b0;
- b1 = fz_read_byte(ctx, chain);
- if (b1 < 0)
- return b1;
- b2 = fz_read_byte(ctx, chain);
- if (b2 < 0)
- return b2;
- luv = (b0<<16) | (b1<<8) | b2;
- /* decode luminance */
- p = (luv>>14) & 0x3ff;
- Y = (p == 0 ? 0 : expf(FZ_LN2/64*(p+.5f) - FZ_LN2*12));
- if (Y <= 0)
- {
- X = Y = Z = 0;
- }
- else
- {
- /* decode color */
- if (uv_decode(&u, &v, luv & 0x3fff) < 0) {
- u = U_NEU; v = V_NEU;
- }
- s = 6*u - 16*v + 12;
- x = 9*u;
- y = 4*v;
- /* convert to XYZ */
- X = x/y * Y;
- Z = (s-x-y)/y * Y;
- }
- /* assume CCIR-709 primaries */
- r = 2.690f*X + -1.276f*Y + -0.414f*Z;
- g = -1.022f*X + 1.978f*Y + 0.044f*Z;
- b = 0.061f*X + -0.224f*Y + 1.163f*Z;
- /* assume 2.0 gamma for speed */
- /* could use integer sqrt approx., but this is probably faster */
- rgb[0] = (uint8_t)((r<=0) ? 0 : (r >= 1) ? 255 : (int)(256*sqrtf(r)));
- rgb[1] = (uint8_t)((g<=0) ? 0 : (g >= 1) ? 255 : (int)(256*sqrtf(g)));
- rgb[2] = (uint8_t)((b<=0) ? 0 : (b >= 1) ? 255 : (int)(256*sqrtf(b)));
- return 0;
- }
- static int
- next_sgilog24(fz_context *ctx, fz_stream *stm, size_t max)
- {
- fz_sgilog24 *state = stm->state;
- uint8_t *p;
- uint8_t *ep;
- (void)max;
- if (state->err)
- return EOF;
- memset(state->temp, 0, state->w * 3);
- p = state->temp;
- ep = p + state->w * 3;
- while (p < ep)
- {
- int c = sgilog24val(ctx, state->chain, p);
- if (c < 0)
- {
- state->err = 1;
- fz_throw(ctx, FZ_ERROR_FORMAT, "premature end of data in run length decode");
- }
- p += 3;
- }
- stm->rp = state->temp;
- stm->wp = p;
- stm->pos += p - stm->rp;
- if (p == stm->rp)
- return EOF;
- return *stm->rp++;
- }
- static void
- close_sgilog24(fz_context *ctx, void *state_)
- {
- fz_sgilog24 *state = (fz_sgilog24 *)state_;
- fz_stream *chain = state->chain;
- fz_free(ctx, state->temp);
- fz_free(ctx, state);
- fz_drop_stream(ctx, chain);
- }
- fz_stream *
- fz_open_sgilog24(fz_context *ctx, fz_stream *chain, int w)
- {
- fz_sgilog24 *state = fz_malloc_struct(ctx, fz_sgilog24);
- fz_try(ctx)
- {
- state->err = 0;
- state->w = w;
- state->temp = Memento_label(fz_malloc(ctx, w * 3), "sgilog24_temp");
- state->chain = fz_keep_stream(ctx, chain);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, state->temp);
- fz_free(ctx, state);
- fz_rethrow(ctx);
- }
- return fz_new_stream(ctx, state, next_sgilog24, close_sgilog24);
- }
- /* SGI Log 32bit */
- typedef struct
- {
- fz_stream *chain;
- int run, n, c, w;
- uint32_t *temp;
- } fz_sgilog32;
- static inline void
- sgilog32val(fz_context *ctx, uint32_t p, uint8_t *rgb)
- {
- float r, g, b;
- float u, v, s, x, y;
- float X, Y, Z;
- if (p>>31)
- {
- X = Y = Z = 0;
- }
- else
- {
- int Le = (p>>16) & 0x7fff;
- Y = !Le ? 0 : expf(FZ_LN2/256*(Le+.5f) - FZ_LN2*64);
- /* decode color */
- u = (1.f/UVSCALE) * ((p>>8 & 0xff) + .5f);
- v = (1.f/UVSCALE) * ((p & 0xff) + .5f);
- s = 6*u - 16*v + 12;
- x = 9 * u;
- y = 4 * v;
- /* convert to XYZ */
- X = x/y * Y;
- Z = (s-x-y)/y * Y;
- }
- /* assume CCIR-709 primaries */
- r = 2.690f*X + -1.276f*Y + -0.414f*Z;
- g = -1.022f*X + 1.978f*Y + 0.044f*Z;
- b = 0.061f*X + -0.224f*Y + 1.163f*Z;
- /* assume 2.0 gamma for speed */
- /* could use integer sqrt approx., but this is probably faster */
- rgb[0] = (uint8_t)((r<=0) ? 0 : (r >= 1) ? 255 : (int)(256*sqrtf(r)));
- rgb[1] = (uint8_t)((g<=0) ? 0 : (g >= 1) ? 255 : (int)(256*sqrtf(g)));
- rgb[2] = (uint8_t)((b<=0) ? 0 : (b >= 1) ? 255 : (int)(256*sqrtf(b)));
- }
- static int
- next_sgilog32(fz_context *ctx, fz_stream *stm, size_t max)
- {
- fz_sgilog32 *state = stm->state;
- uint32_t *p;
- uint32_t *ep;
- uint8_t *q;
- int shift;
- (void)max;
- if (state->run < 0)
- return EOF;
- memset(state->temp, 0, state->w * sizeof(uint32_t));
- for (shift = 24; shift >= 0; shift -= 8)
- {
- p = state->temp;
- ep = p + state->w;
- while (p < ep)
- {
- if (state->n == 0)
- {
- state->run = fz_read_byte(ctx, state->chain);
- if (state->run < 0)
- {
- state->run = -1;
- fz_throw(ctx, FZ_ERROR_FORMAT, "premature end of data in run length decode");
- }
- if (state->run < 128)
- state->n = state->run;
- else
- {
- state->n = state->run - 126;
- state->c = fz_read_byte(ctx, state->chain);
- if (state->c < 0)
- {
- state->run = -1;
- fz_throw(ctx, FZ_ERROR_FORMAT, "premature end of data in run length decode");
- }
- }
- }
- if (state->run < 128)
- {
- while (p < ep && state->n)
- {
- int c = fz_read_byte(ctx, state->chain);
- if (c < 0)
- {
- state->run = -1;
- fz_throw(ctx, FZ_ERROR_FORMAT, "premature end of data in run length decode");
- }
- *p++ |= c<<shift;
- state->n--;
- }
- }
- else
- {
- while (p < ep && state->n)
- {
- *p++ |= state->c<<shift;
- state->n--;
- }
- }
- }
- }
- p = state->temp;
- q = (uint8_t *)p;
- ep = p + state->w;
- while (p < ep)
- {
- sgilog32val(ctx, *p++, q);
- q += 3;
- }
- stm->rp = (uint8_t *)(state->temp);
- stm->wp = q;
- stm->pos += q - stm->rp;
- if (q == stm->rp)
- return EOF;
- return *stm->rp++;
- }
- static void
- close_sgilog32(fz_context *ctx, void *state_)
- {
- fz_sgilog32 *state = (fz_sgilog32 *)state_;
- fz_drop_stream(ctx, state->chain);
- fz_free(ctx, state->temp);
- fz_free(ctx, state);
- }
- fz_stream *
- fz_open_sgilog32(fz_context *ctx, fz_stream *chain, int w)
- {
- fz_sgilog32 *state = fz_malloc_struct(ctx, fz_sgilog32);
- fz_try(ctx)
- {
- state->run = 0;
- state->n = 0;
- state->c = 0;
- state->w = w;
- state->temp = Memento_label(fz_malloc(ctx, w * sizeof(uint32_t)), "sgilog32_temp");
- state->chain = fz_keep_stream(ctx, chain);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, state->temp);
- fz_free(ctx, state);
- fz_rethrow(ctx);
- }
- return fz_new_stream(ctx, state, next_sgilog32, close_sgilog32);
- }
|