Logo Search packages:      
Sourcecode: ufraw version File versions

ufraw_routines.c

/*
   UFRaw - Unidentified Flying Raw
   Raw photo loader plugin for The GIMP
   by udi Fuchs,

   based on the gimp plug-in by Pawel T. Jochym jochym at ifj edu pl,
   
   based on the gimp plug-in by Dave Coffin
   http://www.cybercom.net/~dcoffin/

   UFRaw is licensed under the GNU General Public License.
   It uses "dcraw" code to do the actual raw decoding.
*/

#include <stdio.h>
#include <stdlib.h> /* needed for getenv() */
#include <string.h>
#include <ctype.h> /* needed for isspace() */
#include <errno.h>
#include <math.h>
#include <lcms.h>
#include <glib.h>
#include "ufraw.h"
#include "blackbody.h"

const cfg_data cfg_default = {
    sizeof(cfg_data), 3, "", "",
    load_default, load_preserve, load_preserve, ppm8_type, 85,
    camera_wb, 5, rgb_histogram, 
    { TRUE, TRUE, TRUE, TRUE, TRUE }, full_interpolation, 1,
    4750, 1.2, 0.0,
    FALSE /* Unclip highlights */,
    FALSE /* Overexposure indicator */,
    FALSE /* Underexposure indicator */,
    FALSE /* Overwrite exsisting files without asking */,
    FALSE /* Lossless compression */,
    /* Curves defaults */
    camera_curve, camera_curve+1,
    { { 0.45, 0.0, 1.0, 0.0, 0.0, 0.0, 0.1,
        "Gamma curve", "", 0, 0 , { { 0, 0 } } },
      { 0.45, 0.0, 1.0, 0.0, 0.0, 0.0, 0.1,
        "Log curve", "", 0, 0 , { { 0, 0 } } },
      { 0.45, 0.0, 1.0, 0.0, 0.0, 0.0, 0.1,
        "Linear curve", "", 0x10000, 2 , { {0, 0}, {0xFFFF, 0xFF} } },
      { 0.45, 0.0, 1.0, 0.0, 0.0, 0.0, 0.1,
        "Camera curve", "", 0, 0 , { { 0, 0 } } } },
    "",
    /* Profiles defaults */
    { 0, 0 } , { 1, 1 },
    { { { "sRGB", "", "", 1.0, camera_curve } },
      { { "sRGB", "", "", 0.0, 0 } } },
    0, /* intent */
    ""
};

const wb_data wb_preset[] = { { "-------------", 0, 0},
    { "Camera WB", 0, 0},
    { "Auto WB", 0, 0},
    { "Incandescent", 1.34375/2.043, 2.816406/1.625 }, /* 3000K */
    { "Fluorescent", 1.964844/2.043, 2.476563/1.625 }, /* 4200K */
    { "Direct sunlight", 2.0625/2.043, 1.597656/1.625 }, /* 5200K*/
    { "Flash", 2.441406/2.043, 1.5/1.625 }, /* 5400K */
    { "Cloudy", 2.257813/2.043, 1.457031/1.625 }, /* 6000K */
    { "Shade", 2.613281/2.043, 1.277344/1.625 } /* 8000K */ };
const int wb_preset_count = sizeof(wb_preset) / sizeof(wb_data);

const char raw_ext[]= "bay,bmq,cr2,crw,cs1,dc2,dcr,fff,hdr,k25,kdc,mrw,nef,"
        "orf,pef,raf,raw,rdc,srf,x3f,jpg,tif";

const char *file_type[] = { ".ppm", ".ppm", ".tif", ".tif", ".jpg" };

void set_curve(guint16 *curve, int maxValue, int curveType, curve_data *cp)
{
    int i, ci, norm;
    float x, val, lam;

    norm = 0x10000/(1-cp->black);
    if (curveType==gamma_curve || curveType==log_curve) {
        lam = pow(cp->gamma, -3) - 1;
        if (lam==0) lam = 0.01;
        for (i=0; i<maxValue; i++) {
            x = (float)i/maxValue;
            curve[i] = MAX(( curveType==log_curve ?
                    log(1+lam*x)/log(1+lam) : pow(x, cp->gamma) ) *
                    (1+cp->shadow*exp(-x/cp->depth)) /
                    (1+cp->shadow*exp(-1/cp->depth)) - cp->black, 0) * norm;
        }
    } else {
        for (i=0, ci=0; i<maxValue; i++) {
            x = (float)i/maxValue;
            if ( ci+1 < cp->curveSize &&
                    x*cp->indexSize >= cp->curve[ci+1].index) ci++;
            val = ( cp->curve[ci].value +
                    (float)(cp->curve[ci+1].value - cp->curve[ci].value) *
                    (x*cp->indexSize - cp->curve[ci].index) /
                    (cp->curve[ci+1].index - cp->curve[ci].index) )/MAXOUT;
            /* It seems that (int)f is not always the same as (int)floor(f) */
            curve[i] = MIN( floor( MAX(
                    ( cp->contrast==0 ? val :
                        log(1+cp->contrast*val) / log(1+cp->contrast) ) *
                    ( 1 + cp->shadow*exp(-val/cp->depth) ) /
                    ( 1 + cp->shadow*exp(-1/cp->depth) ) - cp->black, 0)
                        * norm), 0xFFFF);
        }
    }
}

