Commit message: parse_qt: possible integer overflow
CVE: CVE-2018-5815
CWE: CWE-190
Vulnerability description: An integer overflow error within the "parse_qt()" function (internal/dcraw_common.cpp) in LibRaw versions prior to 0.18.12 can be exploited to trigger an infinite loop via a specially crafted Apple QuickTime file.

Project: LibRaw
File: dcraw.c

void CLASS parse_ciff (int offset, int length, int depth)
{
  int tboff, nrecs, c, type, len, save, wbi=-1;
  ushort key[] = { 0x410, 0x45f3 };

  fseek (ifp, offset+length-4, SEEK_SET);
  tboff = get4() + offset;
  fseek (ifp, tboff, SEEK_SET);
  nrecs = get2();
  if ((nrecs | depth) > 127) return;
  while (nrecs--) {
    type = get2();
    len  = get4();
    save = ftell(ifp) + 4;
    fseek (ifp, offset+get4(), SEEK_SET);
    if ((((type >> 8) + 8) | 8) == 0x38) {
      parse_ciff (ftell(ifp), len, depth+1); /* Parse a sub-table */
    }
#ifdef LIBRAW_LIBRARY_BUILD
    if (type == 0x3004) parse_ciff (ftell(ifp), len, depth+1);
#endif
    if (type == 0x0810)
      fread (artist, 64, 1, ifp);
    if (type == 0x080a) {
      fread (make, 64, 1, ifp);
      fseek (ifp, strbuflen(make) - 63, SEEK_CUR);
      fread (model, 64, 1, ifp);
    }
    if (type == 0x1810) {
      width = get4();
      height = get4();
      pixel_aspect = int_to_float(get4());
      flip = get4();
    }
    if (type == 0x1835)			/* Get the decoder table */
      tiff_compress = get4();
    if (type == 0x2007) {
      thumb_offset = ftell(ifp);
      thumb_length = len;
    }
    if (type == 0x1818) {
      shutter = libraw_powf64(2.0f, -int_to_float((get4(),get4())));
      aperture = libraw_powf64(2.0f, int_to_float(get4())/2);
#ifdef LIBRAW_LIBRARY_BUILD
      imgdata.lens.makernotes.CurAp = aperture;
#endif
    }
    if (type == 0x102a) {
//      iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50;
      iso_speed = libraw_powf64(2.0f, ((get2(),get2()) + get2())/32.0f - 5.0f) * 100.0f;
#ifdef LIBRAW_LIBRARY_BUILD
      aperture  = _CanonConvertAperture((get2(),get2()));
      imgdata.lens.makernotes.CurAp = aperture;
#else
      aperture  = libraw_powf64(2.0, (get2(),(short)get2())/64.0);
#endif
      shutter   = libraw_powf64(2.0,-((short)get2())/32.0);
      wbi = (get2(),get2());
      if (wbi > 17) wbi = 0;
      fseek (ifp, 32, SEEK_CUR);
      if (shutter > 1e6) shutter = get2()/10.0;
    }
    if (type == 0x102c) {
      if (get2() > 512) {		/* Pro90, G1 */
	fseek (ifp, 118, SEEK_CUR);
	FORC4 cam_mul[c ^ 2] = get2();
      } else {				/* G2, S30, S40 */
	fseek (ifp, 98, SEEK_CUR);
	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2();
      }
    }
#ifdef LIBRAW_LIBRARY_BUILD
    if (type == 0x10a9)
      {
	INT64 o = ftell(ifp);
	fseek (ifp, (0x5<<1), SEEK_CUR);
	Canon_WBpresets(0,0);
	fseek(ifp,o,SEEK_SET);
      }
    if (type == 0x102d)
      {
	INT64 o = ftell(ifp);
	Canon_CameraSettings();
	fseek(ifp,o,SEEK_SET);
      }
    if (type == 0x580b)
      {
        if (strcmp(model,"Canon EOS D30")) sprintf(imgdata.shootinginfo.BodySerial, "%d", len);
        else sprintf(imgdata.shootinginfo.BodySerial, "%0x-%05d", len>>16, len&0xffff);
      }
#endif
    if (type == 0x0032) {
      if (len == 768) {			/* EOS D30 */
	fseek (ifp, 72, SEEK_CUR);
        FORC4
        {
          ushort q = get2();
          cam_mul[c ^ (c >> 1)] = q? 1024.0 / get2() : 1024;
        }
	if (!wbi) cam_mul[0] = -1;	/* use my auto white balance */
      } else if (!cam_mul[0]) {
	if (get2() == key[0])		/* Pro1, G6, S60, S70 */
	  c = (strstr(model,"Pro1") ?
	      "012346000000000000":"01345:000000006008")[LIM(0,wbi,17)]-'0'+ 2;
	else {				/* G3, G5, S45, S50 */
	  c = "023457000000006000"[LIM(0,wbi,17)]-'0';
	  key[0] = key[1] = 0;
	}
	fseek (ifp, 78 + c*8, SEEK_CUR);
	FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1];
	if (!wbi) cam_mul[0] = -1;
      }
    }
    if (type == 0x10a9) {		/* D60, 10D, 300D, and clones */
      if (len > 66) wbi = "0134567028"[LIM(0,wbi,9)]-'0';
      fseek (ifp, 2 + wbi*8, SEEK_CUR);
      FORC4 cam_mul[c ^ (c >> 1)] = get2();
    }
    if (type == 0x1030 && wbi>=0 && (0x18040 >> wbi & 1))
      ciff_block_1030();		/* all that don't have 0x10a9 */
    if (type == 0x1031) {
      raw_width = (get2(),get2());
      raw_height = get2();
    }
    if (type == 0x501c) {
      iso_speed = len & 0xffff;
    }
    if (type == 0x5029) {
#ifdef LIBRAW_LIBRARY_BUILD
      imgdata.lens.makernotes.CurFocal  = len >> 16;
      imgdata.lens.makernotes.FocalType = len & 0xffff;
      if (imgdata.lens.makernotes.FocalType == 2) {
        imgdata.lens.makernotes.CanonFocalUnits = 32;
	if(imgdata.lens.makernotes.CanonFocalUnits>1)
	  imgdata.lens.makernotes.CurFocal /= (float)imgdata.lens.makernotes.CanonFocalUnits;
      }
      focal_len = imgdata.lens.makernotes.CurFocal;
#else
      focal_len = len >> 16;
      if ((len & 0xffff) == 2) focal_len /= 32;
#endif
    }
    if (type == 0x5813) flash_used = int_to_float(len);
    if (type == 0x5814) canon_ev   = int_to_float(len);
    if (type == 0x5817) shot_order = len;
    if (type == 0x5834)
      {
         unique_id  = len;
#ifdef LIBRAW_LIBRARY_BUILD
         setCanonBodyFeatures(unique_id);
#endif
      }
    if (type == 0x580e) timestamp  = len;
    if (type == 0x180e) timestamp  = get4();
#ifdef LOCALTIME
    if ((type | 0x4000) == 0x580e)
      timestamp = mktime (gmtime (&timestamp));
#endif
    fseek (ifp, save, SEEK_SET);
  }
}

Project: LibRaw
File: dcraw.c

void CLASS read_shorts (ushort *pixel, unsigned count)
{
  if (fread (pixel, 2, count, ifp) < count) derror();
  if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
    swab ((char*)pixel, (char*)pixel, count*2);
}

Project: LibRaw
File: dcraw.c

static float _CanonConvertAperture(ushort in)
{
  if ((in == (ushort)0xffe0) || (in == (ushort)0x7fff)) return 0.0f;
  return libraw_powf64(2.0, in/64.0);
}

Project: LibRaw
File: dcraw.c

void CLASS parse_makernote_0xc634(int base, int uptag, unsigned dng_writer)
{
  unsigned ver97 = 0, offset = 0, entries, tag, type, len, save, c;
  unsigned i;

  uchar NikonKey, ci, cj, ck;
  unsigned serial = 0;
  unsigned custom_serial = 0;
  unsigned NikonLensDataVersion = 0;
  unsigned lenNikonLensData = 0;
  unsigned NikonFlashInfoVersion = 0;

  uchar *CanonCameraInfo;
  unsigned lenCanonCameraInfo = 0;

  uchar *table_buf;
  uchar *table_buf_0x9050;
  ushort table_buf_0x9050_present = 0;
  uchar *table_buf_0x940c;
  ushort table_buf_0x940c_present = 0;

  short morder, sorder = order;
  char buf[10];
  INT64 fsize = ifp->size();

  fread(buf, 1, 10, ifp);
  if (!strcmp(buf, "Nikon")) {
    base = ftell(ifp);
    order = get2();
    if (get2() != 42) goto quit;
    offset = get4();
    fseek(ifp, offset - 8, SEEK_CUR);
  }
  else if (!strcmp(buf, "OLYMPUS") ||
           !strcmp(buf, "PENTAX ") ||
           (!strncmp(make, "SAMSUNG", 7) && (dng_writer == CameraDNG))) {
    base = ftell(ifp) - 10;
    fseek(ifp, -2, SEEK_CUR);
    order = get2();
    if (buf[0] == 'O') get2();
  }
  else if (!strncmp(buf, "SONY", 4) ||
           !strcmp(buf, "Panasonic")) {
    goto nf;
  }
  else if (!strncmp(buf, "FUJIFILM", 8)) {
    base = ftell(ifp) - 10;
  nf: order = 0x4949;
    fseek(ifp, 2, SEEK_CUR);
  }
  else if (!strcmp(buf, "OLYMP") ||
           !strcmp(buf, "LEICA") ||
           !strcmp(buf, "Ricoh") ||
           !strcmp(buf, "EPSON"))
    fseek(ifp, -2, SEEK_CUR);
  else if (!strcmp(buf, "AOC") ||
           !strcmp(buf, "QVC"))
    fseek(ifp, -4, SEEK_CUR);
  else {
    fseek(ifp, -10, SEEK_CUR);
    if ((!strncmp(make, "SAMSUNG", 7) &&
				(dng_writer == AdobeDNG)))
      base = ftell(ifp);
  }

  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) continue;
    tag |= uptag << 16;
    if(len > 100*1024*1024) goto next; // 100Mb tag? No!

    if (!strncmp(make, "Canon",5))
      {
        if (tag == 0x000d && len < 256000) // camera info
          {
            CanonCameraInfo = (uchar*)malloc(MAX(16,len));
            fread(CanonCameraInfo, len, 1, ifp);
            lenCanonCameraInfo = len;
          }

        else if (tag == 0x10)	 // Canon ModelID
          {
            unique_id = get4();
            if (unique_id == 0x03740000) unique_id = 0x80000374;	// M3
            if (unique_id == 0x03840000) unique_id = 0x80000384;	// M10
            if (unique_id == 0x03940000) unique_id = 0x80000394;	// M5
            setCanonBodyFeatures(unique_id);
            if (lenCanonCameraInfo)
              {
                processCanonCameraInfo(unique_id, CanonCameraInfo,lenCanonCameraInfo);
                free(CanonCameraInfo);
                CanonCameraInfo = 0;
                lenCanonCameraInfo = 0;
              }
          }

        else parseCanonMakernotes (tag, type, len);
      }

    else if (!strncmp(make, "FUJI", 4))
      parseFujiMakernotes (tag, type);

    else if (!strncasecmp(make, "LEICA", 5))
      {
        if (((tag == 0x035e) || (tag == 0x035f)) && (type == 10) && (len == 9))
        {
          int ind = tag == 0x035e?0:1;
	      for (int j=0; j < 3; j++)
	       FORCC imgdata.color.dng_color[ind].forwardmatrix[j][c]= getreal(type);
        }
        if ((tag == 0x0303) && (type != 4))
          {
            stmread(imgdata.lens.makernotes.Lens, len,ifp);
          }

        if ((tag == 0x3405) ||
            (tag == 0x0310) ||
            (tag == 0x34003405))
          {
            imgdata.lens.makernotes.LensID = get4();
            imgdata.lens.makernotes.LensID =
              ((imgdata.lens.makernotes.LensID>>2)<<8) |
              (imgdata.lens.makernotes.LensID & 0x3);
            if (imgdata.lens.makernotes.LensID != -1)
              {
                if ((model[0] == 'M') ||
                    !strncasecmp (model, "LEICA M", 7))
                  {
                    imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_M;
                    if (imgdata.lens.makernotes.LensID)
                      imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_M;
                  }
                else if ((model[0] == 'S') ||
                         !strncasecmp (model, "LEICA S", 7))
                  {
                    imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_S;
                    if (imgdata.lens.makernotes.Lens[0])
                      imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_S;
                  }
              }
          }

        else if (
                 ((tag == 0x0313) || (tag == 0x34003406)) &&
                 (fabs(imgdata.lens.makernotes.CurAp) < 0.17f) &&
                 ((type == 10) || (type == 5))
                )
          {
            imgdata.lens.makernotes.CurAp = getreal(type);
            if (imgdata.lens.makernotes.CurAp > 126.3)
              imgdata.lens.makernotes.CurAp = 0.0f;
          }

        else if (tag == 0x3400)
          {
            parse_makernote (base, 0x3400);
          }
      }

    else if (!strncmp(make, "NIKON", 5))
      {
        if (tag == 0x1d)							// serial number
          while ((c = fgetc(ifp)) && c != EOF)
          {
            if ((!custom_serial) && (!isdigit(c)))
            {
              if ((strbuflen(model) == 3) && (!strcmp(model,"D50")))
              {
                custom_serial = 34;
              }
              else
              {
                custom_serial = 96;
              }
            }
            serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
          }
        else if (tag == 0x000a)
          {
            imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens;
            imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
          }
        else if (tag == 0x0082)				// lens attachment
          {
            stmread(imgdata.lens.makernotes.Attachment, len, ifp);
          }
        else if (tag == 0x0083)				// lens type
          {
            imgdata.lens.nikon.NikonLensType = fgetc(ifp);
          }
        else if (tag == 0x0084)				// lens
          {
            imgdata.lens.makernotes.MinFocal = getreal(type);
            imgdata.lens.makernotes.MaxFocal = getreal(type);
            imgdata.lens.makernotes.MaxAp4MinFocal = getreal(type);
            imgdata.lens.makernotes.MaxAp4MaxFocal = getreal(type);
          }
        else if (tag == 0x008b)				// lens f-stops
          {
            uchar a, b, c;
            a = fgetc(ifp);
            b = fgetc(ifp);
            c = fgetc(ifp);
            if (c)
              {
                imgdata.lens.nikon.NikonLensFStops = a*b*(12/c);
                imgdata.lens.makernotes.LensFStops =
                  (float)imgdata.lens.nikon.NikonLensFStops /12.0f;
              }
          }
        else if (tag == 0x0093)
          {
            i = get2();
            if ((i == 7) || (i == 9))
            {
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens;
              imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
            }
          }
        else if (tag == 0x0097)
          {
            for (i=0; i < 4; i++)
	            ver97 = ver97 * 10 + fgetc(ifp)-'0';
	          if (ver97 == 601)  // Coolpix A
	          {
	            imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens;
                    imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
	          }
	        }
        else if (tag == 0x0098)				// contains lens data
          {
            for (i = 0; i < 4; i++)
              {
                NikonLensDataVersion = NikonLensDataVersion * 10 + fgetc(ifp) - '0';
              }
            switch (NikonLensDataVersion)
              {
              case 100: lenNikonLensData = 9; break;
              case 101:
              case 201:	// encrypted, starting from v.201
              case 202:
              case 203: lenNikonLensData = 15; break;
              case 204: lenNikonLensData = 16; break;
              case 400: lenNikonLensData = 459; break;
              case 401: lenNikonLensData = 590; break;
              case 402: lenNikonLensData = 509; break;
              case 403: lenNikonLensData = 879; break;
              }
            if(lenNikonLensData)
              {
                table_buf = (uchar*)malloc(lenNikonLensData);
                fread(table_buf, lenNikonLensData, 1, ifp);
                if ((NikonLensDataVersion < 201) && lenNikonLensData)
                  {
                    processNikonLensData(table_buf, lenNikonLensData);
                    free(table_buf);
                    lenNikonLensData = 0;
                  }
              }
          }

        else if (tag == 0xa7)					// shutter count
          {
            NikonKey = fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp);
            if ((NikonLensDataVersion > 200) && lenNikonLensData)
            {
              if (custom_serial)
              {
                ci = xlat[0][custom_serial];
              }
              else
              {
                ci = xlat[0][serial & 0xff];
              }
              cj = xlat[1][NikonKey];
              ck = 0x60;
              for (i = 0; i < lenNikonLensData; i++)
                table_buf[i] ^= (cj += ci * ck++);
              processNikonLensData(table_buf, lenNikonLensData);
              lenNikonLensData = 0;
              free(table_buf);
            }
          }
        else if (tag == 0x00a8)		// contains flash data
          {
          	for (i = 0; i < 4; i++)
              {
                NikonFlashInfoVersion = NikonFlashInfoVersion * 10 + fgetc(ifp) - '0';
              }
          }

        else if (tag == 37 && (!iso_speed || iso_speed == 65535))
          {
            unsigned char cc;
            fread(&cc, 1, 1, ifp);
            iso_speed = (int)(100.0 * libraw_powf64(2.0, (double)(cc) / 12.0 - 5.0));
            break;
          }
      }

    else if (!strncmp(make, "OLYMPUS", 7))
      {
        int SubDirOffsetValid =
              strncmp (model, "E-300", 5) &&
              strncmp (model, "E-330", 5) &&
              strncmp (model, "E-400", 5) &&
              strncmp (model, "E-500", 5) &&
              strncmp (model, "E-1", 3);

        if ((tag == 0x2010) || (tag == 0x2020))
          {
            fseek(ifp, save - 4, SEEK_SET);
            fseek(ifp, base + get4(), SEEK_SET);
            parse_makernote_0xc634(base, tag, dng_writer);
          }
        if (!SubDirOffsetValid &&
            ((len > 4) ||
             ( ((type == 3) || (type == 8)) && (len > 2))  ||
             ( ((type == 4) || (type == 9)) && (len > 1))  || (type == 5) || (type > 9)))
        goto skip_Oly_broken_tags;

        switch (tag) {
        case 0x0207:
        case 0x20100100:
          {
            uchar sOlyID[8];
            unsigned long long OlyID;
            fread (sOlyID, MIN(len,7), 1, ifp);
	    sOlyID[7] = 0;
            OlyID = sOlyID[0];
            i = 1;
            while (i < 7 && sOlyID[i])
              {
                OlyID = OlyID << 8 | sOlyID[i];
                i++;
              }
            setOlympusBodyFeatures(OlyID);
          }
          break;
        case 0x1002:
          imgdata.lens.makernotes.CurAp = libraw_powf64(2.0f, getreal(type)/2);
          break;
        case 0x20100102:
            stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp);
        break;
        case 0x20100201:
          imgdata.lens.makernotes.LensID =
            (unsigned long long)fgetc(ifp)<<16 |
            (unsigned long long)(fgetc(ifp), fgetc(ifp))<<8 |
            (unsigned long long)fgetc(ifp);
          imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FT;
          imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_FT;
          if (((imgdata.lens.makernotes.LensID < 0x20000) ||
               (imgdata.lens.makernotes.LensID > 0x4ffff)) &&
              (imgdata.lens.makernotes.LensID & 0x10))
            {
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_mFT;
            }
          break;
        case 0x20100202:
          if ((!imgdata.lens.LensSerial[0]))
              stmread(imgdata.lens.LensSerial, len, ifp);
          break;
        case 0x20100203:
          stmread(imgdata.lens.makernotes.Lens,len, ifp);
          break;
        case 0x20100205:
          imgdata.lens.makernotes.MaxAp4MinFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f);
          break;
        case 0x20100206:
          imgdata.lens.makernotes.MaxAp4MaxFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f);
          break;
        case 0x20100207:
          imgdata.lens.makernotes.MinFocal = (float)get2();
          break;
        case 0x20100208:
          imgdata.lens.makernotes.MaxFocal = (float)get2();
          if (imgdata.lens.makernotes.MaxFocal > 1000.0f)
            imgdata.lens.makernotes.MaxFocal = imgdata.lens.makernotes.MinFocal;
          break;
        case 0x2010020a:
          imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f);
          break;
        case 0x20100301:
          imgdata.lens.makernotes.TeleconverterID = fgetc(ifp) << 8;
          fgetc(ifp);
          imgdata.lens.makernotes.TeleconverterID =
            imgdata.lens.makernotes.TeleconverterID | fgetc(ifp);
          break;
        case 0x20100303:
          stmread(imgdata.lens.makernotes.Teleconverter, len, ifp);
          break;
        case 0x20100403:
          stmread(imgdata.lens.makernotes.Attachment,len, ifp);
          break;
        case 0x20200401:
	      imgdata.other.FlashEC = getreal(type);
	      break;
        }
        skip_Oly_broken_tags:;
      }

    else if (!strncmp(make, "PENTAX", 6) ||
             !strncmp(model, "PENTAX", 6) ||
             (!strncmp(make, "SAMSUNG", 7) && (dng_writer == CameraDNG)))
      {
        if (tag == 0x0005)
          {
            unique_id = get4();
            setPentaxBodyFeatures(unique_id);
          }
        else if (tag == 0x0013)
          {
            imgdata.lens.makernotes.CurAp = (float)get2()/10.0f;
          }
        else if (tag == 0x0014)
          {
            PentaxISO(get2());
          }
        else if (tag == 0x001d)
          {
            imgdata.lens.makernotes.CurFocal = (float)get4()/100.0f;
          }
        else if (tag == 0x003f)
          {
            imgdata.lens.makernotes.LensID = fgetc(ifp) << 8 | fgetc(ifp);
          }
        else if (tag == 0x004d)
          {
            if (type == 9) imgdata.other.FlashEC = getreal(type) / 256.0f;
            else imgdata.other.FlashEC = (float) ((signed short) fgetc(ifp)) / 6.0f;
          }
         else if (tag == 0x007e)
           {
             imgdata.color.linear_max[0] =
             imgdata.color.linear_max[1] =
             imgdata.color.linear_max[2] =
             imgdata.color.linear_max[3] = (long)(-1) * get4();
           }
        else if (tag == 0x0207)
          {
	    if(len < 65535) // Safety belt
               PentaxLensInfo(imgdata.lens.makernotes.CamID, len);
          }
        else if (tag == 0x020d)
        {
                FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x020e)
        {
                FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x020f)
        {
                FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0210)
        {
                FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0211)
        {
                FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0212)
        {
                FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0213)
        {
                FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0214)
        {
                FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0221)
        {
	  int nWB = get2();
	  if(nWB<=sizeof(imgdata.color.WBCT_Coeffs)/sizeof(imgdata.color.WBCT_Coeffs[0]))
	     for (int i = 0; i < nWB; i++)
	       {
		 imgdata.color.WBCT_Coeffs[i][0] = (unsigned)0xcfc6 - get2();
		 fseek(ifp, 2, SEEK_CUR);
		 imgdata.color.WBCT_Coeffs[i][1] = get2();
		 imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 0x2000;
		 imgdata.color.WBCT_Coeffs[i][3] = get2();
        	}
        }
        else if (tag == 0x0215)
        {
          fseek (ifp, 16, SEEK_CUR);
          sprintf(imgdata.shootinginfo.InternalBodySerial, "%d", get4());
        }
        else if (tag == 0x0229)
        {
          stmread(imgdata.shootinginfo.BodySerial, len, ifp);
        }
        else if (tag == 0x022d)
        {
	  fseek (ifp,2,SEEK_CUR);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0239)		// Q-series lens info (LensInfoQ)
          {
            char LensInfo [20];
            fseek (ifp, 12, SEEK_CUR);
            stread(imgdata.lens.makernotes.Lens, 30, ifp);
            strcat(imgdata.lens.makernotes.Lens, " ");
            stread(LensInfo, 20, ifp);
            strcat(imgdata.lens.makernotes.Lens, LensInfo);
          }
      }

    else if (!strncmp(make, "SAMSUNG", 7) &&
             (dng_writer == AdobeDNG))
      {
        if (tag == 0x0002)
          {
            if(get4() == 0x2000)
              {
                imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX;
              }
            else if (!strncmp(model, "NX mini", 7))
              {
                imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX_M;
              }
            else
              {
                imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
                imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens;
              }
          }
        else if (tag == 0x0003)
          {
            imgdata.lens.makernotes.CamID = unique_id = get4();
          }
        else if (tag == 0xa003)
          {
            imgdata.lens.makernotes.LensID = get2();
            if (imgdata.lens.makernotes.LensID)
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Samsung_NX;
          }
        else if (tag == 0xa005)
          {
            stmread(imgdata.lens.InternalLensSerial, len, ifp);
          }
        else if (tag == 0xa019)
          {
            imgdata.lens.makernotes.CurAp = getreal(type);
          }
        else if (tag == 0xa01a)
          {
            imgdata.lens.makernotes.FocalLengthIn35mmFormat = get4() / 10.0f;
            if (imgdata.lens.makernotes.FocalLengthIn35mmFormat < 10.0f)
              imgdata.lens.makernotes.FocalLengthIn35mmFormat *= 10.0f;
          }
      }

    else if (!strncasecmp(make, "SONY", 4) ||
             !strncasecmp(make, "Konica", 6) ||
             !strncasecmp(make, "Minolta", 7) ||
             (!strncasecmp(make, "Hasselblad", 10) &&
              (!strncasecmp(model, "Stellar", 7) ||
               !strncasecmp(model, "Lunar", 5) ||
               !strncasecmp(model, "Lusso", 5) ||
               !strncasecmp(model, "HV",2))))
      {
        ushort lid;

        if (tag == 0xb001)			// Sony ModelID
          {
            unique_id = get2();
            setSonyBodyFeatures(unique_id);
            if (table_buf_0x9050_present)
              {
                process_Sony_0x9050(table_buf_0x9050, unique_id);
                free (table_buf_0x9050);
                table_buf_0x9050_present = 0;
              }
            if (table_buf_0x940c_present)
              {
                if (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E)
                  {
                    process_Sony_0x940c(table_buf_0x940c);
                  }
                free (table_buf_0x940c);
                table_buf_0x940c_present = 0;
              }
          }
        else if ((tag == 0x0010) &&					// CameraInfo
                 strncasecmp(model, "DSLR-A100", 9) &&
                 strncasecmp(model, "NEX-5C", 6) &&
                 !strncasecmp(make, "SONY", 4) &&
                 ((len == 368) ||			// a700
                  (len == 5478) ||		// a850, a900
                  (len == 5506) ||		// a200, a300, a350
                  (len == 6118) ||		// a230, a290, a330, a380, a390

                  // a450, a500, a550, a560, a580
                  // a33, a35, a55
                  // NEX3, NEX5, NEX5C, NEXC3, VG10E
                  (len == 15360))
                 )
          {
            table_buf = (uchar*)malloc(len);
            fread(table_buf, len, 1, ifp);
            if (memcmp(table_buf, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) &&
                memcmp(table_buf, "\x00\x00\x00\x00\x00\x00\x00\x00", 8))
              {
                switch (len) {
                case 368:
                case 5478:
                  // a700, a850, a900: CameraInfo
                  if (saneSonyCameraInfo(table_buf[0], table_buf[3], table_buf[2], table_buf[5], table_buf[4], table_buf[7]))
                    {
                      if (table_buf[0] | table_buf[3])
                        imgdata.lens.makernotes.MinFocal =
                          bcd2dec(table_buf[0]) * 100 + bcd2dec(table_buf[3]);
                      if (table_buf[2] | table_buf[5])
                        imgdata.lens.makernotes.MaxFocal =
                          bcd2dec(table_buf[2]) * 100 + bcd2dec(table_buf[5]);
                      if (table_buf[4])
                        imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[4]) / 10.0f;
                      if (table_buf[4])
                        imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[7]) / 10.0f;
                      parseSonyLensFeatures(table_buf[1], table_buf[6]);
                    }
                  break;
                default:
                  // CameraInfo2 & 3
                  if (saneSonyCameraInfo(table_buf[1], table_buf[2], table_buf[3], table_buf[4], table_buf[5], table_buf[6]))
                    {
                      if (table_buf[1] | table_buf[2])
                        imgdata.lens.makernotes.MinFocal =
                          bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]);
                      if (table_buf[3] | table_buf[4])
                        imgdata.lens.makernotes.MaxFocal =
                          bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]);
                      if (table_buf[5])
                        imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f;
                      if (table_buf[6])
                        imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f;
                      parseSonyLensFeatures(table_buf[0], table_buf[7]);
                    }
                }
              }
            free(table_buf);
          }

		else if (tag == 0x0104)
		  {
		    imgdata.other.FlashEC = getreal(type);
		  }

        else if (tag == 0x0105)					// Teleconverter
          {
            imgdata.lens.makernotes.TeleconverterID = get2();
          }

        else if (tag == 0x0114 && len < 65535)					// CameraSettings
          {
            table_buf = (uchar*)malloc(len);
            fread(table_buf, len, 1, ifp);
            switch (len) {
            case 280:
            case 364:
            case 332:
              // CameraSettings and CameraSettings2 are big endian
              if (table_buf[2] | table_buf[3])
                {
                  lid = (((ushort)table_buf[2])<<8) |
                    ((ushort)table_buf[3]);
                  imgdata.lens.makernotes.CurAp =
                    libraw_powf64(2.0f, ((float)lid/8.0f-1.0f)/2.0f);
                }
              break;
            case 1536:
            case 2048:
              // CameraSettings3 are little endian
              parseSonyLensType2(table_buf[1016], table_buf[1015]);
              if (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF)
                {
                  switch (table_buf[153]) {
                  case 16: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; break;
                  case 17: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; break;
                  }
                }
              break;
            }
            free(table_buf);
          }

        else if (tag == 0x9050 && len < 256000)		// little endian
          {
            table_buf_0x9050 = (uchar*)malloc(len);
            table_buf_0x9050_present = 1;
            fread(table_buf_0x9050, len, 1, ifp);

            if (imgdata.lens.makernotes.CamID)
              {
                process_Sony_0x9050(table_buf_0x9050, imgdata.lens.makernotes.CamID);
                free (table_buf_0x9050);
                table_buf_0x9050_present = 0;
              }
          }

        else if (tag == 0x940c && len < 256000)
          {
            table_buf_0x940c = (uchar*)malloc(len);
            table_buf_0x940c_present = 1;
            fread(table_buf_0x940c, len, 1, ifp);
            if ((imgdata.lens.makernotes.CamID) &&
                (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E))
              {
                process_Sony_0x940c(table_buf_0x940c);
                free(table_buf_0x940c);
                table_buf_0x940c_present = 0;
              }
          }

        else if (((tag == 0xb027) || (tag == 0x010c)) && (imgdata.lens.makernotes.LensID == -1))
          {
            imgdata.lens.makernotes.LensID = get4();
            if ((imgdata.lens.makernotes.LensID > 0x4900) &&
                (imgdata.lens.makernotes.LensID <= 0x5900))
            {
              imgdata.lens.makernotes.AdapterID = 0x4900;
              imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID;
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sigma_X3F;
              strcpy(imgdata.lens.makernotes.Adapter, "MC-11");
            }

            else if ((imgdata.lens.makernotes.LensID > 0xEF00) &&
                (imgdata.lens.makernotes.LensID < 0xFFFF)      &&
                (imgdata.lens.makernotes.LensID != 0xFF00))
            {
              imgdata.lens.makernotes.AdapterID = 0xEF00;
              imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID;
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF;
            }
            if (tag == 0x010c) imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Minolta_A;
          }

        else if (tag == 0xb02a && len < 256000)	// Sony LensSpec
          {
            table_buf = (uchar*)malloc(len);
            fread(table_buf, len, 1, ifp);
            if (saneSonyCameraInfo(table_buf[1], table_buf[2], table_buf[3], table_buf[4], table_buf[5], table_buf[6]))
              {
                if (table_buf[1] | table_buf[2])
                  imgdata.lens.makernotes.MinFocal =
                    bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]);
                if (table_buf[3] | table_buf[4])
                  imgdata.lens.makernotes.MaxFocal =
                    bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]);
                if (table_buf[5])
                  imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f;
                if (table_buf[6])
                  imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f;
                parseSonyLensFeatures(table_buf[0], table_buf[7]);
              }
            free(table_buf);
          }
      }
  next:
    fseek (ifp, save, SEEK_SET);
  }
 quit:
  order = sorder;
}

