Skip to content

Commit

Permalink
Merge pull request timothybrooks#36 from brotherofken/add_exif2_support
Browse files Browse the repository at this point in the history
Add LibRaw for input reading.
  • Loading branch information
Titaniumtown committed Apr 1, 2019
2 parents c1d73f8 + 0fc3538 commit dce3ca4
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 115 deletions.
24 changes: 17 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
cmake_minimum_required(VERSION 2.8.11)
cmake_minimum_required(VERSION 3.10)
project(HDR_PLUS)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-O3 -g -Wall")
#set(CMAKE_CXX_FLAGS "-O3 -v -g -Wall") # Use -DCMAKE_BUILD_TYPE=Release/Debug instead
find_package(PNG REQUIRED)


set(HALIDE_ROOT_DIR "")

if(" ${HALIDE_ROOT_DIR}" STREQUAL " ")
message( FATAL_ERROR "Specify HALIDE_ROOT_DIR variable in the cmake file." )
endif()

find_library(LIBRAW_LIBRARY
NAMES raw raw_r
)

set(src_files
src/HDRPlus.cpp
src/align.cpp
src/finish.cpp
src/merge.cpp
src/util.cpp
)
src/InputSource.cpp
src/InputSource.h
src/Burst.cpp
src/Burst.h)

include_directories(/usr/local/lib /usr/local/include ${HALIDE_ROOT_DIR}/bin ${HALIDE_ROOT_DIR}/lib ${HALIDE_ROOT_DIR}/include ${HALIDE_ROOT_DIR}/tools)

link_directories(/usr/local/lib /usr/local/include ${HALIDE_ROOT_DIR}/bin ${HALIDE_ROOT_DIR}/lib ${HALIDE_ROOT_DIR}/include ${HALIDE_ROOT_DIR}/tools)

include_directories(${HALIDE_ROOT_DIR}/lib ${HALIDE_ROOT_DIR}/include ${HALIDE_ROOT_DIR}/tools)
link_directories(${HALIDE_ROOT_DIR}/bin ${HALIDE_ROOT_DIR}/lib)

add_executable(hdrplus ${src_files})

target_link_libraries(hdrplus Halide png)
target_link_libraries(hdrplus Halide png ${LIBRAW_LIBRARY})
27 changes: 27 additions & 0 deletions src/Burst.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "Burst.h"

Halide::Runtime::Buffer<uint16_t> Burst::ToBuffer() const {
if (Raws.empty()) {
return Halide::Runtime::Buffer<uint16_t>();
}

Halide::Runtime::Buffer<uint16_t> result(GetWidth(), GetHeight(), Raws.size());
for (int i = 0; i < Raws.size(); ++i) {
auto resultSlice = result.sliced(2, i);
Raws[i]->CopyToBuffer(resultSlice);
}
return result;
}

void Burst::CopyToBuffer(Halide::Runtime::Buffer<uint16_t> &buffer) const {
buffer.copy_from(ToBuffer());
}

std::vector<AbstractInputSource::SPtr> Burst::LoadRaws(const std::string &dirPath, std::vector<std::string> &inputs) {
std::vector<AbstractInputSource::SPtr> result;
for (const auto& input : inputs) {
const std::string img_path = dirPath + "/" + input;
result.emplace_back(std::make_shared<RawSource>(img_path));
}
return result;
}
42 changes: 42 additions & 0 deletions src/Burst.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include "InputSource.h"

#include <Halide.h>

#include <string>
#include <vector>
#include <Halide.h>