int curve_load(curve_data *cp, char *filename)
{
    FILE *in;
    unsigned i;

    if ( (in=fopen(filename, "r"))==NULL ) {
        ufraw_message(UFRAW_ERROR, "Error loading curve file %s: %s",
                filename, g_strerror(errno));
        return UFRAW_ERROR;
    }
    for (i=0; !feof(in) && i<257; i++) {
        if (fscanf(in, "%hd %hhd\n",
                &cp->curve[i].index, &cp->curve[i].value)!=2) {
            ufraw_message(UFRAW_ERROR, "Invalid curve file structure - %s",
                                        filename);
            fclose(in);
            return UFRAW_ERROR;
        }
    }
    fclose(in);
    cp->indexSize = cp->curve[i-1].index+1;
    cp->curveSize = i;
    g_strlcpy(cp->file, filename, max_path);
    for (i=strlen(filename); i>0 && filename[i]!='/' && filename[i]!='\\'; i--);
    filename += i+1;
    for (i=0; i<strlen(filename) && filename[i]!='.' && i<max_name-1; i++)
        cp->name[i] = filename[i];
    cp->name[i] = '\0';
    return UFRAW_SUCCESS;
}

void curve_convert(curve_data *cp, int curveSize, guint8 *curve)
{
    int index, ci, i;
    index = 0;
    ci = 0;
    cp->indexSize = curveSize;
    cp->curve[ci].index = 0;
    cp->curve[ci].value = curve[0];
    ci++;
    for (i=0; i<curveSize && ci<256; i++) {
        /* if the curve "steps up" record that point */
        if (curve[i]>curve[index]) {
            /* if current point and previous point are on the same
             * line, remove previous point. Strait line condition:
             * ([ci-1].v-[ci-2].v)/([ci-1].i-[ci-2].i) ==
             * ([ci].v-[ci-2].v)/([ci].i-[ci-2].i) */
            if (ci>1 &&
                (cp->curve[ci-1].value - cp->curve[ci-2].value)*
                (i - cp->curve[ci-2].index) ==
                (curve[i] - cp->curve[ci-2].value)*
                (cp->curve[ci-1].index - cp->curve[ci-2].index))
                    ci--;
            cp->curve[ci].index = i;
            cp->curve[ci].value = curve[i];
            ci++;
            index = i;
        }
    }
    cp->curveSize = ci;
    /* last point is only needed internaly */
    cp->curve[ci].index = curveSize-1;
    cp->curve[ci].value = curve[curveSize-1];
}

developer_data *developer_init()
{
    int i;
    developer_data *d = g_new(developer_data,1);
    d->gamma = -1;
    d->saturation = -1;
    for (i=0; i<profile_types; i++) {
        d->profile[i] = NULL;
        strcpy(d->file[i],"no such file");
    }
    d->intent = -1;
    d->updateTransform = TRUE;
    d->colorTransform = NULL;
    cmsSetErrorHandler((void *)ufraw_message_handler);
    return d;
}

void developer_destroy(developer_data *d)
{
    int i;
    if (d==NULL) return;
    for (i=0; i<profile_types; i++)
        if (d->profile[i]!=NULL) cmsCloseProfile(d->profile[i]);
    if (d->colorTransform!=NULL)
        cmsDeleteTransform(d->colorTransform);
    g_free(d);
}

