Update of /cvsroot/ufraw/ufraw
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv26574
Modified Files:
ufraw.h ufraw_developer.c ufraw_preview.c ufraw_ufraw.c
Log Message:
Calculate live histogram from working color-space instead of
display color-space.
Calculate live histogram from cropped area only.
Based on patches by Konrad.
Index: ufraw.h
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw.h,v
retrieving revision 1.127
retrieving revision 1.128
diff -u -d -r1.127 -r1.128
--- ufraw.h 28 Oct 2009 04:44:05 -0000 1.127
+++ ufraw.h 31 Oct 2009 01:59:19 -0000 1.128
@@ -71,7 +71,7 @@
typedef enum { perceptual_intent, relative_intent, saturation_intent,
absolute_intent, disable_intent } Intent;
typedef enum { ufraw_raw_phase, ufraw_first_phase, ufraw_develop_phase,
- ufraw_lensfun_phase, ufraw_phases_num } UFRawPhase;
+ ufraw_lensfun_phase, ufraw_display_phase, ufraw_phases_num }
UFRawPhase;
typedef enum { grayscale_none, grayscale_lightness, grayscale_luminance,
grayscale_value, grayscale_mixer } GrayscaleMode;
@@ -100,6 +100,7 @@
Intent intent[profile_types];
gboolean updateTransform;
void *colorTransform;
+ void *working2displayTransform;
void *rgbtolabTransform;
double saturation;
double contrast;
@@ -314,6 +315,7 @@
ufraw_image_data *ufraw_rgb_image(ufraw_data *uf, gboolean bufferok,
const char *dbg);
ufraw_image_data *ufraw_final_image(ufraw_data *uf, gboolean bufferok);
+ufraw_image_data *ufraw_display_image(ufraw_data *uf, gboolean bufferok);
ufraw_image_data *ufraw_convert_image_area(ufraw_data *uf, unsigned saidx,
UFRawPhase phase);
void ufraw_close(ufraw_data *uf);
@@ -411,6 +413,7 @@
int rgbMax, float rgb_cam[3][4], int colors, int useMatrix,
DeveloperMode mode);
void develop(void *po, guint16 pix[4], developer_data *d, int mode, int count);
+void develop_display(void *pout, void *pin, developer_data *d, int count);
void develop_linear(guint16 in[4], guint16 out[3], developer_data *d);
/* prototype for functions in ufraw_saver.c */
Index: ufraw_developer.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_developer.c,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -d -r1.76 -r1.77
--- ufraw_developer.c 28 Oct 2009 04:44:05 -0000 1.76
+++ ufraw_developer.c 31 Oct 2009 01:59:19 -0000 1.77
@@ -63,6 +63,7 @@
d->intent[display_profile] = -1;
d->updateTransform = TRUE;
d->colorTransform = NULL;
+ d->working2displayTransform = NULL;
d->rgbtolabTransform = NULL;
d->grayscaleMode = -1;
d->grayscaleMixer[0] = d->grayscaleMixer[1] = d->grayscaleMixer[2] = -1;
@@ -88,6 +89,8 @@
cmsCloseProfile(d->adjustmentProfile);
if (d->colorTransform!=NULL)
cmsDeleteTransform(d->colorTransform);
+ if (d->working2displayTransform!=NULL)
+ cmsDeleteTransform(d->working2displayTransform);
if (d->rgbtolabTransform!=NULL)
cmsDeleteTransform(d->rgbtolabTransform);
g_free(d);
@@ -329,96 +332,77 @@
if ( !d->updateTransform )
return;
d->updateTransform = FALSE;
- if (d->colorTransform!=NULL)
- cmsDeleteTransform(d->colorTransform);
- if (d->rgbtolabTransform!=NULL)
- cmsDeleteTransform(d->rgbtolabTransform);
-
+ /* Create transformations according to mode:
+ * auto_developer|output_developer:
+ * colorTransformation from in to out
+ * working2displayTransform is null
+ * display_developer:
+ * with softproofing:
+ * colorTransformation from in to out
+ * working2displayTransform from out to display
+ * without softproofing:
+ * colorTransformation from in to display
+ * working2displayTransform is null
+ */
int targetProfile;
- if ( mode==file_developer || mode==auto_developer ) {
- targetProfile = out_profile;
- } else { /* mode==display_developer */
+ if ( mode == display_developer
+ && d->intent[display_profile] == disable_intent ) {
targetProfile = display_profile;
+ } else {
+ targetProfile = out_profile;
}
- /* When softproofing is disabled, use the out_profile intent. */
- if ( mode==file_developer || mode==auto_developer ||
- d->intent[display_profile]==disable_intent ) {
- /* No need for proofing transformation. */
- if ( strcmp(d->profileFile[in_profile],"")==0 &&
- strcmp(d->profileFile[targetProfile],"")==0 &&
- d->luminosityProfile==NULL &&
- d->adjustmentProfile==NULL &&
- d->saturationProfile==NULL ) {
- /* No transformation at all. */
- d->colorTransform = NULL;
+ if (d->colorTransform!=NULL)
+ cmsDeleteTransform(d->colorTransform);
+ if ( strcmp(d->profileFile[in_profile],"")==0 &&
+ strcmp(d->profileFile[targetProfile],"")==0 &&
+ d->luminosityProfile==NULL &&
+ d->adjustmentProfile==NULL &&
+ d->saturationProfile==NULL ) {
+ /* No transformation at all. */
+ d->colorTransform = NULL;
#if defined(LCMS_VERSION) && LCMS_VERSION <= 113 /* Bypass a lcms 1.13 bug. */
- } else if ( d->luminosityProfile==NULL
- && d->adjustmentProfile==NULL
- && d->saturationProfile==NULL ) {
- d->colorTransform = cmsCreateTransform(
- d->profile[in_profile], TYPE_RGB_16,
- d->profile[targetProfile], TYPE_RGB_16,
- d->intent[out_profile], 0);
-#endif
- } else {
- cmsHPROFILE prof[5];
- int i = 0;
- prof[i++] = d->profile[in_profile];
- if ( d->luminosityProfile!=NULL )
- prof[i++] = d->luminosityProfile;
- if ( d->adjustmentProfile!=NULL )
- prof[i++] = d->adjustmentProfile;
- if ( d->saturationProfile!=NULL )
- prof[i++] = d->saturationProfile;
- prof[i++] = d->profile[targetProfile];
- d->colorTransform = cmsCreateMultiprofileTransform(prof, i,
- TYPE_RGB_16, TYPE_RGB_16, d->intent[out_profile], 0);
- }
- } else {
- /* Create a proofing profile */
- if ( d->luminosityProfile==NULL
+ } else if ( d->luminosityProfile==NULL
&& d->adjustmentProfile==NULL
&& d->saturationProfile==NULL ) {
- /* No intermediate profiles, we can use lcms proofing directly. */
- d->colorTransform = cmsCreateProofingTransform(
- d->profile[in_profile], TYPE_RGB_16,
- d->profile[display_profile], TYPE_RGB_16,
- d->profile[out_profile],
- d->intent[out_profile], d->intent[display_profile],
- cmsFLAGS_SOFTPROOFING);
- } else {
- /* Following code imitates the function
- * cmsCreateMultiprofileProofingTransform(),
- * which does not exist in lcms. */
- cmsHPROFILE prof[4];
- int i = 0;
- prof[i++] = d->profile[in_profile];
- if ( d->luminosityProfile!=NULL )
- prof[i++] = d->luminosityProfile;
- if ( d->adjustmentProfile!=NULL )
- prof[i++] = d->adjustmentProfile;
- if ( d->saturationProfile!=NULL )
- prof[i++] = d->saturationProfile;
- d->colorTransform = cmsCreateMultiprofileTransform(prof, i,
- TYPE_RGB_16, NOCOLORSPACECHECK(TYPE_RGB_16),
- d->intent[out_profile], cmsFLAGS_SOFTPROOFING);
+ d->colorTransform = cmsCreateTransform(
+ d->profile[in_profile], TYPE_RGB_16,
+ d->profile[targetProfile], TYPE_RGB_16,
+ d->intent[out_profile], 0);
+#endif
+ } else {
+ cmsHPROFILE prof[5];
+ int i = 0;
+ prof[i++] = d->profile[in_profile];
+ if ( d->luminosityProfile!=NULL )
+ prof[i++] = d->luminosityProfile;
+ if ( d->adjustmentProfile!=NULL )
+ prof[i++] = d->adjustmentProfile;
+ if ( d->saturationProfile!=NULL )
+ prof[i++] = d->saturationProfile;
+ prof[i++] = d->profile[targetProfile];
+ d->colorTransform = cmsCreateMultiprofileTransform(prof, i,
+ TYPE_RGB_16, TYPE_RGB_16, d->intent[out_profile], 0);
+ }
- prof[0] = cmsTransform2DeviceLink(d->colorTransform,
- cmsFLAGS_GUESSDEVICECLASS);
- cmsDeleteTransform(d->colorTransform);
- d->colorTransform = cmsCreateProofingTransform(
- prof[0], TYPE_RGB_16,
- d->profile[display_profile], TYPE_RGB_16,
- d->profile[out_profile],
- d->intent[out_profile], d->intent[display_profile],
- cmsFLAGS_SOFTPROOFING);
- }
+ if (d->working2displayTransform != NULL)
+ cmsDeleteTransform(d->working2displayTransform);
+ if ( mode == display_developer
+ && d->intent[display_profile] != disable_intent
+ && strcmp(d->profileFile[out_profile],
+ d->profileFile[display_profile]) != 0 ) {
+ // TODO: We should use TYPE_RGB_'bit_depth' for working profile.
+ d->working2displayTransform = cmsCreateTransform(
+ d->profile[out_profile], TYPE_RGB_8,
+ d->profile[display_profile], TYPE_RGB_8,
+ d->intent[display_profile], 0);
+ } else {
+ d->working2displayTransform = NULL;
}
- d->rgbtolabTransform = cmsCreateTransform(d->profile[in_profile],
- TYPE_RGB_16,
- cmsCreateLabProfile(cmsD50_xyY()),
- TYPE_Lab_16,
- INTENT_ABSOLUTE_COLORIMETRIC, 0);
+
+ if (d->rgbtolabTransform == NULL)
+ d->rgbtolabTransform = cmsCreateTransform(d->profile[in_profile],
+ TYPE_RGB_16, cmsCreateLabProfile(cmsD50_xyY()),
+ TYPE_Lab_16, INTENT_ABSOLUTE_COLORIMETRIC, 0);
}
static gboolean test_adjustments(const lightness_adjustment
values[max_adjustments],
@@ -824,6 +808,14 @@
}
}
+void develop_display(void *pout, void *pin, developer_data *d, int count)
+{
+ if (d->working2displayTransform == NULL)
+ g_error("develop_display: working2displayTransform == NULL");
+
+ cmsDoTransform(d->working2displayTransform, pin, pout, count);
+}
+
static void develop_grayscale(guint16 *pixel, const developer_data *d)
{
gint32 spot;
Index: ufraw_ufraw.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_ufraw.c,v
retrieving revision 1.202
retrieving revision 1.203
diff -u -d -r1.202 -r1.203
--- ufraw_ufraw.c 29 Oct 2009 05:14:59 -0000 1.202
+++ ufraw_ufraw.c 31 Oct 2009 01:59:19 -0000 1.203
@@ -1169,7 +1169,7 @@
ufraw_image_data *FirstImage = &uf->Images[ufraw_first_phase];
ufraw_image_data *img;
- /* Development image layer */
+ /* Development output image layer */
img = &uf->Images[ufraw_develop_phase];
if (img->height != FirstImage->height ||
img->width != FirstImage->width ||
@@ -1197,6 +1197,24 @@
/* ignore uf->modifier to avoid a call dependency */
img->buffer = g_realloc(img->buffer, img->height * img->rowstride);
#endif /* HAVE_LENSFUN */
+
+ img = &uf->Images[ufraw_display_phase];
+ if (img->height != FirstImage->height ||
+ img->width != FirstImage->width ||
+ !img->buffer)
+ img->valid = 0;
+
+ img->height = FirstImage->height;
+ img->width = FirstImage->width;
+ img->depth = 3;
+ img->rowstride = img->width * img->depth;
+ // TODO: We should be able to allocate a buffer only if it is needed.
+// if (uf->developer->working2displayTransform == NULL) {
+// g_free(img->buffer);
+// img->buffer = NULL;
+// } else {
+ img->buffer = g_realloc(img->buffer, img->height * img->rowstride);
+// }
}
#ifdef HAVE_LENSFUN
@@ -1320,6 +1338,44 @@
return &uf->Images[phase];
}
+ufraw_image_data *ufraw_display_image(ufraw_data *uf, gboolean bufferok)
+{
+ UFRawPhase phase = ufraw_display_phase;
+ if (uf->developer->working2displayTransform == NULL) {
+#ifdef HAVE_LENSFUN
+ if (uf->modifier &&
+ (uf->postproc_ops & (UF_LF_ALL & ~LF_MODIFY_VIGNETTING)))
+ phase = ufraw_lensfun_phase;
+ else
+ phase = ufraw_develop_phase;
+#else /* HAVE_LENSFUN */
+ phase = ufraw_develop_phase;
+#endif /* HAVE_LENSFUN */
+ }
+ if (bufferok) {
+ /* It should never be necessary to actually finish the conversion
+ * because it can break render_preview_image() which uses the
+ * final image "valid" mask for deciding what to update in the
+ * pixbuf. That can be fixed but is suboptimal anyway. The best
+ * we can do is print a warning in case we need to finish the
+ * conversion and finish it here. */
+ if (uf->Images[phase].valid != (long)0xffffffff) {
+ g_warning("%s: fixing unfinished conversion.\n", G_STRFUNC);
+ int i;
+ for (i = 0; i < 32; ++i)
+ ufraw_convert_image_area(uf, i, phase);
+ }
+ } else {
+ if (uf->Images[phase].valid == 0) {
+ g_warning("%s: starting conversion.\n", G_STRFUNC);
+ /* this will update all buffer sizes (e.g. due to rotate) */
+ ufraw_convert_image_area(uf, 0, ufraw_first_phase);
+ }
+ }
+ return &uf->Images[phase];
+}
+
+
ufraw_image_data *ufraw_convert_image_area(ufraw_data *uf, unsigned saidx,
UFRawPhase phase)
{
@@ -1478,6 +1534,18 @@
return in;
#endif /* HAVE_LENSFUN */
+ case ufraw_display_phase:
+ if (uf->developer->working2displayTransform == NULL)
+ return in;
+
+ int yy;
+ for (yy = y; yy < y + h; yy++) {
+ guint8 *dest = out->buffer + (yy * out->width + x) *
out->depth;
+ guint8 *source = in->buffer + (yy * in->width + x) * in->depth;
+ develop_display(dest, source, uf->developer, w);
+ }
+ break;
+
default:
g_warning("%s: invalid phase %d\n", G_STRFUNC, phase);
return in;
@@ -1627,6 +1695,8 @@
(uf->postproc_ops & (UF_LF_ALL & ~LF_MODIFY_VIGNETTING)))
ufraw_flip_image_buffer(&uf->Images[ufraw_lensfun_phase], flip);
#endif /* HAVE_LENSFUN */
+ if (uf->developer->working2displayTransform != NULL)
+ ufraw_flip_image_buffer(&uf->Images[ufraw_display_phase], flip);
return UFRAW_SUCCESS;
}
Index: ufraw_preview.c
===================================================================
RCS file: /cvsroot/ufraw/ufraw/ufraw_preview.c,v
retrieving revision 1.292
retrieving revision 1.293
diff -u -d -r1.292 -r1.293
--- ufraw_preview.c 28 Oct 2009 04:55:40 -0000 1.292
+++ ufraw_preview.c 31 Oct 2009 01:59:19 -0000 1.293
@@ -542,9 +542,6 @@
x+width, pixbufWidth);
if ( width==0 ) return; // Nothing to do
- int rowstride = gdk_pixbuf_get_rowstride(data->PreviewPixbuf);
- guint8 *pixies = gdk_pixbuf_get_pixels(data->PreviewPixbuf);
- guint8 *p8;
gboolean blinkOver = CFG->overExp &&
( !CFG->blinkOverUnder || (data->OverUnderTicker & 3) == 1 );
gboolean blinkUnder = CFG->underExp &&
@@ -567,18 +564,24 @@
int SpotY2 = ceil(MAX(data->SpotY1, data->SpotY2) * scale_y);
int SpotX1 = floor(MIN(data->SpotX1, data->SpotX2) * scale_x);
int SpotX2 = ceil(MAX(data->SpotX1, data->SpotX2) * scale_x);
- int xx, yy, c;
+ int rowstride = gdk_pixbuf_get_rowstride(data->PreviewPixbuf);
+ guint8 *pixies = gdk_pixbuf_get_pixels(data->PreviewPixbuf) + x*3;
/* This is bad. `img' should have been a parameter because we
* cannot request an up to date buffer but it must be up to
* date to some extend. In theory we could get the wrong buffer */
- ufraw_image_data *img = ufraw_final_image(data->UF, FALSE);
+ ufraw_image_data *displayImage = ufraw_display_image(data->UF, FALSE);
+ guint8 *displayPixies = displayImage->buffer + x*displayImage->depth;
+ ufraw_image_data *workingImage = ufraw_final_image(data->UF, FALSE);
+ guint8 *workingPixies = workingImage->buffer + x*workingImage->depth;
+ int xx, yy, c;
for (yy=y; yy<y+height; yy++) {
- p8 = pixies+yy*rowstride+x*3;
- memcpy(p8, img->buffer + yy*img->rowstride + x*img->depth,
- width*img->depth);
- for (xx=x; xx<x+width; xx++, p8+=3) {
+ guint8 *p8 = pixies + yy*rowstride;
+ memcpy(p8, displayPixies + yy*displayImage->rowstride,
+ width*displayImage->depth);
+ guint8 *p8working = workingPixies + yy*workingImage->rowstride;
+ for (xx=x; xx<x+width; xx++, p8+=3, p8working+=workingImage->depth) {
if ( data->SpotDraw &&
( ((yy==SpotY1-1 || yy==SpotY2) && xx>=SpotX1-1 && xx<=SpotX2)
||
@@ -596,11 +599,14 @@
((xx==CropX1-1 || xx==CropX2) && yy>=CropY1-1 && yy<=CropY2) )
{
p8[0] = p8[1] = p8[2] = 255;
+ continue;
}
/* Shade the cropped out area */
else if ( yy<CropY1 || yy>=CropY2 || xx<CropX1 || xx>=CropX2 ) {
for (c=0; c<3; c++) p8[c] = p8[c]/4;
- } else if (data->RenderMode==render_default) {
+ continue;
+ }
+ if (data->RenderMode==render_default) {
/* Shade out the alignment lines */
if ( CFG->drawLines &&
yy > CropY1 + 1 && yy < CropY2 - 2 &&
@@ -618,14 +624,14 @@
}
}
/* Blink the overexposed/underexposed spots */
- if ( blinkOver && (p8[0]==255 || p8[1]==255 || p8[2]==255) )
+ if ( blinkOver && (p8working[0]==255 || p8working[1]==255 ||
p8working[2]==255) )
p8[0] = p8[1] = p8[2] = 0;
- else if ( blinkUnder && (p8[0]==0 || p8[1]==0 || p8[2]==0) )
+ else if ( blinkUnder && (p8working[0]==0 || p8working[1]==0 ||
p8working[2]==0) )
p8[0] = p8[1] = p8[2] = 255;
} else if (data->RenderMode==render_overexposed) {
- for (c=0; c<3; c++) if (p8[c]!=255) p8[c] = 0;
+ for (c=0; c<3; c++) if (p8working[c]!=255) p8[c] = 0;
} else if (data->RenderMode==render_underexposed) {
- for (c=0; c<3; c++) if (p8[c]!=0) p8[c] = 255;
+ for (c=0; c<3; c++) if (p8working[c]!=0) p8[c] = 255;
}
}
}
@@ -1081,17 +1087,24 @@
{
if (data->FreezeDialog) return FALSE;
- int width = gdk_pixbuf_get_width(data->PreviewPixbuf);
- int height = gdk_pixbuf_get_height(data->PreviewPixbuf);
- int i, x, y, c, min, max;
- guint8 *p8;
+ int x, y, c, min, max;
ufraw_image_data *img = ufraw_final_image(data->UF, TRUE);
+
+ /* Scale crop image coordinates to pixbuf coordinates */
+ float scale_x = ((float)img->width) / data->UF->rotatedWidth;
+ float scale_y = ((float)img->height) / data->UF->rotatedHeight;
+ int CropY1 = floor(CFG->CropY1 * scale_y);
+ int CropY2 = ceil(CFG->CropY2 * scale_y);
+ int CropX1 = floor(CFG->CropX1 * scale_x);
+ int CropX2 = ceil(CFG->CropX2 * scale_x);
+
double rgb[3];
guint64 sum[3], sqr[3];
int live_his[live_his_size][4];
memset(live_his, 0, sizeof(live_his));
- for (i=0; i < img->height*img->width; i++) {
- p8 = img->buffer + i*img->depth;
+ for (y=CropY1; y < CropY2; y++)
+ for (x=CropX1; x < CropX2; x++) {
+ guint8 *p8 = img->buffer + y*img->rowstride + x*img->depth;
for (c=0, max=0, min=0x100; c<3; c++) {
max = MAX(max, p8[c]);
min = MIN(min, p8[c]);
@@ -1171,17 +1184,19 @@
pix[c] = 96; /* gray */
}
gtk_widget_queue_draw(data->LiveHisto);
+
+ int CropCount = (CropX2 - CropX1) * (CropY2 - CropY1);
for (c=0; c<3; c++)
- rgb[c] = sum[c]/height/width;
+ rgb[c] = sum[c]/CropCount;
color_labels_set(data->AvrLabels, rgb);
for (c=0; c<3; c++)
- rgb[c] = sqrt(sqr[c]/height/width-rgb[c]*rgb[c]);
+ rgb[c] = sqrt(sqr[c]/CropCount - rgb[c]*rgb[c]);
color_labels_set(data->DevLabels, rgb);
for (c=0; c<3; c++)
- rgb[c] = 100.0*live_his[live_his_size-1][c]/height/width;
+ rgb[c] = 100.0*live_his[live_his_size-1][c]/CropCount;
color_labels_set(data->OverLabels, rgb);
for (c=0; c<3; c++)
- rgb[c] = 100.0*live_his[0][c]/height/width;
+ rgb[c] = 100.0*live_his[0][c]/CropCount;
color_labels_set(data->UnderLabels, rgb);
return FALSE;
@@ -1985,6 +2000,8 @@
(GSourceFunc)(preview_draw_crop), data, NULL);
}
update_shrink_ranges(data);
+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE+20,
+ (GSourceFunc)(render_live_histogram), data, NULL);
}
static void crop_reset(GtkWidget *widget, gpointer user_data)
------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
ufraw-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ufraw-cvs