Project: LibRaw
File: dcraw.c

void CLASS parse_minolta (int base)
{
  int save, tag, len, offset, high=0, wide=0, i, c;
  short sorder=order;

  fseek (ifp, base, SEEK_SET);
  if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return;
  order = fgetc(ifp) * 0x101;
  offset = base + get4() + 8;
#ifdef LIBRAW_LIBRARY_BUILD
  if(offset>ifp->size()-8) // At least 8 bytes for tag/len
    offset = ifp->size()-8;
#endif
  while ((save=ftell(ifp)) < offset) {
    for (tag=i=0; i < 4; i++)
      tag = tag << 8 | fgetc(ifp);
    len = get4();
    if(len < 0)
      return; // just ignore wrong len?? or raise bad file exception?
    switch (tag) {
      case 0x505244:				/* PRD */
	fseek (ifp, 8, SEEK_CUR);
	high = get2();
	wide = get2();
	break;
#ifdef LIBRAW_LIBRARY_BUILD
      case 0x524946:				/* RIF */
    if (!strncasecmp(model,"DSLR-A100", 9))
    {
      fseek(ifp, 8, SEEK_CUR);
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][0] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][2] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][0] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][2] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][0] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][2] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][0] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][2] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][0] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][2] = get2();
      get4();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][0] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][2] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][0] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][2] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][0] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][2] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][0] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][2] = get2();
      imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][3] =
        imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] =
        imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] =
        imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][3] =
        imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] =
        imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][3] =
        imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][3] =
        imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][3] =
        imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][3] = 0x100;
    }
	break;
#endif
      case 0x574247:				/* WBG */
	get4();
	i = strcmp(model,"DiMAGE A200") ? 0:3;
	FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2();
	break;
      case 0x545457:				/* TTW */
	parse_tiff (ftell(ifp));
	data_offset = offset;
    }
    fseek (ifp, save+len+8, SEEK_SET);
  }
  raw_height = high;
  raw_width  = wide;
  order = sorder;
}

Project: LibRaw
File: dcraw.c

