File indexing completed on 2025-01-05 03:56:58
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/dcraw_defs.h" 0017 0018 0019 static libraw_area_t sget_CanonArea(uchar *s) { 0020 libraw_area_t la = {}; 0021 la.l = s[0] << 8 | s[1]; 0022 la.t = s[2] << 8 | s[3]; 0023 la.r = s[4] << 8 | s[5]; 0024 la.b = s[6] << 8 | s[7]; 0025 return la; 0026 } 0027 0028 int LibRaw::selectCRXFrame(short trackNum, unsigned frameIndex) 0029 { 0030 uint32_t sample_size; 0031 uint32_t stsc_index = 0; 0032 uint32_t current_sample = 0; 0033 crx_data_header_t *hdr = &libraw_internal_data.unpacker_data.crx_header[trackNum]; 0034 0035 if (frameIndex >= hdr->sample_count) 0036 return -1; 0037 0038 for (int i = 0; i < hdr->chunk_count; i++) 0039 { 0040 int64_t current_offset = hdr->chunk_offsets[i]; 0041 0042 while((stsc_index < hdr->stsc_count) && (i+1 == hdr->stsc_data[stsc_index+1].first)) 0043 stsc_index++; 0044 0045 for (int j = 0; j < hdr->stsc_data[stsc_index].count; j++) 0046 { 0047 if (current_sample > hdr->sample_count) 0048 return -1; 0049 0050 sample_size = hdr->sample_size > 0 ? hdr->sample_size : hdr->sample_sizes[current_sample]; 0051 if(current_sample == frameIndex) 0052 { 0053 hdr->MediaOffset = current_offset; 0054 hdr->MediaSize = sample_size; 0055 return 0; 0056 } 0057 current_offset += sample_size; 0058 current_sample++; 0059 } 0060 } 0061 return -1; 0062 } 0063 0064 void LibRaw::selectCRXTrack() 0065 { 0066 short maxTrack = libraw_internal_data.unpacker_data.crx_track_count; 0067 if (maxTrack < 0) 0068 return; 0069 0070 INT64 bitcounts[LIBRAW_CRXTRACKS_MAXCOUNT], maxbitcount = 0; 0071 int framecounts[LIBRAW_CRXTRACKS_MAXCOUNT], maxframecount = 0; 0072 uint32_t maxjpegbytes = 0; 0073 int framecnt = 0; 0074 int media_tracks = 0; 0075 int track_select = 0; 0076 int frame_select = 0; 0077 int err; 0078 memset(bitcounts, 0, sizeof(bitcounts)); 0079 memset(framecounts, 0, sizeof(framecounts)); 0080 0081 // Calc max frame bitcount for max-sized RAW track(s) selection 0082 for (int i = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++) 0083 { 0084 crx_data_header_t *d = &libraw_internal_data.unpacker_data.crx_header[i]; 0085 if (d->MediaType == 1) // RAW 0086 { 0087 bitcounts[i] = INT64(d->nBits) * INT64(d->f_width) * INT64(d->f_height); 0088 maxbitcount = MAX(bitcounts[i], maxbitcount); 0089 if (d->sample_count > 1) 0090 framecounts[i] = d->sample_count; 0091 } 0092 } 0093 0094 if (maxbitcount < 8) // no raw tracks 0095 return; 0096 0097 // Calc RAW tracks and frames 0098 for (int i = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++) 0099 { 0100 if (bitcounts[i] == maxbitcount) 0101 { 0102 media_tracks++; 0103 if (framecounts[i] > 1) 0104 framecnt = MAX(framecnt, framecounts[i]); 0105 } 0106 } 0107 0108 // If the file has only 1 media track shot_select represents frames select. 0109 // If the file has multiple media tracks shot_select represents track select. 0110 // If the file has multiple media tracks and multiple frames it is currently unsupported. 0111 0112 if (framecnt && media_tracks > 1) 0113 return; 0114 else if (framecnt) 0115 frame_select = shot_select; 0116 else 0117 track_select = shot_select; 0118 0119 int tracki = -1; 0120 for (int i = 0, trackcnt = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++) 0121 { 0122 if (bitcounts[i] == maxbitcount) 0123 { 0124 if (trackcnt <= (int)track_select) 0125 tracki = i; 0126 trackcnt++; 0127 } 0128 } 0129 0130 if (tracki >= 0 && tracki < LIBRAW_CRXTRACKS_MAXCOUNT /* && frame_select > 0 */) 0131 { 0132 framecnt = framecounts[tracki]; // Update to selected track 0133 frame_select = LIM(frame_select, 0, framecnt); 0134 if(frame_select > 0) 0135 if (selectCRXFrame(tracki, frame_select)) 0136 return; 0137 } 0138 else 0139 return; // No RAW track index 0140 0141 // Frame selected: parse CTMD metadata 0142 for (int i = 0, trackcnt = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++) 0143 { 0144 crx_data_header_t *d = &libraw_internal_data.unpacker_data.crx_header[i]; 0145 int fsel = LIM(frame_select, 0, d->sample_count); 0146 if (d->MediaType == 3) // CTMD metadata 0147 { 0148 /* ignore errors !*/ 0149 if (fsel) 0150 selectCRXFrame(i, fsel); 0151 parseCR3_CTMD(i); 0152 } 0153 else if (d->MediaType == 2) // JPEG 0154 { 0155 if (fsel) 0156 selectCRXFrame(i, fsel); 0157 if (d->MediaSize > maxjpegbytes) 0158 { 0159 maxjpegbytes = d->MediaSize; 0160 thumb_offset = d->MediaOffset; 0161 thumb_length = d->MediaSize; 0162 if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT) 0163 { 0164 bool do_add = true; 0165 for (int idx = 0; idx < imgdata.thumbs_list.thumbcount; idx++) 0166 if (imgdata.thumbs_list.thumblist[idx].toffset == thumb_offset) 0167 { 0168 do_add = false; 0169 break; 0170 } 0171 if (do_add) 0172 { 0173 int idx = imgdata.thumbs_list.thumbcount; 0174 imgdata.thumbs_list.thumblist[idx].tformat = LIBRAW_INTERNAL_THUMBNAIL_JPEG; 0175 imgdata.thumbs_list.thumblist[idx].toffset = thumb_offset; 0176 imgdata.thumbs_list.thumblist[idx].tlength = thumb_length; 0177 imgdata.thumbs_list.thumblist[idx].tflip = 0xffff; 0178 imgdata.thumbs_list.thumblist[idx].tmisc = (3 << 5) | 8; // 3 samples/8 bps 0179 imgdata.thumbs_list.thumblist[idx].twidth = 0; 0180 imgdata.thumbs_list.thumblist[idx].theight = 0; 0181 imgdata.thumbs_list.thumbcount++; 0182 } 0183 } 0184 } 0185 } 0186 } 0187 0188 if (framecnt) 0189 is_raw = framecnt; 0190 else 0191 is_raw = media_tracks; 0192 0193 if (tracki >= 0 && tracki < LIBRAW_CRXTRACKS_MAXCOUNT) 0194 { 0195 crx_data_header_t *d = 0196 &libraw_internal_data.unpacker_data.crx_header[tracki]; 0197 data_offset = d->MediaOffset; 0198 data_size = d->MediaSize; 0199 raw_width = d->f_width; 0200 raw_height = d->f_height; 0201 load_raw = &LibRaw::crxLoadRaw; 0202 tiff_bps = d->encType == 3? d->medianBits : d->nBits; 0203 switch (d->cfaLayout) 0204 { 0205 case 0: 0206 filters = 0x94949494; 0207 break; 0208 case 1: 0209 filters = 0x61616161; 0210 break; 0211 case 2: 0212 filters = 0x49494949; 0213 break; 0214 case 3: 0215 filters = 0x16161616; 0216 break; 0217 } 0218 0219 libraw_internal_data.unpacker_data.crx_track_selected = tracki; 0220 0221 int tiff_idx = -1; 0222 INT64 tpixels = 0; 0223 for (unsigned i = 0; i < tiff_nifds && i < LIBRAW_IFD_MAXCOUNT; i++) 0224 if (INT64(tiff_ifd[i].t_height) * INT64(tiff_ifd[i].t_height) > tpixels) 0225 { 0226 tpixels = INT64(tiff_ifd[i].t_height) * INT64(tiff_ifd[i].t_height); 0227 tiff_idx = i; 0228 } 0229 if (tiff_idx >= 0) 0230 flip = tiff_ifd[tiff_idx].t_flip; 0231 } 0232 } 0233 0234 #define bad_hdr() \ 0235 (((order != 0x4d4d) && (order != 0x4949)) || (get2() != 0x002a) || \ 0236 (get4() != 0x00000008)) 0237 0238 int LibRaw::parseCR3_CTMD(short trackNum) 0239 { 0240 int err = 0; 0241 short s_order = order; 0242 order = 0x4949; 0243 uint32_t relpos_inDir = 0; 0244 uint32_t relpos_inBox = 0; 0245 unsigned szItem, Tag, lTag; 0246 ushort tItem; 0247 0248 #define track libraw_internal_data.unpacker_data.crx_header[trackNum] 0249 0250 if (track.MediaType != 3) 0251 { 0252 err = -10; 0253 goto ctmd_fin; 0254 } 0255 0256 while (relpos_inDir + 6 < track.MediaSize) 0257 { 0258 if (track.MediaOffset + relpos_inDir > ifp->size() - 6) // need at least 6 bytes 0259 { 0260 err = -11; 0261 goto ctmd_fin; 0262 } 0263 fseek(ifp, track.MediaOffset + relpos_inDir, SEEK_SET); 0264 szItem = get4(); 0265 tItem = get2(); 0266 if (szItem < 1 || ( (relpos_inDir + szItem) > track.MediaSize)) 0267 { 0268 err = -11; 0269 goto ctmd_fin; 0270 } 0271 if ((tItem == 7) || (tItem == 8) || (tItem == 9)) 0272 { 0273 relpos_inBox = relpos_inDir + 12L; 0274 while (relpos_inBox + 8 < relpos_inDir + szItem) 0275 { 0276 if (track.MediaOffset + relpos_inBox > ifp->size() - 8) // need at least 8 bytes 0277 { 0278 err = -11; 0279 goto ctmd_fin; 0280 } 0281 fseek(ifp, track.MediaOffset + relpos_inBox, SEEK_SET); 0282 lTag = get4(); 0283 Tag = get4(); 0284 if (lTag < 8) 0285 { 0286 err = -12; 0287 goto ctmd_fin; 0288 } 0289 else if ((relpos_inBox + lTag) > (relpos_inDir + szItem)) 0290 { 0291 err = -11; 0292 goto ctmd_fin; 0293 } 0294 if ((Tag == 0x927c) && ((tItem == 7) || (tItem == 8))) 0295 { 0296 fseek(ifp, track.MediaOffset + relpos_inBox + 8L, 0297 SEEK_SET); 0298 short q_order = order; 0299 order = get2(); 0300 if (bad_hdr()) 0301 { 0302 err = -13; 0303 goto ctmd_fin; 0304 } 0305 fseek(ifp, -8L, SEEK_CUR); 0306 libraw_internal_data.unpacker_data.CR3_CTMDtag = 1; 0307 parse_makernote(track.MediaOffset + relpos_inBox + 8, 0308 0); 0309 libraw_internal_data.unpacker_data.CR3_CTMDtag = 0; 0310 order = q_order; 0311 } 0312 relpos_inBox += lTag; 0313 } 0314 } 0315 relpos_inDir += szItem; 0316 } 0317 0318 ctmd_fin: 0319 order = s_order; 0320 return err; 0321 } 0322 #undef track 0323 0324 int LibRaw::parseCR3(INT64 oAtomList, 0325 INT64 szAtomList, short &nesting, 0326 char *AtomNameStack, short &nTrack, short &TrackType) 0327 { 0328 /* 0329 Atom starts with 4 bytes for Atom size and 4 bytes containing Atom name 0330 Atom size includes the length of the header and the size of all "contained" 0331 Atoms if Atom size == 1, Atom has the extended size stored in 8 bytes located 0332 after the Atom name if Atom size == 0, it is the last top-level Atom extending 0333 to the end of the file Atom name is often a 4 symbol mnemonic, but can be a 0334 4-byte integer 0335 */ 0336 const char UIID_Canon[17] = 0337 "\x85\xc0\xb6\x87\x82\x0f\x11\xe0\x81\x11\xf4\xce\x46\x2b\x6a\x48"; 0338 const unsigned char UIID_CanonPreview[17] = "\xea\xf4\x2b\x5e\x1c\x98\x4b\x88\xb9\xfb\xb7\xdc\x40\x6e\x4d\x16"; 0339 const unsigned char UUID_XMP[17] = "\xbe\x7a\xcf\xcb\x97\xa9\x42\xe8\x9c\x71\x99\x94\x91\xe3\xaf\xac"; 0340 0341 /* 0342 AtomType = 0 - unknown: "unk." 0343 AtomType = 1 - container atom: "cont" 0344 AtomType = 2 - leaf atom: "leaf" 0345 AtomType = 3 - can be container, can be leaf: "both" 0346 */ 0347 short AtomType; 0348 static const struct 0349 { 0350 char AtomName[5]; 0351 short AtomType; 0352 } AtomNamesList[] = { 0353 {"dinf", 1}, 0354 {"edts", 1}, 0355 {"fiin", 1}, 0356 {"ipro", 1}, 0357 {"iprp", 1}, 0358 {"mdia", 1}, 0359 {"meco", 1}, 0360 {"mere", 1}, 0361 {"mfra", 1}, 0362 {"minf", 1}, 0363 {"moof", 1}, 0364 {"moov", 1}, 0365 {"mvex", 1}, 0366 {"paen", 1}, 0367 {"schi", 1}, 0368 {"sinf", 1}, 0369 {"skip", 1}, 0370 {"stbl", 1}, 0371 {"stsd", 1}, 0372 {"strk", 1}, 0373 {"tapt", 1}, 0374 {"traf", 1}, 0375 {"trak", 1}, 0376 0377 {"cdsc", 2}, 0378 {"colr", 2}, 0379 {"dimg", 2}, 0380 // {"dref", 2}, 0381 {"free", 2}, 0382 {"frma", 2}, 0383 {"ftyp", 2}, 0384 {"hdlr", 2}, 0385 {"hvcC", 2}, 0386 {"iinf", 2}, 0387 {"iloc", 2}, 0388 {"infe", 2}, 0389 {"ipco", 2}, 0390 {"ipma", 2}, 0391 {"iref", 2}, 0392 {"irot", 2}, 0393 {"ispe", 2}, 0394 {"meta", 2}, 0395 {"mvhd", 2}, 0396 {"pitm", 2}, 0397 {"pixi", 2}, 0398 {"schm", 2}, 0399 {"thmb", 2}, 0400 {"tkhd", 2}, 0401 {"url ", 2}, 0402 {"urn ", 2}, 0403 0404 {"CCTP", 1}, 0405 {"CRAW", 1}, 0406 0407 {"JPEG", 2}, 0408 {"CDI1", 2}, 0409 {"CMP1", 2}, 0410 0411 {"CNCV", 2}, 0412 {"CCDT", 2}, 0413 {"CTBO", 2}, 0414 {"CMT1", 2}, 0415 {"CMT2", 2}, 0416 {"CMT3", 2}, 0417 {"CMT4", 2}, 0418 {"CNOP", 2}, 0419 {"THMB", 2}, 0420 {"co64", 2}, 0421 {"mdat", 2}, 0422 {"mdhd", 2}, 0423 {"nmhd", 2}, 0424 {"stsc", 2}, 0425 {"stsz", 2}, 0426 {"stts", 2}, 0427 {"vmhd", 2}, 0428 0429 {"dref", 3}, 0430 {"uuid", 3}, 0431 }; 0432 0433 const char sHandlerType[5][5] = {"unk.", "soun", "vide", "hint", "meta"}; 0434 0435 int c, err=0; 0436 0437 ushort tL; // Atom length represented in 4 or 8 bytes 0438 char nmAtom[5]; // Atom name 0439 INT64 oAtom, szAtom; // Atom offset and Atom size 0440 INT64 oAtomContent, 0441 szAtomContent; // offset and size of Atom content 0442 INT64 lHdr; 0443 0444 char UIID[16]; 0445 uchar CMP1[85]; 0446 uchar CDI1[60]; 0447 char HandlerType[5], MediaFormatID[5]; 0448 uint32_t relpos_inDir, relpos_inBox; 0449 unsigned szItem, Tag, lTag; 0450 ushort tItem; 0451 0452 nmAtom[0] = MediaFormatID[0] = nmAtom[4] = MediaFormatID[4] = '\0'; 0453 strcpy(HandlerType, sHandlerType[0]); 0454 oAtom = oAtomList; 0455 nesting++; 0456 if (nesting > 31) 0457 return -14; // too deep nesting 0458 short s_order = order; 0459 0460 while ((oAtom + 8LL) <= (oAtomList + szAtomList)) 0461 { 0462 lHdr = 0ULL; 0463 err = 0; 0464 order = 0x4d4d; 0465 fseek(ifp, oAtom, SEEK_SET); 0466 szAtom = get4(); 0467 FORC4 nmAtom[c] = AtomNameStack[nesting * 4 + c] = fgetc(ifp); 0468 AtomNameStack[(nesting + 1) * 4] = '\0'; 0469 tL = 4; 0470 AtomType = 0; 0471 0472 for (c = 0; c < int(sizeof AtomNamesList / sizeof *AtomNamesList); c++) 0473 if (!strcmp(nmAtom, AtomNamesList[c].AtomName)) 0474 { 0475 AtomType = AtomNamesList[c].AtomType; 0476 break; 0477 } 0478 0479 if (!AtomType) 0480 { 0481 err = 1; 0482 } 0483 0484 if (szAtom == 0ULL) 0485 { 0486 if (nesting != 0) 0487 { 0488 err = -2; 0489 goto fin; 0490 } 0491 szAtom = szAtomList - oAtom; 0492 oAtomContent = oAtom + 8ULL; 0493 szAtomContent = szAtom - 8ULL; 0494 } 0495 else if (szAtom == 1LL) 0496 { 0497 if ((oAtom + 16LL) > (oAtomList + szAtomList)) 0498 { 0499 err = -3; 0500 goto fin; 0501 } 0502 tL = 8; 0503 szAtom = (((unsigned long long)get4()) << 32) | get4(); 0504 oAtomContent = oAtom + 16ULL; 0505 szAtomContent = szAtom - 16ULL; 0506 } 0507 else 0508 { 0509 oAtomContent = oAtom + 8ULL; 0510 szAtomContent = szAtom - 8ULL; 0511 } 0512 0513 if (!strcmp(AtomNameStack, "uuid")) // Top level uuid 0514 { 0515 INT64 tt = ftell(ifp); 0516 lHdr = 16ULL; 0517 fread(UIID, 1, lHdr, ifp); 0518 if (!memcmp(UIID, UUID_XMP, 16) && szAtom > 24LL && szAtom < 1024000LL) 0519 { 0520 xmpdata = (char *)malloc(xmplen = unsigned(szAtom - 23)); 0521 fread(xmpdata, szAtom - 24, 1, ifp); 0522 xmpdata[szAtom - 24] = 0; 0523 } 0524 else if (!memcmp(UIID, UIID_CanonPreview, 16) && szAtom > 48LL && szAtom < 100LL * 1024000LL) 0525 { 0526 // read next 48 bytes, check for 'PRVW' 0527 unsigned char xdata[32]; 0528 fread(xdata, 32, 1, ifp); 0529 if (!memcmp(xdata + 12, "PRVW", 4)) 0530 { 0531 thumb_length = unsigned(szAtom - 56); 0532 thumb_offset = ftell(ifp); 0533 if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT) 0534 { 0535 bool do_add = true; 0536 for(int idx = 0; idx < imgdata.thumbs_list.thumbcount; idx++) 0537 if (imgdata.thumbs_list.thumblist[idx].toffset == thumb_offset) 0538 { 0539 do_add = false; 0540 break; 0541 } 0542 if (do_add) 0543 { 0544 int idx = imgdata.thumbs_list.thumbcount; 0545 imgdata.thumbs_list.thumblist[idx].tformat = LIBRAW_INTERNAL_THUMBNAIL_JPEG; 0546 imgdata.thumbs_list.thumblist[idx].toffset = thumb_offset; 0547 imgdata.thumbs_list.thumblist[idx].tlength = thumb_length; 0548 imgdata.thumbs_list.thumblist[idx].tflip = 0xffff; 0549 imgdata.thumbs_list.thumblist[idx].tmisc = (3 << 5) | 8; // 3 samples/8 bps 0550 imgdata.thumbs_list.thumblist[idx].twidth = (xdata[22] << 8) + xdata[23]; 0551 imgdata.thumbs_list.thumblist[idx].theight = (xdata[24] << 8) + xdata[25]; 0552 imgdata.thumbs_list.thumbcount++; 0553 } 0554 } 0555 0556 } 0557 } 0558 fseek(ifp, tt, SEEK_SET); 0559 } 0560 0561 if (!strcmp(nmAtom, "trak")) 0562 { 0563 nTrack++; 0564 TrackType = 0; 0565 if (nTrack >= LIBRAW_CRXTRACKS_MAXCOUNT) 0566 break; 0567 } 0568 if (!strcmp(AtomNameStack, "moovuuid")) 0569 { 0570 lHdr = 16ULL; 0571 fread(UIID, 1, lHdr, ifp); 0572 if (!strncmp(UIID, UIID_Canon, lHdr)) 0573 { 0574 AtomType = 1; 0575 } 0576 else 0577 fseek(ifp, -lHdr, SEEK_CUR); 0578 } 0579 else if (!strcmp(AtomNameStack, "moovuuidCCTP")) 0580 { 0581 lHdr = 12ULL; 0582 } 0583 else if (!strcmp(AtomNameStack, "moovuuidCMT1")) 0584 { 0585 short q_order = order; 0586 order = get2(); 0587 if ((tL != 4) || bad_hdr()) 0588 { 0589 err = -4; 0590 goto fin; 0591 } 0592 if (!libraw_internal_data.unpacker_data.cr3_ifd0_length) 0593 libraw_internal_data.unpacker_data.cr3_ifd0_length = unsigned(szAtomContent); 0594 parse_tiff_ifd(oAtomContent); 0595 order = q_order; 0596 } 0597 else if (!strcmp(AtomNameStack, "moovuuidTHMB") && szAtom > 24) 0598 { 0599 unsigned char xdata[16]; 0600 fread(xdata, 16, 1, ifp); 0601 INT64 xoffset = ftell(ifp); 0602 if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT) 0603 { 0604 bool do_add = true; 0605 for (int idx = 0; idx < imgdata.thumbs_list.thumbcount; idx++) 0606 if (imgdata.thumbs_list.thumblist[idx].toffset == xoffset) 0607 { 0608 do_add = false; 0609 break; 0610 } 0611 if (do_add) 0612 { 0613 int idx = imgdata.thumbs_list.thumbcount; 0614 imgdata.thumbs_list.thumblist[idx].tformat = LIBRAW_INTERNAL_THUMBNAIL_JPEG; 0615 imgdata.thumbs_list.thumblist[idx].toffset = xoffset; 0616 imgdata.thumbs_list.thumblist[idx].tlength = szAtom-24; 0617 imgdata.thumbs_list.thumblist[idx].tflip = 0xffff; 0618 imgdata.thumbs_list.thumblist[idx].tmisc = (3 << 5) | 8; // 3 samples/8 bps 0619 imgdata.thumbs_list.thumblist[idx].twidth = (xdata[4] << 8) + xdata[5]; 0620 imgdata.thumbs_list.thumblist[idx].theight = (xdata[6] << 8) + xdata[7]; 0621 imgdata.thumbs_list.thumbcount++; 0622 } 0623 } 0624 } 0625 else if (!strcmp(AtomNameStack, "moovuuidCMT2")) 0626 { 0627 short q_order = order; 0628 order = get2(); 0629 if ((tL != 4) || bad_hdr()) 0630 { 0631 err = -5; 0632 goto fin; 0633 } 0634 if (!libraw_internal_data.unpacker_data.cr3_exif_length) 0635 libraw_internal_data.unpacker_data.cr3_exif_length = unsigned(szAtomContent); 0636 parse_exif(oAtomContent); 0637 order = q_order; 0638 } 0639 else if (!strcmp(AtomNameStack, "moovuuidCMT3")) 0640 { 0641 short q_order = order; 0642 order = get2(); 0643 if ((tL != 4) || bad_hdr()) 0644 { 0645 err = -6; 0646 goto fin; 0647 } 0648 fseek(ifp, -12L, SEEK_CUR); 0649 parse_makernote(oAtomContent, 0); 0650 order = q_order; 0651 } 0652 else if (!strcmp(AtomNameStack, "moovuuidCMT4")) 0653 { 0654 short q_order = order; 0655 order = get2(); 0656 if ((tL != 4) || bad_hdr()) 0657 { 0658 err = -6; 0659 goto fin; 0660 } 0661 INT64 off = ftell(ifp); 0662 parse_gps(oAtomContent); 0663 fseek(ifp, off, SEEK_SET); 0664 parse_gps_libraw(oAtomContent); 0665 order = q_order; 0666 } 0667 else if (!strcmp(AtomNameStack, "moovtrakmdiahdlr")) 0668 { 0669 fseek(ifp, 8L, SEEK_CUR); 0670 FORC4 HandlerType[c] = fgetc(ifp); 0671 for (c = 1; c < int(sizeof sHandlerType / sizeof *sHandlerType); c++) 0672 if (!strcmp(HandlerType, sHandlerType[c])) 0673 { 0674 TrackType = c; 0675 break; 0676 } 0677 } 0678 else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsd")) 0679 { 0680 if (szAtomContent >= 16) 0681 { 0682 fseek(ifp, 12L, SEEK_CUR); 0683 lHdr = 8; 0684 } 0685 else 0686 { 0687 err = -7; 0688 goto fin; 0689 } 0690 FORC4 MediaFormatID[c] = fgetc(ifp); 0691 if ((TrackType == 2) && (!strcmp(MediaFormatID, "CRAW"))) 0692 { 0693 if (szAtomContent >= 44) 0694 fseek(ifp, 24L, SEEK_CUR); 0695 else 0696 { 0697 err = -8; 0698 goto fin; 0699 } 0700 } 0701 else 0702 { 0703 AtomType = 2; // only continue for CRAW 0704 lHdr = 0; 0705 } 0706 #define current_track libraw_internal_data.unpacker_data.crx_header[nTrack] 0707 0708 /*ImageWidth =*/ get2(); 0709 /*ImageHeight =*/ get2(); 0710 } 0711 else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAW")) 0712 { 0713 lHdr = 82; 0714 } 0715 else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWCMP1")) 0716 { 0717 int read_size = szAtomContent > 85 ? 85 : szAtomContent; 0718 if (szAtomContent >= 40) 0719 fread(CMP1, 1, read_size, ifp); 0720 else 0721 { 0722 err = -7; 0723 goto fin; 0724 } 0725 if (!crxParseImageHeader(CMP1, nTrack, read_size)) 0726 current_track.MediaType = 1; 0727 } 0728 0729 else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWCDI1")) { 0730 if (szAtomContent >= 60) { 0731 fread(CDI1, 1, 60, ifp); 0732 if (!strncmp((char *)CDI1+8, "IAD1", 4) && (sgetn(8, CDI1) == 0x38)) { 0733 // sensor area at CDI1+12, 4 16-bit values 0734 // Bayer pattern? - next 4 16-bit values 0735 imCanon.RecommendedImageArea = sget_CanonArea(CDI1+12 + 2*4*2); 0736 imCanon.LeftOpticalBlack = sget_CanonArea(CDI1+12 + 3*4*2); 0737 imCanon.UpperOpticalBlack = sget_CanonArea(CDI1+12 + 4*4*2); 0738 imCanon.ActiveArea = sget_CanonArea(CDI1+12 + 5*4*2); 0739 } 0740 } 0741 } 0742 0743 else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsdCRAWJPEG")) 0744 { 0745 current_track.MediaType = 2; 0746 } 0747 else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsc")) 0748 { 0749 if (szAtomContent >= 12) { 0750 fseek(ifp, 4L, SEEK_CUR); 0751 int entries = get4(); 0752 if (entries < 1 || entries > 1000000) 0753 { 0754 err = -9; 0755 goto fin; 0756 } 0757 0758 current_track.stsc_data = (crx_sample_to_chunk_t*) malloc(entries * sizeof(crx_sample_to_chunk_t)); 0759 if(!current_track.stsc_data) 0760 { 0761 err = -9; 0762 goto fin; 0763 } 0764 current_track.stsc_count = entries; 0765 for(int i = 0; i < entries; i++) 0766 { 0767 current_track.stsc_data[i].first = get4(); 0768 current_track.stsc_data[i].count = get4(); 0769 current_track.stsc_data[i].id = get4(); 0770 } 0771 } 0772 } 0773 else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblstsz")) 0774 { 0775 if (szAtomContent >= 12) 0776 { 0777 fseek(ifp, 4L, SEEK_CUR); 0778 int sample_size = get4(); 0779 int entries = get4(); 0780 current_track.sample_count = entries; 0781 0782 // if sample size is zero sample size is fixed 0783 if (sample_size) 0784 { 0785 current_track.MediaSize = sample_size; 0786 current_track.sample_size = sample_size; 0787 } 0788 else 0789 { 0790 current_track.sample_size = 0; 0791 if (entries < 1 || entries > 1000000) { 0792 err = -10; 0793 goto fin; 0794 } 0795 current_track.sample_sizes = (int32_t*)malloc(entries * sizeof(int32_t)); 0796 if (!current_track.sample_sizes) 0797 { 0798 err = -10; 0799 goto fin; 0800 } 0801 for (int i = 0; i < entries; i++) 0802 current_track.sample_sizes[i] = get4(); 0803 0804 current_track.MediaSize = current_track.sample_sizes[0]; 0805 } 0806 } 0807 } 0808 else if (!strcmp(AtomNameStack, "moovtrakmdiaminfstblco64")) 0809 { 0810 if (szAtomContent >= 16) { 0811 fseek(ifp, 4L, SEEK_CUR); 0812 uint32_t entries = get4(); 0813 int i; 0814 if (entries < 1 || entries > 1000000) 0815 { 0816 err = -11; 0817 goto fin; 0818 } 0819 current_track.chunk_offsets = (INT64*)malloc(entries * sizeof(int64_t)); 0820 if(!current_track.chunk_offsets) 0821 { 0822 err = -11; 0823 goto fin; 0824 } 0825 0826 current_track.chunk_count = entries; 0827 for (i = 0; i < entries; i++) 0828 current_track.chunk_offsets[i] = (((int64_t)get4()) << 32) | get4(); 0829 0830 current_track.chunk_count = i; 0831 current_track.MediaOffset = current_track.chunk_offsets[0]; 0832 } 0833 } 0834 0835 if (nTrack >= 0 && nTrack < LIBRAW_CRXTRACKS_MAXCOUNT && 0836 current_track.MediaSize && current_track.MediaOffset && 0837 ((oAtom + szAtom) >= (oAtomList + szAtomList)) && 0838 !strncmp(AtomNameStack, "moovtrakmdiaminfstbl", 20)) 0839 { 0840 if ((TrackType == 4) && (!strcmp(MediaFormatID, "CTMD"))) 0841 { 0842 current_track.MediaType = 3; 0843 } 0844 } 0845 #undef current_track 0846 if (AtomType == 1) 0847 { 0848 err = parseCR3(oAtomContent + lHdr, szAtomContent - lHdr, nesting, 0849 AtomNameStack, nTrack, TrackType); 0850 if (err) 0851 goto fin; 0852 } 0853 oAtom += szAtom; 0854 } 0855 0856 fin: 0857 nesting--; 0858 if (nesting >= 0) 0859 AtomNameStack[nesting * 4] = '\0'; 0860 order = s_order; 0861 return err; 0862 } 0863 #undef bad_hdr 0864 0865 void LibRaw::parseCR3_Free() 0866 { 0867 short maxTrack = libraw_internal_data.unpacker_data.crx_track_count; 0868 if (maxTrack < 0) 0869 return; 0870 0871 for (int i = 0; i <= maxTrack && i < LIBRAW_CRXTRACKS_MAXCOUNT; i++) 0872 { 0873 crx_data_header_t *d = &libraw_internal_data.unpacker_data.crx_header[i]; 0874 if (d->stsc_data) 0875 { 0876 free(d->stsc_data); 0877 d->stsc_data = NULL; 0878 } 0879 if (d->chunk_offsets) 0880 { 0881 free(d->chunk_offsets); 0882 d->chunk_offsets = NULL; 0883 } 0884 0885 if (d->sample_sizes) 0886 { 0887 free(d->sample_sizes); 0888 d->sample_sizes = NULL; 0889 } 0890 d->stsc_count = 0; 0891 d->sample_count = 0; 0892 d->sample_size = 0; 0893 d->chunk_count = 0; 0894 } 0895 libraw_internal_data.unpacker_data.crx_track_count = -1; 0896 }