Example #1
0
X3fDecoder::X3fDecoder(FileMap* file) :
RawDecoder(file), bytes(NULL) {
  decoderVersion = 1;
  huge_table = NULL;
  line_offsets = NULL;
  if (getHostEndianness() == little)
    bytes = new ByteStream(file->getData(0), file->getSize());
  else
    bytes = new ByteStreamSwap(file->getData(0), file->getSize());
}
Example #2
0
void KdcDecoder::decodeMetaDataInternal(CameraMetaData *meta) {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);

  if (data.empty())
    ThrowRDE("KDC Decoder: Model name found");
  if (!data[0]->hasEntry(MAKE))
    ThrowRDE("KDC Decoder: Make name not found");

  string make = data[0]->getEntry(MAKE)->getString();
  string model = data[0]->getEntry(MODEL)->getString();
  setMetaData(meta, make, model, "", 0);

  // Try the kodak hidden IFD for WB
  if (mRootIFD->hasEntryRecursive(KODAK_IFD2)) {
    TiffEntry *ifdoffset = mRootIFD->getEntryRecursive(KODAK_IFD2);
    TiffIFD *kodakifd = NULL;
    try {
      if (mRootIFD->endian == getHostEndianness())
        kodakifd = new TiffIFD(mFile, ifdoffset->getInt());
      else
        kodakifd = new TiffIFDBE(mFile, ifdoffset->getInt());

     if (kodakifd && kodakifd->hasEntryRecursive(KODAK_KDC_WB)) {
        TiffEntry *wb = kodakifd->getEntryRecursive(KODAK_KDC_WB);
        if (wb->count == 3) {
          const uint32 *tmp = wb->getIntArray();
          mRaw->metadata.wbCoeffs[0] = (float)tmp[0];
          mRaw->metadata.wbCoeffs[1] = (float)tmp[1];
          mRaw->metadata.wbCoeffs[2] = (float)tmp[2];
        }
      }
    } catch(TiffParserException e) {
      mRaw->setError(e.what());
    }
    if (kodakifd)
      delete kodakifd;
  }

  // Use the normal WB if available
  if (mRootIFD->hasEntryRecursive(KODAKWB)) {
    TiffEntry *wb = mRootIFD->getEntryRecursive(KODAKWB);
    if (wb->count == 734 || wb->count == 1502) {
      const uchar8 *tmp = wb->getData();
      mRaw->metadata.wbCoeffs[0] = (float)((((ushort16) tmp[148])<<8)|tmp[149])/256.0f;
      mRaw->metadata.wbCoeffs[1] = 1.0f;
      mRaw->metadata.wbCoeffs[2] = (float)((((ushort16) tmp[150])<<8)|tmp[151])/256.0f;
    }
  }
}
Example #3
0
void MrwDecoder::parseHeader() {
  const unsigned char* data = mFile->getData(0);
  
  if (mFile->getSize() < 30)
    ThrowRDE("Not a valid MRW file (size too small)");

  if (!isMRW(mFile))
    ThrowRDE("This isn't actually a MRW file, why are you calling me?");
    
  data_offset = get4BE(data,4)+8;

  if (!mFile->isValid(data_offset))
    ThrowRDE("MRW: Data offset is invalid");

  // Make sure all values have at least been initialized
  raw_width = raw_height = packed = 0;
  wb_coeffs[0] = wb_coeffs[1] = wb_coeffs[2] = wb_coeffs[3] = NAN;

  uint32 currpos = 8;
  while (currpos < data_offset) {
    uint32 tag = get4BE(data,currpos);
    uint32 len = get4BE(data,currpos+4);
    switch(tag) {
    case 0x505244: // PRD
      raw_height = get2BE(data,currpos+16);
      raw_width = get2BE(data,currpos+18);
      packed = (data[currpos+24] == 12);
    case 0x574247: // WBG
      for(uint32 i=0; i<4; i++)
        wb_coeffs[i] = (float)get2BE(data, currpos+12+i*2);
      break;
    case 0x545457: // TTW
      // Base value for offsets needs to be at the beginning of the TIFF block, not the file
      FileMap *f = new FileMap(mFile->getDataWrt(currpos+8), mFile->getSize()-currpos-8);
      if (little == getHostEndianness())
        tiff_meta = new TiffIFDBE(f, 8);
      else
        tiff_meta = new TiffIFD(f, 8);
      delete f;
      break;
    }
    currpos += MAX(len+8,1); // MAX(,1) to make sure we make progress
  }
}
Example #4
0
AriDecoder::AriDecoder(FileMap* file) : RawDecoder(file) {
  if (mFile->getSize() < 4096) {
    ThrowRDE("ARRI: File too small (no header)");
  }
  try {
    ByteStream *s;
    if (getHostEndianness() == little) {
      s = new ByteStream(mFile->getData(8), mFile->getSize()- 8);
    } else {
      s = new ByteStreamSwap(mFile->getData(8), mFile->getSize()- 8);
    }
    mDataOffset = s->getInt();
    uint32 someNumber = s->getInt(); // Value: 3?
    uint32 segmentLength = s->getInt(); // Value: 0x3c = length
	if (someNumber != 3 || segmentLength != 0x3c) {
		ThrowRDE("Unknown values in ARRIRAW header, %d, %d", someNumber, segmentLength);
	}
    mWidth = s->getInt();
    mHeight = s->getInt();
    s->setAbsoluteOffset(0x40);
    mDataSize = s->getInt();

    // Smells like whitebalance
    s->setAbsoluteOffset(0x5c);
    mWB[0] = s->getFloat();  // 1.3667001 in sample
    mWB[1] = s->getFloat();  // 1.0000000 in sample
    mWB[2] = s->getFloat();  // 1.6450000 in sample

    // Smells like iso
    s->setAbsoluteOffset(0xb8);
    mIso = s->getInt();  // 100 in sample

    s->setAbsoluteOffset(0x29c-8);
    mModel = s->getString();
    s->setAbsoluteOffset(0x2a4-8);
    mEncoder = s->getString();
  } catch (IOException &e) {
    ThrowRDE("ARRI: IO Exception:%s", e.what());
  }
}
Example #5
0
X3fParser::X3fParser(FileMap* file) {
  decoder = NULL;
  bytes = NULL;
  mFile = file;
  uint32 size = file->getSize();
  if (size<104+128)
    ThrowRDE("X3F file too small");

  if (getHostEndianness() == little)
    bytes = new ByteStream(file->getData(0), size);
  else
    bytes = new ByteStreamSwap(file->getData(0), size);
  try {
    try {
      // Read signature
      if (bytes->getUInt() != 0x62564f46)
        ThrowRDE("X3F Decoder: Not an X3f file (Signature)");

      uint32 version = bytes->getUInt();
      if (version < 0x00020000)
        ThrowRDE("X3F Decoder: File version too old");

      // Skip identifier + mark bits
      bytes->skipBytes(16+4);

      bytes->setAbsoluteOffset(0);
      decoder = new X3fDecoder(file);
      readDirectory();
    } catch (IOException e) {
      ThrowRDE("X3F Decoder: IO Error while reading header: %s", e.what());
    }
  } catch (RawDecoderException e) {
    freeObjects();
    throw e;
  }
}
Example #6
0
RawImage NefDecoder::decodeRawInternal() {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(CFAPATTERN);

  if (data.empty())
    ThrowRDE("NEF Decoder: No image data found");

  TiffIFD* raw = data[0];
  int compression = raw->getEntry(COMPRESSION)->getInt();

  data = mRootIFD->getIFDsWithTag(MODEL);

  if (data.empty())
    ThrowRDE("NEF Decoder: No model data found");

  TiffEntry *offsets = raw->getEntry(STRIPOFFSETS);
  TiffEntry *counts = raw->getEntry(STRIPBYTECOUNTS);

  if (!data[0]->getEntry(MODEL)->getString().compare("NIKON D100 ")) {  /**Sigh**/
    if (!mFile->isValid(offsets->getInt()))
      ThrowRDE("NEF Decoder: Image data outside of file.");
    if (!D100IsCompressed(offsets->getInt())) {
      DecodeD100Uncompressed();
      return mRaw;
    }
  }

  if (compression == 1 || (hints.find(string("force_uncompressed")) != hints.end()) ||
      NEFIsUncompressed(raw)) {
    DecodeUncompressed();
    return mRaw;
  }

  if (NEFIsUncompressedRGB(raw)) {
    DecodeSNefUncompressed();
    return mRaw;
  }

  if (offsets->count != 1) {
    ThrowRDE("NEF Decoder: Multiple Strips found: %u", offsets->count);
  }
  if (counts->count != offsets->count) {
    ThrowRDE("NEF Decoder: Byte count number does not match strip size: count:%u, strips:%u ", counts->count, offsets->count);
  }
  if (!mFile->isValid(offsets->getInt(), counts->getInt()))
    ThrowRDE("NEF Decoder: Invalid strip byte count. File probably truncated.");


  if (34713 != compression)
    ThrowRDE("NEF Decoder: Unsupported compression");

  uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
  uint32 height = raw->getEntry(IMAGELENGTH)->getInt();
  uint32 bitPerPixel = raw->getEntry(BITSPERSAMPLE)->getInt();

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();

  data = mRootIFD->getIFDsWithTag((TiffTag)0x8c);

  if (data.empty())
    ThrowRDE("NEF Decoder: Decompression info tag not found");

  TiffEntry *meta;
  if (data[0]->hasEntry((TiffTag)0x96)) {
    meta = data[0]->getEntry((TiffTag)0x96);
  } else {
    meta = data[0]->getEntry((TiffTag)0x8c);  // Fall back
  }

  try {
    NikonDecompressor decompressor(mFile, mRaw);
    decompressor.uncorrectedRawValues = uncorrectedRawValues;
    ByteStream* metastream;
    if (getHostEndianness() == data[0]->endian)
      metastream = new ByteStream(meta->getData(), meta->count);
    else
      metastream = new ByteStreamSwap(meta->getData(), meta->count);

    decompressor.DecompressNikon(metastream, width, height, bitPerPixel, offsets->getInt(), counts->getInt());

    delete metastream;
  } catch (IOException &e) {
    mRaw->setError(e.what());
    // Let's ignore it, it may have delivered somewhat useful data.
  }

  return mRaw;
}
Example #7
0
TiffParser::TiffParser(FileMap* inputData): mInput(inputData), mRootIFD(0) {
    host_endian = getHostEndianness();
}
Example #8
0
RawImage Cr2Decoder::decodeRawInternal() {
  if(hints.find("old_format") != hints.end()) {
    uint32 off = 0;
    if (mRootIFD->getEntryRecursive((TiffTag)0x81))
      off = mRootIFD->getEntryRecursive((TiffTag)0x81)->getInt();
    else {
      vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(CFAPATTERN);
      if (data.empty())
        ThrowRDE("CR2 Decoder: Couldn't find offset");
      else {
        if (data[0]->hasEntry(STRIPOFFSETS))
          off = data[0]->getEntry(STRIPOFFSETS)->getInt();
        else
          ThrowRDE("CR2 Decoder: Couldn't find offset");
      }
    }

    ByteStream *b;
    if (getHostEndianness() == big)
      b = new ByteStream(mFile, off+41);
    else
      b = new ByteStreamSwap(mFile, off+41);
    uint32 height = b->getShort();
    uint32 width = b->getShort();

    // Every two lines can be encoded as a single line, probably to try and get
    // better compression by getting the same RGBG sequence in every line
    if(hints.find("double_line_ljpeg") != hints.end()) {
      height *= 2;
      mRaw->dim = iPoint2D(width*2, height/2);
    }
    else {
      width *= 2;
      mRaw->dim = iPoint2D(width, height);
    }

    mRaw->createData();
    LJpegPlain *l = new LJpegPlain(mFile, mRaw);
    try {
      l->startDecoder(off, mFile->getSize()-off, 0, 0);
    } catch (IOException& e) {
      mRaw->setError(e.what());
    }

    delete l;

    if(hints.find("double_line_ljpeg") != hints.end()) {
      // We now have a double width half height image we need to convert to the
      // normal format
      iPoint2D final_size(width, height);
      RawImage procRaw = RawImage::create(final_size, TYPE_USHORT16, 1);
      procRaw->metadata = mRaw->metadata;
      procRaw->copyErrorsFrom(mRaw);

      for (uint32 y = 0; y < height; y++) {
        ushort16 *dst = (ushort16*)procRaw->getData(0,y);
        ushort16 *src = (ushort16*)mRaw->getData(y%2 == 0 ? 0 : width, y/2);
        for (uint32 x = 0; x < width; x++)
          dst[x] = src[x];
      }
      mRaw = procRaw;
    }

    if (mRootIFD->getEntryRecursive((TiffTag)0x123)) {
      TiffEntry *curve = mRootIFD->getEntryRecursive((TiffTag)0x123);
      if (curve->type == TIFF_SHORT && curve->count == 4096) {
        TiffEntry *linearization = mRootIFD->getEntryRecursive((TiffTag)0x123);
        uint32 len = linearization->count;
        ushort16 *table = new ushort16[len];
        linearization->getShortArray(table, len);
        if (!uncorrectedRawValues) {
          mRaw->setTable(table, 4096, true);
          // Apply table
          mRaw->sixteenBitLookup();
          // Delete table
          mRaw->setTable(NULL);
        } else {
          // We want uncorrected, but we store the table.
          mRaw->setTable(table, 4096, false);
        }
      }
    }

    return mRaw;
  }

  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag((TiffTag)0xc5d8);

  if (data.empty())
    ThrowRDE("CR2 Decoder: No image data found");


  TiffIFD* raw = data[0];
  mRaw = RawImage::create();
  mRaw->isCFA = true;
  vector<Cr2Slice> slices;
  int completeH = 0;
  bool doubleHeight = false;

  try {
    TiffEntry *offsets = raw->getEntry(STRIPOFFSETS);
    TiffEntry *counts = raw->getEntry(STRIPBYTECOUNTS);
    // Iterate through all slices
    for (uint32 s = 0; s < offsets->count; s++) {
      Cr2Slice slice;
      slice.offset = offsets[0].getInt();
      slice.count = counts[0].getInt();
      SOFInfo sof;
      LJpegPlain *l = new LJpegPlain(mFile, mRaw);
      l->getSOF(&sof, slice.offset, slice.count);
      delete l;
      slice.w = sof.w * sof.cps;
      slice.h = sof.h;
      if (sof.cps == 4 && slice.w > slice.h * 4) {
        doubleHeight = true;
      }
      if (!slices.empty())
        if (slices[0].w != slice.w)
          ThrowRDE("CR2 Decoder: Slice width does not match.");

      if (mFile->isValid(slice.offset, slice.count)) // Only decode if size is valid
        slices.push_back(slice);
      completeH += slice.h;
    }
  } catch (TiffParserException) {
    ThrowRDE("CR2 Decoder: Unsupported format.");
  }

  // Override with canon_double_height if set.
  map<string,string>::iterator msb_hint = hints.find("canon_double_height");
  if (msb_hint != hints.end())
    doubleHeight = (0 == (msb_hint->second).compare("true"));

  if (slices.empty()) {
    ThrowRDE("CR2 Decoder: No Slices found.");
  }
  mRaw->dim = iPoint2D(slices[0].w, completeH);

  // Fix for Canon 6D mRaw, which has flipped width & height for some part of the image
  // In that case, we swap width and height, since this is the correct dimension
  bool flipDims = false;
  bool wrappedCr2Slices = false;
  if (raw->hasEntry((TiffTag)0xc6c5)) {
    ushort16 ss = raw->getEntry((TiffTag)0xc6c5)->getInt();
    // sRaw
    if (ss == 4) {
      mRaw->dim.x /= 3;
      mRaw->setCpp(3);
      mRaw->isCFA = false;

      // Fix for Canon 80D mraw format.
      // In that format, the frame (as read by getSOF()) is 4032x3402, while the
      // real image should be 4536x3024 (where the full vertical slices in
      // the frame "wrap around" the image.
      if (hints.find("wrapped_cr2_slices") != hints.end() && raw->hasEntry(IMAGEWIDTH) && raw->hasEntry(IMAGELENGTH)) {
        wrappedCr2Slices = true;
        int w = raw->getEntry(IMAGEWIDTH)->getInt();
        int h = raw->getEntry(IMAGELENGTH)->getInt();
        if (w * h != mRaw->dim.x * mRaw->dim.y) {
          ThrowRDE("CR2 Decoder: Wrapped slices don't match image size");
        }
        mRaw->dim = iPoint2D(w, h);
      }
    }
    flipDims = mRaw->dim.x < mRaw->dim.y;
    if (flipDims) {
      int w = mRaw->dim.x;
      mRaw->dim.x = mRaw->dim.y;
      mRaw->dim.y = w;
    }
  }

  mRaw->createData();

  vector<int> s_width;
  if (raw->hasEntry(CANONCR2SLICE)) {
    TiffEntry *ss = raw->getEntry(CANONCR2SLICE);
    for (int i = 0; i < ss->getShort(0); i++) {
      s_width.push_back(ss->getShort(1));
    }
    s_width.push_back(ss->getShort(2));
  } else {
    s_width.push_back(slices[0].w);
  }
  uint32 offY = 0;

  if (s_width.size() > 15)
    ThrowRDE("CR2 Decoder: No more than 15 slices supported");
  _RPT1(0,"Org slices:%d\n", s_width.size());
  for (uint32 i = 0; i < slices.size(); i++) {
    Cr2Slice slice = slices[i];
    try {
      LJpegPlain *l = new LJpegPlain(mFile, mRaw);
      l->addSlices(s_width);
      l->mUseBigtable = true;
      l->mCanonFlipDim = flipDims;
      l->mCanonDoubleHeight = doubleHeight;
      l->mWrappedCr2Slices = wrappedCr2Slices;
      l->startDecoder(slice.offset, slice.count, 0, offY);
      delete l;
    } catch (RawDecoderException &e) {
      if (i == 0)
        throw;
      // These may just be single slice error - store the error and move on
      mRaw->setError(e.what());
    } catch (IOException &e) {
      // Let's try to ignore this - it might be truncated data, so something might be useful.
      mRaw->setError(e.what());
    }
    offY += slice.w;
  }

  if (mRaw->metadata.subsampling.x > 1 || mRaw->metadata.subsampling.y > 1)
    sRawInterpolate();

  return mRaw;
}
Example #9
0
RawImage NefDecoder::decodeRawInternal() {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(CFAPATTERN);

  if (data.empty())
    ThrowRDE("NEF Decoder: No image data found");

  TiffIFD* raw = data[0];
  int compression = raw->getEntry(COMPRESSION)->getInt();

  data = mRootIFD->getIFDsWithTag(MODEL);

  if (data.empty())
    ThrowRDE("NEF Decoder: No model data found");

  TiffEntry *offsets = raw->getEntry(STRIPOFFSETS);
  TiffEntry *counts = raw->getEntry(STRIPBYTECOUNTS);

  if (!data[0]->getEntry(MODEL)->getString().compare("NIKON D100 ")) {  /**Sigh**/
    if (!mFile->isValid(offsets->getInt()))
      ThrowRDE("NEF Decoder: Image data outside of file.");
    if (!D100IsCompressed(offsets->getInt())) {
      DecodeD100Uncompressed();
      return mRaw;
    }
  }

  if (compression == 1) {
    DecodeUncompressed();
    return mRaw;
  }

  if (offsets->count != 1) {
    ThrowRDE("NEF Decoder: Multiple Strips found: %u", offsets->count);
  }
  if (counts->count != offsets->count) {
    ThrowRDE("NEF Decoder: Byte count number does not match strip size: count:%u, strips:%u ", counts->count, offsets->count);
  }
  if (!mFile->isValid(offsets->getInt() + counts->getInt()))
    ThrowRDE("NEF Decoder: Invalid strip byte count. File probably truncated.");


  if (34713 != compression)
    ThrowRDE("NEF Decoder: Unsupported compression");

  uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
  uint32 height = raw->getEntry(IMAGELENGTH)->getInt();
  uint32 bitPerPixel = raw->getEntry(BITSPERSAMPLE)->getInt();

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();

  data = mRootIFD->getIFDsWithTag(MAKERNOTE);
  if (data.empty())
    ThrowRDE("NEF Decoder: No EXIF data found");

  TiffIFD* exif = data[0];
  TiffEntry *makernoteEntry = exif->getEntry(MAKERNOTE);
  const uchar8* makernote = makernoteEntry->getData();
  FileMap makermap((uchar8*)&makernote[10], mFile->getSize() - makernoteEntry->getDataOffset() - 10);
  TiffParser makertiff(&makermap);
  makertiff.parseData();

  data = makertiff.RootIFD()->getIFDsWithTag((TiffTag)0x8c);

  if (data.empty())
    ThrowRDE("NEF Decoder: Decompression info tag not found");

  TiffEntry *meta;
  try {
    meta = data[0]->getEntry((TiffTag)0x96);
  } catch (TiffParserException) {
    meta = data[0]->getEntry((TiffTag)0x8c);  // Fall back
  }

  try {
    NikonDecompressor decompressor(mFile, mRaw);

    ByteStream* metastream;
    if (getHostEndianness() == data[0]->endian)
      metastream = new ByteStream(meta->getData(), meta->count);
    else
      metastream = new ByteStreamSwap(meta->getData(), meta->count);

    decompressor.DecompressNikon(metastream, width, height, bitPerPixel, offsets->getInt(), counts->getInt());

    delete metastream;
  } catch (IOException &e) {
    mRaw->setError(e.what());
    // Let's ignore it, it may have delivered somewhat useful data.
  }

  return mRaw;
}