void CLASS parse_makernote (int base, int uptag)
{
  unsigned offset=0, entries, tag, type, len, save, c;
  unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
  uchar buf97[324], ci, cj, ck;
  short morder, sorder=order;
  char buf[10];
  unsigned SamsungKey[11];
  uchar NikonKey;

#ifdef LIBRAW_LIBRARY_BUILD
  unsigned custom_serial = 0;
  unsigned NikonLensDataVersion = 0;
  unsigned lenNikonLensData = 0;

  unsigned NikonFlashInfoVersion = 0;

  uchar *CanonCameraInfo;
  unsigned lenCanonCameraInfo = 0;

  uchar *table_buf;
  uchar *table_buf_0x9050;
  ushort table_buf_0x9050_present = 0;
  uchar *table_buf_0x940c;
  ushort table_buf_0x940c_present = 0;

  INT64 fsize = ifp->size();
#endif
/*
   The MakerNote might have its own TIFF header (possibly with
   its own byte-order!), or it might just be a table.
 */
  if (!strncmp(make,"Nokia",5)) return;
  fread (buf, 1, 10, ifp);
  if (!strncmp (buf,"KDK" ,3) ||	/* these aren't TIFF tables */
      !strncmp (buf,"VER" ,3) ||
      !strncmp (buf,"IIII",4) ||
      !strncmp (buf,"MMMM",4)) return;
  if (!strncmp (buf,"KC"  ,2) ||	/* Konica KD-400Z, KD-510Z */
      !strncmp (buf,"MLY" ,3)) {	/* Minolta DiMAGE G series */
    order = 0x4d4d;
    while ((i=ftell(ifp)) < data_offset && i < 16384) {
      wb[0] = wb[2];  wb[2] = wb[1];  wb[1] = wb[3];
      wb[3] = get2();
      if (wb[1] == 256 && wb[3] == 256 &&
	  wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
	FORC4 cam_mul[c] = wb[c];
    }
    goto quit;
  }
  if (!strcmp (buf,"Nikon")) {
    base = ftell(ifp);
    order = get2();
    if (get2() != 42) goto quit;
    offset = get4();
    fseek (ifp, offset-8, SEEK_CUR);
  } else if (!strcmp (buf,"OLYMPUS") ||
             !strcmp (buf,"PENTAX ")) {
    base = ftell(ifp)-10;
    fseek (ifp, -2, SEEK_CUR);
    order = get2();
    if (buf[0] == 'O') get2();
  } else if (!strncmp (buf,"SONY",4) ||
             !strcmp  (buf,"Panasonic")) {
    goto nf;
  } else if (!strncmp (buf,"FUJIFILM",8)) {
    base = ftell(ifp)-10;
	nf: order = 0x4949;
    fseek (ifp,  2, SEEK_CUR);
  } else if (!strcmp (buf,"OLYMP") ||
             !strcmp (buf,"LEICA") ||
             !strcmp (buf,"Ricoh") ||
             !strcmp (buf,"EPSON"))
    fseek (ifp, -2, SEEK_CUR);
  else if (!strcmp (buf,"AOC") ||
           !strcmp (buf,"QVC"))
    fseek (ifp, -4, SEEK_CUR);
  else {
    fseek (ifp, -10, SEEK_CUR);
    if (!strncmp(make,"SAMSUNG",7))
      base = ftell(ifp);
  }

  // adjust pos & base for Leica M8/M9/M Mono tags and dir in tag 0x3400
  if (!strncasecmp(make, "LEICA", 5))
    {
      if (!strncmp(model, "M8", 2) ||
          !strncasecmp(model, "Leica M8", 8) ||
          !strncasecmp(model, "LEICA X", 7))
        {
          base = ftell(ifp)-8;
        }
      else if (!strncasecmp(model, "LEICA M (Typ 240)", 17))
        {
          base = 0;
        }
      else if (!strncmp(model, "M9", 2) ||
               !strncasecmp(model, "Leica M9", 8) ||
               !strncasecmp(model, "M Monochrom", 11) ||
               !strncasecmp(model, "Leica M Monochrom", 11))
        {
          if (!uptag)
            {
              base = ftell(ifp) - 10;
              fseek (ifp, 8, SEEK_CUR);
            }
          else if (uptag == 0x3400)
            {
              fseek (ifp, 10, SEEK_CUR);
              base += 10;
            }
        }
      else if (!strncasecmp(model, "LEICA T", 7))
      	{
      	  base = ftell(ifp)-8;
#ifdef LIBRAW_LIBRARY_BUILD
      	  imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_T;
#endif
      	}
#ifdef LIBRAW_LIBRARY_BUILD
      else if (!strncasecmp(model, "LEICA SL", 8))
      	{
      	  imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_SL;
      	  imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_FF;
      	}
#endif
    }

  entries = get2();
  if (entries > 1000) return;
  morder = order;

  while (entries--) {
    order = morder;
    tiff_get (base, &tag, &type, &len, &save);
    tag |= uptag << 16;

#ifdef LIBRAW_LIBRARY_BUILD
    INT64 _pos = ftell(ifp);
    if(len > 8 && _pos+len > 2* fsize) continue;
    if (!strncmp(make, "Canon",5))
      {
        if (tag == 0x000d && len < 256000)	// camera info
          {
            CanonCameraInfo = (uchar*)malloc(MAX(16,len));
            fread(CanonCameraInfo, len, 1, ifp);
            lenCanonCameraInfo = len;
          }

        else if (tag == 0x10)	// Canon ModelID
          {
            unique_id = get4();
            if (unique_id == 0x03740000) unique_id = 0x80000374;	// M3
            if (unique_id == 0x03840000) unique_id = 0x80000384;	// M10
            if (unique_id == 0x03940000) unique_id = 0x80000394;	// M5
            setCanonBodyFeatures(unique_id);
            if (lenCanonCameraInfo)
              {
                processCanonCameraInfo(unique_id, CanonCameraInfo,lenCanonCameraInfo);
                free(CanonCameraInfo);
                CanonCameraInfo = 0;
                lenCanonCameraInfo = 0;
              }
          }

        else parseCanonMakernotes (tag, type, len);
      }

    else if (!strncmp(make, "FUJI", 4)) {
      if (tag == 0x0010) {
         char FujiSerial[sizeof(imgdata.shootinginfo.InternalBodySerial)];
         char *words[4];
         char yy[2], mm[3], dd[3], ystr[16], ynum[16];
         int year, nwords, ynum_len;
         unsigned c;
         stmread(FujiSerial, len, ifp);
         nwords = getwords(FujiSerial, words, 4,sizeof(imgdata.shootinginfo.InternalBodySerial));
         for (int i = 0; i < nwords; i++) {
           mm[2] = dd[2] = 0;
           if (strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1) < 18)
              if (i == 0)
	         strncpy (imgdata.shootinginfo.InternalBodySerial,
		 	words[0],
			sizeof(imgdata.shootinginfo.InternalBodySerial)-1);
              else
	      {
	       char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
	       snprintf (tbuf, sizeof(tbuf), "%s %s",
	            imgdata.shootinginfo.InternalBodySerial, words[i]);
	       strncpy(imgdata.shootinginfo.InternalBodySerial,tbuf,
	            sizeof(imgdata.shootinginfo.InternalBodySerial)-1);
	       }
           else
           {
             strncpy (dd, words[i]+strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-14, 2);
             strncpy (mm, words[i]+strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-16, 2);
             strncpy (yy, words[i]+strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-18, 2);
             year = (yy[0]-'0')*10 + (yy[1]-'0');
             if (year <70) year += 2000; else year += 1900;

             ynum_len = (int)strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-18;
             strncpy(ynum, words[i], ynum_len);
             ynum[ynum_len] = 0;
             for ( int j = 0; ynum[j] && ynum[j+1] && sscanf(ynum+j, "%2x", &c); j += 2) ystr[j/2] = c;
             ystr[ynum_len / 2 + 1] = 0;
             strcpy (model2, ystr);

             if (i == 0) {
	       char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];

               if (nwords == 1)
		   snprintf (tbuf,sizeof(tbuf),
			   "%s %s %d:%s:%s",
			   words[0]+strnlen(words[0],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-12,
				ystr, year, mm, dd);

               else
		 snprintf (tbuf,sizeof(tbuf),
			    "%s %d:%s:%s %s",
			    ystr, year, mm, dd,
			    words[0]+strnlen(words[0],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-12);

	       strncpy(imgdata.shootinginfo.InternalBodySerial,tbuf,
	            sizeof(imgdata.shootinginfo.InternalBodySerial)-1);
             } else {
		char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
	        snprintf (tbuf, sizeof(tbuf),
		"%s %s %d:%s:%s %s",
		imgdata.shootinginfo.InternalBodySerial, ystr, year, mm, dd,
		 words[i]+strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-12);
		 strncpy(imgdata.shootinginfo.InternalBodySerial,tbuf,
		 	sizeof(imgdata.shootinginfo.InternalBodySerial)-1);
      	     }
           }
         }
      }
      else
	parseFujiMakernotes (tag, type);
    }

    else if (!strncasecmp(make, "LEICA", 5))
      {
        if (((tag == 0x035e) || (tag == 0x035f)) && (type == 10) && (len == 9))
        {
          int ind = tag == 0x035e?0:1;
	      for (int j=0; j < 3; j++)
	       FORCC imgdata.color.dng_color[ind].forwardmatrix[j][c]= getreal(type);
        }

        if ((tag == 0x0303) && (type != 4))
          {
            stmread(imgdata.lens.makernotes.Lens, len, ifp);
          }

        if ((tag == 0x3405) ||
            (tag == 0x0310) ||
            (tag == 0x34003405))
          {
            imgdata.lens.makernotes.LensID = get4();
            imgdata.lens.makernotes.LensID =
              ((imgdata.lens.makernotes.LensID>>2)<<8) |
              (imgdata.lens.makernotes.LensID & 0x3);
            if (imgdata.lens.makernotes.LensID != -1)
              {
                if ((model[0] == 'M') ||
                    !strncasecmp (model, "LEICA M", 7))
                  {
                    imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_M;
                    if (imgdata.lens.makernotes.LensID)
                    imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_M;
                  }
                else if ((model[0] == 'S') ||
                         !strncasecmp (model, "LEICA S", 7))
                  {
                    imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_S;
                    if (imgdata.lens.makernotes.Lens[0])
                    imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_S;
                  }
              }
          }

        else if (
                 ((tag == 0x0313) || (tag == 0x34003406)) &&
                 (fabs(imgdata.lens.makernotes.CurAp) < 0.17f) &&
                 ((type == 10) || (type == 5))
                 )
          {
            imgdata.lens.makernotes.CurAp = getreal(type);
            if (imgdata.lens.makernotes.CurAp > 126.3)
              imgdata.lens.makernotes.CurAp = 0.0f;
          }

        else if (tag == 0x3400)
          {
            parse_makernote (base, 0x3400);
          }
      }

    else if (!strncmp(make, "NIKON",5))
      {
        if (tag == 0x000a)
          {
            imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens;
            imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
          }
        else if (tag == 0x0012)
          {
            char a, b, c;
            a = fgetc(ifp);
            b = fgetc(ifp);
            c = fgetc(ifp);
            if (c) imgdata.other.FlashEC = (float)(a*b)/(float)c;
          }
        else if (tag == 0x0082)				// lens attachment
          {
            stmread(imgdata.lens.makernotes.Attachment, len, ifp);
          }
        else if (tag == 0x0083)				// lens type
          {
            imgdata.lens.nikon.NikonLensType = fgetc(ifp);
          }
        else if (tag == 0x0084)				// lens
          {
            imgdata.lens.makernotes.MinFocal = getreal(type);
            imgdata.lens.makernotes.MaxFocal = getreal(type);
            imgdata.lens.makernotes.MaxAp4MinFocal = getreal(type);
            imgdata.lens.makernotes.MaxAp4MaxFocal = getreal(type);
          }
        else if (tag == 0x008b)				// lens f-stops
          {
            uchar a, b, c;
            a = fgetc(ifp);
            b = fgetc(ifp);
            c = fgetc(ifp);
            if (c)
              {
                imgdata.lens.nikon.NikonLensFStops = a*b*(12/c);
                imgdata.lens.makernotes.LensFStops =
                  (float)imgdata.lens.nikon.NikonLensFStops /12.0f;
              }
          }
        else if (tag == 0x0093)
          {
            i = get2();
            if ((i == 7) || (i == 9))
            {
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens;
              imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
            }
          }
        else if (tag == 0x0098)				// contains lens data
          {
            for (i = 0; i < 4; i++)
              {
                NikonLensDataVersion = NikonLensDataVersion * 10 + fgetc(ifp) - '0';
              }
            switch (NikonLensDataVersion)
              {
              case 100: lenNikonLensData = 9; break;
              case 101:
              case 201:	// encrypted, starting from v.201
              case 202:
              case 203: lenNikonLensData = 15; break;
              case 204: lenNikonLensData = 16; break;
              case 400: lenNikonLensData = 459; break;
              case 401: lenNikonLensData = 590; break;
              case 402: lenNikonLensData = 509; break;
              case 403: lenNikonLensData = 879; break;
              }
            if(lenNikonLensData>0)
              {
                table_buf = (uchar*)malloc(lenNikonLensData);
                fread(table_buf, lenNikonLensData, 1, ifp);
                if ((NikonLensDataVersion < 201) && lenNikonLensData)
                  {
                    processNikonLensData(table_buf, lenNikonLensData);
                    free(table_buf);
                    lenNikonLensData = 0;
                  }
              }
          }
        else if (tag == 0x00a0)
          {
            stmread(imgdata.shootinginfo.BodySerial, len, ifp);
          }
        else if (tag == 0x00a8)		// contains flash data
          {
          	for (i = 0; i < 4; i++)
              {
                NikonFlashInfoVersion = NikonFlashInfoVersion * 10 + fgetc(ifp) - '0';
              }
          }
      }

    else if (!strncmp(make, "OLYMPUS", 7))
      {
        switch (tag) {
        case 0x0404:
        case 0x101a:
        case 0x20100101:
          if (!imgdata.shootinginfo.BodySerial[0])
            stmread(imgdata.shootinginfo.BodySerial, len, ifp);
        break;
        case 0x20100102:
          if (!imgdata.shootinginfo.InternalBodySerial[0])
            stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp);
        break;
        case 0x0207:
        case 0x20100100:
          {
            uchar sOlyID[8];
            unsigned long long OlyID;
            fread (sOlyID, MIN(len,7), 1, ifp);
	    sOlyID[7] = 0;
            OlyID = sOlyID[0];
            i = 1;
            while (i < 7 && sOlyID[i])
              {
                OlyID = OlyID << 8 | sOlyID[i];
                i++;
              }
            setOlympusBodyFeatures(OlyID);
          }
          break;
        case 0x1002:
          imgdata.lens.makernotes.CurAp = libraw_powf64(2.0f, getreal(type)/2);
          break;
        case 0x20401112:
          imgdata.makernotes.olympus.OlympusCropID = get2();
          break;
        case 0x20401113:
          FORC4 imgdata.makernotes.olympus.OlympusFrame[c] = get2();
          break;
        case 0x20100201:
          {
            unsigned long long oly_lensid [3];
            oly_lensid[0] = fgetc(ifp);
            fgetc(ifp);
            oly_lensid[1] = fgetc(ifp);
            oly_lensid[2] = fgetc(ifp);
            imgdata.lens.makernotes.LensID =
              (oly_lensid[0] << 16) | (oly_lensid[1] << 8) | oly_lensid[2];
          }
          imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FT;
          imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_FT;
          if (((imgdata.lens.makernotes.LensID < 0x20000) ||
               (imgdata.lens.makernotes.LensID > 0x4ffff)) &&
              (imgdata.lens.makernotes.LensID & 0x10))
            {
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_mFT;
            }
          break;
        case 0x20100202:
          stmread(imgdata.lens.LensSerial, len, ifp);
          break;
        case 0x20100203:
          stmread(imgdata.lens.makernotes.Lens, len, ifp);
          break;
        case 0x20100205:
          imgdata.lens.makernotes.MaxAp4MinFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f);
          break;
        case 0x20100206:
          imgdata.lens.makernotes.MaxAp4MaxFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f);
          break;
        case 0x20100207:
          imgdata.lens.makernotes.MinFocal = (float)get2();
          break;
        case 0x20100208:
          imgdata.lens.makernotes.MaxFocal = (float)get2();
          if (imgdata.lens.makernotes.MaxFocal > 1000.0f)
            imgdata.lens.makernotes.MaxFocal = imgdata.lens.makernotes.MinFocal;
          break;
        case 0x2010020a:
          imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f);
          break;
        case 0x20100301:
          imgdata.lens.makernotes.TeleconverterID = fgetc(ifp) << 8;
          fgetc(ifp);
          imgdata.lens.makernotes.TeleconverterID =
            imgdata.lens.makernotes.TeleconverterID | fgetc(ifp);
          break;
        case 0x20100303:
          stmread(imgdata.lens.makernotes.Teleconverter, len, ifp);
          break;
        case 0x20100403:
          stmread(imgdata.lens.makernotes.Attachment, len, ifp);
          break;
        }
      }

    else if ((!strncmp(make, "PENTAX", 6) || !strncmp(make, "RICOH", 5)) &&
             !strncmp(model, "GR", 2))
      {
        if (tag == 0x0005)
    	  {
    	     char buffer[17];
    	     int count=0;
    	     fread(buffer, 16, 1, ifp);
    	     buffer[16] = 0;
    	     for (int i=0; i<16; i++)
    	     {
//    	        sprintf(imgdata.shootinginfo.InternalBodySerial+2*i, "%02x", buffer[i]);
    	        if ((isspace(buffer[i])) ||
    	            (buffer[i] == 0x2D) ||
    	            (isalnum(buffer[i])))
    	        count++;
    	     }
    	     if (count == 16)
    	     {
    	        sprintf (imgdata.shootinginfo.BodySerial, "%8s", buffer+8);
    	        buffer[8] = 0;
    	        sprintf (imgdata.shootinginfo.InternalBodySerial, "%8s", buffer);
    	     }
    	     else
    	     {
    	        sprintf (imgdata.shootinginfo.BodySerial, "%02x%02x%02x%02x", buffer[4], buffer[5], buffer[6], buffer[7]);
    	        sprintf (imgdata.shootinginfo.InternalBodySerial, "%02x%02x%02x%02x", buffer[8], buffer[9], buffer[10], buffer[11]);
    	     }
    	  }
        else if ((tag == 0x1001) && (type == 3))
          {
            imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
            imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens;
            imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC;
            imgdata.lens.makernotes.LensID = -1;
            imgdata.lens.makernotes.FocalType = 1;
          }

        else if ((tag == 0x100b) && (type == 10))
          {
            imgdata.other.FlashEC = getreal(type);
          }

        else if ((tag == 0x1017) && (get2() == 2))
          {
            strcpy(imgdata.lens.makernotes.Attachment, "Wide-Angle Adapter");
          }
        else if (tag == 0x1500)
          {
            imgdata.lens.makernotes.CurFocal = getreal(type);
          }
      }

    else if (!strncmp(make, "RICOH", 5) &&
             strncmp(model, "PENTAX", 6))
      {
    	if ((tag == 0x0005) && !strncmp(model, "GXR", 3))
    	  {
    	     char buffer[9];
    	     buffer[8] = 0;
    	     fread(buffer, 8, 1, ifp);
    	     sprintf (imgdata.shootinginfo.InternalBodySerial, "%8s", buffer);
    	  }

    	else if ((tag == 0x100b) && (type == 10))
          {
            imgdata.other.FlashEC = getreal(type);
          }

          else if ((tag == 0x1017) && (get2() == 2))
          {
            strcpy(imgdata.lens.makernotes.Attachment, "Wide-Angle Adapter");
          }

        else if (tag == 0x1500)
          {
            imgdata.lens.makernotes.CurFocal = getreal(type);
          }

        else if ((tag == 0x2001) && !strncmp(model, "GXR", 3))
          {
            short ntags, cur_tag;
            fseek(ifp, 20, SEEK_CUR);
            ntags = get2();
            cur_tag = get2();
            while (cur_tag != 0x002c)
              {
                fseek(ifp, 10, SEEK_CUR);
                cur_tag = get2();
              }
            fseek(ifp, 6, SEEK_CUR);
            fseek(ifp, get4()+20, SEEK_SET);
            stread(imgdata.shootinginfo.BodySerial, 12, ifp);
            get2();
            imgdata.lens.makernotes.LensID = getc(ifp) - '0';
            switch(imgdata.lens.makernotes.LensID) {
              case 1:
              case 2:
              case 3:
              case 5:
              case 6:
            	imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
            	imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_RicohModule;
              break;
              case 8:
            	imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_M;
            	imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC;
            	imgdata.lens.makernotes.LensID = -1;
              break;
              default:
            	imgdata.lens.makernotes.LensID = -1;
            }
            fseek(ifp, 17, SEEK_CUR);
            stread(imgdata.lens.LensSerial, 12, ifp);
          }
      }

    else if ((!strncmp(make, "PENTAX", 6) ||
              !strncmp(model, "PENTAX", 6) ||
             (!strncmp(make, "SAMSUNG", 7) && dng_version)) &&
             strncmp(model, "GR", 2))
      {
        if (tag == 0x0005)
          {
            unique_id = get4();
            setPentaxBodyFeatures(unique_id);
          }
        else if (tag == 0x0013)
          {
            imgdata.lens.makernotes.CurAp = (float)get2()/10.0f;
          }
        else if (tag == 0x0014)
          {
            PentaxISO(get2());
          }
        else if (tag == 0x001d)
          {
            imgdata.lens.makernotes.CurFocal = (float)get4()/100.0f;
          }
        else if (tag == 0x003f)
          {
            imgdata.lens.makernotes.LensID = fgetc(ifp) << 8 | fgetc(ifp);
          }
        else if (tag == 0x004d)
          {
            if (type == 9) imgdata.other.FlashEC = getreal(type) / 256.0f;
            else imgdata.other.FlashEC = (float) ((signed short) fgetc(ifp)) / 6.0f;
          }
         else if (tag == 0x007e)
           {
             imgdata.color.linear_max[0] =
             imgdata.color.linear_max[1] =
             imgdata.color.linear_max[2] =
             imgdata.color.linear_max[3] = (long)(-1) * get4();
           }
        else if (tag == 0x0207)
          {
	    if(len < 65535) // Safety belt
            	PentaxLensInfo(imgdata.lens.makernotes.CamID, len);
          }
        else if (tag == 0x020d)
        {
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x020e)
        {
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x020f)
        {
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0210)
        {
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0211)
        {
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0212)
        {
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0213)
        {
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0214)
        {
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0221)
        {
	  int nWB = get2();
	  if(nWB<=sizeof(imgdata.color.WBCT_Coeffs)/sizeof(imgdata.color.WBCT_Coeffs[0]))
	    for (int i = 0; i < nWB; i++)
	      {
		imgdata.color.WBCT_Coeffs[i][0] = (unsigned)0xcfc6 - get2();
		fseek(ifp, 2, SEEK_CUR);
		imgdata.color.WBCT_Coeffs[i][1] = get2();
		imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 0x2000;
		imgdata.color.WBCT_Coeffs[i][3] = get2();
	      }
        }
        else if (tag == 0x0215)
        {
          fseek (ifp, 16, SEEK_CUR);
          sprintf(imgdata.shootinginfo.InternalBodySerial, "%d", get4());
        }
        else if (tag == 0x0229)
        {
          stmread(imgdata.shootinginfo.BodySerial, len, ifp);
        }
        else if (tag == 0x022d)
        {
	  fseek (ifp,2,SEEK_CUR);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ (c >> 1)] = get2();
	  getc(ifp);
          FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c ^ (c >> 1)] = get2();
        }
        else if (tag == 0x0239)		// Q-series lens info (LensInfoQ)
          {
            char LensInfo [20];
            fseek (ifp, 2, SEEK_CUR);
            stread(imgdata.lens.makernotes.Lens, 30, ifp);
            strcat(imgdata.lens.makernotes.Lens, " ");
            stread(LensInfo, 20, ifp);
            strcat(imgdata.lens.makernotes.Lens, LensInfo);
          }
      }

    else if (!strncmp(make, "SAMSUNG", 7))
      {
        if (tag == 0x0002)
          {
            if(get4() == 0x2000)
              {
                imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX;
              }
            else if (!strncmp(model, "NX mini", 7))
              {
                imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX_M;
              }
            else
              {
                imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
                imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens;
              }
          }
        else if (tag == 0x0003)
          {
            unique_id = imgdata.lens.makernotes.CamID = get4();
          }
         else if (tag == 0xa002)
          {
             stmread(imgdata.shootinginfo.BodySerial, len, ifp);
          }
        else if (tag == 0xa003)
          {
            imgdata.lens.makernotes.LensID = get2();
            if (imgdata.lens.makernotes.LensID)
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Samsung_NX;
          }
        else if (tag == 0xa005)
          {
            stmread(imgdata.lens.InternalLensSerial, len, ifp);
          }
        else if (tag == 0xa019)
          {
            imgdata.lens.makernotes.CurAp = getreal(type);
          }
        else if (tag == 0xa01a)
          {
            imgdata.lens.makernotes.FocalLengthIn35mmFormat = get4() / 10.0f;
            if (imgdata.lens.makernotes.FocalLengthIn35mmFormat < 10.0f)
              imgdata.lens.makernotes.FocalLengthIn35mmFormat *= 10.0f;
          }
      }

    else if (!strncasecmp(make, "SONY", 4) ||
             !strncasecmp(make, "Konica", 6) ||
             !strncasecmp(make, "Minolta", 7) ||
             (!strncasecmp(make, "Hasselblad", 10) &&
              (!strncasecmp(model, "Stellar", 7) ||
               !strncasecmp(model, "Lunar", 5) ||
               !strncasecmp(model, "Lusso", 5) ||
               !strncasecmp(model, "HV",2))))
      {
        ushort lid;
        if (tag == 0xb001)			// Sony ModelID
        {
          unique_id = get2();
          setSonyBodyFeatures(unique_id);
          if (table_buf_0x9050_present)
            {
              process_Sony_0x9050(table_buf_0x9050, unique_id);
              free (table_buf_0x9050);
              table_buf_0x9050_present = 0;
            }
          if (table_buf_0x940c_present)
            {
              if (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E)
                {
                  process_Sony_0x940c(table_buf_0x940c);
                }
              free (table_buf_0x940c);
              table_buf_0x940c_present = 0;
            }
        }

        else if ((tag == 0x0010) &&					// CameraInfo
                 strncasecmp(model, "DSLR-A100", 9) &&
                 strncasecmp(model, "NEX-5C", 6) &&
                 !strncasecmp(make, "SONY", 4) &&
                 ((len == 368) ||		// a700
                  (len == 5478) ||		// a850, a900
                  (len == 5506) ||		// a200, a300, a350
                  (len == 6118) ||		// a230, a290, a330, a380, a390
                  				// a450, a500, a550, a560, a580
                  				// a33, a35, a55
                  				// NEX3, NEX5, NEX5C, NEXC3, VG10E
                  (len == 15360))
                 )
          {
            table_buf = (uchar*)malloc(len);
            fread(table_buf, len, 1, ifp);
            if (memcmp(table_buf, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) &&
                memcmp(table_buf, "\x00\x00\x00\x00\x00\x00\x00\x00", 8))
              {
                switch (len)
                  {
                  case 368:
                  case 5478:
                    // a700, a850, a900: CameraInfo
                    if (table_buf[0] | table_buf[3])
                      imgdata.lens.makernotes.MinFocal =
                        bcd2dec(table_buf[0]) * 100 + bcd2dec(table_buf[3]);
                    if (table_buf[2] | table_buf[5])
                      imgdata.lens.makernotes.MaxFocal =
                        bcd2dec(table_buf[2]) * 100 + bcd2dec(table_buf[5]);
                    if (table_buf[4])
                      imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[4]) / 10.0f;
                    if (table_buf[4])
                      imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[7]) / 10.0f;
                    parseSonyLensFeatures(table_buf[1], table_buf[6]);
                    break;
                  default:
                    // CameraInfo2 & 3
                    if (table_buf[1] | table_buf[2])
                      imgdata.lens.makernotes.MinFocal =
                        bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]);
                    if (table_buf[3] | table_buf[4])
                      imgdata.lens.makernotes.MaxFocal =
                        bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]);
                    if (table_buf[5])
                      imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f;
                    if (table_buf[6])
                      imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f;
                    parseSonyLensFeatures(table_buf[0], table_buf[7]);
                }
              }
            free(table_buf);
          }

        else if ((tag == 0x0020) &&				// WBInfoA100, needs 0xb028 processing
                 !strncasecmp(model, "DSLR-A100", 9))
	  {
	    fseek(ifp,0x49dc,SEEK_CUR);
	    stmread(imgdata.shootinginfo.InternalBodySerial, 12, ifp);
	  }

	else if (tag == 0x0104)
	  {
	    imgdata.other.FlashEC = getreal(type);
	  }

        else if (tag == 0x0105)					// Teleconverter
          {
            imgdata.lens.makernotes.TeleconverterID = get2();
          }

        else if (tag == 0x0114 && len < 256000)		// CameraSettings
          {
            table_buf = (uchar*)malloc(len);
            fread(table_buf, len, 1, ifp);
            switch (len) {
            case 280:
            case 364:
            case 332:
              // CameraSettings and CameraSettings2 are big endian
              if (table_buf[2] | table_buf[3])
                {
                  lid = (((ushort)table_buf[2])<<8) |
                    ((ushort)table_buf[3]);
                  imgdata.lens.makernotes.CurAp =
                    libraw_powf64(2.0f, ((float)lid/8.0f-1.0f)/2.0f);
                }
              break;
            case 1536:
            case 2048:
              // CameraSettings3 are little endian
              parseSonyLensType2(table_buf[1016], table_buf[1015]);
              if (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF)
                {
                  switch (table_buf[153]) {
                  case 16: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; break;
                  case 17: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; break;
                  }
                }
              break;
            }
            free(table_buf);
          }

        else if (tag == 0x9050 && len < 256000)		// little endian
          {
            table_buf_0x9050 = (uchar*)malloc(len);
            table_buf_0x9050_present = 1;
            fread(table_buf_0x9050, len, 1, ifp);

            if (imgdata.lens.makernotes.CamID)
              {
                process_Sony_0x9050(table_buf_0x9050, imgdata.lens.makernotes.CamID);
                free (table_buf_0x9050);
                table_buf_0x9050_present = 0;
              }
          }

        else if (tag == 0x940c && len <256000)
          {
            table_buf_0x940c = (uchar*)malloc(len);
            table_buf_0x940c_present = 1;
            fread(table_buf_0x940c, len, 1, ifp);
            if ((imgdata.lens.makernotes.CamID) &&
                (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E))
              {
                process_Sony_0x940c(table_buf_0x940c);
                free(table_buf_0x940c);
                table_buf_0x940c_present = 0;
              }
          }

        else if (((tag == 0xb027) || (tag == 0x010c)) && (imgdata.lens.makernotes.LensID == -1))
          {
            imgdata.lens.makernotes.LensID = get4();
            if ((imgdata.lens.makernotes.LensID > 0x4900) &&
                (imgdata.lens.makernotes.LensID <= 0x5900))
            {
              imgdata.lens.makernotes.AdapterID = 0x4900;
              imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID;
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sigma_X3F;
              strcpy(imgdata.lens.makernotes.Adapter, "MC-11");
            }

            else if ((imgdata.lens.makernotes.LensID > 0xEF00) &&
                (imgdata.lens.makernotes.LensID < 0xFFFF)      &&
                (imgdata.lens.makernotes.LensID != 0xFF00))
            {
              imgdata.lens.makernotes.AdapterID = 0xEF00;
              imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID;
              imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF;
            }
            if (tag == 0x010c) imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Minolta_A;
          }

        else if (tag == 0xb02a && len < 256000)	// Sony LensSpec
          {
            table_buf = (uchar*)malloc(len);
            fread(table_buf, len, 1, ifp);
            if (table_buf[1] | table_buf[2])
              imgdata.lens.makernotes.MinFocal =
                bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]);
            if (table_buf[3] | table_buf[4])
              imgdata.lens.makernotes.MaxFocal =
                bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]);
            if (table_buf[5])
              imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f;
            if (table_buf[6])
              imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f;
            parseSonyLensFeatures(table_buf[0], table_buf[7]);
            free(table_buf);
          }
      }

    fseek(ifp,_pos,SEEK_SET);
