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 }