Update of /cvsroot/ufraw/ufraw In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv10053
Modified Files: ufraw-gimp.c ufraw.h ufraw_lens_ui.c ufraw_preview.c ufraw_ufraw.c ufraw_ui.h ufraw_writer.c Log Message: Resize canvas to fit to lensfun transformations. Index: ufraw_writer.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw_writer.c,v retrieving revision 1.70 retrieving revision 1.71 diff -u -d -r1.70 -r1.71 --- ufraw_writer.c 23 Jan 2010 05:00:59 -0000 1.70 +++ ufraw_writer.c 5 Feb 2010 23:22:16 -0000 1.71 @@ -196,36 +196,35 @@ #endif /*HAVE_LIBPNG*/ void ufraw_write_image_data( - ufraw_data *uf, - void * volatile out, - int width, int height, int left, int top, int bitDepth, int grayscaleMode, - int (*row_writer) (ufraw_data *, void * volatile, void *, int, int, int, int, int)) + ufraw_data *uf, void * volatile out, + const UFRectangle *Crop, int bitDepth, int grayscaleMode, + int (*row_writer)(ufraw_data *, void * volatile, void *, int, int, int, int, int)) { int row, row0; int rowStride = uf->Images[ufraw_first_phase].width; ufraw_image_type *rawImage = (ufraw_image_type *)uf->Images[ufraw_first_phase].buffer; int byteDepth = (bitDepth+7)/8; - guint8 pixbuf8[width * 3 * byteDepth * DEVELOP_BATCH]; + guint8 pixbuf8[Crop->width * 3 * byteDepth * DEVELOP_BATCH]; - progress(PROGRESS_SAVE, -height); - for (row0 = 0; row0 < height; row0 += DEVELOP_BATCH) { + progress(PROGRESS_SAVE, -Crop->height); + for (row0 = 0; row0 < Crop->height; row0 += DEVELOP_BATCH) { progress(PROGRESS_SAVE, DEVELOP_BATCH); #ifdef _OPENMP #pragma omp parallel for default(shared) private(row) #endif for (row = 0; row < DEVELOP_BATCH; row++) { - if (row + row0 >= height) + if (row + row0 >= Crop->height) continue; - guint8 *rowbuf = &pixbuf8[row * width * 3 * byteDepth]; - develop(rowbuf, rawImage[(top+row+row0)*rowStride+left], - uf->developer, bitDepth, width); + guint8 *rowbuf = &pixbuf8[row * Crop->width * 3 * byteDepth]; + develop(rowbuf, rawImage[(Crop->y+row+row0)*rowStride+Crop->x], + uf->developer, bitDepth, Crop->width); if (grayscaleMode) - grayscale_buffer(rowbuf, width, bitDepth); + grayscale_buffer(rowbuf, Crop->width, bitDepth); } - int batchHeight = MIN(height-row0, DEVELOP_BATCH); - if ( row_writer(uf, out, pixbuf8, row0, width, batchHeight, - grayscaleMode, bitDepth) != UFRAW_SUCCESS ) + int batchHeight = MIN(Crop->height-row0, DEVELOP_BATCH); + if (row_writer(uf, out, pixbuf8, row0, Crop->width, batchHeight, + grayscaleMode, bitDepth) != UFRAW_SUCCESS) break; } } @@ -237,7 +236,6 @@ #ifdef HAVE_LIBCFITSIO fitsfile *fitsFile; #endif - int width, height, left, top; char * volatile confFilename=NULL; int grayscaleMode = uf->conf->grayscaleMode != grayscale_none; ufraw_message_reset(uf); @@ -323,30 +321,25 @@ } // TODO: error handling ufraw_convert_image(uf); - ufraw_image_data *FirstImage = &uf->Images[ufraw_first_phase]; - left = uf->conf->CropX1 * FirstImage->width / uf->rotatedWidth; - top = uf->conf->CropY1 * FirstImage->height / uf->rotatedHeight; + UFRectangle Crop; + ufraw_get_scaled_crop(uf, &Crop); volatile int BitDepth = uf->conf->profile[out_profile] [uf->conf->profileIndex[out_profile]].BitDepth; if ( BitDepth!=16 ) BitDepth = 8; - width = (uf->conf->CropX2 - uf->conf->CropX1) - * FirstImage->width / uf->rotatedWidth; - height = (uf->conf->CropY2 - uf->conf->CropY1) - * FirstImage->height / uf->rotatedHeight; if ( uf->conf->type==ppm_type && BitDepth==8 ) { fprintf(out, "P%c\n%d %d\n%d\n", - grayscaleMode ? '5' : '6', width, height, 0xFF); - ufraw_write_image_data(uf, out, width, height, left, top, - BitDepth, grayscaleMode, ppm_row_writer); + grayscaleMode ? '5' : '6', Crop.width, Crop.height, 0xFF); + ufraw_write_image_data(uf, out, &Crop, BitDepth, grayscaleMode, + ppm_row_writer); } else if ( uf->conf->type==ppm_type && BitDepth==16 ) { fprintf(out, "P%c\n%d %d\n%d\n", - grayscaleMode ? '5' : '6', width, height, 0xFFFF); - ufraw_write_image_data(uf, out, width, height, left, top, - BitDepth, grayscaleMode, ppm_row_writer); + grayscaleMode ? '5' : '6', Crop.width, Crop.height, 0xFFFF); + ufraw_write_image_data(uf, out, &Crop, BitDepth, grayscaleMode, + ppm_row_writer); #ifdef HAVE_LIBTIFF } else if ( uf->conf->type==tiff_type ) { - TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width); - TIFFSetField(out, TIFFTAG_IMAGELENGTH, height); + TIFFSetField(out, TIFFTAG_IMAGEWIDTH, Crop.width); + TIFFSetField(out, TIFFTAG_IMAGELENGTH, Crop.height); TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, grayscaleMode ? 1 : 3); TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, BitDepth); @@ -395,8 +388,8 @@ } TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, 0)); - ufraw_write_image_data(uf, out, width, height, left, top, - BitDepth, grayscaleMode, tiff_row_writer); + ufraw_write_image_data(uf, out, &Crop, BitDepth, grayscaleMode, + tiff_row_writer); #endif /*HAVE_LIBTIFF*/ #ifdef HAVE_LIBJPEG @@ -413,8 +406,8 @@ cinfo.client_data = uf; jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, out); - cinfo.image_width = width; - cinfo.image_height = height; + cinfo.image_width = Crop.width; + cinfo.image_height = Crop.height; if (grayscaleMode) { cinfo.input_components = 1; cinfo.in_color_space = JCS_GRAYSCALE; @@ -481,8 +474,8 @@ } } - ufraw_write_image_data(uf, &cinfo, width, height, left, top, - 8, grayscaleMode, jpeg_row_writer); + ufraw_write_image_data(uf, &cinfo, &Crop, 8, grayscaleMode, + jpeg_row_writer); if ( ufraw_is_error(uf) ) { char *message = g_strdup(ufraw_get_message(uf)); @@ -510,7 +503,7 @@ png_destroy_write_struct(&png, &info); } else { png_init_io(png, out); - png_set_IHDR(png, info, width, height, BitDepth, + png_set_IHDR(png, info, Crop.width, Crop.height, BitDepth, grayscaleMode ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); @@ -573,8 +566,8 @@ if (BitDepth != 8 && G_BYTE_ORDER==G_LITTLE_ENDIAN ) png_set_swap(png); // Swap byte order to big-endian - ufraw_write_image_data(uf, png, width, height, left, top, - BitDepth, grayscaleMode, png_row_writer); + ufraw_write_image_data(uf, png, &Crop, BitDepth, grayscaleMode, + png_row_writer); png_write_end(png, NULL); png_destroy_write_struct(&png, &info); @@ -593,8 +586,8 @@ int naxis = 3; // 3-dimensional image int status = 0; // status variable for fitsio - long naxes[3] = { width, height, 3 }; - long dim = width * height; + long naxes[3] = { Crop.width, Crop.height, 3 }; + long dim = Crop.width * Crop.height; long offset = 0; image = g_new(guint16, 3 * dim); @@ -609,13 +602,13 @@ // Avoid FITS images being saved upside down ufraw_flip_image(uf, 2); - progress(PROGRESS_SAVE, -height); - for (row=0; row<height; row++) { + progress(PROGRESS_SAVE, -Crop.height); + for (row=0; row<Crop.height; row++) { progress(PROGRESS_SAVE, 1); - for (i=0; i < width; i++) + for (i=0; i < Crop.width; i++) { - offset = row*width + i; - develop_linear(rawImage[(top+row)*rowStride+left+i], pixbuf16, + offset = row*Crop.width + i; + develop_linear(rawImage[(Crop.y+row)*rowStride+Crop.x+i], pixbuf16, uf->developer); int c; for (c=0; c<3; c++) { Index: ufraw_lens_ui.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw_lens_ui.c,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- ufraw_lens_ui.c 23 Jan 2010 05:00:58 -0000 1.24 +++ ufraw_lens_ui.c 5 Feb 2010 23:22:15 -0000 1.25 @@ -334,6 +334,7 @@ ufraw_invalidate_layer(data->UF, ufraw_first_phase); else ufraw_invalidate_layer(data->UF, ufraw_transform_phase); + resize_canvas(data); render_preview (data); } @@ -610,6 +611,7 @@ preview_data *data = get_preview_data (adj); *valuep = gtk_adjustment_get_value (adj); ufraw_invalidate_layer(data->UF, ufraw_transform_phase); + resize_canvas(data); render_preview (data); } @@ -619,6 +621,7 @@ preview_data *data = get_preview_data (button); gtk_adjustment_set_value (data->LensScaleAdjustment, 0.0); ufraw_invalidate_layer(data->UF, ufraw_transform_phase); + resize_canvas(data); render_preview (data); } @@ -635,6 +638,7 @@ gtk_adjustment_set_value (data->LensScaleAdjustment, log (cs * as) / log (2.0)); ufraw_invalidate_layer(data->UF, ufraw_transform_phase); + resize_canvas(data); render_preview (data); } } @@ -891,6 +895,7 @@ lf_lens_add_calib_distortion (CFG->lens, &CFG->lens_distortion); ufraw_invalidate_layer(data->UF, ufraw_transform_phase); + resize_canvas(data); render_preview (data); } @@ -929,6 +934,7 @@ gtk_widget_show_all (data->LensDistortionTable); ufraw_invalidate_layer(data->UF, ufraw_transform_phase); + resize_canvas(data); render_preview (data); } @@ -1001,6 +1007,7 @@ gtk_label_set_text (GTK_LABEL (data->LensFromGeometryDesc), details); ufraw_invalidate_layer(data->UF, ufraw_transform_phase); + resize_canvas(data); render_preview (data); } Index: ufraw_preview.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw_preview.c,v retrieving revision 1.332 retrieving revision 1.333 diff -u -d -r1.332 -r1.333 --- ufraw_preview.c 4 Feb 2010 05:59:57 -0000 1.332 +++ ufraw_preview.c 5 Feb 2010 23:22:15 -0000 1.333 @@ -507,20 +507,6 @@ return 0; } -/* Scale crop coordinates to final image coordinates */ -void scale_crop_to_final_image(ufraw_data *uf, - int *x1, int *x2, int *y1, int *y2) -{ - ufraw_image_data *img = ufraw_get_image(uf, ufraw_develop_phase, FALSE); - - float scale_x = ((float)img->width) / uf->rotatedWidth; - float scale_y = ((float)img->height) / uf->rotatedHeight; - *x1 = MAX(floor(uf->conf->CropX1 * scale_x), 0); - *x2 = MIN(ceil(uf->conf->CropX2 * scale_x), img->width); - *y1 = MAX(floor(uf->conf->CropY1 * scale_y), 0); - *y2 = MIN(ceil(uf->conf->CropY2 * scale_y), img->height); -} - /* Modify the preview image to mark crop and spot areas. * Note that all coordinate intervals are semi-inclusive, e.g. * X1 <= pixels < X2 and Y1 <= pixels < Y2 @@ -553,10 +539,10 @@ gboolean blinkUnder = CFG->underExp && ( !CFG->blinkOverUnder || (data->OverUnderTicker & 3) == 3 ); - int CropX1, CropX2, CropY1, CropY2; - scale_crop_to_final_image(data->UF, &CropX1, &CropX2, &CropY1, &CropY2); - int CropWidth = CropX2 - CropX1; - int CropHeight = CropY2 - CropY1; + UFRectangle Crop; + ufraw_get_scaled_crop(data->UF, &Crop); + int CropX2 = Crop.x + Crop.width; + int CropY2 = Crop.y + Crop.height; int drawLines = CFG->drawLines + 1; /* Scale spot image coordinates to pixbuf coordinates */ @@ -605,24 +591,24 @@ continue; } /* Draw white frame around crop area */ - if ( ((yy==CropY1-1 || yy==CropY2) && xx>=CropX1-1 && xx<=CropX2) || - ((xx==CropX1-1 || xx==CropX2) && yy>=CropY1-1 && yy<=CropY2) ) + if ( ((yy==Crop.y-1 || yy==CropY2) && xx>=Crop.x-1 && xx<=CropX2) || + ((xx==Crop.x-1 || xx==CropX2) && yy>=Crop.y-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 ) { + else if ( yy<Crop.y || yy>=CropY2 || xx<Crop.x || xx>=CropX2 ) { for (c=0; c<3; c++) p8[c] = p8[c]/4; continue; } if (data->RenderMode==render_default) { /* Shade out the alignment lines */ if ( CFG->drawLines && - yy > CropY1 + 1 && yy < CropY2 - 2 && - xx > CropX1 + 1 && xx < CropX2 - 2 ) { - int dx = (xx - CropX1) * drawLines % CropWidth / drawLines; - int dy = (yy - CropY1) * drawLines % CropHeight / drawLines; + yy > Crop.y + 1 && yy < CropY2 - 2 && + xx > Crop.x + 1 && xx < CropX2 - 2 ) { + int dx = (xx-Crop.x) * drawLines % Crop.width / drawLines; + int dy = (yy-Crop.y) * drawLines % Crop.height / drawLines; if (dx == 0 || dy == 0) { p8[0] /= 2; p8[1] /= 2; @@ -665,10 +651,9 @@ static gboolean preview_draw_crop(preview_data *data) { - int CropX1, CropX2, CropY1, CropY2; - scale_crop_to_final_image(data->UF, &CropX1, &CropX2, &CropY1, &CropY2); - preview_draw_area(data, CropX1, CropY1, CropX2-CropX1, CropY2-CropY1); - + UFRectangle Crop; + ufraw_get_scaled_crop(data->UF, &Crop); + preview_draw_area(data, Crop.x, Crop.y, Crop.width, Crop.height); return FALSE; } @@ -685,16 +670,16 @@ return TRUE; if (!is_rendering(data)) { /* Set the area to redraw based on the crop rectangle and view port. */ - int x1, x2, y1, y2; - scale_crop_to_final_image(data->UF, &x1, &x2, &y1, &y2); + UFRectangle Crop; + ufraw_get_scaled_crop(data->UF, &Crop); GdkRectangle viewRect; gtk_image_view_get_viewport(GTK_IMAGE_VIEW(data->PreviewWidget), &viewRect); - x1 = MAX(x1, viewRect.x); - int width = MIN(MAX(x2 - x1, 0), viewRect.width); - y1 = MAX(y1, viewRect.y); - int height = MIN(MAX(y2 - y1, 0), viewRect.height); + int x1 = MAX(Crop.x, viewRect.x); + int width = MIN(Crop.width, viewRect.width); + int y1 = MAX(Crop.y, viewRect.y); + int height = MIN(Crop.height, viewRect.height); data->OverUnderTicker++; preview_draw_area(data, x1, y1, width, height); @@ -1169,15 +1154,15 @@ ufraw_image_data *img = ufraw_get_image(data->UF, ufraw_develop_phase, TRUE); - int CropX1, CropX2, CropY1, CropY2; - scale_crop_to_final_image(data->UF, &CropX1, &CropX2, &CropY1, &CropY2); + UFRectangle Crop; + ufraw_get_scaled_crop(data->UF, &Crop); double rgb[3]; guint64 sum[3], sqr[3]; int live_his[live_his_size][4]; memset(live_his, 0, sizeof(live_his)); - for (y=CropY1; y < CropY2; y++) - for (x=CropX1; x < CropX2; x++) { + for (y=Crop.y; y < Crop.y+Crop.height; y++) + for (x=Crop.x; x < Crop.x+Crop.width; 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]); @@ -1259,7 +1244,7 @@ } gtk_widget_queue_draw(data->LiveHisto); - int CropCount = (CropX2 - CropX1) * (CropY2 - CropY1); + int CropCount = Crop.width * Crop.height; for (c=0; c<3; c++) rgb[c] = sum[c]/CropCount; color_labels_set(data->AvrLabels, rgb); @@ -1746,7 +1731,8 @@ (GSourceFunc)(render_spot), data, NULL); return TRUE; } - if ( data->PageNum==data->PageNumCrop ) { + if (data->PageNum==data->PageNumCrop || + data->PageNum==data->PageNumLensfun) { data->PreviewButtonPressed = TRUE; return TRUE; } @@ -1869,7 +1855,8 @@ (void)user_data; if (!gtk_event_box_get_above_child(GTK_EVENT_BOX(event_box))) return FALSE; - if ( data->PageNum==data->PageNumCrop ) + if (data->PageNum==data->PageNumCrop || + data->PageNum==data->PageNumLensfun) return crop_motion_notify(data, event); if ((event->state&GDK_BUTTON1_MASK)==0) return FALSE; if ( !data->PreviewButtonPressed ) return FALSE; @@ -1951,38 +1938,40 @@ data->FreezeDialog--; - int CropX1, CropX2, CropY1, CropY2; - scale_crop_to_final_image(data->UF, &CropX1, &CropX2, &CropY1, &CropY2); + UFRectangle Crop; + ufraw_get_scaled_crop(data->UF, &Crop); + int CropX2 = Crop.x + Crop.width; + int CropY2 = Crop.y + Crop.height; int x1[4], x2[4], y1[4], y2[4], i = 0; - if (CropX1!=data->DrawnCropX1) { - x1[i] = MIN(CropX1, data->DrawnCropX1); - x2[i] = MAX(CropX1, data->DrawnCropX1); - y1[i] = MIN(CropY1, data->DrawnCropY1); + if (Crop.x!=data->DrawnCropX1) { + x1[i] = MIN(Crop.x, data->DrawnCropX1); + x2[i] = MAX(Crop.x, data->DrawnCropX1); + y1[i] = MIN(Crop.y, data->DrawnCropY1); y2[i] = MAX(CropY2, data->DrawnCropY2); - data->DrawnCropX1 = CropX1; + data->DrawnCropX1 = Crop.x; i++; } if (CropX2!=data->DrawnCropX2) { x1[i] = MIN(CropX2, data->DrawnCropX2); x2[i] = MAX(CropX2, data->DrawnCropX2); - y1[i] = MIN(CropY1, data->DrawnCropY1); + y1[i] = MIN(Crop.y, data->DrawnCropY1); y2[i] = MAX(CropY2, data->DrawnCropY2); data->DrawnCropX2 = CropX2; i++; } - if (CropY1!=data->DrawnCropY1) { - y1[i] = MIN(CropY1, data->DrawnCropY1); - y2[i] = MAX(CropY1, data->DrawnCropY1); - x1[i] = MIN(CropX1, data->DrawnCropX1); + if (Crop.y!=data->DrawnCropY1) { + y1[i] = MIN(Crop.y, data->DrawnCropY1); + y2[i] = MAX(Crop.y, data->DrawnCropY1); + x1[i] = MIN(Crop.x, data->DrawnCropX1); x2[i] = MAX(CropX2, data->DrawnCropX2); - data->DrawnCropY1 = CropY1; + data->DrawnCropY1 = Crop.y; i++; } if (CropY2!=data->DrawnCropY2) { y1[i] = MIN(CropY2, data->DrawnCropY2); y2[i] = MAX(CropY2, data->DrawnCropY2); - x1[i] = MIN(CropX1, data->DrawnCropX1); + x1[i] = MIN(Crop.x, data->DrawnCropX1); x2[i] = MAX(CropX2, data->DrawnCropX2); data->DrawnCropY2 = CropY2; i++; @@ -2970,39 +2959,14 @@ * are valid. Try to preserve them over a rotate forth and back and try to * preserve their geometry. */ -static void adjustment_update_rotation(GtkAdjustment *adj, gpointer user_data) +void resize_canvas(preview_data *data) { - preview_data *data = get_preview_data(adj); - (void)user_data; - - /* Normalize the "unnormalized" value displayed to the user to - * -180 < a <= 180, though we later normalize to an orientation - * and flip plus 0 <= a < 90 rotation for processing. */ - if (data->FreezeDialog) - return; - gboolean FullCrop = CFG->CropX1==0 && CFG->CropX2==data->UF->rotatedWidth && CFG->CropY1==0 && CFG->CropY2==data->UF->rotatedHeight; - int oldFlip = CFG->orientation; - ufraw_unnormalize_rotation(data->UF); - CFG->rotationAngle = gtk_adjustment_get_value(data->RotationAdjustment); - CFG->orientation = data->UnnormalizedOrientation; - ufraw_normalize_rotation(data->UF); - int newFlip = CFG->orientation; - int flip; - for (flip=0; flip<8; flip++) { - CFG->orientation = oldFlip; - ufraw_flip_orientation(data->UF, flip); - if (CFG->orientation == newFlip) - break; - } - CFG->orientation = oldFlip; - ufraw_flip_image(data->UF, flip); - gtk_widget_set_sensitive(data->ResetRotationAdjustment, - CFG->rotationAngle != 0 || - CFG->orientation != CFG->CameraOrientation); + ufraw_get_image_dimensions(data->UF); + if (FullCrop) { if (CFG->LockAspect) { double newAspect = (double)data->UF->rotatedWidth / @@ -3046,15 +3010,47 @@ data->SpotY1 = -1; data->SpotY2 = -1; } - ufraw_invalidate_layer(data->UF, ufraw_transform_phase); - if (CFG->CropX2 > data->UF->rotatedWidth) fix_crop_aspect(data, top_right_cursor, FALSE); else if (CFG->CropY2 > data->UF->rotatedHeight) fix_crop_aspect(data, bottom_left_cursor, FALSE); else update_crop_ranges(data, FALSE); - update_scales(data); +} + +static void adjustment_update_rotation(GtkAdjustment *adj, gpointer user_data) +{ + preview_data *data = get_preview_data(adj); + (void)user_data; + + /* Normalize the "unnormalized" value displayed to the user to + * -180 < a <= 180, though we later normalize to an orientation + * and flip plus 0 <= a < 90 rotation for processing. */ + if (data->FreezeDialog) + return; + + int oldFlip = CFG->orientation; + ufraw_unnormalize_rotation(data->UF); + CFG->rotationAngle = gtk_adjustment_get_value(data->RotationAdjustment); + CFG->orientation = data->UnnormalizedOrientation; + ufraw_normalize_rotation(data->UF); + int newFlip = CFG->orientation; + int flip; + for (flip=0; flip<8; flip++) { + CFG->orientation = oldFlip; + ufraw_flip_orientation(data->UF, flip); + if (CFG->orientation == newFlip) + break; + } + CFG->orientation = oldFlip; + ufraw_flip_image(data->UF, flip); + gtk_widget_set_sensitive(data->ResetRotationAdjustment, + CFG->rotationAngle != 0 || + CFG->orientation != CFG->CameraOrientation); + + ufraw_invalidate_layer(data->UF, ufraw_transform_phase); + resize_canvas(data); + render_preview(data); } void ufraw_image_changed(UFObject *obj, UFEventType type) @@ -3954,7 +3950,8 @@ gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box), TRUE); gdk_window_set_cursor(event_box->window, data->Cursor[spot_cursor]); draw_spot(data, TRUE); - } else if ( page_num==data->PageNumCrop ) { + } else if ( page_num==data->PageNumCrop || + page_num==data->PageNumLensfun) { gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box), TRUE); gdk_window_set_cursor(event_box->window, data->Cursor[crop_cursor]); draw_spot(data, FALSE); @@ -5458,7 +5455,10 @@ #ifdef HAVE_LENSFUN /* Lens correction page */ page = notebook_page_new(notebook, _("Lens correction"), "lens"); + data->PageNumLensfun = gtk_notebook_page_num(notebook, page); lens_fill_interface(data, page); +#else /* HAVE_LENSFUN */ + data->PageNumLensfun = -1; #endif /* HAVE_LENSFUN */ page = notebook_page_new(notebook, _("Base curve"), "base-curve"); @@ -5656,6 +5656,7 @@ while (gtk_events_pending()) gtk_main_iteration(); #endif if ( CFG->WindowMaximized ) { + gtk_widget_set_size_request(scroll, -1, -1); preview_progress_disable(data); while (gtk_events_pending()) gtk_main_iteration(); // scroll widget is allocated size only after gtk_widget_show_all() @@ -5701,6 +5702,7 @@ } else { CFG->size = 0; } + ufraw_invalidate_layer(data->UF, ufraw_first_phase); /* Save initial WB data for the sake of "Reset WB" */ UFObject *Image = CFG->ufobject; Index: ufraw.h =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw.h,v retrieving revision 1.145 retrieving revision 1.146 diff -u -d -r1.145 -r1.146 --- ufraw.h 30 Jan 2010 00:48:52 -0000 1.145 +++ ufraw.h 5 Feb 2010 23:22:15 -0000 1.146 @@ -380,6 +380,8 @@ void ufraw_normalize_rotation(ufraw_data *uf); void ufraw_unnormalize_rotation(ufraw_data *uf); void ufraw_get_image_dimensions(ufraw_data *uf); +/* Get scaled crop coordinates in final image coordinates */ +void ufraw_get_scaled_crop(ufraw_data *uf, UFRectangle *crop); UFRectangle ufraw_image_get_subarea_rectangle(ufraw_image_data *img, unsigned saidx); @@ -465,10 +467,9 @@ /* prototype for functions in ufraw_writer.c */ int ufraw_write_image(ufraw_data *uf); void ufraw_write_image_data( - ufraw_data *uf, - void * volatile out, - int width, int height, int left, int top, int bitDepth, int grayscaleMode, - int (*row_writer) (ufraw_data *, void * volatile, void *, int, int, int, int, int)); + ufraw_data *uf, void * volatile out, + const UFRectangle *Crop, int bitDepth, int grayscaleMode, + int (*row_writer)(ufraw_data *, void * volatile, void *, int, int, int, int, int)); /* prototype for functions in ufraw_delete.c */ long ufraw_delete(void *widget, ufraw_data *uf); Index: ufraw-gimp.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw-gimp.c,v retrieving revision 1.61 retrieving revision 1.62 diff -u -d -r1.61 -r1.62 --- ufraw-gimp.c 23 Jan 2010 05:00:58 -0000 1.61 +++ ufraw-gimp.c 5 Feb 2010 23:22:15 -0000 1.62 @@ -309,7 +309,8 @@ GimpDrawable *drawable; GimpPixelRgn pixel_region; gint32 layer; - int height, width, top, left, depth, tile_height, row, nrows; + UFRectangle Crop; + int depth, tile_height, row, nrows; (void)widget; uf->gimpImage = -1; @@ -317,21 +318,15 @@ if (uf->conf->embeddedImage) { if (ufraw_convert_embedded(uf)!=UFRAW_SUCCESS) return UFRAW_ERROR; - height = uf->thumb.height; - width = uf->thumb.width; - top = 0; - left = 0; + Crop.height = uf->thumb.height; + Crop.width = uf->thumb.width; + Crop.y = 0; + Crop.x = 0; depth = 3; } else { if (ufraw_convert_image(uf)!=UFRAW_SUCCESS) return UFRAW_ERROR; - ufraw_image_data *FirstImage = &uf->Images[ufraw_first_phase]; - height = (uf->conf->CropY2 - uf->conf->CropY1) - * FirstImage->height / uf->rotatedHeight; - width = (uf->conf->CropX2 - uf->conf->CropX1) - * FirstImage->width / uf->rotatedWidth; - top = uf->conf->CropY1 * FirstImage->height / uf->rotatedHeight; - left = uf->conf->CropX1 * FirstImage->width / uf->rotatedWidth; + ufraw_get_scaled_crop(uf, &Crop); #ifdef UFRAW_CINEPAINT if ( uf->conf->profile[out_profile] [uf->conf->profileIndex[out_profile]].BitDepth==16 ) @@ -342,7 +337,7 @@ depth = 3; #endif } - uf->gimpImage = gimp_image_new(width, height, + uf->gimpImage = gimp_image_new(Crop.width, Crop.height, depth==3 ? GIMP_RGB : U16_RGB ); if (uf->gimpImage== -1) { ufraw_message(UFRAW_ERROR, _("Can't allocate new image.")); @@ -351,8 +346,8 @@ gimp_image_set_filename(uf->gimpImage, uf->filename); /* Create the "background" layer to hold the image... */ - layer = gimp_layer_new(uf->gimpImage, _("Background"), width, - height, depth==3 ? GIMP_RGB_IMAGE : U16_RGB_IMAGE, + layer = gimp_layer_new(uf->gimpImage, _("Background"), Crop.width, + Crop.height, depth==3 ? GIMP_RGB_IMAGE : U16_RGB_IMAGE, 100.0, GIMP_NORMAL_MODE); gimp_image_add_layer(uf->gimpImage, layer, 0); @@ -363,14 +358,14 @@ tile_height = gimp_tile_height(); if (uf->conf->embeddedImage) { - for (row = 0; row < height; row += tile_height) { - nrows = MIN(height-row, tile_height); + for (row = 0; row < Crop.height; row += tile_height) { + nrows = MIN(Crop.height-row, tile_height); gimp_pixel_rgn_set_rect(&pixel_region, - uf->thumb.buffer+3*row*width, 0, row, width, nrows); + uf->thumb.buffer+3*row*Crop.width, 0, row, Crop.width, nrows); } } else { - ufraw_write_image_data(uf, &pixel_region, width, height, left, top, - depth==3 ? 8 : 16, 0, gimp_row_writer); + ufraw_write_image_data(uf, &pixel_region, &Crop, depth==3 ? 8 : 16, 0, + gimp_row_writer); } gimp_drawable_flush(drawable); gimp_drawable_detach(drawable); Index: ufraw_ufraw.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw_ufraw.c,v retrieving revision 1.233 retrieving revision 1.234 diff -u -d -r1.233 -r1.234 --- ufraw_ufraw.c 30 Jan 2010 00:48:52 -0000 1.233 +++ ufraw_ufraw.c 5 Feb 2010 23:22:16 -0000 1.234 @@ -47,7 +47,6 @@ static void ufraw_convert_image_first(ufraw_data *uf, UFRawPhase phase); static void ufraw_convert_image_transform(ufraw_data *uf, ufraw_image_data *img, ufraw_image_data *outimg, UFRectangle *area); -static void ufraw_prepare_transform(ufraw_data *uf); static void ufraw_convert_prepare_first_buffer(ufraw_data *uf, ufraw_image_data *img); static void ufraw_convert_prepare_transform_buffer(ufraw_data *uf, @@ -352,12 +351,7 @@ dcraw_image_dimensions(uf->raw, uf->conf->orientation, 1, &uf->initialHeight, &uf->initialWidth); - // update rotated dimensions - double rotationRadians = (uf->conf->rotationAngle * 2 * M_PI) / 360; - uf->rotatedWidth = ceil((uf->initialHeight * sin(rotationRadians)) - + (uf->initialWidth * cos(rotationRadians))); - uf->rotatedHeight = ceil((uf->initialWidth * sin(rotationRadians)) - + (uf->initialHeight * cos(rotationRadians))); + ufraw_get_image(uf, ufraw_transform_phase, FALSE); if (uf->conf->CropX1 < 0) uf->conf->CropX1 = 0; if (uf->conf->CropY1 < 0) uf->conf->CropY1 = 0; @@ -365,6 +359,21 @@ if (uf->conf->CropY2 < 0) uf->conf->CropY2 = uf->rotatedHeight; } +/* Get scaled crop coordinates in final image coordinates */ +void ufraw_get_scaled_crop(ufraw_data *uf, UFRectangle *crop) +{ + ufraw_image_data *img = ufraw_get_image(uf, ufraw_transform_phase, FALSE); + + float scale_x = ((float)img->width) / uf->rotatedWidth; + float scale_y = ((float)img->height) / uf->rotatedHeight; + crop->x = MAX(floor(uf->conf->CropX1 * scale_x), 0); + int x2 = MIN(ceil(uf->conf->CropX2 * scale_x), img->width); + crop->width = x2 - crop->x; + crop->y = MAX(floor(uf->conf->CropY1 * scale_y), 0); + int y2 = MIN(ceil(uf->conf->CropY2 * scale_y), img->height); + crop->height = y2 - crop->y; +} + int ufraw_config(ufraw_data *uf, conf_data *rc, conf_data *conf, conf_data *cmd) { int status; @@ -768,14 +777,14 @@ ufraw_convert_image_first(uf, ufraw_first_phase); UFRectangle area = { 0, 0, img->width, img->height }; + // prepare_transform has to be called before applying vignetting + ufraw_image_data *img2 = &uf->Images[ufraw_transform_phase]; + ufraw_convert_prepare_transform_buffer(uf, img2, img->width, img->height); #ifdef HAVE_LENSFUN - ufraw_prepare_transform(uf); if (uf->modifier != NULL) { ufraw_convert_image_vignetting(uf, img, &area); } #endif - ufraw_image_data *img2 = &uf->Images[ufraw_transform_phase]; - ufraw_convert_prepare_transform_buffer(uf, img2, img->width, img->height); if (img2->buffer != NULL) { area.width = img2->width; area.height = img2->height; @@ -808,15 +817,23 @@ float sine = sin(uf->conf->rotationAngle * 2 * M_PI / 360); float cosine = cos(uf->conf->rotationAngle * 2 * M_PI / 360); - int x, y, c; - + // If we rotate around the center: + // srcX = (X-outimg->width/2)*cosine + (Y-outimg->height/2)*sine; + // srcY = -(X-outimg->width/2)*sine + (Y-outimg->height/2)*cosine; + // Then the base offset is: + // baseX = img->width/2; + // baseY = img->height/2; + // Since we rotate around the top-left corner, the base offset is: + float baseX = img->width/2 - outimg->width/2*cosine - outimg->height/2*sine; + float baseY = img->height/2 + outimg->width/2*sine - outimg->height/2*cosine; #ifdef HAVE_LENSFUN gboolean applyLF = uf->modifier != NULL && (uf->modFlags & UF_LF_TRANSFORM); #endif + int x, y, c; for (y = area->y; y < area->y + area->height; y++) { guint8 *cur0 = outimg->buffer + y * outimg->rowstride; - float srcX0 = y*sine - img->height*sine*cosine; - float srcY0 = y*cosine + img->height*sine*sine; + float srcX0 = y*sine + baseX; + float srcY0 = y*cosine + baseY; for (x = area->x; x < area->x + area->width; x++) { guint16 *cur = (guint16 *)(cur0 + x * outimg->depth); float srcX = srcX0 + x*cosine; @@ -1365,10 +1382,46 @@ } } +static void ufraw_convert_prepare_transform(ufraw_data *uf, + int width, int height, gboolean reverse) +{ +#ifdef HAVE_LENSFUN + conf_data *conf = uf->conf; + if (uf->modifier != NULL) + lf_modifier_destroy(uf->modifier); + uf->modifier = NULL; + + if (conf->camera == NULL || conf->lens == NULL) + return; + + uf->modifier = lf_modifier_new(conf->lens, conf->camera->CropFactor, + width, height); + if (uf->modifier == NULL) + return; + + float real_scale = pow(2.0, conf->lens_scale); + uf->modFlags = lf_modifier_initialize(uf->modifier, conf->lens, + LF_PF_U16, conf->focal_len, conf->aperture, conf->subject_distance, + real_scale, conf->cur_lens_type, + UF_LF_TRANSFORM | LF_MODIFY_VIGNETTING, reverse); + if ((uf->modFlags & UF_LF_ALL) == 0) { + lf_modifier_destroy(uf->modifier); + uf->modifier = NULL; + } +#else /* HAVE_LENSFUN */ + (void)uf; + (void)width; + (void)height; + (void)reverse; +#endif /* HAVE_LENSFUN */ +} + static void ufraw_convert_prepare_transform_buffer(ufraw_data *uf, ufraw_image_data *img, int width, int height) { - ufraw_prepare_transform(uf); + const int iWidth = uf->initialWidth; + const int iHeight = uf->initialHeight; + ufraw_convert_prepare_transform(uf, iWidth, iHeight, TRUE); #ifdef HAVE_LENSFUN if (uf->conf->rotationAngle == 0 && (uf->modifier == NULL || !(uf->modFlags & UF_LF_TRANSFORM))) @@ -1380,15 +1433,55 @@ img->buffer = NULL; img->width = width; img->height = height; - } else { - double sine = sin(uf->conf->rotationAngle * 2 * M_PI / 360); - double cosine = cos(uf->conf->rotationAngle * 2 * M_PI / 360); - int newWidth = ceil((height * sine) + (width * cosine)); - int newHeight = ceil((width * sine) + (height * cosine)); - width = newWidth; - height = newHeight; - ufraw_image_init(img, width, height, 8); + // We still need the transform for vignetting + ufraw_convert_prepare_transform(uf, width, height, FALSE); + uf->rotatedWidth = iWidth; + uf->rotatedHeight = iHeight; + return; } + const float sine = sin(uf->conf->rotationAngle * 2 * M_PI / 360); + const float cosine = cos(uf->conf->rotationAngle * 2 * M_PI / 360); + const float midX = iWidth/2.0 - 0.5; + const float midY = iHeight/2.0 - 0.5; +#ifdef HAVE_LENSFUN + gboolean applyLF = uf->modifier != NULL && (uf->modFlags & UF_LF_TRANSFORM); +#endif + float maxX = 0, maxY = 0; + int i; + for (i = 0; i < iWidth + iHeight - 1; i++) { + int x, y; + if (i < iWidth) { // Trace the left border of the image + x = i; + y = 0; + } else { // Trace the bottom border of the image + x = iWidth - 1; + y = i - iWidth + 1; + } + float buff[2]; +#ifdef HAVE_LENSFUN + if (applyLF) { + lf_modifier_apply_geometry_distortion(uf->modifier, + x, y, 1, 1, buff); + } else { + buff[0] = x; + buff[1] = y; + } +#else + buff[0] = x; + buff[1] = y; +#endif + float srcX = (buff[0]-midX)*cosine - (buff[1]-midY)*sine; + float srcY = (buff[0]-midX)*sine + (buff[1]-midY)*cosine; + maxX = MAX(maxX, fabs(srcX)); + maxY = MAX(maxY, fabs(srcY)); + } + // Do not allow increasing canvas size by more than a factor of 2 + uf->rotatedWidth = MIN(ceil(2*maxX), 2*iWidth); + uf->rotatedHeight = MIN(ceil(2*maxY), 2*iHeight); + int newWidth = uf->rotatedWidth * width / iWidth; + int newHeight = uf->rotatedHeight * height / iHeight; + ufraw_image_init(img, newWidth, newHeight, 8); + ufraw_convert_prepare_transform(uf, width, height, FALSE); } /* @@ -1463,38 +1556,6 @@ } #endif -static void ufraw_prepare_transform(ufraw_data *uf) -{ -#ifdef HAVE_LENSFUN - ufraw_image_data *img = &uf->Images[ufraw_first_phase]; - conf_data *conf = uf->conf; - - if (uf->modifier != NULL) - lf_modifier_destroy(uf->modifier); - uf->modifier = NULL; - - if (conf->camera == NULL || conf->lens == NULL) - return; - - uf->modifier = lf_modifier_new(conf->lens, conf->camera->CropFactor, - img->width, img->height); - if (uf->modifier == NULL) - return; - - float real_scale = pow(2.0, conf->lens_scale); - uf->modFlags = lf_modifier_initialize(uf->modifier, conf->lens, - LF_PF_U16, conf->focal_len, conf->aperture, conf->subject_distance, - real_scale, conf->cur_lens_type, - UF_LF_TRANSFORM | LF_MODIFY_VIGNETTING, FALSE); - if ((uf->modFlags & UF_LF_ALL) == 0) { - lf_modifier_destroy(uf->modifier); - uf->modifier = NULL; - } -#else /* HAVE_LENSFUN */ - (void)uf; -#endif /* HAVE_LENSFUN */ -} - /* * This function is very permissive in accepting NULL pointers but it does * so to make it easy to call this function: consider it documentation with Index: ufraw_ui.h =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw_ui.h,v retrieving revision 1.34 retrieving revision 1.35 diff -u -d -r1.34 -r1.35 --- ufraw_ui.h 31 Jan 2010 08:23:27 -0000 1.34 +++ ufraw_ui.h 5 Feb 2010 23:22:16 -0000 1.35 @@ -162,6 +162,7 @@ int PageNum; int PageNumSpot; int PageNumGray; + int PageNumLensfun; int PageNumLightness; int PageNumCrop; int HisMinHeight; @@ -195,6 +196,8 @@ preview_data *get_preview_data (void *object); +void resize_canvas(preview_data *data); + void lens_fill_interface (preview_data *data, GtkWidget *page); GtkWidget *table_with_frame (GtkWidget *box, char *label, gboolean expand); ------------------------------------------------------------------------------ The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away. http://p.sf.net/sfu/theplanet-com _______________________________________________ ufraw-cvs mailing list ufraw-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ufraw-cvs