#endif

    if (tag == 2 && strstr(make,"NIKON") && !iso_speed)
      iso_speed = (get2(),get2());
    if (tag == 37 && strstr(make,"NIKON") && (!iso_speed || iso_speed == 65535))
      {
        unsigned char cc;
        fread(&cc,1,1,ifp);
        iso_speed = int(100.0 * libraw_powf64(2.0f,float(cc)/12.0-5.0));
      }
    if (tag == 4 && len > 26 && len < 35) {
      if ((i=(get4(),get2())) != 0x7fff && (!iso_speed || iso_speed == 65535))
	iso_speed = 50 * libraw_powf64(2.0, i/32.0 - 4);
#ifdef LIBRAW_LIBRARY_BUILD
      get4();
#else
      if ((i=(get2(),get2())) != 0x7fff && !aperture)
	aperture = libraw_powf64(2.0, i/64.0);
#endif
      if ((i=get2()) != 0xffff && !shutter)
	shutter = libraw_powf64(2.0, (short) i/-32.0);
      wbi = (get2(),get2());
      shot_order = (get2(),get2());
    }
    if ((tag == 4 || tag == 0x114) && !strncmp(make,"KONICA",6)) {
      fseek (ifp, tag == 4 ? 140:160, SEEK_CUR);
      switch (get2()) {
	case 72:  flip = 0;  break;
	case 76:  flip = 6;  break;
	case 82:  flip = 5;  break;
      }
    }
    if (tag == 7 && type == 2 && len > 20)
      fgets (model2, 64, ifp);
    if (tag == 8 && type == 4)
      shot_order = get4();
    if (tag == 9 && !strncmp(make,"Canon",5))
      fread (artist, 64, 1, ifp);
    if (tag == 0xc && len == 4)
      FORC3 cam_mul[(c << 1 | c >> 1) & 3] = getreal(type);
    if (tag == 0xd && type == 7 && get2() == 0xaaaa) {
      for (c=i=2; (ushort) c != 0xbbbb && i < len; i++)
	c = c << 8 | fgetc(ifp);
      while ((i+=4) < len-5)
	if (get4() == 257 && (i=len) && (c = (get4(),fgetc(ifp))) < 3)
	  flip = "065"[c]-'0';
    }

#ifndef LIBRAW_LIBRARY_BUILD
    if (tag == 0x10 && type == 4) unique_id = get4();
#endif

#ifdef LIBRAW_LIBRARY_BUILD
    INT64 _pos2 = ftell(ifp);
	if (!strncasecmp(make,"Olympus",7))
	{
	  short nWB, tWB;
	  if ((tag == 0x20300108) || (tag == 0x20310109))
	      imgdata.makernotes.olympus.ColorSpace = get2();

	  if ((tag == 0x20400102) && (len == 2) &&
	      (!strncasecmp(model, "E-410", 5) || !strncasecmp(model, "E-510", 5)))
	    {
	      int i;
	      for (i=0; i<64; i++)
		imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] =
		  imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100;
	      for (i=64; i<256; i++)
		imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100;
	    }
	  if ((tag >= 0x20400102) && (tag <= 0x2040010d))
	    {
	      ushort CT;
	      nWB = tag-0x20400102;
	      switch (nWB)
		{
                case 0 : CT = 3000; tWB = LIBRAW_WBI_Tungsten; break;
		case 1 : CT = 3300; tWB = 0x100; break;
		case 2 : CT = 3600; tWB = 0x100; break;
		case 3 : CT = 3900; tWB = 0x100; break;
                case 4 : CT = 4000; tWB = LIBRAW_WBI_FL_W; break;
		case 5 : CT = 4300; tWB = 0x100; break;
                case 6 : CT = 4500; tWB = LIBRAW_WBI_FL_D; break;
		case 7 : CT = 4800; tWB = 0x100; break;
                case 8 : CT = 5300; tWB = LIBRAW_WBI_FineWeather; break;
                case 9 : CT = 6000; tWB = LIBRAW_WBI_Cloudy; break;
                case 10: CT = 6600; tWB = LIBRAW_WBI_FL_N; break;
                case 11: CT = 7500; tWB = LIBRAW_WBI_Shade; break;
		default: CT = 0; tWB = 0x100;
		}
	      if (CT)
		{
		  imgdata.color.WBCT_Coeffs[nWB][0] = CT;
		  imgdata.color.WBCT_Coeffs[nWB][1] = get2();
		  imgdata.color.WBCT_Coeffs[nWB][3] = get2();
		  if (len == 4)
		    {
		      imgdata.color.WBCT_Coeffs[nWB][2] = get2();
		      imgdata.color.WBCT_Coeffs[nWB][4] = get2();
		    }
		}
	      if (tWB != 0x100)
		FORC4 imgdata.color.WB_Coeffs[tWB][c] = imgdata.color.WBCT_Coeffs[nWB][c+1];
	    }
	  if ((tag >= 0x20400113) && (tag <= 0x2040011e))
	    {
	      nWB = tag-0x20400113;
	      imgdata.color.WBCT_Coeffs[nWB][2] = imgdata.color.WBCT_Coeffs[nWB][4] = get2();
	      switch (nWB)
		{
                case 0:  tWB = LIBRAW_WBI_Tungsten; break;
                case 4:  tWB = LIBRAW_WBI_FL_W; break;
                case 6:  tWB = LIBRAW_WBI_FL_D; break;
                case 8:  tWB = LIBRAW_WBI_FineWeather; break;
                case 9:  tWB = LIBRAW_WBI_Cloudy; break;
                case 10: tWB = LIBRAW_WBI_FL_N; break;
                case 11: tWB = LIBRAW_WBI_Shade; break;
		default: tWB = 0x100;
		}
	      if (tWB != 0x100)
		imgdata.color.WB_Coeffs[tWB][1] = imgdata.color.WB_Coeffs[tWB][3] =
		  imgdata.color.WBCT_Coeffs[nWB][2];
	    }

	  if (tag == 0x20400121)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][2] = get2();
	      if (len == 4)
		{
                  imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = get2();
                  imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = get2();
		}
	    }
	  if (tag == 0x2040011f)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = get2();
	    }
	  if (tag == 0x30000120)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][2] = get2();
	      if (len == 2)
		{
		  for (int i=0; i<256; i++)
		    imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100;
		}
	    }
	  if (tag == 0x30000121)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][2] = get2();
	    }
	  if (tag == 0x30000122)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][2] = get2();
	    }
	  if (tag == 0x30000123)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][2] = get2();
	    }
	  if (tag == 0x30000124)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Sunset][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_Sunset][2] = get2();
	    }
	  if (tag == 0x30000130)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][2] = get2();
	    }
	  if (tag == 0x30000131)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][2] = get2();
	    }
	  if (tag == 0x30000132)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][2] = get2();
	    }
	  if (tag == 0x30000133)
	    {
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][0] = get2();
              imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][2] = get2();
	    }

	  if((tag == 0x20400805) && (len == 2))
	    {
	      imgdata.makernotes.olympus.OlympusSensorCalibration[0]=getreal(type);
	      imgdata.makernotes.olympus.OlympusSensorCalibration[1]=getreal(type);
	      FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.olympus.OlympusSensorCalibration[0];
	    }
	  if (tag == 0x20200401)
	    {
	      imgdata.other.FlashEC = getreal(type);
	    }
	}
    fseek(ifp,_pos2,SEEK_SET);

#endif
    if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) {
      fseek (ifp, get4()+base, SEEK_SET);
      parse_tiff_ifd (base);
    }
    if (tag == 0x14 && type == 7) {
      if (len == 2560) {
	fseek (ifp, 1248, SEEK_CUR);
	goto get2_256;
      }
      fread (buf, 1, 10, ifp);
      if (!strncmp(buf,"NRW ",4)) {
	fseek (ifp, strcmp(buf+4,"0100") ? 46:1546, SEEK_CUR);
	cam_mul[0] = get4() << 2;
	cam_mul[1] = get4() + get4();
	cam_mul[2] = get4() << 2;
      }
    }
    if (tag == 0x15 && type == 2 && is_raw)
      fread (model, 64, 1, ifp);
    if (strstr(make,"PENTAX")) {
      if (tag == 0x1b) tag = 0x1018;
      if (tag == 0x1c) tag = 0x1017;
    }
    if (tag == 0x1d) {
      while ((c = fgetc(ifp)) && c != EOF)
#ifdef LIBRAW_LIBRARY_BUILD
      {
        if ((!custom_serial) && (!isdigit(c)))
        {
          if ((strbuflen(model) == 3) && (!strcmp(model,"D50")))
          {
            custom_serial = 34;
          }
          else
          {
            custom_serial = 96;
          }
        }
#endif
	serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
#ifdef LIBRAW_LIBRARY_BUILD
      }
      if (!imgdata.shootinginfo.BodySerial[0])
        sprintf(imgdata.shootinginfo.BodySerial, "%d", serial);
#endif
    }
    if (tag == 0x29 && type == 1) {  // Canon PowerShot G9
      c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
      fseek (ifp, 8 + c*32, SEEK_CUR);
      FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
    }
#ifndef LIBRAW_LIBRARY_BUILD
    if (tag == 0x3d && type == 3 && len == 4)
      FORC4 cblack[c ^ c >> 1] = get2() >> (14-tiff_bps);
#endif
    if (tag == 0x81 && type == 4) {
      data_offset = get4();
      fseek (ifp, data_offset + 41, SEEK_SET);
      raw_height = get2() * 2;
      raw_width  = get2();
      filters = 0x61616161;
    }
    if ((tag == 0x81  && type == 7) ||
	(tag == 0x100 && type == 7) ||
	(tag == 0x280 && type == 1)) {
      thumb_offset = ftell(ifp);
      thumb_length = len;
    }
    if (tag == 0x88 && type == 4 && (thumb_offset = get4()))
      thumb_offset += base;
    if (tag == 0x89 && type == 4)
      thumb_length = get4();
    if (tag == 0x8c || tag == 0x96)
      meta_offset = ftell(ifp);
    if (tag == 0x97) {
      for (i=0; i < 4; i++)
	ver97 = ver97 * 10 + fgetc(ifp)-'0';
      switch (ver97) {
	case 100:
	  fseek (ifp, 68, SEEK_CUR);
	  FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
	  break;
	case 102:
	  fseek (ifp, 6, SEEK_CUR);
	  FORC4 cam_mul[c ^ (c >> 1)] = get2();
	  break;
	case 103:
	  fseek (ifp, 16, SEEK_CUR);
	  FORC4 cam_mul[c] = get2();
      }
      if (ver97 >= 200) {
	if (ver97 != 205) fseek (ifp, 280, SEEK_CUR);
	fread (buf97, 324, 1, ifp);
      }
    }
    if (tag == 0xa1 && type == 7) {
      order = 0x4949;
      fseek (ifp, 140, SEEK_CUR);
      FORC3 cam_mul[c] = get4();
    }
    if (tag == 0xa4 && type == 3) {
      fseek (ifp, wbi*48, SEEK_CUR);
      FORC3 cam_mul[c] = get2();
    }

    if (tag == 0xa7) {	// shutter count
      NikonKey = fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp);
        if ( (unsigned) (ver97-200) < 17) {
        ci = xlat[0][serial & 0xff];
        cj = xlat[1][NikonKey];
        ck = 0x60;
        for (i=0; i < 324; i++)
          buf97[i] ^= (cj += ci * ck++);
        i = "66666>666;6A;:;55"[ver97-200] - '0';
        FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
          sget2 (buf97 + (i & -2) + c*2);
      }
#ifdef LIBRAW_LIBRARY_BUILD
      if ((NikonLensDataVersion > 200) && lenNikonLensData)
      {
        if (custom_serial)
        {
          ci = xlat[0][custom_serial];
        }
        else
        {
          ci = xlat[0][serial & 0xff];
        }
        cj = xlat[1][NikonKey];
        ck = 0x60;
        for (i = 0; i < lenNikonLensData; i++)
          table_buf[i] ^= (cj += ci * ck++);
        processNikonLensData(table_buf, lenNikonLensData);
        lenNikonLensData = 0;
        free(table_buf);
      }
      if (ver97 == 601)  // Coolpix A
    	{
          imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens;
          imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens;
    	}
#endif
    }

    if(tag == 0xb001 && type == 3)	// Sony ModelID
      {
        unique_id = get2();
      }
    if (tag == 0x200 && len == 3)
      shot_order = (get4(),get4());
    if (tag == 0x200 && len == 4)
      FORC4 cblack[c ^ c >> 1] = get2();
    if (tag == 0x201 && len == 4)
         FORC4 cam_mul[c ^ (c >> 1)] = get2();
    if (tag == 0x220 && type == 7)
      meta_offset = ftell(ifp);
    if (tag == 0x401 && type == 4 && len == 4)
      FORC4 cblack[c ^ c >> 1] = get4();
#ifdef LIBRAW_LIBRARY_BUILD
    // not corrected for file bitcount, to be patched in open_datastream
    if (tag == 0x03d && strstr(make,"NIKON") && len == 4)
      {
        FORC4 cblack[c ^ c >> 1] = get2();
        i = cblack[3];
        FORC3 if(i>cblack[c]) i = cblack[c];
        FORC4 cblack[c]-=i;
        black += i;
      }
