Пример #1
0
void PefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
  int iso = 0;
  mRaw->cfa.setCFA(iPoint2D(2,2), CFA_RED, CFA_GREEN, CFA_GREEN, CFA_BLUE);

  if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
    iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getU32();

  setMetaData(meta, "", iso);

  // Read black level
  if (mRootIFD->hasEntryRecursive(static_cast<TiffTag>(0x200))) {
    TiffEntry* black = mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x200));
    if (black->count == 4) {
      for (int i = 0; i < 4; i++)
        mRaw->blackLevelSeparate[i] = black->getU32(i);
    }
  }

  // Set the whitebalance
  if (mRootIFD->hasEntryRecursive(static_cast<TiffTag>(0x0201))) {
    TiffEntry* wb = mRootIFD->getEntryRecursive(static_cast<TiffTag>(0x0201));
    if (wb->count == 4) {
      mRaw->metadata.wbCoeffs[0] = wb->getU32(0);
      mRaw->metadata.wbCoeffs[1] = wb->getU32(1);
      mRaw->metadata.wbCoeffs[2] = wb->getU32(3);
    }
  }
}
Пример #2
0
RawImage CrwDecoder::decodeRawInternal() {
    CiffEntry *sensorInfo = mRootIFD->getEntryRecursive(CIFF_SENSORINFO);

    if (!sensorInfo || sensorInfo->count < 6 || sensorInfo->type != CIFF_SHORT)
        ThrowRDE("CRW: Couldn't find image sensor info");

    uint32 width = sensorInfo->getShort(1);
    uint32 height = sensorInfo->getShort(2);

    CiffEntry *decTable = mRootIFD->getEntryRecursive(CIFF_DECODERTABLE);
    if (!decTable || decTable->type != CIFF_LONG)
        ThrowRDE("CRW: Couldn't find decoder table");

    uint32 dec_table = decTable->getInt();
    if (dec_table > 2)
        ThrowRDE("CRW: Unknown decoder table %d", dec_table);

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

    bool lowbits = hints.find("no_decompressed_lowbits") == hints.end();
    decodeRaw(lowbits, dec_table, width, height);

    return mRaw;
}
Пример #3
0
RawImage KdcDecoder::decodeRawInternal() {
  int compression = mRootIFD->getEntryRecursive(COMPRESSION)->getInt();
  if (7 != compression)
    ThrowRDE("KDC Decoder: Unsupported compression %d", compression);

  TiffEntry *ex = mRootIFD->getEntryRecursive(PIXELXDIMENSION);
  TiffEntry *ey = mRootIFD->getEntryRecursive(PIXELYDIMENSION);

  if (NULL == ex || NULL == ey)
    ThrowRDE("KDC Decoder: Unable to retrieve image size");

  uint32 width = ex->getInt();
  uint32 height = ey->getInt();

  TiffEntry *offset = mRootIFD->getEntryRecursive(KODAK_KDC_OFFSET);
  if (!offset || offset->count < 13)
    ThrowRDE("KDC Decoder: Couldn't find the KDC offset");
  const uint32 *offsetarray = offset->getIntArray();
  uint32 off = offsetarray[4] + offsetarray[12];

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();
  ByteStream input(mFile->getData(off), mFile->getSize()-off);

  Decode12BitRawBE(input, width, height);

  return mRaw;
}
Пример #4
0
RawImage MrwDecoder::decodeRawInternal() {
  uint32 imgsize;

  mRaw->dim = iPoint2D(raw_width, raw_height);
  mRaw->createData();

  if (packed)
    imgsize = raw_width * raw_height * 3 / 2;
  else
    imgsize = raw_width * raw_height * 2;

  if (!mFile->isValid(data_offset))
    ThrowRDE("MRW decoder: Data offset after EOF, file probably truncated");
  if (!mFile->isValid(data_offset+imgsize-1))
    ThrowRDE("MRW decoder: Image end after EOF, file probably truncated");

  ByteStream input(mFile->getData(data_offset), imgsize);
 
  try {
    if (packed)
      Decode12BitRawBE(input, raw_width, raw_height);
    else
      Decode12BitRawBEunpacked(input, raw_width, raw_height);
  } catch (IOException &e) {
    mRaw->setError(e.what());
    // Let's ignore it, it may have delivered somewhat useful data.
  }

  return mRaw;
}
Пример #5
0
RawImage AriDecoder::decodeRawInternal() {
  mRaw->dim = iPoint2D(mWidth, mHeight);
  mRaw->createData();

  startThreads();

  mRaw->whitePoint = 4095;
  return mRaw;
}
Пример #6
0
RawImage MosDecoder::decodeRawInternal() {
  vector<TiffIFD*> data;
  TiffIFD* raw = NULL;
  uint32 off = 0;

  uint32 base = 8;
  // We get a pointer up to the end of the file as we check offset bounds later
  const uchar8 *insideTiff = mFile->getData(base, mFile->getSize()-base);
  if (get4LE(insideTiff, 0) == 0x49494949) {
    uint32 offset = get4LE(insideTiff, 8);
    if (offset+base+4 > mFile->getSize())
      ThrowRDE("MOS: PhaseOneC offset out of bounds");

    uint32 entries = get4LE(insideTiff, offset);
    uint32 pos = 8; // Skip another 4 bytes

    uint32 width=0, height=0, strip_offset=0, data_offset=0, wb_offset=0;
    while (entries--) {
      if (offset+base+pos+16 > mFile->getSize())
        ThrowRDE("MOS: PhaseOneC offset out of bounds");

      uint32 tag  = get4LE(insideTiff, offset+pos);
      //uint32 type = get4LE(insideTiff, offset+pos+4);
      //uint32 len  = get4LE(insideTiff, offset+pos+8);
      uint32 data = get4LE(insideTiff, offset+pos+12);
      pos += 16;
      switch(tag) {
      case 0x107: wb_offset    = data+base;      break;
      case 0x108: width        = data;      break;
      case 0x109: height       = data;      break;
      case 0x10f: data_offset  = data+base; break;
      case 0x21c: strip_offset = data+base; break;
      case 0x21d: black_level  = data>>2;   break;
      }
    }
    if (width <= 0 || height <= 0)
      ThrowRDE("MOS: PhaseOneC couldn't find width and height");
    if (strip_offset+height*4 > mFile->getSize())
      ThrowRDE("MOS: PhaseOneC strip offsets out of bounds");
    if (data_offset > mFile->getSize())
      ThrowRDE("MOS: PhaseOneC data offset out of bounds");

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

    DecodePhaseOneC(data_offset, strip_offset, width, height);

    const uchar8 *data = mFile->getData(wb_offset, 12);
    for(int i=0; i<3; i++) {
      // Use get4LE instead of going straight to float so this is endian clean
      uint32 value = get4LE(data, i*4);
      mRaw->metadata.wbCoeffs[i] = *((float *) &value);
    }

    return mRaw;
  } else {
Пример #7
0
RawImage NakedDecoder::decodeRawInternal() {
  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();

  ByteStream input(mFile->getData(offset), mFile->getSize()-offset);
  iPoint2D pos(0, 0);
  readUncompressedRaw(input, mRaw->dim, pos, width*bits/8, bits, BitOrder_Jpeg16);

  return mRaw;
}
Пример #8
0
void AriDecoder::decodeMetaDataInternal(CameraMetaData *meta) {
  mRaw->cfa.setCFA(iPoint2D(2,2), CFA_GREEN, CFA_RED, CFA_BLUE, CFA_GREEN2);
  mRaw->metadata.wbCoeffs[0] = mWB[0];
  mRaw->metadata.wbCoeffs[1] = mWB[1];
  mRaw->metadata.wbCoeffs[2] = mWB[2];
  if (meta->hasCamera("ARRI", mModel, mEncoder)) {
    setMetaData(meta, "ARRI", mModel, mEncoder, mIso);
  } else {
    setMetaData(meta, "ARRI", mModel, "", mIso);
  }
}
Пример #9
0
RawImage NakedDecoder::decodeRawInternal() {
  uint32 width=0, height=0, filesize=0, bits=0, offset=0;
  if(cam->hints.find("full_width") != cam->hints.end()) {
    string tmp = cam->hints.find(string("full_width"))->second;
    width = (uint32) atoi(tmp.c_str());
  } else
    ThrowRDE("Naked: couldn't find width");

  if(cam->hints.find("full_height") != cam->hints.end()) {
    string tmp = cam->hints.find(string("full_height"))->second;
    height = (uint32) atoi(tmp.c_str());
  } else
    ThrowRDE("Naked: couldn't find height");

  if(cam->hints.find("filesize") != cam->hints.end()) {
    string tmp = cam->hints.find(string("filesize"))->second;
    filesize = (uint32) atoi(tmp.c_str());
  } else
    ThrowRDE("Naked: couldn't find filesize");

  if(cam->hints.find("offset") != cam->hints.end()) {
    string tmp = cam->hints.find(string("offset"))->second;
    offset = (uint32) atoi(tmp.c_str());
  }

  if(cam->hints.find("bits") != cam->hints.end()) {
    string tmp = cam->hints.find(string("bits"))->second;
    bits = (uint32) atoi(tmp.c_str());
  } else
    bits = (filesize-offset)*8/width/height;

  BitOrder bo = BitOrder_Jpeg16;  // Default
  if(cam->hints.find("order") != cam->hints.end()) {
    string tmp = cam->hints.find(string("order"))->second;
    if (tmp.compare("plain") == 0) {
      bo = BitOrder_Plain;
    } else if (tmp.compare("jpeg") == 0) {
      bo = BitOrder_Jpeg;
    } else if (tmp.compare("jpeg16") == 0) {
      bo = BitOrder_Jpeg16;    
    } else if (tmp.compare("jpeg32") == 0) {
      bo = BitOrder_Jpeg32;    
    }
  }

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

  ByteStream input(mFile->getData(offset), mFile->getSize()-offset);
  iPoint2D pos(0, 0);
  readUncompressedRaw(input, mRaw->dim, pos, width*bits/8, bits, bo);

  return mRaw;
}
Пример #10
0
void CrwDecoder::decodeMetaDataInternal(CameraMetaData *meta) {
    int iso = 0;
    mRaw->cfa.setCFA(iPoint2D(2,2), CFA_RED, CFA_GREEN, CFA_GREEN2, CFA_BLUE);
    vector<CiffIFD*> data = mRootIFD->getIFDsWithTag(CIFF_MAKEMODEL);
    if (data.empty())
        ThrowRDE("CRW Support check: Model name not found");
    vector<string> makemodel = data[0]->getEntry(CIFF_MAKEMODEL)->getStrings();
    if (makemodel.size() < 2)
        ThrowRDE("CRW Support check: wrong number of strings for make/model");
    string make = makemodel[0];
    string model = makemodel[1];
    string mode = "";

    if (mRootIFD->hasEntryRecursive(CIFF_SHOTINFO)) {
        CiffEntry *shot_info = mRootIFD->getEntryRecursive(CIFF_SHOTINFO);
        if (shot_info->type == CIFF_SHORT && shot_info->count >= 2) {
            // os << exp(canonEv(value.toLong()) * log(2.0)) * 100.0 / 32.0;
            ushort16 iso_index = shot_info->getShort(2);
            iso = expf(canonEv((long)iso_index) * logf(2.0)) * 100.0f / 32.0f;
        }
    }

    // Fetch the white balance
    try {
        if(mRootIFD->hasEntryRecursive((CiffTag)0x0032)) {
            CiffEntry *wb = mRootIFD->getEntryRecursive((CiffTag)0x0032);
            if (wb->type == CIFF_BYTE && wb->count == 768) {
                // We're in a D30 file, values are RGGB
                // This will probably not get used anyway as a 0x102c tag should exist
                mRaw->metadata.wbCoeffs[0] = (float) (1024.0 /wb->getByte(72));
                mRaw->metadata.wbCoeffs[1] = (float) ((1024.0/wb->getByte(73))+(1024.0/wb->getByte(74)))/2.0f;
                mRaw->metadata.wbCoeffs[2] = (float) (1024.0 /wb->getByte(75));
            } else if (wb->type == CIFF_BYTE && wb->count > 768) { // Other G series and S series cameras
                // correct offset for most cameras
                int offset = 120;
                // check for the hint that we need to use other offset
                if (hints.find("wb_offset") != hints.end()) {
                    stringstream wb_offset(hints.find("wb_offset")->second);
                    wb_offset >> offset;
                }

                ushort16 key[] = { 0x410, 0x45f3 };
                if (hints.find("wb_mangle") == hints.end())
                    key[0] = key[1] = 0;

                offset /= 2;
                mRaw->metadata.wbCoeffs[0] = (float) (wb->getShort(offset+1) ^ key[1]);
                mRaw->metadata.wbCoeffs[1] = (float) (wb->getShort(offset+0) ^ key[0]);
                mRaw->metadata.wbCoeffs[2] = (float) (wb->getShort(offset+2) ^ key[0]);
            }
Пример #11
0
void Camera::parseCFA(xmlDocPtr doc, xmlNodePtr cur) {
  xmlChar *key;
  if (!xmlStrcmp(cur->name, (const xmlChar *) "Color")) {
    int x = getAttributeAsInt(cur, cur->name, "x");
    if (x < 0 || x > 1) {
      ThrowCME("Invalid x coordinate in CFA array of in camera %s %s", make.c_str(), model.c_str());
    }

    int y = getAttributeAsInt(cur, cur->name, "y");
    if (y < 0 || y > 1) {
      ThrowCME("Invalid y coordinate in CFA array of in camera %s %s", make.c_str(), model.c_str());
    }

    key = xmlNodeListGetString(doc, cur->children, 1);
    if (!xmlStrcmp(key, (const xmlChar *) "GREEN"))
      cfa.setColorAt(iPoint2D(x, y), CFA_GREEN);
    else if (!xmlStrcmp(key, (const xmlChar *) "RED"))
      cfa.setColorAt(iPoint2D(x, y), CFA_RED);
    else if (!xmlStrcmp(key, (const xmlChar *) "BLUE"))
      cfa.setColorAt(iPoint2D(x, y), CFA_BLUE);

    xmlFree(key);
  }
}
Пример #12
0
void SrwDecoder::decodeMetaDataInternal(CameraMetaData *meta) {
  mRaw->cfa.setCFA(CFA_RED, CFA_GREEN, CFA_GREEN2, CFA_BLUE);
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);

  if (data.empty())
    ThrowRDE("SRW Meta Decoder: Model name found");

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

  data = mRootIFD->getIFDsWithTag(CFAPATTERN);
  if (!this->checkCameraSupported(meta, make, model, "") && !data.empty() && data[0]->hasEntry(CFAREPEATPATTERNDIM)) {
    const unsigned short* pDim = data[0]->getEntry(CFAREPEATPATTERNDIM)->getShortArray();
    iPoint2D cfaSize(pDim[1], pDim[0]);
    if (cfaSize.x != 2 && cfaSize.y != 2)
      ThrowRDE("SRW Decoder: Unsupported CFA pattern size");

    const uchar8* cPat = data[0]->getEntry(CFAPATTERN)->getData();
    if (cfaSize.area() != data[0]->getEntry(CFAPATTERN)->count)
      ThrowRDE("SRW Decoder: CFA pattern dimension and pattern count does not match: %d.");

    for (int y = 0; y < cfaSize.y; y++) {
      for (int x = 0; x < cfaSize.x; x++) {
        uint32 c1 = cPat[x+y*cfaSize.x];
        CFAColor c2;
        switch (c1) {
            case 0:
              c2 = CFA_RED; break;
            case 1:
              c2 = CFA_GREEN; break;
            case 2:
              c2 = CFA_BLUE; break;
            default:
              c2 = CFA_UNKNOWN;
              ThrowRDE("SRW Decoder: Unsupported CFA Color.");
        }
        mRaw->cfa.setColorAt(iPoint2D(x, y), c2);
      }
    }
    printf("Camera CFA: %s\n", mRaw->cfa.asString().c_str());
  }

  int iso = 0;
  if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
    iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getInt();

  setMetaData(meta, make, model, "", iso);
}
Пример #13
0
RawImage PefDecoder::decodeRawInternal() {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(STRIPOFFSETS);

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

  TiffIFD* raw = data[0];

  int compression = raw->getEntry(COMPRESSION)->getInt();

  if (1 == compression) {
    decodeUncompressed(raw, true);
    return mRaw;
  }

  if (65535 != compression)
    ThrowRDE("PEF Decoder: Unsupported compression");

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

  if (offsets->count != 1) {
    ThrowRDE("PEF Decoder: Multiple Strips found: %u", offsets->count);
  }
  if (counts->count != offsets->count) {
    ThrowRDE("PEF 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("PEF Decoder: Truncated file.");

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

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();
  try {
    PentaxDecompressor l(mFile, mRaw);
    l.decodePentax(mRootIFD, offsets->getInt(), counts->getInt());
  } catch (IOException &e) {
    errors.push_back(_strdup(e.what()));
    // Let's ignore it, it may have delivered somewhat useful data.
  }

  return mRaw;
}
Пример #14
0
RawImage PefDecoder::decodeRawInternal() {
  auto raw = mRootIFD->getIFDWithTag(STRIPOFFSETS);

  int compression = raw->getEntry(COMPRESSION)->getU32();

  if (1 == compression || compression == 32773) {
    decodeUncompressed(raw, BitOrder_MSB);
    return mRaw;
  }

  if (65535 != compression)
    ThrowRDE("Unsupported compression");

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

  if (offsets->count != 1) {
    ThrowRDE("Multiple Strips found: %u", offsets->count);
  }
  if (counts->count != offsets->count) {
    ThrowRDE(
        "Byte count number does not match strip size: count:%u, strips:%u ",
        counts->count, offsets->count);
  }
  if (!mFile->isValid(offsets->getU32(), counts->getU32()))
    ThrowRDE("Truncated file.");

  uint32 width = raw->getEntry(IMAGEWIDTH)->getU32();
  uint32 height = raw->getEntry(IMAGELENGTH)->getU32();

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();
  try {
    PentaxDecompressor::decompress(
        mRaw, ByteStream(mFile, offsets->getU32(), counts->getU32()),
        getRootIFD());
  } catch (IOException &e) {
    mRaw->setError(e.what());
    // Let's ignore it, it may have delivered somewhat useful data.
  }

  return mRaw;
}
Пример #15
0
void NefDecoder::DecodeUncompressed() {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(CFAPATTERN);
  TiffIFD* raw = FindBestImage(&data);
  uint32 nslices = raw->getEntry(STRIPOFFSETS)->count;
  const uint32 *offsets = raw->getEntry(STRIPOFFSETS)->getIntArray();
  const uint32 *counts = raw->getEntry(STRIPBYTECOUNTS)->getIntArray();
  uint32 yPerSlice = raw->getEntry(ROWSPERSTRIP)->getInt();
  uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
  uint32 height = raw->getEntry(IMAGELENGTH)->getInt();
  uint32 bitPerPixel = raw->getEntry(BITSPERSAMPLE)->getInt();

  vector<NefSlice> slices;
  uint32 offY = 0;

  for (uint32 s = 0; s < nslices; s++) {
    NefSlice slice;
    slice.offset = offsets[s];
    slice.count = counts[s];
    if (offY + yPerSlice > height)
      slice.h = height - offY;
    else
      slice.h = yPerSlice;

    offY = MIN(height, offY + yPerSlice);

    if (mFile->isValid(slice.offset, slice.count)) // Only decode if size is valid
      slices.push_back(slice);
  }

  if (0 == slices.size())
    ThrowRDE("NEF Decoder: No valid slices found. File probably truncated.");

  mRaw->dim = iPoint2D(width, offY);

  mRaw->createData();
  if (bitPerPixel == 14 && width*slices[0].h*2 == slices[0].count)
    bitPerPixel = 16; // D3 & D810

  if(hints.find("real_bpp") != hints.end()) {
    stringstream convert(hints.find("real_bpp")->second);
    convert >> bitPerPixel;
  }
Пример #16
0
RawImage ThreefrDecoder::decodeRawInternal() {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(STRIPOFFSETS);

  if (data.size() < 2)
    ThrowRDE("3FR Decoder: No image data found");

  TiffIFD* raw = data[1];
  uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
  uint32 height = raw->getEntry(IMAGELENGTH)->getInt();
  uint32 off = raw->getEntry(STRIPOFFSETS)->getInt();

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();
  ByteStream input(mFile->getData(off), mFile->getSize() - off);

  HasselbladDecompressor l(mFile, mRaw);
  map<string,string>::iterator pixelOffset = hints.find("pixelBaseOffset");
  if (pixelOffset != hints.end()) {
    stringstream convert((*pixelOffset).second);
    convert >> l.pixelBaseOffset;
  }
Пример #17
0
void Cr2Decoder::decodeMetaDataInternal(CameraMetaData *meta) {
  int iso = 0;
  mRaw->cfa.setCFA(iPoint2D(2,2), CFA_RED, CFA_GREEN, CFA_GREEN2, CFA_BLUE);
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);

  if (data.empty())
    ThrowRDE("CR2 Meta Decoder: Model name not found");

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

  if (mRaw->metadata.subsampling.y == 2 && mRaw->metadata.subsampling.x == 2)
    mode = "sRaw1";

  if (mRaw->metadata.subsampling.y == 1 && mRaw->metadata.subsampling.x == 2)
    mode = "sRaw2";

  if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
    iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getInt();

  // Fetch the white balance
  try{
    if (mRootIFD->hasEntryRecursive(CANONCOLORDATA)) {
      TiffEntry *wb = mRootIFD->getEntryRecursive(CANONCOLORDATA);
      // this entry is a big table, and different cameras store used WB in
      // different parts, so find the offset, starting with the most common one
      int offset = 126;

      // replace it with a hint if it exists
      if (hints.find("wb_offset") != hints.end()) {
        stringstream wb_offset(hints.find("wb_offset")->second);
        wb_offset >> offset;
      }

      offset /= 2;
      mRaw->metadata.wbCoeffs[0] = (float) wb->getShort(offset + 0);
      mRaw->metadata.wbCoeffs[1] = (float) wb->getShort(offset + 1);
      mRaw->metadata.wbCoeffs[2] = (float) wb->getShort(offset + 3);
    } else {
Пример #18
0
RawImage KdcDecoder::decodeRawInternal() {
  if (!mRootIFD->hasEntryRecursive(COMPRESSION))
    ThrowRDE("KDC Decoder: Couldn't find compression setting");

  int compression = mRootIFD->getEntryRecursive(COMPRESSION)->getInt();
  if (7 != compression)
    ThrowRDE("KDC Decoder: Unsupported compression %d", compression);

  uint32 width = 0;
  uint32 height = 0;
  TiffEntry *ew = mRootIFD->getEntryRecursive(KODAK_KDC_WIDTH);
  TiffEntry *eh = mRootIFD->getEntryRecursive(KODAK_KDC_HEIGHT);
  if (ew && eh) {
    width = ew->getInt()+80;
    height = eh->getInt()+70;
  } else
    ThrowRDE("KDC Decoder: Unable to retrieve image size");

  TiffEntry *offset = mRootIFD->getEntryRecursive(KODAK_KDC_OFFSET);
  if (!offset || offset->count < 13)
    ThrowRDE("KDC Decoder: Couldn't find the KDC offset");
  const uint32 *offsetarray = offset->getIntArray();
  uint32 off = offsetarray[4] + offsetarray[12];

  // Offset hardcoding gotten from dcraw
  if (hints.find("easyshare_offset_hack") != hints.end())
    off = off < 0x15000 ? 0x15000 : 0x17000;

  if (off > mFile->getSize())
    ThrowRDE("KDC Decoder: offset is out of bounds");

  mRaw->dim = iPoint2D(width, height);
  mRaw->createData();
  ByteStream input(mFile, off);

  Decode12BitRawBE(input, width, height);

  return mRaw;
}
Пример #19
0
void PefDecoder::decodeMetaDataInternal(CameraMetaData *meta) {
  int iso = 0;
  mRaw->cfa.setCFA(iPoint2D(2,2), CFA_RED, CFA_GREEN, CFA_GREEN2, CFA_BLUE);
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);

  if (data.empty())
    ThrowRDE("PEF Meta Decoder: Model name found");

  TiffIFD* raw = data[0];

  string make = raw->getEntry(MAKE)->getString();
  string model = raw->getEntry(MODEL)->getString();

  if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
    iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getInt();

  setMetaData(meta, make, model, "", iso);

  // Read black level
  if (mRootIFD->hasEntryRecursive((TiffTag)0x200)) {
    TiffEntry *black = mRootIFD->getEntryRecursive((TiffTag)0x200);
    const ushort16 *levels = black->getShortArray();
    for (int i = 0; i < 4; i++)
      mRaw->blackLevelSeparate[i] = levels[i];
  }

  // Set the whitebalance
  if (mRootIFD->hasEntryRecursive((TiffTag) 0x0201)) {
    TiffEntry *wb = mRootIFD->getEntryRecursive((TiffTag) 0x0201);
    if (wb->count == 4) {
      const ushort16 *tmp = wb->getShortArray();
      mRaw->metadata.wbCoeffs[0] = tmp[0];
      mRaw->metadata.wbCoeffs[1] = tmp[1];
      mRaw->metadata.wbCoeffs[2] = tmp[3];
    }
  }
}
Пример #20
0
void Cr2Decoder::decodeMetaDataInternal(CameraMetaData *meta) {
  int iso = 0;
  mRaw->cfa.setCFA(iPoint2D(2,2), CFA_RED, CFA_GREEN, CFA_GREEN2, CFA_BLUE);
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(MODEL);

  if (data.empty())
    ThrowRDE("CR2 Meta Decoder: Model name not found");

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

  if (mRaw->metadata.subsampling.y == 2 && mRaw->metadata.subsampling.x == 2)
    mode = "sRaw1";

  if (mRaw->metadata.subsampling.y == 1 && mRaw->metadata.subsampling.x == 2)
    mode = "sRaw2";

  if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
    iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getInt();

  // Fetch the white balance
  if (mRootIFD->hasEntryRecursive(CANONCOLORDATA)) {
    TiffEntry *color_data = mRootIFD->getEntryRecursive(CANONCOLORDATA);

    // this entry is a big table, and different cameras store used WB in
    // different parts, so find the offset

    // correct offset for most cameras
    int offset = 126;

    // check for the hint that we need to use other offset
    if (hints.find("wb_offset") != hints.end()) {
      stringstream wb_offset(hints.find("wb_offset")->second);
      wb_offset >> offset;
    }
Пример #21
0
void LJpegPlain::decodeScanLeft4Comps() {
  // First line
  HuffmanTable *dctbl1 = &huff[frame.compInfo[0].dcTblNo];
  HuffmanTable *dctbl2 = &huff[frame.compInfo[1].dcTblNo];
  HuffmanTable *dctbl3 = &huff[frame.compInfo[2].dcTblNo];
  HuffmanTable *dctbl4 = &huff[frame.compInfo[3].dcTblNo];

  if (mCanonDoubleHeight) {
    frame.h *= 2;
    mRaw->dim = iPoint2D(frame.w * 2, frame.h);
    mRaw->destroyData();
    mRaw->createData();
  }
  uchar8 *draw = mRaw->getData();

  //Prepare slices (for CR2)
  uint32 slices = (uint32)slicesW.size() * (frame.h - skipY);
  offset = new uint32[slices+1];

  uint32 t_y = 0;
  uint32 t_x = 0;
  uint32 t_s = 0;
  uint32 slice = 0;
  for (slice = 0; slice < slices; slice++) {
    offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * mRaw->pitch)) | (t_s << 28);
    _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y);
    t_y++;
    if (t_y == (frame.h - skipY)) {
      t_y = 0;
      t_x += slicesW[t_s++];
    }
  }
  // We check the final position. If bad slice sizes are given we risk writing outside the image
  if ((offset[slices-1]&0x0fffffff) >= mRaw->pitch*mRaw->dim.y) {
    ThrowRDE("LJpegPlain::decodeScanLeft: Last slice out of bounds");
  }
  offset[slices] = offset[slices-1];        // Extra offset to avoid branch in loop.

  slice_width = new int[slices];

  // This is divided by comps, since comps pixels are processed at the time
  for (uint32 i = 0 ; i <  slicesW.size(); i++)
    slice_width[i] = slicesW[i] / COMPS;

  if (skipX)
    slice_width[slicesW.size()-1] -= skipX;

  // First pixels are obviously not predicted
  int p1;
  int p2;
  int p3;
  int p4;
  ushort16 *dest = (ushort16*) & draw[offset[0] & 0x0fffffff];
  ushort16 *predict = dest;
  *dest++ = p1 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl1);
  *dest++ = p2 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl2);
  *dest++ = p3 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl3);
  *dest++ = p4 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl4);

  slice = 1;
  uint32 pixInSlice = slice_width[0] - 1;

  uint32 cw = (frame.w - skipX);
  uint32 x = 1;                            // Skip first pixels on first line.

  if (mCanonDoubleHeight)
    skipY = frame.h >> 1;

  uint32 ch = (frame.h - skipY);

  // Fix for Canon 80D mraw format.
  // In that format, `frame` is 4032x3402, while `mRaw` is 4536x3024.
  // Consequently, the slices in `frame` wrap around (this is taken care of by
  // `offset`) and must be decoded fully (without skipY) to fill the image
  if (mWrappedCr2Slices)
    ch = frame.h;

  for (uint32 y = 0;y < ch;y++) {
    for (; x < cw ; x++) {
      p1 += HuffDecode(dctbl1);
      *dest++ = (ushort16)p1;

      p2 += HuffDecode(dctbl2);
      *dest++ = (ushort16)p2;

      p3 += HuffDecode(dctbl3);
      *dest++ = (ushort16)p3;

      p4 += HuffDecode(dctbl4);
      *dest++ = (ushort16)p4;

      if (0 == --pixInSlice) { // Next slice
        if (slice > slices)
          ThrowRDE("LJpegPlain::decodeScanLeft: Ran out of slices");
        uint32 o = offset[slice++];
        dest = (ushort16*) & draw[o&0x0fffffff];  // Adjust destination for next pixel
        if((o&0x0fffffff) > mRaw->pitch*mRaw->dim.y)
          ThrowRDE("LJpegPlain::decodeScanLeft: Offset out of bounds");
        pixInSlice = slice_width[o>>28];
      }
    }
    if (skipX) {
      for (uint32 i = 0; i < skipX; i++) {
        HuffDecode(dctbl1);
        HuffDecode(dctbl2);
        HuffDecode(dctbl3);
        HuffDecode(dctbl4);
      }
    }
    bits->checkPos();
    p1 = predict[0];  // Predictors for next row
    p2 = predict[1];
    p3 = predict[2];  // Predictors for next row
    p4 = predict[3];
    predict = dest;  // Adjust destination for next prediction
    x = 0;
  }
}
Пример #22
0
RawImage Rw2Decoder::decodeRawInternal() {

  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(PANASONIC_STRIPOFFSET);

  bool isOldPanasonic = FALSE;

  if (data.empty()) {
    if (!mRootIFD->hasEntryRecursive(STRIPOFFSETS))
      ThrowRDE("RW2 Decoder: No image data found");
    isOldPanasonic = TRUE;
    data = mRootIFD->getIFDsWithTag(STRIPOFFSETS);
  }

  TiffIFD* raw = data[0];
  uint32 height = raw->getEntry((TiffTag)3)->getShort();
  uint32 width = raw->getEntry((TiffTag)2)->getShort();

  if (isOldPanasonic) {
    ThrowRDE("Cannot decode old-style Panasonic RAW files");
    TiffEntry *offsets = raw->getEntry(STRIPOFFSETS);
    TiffEntry *counts = raw->getEntry(STRIPBYTECOUNTS);

    if (offsets->count != 1) {
      ThrowRDE("RW2 Decoder: Multiple Strips found: %u", offsets->count);
    }
    int off = offsets->getInt();
    if (!mFile->isValid(off))
      ThrowRDE("Panasonic RAW Decoder: Invalid image data offset, cannot decode.");

    int count = counts->getInt();
    if (count != (int)(width*height*2))
      ThrowRDE("Panasonic RAW Decoder: Byte count is wrong.");

    if (!mFile->isValid(off+count))
      ThrowRDE("Panasonic RAW Decoder: Invalid image data offset, cannot decode.");
      
    mRaw->dim = iPoint2D(width, height);
    mRaw->createData();
    ByteStream input_start(mFile->getData(off), mFile->getSize() - off);
    iPoint2D pos(0, 0);
    readUncompressedRaw(input_start, mRaw->dim,pos, width*2, 16, BitOrder_Plain);

  } else {

    mRaw->dim = iPoint2D(width, height);
    mRaw->createData();
    TiffEntry *offsets = raw->getEntry(PANASONIC_STRIPOFFSET);

    if (offsets->count != 1) {
      ThrowRDE("RW2 Decoder: Multiple Strips found: %u", offsets->count);
    }

    load_flags = 0x2008;
    int off = offsets->getInt();

    if (!mFile->isValid(off))
      ThrowRDE("RW2 Decoder: Invalid image data offset, cannot decode.");

    input_start = new ByteStream(mFile->getData(off), mFile->getSize() - off);
    DecodeRw2();
  }
  // Read blacklevels
  if (raw->hasEntry((TiffTag)0x1c) && raw->hasEntry((TiffTag)0x1d) && raw->hasEntry((TiffTag)0x1e)) {
    mRaw->blackLevelSeparate[0] = raw->getEntry((TiffTag)0x1c)->getInt() + 15;
    mRaw->blackLevelSeparate[1] = mRaw->blackLevelSeparate[2] = raw->getEntry((TiffTag)0x1d)->getInt() + 15;
    mRaw->blackLevelSeparate[3] = raw->getEntry((TiffTag)0x1e)->getInt() + 15;
  }
  return mRaw;
}
Пример #23
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;
}
Пример #24
0
void NefDecoder::DecodeUncompressed() {
  vector<TiffIFD*> data = mRootIFD->getIFDsWithTag(CFAPATTERN);
  TiffIFD* raw = FindBestImage(&data);
  uint32 nslices = raw->getEntry(STRIPOFFSETS)->count;
  const uint32 *offsets = raw->getEntry(STRIPOFFSETS)->getIntArray();
  const uint32 *counts = raw->getEntry(STRIPBYTECOUNTS)->getIntArray();
  uint32 yPerSlice = raw->getEntry(ROWSPERSTRIP)->getInt();
  uint32 width = raw->getEntry(IMAGEWIDTH)->getInt();
  uint32 height = raw->getEntry(IMAGELENGTH)->getInt();
  uint32 bitPerPixel = raw->getEntry(BITSPERSAMPLE)->getInt();

  vector<NefSlice> slices;
  uint32 offY = 0;

  for (uint32 s = 0; s < nslices; s++) {
    NefSlice slice;
    slice.offset = offsets[s];
    slice.count = counts[s];
    if (offY + yPerSlice > height)
      slice.h = height - offY;
    else
      slice.h = yPerSlice;

    offY += yPerSlice;

    if (mFile->isValid(slice.offset + slice.count)) // Only decode if size is valid
      slices.push_back(slice);
  }

  if (0 == slices.size())
    ThrowRDE("NEF Decoder: No valid slices found. File probably truncated.");

  mRaw->dim = iPoint2D(width, offY);
  mRaw->createData();
  if (bitPerPixel == 14 && width*slices[0].h*2 == slices[0].count)
    bitPerPixel = 16; // D3

  offY = 0;
  for (uint32 i = 0; i < slices.size(); i++) {
    NefSlice slice = slices[i];
    ByteStream in(mFile->getData(slice.offset), slice.count);
    iPoint2D size(width, slice.h);
    iPoint2D pos(0, offY);
    try {
      if (hints.find(string("coolpixmangled")) != hints.end())
        readCoolpixMangledRaw(in, size, pos, width*bitPerPixel / 8);
      else if (hints.find(string("coolpixsplit")) != hints.end())
        readCoolpixSplitRaw(in, size, pos, width*bitPerPixel / 8);
      else
        readUncompressedRaw(in, size, pos, width*bitPerPixel / 8, bitPerPixel, true);
    } catch (RawDecoderException e) {
      if (i>0)
        mRaw->setError(e.what());
      else
        throw;
    } catch (IOException e) {
      if (i>0)
        mRaw->setError(e.what());
      else
        ThrowRDE("NEF decoder: IO error occurred in first slice, unable to decode more. Error is: %s", e.what());
    }
    offY += slice.h;
  }
}
Пример #25
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;
}
Пример #26
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;
}
Пример #27
0
RawImage Cr2Decoder::decodeRawInternal() {

  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;

  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(mFile, mRaw);
      l.getSOF(&sof, slice.offset, slice.count);
      slice.w = sof.w * sof.cps;
      slice.h = sof.h;
      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.");
  }

  if (slices.empty()) {
    ThrowRDE("CR2 Decoder: No Slices found.");
  }

  mRaw->dim = iPoint2D(slices[0].w, completeH);

  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;
    }
  }

  mRaw->createData();

  vector<int> s_width;
  if (raw->hasEntry(CANONCR2SLICE)) {
    const ushort16 *ss = raw->getEntry(CANONCR2SLICE)->getShortArray();
    for (int i = 0; i < ss[0]; i++) {
      s_width.push_back(ss[1]);
    }
    s_width.push_back(ss[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(mFile, mRaw);
      l.addSlices(s_width);
      l.mUseBigtable = true;
      l.startDecoder(slice.offset, slice.count, 0, offY);
    } catch (RawDecoderException &e) {
      if (i == 0)
        throw;
      // These may just be single slice error - store the error and move on
      errors.push_back(_strdup(e.what()));
    } catch (IOException &e) {
      // Let's try to ignore this - it might be truncated data, so something might be useful.
      errors.push_back(_strdup(e.what()));
    }
    offY += slice.w;
  }

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

  return mRaw;
}