Issue 2139: extended camconst.json to handle raw crop

This commit is contained in:
torger
2013-12-18 14:27:57 +01:00
parent 803bef6b35
commit e90ab032f2
4 changed files with 147 additions and 13 deletions

100
rtengine/camconst.cc Normal file → Executable file
View File

@@ -22,6 +22,8 @@ extern const Settings* settings;
CameraConst::CameraConst()
{
memset(dcraw_matrix, 0, sizeof(dcraw_matrix));
memset(raw_crop, 0, sizeof(raw_crop));
memset(raw_mask, 0, sizeof(raw_mask));
white_max = 0;
}
@@ -96,16 +98,29 @@ CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_)
}
for (ji = ji->child; ji != NULL; ji = ji->next) {
int iso = 0;
int iso[1000] = { 0 };
int iso_count = 0;
cJSON *js = cJSON_GetObjectItem(ji, "iso");
if (!js) {
fprintf(stderr, "missing \"ranges\":\"%s\":\"iso\" object item.\n", bw ? "white" : "black");
return false;
} else if (js->type != cJSON_Number) {
fprintf(stderr, "\"ranges\":\"%s\":\"iso\" must be a a number.\n", bw ? "white" : "black");
} else if (js->type == cJSON_Number) {
iso[0] = js->valueint;
iso_count = 1;
} else if (js->type == cJSON_Array) {
int i;
for (js = js->child, i = 0; js != NULL && i < 1000; js = js->next, i++) {
if (js->type != cJSON_Number) {
fprintf(stderr, "\"ranges\":\"%s\":\"iso\" must be a number or an array of numbers.\n", bw ? "white" : "black");
return false;
}
iso[i] = js->valueint;
}
iso_count = i;
} else {
fprintf(stderr, "\"ranges\":\"%s\":\"iso\" must be an array or a number.\n", bw ? "white" : "black");
return false;
}
iso = js->valueint;
js = cJSON_GetObjectItem(ji, "levels");
if (!js) {
fprintf(stderr, "missing \"ranges\":\"%s\":\"levels\".\n", bw ? "white" : "black");
@@ -135,7 +150,9 @@ CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_)
fprintf(stderr, "\"ranges\":\"%s\":\"levels\" must be a number or an array of numbers.\n", bw ? "white" : "black");
return false;
}
cc->mLevels[bw].insert(std::pair<int,struct camera_const_levels>(iso, lvl));
for (int i = 0; i < iso_count; i++) {
cc->mLevels[bw].insert(std::pair<int,struct camera_const_levels>(iso[i], lvl));
}
}
return true;
}
@@ -165,6 +182,44 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model)
cc->dcraw_matrix[i] = (short)ji->valueint;
}
}
ji = cJSON_GetObjectItem(js, "raw_crop");
if (ji) {
if (ji->type != cJSON_Array) {
fprintf(stderr, "\"raw_crop\" must be an array\n");
goto parse_error;
}
int i;
for (i = 0, ji = ji->child; i < 4 && ji != NULL; i++, ji = ji->next) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"raw_crop\" array must contain numbers\n");
goto parse_error;
}
cc->raw_crop[i] = ji->valueint;
}
if (i != 4 || ji != NULL) {
fprintf(stderr, "\"raw_crop\" must contain 4 numbers\n");
goto parse_error;
}
}
ji = cJSON_GetObjectItem(js, "masked_areas");
if (ji) {
if (ji->type != cJSON_Array) {
fprintf(stderr, "\"masked_areas\" must be an array\n");
goto parse_error;
}
int i;
for (i = 0, ji = ji->child; i < 8 * 4 && ji != NULL; i++, ji = ji->next) {
if (ji->type != cJSON_Number) {
fprintf(stderr, "\"masked_areas\" array must contain numbers\n");
goto parse_error;
}
cc->raw_mask[i/4][i%4] = ji->valueint;
}
if (i % 4 != 0) {
fprintf(stderr, "\"masked_areas\" array length must be divisable by 4\n");
goto parse_error;
}
}
jranges = cJSON_GetObjectItem(js, "ranges");
if (jranges) {
ji = cJSON_GetObjectItem(jranges, "black");
@@ -236,6 +291,41 @@ CameraConst::get_dcrawMatrix(void)
return dcraw_matrix;
}
bool
CameraConst::has_rawCrop(void)
{
return raw_crop[0] != 0 || raw_crop[1] != 0 || raw_crop[2] != 0 || raw_crop[3] != 0;
}
void
CameraConst::get_rawCrop(int& left_margin, int& top_margin, int& width, int& height)
{
left_margin = raw_crop[0];
top_margin = raw_crop[1];
width = raw_crop[2];
height = raw_crop[3];
}
bool
CameraConst::has_rawMask(int idx)
{
if (idx < 0 || idx > 7)
return false;
return (raw_mask[idx][0] | raw_mask[idx][1] | raw_mask[idx][2] | raw_mask[idx][3]) != 0;
}
void
CameraConst::get_rawMask(int idx, int& top, int& left, int& bottom, int& right)
{
top = left = bottom = right = 0;
if (idx < 0 || idx > 7)
return;
top = raw_mask[idx][0];
left = raw_mask[idx][1];
bottom = raw_mask[idx][2];
right = raw_mask[idx][3];
}
void
CameraConst::update_Levels(const CameraConst *other) {
if (!other)

6
rtengine/camconst.h Normal file → Executable file
View File

@@ -17,6 +17,8 @@ class CameraConst {
private:
Glib::ustring make_model;
short dcraw_matrix[12];
int raw_crop[4];
int raw_mask[8][4];
int white_max;
std::map<int, struct camera_const_levels> mLevels[2];
std::map<float, float> mApertureScaling;
@@ -32,6 +34,10 @@ class CameraConst {
bool has_dcrawMatrix(void);
void update_dcrawMatrix(const short *other);
const short *get_dcrawMatrix(void);
bool has_rawCrop(void);
void get_rawCrop(int& left_margin, int& top_margin, int& width, int& height);
bool has_rawMask(int idx);
void get_rawMask(int idx, int& top, int& left, int& bottom, int& right);
int get_BlackLevel(int idx, int iso_speed);
int get_WhiteLevel(int idx, int iso_speed, float fnumber);
void update_Levels(const CameraConst *other);

View File

@@ -61,7 +61,13 @@ Examples:
// ColorMatrix with D65 Calibration Illuminant, in dcraw format
"dcraw_matrix": [ 7530, -1942, -255, -4318, 11390, 3362, -926, 1694, 7649 ],
// black and white level same for all colors at all ISOs
"ranges": { "black": 10, "white": 1000 }
"ranges": { "black": 10, "white": 1000 },
// crop away masked sensor borders, 10 pixels left, 20 pixels top, resulting image width/height 4000x3000
// instead of width/height you can write a negative number which specifies how much of right/bottom border
// that should be removed
"raw_crop": [ 10, 20, 4000, 3000 ],
// same as MaskedAreas DNG tag, used for black level measuring here two areas defined
"masked_areas": [ 51, 2, 3804, 156, 51, 5794, 3804, 5792 ],
},
{
@@ -500,6 +506,8 @@ Quality X: unknown, ie we knowing to little about the camera properties to know
{
"make_model": "DummyMake DummyModel",
"dcraw_matrix": [ 7530,-1942,-255,-4318,11390,3362,-926,1694,7649 ],
"raw_crop": [ 10, 20, 4000, 3000 ],
"masked_areas": [ 51, 2, 3804, 156, 51, 5794, 3804, 5792 ],
"ranges": {
"aperture_scaling": [
{ "aperture": 1.2, "scale_factor": 1.1 },
@@ -507,6 +515,7 @@ Quality X: unknown, ie we knowing to little about the camera properties to know
],
"black": [
{ "iso": 100 , "levels": [ 10, 20, 10, 20 ] },
{ "iso": [100, 200] , "levels": [ 30, 40, 30 ] },
{ "iso": 3200, "levels": [ 50, 60, 50, 60 ] }
],
"white": [

View File

@@ -232,11 +232,41 @@ int RawImage::loadRaw (bool loadData, bool closeFile)
fseek (ifp, data_offset, SEEK_SET);
(this->*load_raw)();
if (raw_image) {
crop_masked_pixels();
free (raw_image);
raw_image=NULL;
}
CameraConstantsStore* ccs = CameraConstantsStore::getInstance();
CameraConst *cc = ccs->get(make, model);
if (raw_image) {
if (cc && cc->has_rawCrop()) {
int lm, tm, w, h;
cc->get_rawCrop(lm, tm, w, h);
left_margin = lm;
top_margin = tm;
if (w < 0) {
iwidth += w;
iwidth -= left_margin;
width += w;
width -= left_margin;
} else if (w > 0) {
iwidth = width = w;
}
if (h < 0) {
iheight += h;
iheight -= top_margin;
height += h;
height -= top_margin;
} else if (h > 0) {
iheight = height = h;
}
}
if (cc && cc->has_rawMask(0)) {
for (int i = 0; i < 8 && cc->has_rawMask(i); i++) {
cc->get_rawMask(i, mask[i][0], mask[i][1], mask[i][2], mask[i][3]);
}
}
crop_masked_pixels();
free (raw_image);
raw_image=NULL;
}
// Load embedded profile
if (profile_length) {
@@ -257,8 +287,6 @@ int RawImage::loadRaw (bool loadData, bool closeFile)
*/
int black_c4[4] = { -1, -1, -1, -1 };
CameraConstantsStore* ccs = CameraConstantsStore::getInstance();
CameraConst *cc = ccs->get(make, model);
bool white_from_cc = false;
bool black_from_cc = false;
if (cc) {
@@ -296,6 +324,7 @@ int RawImage::loadRaw (bool loadData, bool closeFile)
black_from_cc ? "provided by camconst.json" : "provided by dcraw");
printf("white levels: R:%d G1:%d B:%d G2:%d (%s)\n", get_white(0), get_white(1), get_white(2), get_white(3),
white_from_cc ? "provided by camconst.json" : "provided by dcraw");
printf("raw crop: %d %d %d %d (provided by %s)\n", left_margin, top_margin, iwidth, iheight, (cc && cc->has_rawCrop()) ? "camconst.json" : "dcraw");
printf("color matrix provided by %s\n", (cc && cc->has_dcrawMatrix()) ? "camconst.json" : "dcraw");
}
}