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 }