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

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/dcraw_defs.h"
0016 
0017 void LibRaw::setLeicaBodyFeatures(int LeicaMakernoteSignature)
0018 {
0019   if (LeicaMakernoteSignature == -3) // M8
0020   {
0021     ilm.CameraFormat = LIBRAW_FORMAT_APSH;
0022     ilm.CameraMount = LIBRAW_MOUNT_Leica_M;
0023   }
0024   else if (LeicaMakernoteSignature == -2) // DMR
0025   {
0026     ilm.CameraFormat = LIBRAW_FORMAT_Leica_DMR;
0027     if ((model[0] == 'R') || (model[6] == 'R'))
0028       ilm.CameraMount = LIBRAW_MOUNT_Leica_R;
0029   }
0030   else if (LeicaMakernoteSignature == 0) // "DIGILUX 2"
0031   {
0032     ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
0033     ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
0034   }
0035   else if ((LeicaMakernoteSignature == 0x0100) || // X1
0036            (LeicaMakernoteSignature == 0x0500) || // X2, "X-E (Typ 102)"
0037            (LeicaMakernoteSignature == 0x0700) || // "X (Typ 113)"
0038            (LeicaMakernoteSignature == 0x1000))   // "X-U (Typ 113)"
0039   {
0040     ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC;
0041     ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
0042     ilm.FocalType = LIBRAW_FT_PRIME_LENS;
0043   }
0044   else if (LeicaMakernoteSignature == 0x0400) // "X VARIO (Typ 107)"
0045   {
0046     ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_APSC;
0047     ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
0048     ilm.FocalType = LIBRAW_FT_ZOOM_LENS;
0049   }
0050   else if ((LeicaMakernoteSignature ==
0051             0x0200) || // M10, M10-D, M10-R, "S (Typ 007)", M11
0052            (LeicaMakernoteSignature ==
0053             0x02ff) || // "M (Typ 240)", "M (Typ 262)", "M-D (Typ 262)",
0054                        // "M Monochrom (Typ 246)", "S (Typ 006)", "S-E (Typ 006)", S2, S3
0055            (LeicaMakernoteSignature ==
0056             0x0300))   // M9, "M9 Monochrom", "M Monochrom", M-E
0057   {
0058     if ((model[0] == 'M') || (model[6] == 'M'))
0059     {
0060       ilm.CameraFormat = LIBRAW_FORMAT_FF;
0061       ilm.CameraMount = LIBRAW_MOUNT_Leica_M;
0062     }
0063     else if ((model[0] == 'S') || (model[6] == 'S'))
0064     {
0065       ilm.CameraFormat = LIBRAW_FORMAT_LeicaS;
0066       ilm.CameraMount = LIBRAW_MOUNT_Leica_S;
0067     }
0068   }
0069   else if ((LeicaMakernoteSignature == 0x0600) || // "T (Typ 701)", TL
0070            (LeicaMakernoteSignature == 0x0900) || // SL2, "SL2-S", "SL (Typ 601)", CL, Q2, "Q2 MONO"
0071            (LeicaMakernoteSignature == 0x1a00))   // TL2
0072   {
0073     if ((model[0] == 'S') || (model[6] == 'S'))
0074     {
0075       ilm.CameraFormat = LIBRAW_FORMAT_FF;
0076       ilm.CameraMount = LIBRAW_MOUNT_LPS_L;
0077     }
0078     else if ((model[0] == 'T') || (model[6] == 'T') ||
0079              (model[0] == 'C') || (model[6] == 'C'))
0080     {
0081       ilm.CameraFormat = LIBRAW_FORMAT_APSC;
0082       ilm.CameraMount = LIBRAW_MOUNT_LPS_L;
0083     }
0084     else if (((model[0] == 'Q') || (model[6] == 'Q')) &&
0085              ((model[1] == '2') || (model[7] == '2')))
0086     {
0087       ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_FF;
0088       ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
0089       ilm.FocalType = LIBRAW_FT_PRIME_LENS;
0090     }
0091   }
0092   else if (LeicaMakernoteSignature == 0x0800) // "Q (Typ 116)"
0093   {
0094     ilm.CameraFormat = ilm.LensFormat = LIBRAW_FORMAT_FF;
0095     ilm.CameraMount = ilm.LensMount = LIBRAW_MOUNT_FixedLens;
0096     ilm.FocalType = LIBRAW_FT_PRIME_LENS;
0097   }
0098 }
0099 
0100 void LibRaw::parseLeicaLensID()
0101 {
0102   ilm.LensID = get4();
0103   if (ilm.LensID)
0104   {
0105     ilm.LensID = ((ilm.LensID >> 2) << 8) | (ilm.LensID & 0x3);
0106     if ((ilm.LensID > 0x00ff) && (ilm.LensID < 0x3b00))
0107     {
0108       ilm.LensMount = ilm.CameraMount;
0109       ilm.LensFormat = LIBRAW_FORMAT_FF;
0110     }
0111   }
0112 }
0113 
0114 int LibRaw::parseLeicaLensName(unsigned len)
0115 {
0116 #define plln ilm.Lens
0117   if (!len)
0118   {
0119     strcpy(plln, "N/A");
0120     return 0;
0121   }
0122   stmread(plln, len, ifp);
0123   if ((plln[0] == ' ') || !strncasecmp(plln, "not ", 4) ||
0124       !strncmp(plln, "---", 3) || !strncmp(plln, "***", 3))
0125   {
0126     strcpy(plln, "N/A");
0127     return 0;
0128   }
0129   else
0130     return 1;
0131 #undef plln
0132 }
0133 
0134 int LibRaw::parseLeicaInternalBodySerial(unsigned len)
0135 {
0136 #define plibs imgdata.shootinginfo.InternalBodySerial
0137   if (!len)
0138   {
0139     strcpy(plibs, "N/A");
0140     return 0;
0141   }
0142   stmread(plibs, len, ifp);
0143   if (!strncmp(plibs, "000000000000", 12))
0144   {
0145     plibs[0] = '0';
0146     plibs[1] = '\0';
0147     return 1;
0148   }
0149 
0150   if (strnlen(plibs, len) == 13)
0151   {
0152     for (int i = 3; i < 13; i++)
0153     {
0154       if (!isdigit(plibs[i]))
0155         goto non_std;
0156     }
0157     memcpy(plibs + 15, plibs + 9, 4);
0158     memcpy(plibs + 12, plibs + 7, 2);
0159     memcpy(plibs + 9, plibs + 5, 2);
0160     memcpy(plibs + 6, plibs + 3, 2);
0161     plibs[3] = plibs[14] = ' ';
0162     plibs[8] = plibs[11] = '/';
0163     if (((short)(plibs[3] - '0') * 10 + (short)(plibs[4] - '0')) < 70)
0164     {
0165       memcpy(plibs + 4, "20", 2);
0166     }
0167     else
0168     {
0169       memcpy(plibs + 4, "19", 2);
0170     }
0171     return 2;
0172   }
0173 non_std:
0174 #undef plibs
0175   return 1;
0176 }
0177 
0178 void LibRaw::parseLeicaMakernote(int base, int uptag, unsigned MakernoteTagType)
0179 {
0180   int c;
0181   uchar ci, cj;
0182   unsigned entries, tag, type, len, save;
0183   short morder, sorder = order;
0184   char buf[10];
0185   int LeicaMakernoteSignature = -1;
0186   INT64 fsize = ifp->size();
0187 
0188   fread(buf, 1, 10, ifp);
0189   if (strncmp(buf, "LEICA", 5))
0190   {
0191     fseek(ifp, -10, SEEK_CUR);
0192     if (uptag == 0x3400)
0193       LeicaMakernoteSignature = 0x3400;
0194     else
0195       LeicaMakernoteSignature = -2; // DMR
0196   }
0197   else
0198   {
0199     fseek(ifp, -2, SEEK_CUR);
0200     LeicaMakernoteSignature = ((uchar)buf[6] << 8) | (uchar)buf[7];
0201     // printf ("LeicaMakernoteSignature 0x%04x\n", LeicaMakernoteSignature);
0202     if (!LeicaMakernoteSignature &&
0203         (!strncmp(model, "M8", 2) || !strncmp(model + 6, "M8", 2)))
0204       LeicaMakernoteSignature = -3;
0205     if ((LeicaMakernoteSignature != 0x0000) &&
0206         (LeicaMakernoteSignature != 0x0200) &&
0207         (LeicaMakernoteSignature != 0x0800) &&
0208         (LeicaMakernoteSignature != 0x0900) &&
0209         (LeicaMakernoteSignature != 0x02ff))
0210       base = ftell(ifp) - 8;
0211   }
0212   setLeicaBodyFeatures(LeicaMakernoteSignature);
0213 
0214   entries = get2();
0215   if (entries > 1000)
0216     return;
0217   morder = order;
0218 
0219   while (entries--)
0220   {
0221     order = morder;
0222     tiff_get(base, &tag, &type, &len, &save);
0223 
0224     INT64 pos = ifp->tell();
0225     if (len > 8 && pos + len > 2 * fsize)
0226     {
0227       fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
0228       continue;
0229     }
0230     tag |= uptag << 16;
0231     if (len > 100 * 1024 * 1024)
0232       goto next; // 100Mb tag? No!
0233 
0234     if (LeicaMakernoteSignature == -3) // M8
0235     {
0236       if (tag == 0x0310)
0237       {
0238         parseLeicaLensID();
0239       }
0240       else if ((tag == 0x0313) && (fabs(ilm.CurAp) < 0.17f))
0241       {
0242         ilm.CurAp = getreal(type);
0243         if (ilm.CurAp > 126.3)
0244         {
0245           ilm.CurAp = 0.0f;
0246         } else if (fabs(aperture) < 0.17f)
0247            aperture = ilm.CurAp;
0248       }
0249       else if (tag == 0x0320)
0250       {
0251         imCommon.CameraTemperature = getreal(type);
0252       }
0253     }
0254     else if (LeicaMakernoteSignature == -2) // DMR
0255     {
0256       if (tag == 0x000d)
0257       {
0258         FORC3 cam_mul[c] = get2();
0259         cam_mul[3] = cam_mul[1];
0260       }
0261     }
0262     else if (LeicaMakernoteSignature == 0) // "DIGILUX 2"
0263     {
0264       if (tag == 0x0007)
0265       {
0266         imgdata.shootinginfo.FocusMode = get2();
0267       }
0268       else if (tag == 0x001a)
0269       {
0270         imgdata.shootinginfo.ImageStabilization = get2();
0271       }
0272     }
0273     else if ((LeicaMakernoteSignature == 0x0100) || // X1
0274              (LeicaMakernoteSignature == 0x0400) || // "X VARIO"
0275              (LeicaMakernoteSignature == 0x0500) || // X2, "X-E (Typ 102)"
0276              (LeicaMakernoteSignature == 0x0700) || // "X (Typ 113)"
0277              (LeicaMakernoteSignature == 0x1000))   // "X-U (Typ 113)"
0278     {
0279       if (tag == 0x040d)
0280       {
0281         ci = fgetc(ifp);
0282         cj = fgetc(ifp);
0283         imgdata.shootinginfo.ExposureMode = ((ushort)ci << 8) | cj;
0284       }
0285     }
0286     else if ((LeicaMakernoteSignature == 0x0600) || // TL, "T (Typ 701)"
0287              (LeicaMakernoteSignature == 0x1a00))   // TL2
0288     {
0289       if (tag == 0x040d)
0290       {
0291         ci = fgetc(ifp);
0292         cj = fgetc(ifp);
0293         imgdata.shootinginfo.ExposureMode = ((ushort)ci << 8) | cj;
0294       }
0295       else if (tag == 0x0303)
0296       {
0297         parseLeicaLensName(len);
0298       }
0299     }
0300     else if (LeicaMakernoteSignature == 0x0200) // M10, M10-D, M10-R, "S (Typ 007)", M11
0301     {
0302       if ((tag == 0x035a) && (fabs(ilm.CurAp) < 0.17f))
0303       {
0304         ilm.CurAp = get4() / 1000.0f;
0305         if (ilm.CurAp > 126.3)
0306         {
0307           ilm.CurAp = 0.0f;
0308         } else if (fabs(aperture) < 0.17f)
0309            aperture = ilm.CurAp;
0310       }
0311     }
0312     else if (LeicaMakernoteSignature == 0x02ff)
0313                      // "M (Typ 240)", "M (Typ 262)", "M-D (Typ 262)"
0314                      // "M Monochrom (Typ 246)"
0315                      // "S (Typ 006)", "S-E (Typ 006)", S2, S3
0316     {
0317       if (tag == 0x0303)
0318       {
0319         if (parseLeicaLensName(len))
0320         {
0321           ilm.LensMount = ilm.CameraMount;
0322           ilm.LensFormat = ilm.CameraFormat;
0323         }
0324       }
0325     }
0326     else if (LeicaMakernoteSignature == 0x0300) // M9, "M9 Monochrom", "M Monochrom", M-E
0327     {
0328       if (tag == 0x3400)
0329       {
0330         parseLeicaMakernote(base, 0x3400, MakernoteTagType);
0331       }
0332     }
0333     else if ((LeicaMakernoteSignature == 0x0800) || // "Q (Typ 116)"
0334              (LeicaMakernoteSignature == 0x0900))   // SL2, "SL2-S", "SL (Typ 601)",
0335                                                     // CL, Q2, "Q2 MONO"
0336     {
0337       if ((tag == 0x0304) && (len == 1) && ((c = fgetc(ifp)) != 0) &&
0338           (ilm.CameraMount == LIBRAW_MOUNT_LPS_L))
0339       {
0340         strcpy(ilm.Adapter, "M-Adapter L");
0341         ilm.LensMount = LIBRAW_MOUNT_Leica_M;
0342         ilm.LensFormat = LIBRAW_FORMAT_FF;
0343         if (c != 0xff) ilm.LensID = c * 256;
0344       }
0345       else if (tag == 0x0500)
0346       {
0347         parseLeicaInternalBodySerial(len);
0348       }
0349     }
0350     else if (LeicaMakernoteSignature == 0x3400) // tag 0x3400 in M9, "M9 Monochrom", "M Monochrom"
0351     {
0352       if (tag == 0x34003402)
0353       {
0354         imCommon.CameraTemperature = getreal(type);
0355       }
0356       else if (tag == 0x34003405)
0357       {
0358         parseLeicaLensID();
0359       }
0360       else if ((tag == 0x34003406) && (fabs(ilm.CurAp) < 0.17f))
0361       {
0362         ilm.CurAp = getreal(type);
0363         if (ilm.CurAp > 126.3)
0364         {
0365           ilm.CurAp = 0.0f;
0366         } else if (fabs(aperture) < 0.17f)
0367            aperture = ilm.CurAp;
0368       }
0369     }
0370 
0371   next:
0372     fseek(ifp, save, SEEK_SET);
0373   }
0374   order = sorder;
0375 }