void developer_profile(developer_data *d, int type, profile_data *p)
{
    if (strcmp(p->file, d->file[type])) {
        g_strlcpy(d->file[type], p->file, max_path);
        if (d->profile[type]!=NULL) cmsCloseProfile(d->profile[type]);
        if (!strcmp(d->file[type],""))
            d->profile[type] = cmsCreate_sRGBProfile();
        else d->profile[type] = cmsOpenProfileFromFile(d->file[type], "r");
        if (d->profile[type]!=NULL)
            g_strlcpy(p->productName, cmsTakeProductName(d->profile[type]),
                        max_name);
        else
            strcpy(p->productName, "");
    }
    if (p->curve==-1) {
        if ( !strncmp("Nikon D70 for NEF", p->productName, 17) ||
             !strncmp("Nikon D100 for NEF", p->productName, 18) ||
             !strncmp("Nikon D1 for NEF", p->productName, 16) ) {
            p->gamma = 0.45;
            p->curve = linear_curve;
        } else {
            p->curve = cfg_default.profile[type][0].curve;
        }
    }
    d->updateTransform = TRUE;
}

void developer_prepare(developer_data *d, int rgbMax, float exposure,
        int unclip, float temperature, float green, float pre_mul[4],
        profile_data *in, profile_data *out, int intent,
        float saturation, int curveType, curve_data *curve)
{
    int c, i;

    d->rgbMax = rgbMax;
    i = temperature/10-200;
    for (c=0; c<4; c++)
        d->rgbWB[c] = bbWB[i][1]/bbWB[i][c]*pre_mul[c]*
                        (c==1||c==3?green:1.0)*0x10000;
    d->exposure = exposure;
    if (unclip) d->max = 0xFFFF;
    else d->max = MIN(exposure*0x10000, 0xFFFF);
    for (c=0; c<4; c++) d->rgbWB[c] = d->rgbWB[c] * d->exposure;
    if (in->gamma!=d->gamma) {
        d->gamma = in->gamma;
        for (i=0; i<0x10000; i++) d->gammaCurve[i] =
            MIN(pow((float)i/0x10000, d->gamma)*0x10000, 0xFFFF);
    }
    developer_profile(d, 0, in);
    developer_profile(d, 1, out);
    if (intent!=d->intent) {
        d->intent = intent;
        d->updateTransform = TRUE;
    }
    if (d->updateTransform) {
        if (d->colorTransform!=NULL)
            cmsDeleteTransform(d->colorTransform);
        if (!strcmp(d->file[0],"") && !strcmp(d->file[1],""))
            d->colorTransform = NULL;
        else
            d->colorTransform = cmsCreateTransform(
                    d->profile[0], TYPE_RGB_16,
                    d->profile[1], TYPE_RGB_16, d->intent, 0);
    }
    if (saturation!=d->saturation) {
        d->saturation = saturation;
        for (i=0; i<0x10000; i++) d->saturationCurve[i] = MAX(MIN(
            pow((float)i/0x10000, saturation)*0x10000,0xFFFF),1);
    }
    set_curve(d->toneCurve, 0x10000, curveType, curve);
}

inline void develope(void *po, guint16 pix[4], developer_data *d, int mode,
    guint16 *buf, int count)
{
    guint8 *p8 = po;
    guint16 *p16 = po, *p, maxc, midc, minc, c;
    unsigned sat, hue;
    int i;

    for (i=0; i<count; i++)
        for (c=0; c<3; c++) buf[i*3+c] = d->gammaCurve[
            MIN((guint64)d->rgbWB[c]*pix[i*4+c]/d->rgbMax,(guint64)d->max)];
    if (d->colorTransform!=NULL)
        cmsDoTransform(d->colorTransform, buf, buf, count);
    if (d->saturation!=1) for (i=0, p=buf; i<count; i++, p+=3) {
        if (p[0] > p[1] && p[0] > p[2]) {
            maxc = 0;
            if (p[1] > p[2]) { midc = 1; minc = 2; }
            else { midc = 2; minc = 1; }
        } else if (p[1] > p[2]) {
            maxc = 1;
            if (p[0] > p[2]) { midc = 0; minc = 2; }
            else { midc = 2; minc = 0; }
        } else {
            maxc = 2;
            if (p[0] > p[1]) { midc = 0; minc = 1; }
            else { midc = 1; minc = 0; }
        }
        if (p[maxc]!=p[minc]) {
            /* oldSaturation = (max-min) / max */
            /* newSaturation = 1 - pow(1 - oldSaturation, saturate) */
            sat = 0x10000 - (unsigned)d->saturationCurve[p[minc]]*0x10000 /
                    d->saturationCurve[p[maxc]];
            hue = (unsigned)(p[midc]-p[minc])*0x10000/(p[maxc]-p[minc]);
            p[minc] = p[maxc]*(0x10000-sat)/0x10000;
            p[midc] = p[maxc]*(0x10000-sat+sat*hue/0x10000)/0x10000; 
            /* It is also possible to define oldSaturation = max-min */
        }
    }
    if (mode==16) for (i=0; i<3*count; i++) p16[i] = d->toneCurve[buf[i]];
    else for (i=0; i<3*count; i++) p8[i] = d->toneCurve[buf[i]] >> 8;
}