#endif
    if (tag == 0xe01) {		/* Nikon Capture Note */
#ifdef LIBRAW_LIBRARY_BUILD
	int loopc = 0;
#endif
      order = 0x4949;
      fseek (ifp, 22, SEEK_CUR);
      for (offset=22; offset+22 < len; offset += 22+i) {
#ifdef LIBRAW_LIBRARY_BUILD
	if(loopc++>1024)
		throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
	tag = get4();
	fseek (ifp, 14, SEEK_CUR);
	i = get4()-4;
	if (tag == 0x76a43207) flip = get2();
	else fseek (ifp, i, SEEK_CUR);
      }
    }
    if (tag == 0xe80 && len == 256 && type == 7) {
      fseek (ifp, 48, SEEK_CUR);
      cam_mul[0] = get2() * 508 * 1.078 / 0x10000;
      cam_mul[2] = get2() * 382 * 1.173 / 0x10000;
    }
    if (tag == 0xf00 && type == 7) {
      if (len == 614)
	fseek (ifp, 176, SEEK_CUR);
      else if (len == 734 || len == 1502)
	fseek (ifp, 148, SEEK_CUR);
      else goto next;
      goto get2_256;
    }
    if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
          for (i=0; i < 3; i++)
	  {
#ifdef LIBRAW_LIBRARY_BUILD
           if (!imgdata.makernotes.olympus.ColorSpace)
	   {
            FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
	   }
           else
	   {
            FORC3 imgdata.color.ccm[i][c] = ((short) get2()) / 256.0;
	   }
#else
            FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
#endif
          }
    if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
      FORC4 cblack[c ^ c >> 1] = get2();
    if (tag == 0x1017 || tag == 0x20400100)
      cam_mul[0] = get2() / 256.0;
    if (tag == 0x1018 || tag == 0x20400100)
      cam_mul[2] = get2() / 256.0;
    if (tag == 0x2011 && len == 2) {
get2_256:
      order = 0x4d4d;
      cam_mul[0] = get2() / 256.0;
      cam_mul[2] = get2() / 256.0;
    }
    if ((tag | 0x70) == 0x2070 && (type == 4 || type == 13))
      fseek (ifp, get4()+base, SEEK_SET);
#ifdef LIBRAW_LIBRARY_BUILD
// IB start
    if (tag == 0x2010)
      {
        INT64 _pos3 = ftell(ifp);
        parse_makernote(base, 0x2010);
        fseek(ifp,_pos3,SEEK_SET);
      }

    if (
         ((tag == 0x2020) || (tag == 0x3000) || (tag == 0x2030) || (tag == 0x2031)) &&
         ((type == 7) || (type == 13)) &&
         !strncasecmp(make,"Olympus",7)
       )
      {
        INT64 _pos3 = ftell(ifp);
        parse_makernote(base, tag);
        fseek(ifp,_pos3,SEEK_SET);
      }
// IB end
#endif
    if ((tag == 0x2020) && ((type == 7) || (type == 13)) && !strncmp(buf,"OLYMP",5))
      parse_thumb_note (base, 257, 258);
    if (tag == 0x2040)
      parse_makernote (base, 0x2040);
    if (tag == 0xb028) {
      fseek (ifp, get4()+base, SEEK_SET);
      parse_thumb_note (base, 136, 137);
    }
    if (tag == 0x4001 && len > 500 && len < 100000) {
      i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
      fseek (ifp, i, SEEK_CUR);
      FORC4 cam_mul[c ^ (c >> 1)] = get2();
      for (i+=18; i <= len; i+=10) {
      	get2();
      	FORC4 sraw_mul[c ^ (c >> 1)] = get2();
      	if (sraw_mul[1] == 1170) break;
      }
    }
    if(!strncasecmp(make,"Samsung",7))
      {
        if (tag == 0xa020) // get the full Samsung encryption key
            for (i=0; i<11; i++) SamsungKey[i] = get4();
        if (tag == 0xa021) // get and decode Samsung cam_mul array
            FORC4 cam_mul[c ^ (c >> 1)] = get4() - SamsungKey[c];
#ifdef LIBRAW_LIBRARY_BUILD
        if (tag == 0xa023)
          {
            imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][0] = get4() - SamsungKey[8];
            imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] = get4() - SamsungKey[9];
            imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][3] = get4() - SamsungKey[10];
            imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][2] = get4() - SamsungKey[0];
            if (imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][0] < (imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1]>>1))
              {
                imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] >> 4;
                imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][3] >> 4;
              }
          }
        if (tag == 0xa024)
          {
            FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][c ^ (c >> 1)] = get4() - SamsungKey[c+1];
            if (imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][0] < (imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][1]>>1))
              {
                imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][1] >> 4;
                imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][3] >> 4;
              }
          }
        if (tag == 0xa025)
           imgdata.color.linear_max[0]=
             imgdata.color.linear_max[1]=
             imgdata.color.linear_max[2]=
             imgdata.color.linear_max[3]= get4() - SamsungKey[0];
        if (tag == 0xa030 && len == 9)
            for (i=0; i < 3; i++)
              FORC3 imgdata.color.ccm[i][c] = (float)((short)((get4() + SamsungKey[i*3+c])))/256.0;
#endif
        if (tag == 0xa031 && len == 9)	// get and decode Samsung color matrix
            for (i=0; i < 3; i++)
              FORC3 cmatrix[i][c] = (float)((short)((get4() + SamsungKey[i*3+c])))/256.0;

        if (tag == 0xa028)
          FORC4 cblack[c ^ (c >> 1)] = get4() - SamsungKey[c];
      }
    else
      {
        // Somebody else use 0xa021 and 0xa028?
        if (tag == 0xa021)
          FORC4 cam_mul[c ^ (c >> 1)] = get4();
        if (tag == 0xa028)
          FORC4 cam_mul[c ^ (c >> 1)] -= get4();
      }
    if (tag == 0x4021 && get4() && get4())
      FORC4 cam_mul[c] = 1024;
next:
    fseek (ifp, save, SEEK_SET);
  }
quit:
  order = sorder;
}

Project: LibRaw
File: dcraw.c

void CLASS quicktake_100_load_raw()
{
  uchar pixel[484][644];
  static const short gstep[16] =
  { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
  static const short rstep[6][4] =
  { {  -3,-1,1,3  }, {  -5,-1,1,5  }, {  -8,-2,2,8  },
    { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
  static const short t_curve[256] =
  { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
    28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53,
    54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,
    79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116,
    118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155,
    158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195,
    197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244,
    248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322,
    326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400,
    405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479,
    483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643,
    654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844,
    855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 };
  int rb, row, col, sharp, val=0;
#ifdef LIBRAW_LIBRARY_BUILD
  if(width>640 || height > 480)
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
  
  getbits(-1);
  memset (pixel, 0x80, sizeof pixel);
  for (row=2; row < height+2; row++) {
#ifdef LIBRAW_LIBRARY_BUILD
    checkCancel();
#endif
    for (col=2+(row & 1); col < width+2; col+=2) {
      val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
		pixel[row][col-2]) >> 2) + gstep[getbits(4)];
      pixel[row][col] = val = LIM(val,0,255);
      if (col < 4)
	pixel[row][col-2] = pixel[row+1][~row & 1] = val;
      if (row == 2)
	pixel[row-1][col+1] = pixel[row-1][col+3] = val;
    }
    pixel[row][col] = val;
  }
  for (rb=0; rb < 2; rb++)
    for (row=2+rb; row < height+2; row+=2)
    {
#ifdef LIBRAW_LIBRARY_BUILD
    checkCancel();
#endif
      for (col=3-(row & 1); col < width+2; col+=2) {
	if (row < 4 || col < 4) sharp = 2;
	else {
	  val = ABS(pixel[row-2][col] - pixel[row][col-2])
	      + ABS(pixel[row-2][col] - pixel[row-2][col-2])
	      + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
	  sharp = val <  4 ? 0 : val <  8 ? 1 : val < 16 ? 2 :
		  val < 32 ? 3 : val < 48 ? 4 : 5;
	}
	val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
	      + rstep[sharp][getbits(2)];
	pixel[row][col] = val = LIM(val,0,255);
	if (row < 4) pixel[row-2][col+2] = val;
	if (col < 4) pixel[row+2][col-2] = val;
      }
    }
  for (row=2; row < height+2; row++)
  {
#ifdef LIBRAW_LIBRARY_BUILD
    checkCancel();
#endif
    for (col=3-(row & 1); col < width+2; col+=2) {
      val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
	      pixel[row][col+1]) >> 1) - 0x100;
      pixel[row][col] = LIM(val,0,255);
    }
  }
  for (row=0; row < height; row++)
  {
#ifdef LIBRAW_LIBRARY_BUILD
    checkCancel();
#endif
    for (col=0; col < width; col++)
      RAW(row,col) = t_curve[pixel[row+2][col+2]];
  }
  maximum = 0x3ff;
}

Project: LibRaw
File: dcraw.c

int CLASS parse_tiff_ifd (int base)
{
  unsigned entries, tag, type, len, plen=16, save;
  int ifd, use_cm=0, cfa, i, j, c, ima_len=0;
  char *cbuf, *cp;
  uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
  double fm[3][4], cc[4][4], cm[4][3], cam_xyz[4][3], num;
  double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };
  unsigned sony_curve[] = { 0,0,0,0,0,4095 };
  unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
  struct jhead jh;
  int pana_raw = 0;
#ifndef LIBRAW_LIBRARY_BUILD
  FILE *sfp;
#endif

  if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
    return 1;
  ifd = tiff_nifds++;
  for (j=0; j < 4; j++)
    for (i=0; i < 4; i++)
      cc[j][i] = i == j;
  entries = get2();
  if (entries > 512) return 1;
#ifdef LIBRAW_LIBRARY_BUILD
  INT64 fsize = ifp->size();
#endif
  while (entries--) {
    tiff_get (base, &tag, &type, &len, &save);
#ifdef LIBRAW_LIBRARY_BUILD
    INT64 savepos = ftell(ifp);
    if(len > 8 && len + savepos > fsize*2) continue; // skip tag pointing out of 2xfile
    if(callbacks.exif_cb)
      {
        callbacks.exif_cb(callbacks.exifparser_data,tag|(pana_raw?0x30000:0),type,len,order,ifp);
        fseek(ifp,savepos,SEEK_SET);
      }
#endif

#ifdef LIBRAW_LIBRARY_BUILD
  if (!strncasecmp(make, "SONY", 4) ||
      (!strncasecmp(make, "Hasselblad", 10) &&
        (!strncasecmp(model, "Stellar", 7) ||
         !strncasecmp(model, "Lunar", 5) ||
         !strncasecmp(model, "HV",2))))
  {
  	switch (tag) {
	case 0x7300: // SR2 black level
	    for (int i = 0; i < 4 && i < len; i++)
	      cblack[i] = get2();
	  break;
	case 0x7480:
	case 0x7820:
	    FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c] = get2();
	    imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][1];
	break;
	case 0x7481:
	case 0x7821:
	    FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c] = get2();
	    imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][1];
	break;
	case 0x7482:
	case 0x7822:
	    FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c] = get2();
	    imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1];
	break;
	case 0x7483:
	case 0x7823:
	    FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c] = get2();
	    imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1];
	break;
	case 0x7484:
	case 0x7824:
	    imgdata.color.WBCT_Coeffs[0][0] = 4500;
	    FORC3 imgdata.color.WBCT_Coeffs[0][c+1] = get2();
	    imgdata.color.WBCT_Coeffs[0][4] = imgdata.color.WBCT_Coeffs[0][2];
	break;
	case 0x7486:
                FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][c] = get2();
                imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][1];
	break;
	case 0x7825:
                FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c] = get2();
                imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1];
	break;
	case 0x7826:
                FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c] = get2();
                imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][1];
	break;
	case 0x7827:
                FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c] = get2();
                imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][1];
	break;
	case 0x7828:
                FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c] = get2();
                imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][1];
	break;
	case 0x7829:
                FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c] = get2();
                imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][1];
	break;
	case 0x782a:
	    imgdata.color.WBCT_Coeffs[1][0] = 8500;
	    FORC3 imgdata.color.WBCT_Coeffs[1][c+1] = get2();
	    imgdata.color.WBCT_Coeffs[1][4] = imgdata.color.WBCT_Coeffs[1][2];
	break;
	case 0x782b:
	    imgdata.color.WBCT_Coeffs[2][0] = 6000;
	    FORC3 imgdata.color.WBCT_Coeffs[2][c+1] = get2();
	    imgdata.color.WBCT_Coeffs[2][4] = imgdata.color.WBCT_Coeffs[2][2];
	break;
	case 0x782c:
	    imgdata.color.WBCT_Coeffs[3][0] = 3200;
                FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][c] = imgdata.color.WBCT_Coeffs[3][c+1] = get2();
                imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][3] = imgdata.color.WBCT_Coeffs[3][4] = imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][1];
	break;
	case 0x782d:
	    imgdata.color.WBCT_Coeffs[4][0] = 2500;
	    FORC3 imgdata.color.WBCT_Coeffs[4][c+1] = get2();
	    imgdata.color.WBCT_Coeffs[4][4] = imgdata.color.WBCT_Coeffs[4][2];
	break;
	case 0x787f:
	    FORC3 imgdata.color.linear_max[c] = get2();
	    imgdata.color.linear_max[3] = imgdata.color.linear_max[1];
	break;
	}
  }
#endif


    switch (tag) {
      case 1:   if(len==4) pana_raw = get4(); break;
      case 5:   width  = get2();  break;
      case 6:   height = get2();  break;
      case 7:   width += get2();  break;
      case 9:   if ((i = get2())) filters = i;
#ifdef LIBRAW_LIBRARY_BUILD
        if(pana_raw && len == 1 && type ==3)
          pana_black[3]+=i;
#endif
      break;
      case 8:
      case 10:
#ifdef LIBRAW_LIBRARY_BUILD
        if(pana_raw && len == 1 && type ==3)
          pana_black[3]+=get2();
#endif
      break;
      case 14: case 15: case 16:
#ifdef LIBRAW_LIBRARY_BUILD
        if(pana_raw) {
          imgdata.color.linear_max[tag-14] = get2();
          if (tag == 15 ) imgdata.color.linear_max[3] = imgdata.color.linear_max[1];
        }
#endif
      break;
      case 17: case 18:
	if (type == 3 && len == 1)
	  cam_mul[(tag-17)*2] = get2() / 256.0;
	break;
#ifdef LIBRAW_LIBRARY_BUILD
      case 19:
	if(pana_raw) {
	  ushort nWB, cnt, tWB;
	  nWB = get2();
	  if (nWB > 0x100) break;
	  for (cnt=0; cnt<nWB; cnt++) {
	    tWB = get2();
	    if (tWB < 0x100) {
	      imgdata.color.WB_Coeffs[tWB][0] = get2();
	      imgdata.color.WB_Coeffs[tWB][2] = get2();
	      imgdata.color.WB_Coeffs[tWB][1] = imgdata.color.WB_Coeffs[tWB][3] = 0x100;
	    } else get4();
	  }
	}
      break;
#endif
      case 23:
	if (type == 3) iso_speed = get2();
      break;
      case 28: case 29: case 30:
#ifdef LIBRAW_LIBRARY_BUILD
        if(pana_raw && len == 1 && type ==3)
          {
            pana_black[tag-28] = get2();
          }
        else
#endif
          {
	     cblack[tag-28] = get2();
	     cblack[3] = cblack[1];
          }
	break;
      case 36: case 37: case 38:
	cam_mul[tag-36] = get2();
	break;
      case 39:
#ifdef LIBRAW_LIBRARY_BUILD
	if(pana_raw) {
	    ushort nWB, cnt, tWB;
	    nWB = get2();
	    if (nWB > 0x100) break;
	    for (cnt=0; cnt<nWB; cnt++) {
	        tWB = get2();
	        if (tWB < 0x100) {
	            imgdata.color.WB_Coeffs[tWB][0] = get2();
	            imgdata.color.WB_Coeffs[tWB][1] = imgdata.color.WB_Coeffs[tWB][3] = get2();
	            imgdata.color.WB_Coeffs[tWB][2] = get2();
	        } else fseek(ifp, 6, SEEK_CUR);
	    }
	}
	break;
#endif
	if (len < 50 || cam_mul[0]) break;
	fseek (ifp, 12, SEEK_CUR);
	FORC3 cam_mul[c] = get2();
	break;
      case 46:
	if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break;
	thumb_offset = ftell(ifp) - 2;
	thumb_length = len;
	break;
      case 61440:			/* Fuji HS10 table */
	fseek (ifp, get4()+base, SEEK_SET);
	parse_tiff_ifd (base);
	break;
      case 2: case 256: case 61441:	/* ImageWidth */
	tiff_ifd[ifd].t_width = getint(type);
	break;
      case 3: case 257: case 61442:	/* ImageHeight */
	tiff_ifd[ifd].t_height = getint(type);
	break;
      case 258:				/* BitsPerSample */
      case 61443:
	tiff_ifd[ifd].samples = len & 7;
	tiff_ifd[ifd].bps = getint(type);
	if (tiff_bps < tiff_ifd[ifd].bps)
	    tiff_bps = tiff_ifd[ifd].bps;
	break;
      case 61446:
	raw_height = 0;
	if (tiff_ifd[ifd].bps > 12) break;
	load_raw = &CLASS packed_load_raw;
	load_flags = get4() ? 24:80;
	break;
      case 259:				/* Compression */
	tiff_ifd[ifd].comp = getint(type);
	break;
      case 262:				/* PhotometricInterpretation */
	tiff_ifd[ifd].phint = get2();
	break;
      case 270:				/* ImageDescription */
	fread (desc, 512, 1, ifp);
	break;
      case 271:				/* Make */
	fgets (make, 64, ifp);
	break;
      case 272:				/* Model */
	fgets (model, 64, ifp);
	break;
#ifdef LIBRAW_LIBRARY_BUILD
      case 278:
	tiff_ifd[ifd].rows_per_strip = getint(type);
	break;
#endif
      case 280:				/* Panasonic RW2 offset */
	if (type != 4) break;
	load_raw = &CLASS panasonic_load_raw;
	load_flags = 0x2008;
      case 273:				/* StripOffset */
#ifdef LIBRAW_LIBRARY_BUILD
	if(len > 1 && len < 16384)
	  {
	    off_t sav = ftell(ifp);
	    tiff_ifd[ifd].strip_offsets = (int*)calloc(len,sizeof(int));
	    tiff_ifd[ifd].strip_offsets_count = len;
	    for(int i=0; i< len; i++)
	      tiff_ifd[ifd].strip_offsets[i]=get4()+base;
	    fseek(ifp,sav,SEEK_SET); // restore position
	  }
	/* fallback */
#endif
      case 513:				/* JpegIFOffset */
      case 61447:
	tiff_ifd[ifd].offset = get4()+base;
	if (!tiff_ifd[ifd].bps && tiff_ifd[ifd].offset > 0) {
	  fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
	  if (ljpeg_start (&jh, 1)) {
	    tiff_ifd[ifd].comp    = 6;
	    tiff_ifd[ifd].t_width   = jh.wide;
	    tiff_ifd[ifd].t_height  = jh.high;
	    tiff_ifd[ifd].bps     = jh.bits;
	    tiff_ifd[ifd].samples = jh.clrs;
	    if (!(jh.sraw || (jh.clrs & 1)))
	      tiff_ifd[ifd].t_width *= jh.clrs;
	    if ((tiff_ifd[ifd].t_width > 4*tiff_ifd[ifd].t_height) & ~jh.clrs) {
	      tiff_ifd[ifd].t_width  /= 2;
	      tiff_ifd[ifd].t_height *= 2;
	    }
	    i = order;
	    parse_tiff (tiff_ifd[ifd].offset + 12);
	    order = i;
	  }
	}
	break;
      case 274:				/* Orientation */
	tiff_ifd[ifd].t_flip = "50132467"[get2() & 7]-'0';
	break;
      case 277:				/* SamplesPerPixel */
	tiff_ifd[ifd].samples = getint(type) & 7;
	break;
      case 279:				/* StripByteCounts */
#ifdef LIBRAW_LIBRARY_BUILD
	if(len > 1 && len < 16384)
	  {
	    off_t sav = ftell(ifp);
	    tiff_ifd[ifd].strip_byte_counts = (int*)calloc(len,sizeof(int));
	    tiff_ifd[ifd].strip_byte_counts_count = len;
	    for(int i=0; i< len; i++)
		tiff_ifd[ifd].strip_byte_counts[i]=get4();
	    fseek(ifp,sav,SEEK_SET); // restore position
	  }
	/* fallback */
#endif
      case 514:
      case 61448:
	tiff_ifd[ifd].bytes = get4();
	break;
      case 61454:
	FORC3 cam_mul[(4-c) % 3] = getint(type);
	break;
      case 305:  case 11:		/* Software */
	fgets (software, 64, ifp);
	if (!strncmp(software,"Adobe",5) ||
	    !strncmp(software,"dcraw",5) ||
	    !strncmp(software,"UFRaw",5) ||
	    !strncmp(software,"Bibble",6) ||
	    !strcmp (software,"Digital Photo Professional"))
	  is_raw = 0;
	break;
      case 306:				/* DateTime */
	get_timestamp(0);
	break;
      case 315:				/* Artist */
	fread (artist, 64, 1, ifp);
	break;
      case 317:
	tiff_ifd[ifd].predictor = getint(type);
	break;
      case 322:				/* TileWidth */
	tiff_ifd[ifd].t_tile_width = getint(type);
	break;
      case 323:				/* TileLength */
	tiff_ifd[ifd].t_tile_length = getint(type);
	break;
      case 324:				/* TileOffsets */
	tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
	if (len == 1)
	  tiff_ifd[ifd].t_tile_width = tiff_ifd[ifd].t_tile_length = 0;
	if (len == 4) {
	  load_raw = &CLASS sinar_4shot_load_raw;
	  is_raw = 5;
	}
	break;
      case 325:
	tiff_ifd[ifd].bytes = len > 1 ? ftell(ifp): get4();
	break;
      case 330:				/* SubIFDs */
	if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].t_width == 3872) {
	  load_raw = &CLASS sony_arw_load_raw;
	  data_offset = get4()+base;
	  ifd++;
#ifdef LIBRAW_LIBRARY_BUILD
          if (ifd >= sizeof tiff_ifd / sizeof tiff_ifd[0])
         	throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif  
	  break;
	}
