File indexing completed on 2025-01-05 03:57:08
0001 /* -*- C++ -*- 0002 * Copyright 2019-2021 LibRaw LLC (info@libraw.org) 0003 * 0004 0005 LibRaw is free software; you can redistribute it and/or modify 0006 it under the terms of the one of two licenses as you choose: 0007 0008 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 0009 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 0010 0011 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 0012 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). 0013 0014 */ 0015 0016 #include "../../internal/libraw_cxx_defs.h" 0017 0018 void LibRaw::kodak_thumb_loader() 0019 { 0020 INT64 est_datasize = 0021 T.theight * T.twidth / 3; // is 0.3 bytes per pixel good estimate? 0022 if (ID.toffset < 0) 0023 throw LIBRAW_EXCEPTION_IO_CORRUPT; 0024 0025 if (ID.toffset + est_datasize > ID.input->size() + THUMB_READ_BEYOND) 0026 throw LIBRAW_EXCEPTION_IO_EOF; 0027 0028 if(INT64(T.theight) * INT64(T.twidth) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB) 0029 throw LIBRAW_EXCEPTION_IO_CORRUPT; 0030 0031 if (INT64(T.theight) * INT64(T.twidth) < 64ULL) 0032 throw LIBRAW_EXCEPTION_IO_CORRUPT; 0033 0034 if(T.twidth < 16 || T.twidth > 8192 || T.theight < 16 || T.theight > 8192) 0035 throw LIBRAW_EXCEPTION_IO_CORRUPT; 0036 0037 // some kodak cameras 0038 ushort s_height = S.height, s_width = S.width, s_iwidth = S.iwidth, 0039 s_iheight = S.iheight; 0040 ushort s_flags = libraw_internal_data.unpacker_data.load_flags; 0041 libraw_internal_data.unpacker_data.load_flags = 12; 0042 int s_colors = P1.colors; 0043 unsigned s_filters = P1.filters; 0044 ushort(*s_image)[4] = imgdata.image; 0045 0046 S.height = T.theight; 0047 S.width = T.twidth; 0048 P1.filters = 0; 0049 0050 #define Tformat libraw_internal_data.unpacker_data.thumb_format 0051 0052 0053 if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_YCBCR) 0054 { 0055 S.height += S.height & 1; 0056 S.width += S.width & 1; 0057 } 0058 0059 S.iheight = S.height; 0060 S.iwidth = S.width; 0061 0062 imgdata.image = 0063 (ushort(*)[4])calloc(S.iheight * S.iwidth, sizeof(*imgdata.image)); 0064 0065 ID.input->seek(ID.toffset, SEEK_SET); 0066 // read kodak thumbnail into T.image[] 0067 try 0068 { 0069 if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_YCBCR) 0070 kodak_ycbcr_load_raw(); 0071 else if(Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_RGB) 0072 kodak_rgb_load_raw(); 0073 else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_THUMB) 0074 kodak_thumb_load_raw(); 0075 } 0076 catch (...) 0077 { 0078 free(imgdata.image); 0079 imgdata.image = s_image; 0080 0081 T.twidth = 0; 0082 S.width = s_width; 0083 0084 S.iwidth = s_iwidth; 0085 S.iheight = s_iheight; 0086 0087 T.theight = 0; 0088 S.height = s_height; 0089 0090 T.tcolors = 0; 0091 P1.colors = s_colors; 0092 0093 P1.filters = s_filters; 0094 T.tlength = 0; 0095 libraw_internal_data.unpacker_data.load_flags = s_flags; 0096 return; 0097 } 0098 0099 // from scale_colors 0100 { 0101 double dmax; 0102 float scale_mul[4]; 0103 int c, val; 0104 for (dmax = DBL_MAX, c = 0; c < 3; c++) 0105 if (dmax > C.pre_mul[c]) 0106 dmax = C.pre_mul[c]; 0107 0108 for (c = 0; c < 3; c++) 0109 scale_mul[c] = (C.pre_mul[c] / dmax) * 65535.0 / C.maximum; 0110 scale_mul[3] = scale_mul[1]; 0111 0112 size_t size = S.height * S.width; 0113 for (unsigned i = 0; i < size * 4; i++) 0114 { 0115 val = imgdata.image[0][i]; 0116 if (!val) 0117 continue; 0118 val *= scale_mul[i & 3]; 0119 imgdata.image[0][i] = CLIP(val); 0120 } 0121 } 0122 0123 // from convert_to_rgb 0124 ushort *img; 0125 int row, col; 0126 0127 int(*t_hist)[LIBRAW_HISTOGRAM_SIZE] = 0128 (int(*)[LIBRAW_HISTOGRAM_SIZE])calloc(sizeof(*t_hist), 4); 0129 0130 if (imgdata.idata.maker_index == LIBRAW_CAMERAMAKER_Canon) // Skip color conversion for canon PPM tiffs 0131 { 0132 for (img = imgdata.image[0], row = 0; row < S.height; row++) 0133 for (col = 0; col < S.width; col++, img += 4) 0134 for (int c = 0; c < P1.colors; c++) 0135 t_hist[c][img[c] >> 3]++; 0136 } 0137 else 0138 { 0139 float out[3], out_cam[3][4] = {{2.81761312f, -1.98369181f, 0.166078627f, 0}, 0140 {-0.111855984f, 1.73688626f, -0.625030339f, 0}, 0141 {-0.0379119813f, -0.891268849f, 1.92918086f, 0}}; 0142 0143 for (img = imgdata.image[0], row = 0; row < S.height; row++) 0144 for (col = 0; col < S.width; col++, img += 4) 0145 { 0146 out[0] = out[1] = out[2] = 0; 0147 int c; 0148 for (c = 0; c < 3; c++) 0149 { 0150 out[0] += out_cam[0][c] * img[c]; 0151 out[1] += out_cam[1][c] * img[c]; 0152 out[2] += out_cam[2][c] * img[c]; 0153 } 0154 for (c = 0; c < 3; c++) 0155 img[c] = CLIP((int)out[c]); 0156 for (c = 0; c < P1.colors; c++) 0157 t_hist[c][img[c] >> 3]++; 0158 } 0159 } 0160 0161 // from gamma_lut 0162 int(*save_hist)[LIBRAW_HISTOGRAM_SIZE] = 0163 libraw_internal_data.output_data.histogram; 0164 libraw_internal_data.output_data.histogram = t_hist; 0165 0166 // make curve output curve! 0167 ushort *t_curve = (ushort *)calloc(sizeof(C.curve), 1); 0168 memmove(t_curve, C.curve, sizeof(C.curve)); 0169 memset(C.curve, 0, sizeof(C.curve)); 0170 { 0171 int perc, val, total, t_white = 0x2000, c; 0172 0173 perc = S.width * S.height * 0.01; /* 99th percentile white level */ 0174 if (IO.fuji_width) 0175 perc /= 2; 0176 if (!((O.highlight & ~2) || O.no_auto_bright)) 0177 for (t_white = c = 0; c < P1.colors; c++) 0178 { 0179 for (val = 0x2000, total = 0; --val > 32;) 0180 if ((total += libraw_internal_data.output_data.histogram[c][val]) > 0181 perc) 0182 break; 0183 if (t_white < val) 0184 t_white = val; 0185 } 0186 gamma_curve(O.gamm[0], O.gamm[1], 2, (t_white << 3) / O.bright); 0187 } 0188 0189 libraw_internal_data.output_data.histogram = save_hist; 0190 free(t_hist); 0191 0192 // from write_ppm_tiff - copy pixels into bitmap 0193 0194 int s_flip = imgdata.sizes.flip; 0195 if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_NO_ROTATE_FOR_KODAK_THUMBNAILS) 0196 imgdata.sizes.flip = 0; 0197 0198 S.iheight = S.height; 0199 S.iwidth = S.width; 0200 if (S.flip & 4) 0201 SWAP(S.height, S.width); 0202 0203 if (T.thumb) 0204 free(T.thumb); 0205 T.thumb = (char *)calloc(S.width * S.height, P1.colors); 0206 T.tlength = S.width * S.height * P1.colors; 0207 0208 // from write_tiff_ppm 0209 { 0210 int soff = flip_index(0, 0); 0211 int cstep = flip_index(0, 1) - soff; 0212 int rstep = flip_index(1, 0) - flip_index(0, S.width); 0213 0214 for (int rr = 0; rr < S.height; rr++, soff += rstep) 0215 { 0216 char *ppm = T.thumb + rr * S.width * P1.colors; 0217 for (int cc = 0; cc < S.width; cc++, soff += cstep) 0218 for (int c = 0; c < P1.colors; c++) 0219 ppm[cc * P1.colors + c] = 0220 imgdata.color.curve[imgdata.image[soff][c]] >> 8; 0221 } 0222 } 0223 0224 memmove(C.curve, t_curve, sizeof(C.curve)); 0225 free(t_curve); 0226 0227 // restore variables 0228 free(imgdata.image); 0229 imgdata.image = s_image; 0230 0231 if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_NO_ROTATE_FOR_KODAK_THUMBNAILS) 0232 imgdata.sizes.flip = s_flip; 0233 0234 T.twidth = S.width; 0235 S.width = s_width; 0236 0237 S.iwidth = s_iwidth; 0238 S.iheight = s_iheight; 0239 0240 T.theight = S.height; 0241 S.height = s_height; 0242 0243 T.tcolors = P1.colors; 0244 P1.colors = s_colors; 0245 0246 P1.filters = s_filters; 0247 libraw_internal_data.unpacker_data.load_flags = s_flags; 0248 } 0249 0250 // ������� thumbnail �� �����, ������ thumb_format � ������������ � �������� 0251 0252 int LibRaw::thumbOK(INT64 maxsz) 0253 { 0254 if (!ID.input) 0255 return 0; 0256 if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 && 0257 load_raw == &LibRaw::broadcom_load_raw) // RPi 0258 #ifdef USE_6BY9RPI 0259 && !(imgdata.thumbnail.tlength > 0 && libraw_internal_data.unpacker_data.load_flags & 0x4000 && 0260 (load_raw == &LibRaw::rpi_load_raw8 || load_raw == &LibRaw::nokia_load_raw || 0261 load_raw == &LibRaw::rpi_load_raw12 || load_raw == &LibRaw::rpi_load_raw14)) 0262 #endif 0263 ) 0264 return 0; 0265 INT64 fsize = ID.input->size(); 0266 if (fsize > 0xffffffffU) 0267 return 0; // No thumb for raw > 4Gb-1 0268 int tsize = 0; 0269 int tcol = (T.tcolors > 0 && T.tcolors < 4) ? T.tcolors : 3; 0270 if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_JPEG) 0271 tsize = T.tlength; 0272 else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_PPM) 0273 tsize = tcol * T.twidth * T.theight; 0274 else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_PPM16) 0275 tsize = tcol * T.twidth * T.theight * 0276 ((imgdata.rawparams.options & LIBRAW_RAWOPTIONS_USE_PPM16_THUMBS) ? 2 : 1); 0277 #ifdef USE_X3FTOOLS 0278 else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_X3F) 0279 { 0280 tsize = x3f_thumb_size(); 0281 } 0282 #endif 0283 else // Kodak => no check 0284 tsize = 1; 0285 if (tsize < 0) 0286 return 0; 0287 if (maxsz > 0 && tsize > maxsz) 0288 return 0; 0289 return (tsize + ID.toffset <= fsize) ? 1 : 0; 0290 } 0291 0292 int LibRaw::dcraw_thumb_writer(const char *fname) 0293 { 0294 // CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD); 0295 0296 if (!fname) 0297 return ENOENT; 0298 0299 FILE *tfp = fopen(fname, "wb"); 0300 0301 if (!tfp) 0302 return errno; 0303 0304 if (!T.thumb) 0305 { 0306 fclose(tfp); 0307 return LIBRAW_OUT_OF_ORDER_CALL; 0308 } 0309 0310 try 0311 { 0312 switch (T.tformat) 0313 { 0314 case LIBRAW_THUMBNAIL_JPEG: 0315 jpeg_thumb_writer(tfp, T.thumb, T.tlength); 0316 break; 0317 case LIBRAW_THUMBNAIL_BITMAP: 0318 fprintf(tfp, "P%d\n%d %d\n255\n", T.tcolors == 1 ? 5 : 6, T.twidth, T.theight); 0319 fwrite(T.thumb, 1, T.tlength, tfp); 0320 break; 0321 default: 0322 fclose(tfp); 0323 return LIBRAW_UNSUPPORTED_THUMBNAIL; 0324 } 0325 fclose(tfp); 0326 return 0; 0327 } 0328 catch (const std::bad_alloc&) 0329 { 0330 fclose(tfp); 0331 EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC); 0332 } 0333 catch (const LibRaw_exceptions& err) 0334 { 0335 fclose(tfp); 0336 EXCEPTION_HANDLER(err); 0337 } 0338 }