void pixbuf_reverse(int x, int y, guchar *pixbuf, int width, int height,
        int rowstride)
{
    int c;
    
    if (x>0 && y>0 && x<width && y<height)
        for (c=0; c<3; c++)
            pixbuf[y*rowstride+3*x+c] =
                (pixbuf[y*rowstride+3*x+c] + 128) % 256;
}

void RGB_to_temperature(float *rgb, float *temperature, float *green)
{
    int l, r, m;
    double rbRatio;
    
    rbRatio = rgb[0]/rgb[2];

    for (l=0, r=sizeof(bbWB)/(sizeof(float)*3), m=(l+r)/2; r-l>1 ; m=(l+r)/2) {
        if (bbWB[m][0]/bbWB[m][2] > rbRatio) l = m;
        else r = m;
    }
    *temperature = m*10+2000;
    *green = (bbWB[m][1]/bbWB[m][0])/(rgb[1]/rgb[0]);
    ufraw_message(UFRAW_VERBOSE,
            "RGB_to_temperature: Temperature=%d K, green component=%f\n",
            (int)*temperature, *green);
}

void cfg_parse_start(GMarkupParseContext *context, const gchar *element,
    const gchar **names, const gchar **values, gpointer user, GError **error)
{
    cfg_data *c = user;
    int int_value;
    GQuark ufrawQuark = g_quark_from_static_string("UFRaw");

    context = context;
    while (*names!=NULL) {
        sscanf(*values, "%d", &int_value);
        if (!strcmp(element, "UFRaw") && !strcmp(*names, "Version")) {
            if (int_value!=c->version) 
                g_set_error(error, ufrawQuark, UFRAW_RC_VERSION,
                    "UFRaw version in .ufrawrc does not "
                    "match current version");
        }
        if (!strcmp(*names,"Current") && int_value!=0) {
            if (!strcmp("GammaCurve", element))
                c->curveIndex = gamma_curve;
            if (!strcmp("LogCurve", element))
                c->curveIndex = log_curve;
            if (!strcmp("LinearCurve", element))
                c->curveIndex = linear_curve;
            if (!strcmp("CameraCurve", element))
                c->curveIndex = camera_curve;
            if (!strcmp("Curve", element))
                c->curveIndex = c->curveCount;
            if (!strcmp("sRGBInputProfile", element))
                c->profileIndex[0] = 0;
            if (!strcmp("sRGBOutputProfile", element))
                c->profileIndex[1] = 0;
            if (!strcmp("InputProfile", element))
                c->profileIndex[0] = c->profileCount[0];
            if (!strcmp("OutputProfile", element))
                c->profileIndex[1] = c->profileCount[1];
        }
        names++;
        values++;
    }
    /* The default curve/profile count is always larger than 0,
     * threfore we can treat 0 as a negative number */
    if (!strcmp("GammaCurve", element)) c->curveCount = - gamma_curve;
    if (!strcmp("LogCurve", element)) c->curveCount = - log_curve;
    if (!strcmp("LinearCurve", element)) c->curveCount = - linear_curve;
    if (!strcmp("CameraCurve", element)) c->curveCount = - camera_curve;
    if (!strcmp("sRGBInputProfile", element)) c->profileCount[0] = 0;
    if (!strcmp("sRGBOutputProfile", element)) c->profileCount[1] = 0;
}

void cfg_parse_end(GMarkupParseContext *context, const gchar *element,
         gpointer user, GError **error)
{
    cfg_data *c = user;
    context = context;
    error = error;
    if (!strcmp("GammaCurve", element)) c->curveCount = camera_curve+1;
    if (!strcmp("LogCurve", element)) c->curveCount = camera_curve+1;
    if (!strcmp("LinearCurve", element)) c->curveCount = camera_curve+1;
    if (!strcmp("CameraCurve", element)) c->curveCount = camera_curve+1;
    if (c->curveCount<=0 && !strcmp("Curve", element))
        c->curveCount = - c->curveCount + 1;
    if (!strcmp("sRGBInputProfile", element)) c->profileCount[0] = 1;
    if (!strcmp("sRGBOutputProfile", element)) c->profileCount[1] = 1;
    if (c->profileCount[0]<=0 && !strcmp("InputProfile", element))
        c->profileCount[0] = - c->profileCount[0] + 1;
    if (c->profileCount[1]<=0 && !strcmp("OutputProfile", element))
        c->profileCount[1] = - c->profileCount[1] + 1;
}