#ifdef LIBRAW_LIBRARY_BUILD
	if (!strncmp(make,"Hasselblad",10) && libraw_internal_data.unpacker_data.hasselblad_parser_flag) {
          fseek (ifp, ftell(ifp)+4, SEEK_SET);
          fseek (ifp, get4()+base, SEEK_SET);
          parse_tiff_ifd (base);
          break;
	}
#endif
        if(len > 1000) len=1000; /* 1000 SubIFDs is enough */
	while (len--) {
	  i = ftell(ifp);
	  fseek (ifp, get4()+base, SEEK_SET);
	  if (parse_tiff_ifd (base)) break;
	  fseek (ifp, i+4, SEEK_SET);
	}
	break;
      case 339:
	tiff_ifd[ifd].sample_format = getint(type);
	break;
      case 400:
	strcpy (make, "Sarnoff");
	maximum = 0xfff;
	break;
#ifdef LIBRAW_LIBRARY_BUILD
      case 700:
        if((type == 1 || type == 2 || type == 6 || type == 7) && len > 1 && len < 5100000)
          {
            xmpdata = (char*)malloc(xmplen = len+1);
            fread(xmpdata,len,1,ifp);
            xmpdata[len]=0;
          }
        break;
#endif
      case 28688:
	FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff;
	for (i=0; i < 5; i++)
	  for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++)
	    curve[j] = curve[j-1] + (1 << i);
	break;
      case 29184: sony_offset = get4();  break;
      case 29185: sony_length = get4();  break;
      case 29217: sony_key    = get4();  break;
      case 29264:
	parse_minolta (ftell(ifp));
	raw_width = 0;
	break;
      case 29443:
	FORC4 cam_mul[c ^ (c < 2)] = get2();
	break;
      case 29459:
	FORC4 cam_mul[c] = get2();
	i = (cam_mul[1] == 1024 && cam_mul[2] == 1024) << 1;
	SWAP (cam_mul[i],cam_mul[i+1])
	break;
#ifdef LIBRAW_LIBRARY_BUILD
    case 30720: // Sony matrix, Sony_SR2SubIFD_0x7800
      for (i=0; i < 3; i++) {
        float num = 0.0;
        for (c=0; c<3; c++) {
          imgdata.color.ccm[i][c] = (float) ((short)get2());
          num += imgdata.color.ccm[i][c];
        }
        if (num > 0.01) FORC3 imgdata.color.ccm[i][c] = imgdata.color.ccm[i][c] / num;
      }
      break;
#endif
    case 29456: // Sony black level, Sony_SR2SubIFD_0x7310, no more needs to be divided by 4
	  FORC4 cblack[c ^ c >> 1] = get2();
	  i = cblack[3];
	  FORC3 if(i>cblack[c]) i = cblack[c];
	  FORC4 cblack[c]-=i;
	  black = i;

#ifdef DCRAW_VERBOSE
      if (verbose) fprintf (stderr, _("...Sony black: %u cblack: %u %u %u %u\n"),black, cblack[0],cblack[1],cblack[2], cblack[3]);
#endif
      break;
      case 33405:			/* Model2 */
	fgets (model2, 64, ifp);
	break;
      case 33421:			/* CFARepeatPatternDim */
	if (get2() == 6 && get2() == 6)
	  filters = 9;
	break;
      case 33422:			/* CFAPattern */
	if (filters == 9) {
	  FORC(36) ((char *)xtrans)[c] = fgetc(ifp) & 3;
	  break;
	}
      case 64777:			/* Kodak P-series */
        if(len == 36)
          {
            filters = 9;
            colors = 3;
            FORC(36) xtrans[0][c] = fgetc(ifp) & 3;
          }
        else if(len > 0)
          {
            if ((plen=len) > 16) plen = 16;
            fread (cfa_pat, 1, plen, ifp);
            for (colors=cfa=i=0; i < plen && colors < 4; i++) {
              colors += !(cfa & (1 << cfa_pat[i]));
              cfa |= 1 << cfa_pat[i];
            }
            if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3);	/* CMY */
            if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4);	/* GMCY */
            goto guess_cfa_pc;
          }
        break;
      case 33424:
      case 65024:
	fseek (ifp, get4()+base, SEEK_SET);
	parse_kodak_ifd (base);
	break;
      case 33434:			/* ExposureTime */
	tiff_ifd[ifd].t_shutter = shutter = getreal(type);
	break;
      case 33437:			/* FNumber */
	aperture = getreal(type);
	break;
#ifdef LIBRAW_LIBRARY_BUILD
// IB start
    case 0xa405:		// FocalLengthIn35mmFormat
      imgdata.lens.FocalLengthIn35mmFormat = get2();
      break;
    case 0xa431:		// BodySerialNumber
    case 0xc62f:
      stmread(imgdata.shootinginfo.BodySerial, len, ifp);
      break;
    case 0xa432:		// LensInfo, 42034dec, Lens Specification per EXIF standard
      imgdata.lens.MinFocal = getreal(type);
      imgdata.lens.MaxFocal = getreal(type);
      imgdata.lens.MaxAp4MinFocal = getreal(type);
      imgdata.lens.MaxAp4MaxFocal = getreal(type);
      break;
    case 0xa435:		// LensSerialNumber
      stmread(imgdata.lens.LensSerial, len, ifp);
      break;
    case 0xc630:		// DNG LensInfo, Lens Specification per EXIF standard
      imgdata.lens.MinFocal = getreal(type);
      imgdata.lens.MaxFocal = getreal(type);
      imgdata.lens.MaxAp4MinFocal = getreal(type);
      imgdata.lens.MaxAp4MaxFocal = getreal(type);
      break;
    case 0xa433:		// LensMake
      stmread(imgdata.lens.LensMake, len, ifp);
      break;
    case 0xa434:		// LensModel
      stmread(imgdata.lens.Lens, len, ifp);
      if (!strncmp(imgdata.lens.Lens, "----", 4))
        imgdata.lens.Lens[0] = 0;
      break;
    case 0x9205:
      imgdata.lens.EXIF_MaxAp = libraw_powf64(2.0f, (getreal(type) / 2.0f));
      break;
// IB end
#endif
      case 34306:			/* Leaf white balance */
	FORC4 cam_mul[c ^ 1] = 4096.0 / get2();
	break;
      case 34307:			/* Leaf CatchLight color matrix */
	fread (software, 1, 7, ifp);
	if (strncmp(software,"MATRIX",6)) break;
	colors = 4;
	for (raw_color = i=0; i < 3; i++) {
	  FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]);
	  if (!use_camera_wb) continue;
	  num = 0;
	  FORC4 num += rgb_cam[i][c];
	  FORC4 rgb_cam[i][c] /= MAX(1,num);
	}
	break;
      case 34310:			/* Leaf metadata */
	parse_mos (ftell(ifp));
      case 34303:
	strcpy (make, "Leaf");
	break;
      case 34665:			/* EXIF tag */
	fseek (ifp, get4()+base, SEEK_SET);
	parse_exif (base);
	break;
      case 34853:			/* GPSInfo tag */
        {
          unsigned pos;
          fseek(ifp, pos = (get4() + base), SEEK_SET);
          parse_gps(base);
#ifdef LIBRAW_LIBRARY_BUILD
          fseek(ifp, pos, SEEK_SET);
          parse_gps_libraw(base);
#endif
        }
	break;
      case 34675:			/* InterColorProfile */
      case 50831:			/* AsShotICCProfile */
	profile_offset = ftell(ifp);
	profile_length = len;
	break;
      case 37122:			/* CompressedBitsPerPixel */
	kodak_cbpp = get4();
	break;
      case 37386:			/* FocalLength */
	focal_len = getreal(type);
	break;
      case 37393:			/* ImageNumber */
	shot_order = getint(type);
	break;
      case 37400:			/* old Kodak KDC tag */
	for (raw_color = i=0; i < 3; i++) {
	  getreal(type);
	  FORC3 rgb_cam[i][c] = getreal(type);
	}
	break;
      case 40976:
	strip_offset = get4();
	switch (tiff_ifd[ifd].comp) {
	  case 32770: load_raw = &CLASS samsung_load_raw;   break;
	  case 32772: load_raw = &CLASS samsung2_load_raw;  break;
	  case 32773: load_raw = &CLASS samsung3_load_raw;  break;
	}
	break;
      case 46275:			/* Imacon tags */
	strcpy (make, "Imacon");
	data_offset = ftell(ifp);
	ima_len = len;
	break;
      case 46279:
	if (!ima_len) break;
	fseek (ifp, 38, SEEK_CUR);
      case 46274:
	fseek (ifp, 40, SEEK_CUR);
	raw_width  = get4();
	raw_height = get4();
	left_margin = get4() & 7;
	width = raw_width - left_margin - (get4() & 7);
	top_margin = get4() & 7;
	height = raw_height - top_margin - (get4() & 7);
	if (raw_width == 7262 && ima_len == 234317952 ) {
	  height = 5412;
	  width  = 7216;
	  left_margin = 7;
          filters=0;
	} else 	if (raw_width == 7262) {
	  height = 5444;
	  width  = 7244;
	  left_margin = 7;
	}
	fseek (ifp, 52, SEEK_CUR);
	FORC3 cam_mul[c] = getreal(11);
	fseek (ifp, 114, SEEK_CUR);
	flip = (get2() >> 7) * 90;
	if (width * height * 6 == ima_len) {
	  if (flip % 180 == 90) SWAP(width,height);
	  raw_width = width;
	  raw_height = height;
	  left_margin = top_margin = filters = flip = 0;
	}
	sprintf (model, "Ixpress %d-Mp", height*width/1000000);
	load_raw = &CLASS imacon_full_load_raw;
	if (filters) {
	  if (left_margin & 1) filters = 0x61616161;
	  load_raw = &CLASS unpacked_load_raw;
	}
	maximum = 0xffff;
	break;
      case 50454:			/* Sinar tag */
      case 50455:
	if (len < 1 || len > 2560000 || !(cbuf = (char *) malloc(len))) break;
#ifndef LIBRAW_LIBRARY_BUILD
	fread (cbuf, 1, len, ifp);
#else
	if(fread (cbuf, 1, len, ifp) != len)
		throw LIBRAW_EXCEPTION_IO_CORRUPT; // cbuf to be free'ed in recycle
#endif
        cbuf[len-1] = 0;
	for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n'))
	  if (!strncmp (++cp,"Neutral ",8))
	    sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2);
	free (cbuf);
	break;
      case 50458:
	if (!make[0]) strcpy (make, "Hasselblad");
	break;
      case 50459:			/* Hasselblad tag */
#ifdef LIBRAW_LIBRARY_BUILD
        libraw_internal_data.unpacker_data.hasselblad_parser_flag=1;
#endif
	i = order;
	j = ftell(ifp);
	c = tiff_nifds;
	order = get2();
	fseek (ifp, j+(get2(),get4()), SEEK_SET);
	parse_tiff_ifd (j);
	maximum = 0xffff;
	tiff_nifds = c;
	order = i;
	break;
      case 50706:			/* DNGVersion */
	FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
	if (!make[0]) strcpy (make, "DNG");
	is_raw = 1;
	break;
      case 50708:			/* UniqueCameraModel */
#ifdef LIBRAW_LIBRARY_BUILD
        stmread(imgdata.color.UniqueCameraModel, len, ifp);
        imgdata.color.UniqueCameraModel[sizeof(imgdata.color.UniqueCameraModel)-1] = 0;
#endif
	if (model[0]) break;
#ifndef LIBRAW_LIBRARY_BUILD
	fgets (make, 64, ifp);
#else
        strncpy (make, imgdata.color.UniqueCameraModel, MIN(len, sizeof(imgdata.color.UniqueCameraModel)));
#endif
	if ((cp = strchr(make,' '))) {
	  strcpy(model,cp+1);
	  *cp = 0;
	}
	break;
      case 50710:			/* CFAPlaneColor */
	if (filters == 9) break;
	if (len > 4) len = 4;
	colors = len;
	fread (cfa_pc, 1, colors, ifp);
guess_cfa_pc:
        FORCC tab[cfa_pc[c]] = c;
        cdesc[c] = 0;
        for (i=16; i--; )
          filters = filters << 2 | tab[cfa_pat[i % plen]];
        filters -= !filters;
	break;
      case 50711:			/* CFALayout */
	if (get2() == 2) fuji_width = 1;
	break;
      case 291:
      case 50712:			/* LinearizationTable */
	linear_table (len);
	break;
      case 50713:			/* BlackLevelRepeatDim */
#ifdef LIBRAW_LIBRARY_BUILD
        imgdata.color.dng_levels.dng_cblack[4] = 
#endif
	cblack[4] = get2();
#ifdef LIBRAW_LIBRARY_BUILD
        imgdata.color.dng_levels.dng_cblack[5] = 
#endif
	cblack[5] = get2();
	if (cblack[4] * cblack[5] > (sizeof(cblack) / sizeof (cblack[0]) - 6))
#ifdef LIBRAW_LIBRARY_BUILD
            imgdata.color.dng_levels.dng_cblack[4]=
	    imgdata.color.dng_levels.dng_cblack[5]= 
#endif
	    cblack[4] = cblack[5] = 1;
	break;

#ifdef LIBRAW_LIBRARY_BUILD
	case 0xf00c: {
    	unsigned fwb[4];
    	FORC4 fwb[c] = get4();
		if (fwb[3] < 0x100)
		{
		  imgdata.color.WB_Coeffs[fwb[3]][0] = fwb[1];
		  imgdata.color.WB_Coeffs[fwb[3]][1] = imgdata.color.WB_Coeffs[fwb[3]][3] = fwb[0];
		  imgdata.color.WB_Coeffs[fwb[3]][2] = fwb[2];
		  if ((fwb[3] == 17) && libraw_internal_data.unpacker_data.lenRAFData>3 && libraw_internal_data.unpacker_data.lenRAFData < 10240000)
		  {
		    long long f_save = ftell(ifp);
		    int fj, found = 0;
		    ushort *rafdata = (ushort*) malloc (sizeof(ushort)*libraw_internal_data.unpacker_data.lenRAFData);
		    fseek (ifp, libraw_internal_data.unpacker_data.posRAFData, SEEK_SET);
		    fread (rafdata, sizeof(ushort), libraw_internal_data.unpacker_data.lenRAFData, ifp);
		    fseek(ifp, f_save, SEEK_SET);
		    for (int fi=0; fi<(libraw_internal_data.unpacker_data.lenRAFData-3); fi++)
			{
			  if ((fwb[0]==rafdata[fi]) && (fwb[1]==rafdata[fi+1]) && (fwb[2]==rafdata[fi+2]))
			  {
			    if (rafdata[fi-15] != fwb[0]) continue;
			    fi = fi - 15;
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][3] = rafdata[fi];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][0] = rafdata[fi+1];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][2] = rafdata[fi+2];

                            imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = rafdata[fi+3];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][0] = rafdata[fi+4];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][2] = rafdata[fi+5];

                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][3] = rafdata[fi+6];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][0] = rafdata[fi+7];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][2] = rafdata[fi+8];

                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][3] = rafdata[fi+9];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][0] = rafdata[fi+10];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][2] = rafdata[fi+11];

                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][3] = rafdata[fi+12];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][0] = rafdata[fi+13];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][2] = rafdata[fi+14];

                            imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = rafdata[fi+15];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][0] = rafdata[fi+16];
                            imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][2] = rafdata[fi+17];

                fi += 111;
                for (fj = fi; fj<(fi+15); fj+=3)
                  if (rafdata[fj] != rafdata[fi])
                  {
                    found = 1;
                    break;
                  }
                if (found)
                {
                  int FujiCCT_K [31] = {2500,2550,2650,2700,2800,2850,2950,3000,3100,3200,3300,3400,3600,3700,3800,4000,4200,4300,4500,4800,5000,5300,5600,5900,6300,6700,7100,7700,8300,9100,10000};
                  fj = fj - 93;
                  for (int iCCT=0; iCCT < 31; iCCT++)
                  {
                    imgdata.color.WBCT_Coeffs[iCCT][0] = FujiCCT_K[iCCT];
                    imgdata.color.WBCT_Coeffs[iCCT][1] = rafdata[iCCT*3+1+fj];
                    imgdata.color.WBCT_Coeffs[iCCT][2] = imgdata.color.WBCT_Coeffs[iCCT][4] = rafdata[iCCT*3+fj];
                    imgdata.color.WBCT_Coeffs[iCCT][3] = rafdata[iCCT*3+2+fj];
				  }
				}
			    free (rafdata);
				break;
			  }
			}
		  }
		}
		FORC4 fwb[c] = get4();
		if (fwb[3] < 0x100)
		{
		  imgdata.color.WB_Coeffs[fwb[3]][0] = fwb[1];
		  imgdata.color.WB_Coeffs[fwb[3]][1] = imgdata.color.WB_Coeffs[fwb[3]][3] = fwb[0];
		  imgdata.color.WB_Coeffs[fwb[3]][2] = fwb[2];
		}
    }
    break;
#endif

#ifdef LIBRAW_LIBRARY_BUILD
      case 50709:
        stmread(imgdata.color.LocalizedCameraModel,len, ifp);
      break;
#endif

      case 61450:
	cblack[4] = cblack[5] = MIN(sqrt((double)len),64);
      case 50714:			/* BlackLevel */
#ifdef LIBRAW_LIBRARY_BUILD
	if(tiff_ifd[ifd].samples > 1  && tiff_ifd[ifd].samples == len) // LinearDNG, per-channel black
	  {
	    for(i=0; i < colors && i < 4 && i < len; i++)
	      imgdata.color.dng_levels.dng_cblack[i]=
	        cblack[i]=
		  getreal(type)+0.5;

	    imgdata.color.dng_levels.dng_black= black = 0;
	  }
	else
#endif
	  if((cblack[4] * cblack[5] < 2) && len == 1)
	    {
#ifdef LIBRAW_LIBRARY_BUILD
	      imgdata.color.dng_levels.dng_black= 
#endif
	        black =
		  getreal(type);
	    }
	  else if(cblack[4] * cblack[5] <= len)
	    {
	      FORC (cblack[4] * cblack[5])
		cblack[6+c] = getreal(type);
	      black = 0;
	      FORC4
		cblack[c] = 0;

#ifdef LIBRAW_LIBRARY_BUILD
              if(tag == 50714)
	      {
	        FORC (cblack[4] * cblack[5])
	          imgdata.color.dng_levels.dng_cblack[6+c]= cblack[6+c];
	        imgdata.color.dng_levels.dng_black=0;
	        FORC4
	          imgdata.color.dng_levels.dng_cblack[c]= 0;
	      }
#endif
	    }
      break;
      case 50715:			/* BlackLevelDeltaH */
      case 50716:			/* BlackLevelDeltaV */
	for (num=i=0; i < len && i < 65536; i++)
	  num += getreal(type);
	black += num/len + 0.5;
