Implement Sony Pixel Shift for LibRaw
This commit is contained in:
@@ -136,6 +136,15 @@ protected:
|
||||
ushort *linebuf[_ltotal];
|
||||
};
|
||||
|
||||
/**
|
||||
* Metadata for merged pixel-shift image.
|
||||
*/
|
||||
struct MergedPixelshift
|
||||
{
|
||||
bool is_merged_pixelshift = false;
|
||||
unsigned sub_frame_shot_select;
|
||||
};
|
||||
|
||||
int fuji_total_lines, fuji_total_blocks, fuji_block_width, fuji_bits, fuji_raw_type;
|
||||
|
||||
ushort raw_height, raw_width, height, width, top_margin, left_margin;
|
||||
@@ -162,6 +171,7 @@ protected:
|
||||
ThreeValBool RT_matrix_from_constant;
|
||||
std::string RT_software;
|
||||
double RT_baseline_exposure;
|
||||
struct MergedPixelshift merged_pixelshift;
|
||||
|
||||
struct PanasonicRW2Info {
|
||||
ushort bpp;
|
||||
|
@@ -505,6 +505,22 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
||||
libraw->imgdata.rawparams.shot_select = shot_select;
|
||||
|
||||
int err = libraw->open_buffer(ifp->data, ifp->size);
|
||||
|
||||
merged_pixelshift.is_merged_pixelshift =
|
||||
err == LIBRAW_SUCCESS &&
|
||||
(strncmp(libraw->unpack_function_name(), "sony_arq_load_raw", 17) == 0 &&
|
||||
libraw->imgdata.idata.raw_count == 1 &&
|
||||
libraw->imgdata.idata.colors == 4);
|
||||
|
||||
if (err == LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE || (merged_pixelshift.is_merged_pixelshift && shot_select)) {
|
||||
// Try again last valid frame. Sony Pixel Shift, for example, has a
|
||||
// single frame, but we want to represent the data as four.
|
||||
shot_select = merged_pixelshift.is_merged_pixelshift ? shot_select / 4 : shot_select;
|
||||
shot_select = std::min(shot_select, std::max(libraw->imgdata.idata.raw_count, 1u) - 1);
|
||||
libraw->imgdata.rawparams.shot_select = shot_select;
|
||||
err = libraw->open_buffer(ifp->data, ifp->size);
|
||||
}
|
||||
|
||||
if (err == LIBRAW_FILE_UNSUPPORTED || err == LIBRAW_TOO_BIG) {
|
||||
// fallback to the internal one
|
||||
return err;
|
||||
@@ -532,6 +548,18 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
||||
colors = d.colors;
|
||||
tiff_bps = 0;
|
||||
|
||||
if (merged_pixelshift.is_merged_pixelshift ||
|
||||
(strncmp(libraw->unpack_function_name(), "sony_arq_load_raw", 17) == 0 &&
|
||||
is_raw == 1 && colors == 4)) {
|
||||
// Represent merged pixelshift as 4 sub-frames.
|
||||
merged_pixelshift.is_merged_pixelshift = true;
|
||||
merged_pixelshift.sub_frame_shot_select = imageNum % 4;
|
||||
|
||||
filters = 0x94949494;
|
||||
colors = 3;
|
||||
is_raw = 4;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
for (int j = 0; j < 6; ++j) {
|
||||
xtrans[i][j] = d.xtrans[i][j];
|
||||
@@ -576,6 +604,9 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
||||
cam_mul[i] = cd.cam_mul[i];
|
||||
pre_mul[i] = cd.pre_mul[i];
|
||||
}
|
||||
if (merged_pixelshift.is_merged_pixelshift) {
|
||||
pre_mul[3] = 0.f; // 4th value is undefined after reducing to 3 colors.
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
@@ -1102,6 +1133,41 @@ float** RawImage::compress_image(unsigned int frameNum, bool freeImage)
|
||||
|
||||
delete [] float_raw_image;
|
||||
float_raw_image = nullptr;
|
||||
} else if (merged_pixelshift.is_merged_pixelshift) {
|
||||
// Frame 0 is not shifted. Frame 1 is shifted down. Frame 2 is shifted
|
||||
// down and right. Frame 3 is shifted right.
|
||||
int h_shift = (merged_pixelshift.sub_frame_shot_select >> 1) & 1;
|
||||
int v_shift = ((merged_pixelshift.sub_frame_shot_select + 1u) >> 1) & 1;
|
||||
|
||||
// Reset edges to 0.
|
||||
for (int row = 0; row < v_shift; ++row) {
|
||||
for (int col = 0; col < width; ++col) {
|
||||
this->data[row][col] = 0;
|
||||
}
|
||||
}
|
||||
for (int col = 0; col < h_shift; ++col) {
|
||||
for (int row = 0; row < height; ++row) {
|
||||
this->data[row][col] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const int image_v_shift = top_margin - v_shift;
|
||||
const int image_h_shift = left_margin - h_shift;
|
||||
const unsigned original_filters = filters;
|
||||
|
||||
filters = 0xb4b4b4b4; // R G1 B G2.
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
|
||||
for (int row = v_shift; row < height; row++) {
|
||||
for (int col = h_shift; col < width; col++) {
|
||||
this->data[row][col] = image[(row + image_v_shift) * iwidth + col + image_h_shift][FC(row, col)];
|
||||
}
|
||||
}
|
||||
|
||||
filters = original_filters;
|
||||
} else if (filters != 0 && !isXtrans()) {
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
|
Reference in New Issue
Block a user