void cfg_parse_text(GMarkupParseContext *context, const gchar *text, gsize len,
        gpointer user, GError **error)
{
    cfg_data *c = user;
    const gchar *element = g_markup_parse_context_get_element(context);
    char temp[max_path];
    int i;
    error = error;
    for(; len>0 && isspace(*text); len--, text++);
    for(; len>0 && isspace(text[len-1]); len--);
    if (len==0) return;
    if (len>max_path-1) len=max_path-1;
    strncpy(temp, text, len);
    temp[len] = '\0';
    if (c->curveCount<=0) {
        i = - c->curveCount;
        if (!strcmp("File", element))
            g_strlcpy(c->curve[i].file, temp, max_path);
        if (!strcmp("Gamma", element))
            sscanf(temp, "%f", &c->curve[i].gamma);
        if (!strcmp("Contrast", element))
            sscanf(temp, "%f", &c->curve[i].contrast);
        if (!strcmp("Saturation", element))
            sscanf(temp, "%f", &c->curve[i].saturation);
        if (!strcmp("Brightness", element))
            sscanf(temp, "%f", &c->curve[i].brightness);
        if (!strcmp("BlackPoint", element))
            sscanf(temp, "%f", &c->curve[i].black);
        if (!strcmp("Shadow", element))
            sscanf(temp, "%f", &c->curve[i].shadow);
        if (!strcmp("ShadowDepth", element))
            sscanf(temp, "%f", &c->curve[i].depth);
        return;
    }
    if (c->profileCount[0]<=0) {
        i = - c->profileCount[0];
        if (!strcmp("File", element))
            g_strlcpy(c->profile[0][i].file, temp, max_path);
        if (!strcmp("ProductName", element))
            g_strlcpy(c->profile[0][i].productName, temp, max_path);
        if (!strcmp("Gamma", element))
            sscanf(temp, "%f", &c->profile[0][i].gamma);
        if (!strcmp("Curve", element))
            sscanf(temp, "%d", &c->profile[0][i].curve);
        return;
    }
    if (c->profileCount[1]<=0) {
        i = - c->profileCount[1];
        if (!strcmp("File", element))
            g_strlcpy(c->profile[1][i].file, temp, max_path);
        if (!strcmp("ProductName", element))
            g_strlcpy(c->profile[0][i].productName, temp, max_path);
        return;
    }
    if (!strcmp("Curve", element)) {
        c->curveCount = - c->curveCount;
        i = - c->curveCount;
        c->curve[i] = cfg_default.curve[0];
        g_strlcpy(c->curve[i].name, temp, max_name);
    }
    if (!strcmp("InputProfile", element)) {
        c->profileCount[0] = - c->profileCount[0];
        i = - c->profileCount[0];
        c->profile[0][i] = cfg_default.profile[0][0];
        g_strlcpy(c->profile[0][i].name, temp, max_name);
    }
    if (!strcmp("OutputProfile", element)) {
        c->profileCount[1] = - c->profileCount[1];
        i = - c->profileCount[1];
        c->profile[1][i] = cfg_default.profile[1][0];
        g_strlcpy(c->profile[1][i].name, temp, max_name);
    }
    if (!strcmp("InputFilename", element))
            g_strlcpy(c->inputFilename, temp, max_path);
    if (!strcmp("OutputFilename", element))
            g_strlcpy(c->outputFilename, temp, max_path);
    if (!strcmp("LoadWB", element)) sscanf(temp, "%d", &c->wbLoad);
    if (!strcmp("LoadCurve", element)) sscanf(temp, "%d", &c->curveLoad);
    if (!strcmp("LoadExposure", element)) sscanf(temp, "%d", &c->exposureLoad);
    if (!strcmp("Interpolation", element))
            sscanf(temp, "%d", &c->interpolation);
    if (!strcmp("RawExpander", element))
            sscanf(temp, "%d", &c->expander[raw_expander]);
    if (!strcmp("WBExpander", element))
            sscanf(temp, "%d", &c->expander[wb_expander]);
    if (!strcmp("ColorExpander", element))
            sscanf(temp, "%d", &c->expander[color_expander]);
    if (!strcmp("CurveExpander", element))
            sscanf(temp, "%d", &c->expander[curve_expander]);
    if (!strcmp("LiveExpander", element))
            sscanf(temp, "%d", &c->expander[live_expander]);
    if (!strcmp("Histogram", element)) sscanf(temp, "%d", &c->histogram);
    if (!strcmp("SpotSize", element)) sscanf(temp, "%d", &c->spotSize);
    if (!strcmp("OverExposure", element)) sscanf(temp, "%d", &c->overExp);
    if (!strcmp("UnderExposure", element)) sscanf(temp, "%d", &c->underExp);
    if (!strcmp("WB", element)) sscanf(temp, "%d", &c->wb);
    if (!strcmp("Temperature", element)) sscanf(temp, "%f", &c->temperature);
    if (!strcmp("Green", element)) sscanf(temp, "%f", &c->green);
    if (!strcmp("Exposure", element)) sscanf(temp, "%f", &c->exposure);
    if (!strcmp("Unclip", element)) sscanf(temp, "%d", &c->unclip);
    if (!strcmp("CurvePath", element)) g_strlcpy(c->curvePath, temp, max_path);
    if (!strcmp("RGBProfileGamma", element))
            sscanf(temp, "%f", &c->profile[0][0].gamma);
    if (!strcmp("Intent", element)) sscanf(temp, "%d", &c->intent);
    if (!strcmp("ProfilePath", element))
            g_strlcpy(c->profilePath, temp, max_path);
    if (!strcmp("Shrink", element)) sscanf(temp, "%d", &c->shrink);
    if (!strcmp("OutputType", element)) sscanf(temp, "%d", &c->type);
    if (!strcmp("Compression", element)) sscanf(temp, "%d", &c->compression);
    if (!strcmp("Overwrite", element)) sscanf(temp, "%d", &c->overwrite);
    if (!strcmp("LosslessCompression", element))
            sscanf(temp, "%d", &c->losslessCompress);
}