#ifdef LIBRAW_LIBRARY_BUILD
	imgdata.color.dng_levels.dng_black += num/len + 0.5;
#endif
	break;
      case 50717:			/* WhiteLevel */
#ifdef LIBRAW_LIBRARY_BUILD
	imgdata.color.dng_levels.dng_whitelevel[0]=
#endif
	maximum = getint(type);
#ifdef LIBRAW_LIBRARY_BUILD
	if(tiff_ifd[ifd].samples > 1 ) // Linear DNG case
		for(i=1; i < colors && i < 4 && i < len; i++)
			imgdata.color.dng_levels.dng_whitelevel[i]=getint(type);
#endif
	break;
      case 50718:			/* DefaultScale */
	pixel_aspect  = getreal(type);
	pixel_aspect /= getreal(type);
	if(pixel_aspect > 0.995 && pixel_aspect < 1.005)
          pixel_aspect = 1.0;
	break;
#ifdef LIBRAW_LIBRARY_BUILD
      case 50778:
        imgdata.color.dng_color[0].illuminant = get2();
        break;
      case 50779:
        imgdata.color.dng_color[1].illuminant = get2();
        break;
#endif
      case 50721:			/* ColorMatrix1 */
      case 50722:			/* ColorMatrix2 */
#ifdef LIBRAW_LIBRARY_BUILD
        i = tag == 50721?0:1;
#endif
	FORCC for (j=0; j < 3; j++)
          {
#ifdef LIBRAW_LIBRARY_BUILD
          imgdata.color.dng_color[i].colormatrix[c][j]=
#endif
	  cm[c][j] = getreal(type);
          }
	use_cm = 1;
	break;

	case 0xc714:			/* ForwardMatrix1 */
        case 0xc715:			/* ForwardMatrix2 */
#ifdef LIBRAW_LIBRARY_BUILD
        i = tag == 0xc714?0:1;
#endif
	for (j=0; j < 3; j++)
	  FORCC
            {
#ifdef LIBRAW_LIBRARY_BUILD
              imgdata.color.dng_color[i].forwardmatrix[j][c]=
#endif
              fm[j][c] = getreal(type);
            }
	break;

      case 50723:			/* CameraCalibration1 */
      case 50724:			/* CameraCalibration2 */
#ifdef LIBRAW_LIBRARY_BUILD
        j = tag == 50723?0:1;
#endif
	for (i=0; i < colors; i++)
	  FORCC
            {
#ifdef LIBRAW_LIBRARY_BUILD
              imgdata.color.dng_color[j].calibration[i][c]=
#endif
              cc[i][c] = getreal(type);
            }
	break;
      case 50727:			/* AnalogBalance */
	FORCC{
#ifdef LIBRAW_LIBRARY_BUILD
              imgdata.color.dng_levels.analogbalance[c]=
#endif
	      ab[c] = getreal(type);
	}
	break;
      case 50728:			/* AsShotNeutral */
	FORCC asn[c] = getreal(type);
	break;
      case 50729:			/* AsShotWhiteXY */
	xyz[0] = getreal(type);
	xyz[1] = getreal(type);
	xyz[2] = 1 - xyz[0] - xyz[1];
	FORC3 xyz[c] /= d65_white[c];
	break;
#ifdef LIBRAW_LIBRARY_BUILD
      case 50730:			/* DNG: Baseline Exposure */
        baseline_exposure = getreal(type);
        break;
#endif
		  // IB start
    case 50740:			/* tag 0xc634 : DNG Adobe, DNG Pentax, Sony SR2, DNG Private */
#ifdef LIBRAW_LIBRARY_BUILD
      {
        char mbuf[64];
        unsigned short makernote_found = 0;
        INT64 curr_pos, start_pos = ftell(ifp);
        unsigned MakN_order, m_sorder = order;
        unsigned MakN_length;
        unsigned pos_in_original_raw;
        fread(mbuf, 1, 6, ifp);

        if (!strcmp(mbuf, "Adobe"))
          {
            order = 0x4d4d;				// Adobe header is always in "MM" / big endian
            curr_pos = start_pos + 6;
            while (curr_pos + 8 - start_pos <= len)
              {
                fread(mbuf, 1, 4, ifp);
                curr_pos += 8;
                if (!strncmp(mbuf, "MakN", 4)) {
                  makernote_found = 1;
                MakN_length = get4();
                MakN_order = get2();
                pos_in_original_raw = get4();
                order = MakN_order;
                parse_makernote_0xc634(curr_pos + 6 - pos_in_original_raw, 0, AdobeDNG);
                break;
                }
              }
          }
        else
          {
            fread(mbuf + 6, 1, 2, ifp);
            if (!strcmp(mbuf, "PENTAX ") ||
                !strcmp(mbuf, "SAMSUNG"))
              {
                makernote_found = 1;
                fseek(ifp, start_pos, SEEK_SET);
                parse_makernote_0xc634(base, 0, CameraDNG);
              }
          }

        fseek(ifp, start_pos, SEEK_SET);
        order = m_sorder;
      }
      // IB end
#endif
      if (dng_version) break;
      parse_minolta (j = get4()+base);
      fseek (ifp, j, SEEK_SET);
      parse_tiff_ifd (base);
      break;
    case 50752:
      read_shorts (cr2_slice, 3);
      break;
    case 50829:			/* ActiveArea */
      top_margin = getint(type);
      left_margin = getint(type);
      height = getint(type) - top_margin;
      width = getint(type) - left_margin;
      break;
    case 50830:			/* MaskedAreas */
      for (i=0; i < len && i < 32; i++)
        ((int*)mask)[i] = getint(type);
      black = 0;
      break;
    case 51009:			/* OpcodeList2 */
      meta_offset = ftell(ifp);
      break;
    case 64772:			/* Kodak P-series */
      if (len < 13) break;
      fseek (ifp, 16, SEEK_CUR);
      data_offset = get4();
      fseek (ifp, 28, SEEK_CUR);
      data_offset += get4();
      load_raw = &CLASS packed_load_raw;
      break;
    case 65026:
      if (type == 2) fgets (model2, 64, ifp);
    }
    fseek (ifp, save, SEEK_SET);
  }
  if (sony_length && sony_length < 10240000 && (buf = (unsigned *) malloc(sony_length))) {
    fseek (ifp, sony_offset, SEEK_SET);
    fread (buf, sony_length, 1, ifp);
    sony_decrypt (buf, sony_length/4, 1, sony_key);
#ifndef LIBRAW_LIBRARY_BUILD
    sfp = ifp;
    if ((ifp = tmpfile())) {
      fwrite (buf, sony_length, 1, ifp);
      fseek (ifp, 0, SEEK_SET);
      parse_tiff_ifd (-sony_offset);
      fclose (ifp);
    }
    ifp = sfp;
#else
    if( !ifp->tempbuffer_open(buf,sony_length))
        {
            parse_tiff_ifd(-sony_offset);
            ifp->tempbuffer_close();
        }
#endif
    free (buf);
  }
  for (i=0; i < colors; i++)
    FORCC cc[i][c] *= ab[i];
  if (use_cm) {
    FORCC for (i=0; i < 3; i++)
      for (cam_xyz[c][i]=j=0; j < colors; j++)
	cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
    cam_xyz_coeff (cmatrix, cam_xyz);
  }
  if (asn[0]) {
    cam_mul[3] = 0;
    FORCC cam_mul[c] = 1 / asn[c];
  }
  if (!use_cm)
    FORCC pre_mul[c] /= cc[c][c];
  return 0;
}

Project: LibRaw
File: dcraw.c

void CLASS processNikonLensData (uchar *LensData, unsigned len)
{
  ushort i;
  if (!(imgdata.lens.nikon.NikonLensType & 0x01))
    {
      imgdata.lens.makernotes.LensFeatures_pre[0] = 'A';
      imgdata.lens.makernotes.LensFeatures_pre[1] = 'F';
    }
  else
    {
      imgdata.lens.makernotes.LensFeatures_pre[0] = 'M';
      imgdata.lens.makernotes.LensFeatures_pre[1] = 'F';
    }

  if (imgdata.lens.nikon.NikonLensType & 0x02)
    {
      if (imgdata.lens.nikon.NikonLensType & 0x04)
        imgdata.lens.makernotes.LensFeatures_suf[0] = 'G';
      else
        imgdata.lens.makernotes.LensFeatures_suf[0] = 'D';
      imgdata.lens.makernotes.LensFeatures_suf[1] = ' ';
    }

  if (imgdata.lens.nikon.NikonLensType & 0x08)
    {
      imgdata.lens.makernotes.LensFeatures_suf[2] = 'V';
      imgdata.lens.makernotes.LensFeatures_suf[3] = 'R';
    }

  if (imgdata.lens.nikon.NikonLensType & 0x10)
  {
    imgdata.lens.makernotes.LensMount = imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Nikon_CX;
    imgdata.lens.makernotes.CameraFormat = imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_1INCH;
  }
  else
    imgdata.lens.makernotes.LensMount = imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Nikon_F;

  if (imgdata.lens.nikon.NikonLensType & 0x20)
  {
    strcpy(imgdata.lens.makernotes.Adapter, "FT-1");
    imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Nikon_F;
    imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Nikon_CX;
    imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_1INCH;
  }

  imgdata.lens.nikon.NikonLensType = imgdata.lens.nikon.NikonLensType & 0xdf;

  if (len < 20) {
    switch (len) {
    case 9:
      i = 2;
      break;
    case 15:
      i = 7;
      break;
    case 16:
      i = 8;
      break;
    }
    imgdata.lens.nikon.NikonLensIDNumber = LensData[i];
    imgdata.lens.nikon.NikonLensFStops = LensData[i + 1];
    imgdata.lens.makernotes.LensFStops = (float)imgdata.lens.nikon.NikonLensFStops /12.0f;
    if (fabsf(imgdata.lens.makernotes.MinFocal) < 1.1f)
    {
      if ((imgdata.lens.nikon.NikonLensType ^ (uchar)0x01) || LensData[i + 2])
        imgdata.lens.makernotes.MinFocal = 5.0f * libraw_powf64(2.0f, (float)LensData[i + 2] / 24.0f);
      if ((imgdata.lens.nikon.NikonLensType ^ (uchar)0x01) || LensData[i + 3])
        imgdata.lens.makernotes.MaxFocal = 5.0f * libraw_powf64(2.0f, (float)LensData[i + 3] / 24.0f);
      if ((imgdata.lens.nikon.NikonLensType ^ (uchar)0x01) || LensData[i + 4])
        imgdata.lens.makernotes.MaxAp4MinFocal = libraw_powf64(2.0f, (float)LensData[i + 4] / 24.0f);
      if ((imgdata.lens.nikon.NikonLensType ^ (uchar)0x01) || LensData[i + 5])
        imgdata.lens.makernotes.MaxAp4MaxFocal = libraw_powf64(2.0f, (float)LensData[i + 5] / 24.0f);
    }
    imgdata.lens.nikon.NikonMCUVersion = LensData[i + 6];
    if (i != 2)
      {
        if ((LensData[i - 1]) &&
            (fabsf(imgdata.lens.makernotes.CurFocal) < 1.1f))
          imgdata.lens.makernotes.CurFocal = 5.0f * libraw_powf64(2.0f, (float)LensData[i - 1] / 24.0f);
        if (LensData[i + 7]) imgdata.lens.nikon.NikonEffectiveMaxAp = libraw_powf64(2.0f, (float)LensData[i + 7] / 24.0f);
      }
    imgdata.lens.makernotes.LensID =
      (unsigned long long) LensData[i] << 56 |
      (unsigned long long) LensData[i + 1] << 48 |
      (unsigned long long) LensData[i + 2] << 40 |
      (unsigned long long) LensData[i + 3] << 32 |
      (unsigned long long) LensData[i + 4] << 24 |
      (unsigned long long) LensData[i + 5] << 16 |
      (unsigned long long) LensData[i + 6] << 8 |
      (unsigned long long) imgdata.lens.nikon.NikonLensType;

  }
  else if ((len == 459) || (len == 590))
    {
      memcpy(imgdata.lens.makernotes.Lens, LensData + 390, 64);
    }
  else if (len == 509)
    {
      memcpy(imgdata.lens.makernotes.Lens, LensData + 391, 64);
    }
  else if (len == 879)
    {
      memcpy(imgdata.lens.makernotes.Lens, LensData + 680, 64);
    }
  return;
}

Project: LibRaw
File: dcraw.c

void CLASS samsung_load_raw()
{
  int row, col, c, i, dir, op[4], len[4];
#ifdef LIBRAW_LIBRARY_BUILD
  if(raw_width> 32768 || raw_height > 32768)  // definitely too much for old samsung
    throw LIBRAW_EXCEPTION_IO_BADFILE;
#endif
  unsigned maxpixels = raw_width*(raw_height+7);

  order = 0x4949;
  for (row=0; row < raw_height; row++) {
#ifdef LIBRAW_LIBRARY_BUILD
    checkCancel();
#endif
    fseek (ifp, strip_offset+row*4, SEEK_SET);
    fseek (ifp, data_offset+get4(), SEEK_SET);
    ph1_bits(-1);
    FORC4 len[c] = row < 2 ? 7:4;
    for (col=0; col < raw_width; col+=16) {
      dir = ph1_bits(1);
      FORC4 op[c] = ph1_bits(2);
      FORC4 switch (op[c]) {
	case 3: len[c] = ph1_bits(4);	break;
	case 2: len[c]--;		break;
	case 1: len[c]++;
      }
      for (c = 0; c < 16; c += 2)
      {
        i = len[((c & 1) << 1) | (c >> 3)];
	unsigned idest = RAWINDEX(row, col + c);
	unsigned isrc = (dir ? RAWINDEX(row + (~c | -2), col + c) : col ? RAWINDEX(row, col + (c | -2)) : 0);
	if(idest < maxpixels && isrc < maxpixels) // less than zero is handled by unsigned conversion
  	RAW(row, col + c) = ((signed)ph1_bits(i) << (32 - i) >> (32 - i)) + 			                (dir ? RAW(row + (~c | -2), col + c) : col ? RAW(row, col + (c | -2)) : 128);
	else
  	  derror();
        if (c == 14)
          c = -1;
      }
    }
  }
  for (row=0; row < raw_height-1; row+=2)
    for (col=0; col < raw_width-1; col+=2)
      SWAP (RAW(row,col+1), RAW(row+1,col));
}

Project: LibRaw
File: dcraw.c

static float libraw_powf64(float a, float b)
{
  return powf_lim(a,b,64.f);
}

Project: LibRaw
File: dcraw.c

void CLASS leaf_hdr_load_raw()
{
  ushort *pixel=0;
  unsigned tile=0, r, c, row, col;

  if (!filters) {
#ifdef LIBRAW_LIBRARY_BUILD
    if(!image)
      throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
    pixel = (ushort *) calloc (raw_width, sizeof *pixel);
    merror (pixel, "leaf_hdr_load_raw()");
  }
#ifdef LIBRAW_LIBRARY_BUILD
  try {
#endif
  FORC(tiff_samples)
    for (r=0; r < raw_height; r++) {
#ifdef LIBRAW_LIBRARY_BUILD
    checkCancel();
#endif
      if (r % tile_length == 0) {
	fseek (ifp, data_offset + 4*tile++, SEEK_SET);
	fseek (ifp, get4(), SEEK_SET);
      }
      if (filters && c != shot_select) continue;
      if (filters) pixel = raw_image + r*raw_width;
      read_shorts (pixel, raw_width);
      if (!filters && (row = r - top_margin) < height)
	for (col=0; col < width; col++)
	  image[row*width+col][c] = pixel[col+left_margin];
    }
#ifdef LIBRAW_LIBRARY_BUILD
  } catch (...) {
    if(!filters) free(pixel);
    throw;
  }
#endif
  if (!filters) {
    maximum = 0xffff;
    raw_color = 1;
    free (pixel);
  }
}

Project: LibRaw
File: dcraw.c

void CLASS parse_exif (int base)
{
  unsigned kodak, entries, tag, type, len, save, c;
  double expo,ape;

  kodak = !strncmp(make,"EASTMAN",7) && tiff_nifds < 3;
  entries = get2();
  if(!strncmp(make,"Hasselblad",10) && (tiff_nifds > 3) && (entries > 512)) return;
#ifdef LIBRAW_LIBRARY_BUILD
  INT64 fsize = ifp->size();
#endif
  while (entries--) {
    tiff_get (base, &tag, &type, &len, &save);

#ifdef LIBRAW_LIBRARY_BUILD
    INT64 savepos = ftell(ifp);
    if(len > 8 && savepos + len > fsize*2) continue;
    if(callbacks.exif_cb)
      {
        callbacks.exif_cb(callbacks.exifparser_data,tag,type,len,order,ifp);
        fseek(ifp,savepos,SEEK_SET);
      }
#endif
    switch (tag) {
#ifdef LIBRAW_LIBRARY_BUILD
    case 0xa405:		// FocalLengthIn35mmFormat
      imgdata.lens.FocalLengthIn35mmFormat = get2();
      break;
    case 0xa431:		// BodySerialNumber
      stmread(imgdata.shootinginfo.BodySerial, len, ifp);
      break;
    case 0xa432:		// LensInfo, 42034dec, Lens Specification per EXIF standard
      imgdata.lens.MinFocal = getreal(type);
      imgdata.lens.MaxFocal = getreal(type);
      imgdata.lens.MaxAp4MinFocal = getreal(type);
      imgdata.lens.MaxAp4MaxFocal = getreal(type);
      break;
    case 0xa435:		// LensSerialNumber
      stmread(imgdata.lens.LensSerial, len, ifp);
      break;
    case 0xc630:		// DNG LensInfo, Lens Specification per EXIF standard
      imgdata.lens.dng.MinFocal = getreal(type);
      imgdata.lens.dng.MaxFocal = getreal(type);
      imgdata.lens.dng.MaxAp4MinFocal = getreal(type);
      imgdata.lens.dng.MaxAp4MaxFocal = getreal(type);
      break;
    case 0xa433:		// LensMake
      stmread(imgdata.lens.LensMake, len, ifp);
      break;
    case 0xa434:		// LensModel
      stmread(imgdata.lens.Lens, len, ifp);
      if (!strncmp(imgdata.lens.Lens, "----", 4))
        imgdata.lens.Lens[0] = 0;
      break;
    case 0x9205:
      imgdata.lens.EXIF_MaxAp = libraw_powf64(2.0f, (getreal(type) / 2.0f));
      break;
#endif
      case 33434:  tiff_ifd[tiff_nifds-1].t_shutter =
		   shutter = getreal(type);		break;
      case 33437:  aperture = getreal(type);		break;  // 0x829d FNumber
      case 34855:  iso_speed = get2();			break;
      case 34866:
        if (iso_speed == 0xffff && (!strncasecmp(make, "SONY",4) || !strncasecmp(make, "CANON",5)))
          iso_speed = getreal(type);
        break;
      case 36867:
      case 36868:  get_timestamp(0);			break;
      case 37377:  if ((expo = -getreal(type)) < 128 && shutter == 0.)
		     tiff_ifd[tiff_nifds-1].t_shutter =
			shutter = libraw_powf64(2.0, expo);
		break;
      case 37378:                                       // 0x9202 ApertureValue
        if ((fabs(ape = getreal(type))<256.0) && (!aperture))
          aperture = libraw_powf64(2.0, ape/2);
        break;
      case 37385:  flash_used = getreal(type);          break;
      case 37386:  focal_len = getreal(type);		break;
      case 37500:  	                         // tag 0x927c
#ifdef LIBRAW_LIBRARY_BUILD
       if (((make[0] == '\0') && (!strncmp(model, "ov5647",6))) ||
           ((!strncmp(make, "RaspberryPi",11)) && (!strncmp(model, "RP_OV5647",9))) ||
           ((!strncmp(make, "RaspberryPi",11)) && (!strncmp(model, "RP_imx219",9)))) {
        char mn_text[512];
        char *pos;
        char ccms[512];
        ushort l;
        float num;

	fgets(mn_text, MIN(len,511), ifp);
        mn_text[511] = 0;

        pos = strstr(mn_text, "gain_r=");
        if (pos)
          cam_mul[0] = atof(pos + 7);
        pos = strstr(mn_text, "gain_b=");
        if (pos)
          cam_mul[2] = atof(pos + 7);
        if ((cam_mul[0] > 0.001f) && (cam_mul[2] > 0.001f))
          cam_mul[1] = cam_mul[3] = 1.0f;
        else
          cam_mul[0] = cam_mul[2] = 0.0f;

        pos = strstr(mn_text, "ccm=");
        if(pos)
        {
         pos +=4;
         char *pos2 = strstr(pos, " ");
         if(pos2)
         {
           l = pos2 - pos;
           memcpy(ccms, pos, l);
           ccms[l] = '\0';
#if defined WIN32 || defined(__MINGW32__)
           // Win32 strtok is already thread-safe
          pos = strtok(ccms, ",");
#else
          char *last=0;
          pos = strtok_r(ccms, ",",&last);
#endif
          if(pos)
          {
            for (l = 0; l < 4; l++)
            {
              num = 0.0;
              for (c = 0; c < 3; c++)
              {
                imgdata.color.ccm[l][c] = (float)atoi(pos);
                num += imgdata.color.ccm[l][c];
#if defined WIN32 || defined(__MINGW32__)
                pos = strtok(NULL, ",");
#else
                pos = strtok_r(NULL, ",",&last);
#endif
                if(!pos) goto end; // broken
              }
              if (num > 0.01)
                FORC3 imgdata.color.ccm[l][c] = imgdata.color.ccm[l][c] / num;
            }
          }
        }
       }
      end:;
      }
      else
#endif
        parse_makernote (base, 0);
       break;
      case 40962:  if (kodak) raw_width  = get4();	break;
      case 40963:  if (kodak) raw_height = get4();	break;
      case 41730:
	if (get4() == 0x20002)
	  for (exif_cfa=c=0; c < 8; c+=2)
	    exif_cfa |= fgetc(ifp) * 0x01010101 << c;
    }
    fseek (ifp, save, SEEK_SET);
  }
}

