> Date: Thu, 9 Jul 2009 08:10:52 +0200
> From: [email protected]
> To: [email protected]
> Subject: [UFRaw-Devel] preview and writer fix for image rotation.
>
> The patch below shows image rotation (not just flipping) in the preview
> window of ufraw. The only way to specify a rotation is still to modify the
> ID file but at least the preview window is now showing it correctly. There
> are a couple of ways to make this accessible from within the GUI, for
> example let the user draw a line on the horizon in the image but I'll
> leave that for someone else.
>
> The preview code contains lots of references to the initial width,height
> instead of the rotated width,height but in order to keep the patch more
> readable _for_now_ this has been fixed by a #define instead of fixing
> it by search-and-replace.
>
> A cropping bug for rotated images has been fixed in the writer too.
>
I have attached a version of the patch with all the initial{Heigth,Width} ->
rotated{Heigth,Width} conversions done.
One problem I have found with the patch is that it breaks rotation when lensfun
is used. It is easy to reproduce:
1. Build UFRaw with lensfun support and this patch applied.
2. Load an image file and rotate 90 deg.
This has to be fixed before it can be included into UFRaw.
Regards,
Niels Kristian
_________________________________________________________________
Nej, det er ikke svært at samle alle vennerne fra Hotmail, Myspace og Facebook
på Messenger. Læs mere her
http://www.microsoft.com/danmark/windows/windowslive/import-friends/
diff -urN ufraw-0.16cvs/ufraw.h ufraw/ufraw.h
--- ufraw-0.16cvs/ufraw.h 2009-07-08 07:46:29.000000000 +0200
+++ ufraw/ufraw.h 2009-07-10 07:06:29.000000000 +0200
@@ -319,6 +319,7 @@
void ufraw_auto_curve(ufraw_data *uf);
void ufraw_rotate_row(image_data *image, void *pixbuf, double angle,
int bitDepth, int row, int offset, int width);
+void ufraw_rotate_image_buffer(ufraw_image_data *img, double angle);
void ufraw_img_get_subarea_coord (ufraw_image_data *img, unsigned saidx,
int *x, int *y, int *w, int *h);
diff -urN ufraw-0.16cvs/ufraw_preview.c ufraw/ufraw_preview.c
--- ufraw-0.16cvs/ufraw_preview.c 2009-07-08 07:46:29.000000000 +0200
+++ ufraw/ufraw_preview.c 2009-07-10 07:34:53.000000000 +0200
@@ -610,8 +610,8 @@
( !CFG->blinkOverUnder || (data->OverUnderTicker & 3) == 3 );
/* Scale crop image coordinates to pixbuf coordinates */
- float scale_x = ((float)pixbufWidth) / data->UF->initialWidth;
- float scale_y = ((float)pixbufHeight) / data->UF->initialHeight;
+ float scale_x = ((float)pixbufWidth) / data->UF->rotatedWidth;
+ float scale_y = ((float)pixbufHeight) / data->UF->rotatedHeight;
int CropY1 = floor (CFG->CropY1 * scale_y);
int CropY2 = ceil (CFG->CropY2 * scale_y);
@@ -682,8 +682,8 @@
int pixbufWidth = gdk_pixbuf_get_width(data->PreviewPixbuf);
int pixbufHeight = gdk_pixbuf_get_height(data->PreviewPixbuf);
if (data->RenderSubArea == -1) {
- float scale_x = ((float)pixbufWidth) / data->UF->initialWidth;
- float scale_y = ((float)pixbufHeight) / data->UF->initialHeight;
+ float scale_x = ((float)pixbufWidth) / data->UF->rotatedWidth;
+ float scale_y = ((float)pixbufHeight) / data->UF->rotatedHeight;
/* Set the area to redraw based on the crop rectangle and view port. */
#ifdef HAVE_GTKIMAGEVIEW
GdkRectangle viewRect;
@@ -791,11 +791,11 @@
char progressText[max_name];
if (CFG->Scale==0)
g_snprintf(progressText, max_name, _("size %dx%d, zoom %2.f%%"),
- data->UF->initialWidth, data->UF->initialHeight,
+ data->UF->rotatedWidth, data->UF->rotatedHeight,
CFG->Zoom);
else
g_snprintf(progressText, max_name, _("size %dx%d, scale 1/%d"),
- data->UF->initialWidth, data->UF->initialHeight,
+ data->UF->rotatedWidth, data->UF->rotatedHeight,
CFG->Scale);
gtk_progress_bar_set_text(data->ProgressBar, progressText);
gtk_progress_bar_set_fraction(data->ProgressBar, 0);
@@ -1193,8 +1193,8 @@
if (data->FreezeDialog) return FALSE;
if (data->SpotX1<0) return FALSE;
- if ( data->SpotX1>=data->UF->initialWidth ||
- data->SpotY1>=data->UF->initialHeight ) return FALSE;
+ if ( data->SpotX1>=data->UF->rotatedWidth ||
+ data->SpotY1>=data->UF->rotatedHeight ) return FALSE;
int width = data->UF->Images[ufraw_develop_phase].width;
int height = data->UF->Images[ufraw_develop_phase].height;
int outDepth = data->UF->Images[ufraw_develop_phase].depth;
@@ -1204,14 +1204,14 @@
/* We assume that first_phase and final_phase buffer sizes are the same. */
/* Scale image coordinates to Images[ufraw_develop_phase] coordinates */
int spotHeight = abs(data->SpotY1 - data->SpotY2)
- * height / data->UF->initialHeight + 1;
+ * height / data->UF->rotatedHeight + 1;
int spotStartY = MIN(data->SpotY1, data->SpotY2)
- * height / data->UF->initialHeight;
+ * height / data->UF->rotatedHeight;
if (spotHeight+spotStartY>height) spotStartY = height - spotHeight;
int spotWidth = abs(data->SpotX1 - data->SpotX2)
- * width / data->UF->initialWidth + 1;
+ * width / data->UF->rotatedWidth + 1;
int spotStartX = MIN(data->SpotX1, data->SpotX2)
- * width / data->UF->initialWidth;
+ * width / data->UF->rotatedWidth;
if (spotWidth+spotStartX>width) spotStartX = width - spotWidth;
guint64 rawSum[4], outSum[3];
int c, y, x;
@@ -1287,13 +1287,13 @@
data->SpotDraw = draw;
/* Scale spot image coordinates to pixbuf coordinates */
int SpotY1 = MAX(MIN(data->SpotY1, data->SpotY2)
- * height / data->UF->initialHeight - 1, 0);
+ * height / data->UF->rotatedHeight - 1, 0);
int SpotY2 = MIN(MAX(data->SpotY1, data->SpotY2)
- * height / data->UF->initialHeight + 1, height-1);
+ * height / data->UF->rotatedHeight + 1, height-1);
int SpotX1 = MAX(MIN(data->SpotX1, data->SpotX2)
- * width / data->UF->initialWidth - 1, 0);
+ * width / data->UF->rotatedWidth - 1, 0);
int SpotX2 = MIN(MAX(data->SpotX1, data->SpotX2)
- * width / data->UF->initialWidth + 1, width-1);
+ * width / data->UF->rotatedWidth + 1, width-1);
preview_draw_area(data, SpotX1, SpotY1, SpotX2-SpotX1+1, 1);
preview_draw_area(data, SpotX1, SpotY2, SpotX2-SpotX1+1, 1);
preview_draw_area(data, SpotX1, SpotY1, 1, SpotY2-SpotY1+1);
@@ -1488,13 +1488,13 @@
height = gdk_pixbuf_get_height(data->PreviewPixbuf);
/* Scale image coordinates to pixbuf coordinates */
spotHeight = abs(data->SpotY1 - data->SpotY2)
- * height / data->UF->initialHeight + 1;
+ * height / data->UF->rotatedHeight + 1;
spotStartY = MIN(data->SpotY1, data->SpotY2)
- *height / data->UF->initialHeight;
+ *height / data->UF->rotatedHeight;
spotWidth = abs(data->SpotX1 - data->SpotX2)
- * width / data->UF->initialWidth + 1;
+ * width / data->UF->rotatedWidth + 1;
spotStartX = MIN(data->SpotX1, data->SpotX2)
- * width / data->UF->initialWidth;
+ * width / data->UF->rotatedWidth;
ufraw_image_data *image = &data->UF->Images[ufraw_first_phase];
for (c=0; c<4; c++) rgb[c] = 0;
@@ -1562,8 +1562,8 @@
if ( *y<0 ) *y = 0;
if ( *y>height ) *y = height;
/* Scale pixbuf coordinates to image coordinates */
- *x = *x * data->UF->initialWidth / width;
- *y = *y * data->UF->initialHeight / height;
+ *x = *x * data->UF->rotatedWidth / width;
+ *y = *y * data->UF->rotatedHeight / height;
}
static gboolean preview_button_press_event(GtkWidget *event_box,
@@ -1614,9 +1614,9 @@
int y = event->y;
int pixbufHeight = gdk_pixbuf_get_height(data->PreviewPixbuf);
int pixbufWidth = gdk_pixbuf_get_width(data->PreviewPixbuf);
- int sideSizeX = MIN(16 * data->UF->initialWidth / pixbufWidth,
+ int sideSizeX = MIN(16 * data->UF->rotatedWidth / pixbufWidth,
(CFG->CropX2-CFG->CropX1)/3);
- int sideSizeY = MIN(16 * data->UF->initialHeight / pixbufHeight,
+ int sideSizeY = MIN(16 * data->UF->rotatedHeight / pixbufHeight,
(CFG->CropY2-CFG->CropY1)/3);
if ( (event->state&GDK_BUTTON1_MASK)==0 ) {
@@ -1676,16 +1676,16 @@
int d = x - data->OldMouseX;
if (CFG->CropX1 + d < 0)
d = -CFG->CropX1;
- if (CFG->CropX2 + d >= data->UF->initialWidth)
- d = data->UF->initialWidth - CFG->CropX2;
+ if (CFG->CropX2 + d >= data->UF->rotatedWidth)
+ d = data->UF->rotatedWidth - CFG->CropX2;
CFG->CropX1 += d;
CFG->CropX2 += d;
d = y - data->OldMouseY;
if (CFG->CropY1 + d < 0)
d = -CFG->CropY1;
- if (CFG->CropY2 + d >= data->UF->initialHeight)
- d = data->UF->initialHeight - CFG->CropY2;
+ if (CFG->CropY2 + d >= data->UF->rotatedHeight)
+ d = data->UF->rotatedHeight - CFG->CropY2;
CFG->CropY1 += d;
CFG->CropY2 += d;
}
@@ -1758,6 +1758,7 @@
preview_invalidate_layer (data, ufraw_denoise_phase);
ufraw_convert_image_init(data->UF);
ufraw_convert_image_first_phase(data->UF, FALSE);
+ ufraw_rotate_image_buffer(&data->UF->Images[ufraw_first_phase], data->UF->conf->rotationAngle);
CFG->shrink = shrinkSave;
CFG->size = sizeSave;
}
@@ -1812,9 +1813,9 @@
gtk_spin_button_set_range(data->CropX1Spin, 0, CropX2-1);
gtk_spin_button_set_range(data->CropY1Spin, 0, CropY2-1);
gtk_spin_button_set_range(data->CropX2Spin,
- CropX1+1, data->UF->initialWidth);
+ CropX1+1, data->UF->rotatedWidth);
gtk_spin_button_set_range(data->CropY2Spin,
- CropY1+1, data->UF->initialHeight);
+ CropY1+1, data->UF->rotatedHeight);
gtk_adjustment_set_value(data->CropX1Adjustment, CropX1);
gtk_adjustment_set_value(data->CropY1Adjustment, CropY1);
@@ -1825,8 +1826,8 @@
int pixbufHeight = gdk_pixbuf_get_height(data->PreviewPixbuf);
int pixbufWidth = gdk_pixbuf_get_width(data->PreviewPixbuf);
- float scale_x = ((float)pixbufWidth) / data->UF->initialWidth;
- float scale_y = ((float)pixbufHeight) / data->UF->initialHeight;
+ float scale_x = ((float)pixbufWidth) / data->UF->rotatedWidth;
+ float scale_y = ((float)pixbufHeight) / data->UF->rotatedHeight;
CropX1 = floor (CropX1 * scale_x);
CropX2 = MIN(ceil(CropX2 * scale_x), pixbufWidth-1);
@@ -1884,9 +1885,9 @@
CFG->CropX1 = 0;
CFG->CropY1 = 0;
- CFG->CropX2 = data->UF->initialWidth;
- CFG->CropY2 = data->UF->initialHeight;
- data->AspectRatio = ((float)data->UF->initialWidth) / data->UF->initialHeight;
+ CFG->CropX2 = data->UF->rotatedWidth;
+ CFG->CropY2 = data->UF->rotatedHeight;
+ data->AspectRatio = ((float)data->UF->rotatedWidth) / data->UF->rotatedHeight;
refresh_aspect(data);
set_new_aspect(data);
@@ -1947,8 +1948,8 @@
gtk_widget_get_ancestor(data->PreviewWidget, GTK_TYPE_IMAGE_SCROLL_WIN);
int previewWidth = preview->allocation.width;
int previewHeight = preview->allocation.height;
- double wScale = (double)data->UF->initialWidth / previewWidth;
- double hScale = (double)data->UF->initialHeight / previewHeight;
+ double wScale = (double)data->UF->rotatedWidth / previewWidth;
+ double hScale = (double)data->UF->rotatedHeight / previewHeight;
CFG->Zoom = 100.0/LIM(MAX(wScale, hScale), min_scale, max_scale);
CFG->Scale = 0;
if (prev_zoom != CFG->Zoom) {
@@ -1984,28 +1985,25 @@
if (flip & 1) {
temp = CFG->CropX1;
- CFG->CropX1 = data->UF->initialWidth - CFG->CropX2;
- CFG->CropX2 = data->UF->initialWidth - temp;
+ CFG->CropX1 = data->UF->rotatedWidth - CFG->CropX2;
+ CFG->CropX2 = data->UF->rotatedWidth - temp;
if ( data->SpotX1>=0 ) {
temp = data->SpotX1;
- data->SpotX1 = data->UF->initialWidth - data->SpotX2;
- data->SpotX2 = data->UF->initialWidth - temp;
+ data->SpotX1 = data->UF->rotatedWidth - data->SpotX2;
+ data->SpotX2 = data->UF->rotatedWidth - temp;
}
}
if (flip & 2) {
temp = CFG->CropY1;
- CFG->CropY1 = data->UF->initialHeight - CFG->CropY2;
- CFG->CropY2 = data->UF->initialHeight - temp;
+ CFG->CropY1 = data->UF->rotatedHeight - CFG->CropY2;
+ CFG->CropY2 = data->UF->rotatedHeight - temp;
if ( data->SpotX1>=0 ) {
temp = data->SpotY1;
- data->SpotY1 = data->UF->initialHeight - data->SpotY2;
- data->SpotY2 = data->UF->initialHeight - temp;
+ data->SpotY1 = data->UF->rotatedHeight - data->SpotY2;
+ data->SpotY2 = data->UF->rotatedHeight - temp;
}
}
if (flip & 4) {
- temp = data->UF->initialWidth;
- data->UF->initialWidth = data->UF->initialHeight;
- data->UF->initialHeight = temp;
temp = data->UF->rotatedWidth;
data->UF->rotatedWidth = data->UF->rotatedHeight;
data->UF->rotatedHeight = temp;
@@ -2096,18 +2094,18 @@
CFG->CropY2 = CFG->CropY1;
if (CFG->CropX1 < 0)
CFG->CropX1 = 0;
- if (CFG->CropX2 > data->UF->initialWidth)
- CFG->CropX2 = data->UF->initialWidth;
+ if (CFG->CropX2 > data->UF->rotatedWidth)
+ CFG->CropX2 = data->UF->rotatedWidth;
if (CFG->CropY1 < 0)
CFG->CropY1 = 0;
- if (CFG->CropY2 > data->UF->initialHeight)
- CFG->CropY2 = data->UF->initialHeight;
+ if (CFG->CropY2 > data->UF->rotatedHeight)
+ CFG->CropY2 = data->UF->rotatedHeight;
if (!CFG->LockAspect)
return;
if (data->AspectRatio == 0)
- aspect = ((float)data->UF->initialWidth) / data->UF->initialHeight;
+ aspect = ((float)data->UF->rotatedWidth) / data->UF->rotatedHeight;
else
aspect = data->AspectRatio;
@@ -2123,8 +2121,8 @@
int fix_dx = 0;
if (dy > cy)
dy = cy, fix_dx++;
- if (cy + dy > data->UF->initialHeight)
- dy = data->UF->initialHeight - cy, fix_dx++;
+ if (cy + dy > data->UF->rotatedHeight)
+ dy = data->UF->rotatedHeight - cy, fix_dx++;
if (fix_dx)
{
float dx = rint (dy * 2.0 * aspect);
@@ -2147,8 +2145,8 @@
int fix_dy = 0;
if (dx > cx)
dx = cx, fix_dy++;
- if (cx + dx > data->UF->initialWidth)
- dx = data->UF->initialWidth - cx, fix_dy++;
+ if (cx + dx > data->UF->rotatedWidth)
+ dx = data->UF->rotatedWidth - cx, fix_dy++;
if (fix_dy)
{
float dy = rint (dx * 2.0 / aspect);
@@ -2184,8 +2182,8 @@
}
else
{
- if (CFG->CropX1 + dx > data->UF->initialWidth)
- dx = data->UF->initialWidth - CFG->CropX1;
+ if (CFG->CropX1 + dx > data->UF->rotatedWidth)
+ dx = data->UF->rotatedWidth - CFG->CropX1;
CFG->CropX2 = CFG->CropX1 + dx;
}
@@ -2203,9 +2201,9 @@
}
else
{
- if (CFG->CropY1 + dy > data->UF->initialHeight)
+ if (CFG->CropY1 + dy > data->UF->rotatedHeight)
{
- dx = (data->UF->initialHeight - CFG->CropY1) * aspect;
+ dx = (data->UF->rotatedHeight - CFG->CropY1) * aspect;
continue;
}
CFG->CropY2 = CFG->CropY1 + dy;
@@ -2248,9 +2246,9 @@
dx = cx;
dy = dx / data->AspectRatio;
}
- if (cx + dx > data->UF->initialWidth)
+ if (cx + dx > data->UF->rotatedWidth)
{
- dx = data->UF->initialWidth - cx;
+ dx = data->UF->rotatedWidth - cx;
dy = dx / data->AspectRatio;
}
@@ -2259,9 +2257,9 @@
dy = cy;
dx = dy * data->AspectRatio;
}
- if (cy + dy > data->UF->initialHeight)
+ if (cy + dy > data->UF->rotatedHeight)
{
- dy = data->UF->initialHeight - cy;
+ dy = data->UF->rotatedHeight - cy;
dx = dy * data->AspectRatio;
}
@@ -4436,7 +4434,7 @@
gtk_table_attach(table, label, 0, 1, 1, 2, 0, 0, 0, 0);
data->CropX1Adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(
- CFG->CropX1, 0, data->UF->initialWidth, 1, 1, 0));
+ CFG->CropX1, 0, data->UF->rotatedWidth, 1, 1, 0));
data->CropX1Spin = GTK_SPIN_BUTTON(gtk_spin_button_new(
data->CropX1Adjustment, 1, 0));
g_object_set_data(G_OBJECT(data->CropX1Adjustment),
@@ -4450,7 +4448,7 @@
gtk_table_attach(table, label, 1, 2, 0, 1, 0, 0, 0, 0);
data->CropY1Adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(
- CFG->CropY1, 0, data->UF->initialHeight, 1, 1, 0));
+ CFG->CropY1, 0, data->UF->rotatedHeight, 1, 1, 0));
data->CropY1Spin = GTK_SPIN_BUTTON(gtk_spin_button_new(
data->CropY1Adjustment, 1, 0));
g_object_set_data(G_OBJECT(data->CropY1Adjustment),
@@ -4464,7 +4462,7 @@
gtk_table_attach(table, label, 2, 3, 1, 2, 0, 0, 0, 0);
data->CropX2Adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(
- CFG->CropX2, 0, data->UF->initialWidth, 1, 1, 0));
+ CFG->CropX2, 0, data->UF->rotatedWidth, 1, 1, 0));
data->CropX2Spin = GTK_SPIN_BUTTON(gtk_spin_button_new(
data->CropX2Adjustment, 1, 0));
g_object_set_data(G_OBJECT(data->CropX2Adjustment),
@@ -4478,7 +4476,7 @@
gtk_table_attach(table, label, 1, 2, 2, 3, 0, 0, 0, 0);
data->CropY2Adjustment = GTK_ADJUSTMENT(gtk_adjustment_new(
- CFG->CropY2, 0, data->UF->initialHeight, 1, 1, 0));
+ CFG->CropY2, 0, data->UF->rotatedHeight, 1, 1, 0));
data->CropY2Spin = GTK_SPIN_BUTTON(gtk_spin_button_new(
data->CropY2Adjustment, 1, 0));
g_object_set_data(G_OBJECT(data->CropY2Adjustment),
@@ -4531,7 +4529,7 @@
data->LockAspectButton = GTK_TOGGLE_BUTTON(button);
/* Get initial aspect ratio */
- data->AspectRatio = ((float)data->UF->initialWidth) / data->UF->initialHeight;
+ data->AspectRatio = ((float)data->UF->rotatedWidth) / data->UF->rotatedHeight;
refresh_aspect (data);
/* Size/shrink controls */
@@ -4924,14 +4922,14 @@
gdk_screen_get_monitor_geometry(gdk_screen_get_default(), 0, &screen);
max_preview_width = MIN(def_preview_width, screen.width-416);
max_preview_height = MIN(def_preview_height, screen.height-152);
- CFG->Scale = MAX((uf->initialWidth-1)/max_preview_width,
- (uf->initialHeight-1)/max_preview_height)+1;
+ CFG->Scale = MAX((uf->rotatedWidth-1)/max_preview_width,
+ (uf->rotatedHeight-1)/max_preview_height)+1;
CFG->Scale = MAX(2, CFG->Scale);
CFG->Zoom = 100.0 / CFG->Scale;
// Make preview size a tiny bit larger to prevent rounding errors
// that will cause the scrollbars to appear.
- preview_width = (uf->initialWidth+1) / CFG->Scale;
- preview_height = (uf->initialHeight+1) / CFG->Scale;
+ preview_width = (uf->rotatedWidth+1) / CFG->Scale;
+ preview_height = (uf->rotatedHeight+1) / CFG->Scale;
if (screen.height<=600) {
curveeditorHeight = 192;
data->HisMinHeight = 0;
@@ -5266,12 +5264,12 @@
// scroll widget is allocated size only after gtk_widget_show_all()
int scrollWidth = scroll->allocation.width;
int scrollHeight = scroll->allocation.height;
- double wScale = (double)data->UF->initialWidth / scrollWidth;
- double hScale = (double)data->UF->initialHeight / scrollHeight;
+ double wScale = (double)data->UF->rotatedWidth / scrollWidth;
+ double hScale = (double)data->UF->rotatedHeight / scrollHeight;
CFG->Zoom = 100/MAX(wScale, hScale);
CFG->Scale = 0;
- preview_width = uf->initialWidth * CFG->Zoom/100;
- preview_height = uf->initialHeight * CFG->Zoom/100;
+ preview_width = uf->rotatedWidth * CFG->Zoom/100;
+ preview_height = uf->rotatedHeight * CFG->Zoom/100;
}
// Allocate the preview pixbuf
data->PreviewPixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8,
diff -urN ufraw-0.16cvs/ufraw_ufraw.c ufraw/ufraw_ufraw.c
--- ufraw-0.16cvs/ufraw_ufraw.c 2009-07-07 06:40:10.000000000 +0200
+++ ufraw/ufraw_ufraw.c 2009-07-10 07:22:53.000000000 +0200
@@ -638,7 +638,7 @@
g_free(uf->outputExifBuf);
g_free(uf->image.image);
int i;
- for (i=ufraw_first_phase+1; i<ufraw_phases_num; i++)
+ for (i=ufraw_first_phase; i<ufraw_phases_num; i++)
g_free(uf->Images[i].buffer);
g_free(uf->thumb.buffer);
developer_destroy(uf->developer);
@@ -1011,7 +1011,7 @@
FirstImage->width = uf->image.width;
FirstImage->depth = sizeof(dcraw_image_type);
FirstImage->rowstride = FirstImage->width * FirstImage->depth;
- FirstImage->buffer = (guint8 *)uf->image.image;
+ FirstImage->buffer = g_memdup(uf->image.image, FirstImage->height * FirstImage->rowstride);
FirstImage->valid = 0xffffffff;
return UFRAW_SUCCESS;
@@ -1771,3 +1771,71 @@
}
}
}
+
+/*
+ * Rotate an 8 or 16 bits per color image 0-90 degrees. The output pixel is
+ * calculated as a weighted average of the 4 nearest input pixels.
+ */
+void ufraw_rotate_image_buffer(ufraw_image_data *img, double angle)
+{
+ double sine, cosine, movecol, moverow;
+ int oldwidth, oldheight, oldrowstride;
+ int width, height, depth, rowstride;
+ int col, row, uc, ur, i;
+ float c, r, fc, fr;
+ guint8 *in, *in_00, *in_01, *in_10, *in_11, *out;
+
+ if (!angle)
+ return;
+ sine = sin(angle * 2 * M_PI / 360);
+ cosine = cos(angle * 2 * M_PI / 360);
+ depth = img->depth;
+ oldwidth = img->width;
+ oldheight = img->height;
+ oldrowstride = img->rowstride;
+ width = ceil((oldheight * sine) + (oldwidth * cosine));
+ height = ceil((oldwidth * sine) + (oldheight * cosine));
+ rowstride = width * depth;
+ in = img->buffer;
+ out = g_new0(guint8, height * rowstride);
+ img->buffer = out;
+ img->width = width;
+ img->height = height;
+ img->rowstride = rowstride;
+ movecol = -oldheight * sine * cosine;
+ moverow = oldheight * sine * sine;
+ for (row = 0; row < height; ++row) {
+ for (col = 0; col < width; col++) {
+ // (c,r) are the float input subpixel coordinates. fc,fr are the
+ // weighting factors for integer coordinates (uc,ur)..(uc+1,ur+1)
+ // around (c,r)
+ c = (col * cosine) + (row * sine) + movecol;
+ r = (row * cosine) - (col * sine) + moverow;
+ uc = (int)floor(c);
+ ur = (int)floor(r);
+ if (uc >= 0 && uc + 1 < oldwidth && ur >= 0 && ur + 1 < oldheight) {
+ fc = c - uc;
+ fr = r - ur;
+ in_00 = in + ((ur * oldwidth) + uc) * depth; // (uc,ur)
+ in_01 = in_00 + depth; // (uc+1,ur)
+ in_10 = in_00 + oldrowstride; // (uc,ur+1)
+ in_11 = in_10 + depth; // (uc+1,ur+1)
+ if (depth > 4) {
+ for (i = 0; i < 3; ++i) {
+ ((guint16 *)out)[i] =
+ (((guint16 *)in_00)[i] * (1 - fc) + ((guint16 *)in_01)[i] * fc) * (1 - fr) +
+ (((guint16 *)in_10)[i] * (1 - fc) + ((guint16 *)in_11)[i] * fc) * fr;
+ }
+ } else {
+ for (i = 0; i < 3; ++i) {
+ out[i] =
+ (in_00[i] * (1 - fc) + in_01[i] * fc) * (1 - fr) +
+ (in_10[i] * (1 - fc) + in_11[i] * fc) * fr;
+ }
+ }
+ }
+ out += depth;
+ }
+ }
+ g_free(in);
+}
diff -urN ufraw-0.16cvs/ufraw_writer.c ufraw/ufraw_writer.c
--- ufraw-0.16cvs/ufraw_writer.c 2009-01-13 11:50:34.000000000 +0100
+++ ufraw/ufraw_writer.c 2009-07-10 07:00:21.000000000 +0200
@@ -391,8 +391,8 @@
}
// TODO: error handling
ufraw_convert_image(uf);
- left = uf->conf->CropX1 * uf->image.width / uf->rotatedWidth;
- top = uf->conf->CropY1 * uf->image.height / uf->rotatedHeight;
+ left = uf->conf->CropX1 * uf->image.width / uf->initialWidth;
+ top = uf->conf->CropY1 * uf->image.height / uf->initialHeight;
volatile int BitDepth = uf->conf->profile[out_profile]
[uf->conf->profileIndex[out_profile]].BitDepth;
if ( BitDepth!=16 ) BitDepth = 8;
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge
This is your chance to win up to $100,000 in prizes! For a limited time,
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
ufraw-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ufraw-devel