const char *get_home_dir()
{
    const char *hd = g_get_home_dir();
    if (hd==NULL)
#ifdef WIN32
        hd = "C:\\";
#else
        hd = "/";
#endif
    return hd;
}

int load_configuration(cfg_data *c)
{
    char *cfgFilename, line[max_path];
    const char *hd;
    FILE *in;
    GMarkupParser parser={&cfg_parse_start, &cfg_parse_end,
            &cfg_parse_text, NULL, NULL};
    GMarkupParseContext *context;
    GError *err = NULL;
    GQuark ufrawQuark = g_quark_from_static_string("UFRaw");
    int i, j;

    *c = cfg_default;
    hd = get_home_dir();
    cfgFilename = g_build_filename(hd, ".ufrawrc", NULL);
    if ( (in=fopen(cfgFilename, "r"))!=NULL ) {
        context = g_markup_parse_context_new(&parser, 0, c, NULL);
        line[max_path-1] = '\0';
        fgets(line, max_path-1, in);
        while (!feof(in)) {
            if (!g_markup_parse_context_parse(context, line,
                    strlen(line), &err)) {
                ufraw_message(UFRAW_ERROR, "Error parsing %s\n%s",
                        cfgFilename, err->message);
                if (g_error_matches(err, ufrawQuark, UFRAW_RC_VERSION))
                    return UFRAW_RC_VERSION;
                else return UFRAW_RC_ERROR;
            }
            fgets(line, max_path, in);
        }
        g_markup_parse_context_end_parse(context, NULL);
        g_markup_parse_context_free(context);
        fclose(in);
    }
    for (i=camera_curve+1; i<c->curveCount; i++) {
        if (curve_load(&c->curve[i], c->curve[i].file)==UFRAW_SUCCESS)
            continue;
        for (j=i; j<c->curveCount; j++) c->curve[j] = c->curve[j+1];
        c->curveCount--;
        i--;
    }
    /* a few consistency settings */
    if (c->curveIndex>=c->curveCount) c->curveIndex = cfg_default.curveIndex;
    c->profile[0][c->profileIndex[0]].curve = c->curveIndex;
    g_free(cfgFilename);
    return UFRAW_SUCCESS;
}