class Burst : public AbstractInputSource {
public:
Burst(std::string dir_path, std::vector<std::string> inputs)
: Dir(std::move(dir_path))
, Inputs(std::move(inputs))
, Raws(LoadRaws(Dir, Inputs))
{}

~Burst() override = default;

int GetWidth() const override { return Raws.empty() ? -1 : Raws[0]->GetWidth(); }

int GetHeight() const override { return Raws.empty() ? -1 : Raws[0]->GetHeight(); }

int GetBlackLevel() const override { return Raws.empty() ? -1 : Raws[0]->GetBlackLevel(); }

int GetWhiteLevel() const override { return Raws.empty() ? -1 : Raws[0]->GetWhiteLevel(); }

WhiteBalance GetWhiteBalance() const override { return Raws.empty() ? WhiteBalance{-1, -1, -1, -1} : Raws[0]->GetWhiteBalance(); }

Halide::Runtime::Buffer<uint16_t> ToBuffer() const;

void CopyToBuffer(Halide::Runtime::Buffer<uint16_t>& buffer) const override;

private:
std::string Dir;
std::vector<std::string> Inputs;
std::vector<AbstractInputSource::SPtr> Raws;

private:
static std::vector<AbstractInputSource::SPtr> LoadRaws(const std::string& dirPath, std::vector<std::string>& inputs);
};
203 changes: 98 additions & 105 deletions src/HDRPlus.cpp
Original file line number Diff line number Diff line change
@@ -1,125 +1,113 @@
#include "Halide.h"
#include "halide_load_raw.h"

#include "Burst.h"

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "../include/stb_image_write.h"

#include <stdio.h>
#include "align.h"
#include "merge.h"
#include "finish.h"
#include <iostream>
#include <fstream>

using namespace Halide;

using namespace std;
/*
* HDRPlus Class -- Houses file I/O, defines pipeline attributes and calls
* processes main stages of the pipeline.
*/
class HDRPlus {

private:

const Halide::Runtime::Buffer<uint16_t> imgs;

public:

private:

const Buffer<uint16_t> imgs;

public:

// dimensions of pixel phone output images are 3036 x 4048

static const int width = 5796;
static const int height = 3870;

const BlackPoint bp;
const WhitePoint wp;
const WhiteBalance wb;
const Compression c;
const Gain g;

HDRPlus(Buffer<uint16_t> imgs, BlackPoint bp, WhitePoint wp, WhiteBalance wb, Compression c, Gain g) : imgs(imgs), bp(bp), wp(wp), wb(wb), c(c), g(g) {

assert(imgs.dimensions() == 3); // width * height * img_idx
assert(imgs.width() == width);
assert(imgs.height() == height);
assert(imgs.extent(2) >= 2); // must have at least one alternate image
}

/*
* process -- Calls all of the main stages (align, merge, finish) of the pipeline.
*/
Buffer<uint8_t> process() {

Func alignment = align(imgs);
Func merged = merge(imgs, alignment);
Func finished = finish(merged, width, height, bp, wp, wb, c, g);

///////////////////////////////////////////////////////////////////////////
// realize image
///////////////////////////////////////////////////////////////////////////

Buffer<uint8_t> output_img(3, width, height);

finished.realize(output_img);

// transpose to account for interleaved layout

output_img.transpose(0, 1);
output_img.transpose(1, 2);

return output_img;
}

/*
* load_raws -- Loads CR2 (Canon Raw) files into a Halide Image.
*/
static bool load_raws(std::string dir_path, std::vector<std::string> &img_names, Buffer<uint16_t> &imgs) {

int num_imgs = img_names.size();

imgs = Buffer<uint16_t>(width, height, num_imgs);

uint16_t *data = imgs.data();

for (int n = 0; n < num_imgs; n++) {

std::string img_name = img_names[n];
std::string img_path = dir_path + "/" + img_name;

if(!Tools::load_raw(img_path, data, width, height)) {

std::cerr << "Input image failed to load" << std::endl;
return false;
}

data += width * height;
}
return true;

const int width;
const int height;

const BlackPoint bp;
const WhitePoint wp;
const WhiteBalance wb;
const Compression c;
const Gain g;
char *readfile;
std::string readfilestring;
void imagesize();

HDRPlus(Halide::Runtime::Buffer<uint16_t> imgs, BlackPoint bp, WhitePoint wp, WhiteBalance wb, Compression c, Gain g)
: imgs(imgs)
, width(imgs.width())
, height(imgs.height())
, bp(bp)
, wp(wp)
, wb(wb)
, c(c)
, g(g)
{
assert(imgs.dimensions() == 3); // width * height * img_idx
assert(imgs.extent(2) >= 2); // must have at least one alternate image
}

/*
* process -- Calls all of the main stages (align, merge, finish) of the pipeline.
*/
Buffer<uint8_t> process() {
Halide::Buffer<uint16_t> imgsBuffer(*imgs.raw_buffer());

Func alignment = align(imgsBuffer);
Func merged = merge(imgsBuffer, alignment);
Func finished = finish(merged, width, height, bp, wp, wb, c, g);

///////////////////////////////////////////////////////////////////////////
// realize image
///////////////////////////////////////////////////////////////////////////

Buffer<uint8_t> output_img(3, width, height);

finished.realize(output_img);

// transpose to account for interleaved layout

output_img.transpose(0, 1);
output_img.transpose(1, 2);

return output_img;
}

/*
* save_png -- Writes an interleaved Halide image to an output file.
*/
static bool save_png(std::string dir_path, std::string img_name, Buffer<uint8_t> &img) {

std::string img_path = dir_path + "/" + img_name;

std::remove(img_path.c_str());

int stride_in_bytes = img.width() * img.channels();

if(!stbi_write_png(img_path.c_str(), img.width(), img.height(), img.channels(), img.data(), stride_in_bytes)) {

std::cerr << "Unable to write output image '" << img_name << "'" << std::endl;
return false;
}

return true;
}
};

/*
* save_png -- Writes an interleaved Halide image to an output file.
*/
static bool save_png(std::string dir_path, std::string img_name, Buffer<uint8_t> &img) {

std::string img_path = dir_path + "/" + img_name;

std::remove(img_path.c_str());

int stride_in_bytes = img.width() * img.channels();

if(!stbi_write_png(img_path.c_str(), img.width(), img.height(), img.channels(), img.data(), stride_in_bytes)) {

std::cerr << "Unable to write output image '" << img_name << "'" << std::endl;
return false;
}

return true;
}
};

