| /* -*- C++ -*- |
| * Copyright 2019-2025 LibRaw LLC (info@libraw.org) |
| * |
| LibRaw is free software; you can redistribute it and/or modify |
| it under the terms of the one of two licenses as you choose: |
| |
| 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
| (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
| |
| 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
| (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
| |
| */ |
| |
| #include "third_party/libraw/internal/dcraw_defs.h" |
| |
| void LibRaw::setLeicaBodyFeatures(int LeicaMakernoteSignature) |
| { |
| if (LeicaMakernoteSignature == -3) // M8 |
| { |
| ilm.CameraFormat = LIBRAW_FORMAT_APSH; |
| ilm.CameraMount = LIBRAW_MOUNT_Leica_M; |
| } |
| else if (LeicaMakernoteSignature == -2) // DMR |
| { |
| ilm.CameraFormat = LIBRAW_FORMAT_Leica_DMR; |
| if ((model[0] == 'R') || (model[6] == 'R')) |
| ilm.CameraMount = LIBRAW_MOUNT_Leica_R; |
| } |
| else if (LeicaMakernoteSignature == 0) // "DIGILUX 2" |
| { |
| ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens; |
| ilm.FocalType = LIBRAW_FT_ZOOM_LENS; |
| } |
| else if ((LeicaMakernoteSignature == 0x0100) || // X1 |
| (LeicaMakernoteSignature == 0x0500) || // X2, "X-E (Typ 102)" |
| (LeicaMakernoteSignature == 0x0700) || // "X (Typ 113)" |
| (LeicaMakernoteSignature == 0x1000)) // "X-U (Typ 113)" |
| { |
| ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC; |
| ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens; |
| ilm.FocalType = LIBRAW_FT_PRIME_LENS; |
| } |
| else if (LeicaMakernoteSignature == 0x0400) // "X VARIO (Typ 107)" |
| { |
| ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC; |
| ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens; |
| ilm.FocalType = LIBRAW_FT_ZOOM_LENS; |
| } |
| else if ((LeicaMakernoteSignature == |
| 0x0200) || // M10, M10-D, M10-R, "S (Typ 007)", M11, "M11 Monochrom" |
| (LeicaMakernoteSignature == |
| 0x02ff) || // "M (Typ 240)", "M (Typ 262)", "M-D (Typ 262)", |
| // "M Monochrom (Typ 246)", "S (Typ 006)", "S-E (Typ 006)", S2, S3 |
| (LeicaMakernoteSignature == |
| 0x0300)) // M9, "M9 Monochrom", "M Monochrom", M-E |
| { |
| if ((model[0] == 'M') || (model[6] == 'M')) |
| { |
| ilm.CameraFormat = LIBRAW_FORMAT_FF; |
| ilm.CameraMount = LIBRAW_MOUNT_Leica_M; |
| } |
| else if ((model[0] == 'S') || (model[6] == 'S')) |
| { |
| ilm.CameraFormat = LIBRAW_FORMAT_LeicaS; |
| ilm.CameraMount = LIBRAW_MOUNT_Leica_S; |
| } |
| } |
| else if ((LeicaMakernoteSignature == 0x0600) || // "T (Typ 701)", TL |
| (LeicaMakernoteSignature == 0x0900) || // SL2, "SL2-S", "SL (Typ 601)", CL, Q2, "Q2 MONO" |
| (LeicaMakernoteSignature == 0x0a00) || // Q3, "Q3 43", SL3 |
| (LeicaMakernoteSignature == 0x1a00)) // TL2 |
| { |
| if ((model[0] == 'S') || (model[6] == 'S')) |
| { |
| ilm.CameraFormat = LIBRAW_FORMAT_FF; |
| ilm.CameraMount = LIBRAW_MOUNT_LPS_L; |
| } |
| else if ((model[0] == 'T') || (model[6] == 'T') || |
| (model[0] == 'C') || (model[6] == 'C')) |
| { |
| ilm.CameraFormat = LIBRAW_FORMAT_APSC; |
| ilm.CameraMount = LIBRAW_MOUNT_LPS_L; |
| } |
| else if (((model[0] == 'Q') || (model[6] == 'Q')) && |
| (((model[1] == '2') || (model[7] == '2')) || |
| ((model[1] == '3') || (model[7] == '3')))) |
| { |
| ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_FF; |
| ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens; |
| ilm.FocalType = LIBRAW_FT_PRIME_LENS; |
| } |
| } |
| else if (LeicaMakernoteSignature == 0x0800) // "Q (Typ 116)" |
| { |
| ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_FF; |
| ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens; |
| ilm.FocalType = LIBRAW_FT_PRIME_LENS; |
| } |
| } |
| |
| void LibRaw::parseLeicaLensID() |
| { |
| ilm.LensID = get4(); |
| if (ilm.LensID) |
| { |
| ilm.LensID = ((ilm.LensID >> 2) << 8) | (ilm.LensID & 0x3); |
| if ((ilm.LensID > 0x00ff) && (ilm.LensID < 0x3b00)) |
| { |
| ilm.LensMount = ilm.CameraMount; |
| ilm.LensFormat = LIBRAW_FORMAT_FF; |
| } |
| } |
| } |
| |
| int LibRaw::parseLeicaLensName(unsigned len) |
| { |
| #define plln ilm.Lens |
| if (!len) |
| { |
| strcpy(plln, "N/A"); |
| return 0; |
| } |
| stmread(plln, len, ifp); |
| if ((plln[0] == ' ') || !strncasecmp(plln, "not ", 4) || |
| !strncmp(plln, "---", 3) || !strncmp(plln, "***", 3)) |
| { |
| strcpy(plln, "N/A"); |
| return 0; |
| } |
| else |
| return 1; |
| #undef plln |
| } |
| |
| int LibRaw::parseLeicaInternalBodySerial(unsigned len) |
| { |
| #define plibs imgdata.shootinginfo.InternalBodySerial |
| if (!len) |
| { |
| strcpy(plibs, "N/A"); |
| return 0; |
| } |
| stmread(plibs, len, ifp); |
| if (!strncmp(plibs, "000000000000", 12)) |
| { |
| plibs[0] = '0'; |
| plibs[1] = '\0'; |
| return 1; |
| } |
| |
| if (strnlen(plibs, len) == 13) |
| { |
| for (int i = 3; i < 13; i++) |
| { |
| if (!isdigit(plibs[i])) |
| goto non_std; |
| } |
| memcpy(plibs + 15, plibs + 9, 4); |
| memcpy(plibs + 12, plibs + 7, 2); |
| memcpy(plibs + 9, plibs + 5, 2); |
| memcpy(plibs + 6, plibs + 3, 2); |
| plibs[3] = plibs[14] = ' '; |
| plibs[8] = plibs[11] = '/'; |
| if (((short)(plibs[3] - '0') * 10 + (short)(plibs[4] - '0')) < 70) |
| { |
| memcpy(plibs + 4, "20", 2); |
| } |
| else |
| { |
| memcpy(plibs + 4, "19", 2); |
| } |
| return 2; |
| } |
| non_std: |
| #undef plibs |
| return 1; |
| } |
| |
| void LibRaw::parseLeicaMakernote(INT64 base, int uptag, unsigned MakernoteTagType) |
| { |
| int c; |
| uchar ci, cj; |
| unsigned entries, tag, type, len; |
| INT64 save; |
| short morder, sorder = order; |
| char buf[10]; |
| int LeicaMakernoteSignature = -1; |
| INT64 fsize = ifp->size(); |
| |
| memset(buf,0,sizeof(buf)); |
| fread(buf, 1, 10, ifp); |
| buf[9] = 0; |
| if (strncmp(buf, "LEICA", 5)) |
| { |
| fseek(ifp, -10, SEEK_CUR); |
| if (uptag == 0x3400) |
| LeicaMakernoteSignature = 0x3400; |
| else |
| LeicaMakernoteSignature = -2; // DMR |
| } |
| else |
| { |
| fseek(ifp, -2, SEEK_CUR); |
| LeicaMakernoteSignature = ((uchar)buf[6] << 8) | (uchar)buf[7]; |
| // printf ("LeicaMakernoteSignature 0x%04x\n", LeicaMakernoteSignature); |
| if (!LeicaMakernoteSignature && |
| (!strncmp(model, "M8", 2) || !strncmp(model + 6, "M8", 2))) |
| LeicaMakernoteSignature = -3; |
| if ((LeicaMakernoteSignature != 0x0000) && |
| (LeicaMakernoteSignature != 0x0200) && |
| (LeicaMakernoteSignature != 0x0800) && |
| (LeicaMakernoteSignature != 0x0900) && |
| (LeicaMakernoteSignature != 0x0a00) && |
| (LeicaMakernoteSignature != 0x02ff)) |
| base = ftell(ifp) - 8; |
| } |
| setLeicaBodyFeatures(LeicaMakernoteSignature); |
| |
| entries = get2(); |
| if (entries > 1000) |
| return; |
| morder = order; |
| |
| while (entries--) |
| { |
| order = morder; |
| tiff_get(base, &tag, &type, &len, &save); |
| |
| INT64 pos = ifp->tell(); |
| if (len > 8 && pos + len > 2 * fsize) |
| { |
| fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! |
| continue; |
| } |
| tag |= uptag << 16; |
| if (len > 100 * 1024 * 1024) |
| goto next; // 100Mb tag? No! |
| |
| if (callbacks.makernotes_cb) |
| { |
| INT64 _savepos = ifp->tell(); |
| callbacks.makernotes_cb(callbacks.makernotesparser_data, tag, type, len, order, ifp, base); |
| fseek(ifp, _savepos, SEEK_SET); |
| } |
| |
| if (LeicaMakernoteSignature == -3) // M8 |
| { |
| if (tag == 0x0310) |
| { |
| parseLeicaLensID(); |
| } |
| else if ((tag == 0x0313) && (fabs(ilm.CurAp) < 0.17f)) |
| { |
| ilm.CurAp = getrealf(type); |
| if (ilm.CurAp > 126.3) |
| { |
| ilm.CurAp = 0.0f; |
| } else if (fabs(aperture) < 0.17f) |
| aperture = ilm.CurAp; |
| } |
| else if (tag == 0x0320) |
| { |
| imCommon.CameraTemperature = getrealf(type); |
| } |
| } |
| else if (LeicaMakernoteSignature == -2) // DMR |
| { |
| if (tag == 0x000d) |
| { |
| FORC3 cam_mul[c] = get2(); |
| cam_mul[3] = cam_mul[1]; |
| } |
| } |
| else if (LeicaMakernoteSignature == 0) // "DIGILUX 2" |
| { |
| if (tag == 0x0007) |
| { |
| imgdata.shootinginfo.FocusMode = get2(); |
| } |
| else if (tag == 0x001a) |
| { |
| imgdata.shootinginfo.ImageStabilization = get2(); |
| } |
| } |
| else if ((LeicaMakernoteSignature == 0x0100) || // X1 |
| (LeicaMakernoteSignature == 0x0400) || // "X VARIO" |
| (LeicaMakernoteSignature == 0x0500) || // X2, "X-E (Typ 102)" |
| (LeicaMakernoteSignature == 0x0700) || // "X (Typ 113)" |
| (LeicaMakernoteSignature == 0x1000)) // "X-U (Typ 113)" |
| { |
| if (tag == 0x040d) |
| { |
| ci = fgetc(ifp); |
| cj = fgetc(ifp); |
| imgdata.shootinginfo.ExposureMode = ((ushort)ci << 8) | cj; |
| } |
| } |
| else if ((LeicaMakernoteSignature == 0x0600) || // TL, "T (Typ 701)" |
| (LeicaMakernoteSignature == 0x1a00)) // TL2 |
| { |
| if (tag == 0x040d) |
| { |
| ci = fgetc(ifp); |
| cj = fgetc(ifp); |
| imgdata.shootinginfo.ExposureMode = ((ushort)ci << 8) | cj; |
| } |
| else if (tag == 0x0303) |
| { |
| parseLeicaLensName(len); |
| } |
| } |
| else if (LeicaMakernoteSignature == 0x0200) // M10, M10-D, M10-R, "S (Typ 007)", M11, "M11 Monochrom" |
| { |
| if ((tag == 0x035a) && (fabs(ilm.CurAp) < 0.17f)) |
| { |
| ilm.CurAp = get4() / 1000.0f; |
| if (ilm.CurAp > 126.3) |
| { |
| ilm.CurAp = 0.0f; |
| } else if (fabs(aperture) < 0.17f) |
| aperture = ilm.CurAp; |
| } |
| } |
| else if (LeicaMakernoteSignature == 0x02ff) |
| // "M (Typ 240)", "M (Typ 262)", "M-D (Typ 262)" |
| // "M Monochrom (Typ 246)" |
| // "S (Typ 006)", "S-E (Typ 006)", S2, S3 |
| { |
| if (tag == 0x0303) |
| { |
| if (parseLeicaLensName(len)) |
| { |
| ilm.LensMount = ilm.CameraMount; |
| ilm.LensFormat = ilm.CameraFormat; |
| } |
| } |
| } |
| else if (LeicaMakernoteSignature == 0x0300) // M9, "M9 Monochrom", "M Monochrom", M-E |
| { |
| if (tag == 0x3400) |
| { |
| parseLeicaMakernote(base, 0x3400, MakernoteTagType); |
| } |
| } |
| else if ((LeicaMakernoteSignature == 0x0800) || // "Q (Typ 116)" |
| (LeicaMakernoteSignature == 0x0900) || // SL2, "SL2-S", "SL (Typ 601)", |
| // CL, Q2, "Q2 MONO" |
| (LeicaMakernoteSignature == 0x0a00) // Q3, "Q3 43", SL3 |
| ) |
| { |
| if ((tag == 0x0304) && (len == 1) && ((c = fgetc(ifp)) != 0) && |
| (ilm.CameraMount == LIBRAW_MOUNT_LPS_L)) |
| { |
| strcpy(ilm.Adapter, "M-Adapter L"); |
| ilm.LensMount = LIBRAW_MOUNT_Leica_M; |
| ilm.LensFormat = LIBRAW_FORMAT_FF; |
| if (c != 0xff) ilm.LensID = c * 256; |
| } |
| else if (tag == 0x0500) |
| { |
| parseLeicaInternalBodySerial(len); |
| } |
| } |
| else if (LeicaMakernoteSignature == 0x3400) // tag 0x3400 in M9, "M9 Monochrom", "M Monochrom" |
| { |
| if (tag == 0x34003402) |
| { |
| imCommon.CameraTemperature = getrealf(type); |
| } |
| else if (tag == 0x34003405) |
| { |
| parseLeicaLensID(); |
| } |
| else if ((tag == 0x34003406) && (fabs(ilm.CurAp) < 0.17f)) |
| { |
| ilm.CurAp = getrealf(type); |
| if (ilm.CurAp > 126.3) |
| { |
| ilm.CurAp = 0.0f; |
| } else if (fabs(aperture) < 0.17f) |
| aperture = ilm.CurAp; |
| } |
| } |
| |
| next: |
| fseek(ifp, save, SEEK_SET); |
| } |
| order = sorder; |
| } |