diff --git a/rtdata/win/InnoSetup/WindowsInnoSetup.iss.in b/rtdata/win/InnoSetup/WindowsInnoSetup.iss.in index d15846097..5040ab415 100644 --- a/rtdata/win/InnoSetup/WindowsInnoSetup.iss.in +++ b/rtdata/win/InnoSetup/WindowsInnoSetup.iss.in @@ -96,6 +96,7 @@ Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescrip [Files] Source: "{#MyBuildBasePath}\rawtherapee.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#MyBuildBasePath}\camconst.json"; DestDir: "{app}"; Flags: ignoreversion Source: "{#MyBuildBasePath}\dcpprofiles\*"; DestDir: "{app}\dcpprofiles\"; Flags: ignoreversion recursesubdirs createallsubdirs ;Source: "{#MyBuildBasePath}\etc\*"; DestDir: "{app}\etc\"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "{#MyBuildBasePath}\iccprofiles\*"; DestDir: "{app}\iccprofiles\"; Flags: ignoreversion recursesubdirs createallsubdirs diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index dfac79d92..03f339f97 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -5,6 +5,8 @@ link_directories ("${PROJECT_SOURCE_DIR}/rtexif" ${EXTRA_LIBDIR} ${GTHREAD_LIBRA ${GOBJECT_LIBRARY_DIRS} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${IPTCDATA_LIBRARY_DIRS} ${LCMS_LIBRARY_DIRS} ${EXPAT_LIBRARY_DIRS} ${FFTW3F_LIBRARY_DIRS}) +set (CAMCONSTSFILE "camconst.json") + set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc dcraw.cc iccstore.cc color.cc dfmanager.cc ffmanager.cc rawimage.cc image8.cc image16.cc imagefloat.cc imagedata.cc imageio.cc improcfun.cc init.cc dcrop.cc loadinitial.cc procparams.cc rawimagesource.cc demosaic_algos.cc shmap.cc simpleprocess.cc refreshmap.cc @@ -17,6 +19,7 @@ set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagona PF_correct_RT.cc dirpyr_equalizer.cc calc_distort.cc lcp.cc dcp.cc + cJSON.c camconst.cc klt/convolve.cc klt/error.cc klt/klt.cc klt/klt_util.cc klt/pnmio.cc klt/pyramid.cc klt/selectGoodFeatures.cc klt/storeFeatures.cc klt/trackFeatures.cc klt/writeFeatures.cc ) @@ -34,3 +37,5 @@ set_target_properties (rtengine PROPERTIES COMPILE_FLAGS "${RTENGINE_CXX_FLAGS}" target_link_libraries (rtengine rtexif ${EXTRA_LIB} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES} ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${LCMS_LIBRARIES} ${EXPAT_LIBRARIES} ${FFTW3F_LIBRARIES} ${IPTCDATA_LIBRARIES} ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${TIFF_LIBRARIES} ${ZLIB_LIBRARIES}) + +install (FILES ${CAMCONSTSFILE} DESTINATION "${BINDIR}" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) diff --git a/rtengine/cJSON.c b/rtengine/cJSON.c new file mode 100644 index 000000000..31c43dd2e --- /dev/null +++ b/rtengine/cJSON.c @@ -0,0 +1,596 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" + +static const char *ep; + +const char *cJSON_GetErrorPtr(void) {return ep;} + +static int cJSON_strcasecmp(const char *s1,const char *s2) +{ + if (!s1) return (s1==s2)?0:1;if (!s2) return 1; + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; + +static char* cJSON_strdup(const char* str) +{ + size_t len; + char* copy; + + len = strlen(str) + 1; + if (!(copy = (char*)cJSON_malloc(len))) return 0; + memcpy(copy,str,len); + return copy; +} + +void cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; + cJSON_free = (hooks->free_fn)?hooks->free_fn:free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(void) +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) memset(node,0,sizeof(cJSON)); + return node; +} + +/* Delete a cJSON structure. */ +void cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) + { + next=c->next; + if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); + if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); + if (c->string) cJSON_free(c->string); + cJSON_free(c); + c=next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item,const char *num) +{ + double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + + if (*num=='-') sign=-1,num++; /* Has sign? */ + if (*num=='0') num++; /* is zero */ + if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ + if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ + if (*num=='e' || *num=='E') /* Exponent? */ + { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ + while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ + } + + n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble=n; + item->valueint=(int)n; + item->type=cJSON_Number; + return num; +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(cJSON *item) +{ + char *str; + double d=item->valuedouble; + if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) + { + str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) sprintf(str,"%d",item->valueint); + } + else + { + str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) + { + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); + else sprintf(str,"%f",d); + } + } + return str; +} + +static unsigned parse_hex4(const char *str) +{ + unsigned h=0; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + return h; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +static const char *parse_string(cJSON *item,const char *str) +{ + const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; + if (*str!='\"') {ep=str;return 0;} /* not a string! */ + + while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ + + out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ + if (!out) return 0; + + ptr=str+1;ptr2=out; + while (*ptr!='\"' && *ptr) + { + if (*ptr!='\\') *ptr2++=*ptr++; + else + { + ptr++; + switch (*ptr) + { + case 'b': *ptr2++='\b'; break; + case 'f': *ptr2++='\f'; break; + case 'n': *ptr2++='\n'; break; + case 'r': *ptr2++='\r'; break; + case 't': *ptr2++='\t'; break; + case 'u': /* transcode utf16 to utf8. */ + uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ + + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ + + if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ + { + if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ + uc2=parse_hex4(ptr+3);ptr+=6; + if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ + uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); + } + + len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; + + switch (len) { + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 1: *--ptr2 =(uc | firstByteMark[len]); + } + ptr2+=len; + break; + default: *ptr2++=*ptr; break; + } + ptr++; + } + } + *ptr2=0; + if (*ptr=='\"') ptr++; + item->valuestring=out; + item->type=cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str) +{ + const char *ptr;char *ptr2,*out;int len=0;unsigned char token; + + if (!str) return cJSON_strdup(""); + ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} + + out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + + ptr2=out;ptr=str; + *ptr2++='\"'; + while (*ptr) + { + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; + else + { + *ptr2++='\\'; + switch (token=*ptr++) + { + case '\\': *ptr2++='\\'; break; + case '\"': *ptr2++='\"'; break; + case '\b': *ptr2++='b'; break; + case '\f': *ptr2++='f'; break; + case '\n': *ptr2++='n'; break; + case '\r': *ptr2++='r'; break; + case '\t': *ptr2++='t'; break; + default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ + } + } + } + *ptr2++='\"';*ptr2++=0; + return out; +} +/* Invote print_string_ptr (which is useful) on an item. */ +static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item,const char *value); +static char *print_value(cJSON *item,int depth,int fmt); +static const char *parse_array(cJSON *item,const char *value); +static char *print_array(cJSON *item,int depth,int fmt); +static const char *parse_object(cJSON *item,const char *value); +static char *print_object(cJSON *item,int depth,int fmt); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} + +/* Parse an object - create a new root, and populate. */ +cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) +{ + const char *end=0; + cJSON *c=cJSON_New_Item(); + ep=0; + if (!c) return 0; /* memory fail */ + + end=parse_value(c,skip(value)); + if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} + if (return_parse_end) *return_parse_end=end; + return c; +} +/* Default options for cJSON_Parse */ +cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} + +/* Render a cJSON item/entity/structure to text. */ +char *cJSON_Print(cJSON *item) {return print_value(item,0,1);} +char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item,const char *value) +{ + if (!value) return 0; /* Fail on null. */ + if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } + if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } + if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } + if (*value=='\"') { return parse_string(item,value); } + if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } + if (*value=='[') { return parse_array(item,value); } + if (*value=='{') { return parse_object(item,value); } + + ep=value;return 0; /* failure. */ +} + +/* Render a value to text. */ +static char *print_value(cJSON *item,int depth,int fmt) +{ + char *out=0; + if (!item) return 0; + switch ((item->type)&255) + { + case cJSON_NULL: out=cJSON_strdup("null"); break; + case cJSON_False: out=cJSON_strdup("false");break; + case cJSON_True: out=cJSON_strdup("true"); break; + case cJSON_Number: out=print_number(item);break; + case cJSON_String: out=print_string(item);break; + case cJSON_Array: out=print_array(item,depth,fmt);break; + case cJSON_Object: out=print_object(item,depth,fmt);break; + } + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='[') {ep=value;return 0;} /* not an array! */ + + item->type=cJSON_Array; + value=skip(value+1); + if (*value==']') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; /* memory fail */ + value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_value(child,skip(value+1))); + if (!value) return 0; /* memory fail */ + } + + if (*value==']') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an array to text */ +static char *print_array(cJSON *item,int depth,int fmt) +{ + char **entries; + char *out=0,*ptr,*ret;int len=5; + cJSON *child=item->child; + int numentries=0,i=0,fail=0; + + /* How many entries in the array? */ + while (child) numentries++,child=child->next; + /* Explicitly handle numentries==0 */ + if (!numentries) + { + out=(char*)cJSON_malloc(3); + if (out) strcpy(out,"[]"); + return out; + } + /* Allocate an array to hold the values for each */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + /* Retrieve all the results: */ + child=item->child; + while (child && !fail) + { + ret=print_value(child,depth+1,fmt); + entries[i++]=ret; + if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; + child=child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + /* If that fails, we fail. */ + if (!out) fail=1; + + /* Handle failure. */ + if (fail) + { + for (i=0;itype=cJSON_Object; + value=skip(value+1); + if (*value=='}') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; + value=skip(parse_string(child,skip(value))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_string(child,skip(value+1))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + } + + if (*value=='}') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char *print_object(cJSON *item,int depth,int fmt) +{ + char **entries=0,**names=0; + char *out=0,*ptr,*ret,*str;int len=7,i=0,j; + cJSON *child=item->child; + int numentries=0,fail=0; + /* Count the number of entries. */ + while (child) numentries++,child=child->next; + /* Explicitly handle empty object case */ + if (!numentries) + { + out=(char*)cJSON_malloc(fmt?depth+4:3); + if (!out) return 0; + ptr=out;*ptr++='{'; + if (fmt) {*ptr++='\n';for (i=0;ichild;depth++;if (fmt) len+=depth; + while (child) + { + names[i]=str=print_string_ptr(child->string); + entries[i++]=ret=print_value(child,depth,fmt); + if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; + child=child->next; + } + + /* Try to allocate the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + if (!out) fail=1; + + /* Handle failure */ + if (fail) + { + for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} +cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} +cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} +/* Utility for handling references. */ +static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} + +/* Add item to array/object. */ +void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} +void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} +void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} +void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} + +cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; + if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} +void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} +cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} +void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} + +/* Replace array/object items with new ones. */ +void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; + newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; + if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} +void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} + +/* Create basic types: */ +cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} +cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} +cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} +cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} + +/* Create Arrays: */ +cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} + +/* Duplication */ +cJSON *cJSON_Duplicate(cJSON *item,int recurse) +{ + cJSON *newitem,*cptr,*nptr=0,*newchild; + /* Bail on bad ptr */ + if (!item) return 0; + /* Create new item */ + newitem=cJSON_New_Item(); + if (!newitem) return 0; + /* Copy over all vars */ + newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; + if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} + if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} + /* If non-recursive, then we're done! */ + if (!recurse) return newitem; + /* Walk the ->next chain for the child. */ + cptr=item->child; + while (cptr) + { + newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) {cJSON_Delete(newitem);return 0;} + if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ + cptr=cptr->next; + } + return newitem; +} + +void cJSON_Minify(char *json) +{ + char *into=json; + while (*json) + { + if (*json==' ') json++; + else if (*json=='\t') json++; // Whitespace characters. + else if (*json=='\r') json++; + else if (*json=='\n') json++; + else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line. + else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments. + else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive. + else *into++=*json++; // All other characters. + } + *into=0; // and null-terminate. +} \ No newline at end of file diff --git a/rtengine/cJSON.h b/rtengine/cJSON.h new file mode 100644 index 000000000..867b7c32f --- /dev/null +++ b/rtengine/cJSON.h @@ -0,0 +1,143 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 + +/* The cJSON structure: */ +typedef struct cJSON { + struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks { + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(void); +extern cJSON *cJSON_CreateTrue(void); +extern cJSON *cJSON_CreateFalse(void); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(void); +extern cJSON *cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); +extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); +extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); +extern cJSON *cJSON_CreateStringArray(const char **strings,int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); +extern void cJSON_DeleteItemFromArray(cJSON *array,int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); + +/* Update array items. */ +extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ + +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); + +extern void cJSON_Minify(char *json); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc new file mode 100644 index 000000000..c5e5d2f80 --- /dev/null +++ b/rtengine/camconst.cc @@ -0,0 +1,368 @@ +/* + * This file is part of RawTherapee. + */ +#include "camconst.h" +#include "safegtk.h" +#include "rt_math.h" +#include +#include + +// cJSON is a very minimal JSON parser lib in C, not for threaded stuff etc, so if we're going to use JSON more than just +// here we should probably replace cJSON with something beefier. +#include "cJSON.h" +#include +#include +#include + +namespace rtengine { + +CameraConst::CameraConst() +{ + memset(dcraw_matrix, 0, sizeof(dcraw_matrix)); +} + +CameraConst::~CameraConst() +{ +} + +bool +CameraConst::parseLevels(CameraConst *cc, int bw, void *ji_) +{ + cJSON *ji = (cJSON *)ji_; + + if (ji->type == cJSON_Number) { + struct camera_const_levels lvl; + lvl.levels[0] = lvl.levels[1] = lvl.levels[2] = lvl.levels[3] = ji->valueint; + cc->mLevels[bw].insert(std::pair(0, lvl)); + return true; + } else if (ji->type != cJSON_Array) { + fprintf(stderr, "\"ranges\":\"black\" must be a number or an array\n"); + return false; + } + + for (ji = ji->child; ji != NULL; ji = ji->next) { + int iso = 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"); + return false; + } + iso = js->valueint; + js = cJSON_GetObjectItem(ji, "levels"); + if (!js) { + fprintf(stderr, "missing \"ranges\":\"%s\":\"levels\".\n", bw ? "white" : "black"); + return false; + } + struct camera_const_levels lvl; + if (js->type == cJSON_Number) { + lvl.levels[0] = lvl.levels[1] = lvl.levels[2] = lvl.levels[3] = ji->valueint; + } else if (js->type == cJSON_Array) { + int i; + for (js = js->child, i = 0; js != NULL && i < 4; js = js->next, i++) { + if (js->type != cJSON_Number) { + fprintf(stderr, "\"ranges\":\"%s\":\"levels\" must be a number or an array of numbers.\n", bw ? "white" : "black"); + return false; + } + lvl.levels[i] = js->valueint; + } + if (i == 3) { + lvl.levels[3] = lvl.levels[1]; // G2 = G1 + } else if (i == 1) { + lvl.levels[3] = lvl.levels[2] = lvl.levels[1] = lvl.levels[0]; + } else if (i != 4 || js != NULL) { + fprintf(stderr, "\"ranges\":\"%s\":\"levels\" array must have 1, 3 or 4 numbers.\n", bw ? "white" : "black"); + return false; + } + } else { + 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(iso, lvl)); + } + return true; +} + +CameraConst * +CameraConst::parseEntry(void *cJSON_) +{ + CameraConst *cc = 0; + cJSON *js, *ji, *jranges; + js = (cJSON *)cJSON_; + + ji = cJSON_GetObjectItem(js, "make_model"); + if (!ji || ji->type != cJSON_String) { + fprintf(stderr, "missing \"make_model\" object item\n"); + goto parse_error; + } + cc = new CameraConst; + cc->make_model = Glib::ustring(ji->valuestring); + + ji = cJSON_GetObjectItem(js, "dcraw_matrix"); + if (ji) { + if (ji->type != cJSON_Array) { + fprintf(stderr, "\"dcraw_matrix\" must be an array\n"); + goto parse_error; + } + int i; + for (i = 0, ji = ji->child; i < 12 && ji != NULL; i++, ji = ji->next) { + if (ji->type != cJSON_Number) { + fprintf(stderr, "\"dcraw_matrix\" array must contain numbers\n"); + goto parse_error; + } + cc->dcraw_matrix[i] = (short)ji->valueint; + } + } + jranges = cJSON_GetObjectItem(js, "ranges"); + if (jranges) { + ji = cJSON_GetObjectItem(jranges, "black"); + if (ji) { + if (!parseLevels(cc, 0, ji)) { + goto parse_error; + } + } + ji = cJSON_GetObjectItem(jranges, "white"); + if (ji) { + if (!parseLevels(cc, 1, ji)) { + goto parse_error; + } + } + } + for (int bw = 0; bw < 2; bw++) { + if (!cc->get_Levels(bw, 0)) { + std::map::iterator it; + it = cc->mLevels[bw].begin(); + if (it != cc->mLevels[bw].end()) { + // insert levels with lowest iso as the default (iso 0) + struct camera_const_levels lvl = it->second; + cc->mLevels[bw].insert(std::pair(0, lvl)); + } + } + } + return cc; + +parse_error: + return 0; +} + +bool +CameraConst::has_dcrawMatrix(void) +{ + return dcraw_matrix[0] != 0; +} + +void +CameraConst::update_dcrawMatrix(const short *other) { + if (!other) + return; + + for (int i=0; i<12; ++i) + dcraw_matrix[i] = other[i]; +} + +const short * +CameraConst::get_dcrawMatrix(void) +{ + if (!has_dcrawMatrix()) { + return 0; + } + return dcraw_matrix; +} + +void +CameraConst::update_Levels(const CameraConst *other) { + if (!other) + return; + + if (other->mLevels[0].size()) { + mLevels[0].clear(); + mLevels[0] = other->mLevels[0]; + } + if (other->mLevels[1].size()) { + mLevels[1].clear(); + mLevels[1] = other->mLevels[1]; + } + +// for (std::map::iterator i=other->mLevels[0].begin(); i!=other->mLevels[0].end(); i++) { +// } +} + +const struct camera_const_levels * +CameraConst::get_Levels(int bw, int iso) +{ + std::map::iterator it; + it = mLevels[bw].find(iso); + if (it == mLevels[bw].end()) { + std::map::iterator best_it = mLevels[bw].begin(); + if (iso > 0) { + for (it = mLevels[bw].begin(); it != mLevels[bw].end(); it++) { + if (abs(it->first - iso) <= abs(best_it->first - iso)) { + best_it = it; + } else { + break; + } + } + } + it = best_it; + if (it == mLevels[bw].end()) { + return 0; + } + } + return &it->second; +} + +int +CameraConst::get_BlackLevel(const int idx, const int iso_speed) +{ + assert(idx >= 0 && idx <= 3); + const struct camera_const_levels *lvl = get_Levels(0, iso_speed); + return (lvl) ? lvl->levels[idx] : -1; +} + +int +CameraConst::get_WhiteLevel(const int idx, const int iso_speed) +{ + assert(idx >= 0 && idx <= 3); + const struct camera_const_levels *lvl = get_Levels(1, iso_speed); + return (lvl) ? lvl->levels[idx] : -1; +} + +bool +CameraConstantsStore::parse_camera_constants_file(Glib::ustring filename_) +{ + // read the file into a single long string + const char *filename = filename_.c_str(); + FILE *stream = fopen(filename, "rt"); + if (stream == NULL) { + fprintf(stderr, "Could not open camera constants file \"%s\": %s\n", filename, strerror(errno)); + return false; + } + size_t bufsize = 64; // use small initial size just to make sure to test realloc() case + size_t datasize = 0, ret; + char *buf = (char *)malloc(bufsize); + while ((ret = fread(&buf[datasize], 1, bufsize - datasize, stream)) != 0) { + datasize += bufsize - datasize; + if (datasize == bufsize) { + bufsize += 4096; + buf = (char *)realloc(buf, bufsize); + } + } + if (!feof(stream)) { + fclose(stream); + free(buf); + fprintf(stderr, "Failed to read camera constants file \"%s\"\n", filename); + return false; + } + fclose(stream); + datasize += ret; + buf = (char *)realloc(buf, datasize + 1); + buf[datasize] = '\0'; + + // remove comments + cJSON_Minify(buf); + + // parse + cJSON *jsroot = cJSON_Parse(buf); + if (!jsroot) { + char str[128]; + const char *ep = cJSON_GetErrorPtr() - 10; + if ((uintptr_t)ep < (uintptr_t)buf) { + ep = buf; + } + strncpy(str, ep, sizeof(str)); + str[sizeof(str)-1] = '\0'; + fprintf(stderr, "JSON parse error in file \"%s\" near '%s'\n", filename, str); + free(buf); + return false; + } + free(buf); + /*{ + char *js_str = cJSON_Print(jsroot); + printf("%s\n", js_str); + free(js_str); + }*/ + cJSON *js = cJSON_GetObjectItem(jsroot, "camera_constants"); + if (!js) { + fprintf(stderr, "missing \"camera_constants\" object item\n"); + goto parse_error; + } + for (js = js->child; js != NULL; js = js->next) { + cJSON *ji = cJSON_GetObjectItem(js, "make_model"); + if (!ji || ji->type != cJSON_String) { + fprintf(stderr, "missing \"make_model\" object item\n"); + goto parse_error; + } + CameraConst *cc = CameraConst::parseEntry((void *)js); + if (!cc) { + goto parse_error; + } + + Glib::ustring make_model(ji->valuestring); + std::map::iterator existingccIter = mCameraConstants.find(make_model); + + if (existingccIter == mCameraConstants.end()) + // add the new CamConst to the map + mCameraConstants.insert(std::pair(make_model, cc)); + else { + // The CameraConst already exist for this camera make/model -> we merge the values + CameraConst *existingcc = existingccIter->second; + + // updating the dcraw matrix + existingcc->update_dcrawMatrix(cc->get_dcrawMatrix()); + // deleting all the existing levels, replaced by the new ones + existingcc->update_Levels(cc); + } + } + cJSON_Delete(jsroot); + return true; + +parse_error: + fprintf(stderr, "failed to parse camera constants file \"%s\"\n", filename); + mCameraConstants.clear(); + cJSON_Delete(jsroot); + return false; +} + +CameraConstantsStore::CameraConstantsStore() +{ +} + +static CameraConstantsStore *global_instance; + +void CameraConstantsStore::initCameraConstants(Glib::ustring baseDir, Glib::ustring userSettingsDir) +{ + if (global_instance) { + // should only be called once during init. + abort(); + } + global_instance = new CameraConstantsStore(); + global_instance->parse_camera_constants_file(Glib::build_filename(baseDir, "camconst.json")); + + Glib::ustring userFile(Glib::build_filename(userSettingsDir, "camconst.json")); + if (safe_file_test(userFile, Glib::FILE_TEST_EXISTS)) + global_instance->parse_camera_constants_file(userFile); +} + +CameraConstantsStore * +CameraConstantsStore::getInstance(void) +{ + return global_instance; +} + +CameraConst * +CameraConstantsStore::get(const char make[], const char model[]) +{ + Glib::ustring key(make); + key += " "; + key += model; + std::map::iterator it; + it = mCameraConstants.find(key); + if (it == mCameraConstants.end()) { + return 0; + } + return it->second; +} + +} // namespace rtengine diff --git a/rtengine/camconst.h b/rtengine/camconst.h new file mode 100644 index 000000000..3716ec7c0 --- /dev/null +++ b/rtengine/camconst.h @@ -0,0 +1,52 @@ +/* + * This file is part of RawTherapee. + */ +#ifndef __CAMCONST__ +#define __CAMCONST__ + +#include +#include + +namespace rtengine { + +struct camera_const_levels { + int levels[4]; +}; + +class CameraConst { + private: + Glib::ustring make_model; + short dcraw_matrix[12]; + std::map mLevels[2]; + + CameraConst(); + ~CameraConst(); + static bool parseLevels(CameraConst *cc, int bw, void *ji); + const struct camera_const_levels *get_Levels(int bw, int iso); + + public: + static CameraConst *parseEntry(void *cJSON); + bool has_dcrawMatrix(void); + void update_dcrawMatrix(const short *other); + const short *get_dcrawMatrix(void); + int get_BlackLevel(int idx, int iso_speed); + int get_WhiteLevel(int idx, int iso_speed); + void update_Levels(const CameraConst *other); +}; + +class CameraConstantsStore { + private: + std::map mCameraConstants; + + CameraConstantsStore(); + bool parse_camera_constants_file(Glib::ustring filename); + + public: + static void initCameraConstants(Glib::ustring baseDir, Glib::ustring userSettingsDir); + static CameraConstantsStore *getInstance(void); + CameraConst *get(const char make[], const char model[]); +}; + +} + +#endif diff --git a/rtengine/camconst.json b/rtengine/camconst.json new file mode 100644 index 000000000..c685c0272 --- /dev/null +++ b/rtengine/camconst.json @@ -0,0 +1,181 @@ +/* + + DO NOT EDIT THIS FILE! + + All changes made here will be lost on software update. + If you want to add custom values or changes existing ones, + create a "camconst.json" file next to your personal "options" file. + Its values will then override and/or complete the ones of this file. + + If you add values for your own camera and are okay to share them with + RawTherapee's community, please drop a link on the user's forum + + IMPORTANT: + ---------- + + 1. If you set the dcraw matrix in your user file for an already existing entry + in RT's file (same camera, same model), your values will replace RT's ones. + 2. If you set the Black level(s) values in your user file for an already existing + entry in RT's file, your values will replace RT's ones, even if RT's ones are + more complete and/or detailed. You might want to copy/paste RT's levels first + (if provided) to your user's file and complete/modify it. + + Same for the White level(s), independently from the Black level(s). + + +---------------------------------------------------------------------------------- + + +This file is in JSON format and contains camera constants which RawTherapee uses +when parsing raw files. + +Raw files themselves unfortunately do not contain all information needed for making +a raw conversion, typically color response information and black/white levels are +missing. That's why this file is needed. + +It's read once during startup, so if the file is updated you need to restart +RawTherapee in order to take effect. The file is not intended for modification by +the casual user, but advanced users can add missing camera information to this file. +If you do so please report at http://code.google.com/p/rawtherapee/issues so we can +extend the distributed version of this file so your provided camera information +becomes available to all. + +RawTherapee uses DCRAW as the raw format parser. DCRAW contains hard-coded camera +constants, but not for all cameras and not always accurate information. For example +DCRAW only support one white level, while some cameras have different white levels +per channel and per ISO. If a camera is not listed in this file the constants from +DCRAW will be used, if listed here this information will override any constants in +DCRAW (if any). + +Some cameras may only have partial information here, for example if the raw file +itself contains a color matrix it's not entered here. A camera whose black level +is measured on special pixels in the raw file should only have white levels here +etc. + +Examples: + + { + // make and model separated with single space, must match make + // and model as provided by dcraw (case-insensitive). + "make_model": "ManufacturerA ModelB", + // 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 } + }, + + { + "make_model": "ManufacturerA ModelB", + "dcraw_matrix": [ 7530,-1942,-255,-4318,11390,3362,-926,1694,7649 ], + // black and white levels per ISO per channel + // this example only two ISOs, normally the list should be more populated. + // When RawTherapee asks for black/white levels for a specific ISO the closest + // match is picked. + "ranges": { + "black": [ + { "iso": 100, "levels": 10 }, // here only one level, same level for all channels + { "iso": 3200, "levels": [ 50, 60, 50 ] } // 3 levels, G2 same as G1 + ], + "white": [ + { "iso": 100, "levels": [ 10000, 11000, 10000, 12000 ] }, // 4 levels, G1 and G2 different + { "iso": 3200, "levels": [ 11000, 11000, 10000, 12000 ] } + ] + } + } + +*/ +{"camera_constants": [ + + // Phase One: color matrices borrowed from Adobe DNG Converter, black/white levels tested on actual raw files + { + "make_model": "Phase One P40+", + "dcraw_matrix": [ 8035,435,-962,-6001,13872,2320,-1159,3065,5434 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One IQ140", + "dcraw_matrix": [ 8035,435,-962,-6001,13872,2320,-1159,3065,5434 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One P65+", + "dcraw_matrix": [ 8035,435,-962,-6001,13872,2320,-1159,3065,5434 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One IQ160", + "dcraw_matrix": [ 8035,435,-962,-6001,13872,2320,-1159,3065,5434 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One IQ180", + "dcraw_matrix": [ 6294,686,-712,-5435,13417,2211,-1006,2435,5042 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One P20", + "dcraw_matrix": [ 2905,732,-237,-8135,16626,1476,-3038,4253,7517 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One P20+", + "dcraw_matrix": [ 2905,732,-237,-8135,16626,1476,-3038,4253,7517 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One P21", + "dcraw_matrix": [ 6516,-2050,-507,-8217,16703,1479,-3492,4741,8489 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One P21+", + "dcraw_matrix": [ 6516,-2050,-507,-8217,16703,1479,-3492,4741,8489 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One P25", + "dcraw_matrix": [ 2905,732,-237,-8135,16626,1476,-3038,4253,7517 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One P25+", + "dcraw_matrix": [ 2905,732,-237,-8135,16626,1476,-3038,4253,7517 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One P30", + "dcraw_matrix": [ 4516,-244,-36,-7020,14976,2174,-3206,4670,7087 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One P30+", + "dcraw_matrix": [ 4516,-244,-36,-7020,14976,2174,-3206,4670,7087 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One 45", + "dcraw_matrix": [ 5053,-24,-117,-5685,14077,1703,-2619,4491,5850 ], + "ranges": { "black": 0, "white": 64400 } + }, + { + "make_model": "Phase One 45+", + "dcraw_matrix": [ 5053,-24,-117,-5685,14077,1703,-2619,4491,5850 ], + "ranges": { "black": 0, "white": 64400 } + }, + + // dummy test entry to test the parser and show the format with all entries active + { + "make_model": "DummyMake DummyModel", + "dcraw_matrix": [ 7530,-1942,-255,-4318,11390,3362,-926,1694,7649 ], + "ranges": { + "black": [ + { "iso": 100 , "levels": [ 10, 20, 10, 20 ] }, + { "iso": 3200, "levels": [ 50, 60, 50, 60 ] } + ], + "white": [ + { "iso": 100 , "levels": [ 10000, 11000, 10000, 11000 ] }, + { "iso": 3200, "levels": [ 11000, 11000, 10000, 11000 ] } + ] + } + } +]} diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 13b10efde..281bc0cec 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -6231,30 +6231,30 @@ void CLASS adobe_coeff (const char *make, const char *model) { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } }, { "Canon EOS D60", 0, 0xfa0, { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } }, - { "Canon EOS 5D Mark III", 0, 0x3a98, /* RT */ + { "Canon EOS 5D Mark III", 0, 0x3c80, { 6722,-635,-963,-4287,12460,2028,-908,2162,5668 } }, { "Canon EOS 5D Mark II", 0, 0x3cf0, { 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } }, - { "Canon EOS 5D", 0, 0xe6c, /* RT */ - { 6319,-793,-614,-5809,13342,2738,-1132,1559,7971 } }, - { "Canon EOS 6D", 0, 0x3c82, + { "Canon EOS 5D", 0, 0xe6c, + { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } }, + { "Canon EOS 6D", 0, 0x3c82, { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } }, - { "Canon EOS 7D", 0, 0x3510, /* RT - Colin Walker */ - { 5962,-171,-732,-4189,12307,2099,-911,1981,6304 } }, + { "Canon EOS 7D", 0, 0x3510, + { 6844,-996,-856,-3876,11761,2396,-593,1772,6198 } }, { "Canon EOS 10D", 0, 0xfa0, { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, { "Canon EOS 20Da", 0, 0, { 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } }, - { "Canon EOS 20D", 0, 0xfff, /* RT */ - { 7590,-1646,-673,-4697,12411,2568,-627,1118,7295 } }, + { "Canon EOS 20D", 0, 0xfff, + { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } }, { "Canon EOS 30D", 0, 0, { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } }, - { "Canon EOS 40D", 0, 0x3f60, /* RT */ - { 6070,-531,-883,-5763,13647,2315,-1533,2582,6801 } }, + { "Canon EOS 40D", 0, 0x3f60, + { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } }, { "Canon EOS 50D", 0, 0x3d93, { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } }, - { "Canon EOS 60D", 0, 0x2ff7, /* RT - Colin Walker */ - { 5678,-179,-718,-4389,12381,2243,-869,1819,6380 } }, + { "Canon EOS 60D", 0, 0x2ff7, + { 6719,-994,-925,-4408,12426,2211,-887,2129,6051 } }, { "Canon EOS 100D", 0, 0x350f, { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, { "Canon EOS 300D", 0, 0xfa0, @@ -6263,12 +6263,12 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } }, { "Canon EOS 400D", 0, 0xe8e, { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } }, - { "Canon EOS 450D", 0, 0x390d, /* RT */ - { 6246,-1272,-523,-5075,12357,3075,-1035,1825,7333 } }, + { "Canon EOS 450D", 0, 0x390d, + { 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } }, { "Canon EOS 500D", 0, 0x3479, { 4763,712,-646,-6821,14399,2640,-1921,3276,6561 } }, - { "Canon EOS 550D", 0, 0x3dd7, /* RT - Lebedev*/ - { 6519,-772,-703,-4994,12737,2519,-1387,2492,6175 } }, + { "Canon EOS 550D", 0, 0x3dd7, + { 6941,-1164,-857,-3825,11597,2534,-416,1540,6039 } }, { "Canon EOS 600D", 0, 0x3510, { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } }, { "Canon EOS 650D", 0, 0x354d, @@ -6287,8 +6287,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } }, { "Canon EOS-1D Mark IV", 0, 0x3bb0, { 6014,-220,-795,-4109,12014,2361,-561,1824,5787 } }, - { "Canon EOS-1D Mark III", 0, 0x3bb0, /* RT */ - { 7406,-1592,-646,-4856,12457,2698,-432,726,7921 } }, + { "Canon EOS-1D Mark III", 0, 0x3bb0, + { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } }, { "Canon EOS-1D Mark II N", 0, 0xe80, { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } }, { "Canon EOS-1D Mark II", 0, 0xe80, @@ -6307,12 +6307,12 @@ void CLASS adobe_coeff (const char *make, const char *model) { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } }, { "Canon PowerShot A5", 0, 0, { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } }, - { "Canon PowerShot G10", 0, 0, /* RT */ - { 12535,-5030,-796,-2711,10134,3006,-413,1605,5264 } }, + { "Canon PowerShot G10", 0, 0, + { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } }, { "Canon PowerShot G11", 0, 0, { 12177,-4817,-1069,-1612,9864,2049,-98,850,4471 } }, - { "Canon PowerShot G12", 0, 0, /* RT */ - { 12222,-4097,-1380,-2876,11016,2130,-888,1630,4434 } }, + { "Canon PowerShot G12", 0, 0, + { 13244,-5501,-1248,-1508,9858,1935,-270,1083,4366 } }, { "Canon PowerShot G15", 0, 0, { 7474,-2301,-567,-4056,11456,2975,-222,716,4181 } }, { "Canon PowerShot G1 X", 0, 0, @@ -6378,7 +6378,7 @@ void CLASS adobe_coeff (const char *make, const char *model) { "Canon PowerShot S3 IS", 0, 0, /* DJC */ { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } }, { "Canon PowerShot SX110 IS", 0, 0, /* DJC */ - { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, + { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, { "Canon PowerShot SX220", 0, 0, /* DJC */ { 13898,-5076,-1447,-1405,10109,1297,-244,1860,3687 } }, { "Casio EX-S20", 0, 0, /* DJC */ @@ -6461,8 +6461,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } }, { "Fujifilm X100S", 0, 0, { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } }, - { "Fujifilm X100", 0, 0, /* RT - Colin Walker */ - { 10841,-3288,-807,-4652,12552,2344,-642,1355,7206 } }, + { "Fujifilm X100", 0, 0, + { 12161,-4457,-1069,-5034,12874,2400,-795,1724,6904 } }, { "Fujifilm X10", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, { "Fujifilm X20", 0, 0, @@ -6573,24 +6573,24 @@ void CLASS adobe_coeff (const char *make, const char *model) { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } }, { "Nikon D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */ { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } }, - { "Nikon D200", 0, 0xfbc, /* RT */ - { 8498,-2633,-295,-5423,12869,2860,-777,1077,8124 } }, + { "Nikon D200", 0, 0xfbc, + { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }, { "Nikon D2H", 0, 0, { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } }, { "Nikon D2X", 0, 0, { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } }, - { "Nikon D3000", 0, 0, /* RT */ - { 9211,-2521,-104,-6487,14280,2394,-754,1122,8033 } }, - { "Nikon D3100", 0, 0, /* RT */ - { 7729,-2212,-481,-5709,13148,2858,-1295,1908,8936 } }, + { "Nikon D3000", 0, 0, + { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, + { "Nikon D3100", 0, 0, + { 7911,-2167,-813,-5327,13150,2408,-1288,2483,7968 } }, { "Nikon D3200", 0, 0xfb9, { 7013,-1408,-635,-5268,12902,2640,-1470,2801,7379 } }, { "Nikon D300", 0, 0, { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } }, { "Nikon D3X", 0, 0, { 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } }, - { "Nikon D3S", 0, 0, /* RT */ - { 8792,-2663,-344,-5221,12764,2752,-1491,2165,8121 } }, + { "Nikon D3S", 0, 0, + { 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 } }, { "Nikon D3", 0, 0, { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, { "Nikon D40X", 0, 0, @@ -6603,7 +6603,7 @@ void CLASS adobe_coeff (const char *make, const char *model) { 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } }, { "Nikon D5100", 0, 0x3de6, { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, - { "Nikon D5200", 0, 0, // color matrix copied from D5200 DNG D65 matrix + { "Nikon D5200", 0, 0, { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, { "Nikon D50", 0, 0, { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, @@ -6611,12 +6611,12 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } }, { "Nikon D60", 0, 0, { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, - { "Nikon D7000", 0, 0, /* RT - Tanveer(tsk1979) */ - { 7530,-1942,-255,-4318,11390,3362,-926,1694,7649 } }, - { "Nikon D7100", 0, 0, // color matrix and WP copied from D7100 DNG D65 matrix + { "Nikon D7000", 0, 0, + { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, + { "Nikon D7100", 0, 0, { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, - { "Nikon D700", 0, 0, /* RT */ - { 8364,-2503,-352,-6307,14026,2492,-1134,1512,8156 } }, + { "Nikon D700", 0, 0, + { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, { "Nikon D70", 0, 0, { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, { "Nikon D800", 0, 0, @@ -6655,8 +6655,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, { "Nikon E8800", 0, 0, { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } }, - { "Nikon COOLPIX A", 0, 0x3e00, // color matrix and WP copied from "COOLPIX A" DNG D65 matrix - { 8198,-2239,-724,-4871,12389,2798,-1043,205,7181 } }, + { "Nikon COOLPIX A", 0, 0, + { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, { "Nikon COOLPIX P330", 0, 0, { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, { "Nikon COOLPIX P6000", 0, 0, @@ -6693,8 +6693,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, { "Olympus E-330", 0, 0, { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } }, - { "Olympus E-30", 0, 0xfbc, /* RT - Colin Walker */ - { 8510,-2355,-693,-4819,12520,2578,-1029,2067,7752 } }, + { "Olympus E-30", 0, 0xfbc, + { 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } }, { "Olympus E-3", 0, 0xf99, { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } }, { "Olympus E-400", 0, 0, @@ -6711,26 +6711,26 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } }, { "Olympus E-520", 0, 0xfd2, { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } }, - { "Olympus E-5", 0, 0xeec, /* RT - Colin Walker */ - { 9732,-2629,-999,-4899,12931,2173,-1243,2353,7457 } }, + { "Olympus E-5", 0, 0xeec, + { 11200,-3783,-1325,-4576,12593,2206,-695,1742,7504 } }, { "Olympus E-600", 0, 0xfaf, { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } }, { "Olympus E-620", 0, 0xfaf, { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } }, - { "Olympus E-P1", 0, 0xffd, /* RT - Colin Walker */ - { 8834,-2344,-804,-4691,12503,2448,-978,1919,7603 } }, - { "Olympus E-P2", 0, 0xffd, /* RT - Colin Walker */ - { 7758,-1619,-800,-5002,12886,2349,-985,1964,8305 } }, - { "Olympus E-P3", 0, 0, /* RT - Colin Walker */ - { 7041,-1794,-336,-3790,11192,2984,-1364,2625,6217 } }, - { "Olympus E-PL1s", 0, 0, /* RT - Colin Walker */ - { 9010,-2271,-838,-4792,12753,2263,-1059,2058,7589 } }, - { "Olympus E-PL1", 0, 0, /* RT - Colin Walker */ - { 9010,-2271,-838,-4792,12753,2263,-1059,2058,7589 } }, - { "Olympus E-PL2", 0, 0, /* RT - Colin Walker */ - { 11975,-3351,-1184,-4500,12639,2061,-1230,2353,7009 } }, - { "Olympus E-PL3", 0, 0, /* RT - Colin Walker */ - { 7041,-1794,-336,-3790,11192,2984,-1364,2625,6217 } }, + { "Olympus E-P1", 0, 0xffd, + { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } }, + { "Olympus E-P2", 0, 0xffd, + { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } }, + { "Olympus E-P3", 0, 0, + { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, + { "Olympus E-PL1s", 0, 0, + { 11409,-3872,-1393,-4572,12757,2003,-709,1810,7415 } }, + { "Olympus E-PL1", 0, 0, + { 11408,-4289,-1215,-4286,12385,2118,-387,1467,7787 } }, + { "Olympus E-PL2", 0, 0xcf3, + { 15030,-5552,-1806,-3987,12387,1767,-592,1670,7023 } }, + { "Olympus E-PL3", 0, 0, + { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, { "Olympus E-PL5", 0, 0xfcb, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "Olympus E-PM1", 0, 0, @@ -6755,8 +6755,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } }, { "Olympus XZ-10", 0, 0, { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, - { "Olympus XZ-1", 0, 0, /* RT - Colin Walker */ - { 8665,-2247,-762,-2424,10372,2382,-1011,2286,5189 } }, + { "Olympus XZ-1", 0, 0, + { 10901,-4095,-1074,-1141,9208,2293,-62,1417,5158 } }, { "Olympus XZ-2", 0, 0, { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, { "OmniVision ov5647", 0, 0, /* DJC */ @@ -6777,8 +6777,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } }, { "Pentax K20D", 0, 0, { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } }, - { "Pentax K200D", 0, 0, /* RT */ - { 10962,-4428,-542,-5486,13023,2748,-569,842,8390 } }, + { "Pentax K200D", 0, 0, + { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } }, { "Pentax K2000", 0, 0, { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } }, { "Pentax K-m", 0, 0, @@ -6837,8 +6837,6 @@ void CLASS adobe_coeff (const char *make, const char *model) { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } }, { "Leica D-LUX 5", 143, 0, { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } }, - { "Leica Camera AG M9 Digital Camera", 0, 0, /* RT */ - { 7181,-1706,-55,-3557,11409,2450,-621,2072,7533 } }, { "Panasonic DMC-LX7", 143, 0, { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } }, { "Leica D-LUX 6", 143, 0, @@ -6847,8 +6845,8 @@ void CLASS adobe_coeff (const char *make, const char *model) { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } }, { "Leica V-LUX 2", 143, 0xfff, { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } }, - { "Panasonic DMC-FZ150", 143, 0xfff, /* RT */ - { 10435,-3208,-72,-2293,10506,2067,-486,1725,4682 } }, + { "Panasonic DMC-FZ150", 143, 0xfff, + { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } }, { "Leica V-LUX 3", 143, 0xfff, { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } }, { "Panasonic DMC-FZ200", 143, 0xfff, @@ -6857,31 +6855,32 @@ void CLASS adobe_coeff (const char *make, const char *model) { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } }, { "Panasonic DMC-FX150", 15, 0xfff, { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } }, - { "Panasonic DMC-G10", 15, 0xf3c, /* RT - Colin Walker */ - { 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 } }, - { "Panasonic DMC-G1", 15, 0xf94, /* RT - Colin Walker*/ - { 7477,-1615,-651,-5016,12769,2506,-1380,2475,7240 } }, - { "Panasonic DMC-G2", 15, 0xf3c, /* RT - Colin Walker */ - { 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 } }, - { "Panasonic DMC-G3", 143, 0xfff, /* RT - Colin Walker */ - { 6051,-1406,-671,-4015,11505,2868,-1654,2667,6219 } }, - { "Panasonic DMC-G5", 143, 0xfff, /* RT */ - { 7122,-2092,-419,-4643,11769,3283,-1363,2413,5944 } }, - { "Panasonic DMC-GF1", 15, 0xf92, /* RT - Colin Walker */ - { 7863,-2080,-668,-4623,12331,2578,-1020,2066,7266 } }, - { "Panasonic DMC-GF2", 143, 0xfff, /* RT - Colin Walker */ - { 7694,-1791,-745,-4917,12818,2332,-1221,2322,7197 } }, - { "Panasonic DMC-GF3", 143, 0xfff, /* RT - Colin Walker */ - { 8074,-1846,-861,-5026,12999,2239,-1320,2375,7422 } }, + { "Panasonic DMC-G10", 0, 0, + { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } }, + { "Panasonic DMC-G1", 15, 0xf94, + { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } }, + { "Panasonic DMC-G2", 15, 0xf3c, + { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } }, + { "Panasonic DMC-G3", 143, 0xfff, + { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } }, + { "Panasonic DMC-G5", 143, 0xfff, + { 7798,-2562,-740,-3879,11584,2613,-1055,2248,5434 } }, + { "Panasonic DMC-G6", 143, 0xfff, /* DJC */ + { 6395,-2583,-40,-3677,9109,4569,-1502,2806,6431 } }, + { "Panasonic DMC-GF1", 15, 0xf92, + { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, + { "Panasonic DMC-GF2", 143, 0xfff, + { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, + { "Panasonic DMC-GF3", 143, 0xfff, + { 9051,-2468,-1204,-5212,13276,2121,-1197,2510,6890 } }, { "Panasonic DMC-GF5", 143, 0xfff, { 8228,-2945,-660,-3938,11792,2430,-1094,2278,5793 } }, { "Panasonic DMC-GF6", 143, 0, { 8130,-2801,-946,-3520,11289,2552,-1314,2511,5791 } }, - { "Panasonic DMC-GH1", 15, 0xf92, /* RT - Colin Walker */ - { 6360,-1557,-375,-4201,11504,3086,-1378,2518,5843 } }, - { "Panasonic DMC-GH2", 15, 0xf95, /* RT - Colin Walker */ -// { 6855,-1765,-456,-4223,11600,2996,-1450,2602,5761 } }, - { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } }, + { "Panasonic DMC-GH1", 15, 0xf92, + { 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } }, + { "Panasonic DMC-GH2", 15, 0xf95, + { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } }, { "Panasonic DMC-GH3", 144, 0, { 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 } }, { "Panasonic DMC-GX1", 143, 0, @@ -6958,28 +6957,30 @@ void CLASS adobe_coeff (const char *make, const char *model) { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } }, { "Sony DSLR-A5", 128, 0xfeb, { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, - { "Sony DSLR-A700", 126, 0, /* RT */ - { 6509,-1333,-137,-6171,13621,2824,-1490,2226,6952 } }, + { "Sony DSLR-A700", 126, 0, + { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }, { "Sony DSLR-A850", 128, 0, { 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } }, - { "Sony DSLR-A900", 128, 0, /* RT */ - { 5715,-1433,-410,-5603,12937,2989,-644,1247,8372 } }, - { "SONY NEX-3", 128, 0, /* RT - Colin Walker */ - { 5145,-741,-123,-4915,12310,2945,-794,1489,6906 } }, - { "Sony NEX-3N", 128, 0, - { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, - { "SONY NEX-5", 128, 0, /* RT - Colin Walker */ - { 5154,-716,-115,-5065,12506,2882,-988,1715,6800 } }, - { "Sony NEX-5N", 128, 0, /* RT - Colin Walker */ - { 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 } }, + { "Sony DSLR-A900", 128, 0, + { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }, + { "Sony NEX-5N", 128, 0, + { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony NEX-5R", 128, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, + { "Sony NEX-3N", 128, 0, + { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, + { "Sony NEX-3", 138, 0, /* DJC */ + { 6907,-1256,-645,-4940,12621,2320,-1710,2581,6230 } }, + { "Sony NEX-5", 116, 0, /* DJC */ + { 6807,-1350,-342,-4216,11649,2567,-1089,2001,6420 } }, + { "Sony NEX-3", 128, 0, /* Adobe */ + { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, + { "Sony NEX-5", 128, 0, /* Adobe */ + { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, { "Sony NEX-6", 128, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, { "Sony NEX-7", 128, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, - { "SONY NEX-C3", 128, 0, /* RT - Colin Walker */ - { 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 } }, { "Sony NEX", 128, 0, /* NEX-C3, NEX-F3 */ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A33", 128, 0, @@ -6996,10 +6997,10 @@ void CLASS adobe_coeff (const char *make, const char *model) { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A65", 128, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, - { "Sony SLT-A77", 128, 0, /* RT - Colin Walker */ - { 5126,-830,-261,-4788,12196,2934,-948,1602,7068 } }, + { "Sony SLT-A77", 128, 0, + { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, { "Sony SLT-A99", 128, 0, - { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } } + { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, }; double cam_xyz[4][3]; char name[130]; @@ -7017,6 +7018,24 @@ void CLASS adobe_coeff (const char *make, const char *model) } break; } + { /* Check for RawTherapee table overrides and extensions */ + int black_level, white_level; + short trans[12]; + if (dcraw_coeff_overrides(make, model, iso_speed, trans, &black_level, &white_level)) { + if (black_level > -1) { + black = (ushort)black_level; + } + if (white_level > -1) { + maximum = (ushort)white_level; + } + if (trans[0]) { + for (j=0; j < 12; j++) { + cam_xyz[0][j] = trans[j] / 10000.0; + } + cam_xyz_coeff (cam_xyz); + } + } + } } void CLASS simple_coeff (int index) diff --git a/rtengine/dcraw.h b/rtengine/dcraw.h index 2b437a445..9f6f17086 100644 --- a/rtengine/dcraw.h +++ b/rtengine/dcraw.h @@ -52,6 +52,9 @@ public: ,bright(1.),threshold(0.) ,half_size(0),four_color_rgb(0),document_mode(0),highlight(0) ,verbose(0) + ,RT_whitelevel_from_constant(0) + ,RT_blacklevel_from_constant(0) + ,RT_matrix_from_constant(0) ,use_auto_wb(0),use_camera_wb(0),use_camera_matrix(-1) ,output_color(1),output_bps(8),output_tiff(0),med_passes(0),no_auto_bright(0) ,getbithuff(this,ifp,zero_after_ff) @@ -100,6 +103,9 @@ protected: int output_color, output_bps, output_tiff, med_passes; int no_auto_bright; unsigned greybox[4] ; + int RT_matrix_from_constant; + int RT_blacklevel_from_constant; + int RT_whitelevel_from_constant; float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4]; @@ -374,6 +380,7 @@ float find_green (int bps, int bite, int off0, int off1); void identify(); void apply_profile (const char *input, const char *output); void jpeg_thumb() {} // not needed +bool dcraw_coeff_overrides(const char make[], const char model[], int iso_speed, short trans[12], int *black_level, int *white_level); }; diff --git a/rtengine/dcraw.patch b/rtengine/dcraw.patch index f3fb96e3c..0df5f24c3 100644 --- a/rtengine/dcraw.patch +++ b/rtengine/dcraw.patch @@ -1,5 +1,5 @@ ---- dcraw.c 2013-06-28 08:27:29 -0400 -+++ dcraw.cc 2013-06-29 20:49:02 -0400 +--- dcraw.c 2013-08-12 09:32:14.000000000 +0200 ++++ dcraw.cc 2013-10-09 21:07:43.000000000 +0200 @@ -1,3 +1,15 @@ +/*RT*/#include +/*RT*/#include @@ -532,7 +532,7 @@ - ushort (*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; - short (*lab)[TS][TS][3], (*lix)[3]; - char (*homo)[TS][TS], *buffer; -- + - if (verbose) fprintf (stderr,_("AHD interpolation...\n")); - - cielab (0,0); @@ -545,7 +545,7 @@ - - for (top=2; top < height-5; top += TS-6) - for (left=2; left < width-5; left += TS-6) { - +- -/* Interpolate green horizontally and vertically: */ - for (row=top; row < top+TS && row < height-2; row++) { - col = left + (FC(row,left) & 1); @@ -743,392 +743,32 @@ } table[] = { { "AgfaPhoto DC-833m", 0, 0, /* DJC */ { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } }, -@@ -6596,30 +6231,30 @@ - { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } }, - { "Canon EOS D60", 0, 0xfa0, - { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } }, -- { "Canon EOS 5D Mark III", 0, 0x3c80, -+ { "Canon EOS 5D Mark III", 0, 0x3a98, /* RT */ - { 6722,-635,-963,-4287,12460,2028,-908,2162,5668 } }, - { "Canon EOS 5D Mark II", 0, 0x3cf0, - { 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } }, -- { "Canon EOS 5D", 0, 0xe6c, -- { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } }, -- { "Canon EOS 6D", 0, 0x3c82, -+ { "Canon EOS 5D", 0, 0xe6c, /* RT */ -+ { 6319,-793,-614,-5809,13342,2738,-1132,1559,7971 } }, -+ { "Canon EOS 6D", 0, 0x3c82, - { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } }, -- { "Canon EOS 7D", 0, 0x3510, -- { 6844,-996,-856,-3876,11761,2396,-593,1772,6198 } }, -+ { "Canon EOS 7D", 0, 0x3510, /* RT - Colin Walker */ -+ { 5962,-171,-732,-4189,12307,2099,-911,1981,6304 } }, - { "Canon EOS 10D", 0, 0xfa0, - { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, - { "Canon EOS 20Da", 0, 0, - { 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } }, -- { "Canon EOS 20D", 0, 0xfff, -- { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } }, -+ { "Canon EOS 20D", 0, 0xfff, /* RT */ -+ { 7590,-1646,-673,-4697,12411,2568,-627,1118,7295 } }, - { "Canon EOS 30D", 0, 0, - { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } }, -- { "Canon EOS 40D", 0, 0x3f60, -- { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } }, -+ { "Canon EOS 40D", 0, 0x3f60, /* RT */ -+ { 6070,-531,-883,-5763,13647,2315,-1533,2582,6801 } }, - { "Canon EOS 50D", 0, 0x3d93, - { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } }, -- { "Canon EOS 60D", 0, 0x2ff7, -- { 6719,-994,-925,-4408,12426,2211,-887,2129,6051 } }, -+ { "Canon EOS 60D", 0, 0x2ff7, /* RT - Colin Walker */ -+ { 5678,-179,-718,-4389,12381,2243,-869,1819,6380 } }, - { "Canon EOS 100D", 0, 0x350f, - { 6602,-841,-939,-4472,12458,2247,-975,2039,6148 } }, - { "Canon EOS 300D", 0, 0xfa0, -@@ -6628,12 +6263,12 @@ - { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } }, - { "Canon EOS 400D", 0, 0xe8e, - { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } }, -- { "Canon EOS 450D", 0, 0x390d, -- { 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } }, -+ { "Canon EOS 450D", 0, 0x390d, /* RT */ -+ { 6246,-1272,-523,-5075,12357,3075,-1035,1825,7333 } }, - { "Canon EOS 500D", 0, 0x3479, - { 4763,712,-646,-6821,14399,2640,-1921,3276,6561 } }, -- { "Canon EOS 550D", 0, 0x3dd7, -- { 6941,-1164,-857,-3825,11597,2534,-416,1540,6039 } }, -+ { "Canon EOS 550D", 0, 0x3dd7, /* RT - Lebedev*/ -+ { 6519,-772,-703,-4994,12737,2519,-1387,2492,6175 } }, - { "Canon EOS 600D", 0, 0x3510, - { 6461,-907,-882,-4300,12184,2378,-819,1944,5931 } }, - { "Canon EOS 650D", 0, 0x354d, -@@ -6652,8 +6287,8 @@ - { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } }, - { "Canon EOS-1D Mark IV", 0, 0x3bb0, - { 6014,-220,-795,-4109,12014,2361,-561,1824,5787 } }, -- { "Canon EOS-1D Mark III", 0, 0x3bb0, -- { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } }, -+ { "Canon EOS-1D Mark III", 0, 0x3bb0, /* RT */ -+ { 7406,-1592,-646,-4856,12457,2698,-432,726,7921 } }, - { "Canon EOS-1D Mark II N", 0, 0xe80, - { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } }, - { "Canon EOS-1D Mark II", 0, 0xe80, -@@ -6672,12 +6307,12 @@ - { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } }, - { "Canon PowerShot A5", 0, 0, - { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } }, -- { "Canon PowerShot G10", 0, 0, -- { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } }, -+ { "Canon PowerShot G10", 0, 0, /* RT */ -+ { 12535,-5030,-796,-2711,10134,3006,-413,1605,5264 } }, - { "Canon PowerShot G11", 0, 0, - { 12177,-4817,-1069,-1612,9864,2049,-98,850,4471 } }, -- { "Canon PowerShot G12", 0, 0, -- { 13244,-5501,-1248,-1508,9858,1935,-270,1083,4366 } }, -+ { "Canon PowerShot G12", 0, 0, /* RT */ -+ { 12222,-4097,-1380,-2876,11016,2130,-888,1630,4434 } }, - { "Canon PowerShot G15", 0, 0, - { 7474,-2301,-567,-4056,11456,2975,-222,716,4181 } }, - { "Canon PowerShot G1 X", 0, 0, -@@ -6743,7 +6378,7 @@ - { "Canon PowerShot S3 IS", 0, 0, /* DJC */ - { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } }, - { "Canon PowerShot SX110 IS", 0, 0, /* DJC */ -- { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, -+ { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, - { "Canon PowerShot SX220", 0, 0, /* DJC */ - { 13898,-5076,-1447,-1405,10109,1297,-244,1860,3687 } }, - { "Casio EX-S20", 0, 0, /* DJC */ -@@ -6826,8 +6461,8 @@ - { 12085,-4727,-953,-3257,11489,2002,-511,2046,4592 } }, - { "Fujifilm X100S", 0, 0, - { 10592,-4262,-1008,-3514,11355,2465,-870,2025,6386 } }, -- { "Fujifilm X100", 0, 0, -- { 12161,-4457,-1069,-5034,12874,2400,-795,1724,6904 } }, -+ { "Fujifilm X100", 0, 0, /* RT - Colin Walker */ -+ { 10841,-3288,-807,-4652,12552,2344,-642,1355,7206 } }, - { "Fujifilm X10", 0, 0, - { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, - { "Fujifilm X20", 0, 0, -@@ -6938,24 +6573,24 @@ - { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } }, - { "Nikon D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */ - { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } }, -- { "Nikon D200", 0, 0xfbc, -- { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } }, -+ { "Nikon D200", 0, 0xfbc, /* RT */ -+ { 8498,-2633,-295,-5423,12869,2860,-777,1077,8124 } }, - { "Nikon D2H", 0, 0, - { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } }, - { "Nikon D2X", 0, 0, - { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } }, -- { "Nikon D3000", 0, 0, -- { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, -- { "Nikon D3100", 0, 0, -- { 7911,-2167,-813,-5327,13150,2408,-1288,2483,7968 } }, -+ { "Nikon D3000", 0, 0, /* RT */ -+ { 9211,-2521,-104,-6487,14280,2394,-754,1122,8033 } }, -+ { "Nikon D3100", 0, 0, /* RT */ -+ { 7729,-2212,-481,-5709,13148,2858,-1295,1908,8936 } }, - { "Nikon D3200", 0, 0xfb9, - { 7013,-1408,-635,-5268,12902,2640,-1470,2801,7379 } }, - { "Nikon D300", 0, 0, - { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } }, - { "Nikon D3X", 0, 0, - { 7171,-1986,-648,-8085,15555,2718,-2170,2512,7457 } }, -- { "Nikon D3S", 0, 0, -- { 8828,-2406,-694,-4874,12603,2541,-660,1509,7587 } }, -+ { "Nikon D3S", 0, 0, /* RT */ -+ { 8792,-2663,-344,-5221,12764,2752,-1491,2165,8121 } }, - { "Nikon D3", 0, 0, - { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, - { "Nikon D40X", 0, 0, -@@ -6968,7 +6603,7 @@ - { 7309,-1403,-519,-8474,16008,2622,-2433,2826,8064 } }, - { "Nikon D5100", 0, 0x3de6, - { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, -- { "Nikon D5200", 0, 0, -+ { "Nikon D5200", 0, 0, // color matrix copied from D5200 DNG D65 matrix - { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, - { "Nikon D50", 0, 0, - { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, -@@ -6976,12 +6611,12 @@ - { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } }, - { "Nikon D60", 0, 0, - { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } }, -- { "Nikon D7000", 0, 0, -- { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, -- { "Nikon D7100", 0, 0, -+ { "Nikon D7000", 0, 0, /* RT - Tanveer(tsk1979) */ -+ { 7530,-1942,-255,-4318,11390,3362,-926,1694,7649 } }, -+ { "Nikon D7100", 0, 0, // color matrix and WP copied from D7100 DNG D65 matrix - { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, -- { "Nikon D700", 0, 0, -- { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } }, -+ { "Nikon D700", 0, 0, /* RT */ -+ { 8364,-2503,-352,-6307,14026,2492,-1134,1512,8156 } }, - { "Nikon D70", 0, 0, - { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, - { "Nikon D800", 0, 0, -@@ -7020,8 +6655,8 @@ - { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, - { "Nikon E8800", 0, 0, - { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } }, -- { "Nikon COOLPIX A", 0, 0, -- { 8198,-2239,-724,-4871,12389,2798,-1043,2050,7181 } }, -+ { "Nikon COOLPIX A", 0, 0x3e00, // color matrix and WP copied from "COOLPIX A" DNG D65 matrix -+ { 8198,-2239,-724,-4871,12389,2798,-1043,205,7181 } }, - { "Nikon COOLPIX P330", 0, 0, - { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, - { "Nikon COOLPIX P6000", 0, 0, -@@ -7058,8 +6693,8 @@ - { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } }, - { "Olympus E-330", 0, 0, - { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } }, -- { "Olympus E-30", 0, 0xfbc, -- { 8144,-1861,-1111,-7763,15894,1929,-1865,2542,7607 } }, -+ { "Olympus E-30", 0, 0xfbc, /* RT - Colin Walker */ -+ { 8510,-2355,-693,-4819,12520,2578,-1029,2067,7752 } }, - { "Olympus E-3", 0, 0xf99, - { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } }, - { "Olympus E-400", 0, 0, -@@ -7076,26 +6711,26 @@ - { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } }, - { "Olympus E-520", 0, 0xfd2, - { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } }, -- { "Olympus E-5", 0, 0xeec, -- { 11200,-3783,-1325,-4576,12593,2206,-695,1742,7504 } }, -+ { "Olympus E-5", 0, 0xeec, /* RT - Colin Walker */ -+ { 9732,-2629,-999,-4899,12931,2173,-1243,2353,7457 } }, - { "Olympus E-600", 0, 0xfaf, - { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } }, - { "Olympus E-620", 0, 0xfaf, - { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } }, -- { "Olympus E-P1", 0, 0xffd, -- { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } }, -- { "Olympus E-P2", 0, 0xffd, -- { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } }, -- { "Olympus E-P3", 0, 0, -- { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, -- { "Olympus E-PL1s", 0, 0, -- { 11409,-3872,-1393,-4572,12757,2003,-709,1810,7415 } }, -- { "Olympus E-PL1", 0, 0, -- { 11408,-4289,-1215,-4286,12385,2118,-387,1467,7787 } }, -- { "Olympus E-PL2", 0, 0xcf3, -- { 15030,-5552,-1806,-3987,12387,1767,-592,1670,7023 } }, -- { "Olympus E-PL3", 0, 0, -- { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } }, -+ { "Olympus E-P1", 0, 0xffd, /* RT - Colin Walker */ -+ { 8834,-2344,-804,-4691,12503,2448,-978,1919,7603 } }, -+ { "Olympus E-P2", 0, 0xffd, /* RT - Colin Walker */ -+ { 7758,-1619,-800,-5002,12886,2349,-985,1964,8305 } }, -+ { "Olympus E-P3", 0, 0, /* RT - Colin Walker */ -+ { 7041,-1794,-336,-3790,11192,2984,-1364,2625,6217 } }, -+ { "Olympus E-PL1s", 0, 0, /* RT - Colin Walker */ -+ { 9010,-2271,-838,-4792,12753,2263,-1059,2058,7589 } }, -+ { "Olympus E-PL1", 0, 0, /* RT - Colin Walker */ -+ { 9010,-2271,-838,-4792,12753,2263,-1059,2058,7589 } }, -+ { "Olympus E-PL2", 0, 0, /* RT - Colin Walker */ -+ { 11975,-3351,-1184,-4500,12639,2061,-1230,2353,7009 } }, -+ { "Olympus E-PL3", 0, 0, /* RT - Colin Walker */ -+ { 7041,-1794,-336,-3790,11192,2984,-1364,2625,6217 } }, - { "Olympus E-PL5", 0, 0xfcb, - { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, - { "Olympus E-PM1", 0, 0, -@@ -7120,8 +6755,8 @@ - { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } }, - { "Olympus XZ-10", 0, 0, - { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, -- { "Olympus XZ-1", 0, 0, -- { 10901,-4095,-1074,-1141,9208,2293,-62,1417,5158 } }, -+ { "Olympus XZ-1", 0, 0, /* RT - Colin Walker */ -+ { 8665,-2247,-762,-2424,10372,2382,-1011,2286,5189 } }, - { "Olympus XZ-2", 0, 0, - { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } }, - { "OmniVision ov5647", 0, 0, /* DJC */ -@@ -7142,8 +6777,8 @@ - { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } }, - { "Pentax K20D", 0, 0, - { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } }, -- { "Pentax K200D", 0, 0, -- { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } }, -+ { "Pentax K200D", 0, 0, /* RT */ -+ { 10962,-4428,-542,-5486,13023,2748,-569,842,8390 } }, - { "Pentax K2000", 0, 0, - { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } }, - { "Pentax K-m", 0, 0, -@@ -7202,6 +6837,8 @@ - { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } }, - { "Leica D-LUX 5", 143, 0, - { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } }, -+ { "Leica Camera AG M9 Digital Camera", 0, 0, /* RT */ -+ { 7181,-1706,-55,-3557,11409,2450,-621,2072,7533 } }, - { "Panasonic DMC-LX7", 143, 0, - { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } }, - { "Leica D-LUX 6", 143, 0, -@@ -7210,8 +6847,8 @@ - { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } }, - { "Leica V-LUX 2", 143, 0xfff, - { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } }, -- { "Panasonic DMC-FZ150", 143, 0xfff, -- { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } }, -+ { "Panasonic DMC-FZ150", 143, 0xfff, /* RT */ -+ { 10435,-3208,-72,-2293,10506,2067,-486,1725,4682 } }, - { "Leica V-LUX 3", 143, 0xfff, - { 11904,-4541,-1189,-2355,10899,1662,-296,1586,4289 } }, - { "Panasonic DMC-FZ200", 143, 0xfff, -@@ -7220,32 +6857,30 @@ - { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } }, - { "Panasonic DMC-FX150", 15, 0xfff, - { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } }, -- { "Panasonic DMC-G10", 0, 0, -- { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } }, -- { "Panasonic DMC-G1", 15, 0xf94, -- { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } }, -- { "Panasonic DMC-G2", 15, 0xf3c, -- { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } }, -- { "Panasonic DMC-G3", 143, 0xfff, -- { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } }, -- { "Panasonic DMC-G5", 143, 0xfff, -- { 7798,-2562,-740,-3879,11584,2613,-1055,2248,5434 } }, -- { "Panasonic DMC-G6", 143, 0xfff, /* DJC */ -- { 6395,-2583,-40,-3677,9109,4569,-1502,2806,6431 } }, -- { "Panasonic DMC-GF1", 15, 0xf92, -- { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, -- { "Panasonic DMC-GF2", 143, 0xfff, -- { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } }, -- { "Panasonic DMC-GF3", 143, 0xfff, -- { 9051,-2468,-1204,-5212,13276,2121,-1197,2510,6890 } }, -+ { "Panasonic DMC-G10", 15, 0xf3c, /* RT - Colin Walker */ -+ { 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 } }, -+ { "Panasonic DMC-G1", 15, 0xf94, /* RT - Colin Walker*/ -+ { 7477,-1615,-651,-5016,12769,2506,-1380,2475,7240 } }, -+ { "Panasonic DMC-G2", 15, 0xf3c, /* RT - Colin Walker */ -+ { 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 } }, -+ { "Panasonic DMC-G3", 143, 0xfff, /* RT - Colin Walker */ -+ { 6051,-1406,-671,-4015,11505,2868,-1654,2667,6219 } }, -+ { "Panasonic DMC-G5", 143, 0xfff, /* RT */ -+ { 7122,-2092,-419,-4643,11769,3283,-1363,2413,5944 } }, -+ { "Panasonic DMC-GF1", 15, 0xf92, /* RT - Colin Walker */ -+ { 7863,-2080,-668,-4623,12331,2578,-1020,2066,7266 } }, -+ { "Panasonic DMC-GF2", 143, 0xfff, /* RT - Colin Walker */ -+ { 7694,-1791,-745,-4917,12818,2332,-1221,2322,7197 } }, -+ { "Panasonic DMC-GF3", 143, 0xfff, /* RT - Colin Walker */ -+ { 8074,-1846,-861,-5026,12999,2239,-1320,2375,7422 } }, - { "Panasonic DMC-GF5", 143, 0xfff, - { 8228,-2945,-660,-3938,11792,2430,-1094,2278,5793 } }, - { "Panasonic DMC-GF6", 143, 0, - { 8130,-2801,-946,-3520,11289,2552,-1314,2511,5791 } }, -- { "Panasonic DMC-GH1", 15, 0xf92, -- { 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } }, -- { "Panasonic DMC-GH2", 15, 0xf95, -- { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } }, -+ { "Panasonic DMC-GH1", 15, 0xf92, /* RT - Colin Walker */ -+ { 6360,-1557,-375,-4201,11504,3086,-1378,2518,5843 } }, - { "Panasonic DMC-GH3", 144, 0, - { 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 } }, - { "Panasonic DMC-GX1", 143, 0, -@@ -7322,30 +6957,28 @@ - { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } }, - { "Sony DSLR-A5", 128, 0xfeb, - { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, -- { "Sony DSLR-A700", 126, 0, -- { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }, -+ { "Sony DSLR-A700", 126, 0, /* RT */ -+ { 6509,-1333,-137,-6171,13621,2824,-1490,2226,6952 } }, - { "Sony DSLR-A850", 128, 0, - { 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } }, -- { "Sony DSLR-A900", 128, 0, -- { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }, -- { "Sony NEX-5N", 128, 0, -- { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, -- { "Sony NEX-5R", 128, 0, -- { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, -+ { "Sony DSLR-A900", 128, 0, /* RT */ -+ { 5715,-1433,-410,-5603,12937,2989,-644,1247,8372 } }, -+ { "SONY NEX-3", 128, 0, /* RT - Colin Walker */ -+ { 5145,-741,-123,-4915,12310,2945,-794,1489,6906 } }, - { "Sony NEX-3N", 128, 0, - { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, -- { "Sony NEX-3", 138, 0, /* DJC */ -- { 6907,-1256,-645,-4940,12621,2320,-1710,2581,6230 } }, -- { "Sony NEX-5", 116, 0, /* DJC */ -- { 6807,-1350,-342,-4216,11649,2567,-1089,2001,6420 } }, -- { "Sony NEX-3", 128, 0, /* Adobe */ -- { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, -- { "Sony NEX-5", 128, 0, /* Adobe */ -- { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, -+ { "SONY NEX-5", 128, 0, /* RT - Colin Walker */ -+ { 5154,-716,-115,-5065,12506,2882,-988,1715,6800 } }, -+ { "Sony NEX-5N", 128, 0, /* RT - Colin Walker */ -+ { 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 } }, -+ { "Sony NEX-5R", 128, 0, -+ { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, - { "Sony NEX-6", 128, 0, - { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, - { "Sony NEX-7", 128, 0, - { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, -+ { "SONY NEX-C3", 128, 0, /* RT - Colin Walker */ -+ { 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 } }, - { "Sony NEX", 128, 0, /* NEX-C3, NEX-F3 */ - { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, - { "Sony SLT-A33", 128, 0, -@@ -7362,10 +6995,10 @@ - { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, - { "Sony SLT-A65", 128, 0, - { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, -- { "Sony SLT-A77", 128, 0, -- { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, -+ { "Sony SLT-A77", 128, 0, /* RT - Colin Walker */ -+ { 5126,-830,-261,-4788,12196,2934,-948,1602,7068 } }, - { "Sony SLT-A99", 128, 0, -- { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, -+ { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } } - }; - double cam_xyz[4][3]; - char name[130]; -@@ -7682,13 +7315,20 @@ +@@ -7383,6 +7018,24 @@ + } + break; + } ++ { /* Check for RawTherapee table overrides and extensions */ ++ int black_level, white_level; ++ short trans[12]; ++ if (dcraw_coeff_overrides(make, model, iso_speed, trans, &black_level, &white_level)) { ++ if (black_level > -1) { ++ black = (ushort)black_level; ++ } ++ if (white_level > -1) { ++ maximum = (ushort)white_level; ++ } ++ if (trans[0]) { ++ for (j=0; j < 12; j++) { ++ cam_xyz[0][j] = trans[j] / 10000.0; ++ } ++ cam_xyz_coeff (cam_xyz); ++ } ++ } ++ } + } + + void CLASS simple_coeff (int index) +@@ -7682,13 +7335,20 @@ fread (head, 1, 32, ifp); fseek (ifp, 0, SEEK_END); flen = fsize = ftell(ifp); @@ -1151,7 +791,7 @@ parse_ciff (hlen, flen-hlen, 0); load_raw = &CLASS canon_load_raw; } else if (parse_tiff(0)) apply_tiff(); -@@ -7734,6 +7374,7 @@ +@@ -7734,6 +7394,7 @@ fseek (ifp, 100+28*(shot_select > 0), SEEK_SET); parse_tiff (data_offset = get4()); parse_tiff (thumb_offset+12); @@ -1159,7 +799,7 @@ apply_tiff(); } else if (!memcmp (head,"RIFF",4)) { fseek (ifp, 0, SEEK_SET); -@@ -7839,15 +7480,18 @@ +@@ -7839,15 +7500,18 @@ if (make[0] == 0) parse_smal (0, flen); if (make[0] == 0) { parse_jpeg(0); @@ -1187,7 +827,7 @@ } for (i=0; i < sizeof corp / sizeof *corp; i++) -@@ -7878,7 +7522,7 @@ +@@ -7878,7 +7542,7 @@ if (height == 3136 && width == 4864) /* Pentax K20D and Samsung GX20 */ { height = 3124; width = 4688; filters = 0x16161616; } if (width == 4352 && (!strcmp(model,"K-r") || !strcmp(model,"K-x"))) @@ -1196,7 +836,7 @@ if (width >= 4960 && !strncmp(model,"K-5",3)) { left_margin = 10; width = 4950; filters = 0x16161616; } if (width == 4736 && !strcmp(model,"K-7")) -@@ -8026,7 +7670,7 @@ +@@ -8026,7 +7690,7 @@ width -= 44; } else if (!strcmp(model,"D3200") || !strcmp(model,"D600") || @@ -1205,7 +845,7 @@ width -= 46; } else if (!strcmp(model,"D4")) { width -= 52; -@@ -8630,195 +8274,8 @@ +@@ -8630,195 +8294,8 @@ cmsCloseProfile (hInProfile); } #endif @@ -1403,7 +1043,7 @@ struct tiff_tag { ushort tag, type; -@@ -8841,584 +8298,12 @@ +@@ -8841,584 +8318,12 @@ unsigned gps[26]; char desc[512], make[64], model[64], soft[32], date[20], artist[64]; }; diff --git a/rtengine/init.cc b/rtengine/init.cc index c1fb991ca..e4555206f 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -19,6 +19,7 @@ #include "rtengine.h" #include "iccstore.h" #include "dcp.h" +#include "camconst.h" #include "improcfun.h" #include "improccoordinator.h" #include "dfmanager.h" @@ -33,7 +34,7 @@ const Settings* settings; MyMutex* lcmsMutex = NULL; -int init (const Settings* s, Glib::ustring baseDir) { +int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir) { settings = s; iccStore->init (s->iccDirectory, baseDir + "/iccprofiles"); @@ -41,6 +42,7 @@ int init (const Settings* s, Glib::ustring baseDir) { dcpStore->init (baseDir + "/dcpprofiles"); + CameraConstantsStore::initCameraConstants (baseDir, userSettingsDir); profileStore.init (); ProcParams::init (); Color::init(); diff --git a/rtengine/rawimage.cc b/rtengine/rawimage.cc index 0452b30fa..964bd54d9 100644 --- a/rtengine/rawimage.cc +++ b/rtengine/rawimage.cc @@ -7,6 +7,7 @@ #include "rawimage.h" #include "settings.h" #include "colortemp.h" +#include "camconst.h" #include "utils.h" #ifdef WIN32 #include @@ -26,6 +27,7 @@ RawImage::RawImage( const Glib::ustring name ) ,profile_data(NULL) ,allocation(NULL) { + memset(maximum_c4, 0, sizeof(maximum_c4)); } RawImage::~RawImage() @@ -48,11 +50,11 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac unsigned row, col, x, y, c, sum[8]; unsigned W = this->get_width(); unsigned H = this->get_height(); - int val, sat; + int val; double dsum[8], dmin, dmax; for (int c = 0; c < 4; c++){ - cblack_[c] = (float) this->get_cblack(c) + (float) this->get_black();// I don't modify black and cblack of Dcraw + cblack_[c] = (float) this->get_cblack(c); pre_mul_[c] = this->get_pre_mul(c); } if ( this->get_cam_mul(0) == -1 ) { @@ -68,7 +70,7 @@ void RawImage::get_colorsCoeff( float *pre_mul_, float *scale_mul_, float *cblac val = data[y][x]; } else val = data[y][3*x+c]; - if (val > this->get_white() - 25) + if (val > this->get_white(c) - 25) goto skip_block; if ((val -= cblack_[c]) < 0) val = 0; @@ -113,15 +115,10 @@ skip_block: ; dmax = pre_mul_[c]; } - sat = this->get_white() - this->get_calcblack(); - for (c = 0; c < 4; c++) + for (c = 0; c < 4; c++) { + int sat = this->get_white(c) - this->get_cblack(c); scale_mul_[c] = (pre_mul_[c] /= dmax) * 65535.0 / sat; - if (settings->verbose) { - fprintf(stderr,"Scaling with saturation %d, and\nmultipliers", sat); - for (c = 0; c < 4; c++) - fprintf(stderr, " %f", pre_mul[c]); - fputc('\n', stderr); - } + } } int RawImage::loadRaw (bool loadData, bool closeFile) @@ -204,16 +201,40 @@ int RawImage::loadRaw (bool loadData, bool closeFile) fread ( profile_data, 1, profile_length, ifp); } - // Setting the black and cblack - unsigned int minBlack = cblack[3]; - for (int c=0; c < 3; c++) - if (minBlack > cblack[c]) minBlack = cblack[c]; - for (int c=0; c < 4; c++) cblack[c] -= minBlack; + /* + Setting the black level, there are three sources: + dcraw single value 'black' or multi-value 'cblack', can be calculated or come + from a hard-coded table or come from a stored value in the raw file, and + finally there's 'black_c4' which are table values provided by RT camera constants. + Any of these may or may not be set. - black += minBlack; - for (int c=0; c < 4; c++) cblack[c] += black; - calcBlack=black; // safe for compatibility with darkframe substraction - black=0; // since black is already reflected in cblack now, set it to zero + We reduce these sources to one four channel black level, and do this by picking + the highest found. + */ + int black_c4[4] = { -1, -1, -1, -1 }; + + CameraConstantsStore* ccs = CameraConstantsStore::getInstance(); + CameraConst *cc = ccs->get(make, model); + if (cc) { + for (int i = 0; i < 4; i++) { + if (RT_blacklevel_from_constant) { + black_c4[i] = cc->get_BlackLevel(i, iso_speed); + } + // load 4 channel white level here, will be used if available + if (RT_whitelevel_from_constant) { + maximum_c4[i] = cc->get_WhiteLevel(i, iso_speed); + } + } + } + if (black_c4[0] == -1) { + // RT constants not set, bring in the DCRAW single channel black constant + for (int c=0; c < 4; c++) black_c4[c] = black; + } + for (int c=0; c < 4; c++) { + if (cblack[c] < black_c4[c]) { + cblack[c] = black_c4[c]; + } + } } if ( closeFile ) { @@ -279,3 +300,179 @@ RawImage::get_thumbSwap() const } } //namespace rtengine + +bool +DCraw::dcraw_coeff_overrides(const char make[], const char model[], const int iso_speed, short trans[12], int *black_level, int *white_level) +{ + static const struct { + const char *prefix; + int black_level, white_level; // set to -1 for no change + short trans[12]; // set first value to 0 for no change + } table[] = { + + { "Canon EOS 5D Mark III", 0, 0x3a98, /* RT */ + { 6722,-635,-963,-4287,12460,2028,-908,2162,5668 } }, + { "Canon EOS 5D", 0, 0xe6c, /* RT */ + { 6319,-793,-614,-5809,13342,2738,-1132,1559,7971 } }, + { "Canon EOS 6D", 0, 0x3c82, + { 7034,-804,-1014,-4420,12564,2058,-851,1994,5758 } }, + { "Canon EOS 7D", 0, 0x3510, /* RT - Colin Walker */ + { 5962,-171,-732,-4189,12307,2099,-911,1981,6304 } }, + { "Canon EOS 20D", 0, 0xfff, /* RT */ + { 7590,-1646,-673,-4697,12411,2568,-627,1118,7295 } }, + { "Canon EOS 40D", 0, 0x3f60, /* RT */ + { 6070,-531,-883,-5763,13647,2315,-1533,2582,6801 } }, + { "Canon EOS 60D", 0, 0x2ff7, /* RT - Colin Walker */ + { 5678,-179,-718,-4389,12381,2243,-869,1819,6380 } }, + { "Canon EOS 450D", 0, 0x390d, /* RT */ + { 6246,-1272,-523,-5075,12357,3075,-1035,1825,7333 } }, + { "Canon EOS 550D", 0, 0x3dd7, /* RT - Lebedev*/ + { 6519,-772,-703,-4994,12737,2519,-1387,2492,6175 } }, + { "Canon EOS-1D Mark III", 0, 0x3bb0, /* RT */ + { 7406,-1592,-646,-4856,12457,2698,-432,726,7921 } }, + { "Canon PowerShot G10", 0, 0, /* RT */ + { 12535,-5030,-796,-2711,10134,3006,-413,1605,5264 } }, + { "Canon PowerShot G12", 0, 0, /* RT */ + { 12222,-4097,-1380,-2876,11016,2130,-888,1630,4434 } }, + + + { "Fujifilm X100", 0, 0, /* RT - Colin Walker */ + { 10841,-3288,-807,-4652,12552,2344,-642,1355,7206 } }, + + + { "Nikon D200", 0, 0xfbc, /* RT */ + { 8498,-2633,-295,-5423,12869,2860,-777,1077,8124 } }, + { "Nikon D3000", 0, 0, /* RT */ + { 9211,-2521,-104,-6487,14280,2394,-754,1122,8033 } }, + { "Nikon D3100", 0, 0, /* RT */ + { 7729,-2212,-481,-5709,13148,2858,-1295,1908,8936 } }, + { "Nikon D3S", 0, 0, /* RT */ + { 8792,-2663,-344,-5221,12764,2752,-1491,2165,8121 } }, + { "Nikon D5200", 0, 0, // color matrix copied from D5200 DNG D65 matrix + { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, + { "Nikon D7000", 0, 0, /* RT - Tanveer(tsk1979) */ + { 7530,-1942,-255,-4318,11390,3362,-926,1694,7649 } }, + { "Nikon D7100", 0, 0, // color matrix and WP copied from D7100 DNG D65 matrix + { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, + { "Nikon D700", 0, 0, /* RT */ + { 8364,-2503,-352,-6307,14026,2492,-1134,1512,8156 } }, + { "Nikon COOLPIX A", 0, 0x3e00, // color matrix and WP copied from "COOLPIX A" DNG D65 matrix + { 8198,-2239,-724,-4871,12389,2798,-1043,205,7181 } }, + + + { "Olympus E-30", 0, 0xfbc, /* RT - Colin Walker */ + { 8510,-2355,-693,-4819,12520,2578,-1029,2067,7752 } }, + { "Olympus E-5", 0, 0xeec, /* RT - Colin Walker */ + { 9732,-2629,-999,-4899,12931,2173,-1243,2353,7457 } }, + { "Olympus E-P1", 0, 0xffd, /* RT - Colin Walker */ + { 8834,-2344,-804,-4691,12503,2448,-978,1919,7603 } }, + { "Olympus E-P2", 0, 0xffd, /* RT - Colin Walker */ + { 7758,-1619,-800,-5002,12886,2349,-985,1964,8305 } }, + { "Olympus E-P3", 0, 0, /* RT - Colin Walker */ + { 7041,-1794,-336,-3790,11192,2984,-1364,2625,6217 } }, + { "Olympus E-PL1s", 0, 0, /* RT - Colin Walker */ + { 9010,-2271,-838,-4792,12753,2263,-1059,2058,7589 } }, + { "Olympus E-PL1", 0, 0, /* RT - Colin Walker */ + { 9010,-2271,-838,-4792,12753,2263,-1059,2058,7589 } }, + { "Olympus E-PL2", 0, 0, /* RT - Colin Walker */ + { 11975,-3351,-1184,-4500,12639,2061,-1230,2353,7009 } }, + { "Olympus E-PL3", 0, 0, /* RT - Colin Walker */ + { 7041,-1794,-336,-3790,11192,2984,-1364,2625,6217 } }, + { "Olympus XZ-1", 0, 0, /* RT - Colin Walker */ + { 8665,-2247,-762,-2424,10372,2382,-1011,2286,5189 } }, + + + { "Panasonic DMC-FZ150", 143, 0xfff, /* RT */ + { 10435,-3208,-72,-2293,10506,2067,-486,1725,4682 } }, + { "Panasonic DMC-G10", 15, 0xf3c, /* RT - Colin Walker */ + { 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 } }, + { "Panasonic DMC-G1", 15, 0xf94, /* RT - Colin Walker*/ + { 7477,-1615,-651,-5016,12769,2506,-1380,2475,7240 } }, + { "Panasonic DMC-G2", 15, 0xf3c, /* RT - Colin Walker */ + { 8310,-1811,-960,-4941,12990,2151,-1378,2468,6860 } }, + { "Panasonic DMC-G3", 143, 0xfff, /* RT - Colin Walker */ + { 6051,-1406,-671,-4015,11505,2868,-1654,2667,6219 } }, + { "Panasonic DMC-G5", 143, 0xfff, /* RT */ + { 7122,-2092,-419,-4643,11769,3283,-1363,2413,5944 } }, + { "Panasonic DMC-GF1", 15, 0xf92, /* RT - Colin Walker */ + { 7863,-2080,-668,-4623,12331,2578,-1020,2066,7266 } }, + { "Panasonic DMC-GF2", 143, 0xfff, /* RT - Colin Walker */ + { 7694,-1791,-745,-4917,12818,2332,-1221,2322,7197 } }, + { "Panasonic DMC-GF3", 143, 0xfff, /* RT - Colin Walker */ + { 8074,-1846,-861,-5026,12999,2239,-1320,2375,7422 } }, + { "Panasonic DMC-GH1", 15, 0xf92, /* RT - Colin Walker */ + { 6360,-1557,-375,-4201,11504,3086,-1378,2518,5843 } }, + { "Panasonic DMC-GH2", 15, 0xf95, /* RT - Colin Walker */ +// { 6855,-1765,-456,-4223,11600,2996,-1450,2602,5761 } }, disabled + { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } }, // dcraw original + + + { "Pentax K200D", 0, 0, /* RT */ + { 10962,-4428,-542,-5486,13023,2748,-569,842,8390 } }, + + + { "Leica Camera AG M9 Digital Camera", 0, 0, /* RT */ + { 7181,-1706,-55,-3557,11409,2450,-621,2072,7533 } }, + + + { "Sony DSLR-A700", 126, 0, /* RT */ + { 6509,-1333,-137,-6171,13621,2824,-1490,2226,6952 } }, + { "Sony DSLR-A900", 128, 0, /* RT */ + { 5715,-1433,-410,-5603,12937,2989,-644,1247,8372 } }, + { "SONY NEX-3", 128, 0, /* RT - Colin Walker */ + { 5145,-741,-123,-4915,12310,2945,-794,1489,6906 } }, + { "SONY NEX-5", 128, 0, /* RT - Colin Walker */ + { 5154,-716,-115,-5065,12506,2882,-988,1715,6800 } }, + { "Sony NEX-5N", 128, 0, /* RT - Colin Walker */ + { 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 } }, + { "Sony NEX-5R", 128, 0, + { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, + { "SONY NEX-C3", 128, 0, /* RT - Colin Walker */ + { 5130,-1055,-269,-4473,11797,3050,-701,1310,7121 } }, + { "Sony SLT-A77", 128, 0, /* RT - Colin Walker */ + { 5126,-830,-261,-4788,12196,2934,-948,1602,7068 } }, + }; + + *black_level = -1; + *white_level = -1; + memset(trans, 0, sizeof(trans)); + + // indicate that DCRAW wants these from constants (rather than having loaded these from RAW file + // note: this is simplified so far, in some cases dcraw calls this when it has say the black level + // from file, but then we will not provide any black level in the tables. This case is mainly just + // to avoid loading table values if we have loaded a DNG conversion of a raw file (which already + // have constants stored in the file). + RT_whitelevel_from_constant = 1; + RT_blacklevel_from_constant = 1; + RT_matrix_from_constant = 1; + + { // test if we have any information in the camera constants store, if so we take that. + rtengine::CameraConstantsStore* ccs = rtengine::CameraConstantsStore::getInstance(); + rtengine::CameraConst *cc = ccs->get(make, model); + if (cc) { + *black_level = cc->get_BlackLevel(0, iso_speed); + *white_level = cc->get_WhiteLevel(0, iso_speed); + if (cc->has_dcrawMatrix()) { + const short *mx = cc->get_dcrawMatrix(); + for (int j = 0; j < 12; j++) { + trans[j] = mx[j]; + } + } + return true; + } + } + + char name[strlen(make) + strlen(model) + 32]; + sprintf(name, "%s %s", make, model); + for (int i = 0; i < sizeof table / sizeof(table[0]); i++) { + if (strcasecmp(name, table[i].prefix) == 0) { + *black_level = table[i].black_level; + *white_level = table[i].white_level; + for (int j = 0; j < 12; j++) { + trans[j] = table[i].trans[j]; + } + return true; + } + } + return false; +} diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index beaf84bff..10865d0d7 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -106,11 +106,11 @@ protected: int rotate_deg; // 0,90,180,270 degree of rotation: info taken by dcraw from exif char* profile_data; // Embedded ICC color profile unsigned short* allocation; // pointer to allocated memory - - unsigned calcBlack; // calculated black, like DCRAW before 9.15 + int maximum_c4[4]; public: + static void initCameraConstants(Glib::ustring baseDir); std::string get_filename() const { return filename;} int get_width() const { return width; } int get_height() const { return height; } @@ -118,10 +118,8 @@ public: bool isBayer() const { return filters!=0; } unsigned get_filters() const { return filters; } int get_colors() const { return colors;} - int get_black() const { return black;} // from DCRAW 9.15 =0, but reflected in cblack - int get_calcblack() const { return calcBlack;} // simulated like DCRAW before 9.15 int get_cblack(int i) const {return cblack[i];} - int get_white() const { return maximum;} + int get_white(int i) const { if (maximum_c4[0] > 0) return maximum_c4[i]; else return maximum;} unsigned short get_whiteSample( int r, int c ) const { return white[r][c];} double get_ISOspeed() const {return iso_speed;} diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 7cdc60467..c0d228c78 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1167,7 +1167,7 @@ void RawImageSource::HLRecovery_Global(HRecParams hrp ) */ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, RawImage *riDark, RawImage *riFlatFile ) { - unsigned short black=ri->get_calcblack(); + unsigned short black[4]={ri->get_cblack(0),ri->get_cblack(1),ri->get_cblack(2),ri->get_cblack(3)}; if (ri->isBayer()) { if (!rawData) @@ -1175,7 +1175,9 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw if (riDark && W == riDark->get_width() && H == riDark->get_height()) { for (int row = 0; row < H; row++) { for (int col = 0; col < W; col++) { - rawData[row][col] = max(src->data[row][col]+black - riDark->data[row][col], 0); + int c = FC(row, col); + int c4 = ( c == 1 && !(row&1) ) ? 3 : c; + rawData[row][col] = max(src->data[row][col]+black[c4] - riDark->data[row][col], 0); } } }else{ @@ -1211,15 +1213,21 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw //find center ave values by channel for (int m=0; m<2; m++) for (int n=0; n<2; n++) { - refcolor[m][n] = max(0.0f,cfablur[(2*(H>>2)+m)*W+2*(W>>2)+n] - black); + int row = 2*(H>>2)+m; + int col = 2*(W>>2)+n; + int c = FC(row, col); + int c4 = ( c == 1 && !(row&1) ) ? 3 : c; + refcolor[m][n] = max(0.0f,cfablur[row*W+col] - black[c4]); } for (int m=0; m<2; m++) for (int n=0; n<2; n++) { for (int row = 0; row+m < H; row+=2) for (int col = 0; col+n < W; col+=2) { - vignettecorr = ( refcolor[m][n]/max(1e-5f,cfablur[(row+m)*W+col+n]-black) ); - rawData[row+m][col+n] = (rawData[row+m][col+n]-black) * vignettecorr + black; + int c = FC(row, col); + int c4 = ( c == 1 && !(row&1) ) ? 3 : c; + vignettecorr = ( refcolor[m][n]/max(1e-5f,cfablur[(row+m)*W+col+n]-black[c4]) ); + rawData[row+m][col+n] = (rawData[row+m][col+n]-black[c4]) * vignettecorr + black[c4]; } } @@ -1238,9 +1246,11 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw for (int n=0; n<2; n++) { for (int row = 0; row+m < H; row+=2) for (int col = 0; col+n < W; col+=2) { - hlinecorr = (max(1e-5f,cfablur[(row+m)*W+col+n]-black)/max(1e-5f,cfablur1[(row+m)*W+col+n]-black) ); - vlinecorr = (max(1e-5f,cfablur[(row+m)*W+col+n]-black)/max(1e-5f,cfablur2[(row+m)*W+col+n]-black) ); - rawData[row+m][col+n] = ((rawData[row+m][col+n]-black) * hlinecorr * vlinecorr + black); + int c = FC(row, col); + int c4 = ( c == 1 && !(row&1) ) ? 3 : c; + hlinecorr = (max(1e-5f,cfablur[(row+m)*W+col+n]-black[c4])/max(1e-5f,cfablur1[(row+m)*W+col+n]-black[c4]) ); + vlinecorr = (max(1e-5f,cfablur[(row+m)*W+col+n]-black[c4])/max(1e-5f,cfablur2[(row+m)*W+col+n]-black[c4]) ); + rawData[row+m][col+n] = ((rawData[row+m][col+n]-black[c4]) * hlinecorr * vlinecorr + black[c4]); } } free (cfablur1); @@ -1261,9 +1271,11 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw if (riDark && W == riDark->get_width() && H == riDark->get_height()) { for (int row = 0; row < H; row++) { for (int col = 0; col < W; col++) { - rawData[row][3*col+0] = max(src->data[row][3*col+0]+black - riDark->data[row][3*col+0], 0); - rawData[row][3*col+1] = max(src->data[row][3*col+1]+black - riDark->data[row][3*col+1], 0); - rawData[row][3*col+2] = max(src->data[row][3*col+2]+black - riDark->data[row][3*col+2], 0); + int c = FC(row, col); + int c4 = ( c == 1 && !(row&1) ) ? 3 : c; + rawData[row][3*col+0] = max(src->data[row][3*col+0]+black[c4] - riDark->data[row][3*col+0], 0); + rawData[row][3*col+1] = max(src->data[row][3*col+1]+black[c4] - riDark->data[row][3*col+1], 0); + rawData[row][3*col+2] = max(src->data[row][3*col+2]+black[c4] - riDark->data[row][3*col+2], 0); } } } else { @@ -2234,8 +2246,8 @@ void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr) { // Histogram MUST be 256 in size; gamma is applied, blackpoint and gain also void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) { - histRedRaw.clear(); histGreenRaw.clear(); histBlueRaw.clear(); - float mult = 65535.0 / ri->get_white(); + histRedRaw.clear(); histGreenRaw.clear(); histBlueRaw.clear(); + float mult[4] = { 65535.0 / ri->get_white(0), 65535.0 / ri->get_white(1), 65535.0 / ri->get_white(2), 65535.0 / ri->get_white(3) }; #pragma omp parallel { @@ -2247,37 +2259,37 @@ void RawImageSource::getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LU tmphistBlueRaw.clear(); #pragma omp for nowait - for (int i=border; iisBayer()) { - for (int j=start; jdata[i][j]-(cblacksom[c4]/*+black_lev[c4]*/)))); - switch (c) { - case 0: tmphistRedRaw[idx>>8]++; break; - case 1: tmphistGreenRaw[idx>>8]++; break; - case 2: tmphistBlueRaw[idx>>8]++; break; - } - } - } else { - for (int j=start; jdata[i][3*j+c]-cblacksom[c]))); + if (ri->isBayer()) { + for (int j=start; jdata[i][j]-(cblacksom[c4]/*+black_lev[c4]*/)))); switch (c) { case 0: tmphistRedRaw[idx>>8]++; break; case 1: tmphistGreenRaw[idx>>8]++; break; case 2: tmphistBlueRaw[idx>>8]++; break; } - } + } + } else { + for (int j=start; jdata[i][3*j+c]-cblacksom[c]))); + + switch (c) { + case 0: tmphistRedRaw[idx>>8]++; break; + case 1: tmphistGreenRaw[idx>>8]++; break; + case 2: tmphistBlueRaw[idx>>8]++; break; + } + } + } } - } - } + } #pragma omp critical { for(int i=0;i<256;i++){ diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 6cd6be613..85cbafb39 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -348,9 +348,11 @@ namespace rtengine { /** - * Initializes the RT engine - * @param s is a struct of basic settings, baseDir of RT */ - int init (const Settings* s, Glib::ustring baseDir); + * @brief Initializes the RT engine + * @param s is a struct of basic settings + * @param baseDir base directory of RT's installation dir + * @param userSettingsDir RT's base directory in the user's settings dir */ + int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir); /** Cleanup the RT engine (static variables) */ void cleanup (); diff --git a/rtgui/options.cc b/rtgui/options.cc index 23e8ffc1c..ca9f352ec 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -1179,7 +1179,7 @@ void Options::load () { langMgr.load(localeTranslation, new MultiLangMgr(languageTranslation, new MultiLangMgr(defaultTranslation))); - rtengine::init (&options.rtSettings, argv0); + rtengine::init (&options.rtSettings, argv0, rtdir); } void Options::save () {