/*
* read_white_balance -- Reads white balance multipliers from file and returns WhiteBalance.
*/
const WhiteBalance read_white_balance(std::string file_path) {

Tools::Internal::PipeOpener f(("../tools/dcraw -v -i " + file_path).c_str(), "r");
Tools::Internal::PipeOpener f(("../tools/dcraw_macos -v -i " + file_path).c_str(), "r");

char buf[1024];

Expand All @@ -140,6 +128,7 @@ const WhiteBalance read_white_balance(std::string file_path) {
return {1, 1, 1, 1};
}


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

if (argc < 5) {
Expand Down Expand Up @@ -181,18 +170,22 @@ int main(int argc, char* argv[]) {
std::string out_name = argv[i++];

std::vector<std::string> in_names;

while (i < argc) in_names.push_back(argv[i++]);

Buffer<uint16_t> imgs;

if(!HDRPlus::load_raws(dir_path, in_names, imgs)) return -1;
Burst burst(dir_path, in_names);

const WhiteBalance wb = read_white_balance(dir_path + "/" + in_names[0]);
const BlackPoint bp = 2050;
const WhitePoint wp = 15464;
Halide::Runtime::Buffer<uint16_t> imgs = burst.ToBuffer();
if (imgs.channels() < 2) {
return EXIT_FAILURE;
}

HDRPlus hdr_plus = HDRPlus(imgs, bp, wp, wb, c, g);
HDRPlus hdr_plus = HDRPlus(
imgs,
burst.GetBlackLevel(),
burst.GetWhiteLevel(),
burst.GetWhiteBalance(),
c,
g);

Buffer<uint8_t> output = hdr_plus.process();

Expand Down
Loading

0 comments on commit dce3ca4

Please sign in to comment.