File indexing completed on 2025-01-05 03:57:06

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::raw2image_start()
0019 {
0020   // restore color,sizes and internal data into raw_image fields
0021   memmove(&imgdata.color, &imgdata.rawdata.color, sizeof(imgdata.color));
0022   memmove(&imgdata.sizes, &imgdata.rawdata.sizes, sizeof(imgdata.sizes));
0023   memmove(&imgdata.idata, &imgdata.rawdata.iparams, sizeof(imgdata.idata));
0024   memmove(&libraw_internal_data.internal_output_params,
0025           &imgdata.rawdata.ioparams,
0026           sizeof(libraw_internal_data.internal_output_params));
0027 
0028   if (O.user_flip >= 0)
0029     S.flip = O.user_flip;
0030 
0031   switch ((S.flip + 3600) % 360)
0032   {
0033   case 270:
0034     S.flip = 5;
0035     break;
0036   case 180:
0037     S.flip = 3;
0038     break;
0039   case 90:
0040     S.flip = 6;
0041     break;
0042   }
0043 
0044   // adjust for half mode!
0045   IO.shrink =
0046       !imgdata.rawdata.color4_image && !imgdata.rawdata.color3_image &&
0047       !imgdata.rawdata.float4_image && !imgdata.rawdata.float3_image &&
0048       P1.filters &&
0049       (O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1)));
0050 
0051   S.iheight = (S.height + IO.shrink) >> IO.shrink;
0052   S.iwidth = (S.width + IO.shrink) >> IO.shrink;
0053 }
0054 
0055 int LibRaw::raw2image(void)
0056 {
0057 
0058   CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
0059 
0060   try
0061   {
0062     raw2image_start();
0063 
0064     if (is_phaseone_compressed() && imgdata.rawdata.raw_alloc)
0065     {
0066       phase_one_allocate_tempbuffer();
0067       int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc,
0068                                         imgdata.rawdata.raw_image);
0069       if (rc == 0)
0070         rc = phase_one_correct();
0071       if (rc != 0)
0072       {
0073         phase_one_free_tempbuffer();
0074         return rc;
0075       }
0076     }
0077 
0078     // free and re-allocate image bitmap
0079     if (imgdata.image)
0080     {
0081       imgdata.image = (ushort(*)[4])realloc(
0082           imgdata.image, S.iheight * S.iwidth * sizeof(*imgdata.image));
0083       memset(imgdata.image, 0, S.iheight * S.iwidth * sizeof(*imgdata.image));
0084     }
0085     else
0086       imgdata.image =
0087           (ushort(*)[4])calloc(S.iheight * S.iwidth, sizeof(*imgdata.image));
0088 
0089 
0090     libraw_decoder_info_t decoder_info;
0091     get_decoder_info(&decoder_info);
0092 
0093     // Copy area size
0094     int copyheight = MAX(0, MIN(int(S.height), int(S.raw_height) - int(S.top_margin)));
0095     int copywidth = MAX(0, MIN(int(S.width), int(S.raw_width) - int(S.left_margin)));
0096 
0097     // Move saved bitmap to imgdata.image
0098     if ((imgdata.idata.filters || P1.colors == 1) && imgdata.rawdata.raw_image)
0099     {
0100       if (IO.fuji_width)
0101       {
0102         unsigned r, c;
0103         int row, col;
0104         for (row = 0; row < S.raw_height - S.top_margin * 2; row++)
0105         {
0106           for (col = 0;
0107                col < IO.fuji_width
0108                          << int(!libraw_internal_data.unpacker_data.fuji_layout);
0109                col++)
0110           {
0111             if (libraw_internal_data.unpacker_data.fuji_layout)
0112             {
0113               r = IO.fuji_width - 1 - col + (row >> 1);
0114               c = col + ((row + 1) >> 1);
0115             }
0116             else
0117             {
0118               r = IO.fuji_width - 1 + row - (col >> 1);
0119               c = row + ((col + 1) >> 1);
0120             }
0121             if (r < S.height && c < S.width && col + int(S.left_margin) < int(S.raw_width))
0122               imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)]
0123                            [FC(r, c)] =
0124                   imgdata.rawdata
0125                       .raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
0126                                  (col + S.left_margin)];
0127           }
0128         }
0129       }
0130       else
0131       {
0132         int row, col;
0133         for (row = 0; row < copyheight; row++)
0134           for (col = 0; col < copywidth; col++)
0135             imgdata.image[((row) >> IO.shrink) * S.iwidth +
0136                           ((col) >> IO.shrink)][fcol(row, col)] =
0137                 imgdata.rawdata
0138                     .raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
0139                                (col + S.left_margin)];
0140       }
0141     }
0142     else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY)
0143     {
0144       if (imgdata.rawdata.color4_image)
0145       {
0146         if (S.width * 8u == S.raw_pitch && S.height == S.raw_height)
0147           memmove(imgdata.image, imgdata.rawdata.color4_image,
0148                   S.width * S.height * sizeof(*imgdata.image));
0149         else
0150         {
0151             for (int row = 0; row < copyheight; row++)
0152             memmove(&imgdata.image[row * S.width],
0153                     &imgdata.rawdata
0154                          .color4_image[(row + S.top_margin) * S.raw_pitch / 8 +
0155                                        S.left_margin],
0156                     copywidth * sizeof(*imgdata.image));
0157         }
0158       }
0159       else if (imgdata.rawdata.color3_image)
0160       {
0161         unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image;
0162         for (int row = 0; row < copyheight; row++)
0163         {
0164           ushort(*srcrow)[3] =
0165               (ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch];
0166           ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width];
0167           for (int col = 0; col < copywidth; col++)
0168           {
0169             for (int c = 0; c < 3; c++)
0170               dstrow[col][c] = srcrow[S.left_margin + col][c];
0171             dstrow[col][3] = 0;
0172           }
0173         }
0174       }
0175       else
0176       {
0177         // legacy decoder, but no data?
0178         throw LIBRAW_EXCEPTION_DECODE_RAW;
0179       }
0180     }
0181 
0182     // Free PhaseOne separate copy allocated at function start
0183     if (is_phaseone_compressed())
0184     {
0185       phase_one_free_tempbuffer();
0186     }
0187     // hack - clear later flags!
0188 
0189     if (load_raw == &LibRaw::canon_600_load_raw && S.width < S.raw_width)
0190     {
0191       canon_600_correct();
0192     }
0193 
0194     imgdata.progress_flags =
0195         LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN |
0196         LIBRAW_PROGRESS_RAW2_IMAGE | LIBRAW_PROGRESS_IDENTIFY |
0197         LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW;
0198     return 0;
0199   }
0200   catch (const std::bad_alloc&)
0201   {
0202       EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC);
0203   }
0204   catch (const LibRaw_exceptions& err)
0205   {
0206     EXCEPTION_HANDLER(err);
0207   }
0208 }
0209 
0210 void LibRaw::copy_fuji_uncropped(unsigned short cblack[4],
0211                                  unsigned short *dmaxp)
0212 {
0213 #if defined(LIBRAW_USE_OPENMP)
0214 #pragma omp parallel for schedule(dynamic) default(none) firstprivate(cblack) shared(dmaxp)
0215 #endif
0216   for (int row = 0; row < int(S.raw_height) - int(S.top_margin) * 2; row++)
0217   {
0218     int col;
0219     unsigned short ldmax = 0;
0220     for (col = 0;
0221          col < IO.fuji_width << int(!libraw_internal_data.unpacker_data.fuji_layout)
0222          && col + int(S.left_margin) < int(S.raw_width);
0223          col++)
0224     {
0225       unsigned r, c;
0226       if (libraw_internal_data.unpacker_data.fuji_layout)
0227       {
0228         r = IO.fuji_width - 1 - col + (row >> 1);
0229         c = col + ((row + 1) >> 1);
0230       }
0231       else
0232       {
0233         r = IO.fuji_width - 1 + row - (col >> 1);
0234         c = row + ((col + 1) >> 1);
0235       }
0236       if (r < S.height && c < S.width)
0237       {
0238         unsigned short val =
0239             imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
0240                                       (col + S.left_margin)];
0241         int cc = FC(r, c);
0242         if (val > cblack[cc])
0243         {
0244           val -= cblack[cc];
0245           if (val > ldmax)
0246             ldmax = val;
0247         }
0248         else
0249           val = 0;
0250         imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)][cc] =
0251             val;
0252       }
0253     }
0254 #if defined(LIBRAW_USE_OPENMP)
0255 #pragma omp critical(dataupdate)
0256 #endif
0257     {
0258       if (*dmaxp < ldmax)
0259         *dmaxp = ldmax;
0260     }
0261   }
0262 }
0263 
0264 void LibRaw::copy_bayer(unsigned short cblack[4], unsigned short *dmaxp)
0265 {
0266   // Both cropped and uncropped
0267   int maxHeight = MIN(int(S.height),int(S.raw_height)-int(S.top_margin));
0268 #if defined(LIBRAW_USE_OPENMP)
0269 #pragma omp parallel for schedule(dynamic) default(none) shared(dmaxp) firstprivate(cblack, maxHeight)
0270 #endif
0271   for (int row = 0; row < maxHeight ; row++)
0272   {
0273     int col;
0274     unsigned short ldmax = 0;
0275     for (col = 0; col < S.width && col + S.left_margin < S.raw_width; col++)
0276     {
0277       unsigned short val =
0278           imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
0279                                     (col + S.left_margin)];
0280       int cc = fcol(row, col);
0281       if (val > cblack[cc])
0282       {
0283         val -= cblack[cc];
0284         if (val > ldmax)
0285           ldmax = val;
0286       }
0287       else
0288         val = 0;
0289       imgdata.image[((row) >> IO.shrink) * S.iwidth + ((col) >> IO.shrink)][cc] = val;
0290     }
0291 #if defined(LIBRAW_USE_OPENMP)
0292 #pragma omp critical(dataupdate)
0293 #endif
0294     {
0295       if (*dmaxp < ldmax)
0296         *dmaxp = ldmax;
0297     }
0298   }
0299 }
0300 
0301 int LibRaw::raw2image_ex(int do_subtract_black)
0302 {
0303 
0304   CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
0305 
0306   try
0307   {
0308     raw2image_start();
0309 
0310     // Compressed P1 files with bl data!
0311     if (is_phaseone_compressed() && imgdata.rawdata.raw_alloc)
0312     {
0313       phase_one_allocate_tempbuffer();
0314       int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc,
0315                                         imgdata.rawdata.raw_image);
0316       if (rc == 0)
0317         rc = phase_one_correct();
0318       if (rc != 0)
0319       {
0320         phase_one_free_tempbuffer();
0321         return rc;
0322       }
0323     }
0324 
0325     // process cropping
0326     int do_crop = 0;
0327     if (~O.cropbox[2] && ~O.cropbox[3])
0328     {
0329       int crop[4], c, filt;
0330       for (int q = 0; q < 4; q++)
0331       {
0332         crop[q] = O.cropbox[q];
0333         if (crop[q] < 0)
0334           crop[q] = 0;
0335       }
0336 
0337       if (IO.fuji_width && imgdata.idata.filters >= 1000)
0338       {
0339         crop[0] = (crop[0] / 4) * 4;
0340         crop[1] = (crop[1] / 4) * 4;
0341         if (!libraw_internal_data.unpacker_data.fuji_layout)
0342         {
0343           crop[2] *= sqrt(2.0);
0344           crop[3] /= sqrt(2.0);
0345         }
0346         crop[2] = (crop[2] / 4 + 1) * 4;
0347         crop[3] = (crop[3] / 4 + 1) * 4;
0348       }
0349       else if (imgdata.idata.filters == 1)
0350       {
0351         crop[0] = (crop[0] / 16) * 16;
0352         crop[1] = (crop[1] / 16) * 16;
0353       }
0354       else if (imgdata.idata.filters == LIBRAW_XTRANS)
0355       {
0356         crop[0] = (crop[0] / 6) * 6;
0357         crop[1] = (crop[1] / 6) * 6;
0358       }
0359       do_crop = 1;
0360 
0361       crop[2] = MIN(crop[2], (signed)S.width - crop[0]);
0362       crop[3] = MIN(crop[3], (signed)S.height - crop[1]);
0363       if (crop[2] <= 0 || crop[3] <= 0)
0364         throw LIBRAW_EXCEPTION_BAD_CROP;
0365 
0366       // adjust sizes!
0367       S.left_margin += crop[0];
0368       S.top_margin += crop[1];
0369       S.width = crop[2];
0370       S.height = crop[3];
0371 
0372       S.iheight = (S.height + IO.shrink) >> IO.shrink;
0373       S.iwidth = (S.width + IO.shrink) >> IO.shrink;
0374       if (!IO.fuji_width && imgdata.idata.filters &&
0375           imgdata.idata.filters >= 1000)
0376       {
0377         for (filt = c = 0; c < 16; c++)
0378           filt |= FC((c >> 1) + (crop[1]), (c & 1) + (crop[0])) << c * 2;
0379         imgdata.idata.filters = filt;
0380       }
0381     }
0382 
0383     int alloc_width = S.iwidth;
0384     int alloc_height = S.iheight;
0385 
0386     if (IO.fuji_width && do_crop)
0387     {
0388       int IO_fw = S.width >> int(!libraw_internal_data.unpacker_data.fuji_layout);
0389       int t_alloc_width =
0390           (S.height >> libraw_internal_data.unpacker_data.fuji_layout) + IO_fw;
0391       int t_alloc_height = t_alloc_width - 1;
0392       alloc_height = (t_alloc_height + IO.shrink) >> IO.shrink;
0393       alloc_width = (t_alloc_width + IO.shrink) >> IO.shrink;
0394     }
0395     int alloc_sz = alloc_width * alloc_height;
0396 
0397     if (imgdata.image)
0398     {
0399       imgdata.image = (ushort(*)[4])realloc(imgdata.image,
0400                                             alloc_sz * sizeof(*imgdata.image));
0401       memset(imgdata.image, 0, alloc_sz * sizeof(*imgdata.image));
0402     }
0403     else
0404       imgdata.image = (ushort(*)[4])calloc(alloc_sz, sizeof(*imgdata.image));
0405 
0406     libraw_decoder_info_t decoder_info;
0407     get_decoder_info(&decoder_info);
0408 
0409     // Adjust black levels
0410     unsigned short cblack[4] = {0, 0, 0, 0};
0411     unsigned short dmax = 0;
0412     if (do_subtract_black)
0413     {
0414       adjust_bl();
0415       for (int i = 0; i < 4; i++)
0416         cblack[i] = (unsigned short)C.cblack[i];
0417     }
0418 
0419     // Max area size to definitely not overrun in/out buffers
0420     int copyheight = MAX(0, MIN(int(S.height), int(S.raw_height) - int(S.top_margin)));
0421     int copywidth = MAX(0, MIN(int(S.width), int(S.raw_width) - int(S.left_margin)));
0422 
0423     // Move saved bitmap to imgdata.image
0424     if ((imgdata.idata.filters || P1.colors == 1) && imgdata.rawdata.raw_image)
0425     {
0426       if (IO.fuji_width)
0427       {
0428         if (do_crop)
0429         {
0430           IO.fuji_width =
0431               S.width >> int(!libraw_internal_data.unpacker_data.fuji_layout);
0432           int IO_fwidth =
0433               (S.height >> int(libraw_internal_data.unpacker_data.fuji_layout)) +
0434               IO.fuji_width;
0435           int IO_fheight = IO_fwidth - 1;
0436 
0437           int row, col;
0438           for (row = 0; row < S.height; row++)
0439           {
0440             for (col = 0; col < S.width; col++)
0441             {
0442               int r, c;
0443               if (libraw_internal_data.unpacker_data.fuji_layout)
0444               {
0445                 r = IO.fuji_width - 1 - col + (row >> 1);
0446                 c = col + ((row + 1) >> 1);
0447               }
0448               else
0449               {
0450                 r = IO.fuji_width - 1 + row - (col >> 1);
0451                 c = row + ((col + 1) >> 1);
0452               }
0453 
0454               unsigned short val =
0455                   imgdata.rawdata
0456                       .raw_image[(row + S.top_margin) * S.raw_pitch / 2 +
0457                                  (col + S.left_margin)];
0458               int cc = FCF(row, col);
0459               if (val > cblack[cc])
0460               {
0461                 val -= cblack[cc];
0462                 if (dmax < val)
0463                   dmax = val;
0464               }
0465               else
0466                 val = 0;
0467               imgdata.image[((r) >> IO.shrink) * alloc_width +
0468                             ((c) >> IO.shrink)][cc] = val;
0469             }
0470           }
0471           S.height = IO_fheight;
0472           S.width = IO_fwidth;
0473           S.iheight = (S.height + IO.shrink) >> IO.shrink;
0474           S.iwidth = (S.width + IO.shrink) >> IO.shrink;
0475           S.raw_height -= 2 * S.top_margin;
0476         }
0477         else
0478         {
0479           copy_fuji_uncropped(cblack, &dmax);
0480         }
0481       } // end Fuji
0482       else
0483       {
0484         copy_bayer(cblack, &dmax);
0485       }
0486     }
0487     else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY)
0488     {
0489       if (imgdata.rawdata.color4_image)
0490       {
0491           if (S.raw_pitch != S.width * 8u || S.height != S.raw_height)
0492           {
0493               for (int row = 0; row < copyheight; row++)
0494                   memmove(&imgdata.image[row * S.width],
0495                       &imgdata.rawdata
0496                       .color4_image[(row + S.top_margin) * S.raw_pitch / 8 +
0497                       S.left_margin],
0498                       copywidth * sizeof(*imgdata.image));
0499           }
0500           else
0501           {
0502               // legacy is always 4channel and not shrinked!
0503               memmove(imgdata.image, imgdata.rawdata.color4_image,
0504                   S.width*copyheight * sizeof(*imgdata.image));
0505           }
0506       }
0507       else if (imgdata.rawdata.color3_image)
0508       {
0509           unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image;
0510           for (int row = 0; row < copyheight; row++)
0511         {
0512           ushort(*srcrow)[3] =
0513               (ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch];
0514           ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width];
0515           for (int col = 0; col < copywidth; col++)
0516           {
0517             for (int c = 0; c < 3; c++)
0518               dstrow[col][c] = srcrow[S.left_margin + col][c];
0519             dstrow[col][3] = 0;
0520           }
0521         }
0522       }
0523       else
0524       {
0525         // legacy decoder, but no data?
0526         throw LIBRAW_EXCEPTION_DECODE_RAW;
0527       }
0528     }
0529 
0530     // Free PhaseOne separate copy allocated at function start
0531     if (is_phaseone_compressed())
0532     {
0533       phase_one_free_tempbuffer();
0534     }
0535     if (load_raw == &LibRaw::canon_600_load_raw && S.width < S.raw_width)
0536     {
0537       canon_600_correct();
0538     }
0539 
0540     if (do_subtract_black)
0541     {
0542       C.data_maximum = (int)dmax;
0543       C.maximum -= C.black;
0544       //        ZERO(C.cblack);
0545       C.cblack[0] = C.cblack[1] = C.cblack[2] = C.cblack[3] = 0;
0546       C.black = 0;
0547     }
0548 
0549     // hack - clear later flags!
0550     imgdata.progress_flags =
0551         LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN |
0552         LIBRAW_PROGRESS_RAW2_IMAGE | LIBRAW_PROGRESS_IDENTIFY |
0553         LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW;
0554     return 0;
0555   }
0556   catch (const LibRaw_exceptions& err)
0557   {
0558     EXCEPTION_HANDLER(err);
0559   }
0560 }