int main(int argc, const char* argv[])
{

  if(argc != 2)
  {
    fprintf(stderr, "Usage: darktable-rs-identify <file>\n");
    return 2;
  }

  char *camfile = find_cameras_xml(argv[0]);
  if (!camfile)
  {
    //fprintf(stderr, "ERROR: Couldn't find cameras.xml\n");
    return 2;
  }
  //fprintf(stderr, "Using cameras.xml from '%s'\n", camfile);

  try
  {
    std::unique_ptr<CameraMetaData> meta(new CameraMetaData(camfile));

    if(!meta.get())
    {
      fprintf(stderr, "ERROR: Couldn't get a CameraMetaData instance\n");
      return 2;
    }

#ifdef __AFL_HAVE_MANUAL_CONTROL
    __AFL_INIT();
#endif

    FileReader f((char *) argv[1]);

    std::unique_ptr<FileMap> m(f.readFile());

    RawParser t(m.get());

    std::unique_ptr<RawDecoder> d(t.getDecoder(meta.get()));

    if(!d.get())
    {
      fprintf(stderr, "ERROR: Couldn't get a RawDecoder instance\n");
      return 2;
    }

    d->applyCrop = false;
    d->failOnUnknown = true;
    RawImage r = d->mRaw;

    d->decodeMetaData(meta.get());

    fprintf(stdout, "make: %s\n", r->metadata.make.c_str());
    fprintf(stdout, "model: %s\n", r->metadata.model.c_str());

    fprintf(stdout, "canonical_make: %s\n", r->metadata.canonical_make.c_str());
    fprintf(stdout, "canonical_model: %s\n", r->metadata.canonical_model.c_str());
    fprintf(stdout, "canonical_alias: %s\n", r->metadata.canonical_alias.c_str());

    d->checkSupport(meta.get());
    d->decodeRaw();
    d->decodeMetaData(meta.get());
    r = d->mRaw;
    for (uint32 i=0; i<r->errors.size(); i++)
      fprintf(stderr, "WARNING: [rawspeed] %s\n", r->errors[i]);

    fprintf(stdout, "blackLevel: %d\n", r->blackLevel);
    fprintf(stdout, "whitePoint: %d\n", r->whitePoint);

    fprintf(stdout, "blackLevelSeparate: %d %d %d %d\n", 
                    r->blackLevelSeparate[0], r->blackLevelSeparate[1],
                    r->blackLevelSeparate[2], r->blackLevelSeparate[3]);

    fprintf(stdout, "wbCoeffs: %f %f %f %f\n", 
                    r->metadata.wbCoeffs[0], r->metadata.wbCoeffs[1],
                    r->metadata.wbCoeffs[2], r->metadata.wbCoeffs[3]);

    fprintf(stdout, "isCFA: %d\n", r->isCFA);
    uint32 filters = r->cfa.getDcrawFilter();
    fprintf(stdout, "filters: %d (0x%x)\n", filters, filters);
    uint32 bpp = r->getBpp();
    fprintf(stdout, "bpp: %d\n", bpp);
    uint32 cpp = r->getCpp();
    fprintf(stdout, "cpp: %d\n", cpp);
    fprintf(stdout, "dataType: %d\n", r->getDataType());

    // dimensions of uncropped image
    iPoint2D dimUncropped = r->getUncroppedDim();
    fprintf(stdout, "dimUncropped: %dx%d\n", dimUncropped.x, dimUncropped.y);

    // dimensions of cropped image
    iPoint2D dimCropped = r->dim;
    fprintf(stdout, "dimCropped: %dx%d\n", dimCropped.x, dimCropped.y);

    // crop - Top,Left corner
    iPoint2D cropTL = r->getCropOffset();
    fprintf(stdout, "cropOffset: %dx%d\n", cropTL.x, cropTL.y);

    fprintf(stdout, "fuji_rotation_pos: %d\n", r->metadata.fujiRotationPos);
    fprintf(stdout, "pixel_aspect_ratio: %f\n", r->metadata.pixelAspectRatio);

    double sum = 0.0f;
    for(uint32 row = 0; row < ((uint32) dimUncropped.y); row++)
    {
      uchar8 *data = r->getDataUncropped(0, row);
      for(uint32 byte = 0; byte < ((uint32) dimUncropped.x*bpp) ; byte++)
        sum += (double) data[byte];
    }
    fprintf(stdout, "Image byte sum: %lf\n", sum);
    fprintf(stdout, "Image byte avg: %lf\n", sum/(dimUncropped.y*dimUncropped.x*bpp));
  }
  catch(const std::exception &exc)
  {
    printf("ERROR: [rawspeed] %s\n", exc.what());

    /* if an exception is raised lets not retry or handle the
     specific ones, consider the file as corrupted */
    return 2;
  }
  catch(...)
  {
    printf("Unhandled exception in rawspeed-identify\n");
    return 3;
  }

  return 0;
}
int main(int argc, const char* argv[])
{

  if(argc != 2)
  {
    fprintf(stderr, "Usage: darktable-rs-identify <file>\n");
    return 2;
  }

  FileReader f((char *) argv[1]);

#ifdef __APPLE__
  std::auto_ptr<RawDecoder> d;
  std::auto_ptr<FileMap> m;
#else
  std::unique_ptr<RawDecoder> d;
  std::unique_ptr<FileMap> m;
#endif

  char camfile[PATH_MAX] = { 0 };
#if defined(__MACH__) || defined(__APPLE__)
  char *directory = dt_loc_find_install_dir("/share/darktable", argv[0]);
  if(!directory)
  {
    fprintf(stderr, "Couldn't find share/darktable folder\n");
    return 2;
  }
  snprintf(camfile, sizeof(camfile), "%s/rawspeed/cameras.xml", directory);
#else
  snprintf(camfile, sizeof(camfile), "%s/rawspeed/cameras.xml", DARKTABLE_DATADIR);
#endif
  //fprintf(stderr, "Looking for cameras.xml in '%s'\n", camfile);

  try
  {
    CameraMetaData *meta = new CameraMetaData(camfile);

#ifdef __APPLE__
    m = auto_ptr<FileMap>(f.readFile());
#else
    m = unique_ptr<FileMap>(f.readFile());
#endif

    RawParser t(m.get());
#ifdef __APPLE__
    d = auto_ptr<RawDecoder>(t.getDecoder(meta));
#else
    d = unique_ptr<RawDecoder>(t.getDecoder(meta));
#endif

    if(!d.get())
    {
      fprintf(stderr, "ERROR: Couldn't get a RawDecoder instance\n");
      return 2;
    }

    d->failOnUnknown = true;
    d->checkSupport(meta);
    d->decodeRaw();
    d->decodeMetaData(meta);
    RawImage r = d->mRaw;

    for (uint32 i=0; i<r->errors.size(); i++)
      fprintf(stderr, "WARNING: [rawspeed] %s\n", r->errors[i]);

    fprintf(stdout, "make: %s\n", r->metadata.make.c_str());
    fprintf(stdout, "model: %s\n", r->metadata.model.c_str());

    fprintf(stdout, "canonical_make: %s\n", r->metadata.canonical_make.c_str());
    fprintf(stdout, "canonical_model: %s\n", r->metadata.canonical_model.c_str());
    fprintf(stdout, "canonical_alias: %s\n", r->metadata.canonical_alias.c_str());
    fprintf(stdout, "blackLevel: %d\n", r->blackLevel);
    fprintf(stdout, "whitePoint: %d\n", r->whitePoint);

    fprintf(stdout, "blackLevelSeparate: %d %d %d %d\n", 
                    r->blackLevelSeparate[0], r->blackLevelSeparate[1],
                    r->blackLevelSeparate[2], r->blackLevelSeparate[3]);

    fprintf(stdout, "wbCoeffs: %f %f %f %f\n", 
                    r->metadata.wbCoeffs[0], r->metadata.wbCoeffs[1],
                    r->metadata.wbCoeffs[2], r->metadata.wbCoeffs[3]);

    fprintf(stdout, "isCFA: %d\n", r->isCFA);
    uint32_t filters = r->cfa.getDcrawFilter();
    fprintf(stdout, "filters: %d (0x%x)\n", filters, filters);
    uint32_t bpp = r->getBpp();
    fprintf(stdout, "bpp: %d\n", bpp);
    uint32_t cpp = r->getCpp();
    fprintf(stdout, "cpp: %d\n", cpp);
    fprintf(stdout, "dataType: %d\n", r->getDataType());

    // dimensions of uncropped image
    iPoint2D dimUncropped = r->getUncroppedDim();
    fprintf(stdout, "dimUncropped: %dx%d\n", dimUncropped.x, dimUncropped.y);

    // dimensions of cropped image
    iPoint2D dimCropped = r->dim;
    fprintf(stdout, "dimCropped: %dx%d\n", dimCropped.x, dimCropped.y);

    // crop - Top,Left corner
    iPoint2D cropTL = r->getCropOffset();
    fprintf(stdout, "cropOffset: %dx%d\n", cropTL.x, cropTL.y);

    fprintf(stdout, "fuji_rotation_pos: %d\n", r->metadata.fujiRotationPos);
    fprintf(stdout, "pixel_aspect_ratio: %f\n", r->metadata.pixelAspectRatio);

    double sum = 0.0f;
    for(uint32_t row = 0; row < ((uint32_t) dimUncropped.y); row++)
    {
      uint8_t *data = r->getDataUncropped(0, 0);
      for(uint32_t byte = 0; byte < ((uint32_t) dimUncropped.x*cpp*bpp) ; byte++)
        sum += (double) data[byte];
    }
    fprintf(stdout, "Image byte sum: %lf\n", sum);
    fprintf(stdout, "Image byte avg: %lf\n", sum/(dimUncropped.y*dimUncropped.x*cpp*bpp));
  }
  catch(const std::exception &exc)
  {
    printf("ERROR: [rawspeed] %s\n", exc.what());

    /* if an exception is raised lets not retry or handle the
     specific ones, consider the file as corrupted */
    return 2;
  }
  catch(...)
  {
    printf("Unhandled exception in rawspeed-identify\n");
    return 3;
  }

  return 0;
}