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

0001 /* -*- C++ -*-
0002  * Copyright 2019-2021 LibRaw LLC (info@libraw.org)
0003  *
0004  LibRaw is free software; you can redistribute it and/or modify
0005  it under the terms of the one of two licenses as you choose:
0006 
0007 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
0008    (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
0009 
0010 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
0011    (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
0012 
0013  */
0014 
0015 #include "../../internal/libraw_cxx_defs.h"
0016 
0017 #if defined (USE_GPRSDK) && !defined(USE_DNGSDK)
0018 #error  GPR (GoPro) SDK should be used with Adobe DNG SDK
0019 #endif
0020 #ifdef USE_DNGSDK
0021 #include "dng_read_image.h"
0022 #endif
0023 #ifdef USE_GPRSDK
0024 #include "gpr_read_image.h"
0025 #endif
0026 
0027 #ifdef USE_DNGSDK
0028 static dng_ifd* search_single_ifd(const std::vector <dng_ifd *>& v, uint64 offset, int& idx, dng_stream& stream)
0029 {
0030     idx = -1;
0031     for (int i = 0; i < v.size(); i++)
0032     {
0033         if (!v[i]) continue;
0034         if (v[i]->fTileOffsetsOffset == offset)
0035         {
0036             idx = i;
0037             return v[i];
0038         }
0039         else if (v[i]->fTileOffsetsCount == 1 && v[i]->fTileOffset[0] == offset)
0040         {
0041             idx = i;
0042             return v[i];
0043         }
0044         else if (v[i]->fTileOffsetsCount > dng_ifd::kMaxTileInfo)
0045         {
0046             uint64 p  = stream.Position();
0047             stream.SetReadPosition(v[i]->fTileOffsetsOffset);
0048             int32 oo = stream.TagValue_uint32(v[i]->fTileOffsetsType);
0049             stream.SetReadPosition(p);
0050             if (oo == offset)
0051             {
0052                 idx = i;
0053                 return v[i];
0054             }
0055         }
0056     }
0057     return NULL;
0058 }
0059 
0060 static dng_ifd* search_for_ifd(const dng_info& info, uint64 offset, ushort w, ushort h, int& ifdIndex, dng_stream& stream)
0061 {
0062     dng_ifd *ret = 0;
0063     ret = search_single_ifd(info.fIFD, offset, ifdIndex, stream);
0064     int dummy;
0065     if (!ret) ret = search_single_ifd(info.fChainedIFD, offset, dummy, stream);
0066     if (!ret)
0067     {
0068         for (int c = 0; !ret && c < info.fChainedSubIFD.size(); c++)
0069             ret = search_single_ifd(info.fChainedSubIFD[c], offset, dummy, stream);
0070     }
0071     if (ret && (ret->fImageLength == h) && ret->fImageWidth == w)
0072         return ret;
0073     ifdIndex = -1;
0074     return 0;
0075 }
0076 #endif
0077 
0078 int LibRaw::valid_for_dngsdk()
0079 {
0080 #ifndef USE_DNGSDK
0081   return 0;
0082 #else
0083   if (!imgdata.idata.dng_version)
0084     return 0;
0085 
0086   // All DNG larger than 2GB - to DNG SDK
0087   if (libraw_internal_data.internal_data.input->size() > 2147483647ULL)
0088       return 1;
0089 
0090   if (!strcasecmp(imgdata.idata.make, "Blackmagic") 
0091       && (libraw_internal_data.unpacker_data.tiff_compress == 7)
0092       && (libraw_internal_data.unpacker_data.tiff_bps > 8)
0093       )
0094       return 0;
0095 
0096   if (libraw_internal_data.unpacker_data.tiff_compress == 34892
0097       && libraw_internal_data.unpacker_data.tiff_bps == 8
0098       && libraw_internal_data.unpacker_data.tiff_samples == 3
0099       && load_raw == &LibRaw::lossy_dng_load_raw
0100       )
0101   {
0102       if (!dnghost)
0103           return 0;
0104       dng_host *host = static_cast<dng_host *>(dnghost);
0105       libraw_dng_stream stream(libraw_internal_data.internal_data.input);
0106       AutoPtr<dng_negative> negative;
0107       negative.Reset(host->Make_dng_negative());
0108       dng_info info;
0109       info.Parse(*host, stream);
0110       info.PostParse(*host);
0111       if (!info.IsValidDNG())
0112           return 0;
0113       negative->Parse(*host, stream, info);
0114       negative->PostParse(*host, stream, info);
0115       int ifdindex = -1;
0116       dng_ifd *rawIFD = search_for_ifd(info, libraw_internal_data.unpacker_data.data_offset, imgdata.sizes.raw_width, imgdata.sizes.raw_height, ifdindex,stream);
0117       if (rawIFD && ifdindex >= 0 && ifdindex == info.fMainIndex)
0118           return 1;
0119       return 0;
0120   }
0121 
0122 #ifdef USE_GPRSDK
0123   if (load_raw == &LibRaw::vc5_dng_load_raw_placeholder) // regardless of flags or use_dngsdk value!
0124       return 1;
0125 #endif
0126   if (!imgdata.rawparams.use_dngsdk)
0127     return 0;
0128   if (load_raw == &LibRaw::lossy_dng_load_raw) // WHY??
0129     return 0;
0130   if (is_floating_point() && (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_FLOAT))
0131     return 1;
0132   if (!imgdata.idata.filters && (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_LINEAR))
0133     return 1;
0134   if (libraw_internal_data.unpacker_data.tiff_bps == 8 &&
0135       (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_8BIT))
0136     return 1;
0137   if (libraw_internal_data.unpacker_data.tiff_compress == 8 &&
0138       (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_DEFLATE))
0139     return 1;
0140   if (libraw_internal_data.unpacker_data.tiff_samples == 2)
0141     return 0; // Always deny 2-samples (old fuji superccd)
0142   if (imgdata.idata.filters == 9 &&
0143       (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_XTRANS))
0144     return 1;
0145   if (is_fuji_rotated())
0146     return 0; // refuse
0147   if (imgdata.rawparams.use_dngsdk & LIBRAW_DNG_OTHER)
0148     return 1;
0149   return 0;
0150 #endif
0151 }
0152 
0153 
0154 
0155 
0156 int LibRaw::try_dngsdk()
0157 {
0158 #ifdef USE_DNGSDK
0159   if (!dnghost)
0160     return LIBRAW_UNSPECIFIED_ERROR;
0161 
0162   dng_host *host = static_cast<dng_host *>(dnghost);
0163 
0164   try
0165   {
0166     libraw_dng_stream stream(libraw_internal_data.internal_data.input);
0167 
0168     AutoPtr<dng_negative> negative;
0169     negative.Reset(host->Make_dng_negative());
0170 
0171     dng_info info;
0172     info.Parse(*host, stream);
0173     info.PostParse(*host);
0174 
0175     if (!info.IsValidDNG())
0176     {
0177       return LIBRAW_DATA_ERROR;
0178     }
0179     negative->Parse(*host, stream, info);
0180     negative->PostParse(*host, stream, info);
0181     int ifdindex;
0182     dng_ifd *rawIFD = search_for_ifd(info,libraw_internal_data.unpacker_data.data_offset,imgdata.sizes.raw_width,imgdata.sizes.raw_height,ifdindex,stream);
0183     if(!rawIFD)
0184         return LIBRAW_DATA_ERROR;
0185 
0186     AutoPtr<dng_simple_image> stage2;
0187     bool stage23used = false;
0188     bool zerocopy = false;
0189 
0190     //(new dng_simple_image(rawIFD->Bounds(), rawIFD->fSamplesPerPixel, rawIFD->PixelType(), host->Allocator()));
0191 
0192     if (((libraw_internal_data.unpacker_data.tiff_compress == 34892 
0193         && libraw_internal_data.unpacker_data.tiff_bps == 8
0194         && libraw_internal_data.unpacker_data.tiff_samples == 3
0195         && load_raw == &LibRaw::lossy_dng_load_raw) 
0196         || (imgdata.rawparams.options & (LIBRAW_RAWOPTIONS_DNG_STAGE2| LIBRAW_RAWOPTIONS_DNG_STAGE3))
0197         || ((tiff_ifd[ifdindex].dng_levels.parsedfields & (LIBRAW_DNGFM_OPCODE2| LIBRAW_DNGFM_OPCODE3))
0198             && (imgdata.rawparams.options & (LIBRAW_RAWOPTIONS_DNG_STAGE2_IFPRESENT | LIBRAW_RAWOPTIONS_DNG_STAGE3_IFPRESENT)))
0199         )
0200         && ifdindex >= 0)
0201     {
0202         if (info.fMainIndex != ifdindex)
0203             info.fMainIndex = ifdindex;
0204 
0205         negative->ReadStage1Image(*host, stream, info);
0206         negative->BuildStage2Image(*host);
0207         imgdata.process_warnings |= LIBRAW_WARN_DNG_STAGE2_APPLIED;
0208         if (  (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_STAGE3) ||
0209             ((tiff_ifd[ifdindex].dng_levels.parsedfields & LIBRAW_DNGFM_OPCODE3) &&
0210              (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_STAGE3_IFPRESENT))
0211             )
0212         {
0213             negative->BuildStage3Image(*host);
0214             stage2.Reset((dng_simple_image*)negative->Stage3Image());
0215             imgdata.process_warnings |= LIBRAW_WARN_DNG_STAGE3_APPLIED;
0216         }
0217         else
0218             stage2.Reset((dng_simple_image*)negative->Stage2Image());
0219         stage23used = true;
0220     }
0221     else
0222     {
0223         stage2.Reset(new dng_simple_image(rawIFD->Bounds(), rawIFD->fSamplesPerPixel, rawIFD->PixelType(), host->Allocator()));
0224 #ifdef USE_GPRSDK
0225         if (libraw_internal_data.unpacker_data.tiff_compress == 9)
0226         {
0227             gpr_allocator allocator;
0228             allocator.Alloc = ::malloc;
0229             allocator.Free = ::free;
0230             gpr_buffer_auto vc5_image_obj(allocator.Alloc, allocator.Free);
0231 
0232             gpr_read_image reader(&vc5_image_obj);
0233             reader.Read(*host, *rawIFD, stream, *stage2.Get(), NULL, NULL);
0234         }
0235         else
0236 #endif
0237         {
0238             dng_read_image reader;
0239             reader.Read(*host, *rawIFD, stream, *stage2.Get(), NULL, NULL);
0240         }
0241     }
0242 
0243     if (stage2->Bounds().W() != S.raw_width ||
0244         stage2->Bounds().H() != S.raw_height)
0245     {
0246         if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNG_ALLOWSIZECHANGE)
0247         {
0248             S.raw_width = S.width = stage2->Bounds().W();
0249             S.left_margin = 0;
0250             S.raw_height = S.height = stage2->Bounds().H();
0251             S.top_margin = 0;
0252         }
0253         else
0254         {
0255             stage2.Release(); // It holds copy to internal dngnegative
0256             return LIBRAW_DATA_ERROR;
0257         }
0258     }
0259     if (stage23used)
0260     {
0261         if (stage2->Planes() > 1)
0262         {
0263             imgdata.idata.filters = 0;
0264             imgdata.idata.colors = stage2->Planes();
0265         }
0266         // reset BL and whitepoint
0267         imgdata.color.black = 0;
0268         memset(imgdata.color.cblack, 0, sizeof(imgdata.color.cblack));
0269         imgdata.color.maximum = 0xffff;
0270     }
0271 
0272     int pplanes = stage2->Planes();
0273     int ptype = stage2->PixelType();
0274 
0275     dng_pixel_buffer buffer;
0276     stage2->GetPixelBuffer(buffer);
0277 
0278     int pixels = stage2->Bounds().H() * stage2->Bounds().W() * pplanes;
0279 
0280     if (ptype == ttShort && !stage23used &&  !is_curve_linear())
0281     {
0282       imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ptype));
0283       ushort *src = (ushort *)buffer.fData;
0284       ushort *dst = (ushort *)imgdata.rawdata.raw_alloc;
0285       for (int i = 0; i < pixels; i++)
0286         dst[i] = imgdata.color.curve[src[i]];
0287       S.raw_pitch = S.raw_width * pplanes * TagTypeSize(ptype);
0288 
0289     }
0290     else if (ptype == ttByte)
0291     {
0292       imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ttShort));
0293       unsigned char *src = (unsigned char *)buffer.fData;
0294       ushort *dst = (ushort *)imgdata.rawdata.raw_alloc;
0295       if (is_curve_linear())
0296       {
0297         for (int i = 0; i < pixels; i++)
0298           dst[i] = src[i];
0299       }
0300       else
0301       {
0302         for (int i = 0; i < pixels; i++)
0303           dst[i] = imgdata.color.curve[src[i]];
0304       }
0305       S.raw_pitch = S.raw_width * pplanes * TagTypeSize(ttShort);
0306     }
0307     else
0308     {
0309       // Alloc
0310       if ((imgdata.rawparams.options & LIBRAW_RAWOPTIONS_DNGSDK_ZEROCOPY) && !stage23used)
0311       {
0312         zerocopy = true;
0313       }
0314       else
0315       {
0316         imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ptype));
0317         memmove(imgdata.rawdata.raw_alloc, buffer.fData,
0318                 pixels * TagTypeSize(ptype));
0319       }
0320       S.raw_pitch = S.raw_width * pplanes * TagTypeSize(ptype);
0321     }
0322 
0323     if (stage23used)
0324         stage2.Release();
0325 
0326     if ((ptype == ttFloat) && (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT))
0327         zerocopy = true;
0328 
0329     if (zerocopy)
0330     {
0331       switch (ptype)
0332       {
0333       case ttFloat:
0334         if (pplanes == 1)
0335           imgdata.rawdata.float_image = (float *)buffer.fData;
0336         else if (pplanes == 3)
0337           imgdata.rawdata.float3_image = (float(*)[3])buffer.fData;
0338         else if (pplanes == 4)
0339           imgdata.rawdata.float4_image = (float(*)[4])buffer.fData;
0340         break;
0341 
0342       case ttShort:
0343         if (pplanes == 1)
0344           imgdata.rawdata.raw_image = (ushort *)buffer.fData;
0345         else if (pplanes == 3)
0346           imgdata.rawdata.color3_image = (ushort(*)[3])buffer.fData;
0347         else if (pplanes == 4)
0348           imgdata.rawdata.color4_image = (ushort(*)[4])buffer.fData;
0349         break;
0350       default:
0351         /* do nothing */
0352         break;
0353       }
0354     }
0355     else
0356     {
0357       switch (ptype)
0358       {
0359       case ttFloat:
0360         if (pplanes == 1)
0361           imgdata.rawdata.float_image = (float *)imgdata.rawdata.raw_alloc;
0362         else if (pplanes == 3)
0363           imgdata.rawdata.float3_image = (float(*)[3])imgdata.rawdata.raw_alloc;
0364         else if (pplanes == 4)
0365           imgdata.rawdata.float4_image = (float(*)[4])imgdata.rawdata.raw_alloc;
0366         break;
0367 
0368       case ttByte:
0369       case ttShort:
0370         if (pplanes == 1)
0371           imgdata.rawdata.raw_image = (ushort *)imgdata.rawdata.raw_alloc;
0372         else if (pplanes == 3)
0373           imgdata.rawdata.color3_image =
0374               (ushort(*)[3])imgdata.rawdata.raw_alloc;
0375         else if (pplanes == 4)
0376           imgdata.rawdata.color4_image =
0377               (ushort(*)[4])imgdata.rawdata.raw_alloc;
0378         break;
0379       default:
0380         /* do nothing */
0381         break;
0382       }
0383     }
0384 
0385     if ((ptype == ttFloat) && (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_CONVERTFLOAT_TO_INT))
0386     {
0387         convertFloatToInt();
0388         zerocopy = false;
0389     }
0390 
0391     if (zerocopy)
0392     {
0393       dng_negative *stolen = negative.Release();
0394       dngnegative = stolen;
0395       dng_simple_image *simage = stage2.Release();
0396       dngimage = simage;
0397     }
0398   }
0399   catch (...)
0400   {
0401     return LIBRAW_UNSPECIFIED_ERROR;
0402   }
0403   
0404   return (dngnegative || imgdata.rawdata.raw_alloc) ? LIBRAW_SUCCESS : LIBRAW_UNSPECIFIED_ERROR;
0405 #else
0406   return LIBRAW_UNSPECIFIED_ERROR;
0407 #endif
0408 }
0409 void LibRaw::set_dng_host(void *p)
0410 {
0411 #ifdef USE_DNGSDK
0412   dnghost = p;
0413 #endif
0414 }