#define cfg_printf(format, ...) (\
    bufIndex += buf==NULL ? fprintf(out, format, ## __VA_ARGS__) :\
        snprintf(buf+bufIndex, bufSize-bufIndex, format, ## __VA_ARGS__)\
)

int save_configuration(cfg_data *c, char *buf, int bufSize)
{
    char *cfgFilename;
    const char *hd;
    FILE *out=NULL;
    char *type, *current;
    int bufIndex=0, i, j;
    gboolean first;

    if (buf==NULL) {
        hd = get_home_dir();
        cfgFilename = g_build_filename(hd, ".ufrawrc", NULL);
        if ( (out=fopen(cfgFilename, "w"))==NULL ) {
            ufraw_message(UFRAW_OPEN_ERROR,
                    "Can't open configuration file %s for writing\n%s\n",
                    cfgFilename, strerror(errno) );
            return UFRAW_OPEN_ERROR;
        }
        g_free(cfgFilename);
    }
    cfg_printf("<UFRaw Version='%d'>\n", c->version);
    if (strlen(c->inputFilename)>0)
        cfg_printf("<InputFilename>%s</InputFilename>\n", c->inputFilename);
    if (strlen(c->outputFilename)>0)
        cfg_printf("<OutputFilename>%s</OutputFilename>\n", c->outputFilename);
    if (c->wbLoad!=cfg_default.wbLoad)
        cfg_printf("<LoadWB>%d</LoadWB>\n", c->wbLoad);
    if (c->curveLoad!=cfg_default.curveLoad)
        cfg_printf("<LoadCurve>%d</LoadCurve>\n", c->curveLoad);
    if (c->exposureLoad!=cfg_default.exposureLoad)
        cfg_printf("<LoadExposure>%d</LoadExposure>\n", c->exposureLoad);
    if (c->interpolation!=cfg_default.interpolation)
        cfg_printf("<Interpolation>%d</Interpolation>\n", c->interpolation);
    if (c->expander[raw_expander]!=cfg_default.expander[raw_expander])
        cfg_printf("<RawExpander>%d</RawExpander>\n",
                c->expander[raw_expander]);
    if (c->expander[wb_expander]!=cfg_default.expander[wb_expander])
        cfg_printf("<WBExpander>%d</WBExpander>\n", c->expander[wb_expander]);
    if (c->expander[color_expander]!=cfg_default.expander[color_expander])
        cfg_printf("<ColorExpander>%d</ColorExpander>\n",
                c->expander[color_expander]);
    if (c->expander[curve_expander]!=cfg_default.expander[curve_expander])
        cfg_printf("<CurveExpander>%d</CurveExpander>\n",
                c->expander[curve_expander]);
    if (c->expander[live_expander]!=cfg_default.expander[live_expander])
        cfg_printf("<LiveExpander>%d</LiveExpander>\n",
                c->expander[live_expander]);
    if (c->histogram!=cfg_default.histogram)
        cfg_printf("<Histogram>%d</Histogram>\n", c->histogram);
    if (c->spotSize!=cfg_default.spotSize)
        cfg_printf("<SpotSize>%d</SpotSize>\n", c->spotSize);
    if (c->overExp!=cfg_default.overExp)
        cfg_printf("<OverExposure>%d</OverExposure>\n", c->overExp);
    if (c->underExp!=cfg_default.underExp)
        cfg_printf("<UnderExposure>%d</UnderExposure>\n", c->underExp);
    if (c->wb!=cfg_default.wb)
        cfg_printf("<WB>%d</WB>\n", c->wb);
    cfg_printf("<Temperature>%d</Temperature>\n", (int)floor(c->temperature));
    cfg_printf("<Green>%f</Green>\n", c->green);
    if (c->exposure!=cfg_default.exposure)
        cfg_printf("<Exposure>%f</Exposure>\n", c->exposure);
    if (c->unclip!=cfg_default.unclip)
        cfg_printf("<Unclip>%d</Unclip>\n", c->unclip);
    if (c->shrink!=cfg_default.shrink)
        cfg_printf("<Shrink>%d</Shrink>\n", c->shrink);
    if (c->type!=cfg_default.type)
        cfg_printf("<OutputType>%d</OutputType>\n", c->type);
    if (c->compression!=cfg_default.compression)
        cfg_printf("<Compression>%d</Compression>\n", c->compression);
    if (c->overwrite!=cfg_default.overwrite)
        cfg_printf("<Overwrite>%d</Overwrite>\n", c->overwrite);
    if (c->losslessCompress!=cfg_default.losslessCompress)
        cfg_printf("<LosslessCompression>%d</LosslessCompression>\n",
                c->losslessCompress);
    for (i=0; i<c->curveCount; i++) {
        current = i==c->curveIndex?" Current='1'":"";
        switch (i) {
        case gamma_curve: type = "GammaCurve";
                        first = TRUE;
                        break;
        case log_curve: type = "LogCurve";
                        first = TRUE;
                        break;
        case linear_curve: type = "LinearCurve";
                        first = TRUE;
                        break;
        case camera_curve: type = "CameraCurve";
                        first = TRUE;
                        break;
        default: type = "Curve";
                        cfg_printf("<%s%s>%s\n", type, current,
                                c->curve[i].name);
                        first = FALSE;
                        cfg_printf("\t<File>%s</File>\n", c->curve[i].file);
        }
        if (i==c->curveIndex) {
            if (first) cfg_printf("<%s%s>\n", type, current);
            first = FALSE;
        }
        if (c->curve[i].gamma!=cfg_default.curve[0].gamma) {
            if (first) cfg_printf("<%s>\n", type);
            first = FALSE;
            cfg_printf("\t<Gamma>%f</Gamma>\n", c->curve[i].gamma);
        }
        if (c->curve[i].contrast!=cfg_default.curve[0].contrast) {
            if (first) cfg_printf("<%s>\n", type);
            first = FALSE;
            cfg_printf("\t<Contrast>%f</Contrast>\n", c->curve[i].contrast);
        }
        if (c->curve[i].saturation!=cfg_default.curve[0].saturation) {
            if (first) cfg_printf("<%s>\n", type);
            first = FALSE;
            cfg_printf("\t<Saturation>%f</Saturation>\n",
                    c->curve[i].saturation);
        }
        if (c->curve[i].brightness!=cfg_default.curve[0].brightness) {
            if (first) cfg_printf("<%s>\n", type);
            first = FALSE;
            cfg_printf("\t<Brightness>%f</Brightness>\n",
                    c->curve[i].brightness);
        }
        if (c->curve[i].black!=cfg_default.curve[0].black) {
            if (first) cfg_printf("<%s>\n", type);
            first = FALSE;
            cfg_printf("\t<BlackPoint>%f</BlackPoint>\n", c->curve[i].black);
        }
        if (c->curve[i].shadow!=cfg_default.curve[0].shadow) {
            if (first) cfg_printf("<%s>\n", type);
            first = FALSE;
            cfg_printf("\t<Shadow>%f</Shadow>\n", c->curve[i].shadow);
        }
        if (c->curve[i].depth!=cfg_default.curve[0].depth) {
            if (first) cfg_printf("<%s>\n", type);
            first = FALSE;
            cfg_printf("\t<ShadowDepth>%f</ShadowDepth>\n", c->curve[i].depth);
        }
        if (!first) cfg_printf("</%s>\n", type);
    }
    if (strlen(c->curvePath)>0)
        cfg_printf("<CurvePath>%s</CurvePath>\n", c->curvePath);
    for (j=0; j<profile_types; j++) {
        type = j==in_profile ? "InputProfile" :
                j==out_profile ? "OutputProfile" : "Error";
        if ( c->profileIndex[j]==0 ||
             c->profile[j][0].gamma!=cfg_default.profile[0][0].gamma ||
             c->profile[j][0].curve!=cfg_default.profile[0][0].curve ) {
            current = 0==c->profileIndex[j]?" Current='1'":"";
            cfg_printf("<sRGB%s%s>\n", type, current);
            if (c->profile[j][0].gamma!=cfg_default.profile[j][0].gamma)
                cfg_printf("\t<Gamma>%f</Gamma>\n", c->profile[j][0].gamma);
            if (c->profile[j][0].curve!=cfg_default.profile[j][0].curve)
                cfg_printf("\t<Curve>%d</Curve>\n", c->profile[j][0].curve);
            cfg_printf("</sRGB%s>\n", type);
        }
        for (i=1; i<c->profileCount[j]; i++) {
            current = i==c->profileIndex[j]?" Current='1'":"";
            cfg_printf("<%s%s>%s\n", type, current, c->profile[j][i].name);
            cfg_printf("\t<File>%s</File>\n", c->profile[j][i].file);
            cfg_printf("\t<ProductName>%s</ProductName>\n",
                    c->profile[j][i].productName);
            if (c->profile[j][i].gamma!=cfg_default.profile[j][0].gamma)
                cfg_printf("\t<Gamma>%f</Gamma>\n", c->profile[j][i].gamma);
            if (c->profile[j][i].curve!=cfg_default.profile[j][0].curve)
                cfg_printf("\t<Curve>%d</Curve>\n", c->profile[j][i].curve);
            cfg_printf("</%s>\n", type);
        }
    }
    if (c->intent!=cfg_default.intent)
        cfg_printf("<Intent>%d</Intent>\n", c->intent);
    if (strlen(c->profilePath)>0)
        cfg_printf("<ProfilePath>%s</ProfilePath>\n", c->profilePath);
    cfg_printf("</UFRaw>\n");
    if (buf==NULL) fclose(out);
    else if (bufIndex >= bufSize) return UFRAW_ERROR;
    return UFRAW_SUCCESS;
}

Generated by  Doxygen 1.6.0   Back to index