Project: LibRaw
File: dcraw.c

void CLASS rollei_load_raw()
{
  uchar pixel[10];
  unsigned iten = 0, isix, i, buffer = 0, todo[16];
#ifdef LIBRAW_LIBRARY_BUILD
  if(raw_width > 32767 || raw_height > 32767)
    throw LIBRAW_EXCEPTION_IO_BADFILE;
#endif
  unsigned maxpixel = raw_width*(raw_height+7);

  isix = raw_width * raw_height * 5 / 8;
  while (fread (pixel, 1, 10, ifp) == 10) {
#ifdef LIBRAW_LIBRARY_BUILD
    checkCancel();
#endif
    for (i=0; i < 10; i+=2) {
      todo[i]   = iten++;
      todo[i+1] = pixel[i] << 8 | pixel[i+1];
      buffer    = pixel[i] >> 2 | buffer << 6;
    }
    for (   ; i < 16; i+=2) {
      todo[i]   = isix++;
      todo[i+1] = buffer >> (14-i)*5;
    }
    for (i = 0; i < 16; i += 2)
      if(todo[i] < maxpixel)
        raw_image[todo[i]] = (todo[i + 1] & 0x3ff);
      else
        derror();
  }
  maximum = 0x3ff;
}

Project: LibRaw
File: dcraw.c

void CLASS process_Sony_0x9050 (uchar * buf, unsigned id)
{
  ushort lid;

  if ((imgdata.lens.makernotes.CameraMount != LIBRAW_MOUNT_Sony_E) &&
      (imgdata.lens.makernotes.CameraMount != LIBRAW_MOUNT_FixedLens))
    {
      if (buf[0])
        imgdata.lens.makernotes.MaxAp4CurFocal =
          my_roundf(libraw_powf64(2.0f, ((float)SonySubstitution[buf[0]] / 8.0 - 1.06f) / 2.0f)*10.0f) / 10.0f;

      if (buf[1])
        imgdata.lens.makernotes.MinAp4CurFocal =
          my_roundf(libraw_powf64(2.0f, ((float)SonySubstitution[buf[1]] / 8.0 - 1.06f) / 2.0f)*10.0f) / 10.0f;
    }

  if (imgdata.lens.makernotes.CameraMount != LIBRAW_MOUNT_FixedLens)
    {
      if (buf[0x3d] | buf[0x3c])
        {
          lid = SonySubstitution[buf[0x3d]] << 8 |
            SonySubstitution[buf[0x3c]];
          imgdata.lens.makernotes.CurAp =
            libraw_powf64(2.0f, ((float)lid/256.0f - 16.0f) / 2.0f);
        }
      if (buf[0x105] &&
          (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF) &&
          (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Sigma_X3F))
        imgdata.lens.makernotes.LensMount =
          SonySubstitution[buf[0x105]];
      if (buf[0x106])
        imgdata.lens.makernotes.LensFormat =
          SonySubstitution[buf[0x106]];
    }

  if (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E)
    {
      parseSonyLensType2 (SonySubstitution[buf[0x0108]],		// LensType2 - Sony lens ids
                          SonySubstitution[buf[0x0107]]);
    }
  if ((imgdata.lens.makernotes.LensID == -1) &&
      (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Minolta_A) &&
      (buf[0x010a] | buf[0x0109]))
    {
      imgdata.lens.makernotes.LensID =		 // LensType - Minolta/Sony lens ids
        SonySubstitution[buf[0x010a]] << 8 |
        SonySubstitution[buf[0x0109]];

      if ((imgdata.lens.makernotes.LensID > 0x4900) &&
          (imgdata.lens.makernotes.LensID <= 0x5900))
        {
          imgdata.lens.makernotes.AdapterID = 0x4900;
          imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID;
          imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sigma_X3F;
          strcpy(imgdata.lens.makernotes.Adapter, "MC-11");
        }

      else if ((imgdata.lens.makernotes.LensID > 0xEF00) &&
          (imgdata.lens.makernotes.LensID < 0xFFFF)      &&
          (imgdata.lens.makernotes.LensID != 0xFF00))
        {
          imgdata.lens.makernotes.AdapterID = 0xEF00;
          imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID;
          imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF;
        }
    }

  if ((id >= 286) && (id <= 293))
    // "SLT-A65", "SLT-A77", "NEX-7", "NEX-VG20E",
    // "SLT-A37", "SLT-A57", "NEX-F3", "Lunar"
    parseSonyLensFeatures (SonySubstitution[buf[0x115]],
                           SonySubstitution[buf[0x116]]);
  else if (imgdata.lens.makernotes.CameraMount != LIBRAW_MOUNT_FixedLens)
    parseSonyLensFeatures(SonySubstitution[buf[0x116]], SonySubstitution[buf[0x117]]);

  if ((id == 347) || (id == 350) || (id == 357))
  {
    unsigned long long b88 = SonySubstitution[buf[0x88]];
    unsigned long long b89 = SonySubstitution[buf[0x89]];
    unsigned long long b8a = SonySubstitution[buf[0x8a]];
    unsigned long long b8b = SonySubstitution[buf[0x8b]];
    unsigned long long b8c = SonySubstitution[buf[0x8c]];
    unsigned long long b8d = SonySubstitution[buf[0x8d]];
    sprintf(imgdata.shootinginfo.InternalBodySerial, "%06llx",
            (b88 << 40) + (b89 << 32) + (b8a << 24) + (b8b << 16) + (b8c << 8) + b8d);
  }
  else if ((imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Minolta_A) && (id > 279) && (id != 282) && (id != 283))
  {
    unsigned long long bf0 = SonySubstitution[buf[0xf0]];
    unsigned long long bf1 = SonySubstitution[buf[0xf1]];
    unsigned long long bf2 = SonySubstitution[buf[0xf2]];
    unsigned long long bf3 = SonySubstitution[buf[0xf3]];
    unsigned long long bf4 = SonySubstitution[buf[0xf4]];
    sprintf(imgdata.shootinginfo.InternalBodySerial, "%05llx",
            (bf0 << 32) + (bf1 << 24) + (bf2 << 16) + (bf3 << 8) + bf4);
  }
  else if ((imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E) && (id != 288) && (id != 289) && (id != 290))
  {
    unsigned b7c = SonySubstitution[buf[0x7c]];
    unsigned b7d = SonySubstitution[buf[0x7d]];
    unsigned b7e = SonySubstitution[buf[0x7e]];
    unsigned b7f = SonySubstitution[buf[0x7f]];
    sprintf(imgdata.shootinginfo.InternalBodySerial, "%04x", (b7c << 24) + (b7d << 16) + (b7e << 8) + b7f);
  }

  return;
}

Project: LibRaw
File: dcraw.c

void CLASS parse_qt (int end)
{
  unsigned save, size;
  char tag[4];

  order = 0x4d4d;
  while (ftell(ifp)+7 < end) {
    save = ftell(ifp);
    if ((size = get4()) < 8) return;
    if ((int)size < 0) return; // 2+GB is too much
    if (save + size < save) return; // 32bit overflow
    fread (tag, 4, 1, ifp);
    if (!memcmp(tag,"moov",4) ||
	!memcmp(tag,"udta",4) ||
	!memcmp(tag,"CNTH",4))
      parse_qt (save+size);
    if (!memcmp(tag,"CNDA",4))
      parse_jpeg (ftell(ifp));
    fseek (ifp, save+size, SEEK_SET);
  }
}

Project: LibRaw
File: dcraw.c

void CLASS PentaxLensInfo (unsigned id, unsigned len)	// tag 0x0207
{
	ushort iLensData = 0;
	uchar *table_buf;
	table_buf = (uchar*)malloc(MAX(len,128));
	fread(table_buf, len, 1, ifp);
	if ((id < 0x12b9c)  ||
        (((id == 0x12b9c)   ||  // K100D
          (id == 0x12b9d)   ||  // K110D
          (id == 0x12ba2)) &&   // K100D Super
		 ((!table_buf[20] ||
		  (table_buf[20] == 0xff)))))
	  {
		iLensData = 3;
		if (imgdata.lens.makernotes.LensID == -1)
		  imgdata.lens.makernotes.LensID =
			(((unsigned)table_buf[0]) << 8) + table_buf[1];
	  }
	else switch (len)
	  {
	  case 90:							// LensInfo3
		iLensData = 13;
		if (imgdata.lens.makernotes.LensID == -1)
		  imgdata.lens.makernotes.LensID =
			((unsigned)((table_buf[1] & 0x0f) + table_buf[3]) <<8) + table_buf[4];
		break;
	  case 91:							// LensInfo4
		iLensData = 12;
		if (imgdata.lens.makernotes.LensID == -1)
		  imgdata.lens.makernotes.LensID =
			((unsigned)((table_buf[1] & 0x0f) + table_buf[3]) <<8) + table_buf[4];
		break;
	  case 80:							// LensInfo5
	  case 128:
		iLensData = 15;
		if (imgdata.lens.makernotes.LensID == -1)
		  imgdata.lens.makernotes.LensID =
			((unsigned)((table_buf[1] & 0x0f) + table_buf[4]) <<8) + table_buf[5];
		break;
	  default:
		if (id >= 0x12b9c)				// LensInfo2
		  {
			iLensData = 4;
			if (imgdata.lens.makernotes.LensID == -1)
			  imgdata.lens.makernotes.LensID =
				((unsigned)((table_buf[0] & 0x0f) + table_buf[2]) <<8) + table_buf[3];
		  }
	  }
	if (iLensData)
	  {
		if (table_buf[iLensData+9] &&
			(fabs(imgdata.lens.makernotes.CurFocal) < 0.1f))
		  imgdata.lens.makernotes.CurFocal =
			10*(table_buf[iLensData+9]>>2) * libraw_powf64(4, (table_buf[iLensData+9] & 0x03)-2);
		if (table_buf[iLensData+10] & 0xf0)
		  imgdata.lens.makernotes.MaxAp4CurFocal =
			libraw_powf64(2.0f, (float)((table_buf[iLensData+10] & 0xf0) >>4)/4.0f);
		if (table_buf[iLensData+10] & 0x0f)
		  imgdata.lens.makernotes.MinAp4CurFocal =
			libraw_powf64(2.0f, (float)((table_buf[iLensData+10] & 0x0f) + 10)/4.0f);

		if (iLensData != 12)
		  {
			switch (table_buf[iLensData] & 0x06)
			  {
			  case 0: imgdata.lens.makernotes.MinAp4MinFocal = 22.0f; break;
			  case 2: imgdata.lens.makernotes.MinAp4MinFocal = 32.0f; break;
			  case 4: imgdata.lens.makernotes.MinAp4MinFocal = 45.0f; break;
			  case 6: imgdata.lens.makernotes.MinAp4MinFocal = 16.0f; break;
			  }
			if (table_buf[iLensData] & 0x70)
			  imgdata.lens.makernotes.LensFStops =
				((float)(((table_buf[iLensData] & 0x70) >> 4) ^ 0x07)) / 2.0f + 5.0f;

			imgdata.lens.makernotes.MinFocusDistance = (float)(table_buf[iLensData+3] & 0xf8);
			imgdata.lens.makernotes.FocusRangeIndex = (float)(table_buf[iLensData+3] & 0x07);

			if ((table_buf[iLensData+14] > 1) &&
				(fabs(imgdata.lens.makernotes.MaxAp4CurFocal) < 0.7f))
			  imgdata.lens.makernotes.MaxAp4CurFocal =
				libraw_powf64(2.0f, (float)((table_buf[iLensData+14] & 0x7f) -1)/32.0f);
		  }
		else if ((id != 0x12e76) &&	// K-5
				 (table_buf[iLensData+15] > 1) &&
				 (fabs(imgdata.lens.makernotes.MaxAp4CurFocal) < 0.7f))
		  {
			imgdata.lens.makernotes.MaxAp4CurFocal =
			  libraw_powf64(2.0f, (float)((table_buf[iLensData+15] & 0x7f) -1)/32.0f);
		  }
	  }
	free(table_buf);
	return;
}

Project: LibRaw
File: dcraw.c

void CLASS parse_phase_one (int base)
{
  unsigned entries, tag, type, len, data, save, i, c;
  float romm_cam[3][3];
  char *cp;

  memset (&ph1, 0, sizeof ph1);
  fseek (ifp, base, SEEK_SET);
  order = get4() & 0xffff;
  if (get4() >> 8 != 0x526177) return;		/* "Raw" */
  fseek (ifp, get4()+base, SEEK_SET);
  entries = get4();
  get4();
  while (entries--) {
    tag  = get4();
    type = get4();
    len  = get4();
    data = get4();
    save = ftell(ifp);
    fseek (ifp, base+data, SEEK_SET);
    switch (tag) {

#ifdef LIBRAW_LIBRARY_BUILD
    case 0x0102:
      stmread(imgdata.shootinginfo.BodySerial, len, ifp);
      if ((imgdata.shootinginfo.BodySerial[0] == 0x4c) && (imgdata.shootinginfo.BodySerial[1] == 0x49)) {
        unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[2] & 0x3f)) - 0x41;
      } else {
        unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[1] & 0x3f)) - 0x41;
      }
      setPhaseOneFeatures(unique_id);
      break;
    case 0x0401:
      if (type == 4) imgdata.lens.makernotes.CurAp =  libraw_powf64(2.0f, (int_to_float(data)/2.0f));
      else imgdata.lens.makernotes.CurAp = libraw_powf64(2.0f, (getreal(type)/2.0f));
      break;
    case 0x0403:
      if (type == 4) imgdata.lens.makernotes.CurFocal =  int_to_float(data);
      else imgdata.lens.makernotes.CurFocal = getreal(type);
      break;
    case 0x0410:
      stmread(imgdata.lens.makernotes.body, len, ifp);
      break;
    case 0x0412:
      stmread(imgdata.lens.makernotes.Lens, len, ifp);
      break;
    case 0x0414:
      if (type == 4) {
      	imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64(2.0f, (int_to_float(data)/2.0f));
      } else {
        imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64(2.0f, (getreal(type) / 2.0f));
      }
      break;
    case 0x0415:
      if (type == 4) {
      	imgdata.lens.makernotes.MinAp4CurFocal = libraw_powf64(2.0f, (int_to_float(data)/2.0f));
      } else {
        imgdata.lens.makernotes.MinAp4CurFocal = libraw_powf64(2.0f, (getreal(type) / 2.0f));
      }
      break;
    case 0x0416:
      if (type == 4) {
        imgdata.lens.makernotes.MinFocal =  int_to_float(data);
      } else {
        imgdata.lens.makernotes.MinFocal = getreal(type);
      }
      if (imgdata.lens.makernotes.MinFocal > 1000.0f)
        {
          imgdata.lens.makernotes.MinFocal = 0.0f;
        }
      break;
    case 0x0417:
      if (type == 4) {
        imgdata.lens.makernotes.MaxFocal =  int_to_float(data);
      } else {
        imgdata.lens.makernotes.MaxFocal = getreal(type);
      }
      break;
#endif

      case 0x100:  flip = "0653"[data & 3]-'0';  break;
      case 0x106:
	for (i=0; i < 9; i++)
#ifdef LIBRAW_LIBRARY_BUILD
	imgdata.color.P1_color[0].romm_cam[i]=
#endif
	  ((float *)romm_cam)[i] = getreal(11);
	romm_coeff (romm_cam);
	break;
      case 0x107:
	FORC3 cam_mul[c] = getreal(11);
	break;
      case 0x108:  raw_width     = data;	break;
      case 0x109:  raw_height    = data;	break;
      case 0x10a:  left_margin   = data;	break;
      case 0x10b:  top_margin    = data;	break;
      case 0x10c:  width         = data;	break;
      case 0x10d:  height        = data;	break;
      case 0x10e:  ph1.format    = data;	break;
      case 0x10f:  data_offset   = data+base;	break;
      case 0x110:  meta_offset   = data+base;
		   meta_length   = len;			break;
      case 0x112:  ph1.key_off   = save - 4;		break;
      case 0x210:  ph1.tag_210   = int_to_float(data);	break;
      case 0x21a:  ph1.tag_21a   = data;		break;
      case 0x21c:  strip_offset  = data+base;		break;
      case 0x21d:  ph1.t_black     = data;		break;
      case 0x222:  ph1.split_col = data;		break;
      case 0x223:  ph1.black_col = data+base;		break;
      case 0x224:  ph1.split_row = data;		break;
      case 0x225:  ph1.black_row = data+base;		break;
#ifdef LIBRAW_LIBRARY_BUILD
      case 0x226:
	for (i=0; i < 9; i++)
	  imgdata.color.P1_color[1].romm_cam[i] = getreal(11);
	break;
#endif
      case 0x301:
	model[63] = 0;
	fread (model, 1, 63, ifp);
	if ((cp = strstr(model," camera"))) *cp = 0;
    }
    fseek (ifp, save, SEEK_SET);
  }

#ifdef LIBRAW_LIBRARY_BUILD
  if (!imgdata.lens.makernotes.body[0] && !imgdata.shootinginfo.BodySerial[0]) {
    fseek (ifp, meta_offset, SEEK_SET);
    order = get2();
    fseek (ifp, 6, SEEK_CUR);
    fseek (ifp, meta_offset+get4(), SEEK_SET);
    entries = get4();  get4();
    while (entries--) {
      tag  = get4();
      len  = get4();
      data = get4();
      save = ftell(ifp);
      fseek (ifp, meta_offset+data, SEEK_SET);
      if (tag == 0x0407) {
        stmread(imgdata.shootinginfo.BodySerial, len, ifp);
        if ((imgdata.shootinginfo.BodySerial[0] == 0x4c) && (imgdata.shootinginfo.BodySerial[1] == 0x49)) {
          unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[2] & 0x3f)) - 0x41;
        } else {
          unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[1] & 0x3f)) - 0x41;
        }
        setPhaseOneFeatures(unique_id);
      }
      fseek (ifp, save, SEEK_SET);
    }
  }
#endif

  load_raw = ph1.format < 3 ?
	&CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
  maximum = 0xffff;
  strcpy (make, "Phase One");
  if (model[0]) return;
  switch (raw_height) {
    case 2060: strcpy (model,"LightPhase");	break;
    case 2682: strcpy (model,"H 10");		break;
    case 4128: strcpy (model,"H 20");		break;
    case 5488: strcpy (model,"H 25");		break;
  }
}