Revert "Cleanup some numeric code."
[pdfium.git] / core / src / fxcodec / codec / fx_codec_jpx_opj.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <algorithm>
8 #include <limits>
9 #include <vector>
10
11 #include "../../../../third_party/lcms2-2.6/include/lcms2.h"
12 #include "../../../../third_party/libopenjpeg20/openjpeg.h"
13 #include "../../../include/fxcodec/fx_codec.h"
14 #include "../../../include/fxcrt/fx_safe_types.h"
15 #include "codec_int.h"
16
17 static void fx_error_callback(const char* msg, void* client_data) {
18   (void)client_data;
19 }
20 static void fx_warning_callback(const char* msg, void* client_data) {
21   (void)client_data;
22 }
23 static void fx_info_callback(const char* msg, void* client_data) {
24   (void)client_data;
25 }
26 OPJ_SIZE_T opj_read_from_memory(void* p_buffer,
27                                 OPJ_SIZE_T nb_bytes,
28                                 void* p_user_data) {
29   DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
30   if (!srcData || !srcData->src_data || srcData->src_size == 0) {
31     return -1;
32   }
33   // Reads at EOF return an error code.
34   if (srcData->offset >= srcData->src_size) {
35     return -1;
36   }
37   OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset;
38   OPJ_SIZE_T readlength = nb_bytes < bufferLength ? nb_bytes : bufferLength;
39   memcpy(p_buffer, &srcData->src_data[srcData->offset], readlength);
40   srcData->offset += readlength;
41   return readlength;
42 }
43 OPJ_SIZE_T opj_write_from_memory(void* p_buffer,
44                                  OPJ_SIZE_T nb_bytes,
45                                  void* p_user_data) {
46   DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
47   if (!srcData || !srcData->src_data || srcData->src_size == 0) {
48     return -1;
49   }
50   // Writes at EOF return an error code.
51   if (srcData->offset >= srcData->src_size) {
52     return -1;
53   }
54   OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset;
55   OPJ_SIZE_T writeLength = nb_bytes < bufferLength ? nb_bytes : bufferLength;
56   memcpy(&srcData->src_data[srcData->offset], p_buffer, writeLength);
57   srcData->offset += writeLength;
58   return writeLength;
59 }
60 OPJ_OFF_T opj_skip_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) {
61   DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
62   if (!srcData || !srcData->src_data || srcData->src_size == 0) {
63     return -1;
64   }
65   // Offsets are signed and may indicate a negative skip. Do not support this
66   // because of the strange return convention where either bytes skipped or
67   // -1 is returned. Following that convention, a successful relative seek of
68   // -1 bytes would be required to to give the same result as the error case.
69   if (nb_bytes < 0) {
70     return -1;
71   }
72   // FIXME: use std::make_unsigned<OPJ_OFF_T>::type once c++11 lib is OK'd.
73   uint64_t unsignedNbBytes = static_cast<uint64_t>(nb_bytes);
74   // Additionally, the offset may take us beyond the range of a size_t (e.g.
75   // 32-bit platforms). If so, just clamp at EOF.
76   if (unsignedNbBytes >
77       std::numeric_limits<OPJ_SIZE_T>::max() - srcData->offset) {
78     srcData->offset = srcData->src_size;
79   } else {
80     OPJ_SIZE_T checkedNbBytes = static_cast<OPJ_SIZE_T>(unsignedNbBytes);
81     // Otherwise, mimic fseek() semantics to always succeed, even past EOF,
82     // clamping at EOF.  We can get away with this since we don't actually
83     // provide negative relative skips from beyond EOF back to inside the
84     // data, which would be the only reason to need to know exactly how far
85     // beyond EOF we are.
86     srcData->offset =
87         std::min(srcData->offset + checkedNbBytes, srcData->src_size);
88   }
89   return nb_bytes;
90 }
91 OPJ_BOOL opj_seek_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) {
92   DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
93   if (!srcData || !srcData->src_data || srcData->src_size == 0) {
94     return OPJ_FALSE;
95   }
96   // Offsets are signed and may indicate a negative position, which would
97   // be before the start of the file. Do not support this.
98   if (nb_bytes < 0) {
99     return OPJ_FALSE;
100   }
101   // FIXME: use std::make_unsigned<OPJ_OFF_T>::type once c++11 lib is OK'd.
102   uint64_t unsignedNbBytes = static_cast<uint64_t>(nb_bytes);
103   // Additionally, the offset may take us beyond the range of a size_t (e.g.
104   // 32-bit platforms). If so, just clamp at EOF.
105   if (unsignedNbBytes > std::numeric_limits<OPJ_SIZE_T>::max()) {
106     srcData->offset = srcData->src_size;
107   } else {
108     OPJ_SIZE_T checkedNbBytes = static_cast<OPJ_SIZE_T>(nb_bytes);
109     // Otherwise, mimic fseek() semantics to always succeed, even past EOF,
110     // again clamping at EOF.
111     srcData->offset = std::min(checkedNbBytes, srcData->src_size);
112   }
113   return OPJ_TRUE;
114 }
115 opj_stream_t* fx_opj_stream_create_memory_stream(DecodeData* data,
116                                                  OPJ_SIZE_T p_size,
117                                                  OPJ_BOOL p_is_read_stream) {
118   opj_stream_t* l_stream = 00;
119   if (!data || !data->src_data || data->src_size <= 0) {
120     return NULL;
121   }
122   l_stream = opj_stream_create(p_size, p_is_read_stream);
123   if (!l_stream) {
124     return NULL;
125   }
126   opj_stream_set_user_data(l_stream, data, NULL);
127   opj_stream_set_user_data_length(l_stream, data->src_size);
128   opj_stream_set_read_function(l_stream, opj_read_from_memory);
129   opj_stream_set_write_function(l_stream, opj_write_from_memory);
130   opj_stream_set_skip_function(l_stream, opj_skip_from_memory);
131   opj_stream_set_seek_function(l_stream, opj_seek_from_memory);
132   return l_stream;
133 }
134 static void sycc_to_rgb(int offset,
135                         int upb,
136                         int y,
137                         int cb,
138                         int cr,
139                         int* out_r,
140                         int* out_g,
141                         int* out_b) {
142   int r, g, b;
143   cb -= offset;
144   cr -= offset;
145   r = y + (int)(1.402 * (float)cr);
146   if (r < 0) {
147     r = 0;
148   } else if (r > upb) {
149     r = upb;
150   }
151   *out_r = r;
152   g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
153   if (g < 0) {
154     g = 0;
155   } else if (g > upb) {
156     g = upb;
157   }
158   *out_g = g;
159   b = y + (int)(1.772 * (float)cb);
160   if (b < 0) {
161     b = 0;
162   } else if (b > upb) {
163     b = upb;
164   }
165   *out_b = b;
166 }
167 static void sycc444_to_rgb(opj_image_t* img) {
168   int *d0, *d1, *d2, *r, *g, *b;
169   const int *y, *cb, *cr;
170   int maxw, maxh, max, i, offset, upb;
171   i = (int)img->comps[0].prec;
172   offset = 1 << (i - 1);
173   upb = (1 << i) - 1;
174   maxw = (int)img->comps[0].w;
175   maxh = (int)img->comps[0].h;
176   max = maxw * maxh;
177   y = img->comps[0].data;
178   cb = img->comps[1].data;
179   cr = img->comps[2].data;
180   d0 = r = FX_Alloc(int, (size_t)max);
181   d1 = g = FX_Alloc(int, (size_t)max);
182   d2 = b = FX_Alloc(int, (size_t)max);
183   for (i = 0; i < max; ++i) {
184     sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
185     ++y;
186     ++cb;
187     ++cr;
188     ++r;
189     ++g;
190     ++b;
191   }
192   FX_Free(img->comps[0].data);
193   img->comps[0].data = d0;
194   FX_Free(img->comps[1].data);
195   img->comps[1].data = d1;
196   FX_Free(img->comps[2].data);
197   img->comps[2].data = d2;
198 }
199 static void sycc422_to_rgb(opj_image_t* img) {
200   int *d0, *d1, *d2, *r, *g, *b;
201   const int *y, *cb, *cr;
202   int maxw, maxh, max, offset, upb;
203   int i, j;
204   i = (int)img->comps[0].prec;
205   offset = 1 << (i - 1);
206   upb = (1 << i) - 1;
207   maxw = (int)img->comps[0].w;
208   maxh = (int)img->comps[0].h;
209   max = maxw * maxh;
210   y = img->comps[0].data;
211   cb = img->comps[1].data;
212   cr = img->comps[2].data;
213   d0 = r = FX_Alloc(int, (size_t)max);
214   d1 = g = FX_Alloc(int, (size_t)max);
215   d2 = b = FX_Alloc(int, (size_t)max);
216   for (i = 0; i < maxh; ++i) {
217     for (j = 0; (OPJ_UINT32)j < (maxw & ~(OPJ_UINT32)1); j += 2) {
218       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
219       ++y;
220       ++r;
221       ++g;
222       ++b;
223       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
224       ++y;
225       ++r;
226       ++g;
227       ++b;
228       ++cb;
229       ++cr;
230     }
231     if (j < maxw) {
232       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
233       ++y;
234       ++r;
235       ++g;
236       ++b;
237       ++cb;
238       ++cr;
239     }
240   }
241   FX_Free(img->comps[0].data);
242   img->comps[0].data = d0;
243   FX_Free(img->comps[1].data);
244   img->comps[1].data = d1;
245   FX_Free(img->comps[2].data);
246   img->comps[2].data = d2;
247   img->comps[1].w = maxw;
248   img->comps[1].h = maxh;
249   img->comps[2].w = maxw;
250   img->comps[2].h = maxh;
251   img->comps[1].w = (OPJ_UINT32)maxw;
252   img->comps[1].h = (OPJ_UINT32)maxh;
253   img->comps[2].w = (OPJ_UINT32)maxw;
254   img->comps[2].h = (OPJ_UINT32)maxh;
255   img->comps[1].dx = img->comps[0].dx;
256   img->comps[2].dx = img->comps[0].dx;
257   img->comps[1].dy = img->comps[0].dy;
258   img->comps[2].dy = img->comps[0].dy;
259 }
260 static bool sycc420_size_is_valid(OPJ_UINT32 y, OPJ_UINT32 cbcr) {
261   if (!y || !cbcr)
262     return false;
263
264   return (cbcr == y / 2) || ((y & 1) && (cbcr == y / 2 + 1));
265 }
266 static bool sycc420_must_extend_cbcr(OPJ_UINT32 y, OPJ_UINT32 cbcr) {
267   return (y & 1) && (cbcr == y / 2);
268 }
269 void sycc420_to_rgb(opj_image_t* img) {
270   OPJ_UINT32 prec = img->comps[0].prec;
271   if (!prec)
272     return;
273   OPJ_UINT32 offset = 1 << (prec - 1);
274   OPJ_UINT32 upb = (1 << prec) - 1;
275   OPJ_UINT32 yw = img->comps[0].w;
276   OPJ_UINT32 yh = img->comps[0].h;
277   OPJ_UINT32 cbw = img->comps[1].w;
278   OPJ_UINT32 cbh = img->comps[1].h;
279   OPJ_UINT32 crw = img->comps[2].w;
280   OPJ_UINT32 crh = img->comps[2].h;
281   if (cbw != crw || cbh != crh)
282     return;
283   if (!sycc420_size_is_valid(yw, cbw) || !sycc420_size_is_valid(yh, cbh))
284     return;
285   bool extw = sycc420_must_extend_cbcr(yw, cbw);
286   bool exth = sycc420_must_extend_cbcr(yh, cbh);
287   FX_SAFE_DWORD safeSize = yw;
288   safeSize *= yh;
289   if (!safeSize.IsValid())
290     return;
291   int* r = FX_Alloc(int, safeSize.ValueOrDie());
292   int* g = FX_Alloc(int, safeSize.ValueOrDie());
293   int* b = FX_Alloc(int, safeSize.ValueOrDie());
294   int* d0 = r;
295   int* d1 = g;
296   int* d2 = b;
297   const int* y = img->comps[0].data;
298   const int* cb = img->comps[1].data;
299   const int* cr = img->comps[2].data;
300   const int* ny = nullptr;
301   int* nr = nullptr;
302   int* ng = nullptr;
303   int* nb = nullptr;
304   OPJ_UINT32 i = 0;
305   OPJ_UINT32 j = 0;
306   for (i = 0; i < (yh & ~(OPJ_UINT32)1); i += 2) {
307     ny = y + yw;
308     nr = r + yw;
309     ng = g + yw;
310     nb = b + yw;
311     for (j = 0; j < (yw & ~(OPJ_UINT32)1); j += 2) {
312       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
313       ++y;
314       ++r;
315       ++g;
316       ++b;
317       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
318       ++y;
319       ++r;
320       ++g;
321       ++b;
322       sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
323       ++ny;
324       ++nr;
325       ++ng;
326       ++nb;
327       sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
328       ++ny;
329       ++nr;
330       ++ng;
331       ++nb;
332       ++cb;
333       ++cr;
334     }
335     if (j < yw) {
336       if (extw) {
337         --cb;
338         --cr;
339       }
340       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
341       ++y;
342       ++r;
343       ++g;
344       ++b;
345       sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
346       ++ny;
347       ++nr;
348       ++ng;
349       ++nb;
350       ++cb;
351       ++cr;
352     }
353     y += yw;
354     r += yw;
355     g += yw;
356     b += yw;
357   }
358   if (i < yh) {
359     if (exth) {
360       cb -= cbw;
361       cr -= crw;
362     }
363     for (j = 0; j < (yw & ~(OPJ_UINT32)1); j += 2) {
364       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
365       ++y;
366       ++r;
367       ++g;
368       ++b;
369       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
370       ++y;
371       ++r;
372       ++g;
373       ++b;
374       ++cb;
375       ++cr;
376     }
377     if (j < yw) {
378       if (extw) {
379         --cb;
380         --cr;
381       }
382       sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
383     }
384   }
385
386   FX_Free(img->comps[0].data);
387   img->comps[0].data = d0;
388   FX_Free(img->comps[1].data);
389   img->comps[1].data = d1;
390   FX_Free(img->comps[2].data);
391   img->comps[2].data = d2;
392   img->comps[1].w = yw;
393   img->comps[1].h = yh;
394   img->comps[2].w = yw;
395   img->comps[2].h = yh;
396   img->comps[1].w = yw;
397   img->comps[1].h = yh;
398   img->comps[2].w = yw;
399   img->comps[2].h = yh;
400   img->comps[1].dx = img->comps[0].dx;
401   img->comps[2].dx = img->comps[0].dx;
402   img->comps[1].dy = img->comps[0].dy;
403   img->comps[2].dy = img->comps[0].dy;
404 }
405 void color_sycc_to_rgb(opj_image_t* img) {
406   if (img->numcomps < 3) {
407     img->color_space = OPJ_CLRSPC_GRAY;
408     return;
409   }
410   if ((img->comps[0].dx == 1) && (img->comps[1].dx == 2) &&
411       (img->comps[2].dx == 2) && (img->comps[0].dy == 1) &&
412       (img->comps[1].dy == 2) && (img->comps[2].dy == 2)) {
413     sycc420_to_rgb(img);
414   } else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 2) &&
415              (img->comps[2].dx == 2) && (img->comps[0].dy == 1) &&
416              (img->comps[1].dy == 1) && (img->comps[2].dy == 1)) {
417     sycc422_to_rgb(img);
418   } else if ((img->comps[0].dx == 1) && (img->comps[1].dx == 1) &&
419              (img->comps[2].dx == 1) && (img->comps[0].dy == 1) &&
420              (img->comps[1].dy == 1) && (img->comps[2].dy == 1)) {
421     sycc444_to_rgb(img);
422   } else {
423     return;
424   }
425   img->color_space = OPJ_CLRSPC_SRGB;
426 }
427 void color_apply_icc_profile(opj_image_t* image) {
428   cmsHPROFILE out_prof;
429   cmsUInt32Number in_type;
430   cmsUInt32Number out_type;
431   int* r;
432   int* g;
433   int* b;
434   int max;
435   cmsHPROFILE in_prof =
436       cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
437   if (in_prof == NULL) {
438     return;
439   }
440   cmsColorSpaceSignature out_space = cmsGetColorSpace(in_prof);
441   cmsUInt32Number intent = cmsGetHeaderRenderingIntent(in_prof);
442   int max_w = (int)image->comps[0].w;
443   int max_h = (int)image->comps[0].h;
444   int prec = (int)image->comps[0].prec;
445   OPJ_COLOR_SPACE oldspace = image->color_space;
446   if (out_space == cmsSigRgbData) {
447     if (prec <= 8) {
448       in_type = TYPE_RGB_8;
449       out_type = TYPE_RGB_8;
450     } else {
451       in_type = TYPE_RGB_16;
452       out_type = TYPE_RGB_16;
453     }
454     out_prof = cmsCreate_sRGBProfile();
455     image->color_space = OPJ_CLRSPC_SRGB;
456   } else if (out_space == cmsSigGrayData) {
457     if (prec <= 8) {
458       in_type = TYPE_GRAY_8;
459       out_type = TYPE_RGB_8;
460     } else {
461       in_type = TYPE_GRAY_16;
462       out_type = TYPE_RGB_16;
463     }
464     out_prof = cmsCreate_sRGBProfile();
465     image->color_space = OPJ_CLRSPC_SRGB;
466   } else if (out_space == cmsSigYCbCrData) {
467     in_type = TYPE_YCbCr_16;
468     out_type = TYPE_RGB_16;
469     out_prof = cmsCreate_sRGBProfile();
470     image->color_space = OPJ_CLRSPC_SRGB;
471   } else {
472     return;
473   }
474   cmsHTRANSFORM transform =
475       cmsCreateTransform(in_prof, in_type, out_prof, out_type, intent, 0);
476   cmsCloseProfile(in_prof);
477   cmsCloseProfile(out_prof);
478   if (transform == NULL) {
479     image->color_space = oldspace;
480     return;
481   }
482   if (image->numcomps > 2) {
483     if (prec <= 8) {
484       unsigned char *inbuf, *outbuf, *in, *out;
485       max = max_w * max_h;
486       cmsUInt32Number nr_samples = max * 3 * sizeof(unsigned char);
487       in = inbuf = FX_Alloc(unsigned char, nr_samples);
488       out = outbuf = FX_Alloc(unsigned char, nr_samples);
489       r = image->comps[0].data;
490       g = image->comps[1].data;
491       b = image->comps[2].data;
492       for (int i = 0; i < max; ++i) {
493         *in++ = (unsigned char)*r++;
494         *in++ = (unsigned char)*g++;
495         *in++ = (unsigned char)*b++;
496       }
497       cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
498       r = image->comps[0].data;
499       g = image->comps[1].data;
500       b = image->comps[2].data;
501       for (int i = 0; i < max; ++i) {
502         *r++ = (int)*out++;
503         *g++ = (int)*out++;
504         *b++ = (int)*out++;
505       }
506       FX_Free(inbuf);
507       FX_Free(outbuf);
508     } else {
509       unsigned short *inbuf, *outbuf, *in, *out;
510       max = max_w * max_h;
511       cmsUInt32Number nr_samples = max * 3 * sizeof(unsigned short);
512       in = inbuf = FX_Alloc(unsigned short, nr_samples);
513       out = outbuf = FX_Alloc(unsigned short, nr_samples);
514       r = image->comps[0].data;
515       g = image->comps[1].data;
516       b = image->comps[2].data;
517       for (int i = 0; i < max; ++i) {
518         *in++ = (unsigned short)*r++;
519         *in++ = (unsigned short)*g++;
520         *in++ = (unsigned short)*b++;
521       }
522       cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
523       r = image->comps[0].data;
524       g = image->comps[1].data;
525       b = image->comps[2].data;
526       for (int i = 0; i < max; ++i) {
527         *r++ = (int)*out++;
528         *g++ = (int)*out++;
529         *b++ = (int)*out++;
530       }
531       FX_Free(inbuf);
532       FX_Free(outbuf);
533     }
534   } else {
535     unsigned char *in, *inbuf, *out, *outbuf;
536     max = max_w * max_h;
537     cmsUInt32Number nr_samples =
538         (cmsUInt32Number)max * 3 * sizeof(unsigned char);
539     in = inbuf = FX_Alloc(unsigned char, nr_samples);
540     out = outbuf = FX_Alloc(unsigned char, nr_samples);
541     image->comps = (opj_image_comp_t*)realloc(
542         image->comps, (image->numcomps + 2) * sizeof(opj_image_comp_t));
543     if (image->numcomps == 2) {
544       image->comps[3] = image->comps[1];
545     }
546     image->comps[1] = image->comps[0];
547     image->comps[2] = image->comps[0];
548     image->comps[1].data = FX_Alloc(int, (size_t)max);
549     FXSYS_memset(image->comps[1].data, 0, sizeof(int) * (size_t)max);
550     image->comps[2].data = FX_Alloc(int, (size_t)max);
551     FXSYS_memset(image->comps[2].data, 0, sizeof(int) * (size_t)max);
552     image->numcomps += 2;
553     r = image->comps[0].data;
554     for (int i = 0; i < max; ++i) {
555       *in++ = (unsigned char)*r++;
556     }
557     cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
558     r = image->comps[0].data;
559     g = image->comps[1].data;
560     b = image->comps[2].data;
561     for (int i = 0; i < max; ++i) {
562       *r++ = (int)*out++;
563       *g++ = (int)*out++;
564       *b++ = (int)*out++;
565     }
566     FX_Free(inbuf);
567     FX_Free(outbuf);
568   }
569   cmsDeleteTransform(transform);
570 }
571 void color_apply_conversion(opj_image_t* image) {
572   int* row;
573   int enumcs, numcomps;
574   numcomps = image->numcomps;
575   if (numcomps < 3) {
576     return;
577   }
578   row = (int*)image->icc_profile_buf;
579   enumcs = row[0];
580   if (enumcs == 14) {
581     int *L, *a, *b, *red, *green, *blue, *src0, *src1, *src2;
582     double rl, ol, ra, oa, rb, ob, prec0, prec1, prec2;
583     double minL, maxL, mina, maxa, minb, maxb;
584     unsigned int default_type;
585     unsigned int i, max;
586     cmsHPROFILE in, out;
587     cmsHTRANSFORM transform;
588     cmsUInt16Number RGB[3];
589     cmsCIELab Lab;
590     in = cmsCreateLab4Profile(NULL);
591     out = cmsCreate_sRGBProfile();
592     transform = cmsCreateTransform(in, TYPE_Lab_DBL, out, TYPE_RGB_16,
593                                    INTENT_PERCEPTUAL, 0);
594     cmsCloseProfile(in);
595     cmsCloseProfile(out);
596     if (transform == NULL) {
597       return;
598     }
599     prec0 = (double)image->comps[0].prec;
600     prec1 = (double)image->comps[1].prec;
601     prec2 = (double)image->comps[2].prec;
602     default_type = row[1];
603     if (default_type == 0x44454600) {
604       rl = 100;
605       ra = 170;
606       rb = 200;
607       ol = 0;
608       oa = pow(2, prec1 - 1);
609       ob = pow(2, prec2 - 2) + pow(2, prec2 - 3);
610     } else {
611       rl = row[2];
612       ra = row[4];
613       rb = row[6];
614       ol = row[3];
615       oa = row[5];
616       ob = row[7];
617     }
618     L = src0 = image->comps[0].data;
619     a = src1 = image->comps[1].data;
620     b = src2 = image->comps[2].data;
621     max = image->comps[0].w * image->comps[0].h;
622     red = FX_Alloc(int, max);
623     image->comps[0].data = red;
624     green = FX_Alloc(int, max);
625     image->comps[1].data = green;
626     blue = FX_Alloc(int, max);
627     image->comps[2].data = blue;
628     minL = -(rl * ol) / (pow(2, prec0) - 1);
629     maxL = minL + rl;
630     mina = -(ra * oa) / (pow(2, prec1) - 1);
631     maxa = mina + ra;
632     minb = -(rb * ob) / (pow(2, prec2) - 1);
633     maxb = minb + rb;
634     for (i = 0; i < max; ++i) {
635       Lab.L = minL + (double)(*L) * (maxL - minL) / (pow(2, prec0) - 1);
636       ++L;
637       Lab.a = mina + (double)(*a) * (maxa - mina) / (pow(2, prec1) - 1);
638       ++a;
639       Lab.b = minb + (double)(*b) * (maxb - minb) / (pow(2, prec2) - 1);
640       ++b;
641       cmsDoTransform(transform, &Lab, RGB, 1);
642       *red++ = RGB[0];
643       *green++ = RGB[1];
644       *blue++ = RGB[2];
645     }
646     cmsDeleteTransform(transform);
647     FX_Free(src0);
648     FX_Free(src1);
649     FX_Free(src2);
650     image->color_space = OPJ_CLRSPC_SRGB;
651     image->comps[0].prec = 16;
652     image->comps[1].prec = 16;
653     image->comps[2].prec = 16;
654     return;
655   }
656 }
657 class CJPX_Decoder {
658  public:
659   explicit CJPX_Decoder(bool use_colorspace);
660   ~CJPX_Decoder();
661   FX_BOOL Init(const unsigned char* src_data, FX_DWORD src_size);
662   void GetInfo(FX_DWORD* width, FX_DWORD* height, FX_DWORD* components);
663   bool Decode(uint8_t* dest_buf,
664               int pitch,
665               const std::vector<uint8_t>& offsets);
666
667  private:
668   const uint8_t* m_SrcData;
669   FX_DWORD m_SrcSize;
670   opj_image_t* image;
671   opj_codec_t* l_codec;
672   opj_stream_t* l_stream;
673   const bool m_UseColorSpace;
674 };
675
676 CJPX_Decoder::CJPX_Decoder(bool use_colorspace)
677     : image(nullptr),
678       l_codec(nullptr),
679       l_stream(nullptr),
680       m_UseColorSpace(use_colorspace) {
681 }
682
683 CJPX_Decoder::~CJPX_Decoder() {
684   if (l_codec) {
685     opj_destroy_codec(l_codec);
686   }
687   if (l_stream) {
688     opj_stream_destroy(l_stream);
689   }
690   if (image) {
691     opj_image_destroy(image);
692   }
693 }
694
695 FX_BOOL CJPX_Decoder::Init(const unsigned char* src_data, FX_DWORD src_size) {
696   static const unsigned char szJP2Header[] = {
697       0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a};
698   if (!src_data || src_size < sizeof(szJP2Header))
699     return FALSE;
700
701   image = NULL;
702   m_SrcData = src_data;
703   m_SrcSize = src_size;
704   DecodeData srcData(const_cast<unsigned char*>(src_data), src_size);
705   l_stream = fx_opj_stream_create_memory_stream(&srcData,
706                                                 OPJ_J2K_STREAM_CHUNK_SIZE, 1);
707   if (l_stream == NULL) {
708     return FALSE;
709   }
710   opj_dparameters_t parameters;
711   opj_set_default_decoder_parameters(&parameters);
712   parameters.decod_format = 0;
713   parameters.cod_format = 3;
714   if (FXSYS_memcmp(m_SrcData, szJP2Header, sizeof(szJP2Header)) == 0) {
715     l_codec = opj_create_decompress(OPJ_CODEC_JP2);
716     parameters.decod_format = 1;
717   } else {
718     l_codec = opj_create_decompress(OPJ_CODEC_J2K);
719   }
720   if (!l_codec) {
721     return FALSE;
722   }
723   opj_set_info_handler(l_codec, fx_info_callback, 00);
724   opj_set_warning_handler(l_codec, fx_warning_callback, 00);
725   opj_set_error_handler(l_codec, fx_error_callback, 00);
726   if (!opj_setup_decoder(l_codec, &parameters)) {
727     return FALSE;
728   }
729   if (!opj_read_header(l_stream, l_codec, &image)) {
730     image = NULL;
731     return FALSE;
732   }
733   image->pdfium_use_colorspace = m_UseColorSpace;
734
735   if (!parameters.nb_tile_to_decode) {
736     if (!opj_set_decode_area(l_codec, image, parameters.DA_x0, parameters.DA_y0,
737                              parameters.DA_x1, parameters.DA_y1)) {
738       opj_image_destroy(image);
739       image = NULL;
740       return FALSE;
741     }
742     if (!(opj_decode(l_codec, l_stream, image) &&
743           opj_end_decompress(l_codec, l_stream))) {
744       opj_image_destroy(image);
745       image = NULL;
746       return FALSE;
747     }
748   } else {
749     if (!opj_get_decoded_tile(l_codec, l_stream, image,
750                               parameters.tile_index)) {
751       return FALSE;
752     }
753   }
754   opj_stream_destroy(l_stream);
755   l_stream = NULL;
756   if (image->color_space != OPJ_CLRSPC_SYCC && image->numcomps == 3 &&
757       image->comps[0].dx == image->comps[0].dy && image->comps[1].dx != 1) {
758     image->color_space = OPJ_CLRSPC_SYCC;
759   } else if (image->numcomps <= 2) {
760     image->color_space = OPJ_CLRSPC_GRAY;
761   }
762   if (image->color_space == OPJ_CLRSPC_SYCC) {
763     color_sycc_to_rgb(image);
764   }
765   if (image->icc_profile_buf) {
766     FX_Free(image->icc_profile_buf);
767     image->icc_profile_buf = NULL;
768     image->icc_profile_len = 0;
769   }
770   if (!image) {
771     return FALSE;
772   }
773   return TRUE;
774 }
775
776 void CJPX_Decoder::GetInfo(FX_DWORD* width,
777                            FX_DWORD* height,
778                            FX_DWORD* components) {
779   *width = (FX_DWORD)image->x1;
780   *height = (FX_DWORD)image->y1;
781   *components = (FX_DWORD)image->numcomps;
782 }
783
784 bool CJPX_Decoder::Decode(uint8_t* dest_buf,
785                           int pitch,
786                           const std::vector<uint8_t>& offsets) {
787   if (image->comps[0].w != image->x1 || image->comps[0].h != image->y1)
788     return false;
789
790   if (pitch<(int)(image->comps[0].w * 8 * image->numcomps + 31)>> 5 << 2)
791     return false;
792
793   FXSYS_memset(dest_buf, 0xff, image->y1 * pitch);
794   std::vector<uint8_t*> channel_bufs(image->numcomps);
795   std::vector<int> adjust_comps(image->numcomps);
796   for (uint32_t i = 0; i < image->numcomps; i++) {
797     channel_bufs[i] = dest_buf + offsets[i];
798     adjust_comps[i] = image->comps[i].prec - 8;
799     if (i > 0) {
800       if (image->comps[i].dx != image->comps[i - 1].dx ||
801           image->comps[i].dy != image->comps[i - 1].dy ||
802           image->comps[i].prec != image->comps[i - 1].prec) {
803         return false;
804       }
805     }
806   }
807   int width = image->comps[0].w;
808   int height = image->comps[0].h;
809   for (uint32_t channel = 0; channel < image->numcomps; ++channel) {
810     uint8_t* pChannel = channel_bufs[channel];
811     if (adjust_comps[channel] < 0) {
812       for (int row = 0; row < height; ++row) {
813         uint8_t* pScanline = pChannel + row * pitch;
814         for (int col = 0; col < width; ++col) {
815           uint8_t* pPixel = pScanline + col * image->numcomps;
816           int src = image->comps[channel].data[row * width + col];
817           src += image->comps[channel].sgnd
818                      ? 1 << (image->comps[channel].prec - 1)
819                      : 0;
820           if (adjust_comps[channel] > 0) {
821             *pPixel = 0;
822           } else {
823             *pPixel = (uint8_t)(src << -adjust_comps[channel]);
824           }
825         }
826       }
827     } else {
828       for (int row = 0; row < height; ++row) {
829         uint8_t* pScanline = pChannel + row * pitch;
830         for (int col = 0; col < width; ++col) {
831           uint8_t* pPixel = pScanline + col * image->numcomps;
832           if (!image->comps[channel].data) {
833             continue;
834           }
835           int src = image->comps[channel].data[row * width + col];
836           src += image->comps[channel].sgnd
837                      ? 1 << (image->comps[channel].prec - 1)
838                      : 0;
839           if (adjust_comps[channel] - 1 < 0) {
840             *pPixel = (uint8_t)((src >> adjust_comps[channel]));
841           } else {
842             int tmpPixel = (src >> adjust_comps[channel]) +
843                            ((src >> (adjust_comps[channel] - 1)) % 2);
844             if (tmpPixel > 255) {
845               tmpPixel = 255;
846             } else if (tmpPixel < 0) {
847               tmpPixel = 0;
848             }
849             *pPixel = (uint8_t)tmpPixel;
850           }
851         }
852       }
853     }
854   }
855   return true;
856 }
857
858 CCodec_JpxModule::CCodec_JpxModule() {}
859 CCodec_JpxModule::~CCodec_JpxModule() {
860 }
861
862 CJPX_Decoder* CCodec_JpxModule::CreateDecoder(const uint8_t* src_buf,
863                                               FX_DWORD src_size,
864                                               bool use_colorspace) {
865   nonstd::unique_ptr<CJPX_Decoder> decoder(new CJPX_Decoder(use_colorspace));
866   return decoder->Init(src_buf, src_size) ? decoder.release() : nullptr;
867 }
868
869 void CCodec_JpxModule::GetImageInfo(CJPX_Decoder* pDecoder,
870                                     FX_DWORD* width,
871                                     FX_DWORD* height,
872                                     FX_DWORD* components) {
873   pDecoder->GetInfo(width, height, components);
874 }
875
876 bool CCodec_JpxModule::Decode(CJPX_Decoder* pDecoder,
877                               uint8_t* dest_data,
878                               int pitch,
879                               const std::vector<uint8_t>& offsets) {
880   return pDecoder->Decode(dest_data, pitch, offsets);
881 }
882
883 void CCodec_JpxModule::DestroyDecoder(CJPX_Decoder* pDecoder) {
884   delete pDecoder;
885 }