Rewrote scaling algorithm in Filter.cpp

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5410 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer
2003-11-18 21:45:29 +00:00
parent 19c76de4a0
commit 142491fe30
2 changed files with 0 additions and 275 deletions
-253
View File
@@ -1,253 +0,0 @@
/*
Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
*/
#include "Scale.h"
#include <malloc.h>
#include <Bitmap.h>
typedef struct {
long x_i;
float p;
float p1;
} row_values;
static void
scale_bilinear_8(const BBitmap *src, BBitmap *dest,
const float xFactor, const float yFactor,
volatile bool *running)
{
register long drows, dcols, srows, scols;
register unsigned char *spixptr, *dpixptr, *spix1, *spix2, *dpix;
register unsigned long slb, dlb;
register long i, j;
float p, q, p1, q1;
float xfac, yfac;
float xfac_inv, yfac_inv;
float src_y_f;
long src_y_i, src_x_i;
register unsigned char a, b, c, d;
row_values *r, *rptr;
float x_f;
float result;
// Get values from image
dpix = dpixptr = (unsigned char *)dest->Bits();
spixptr = (unsigned char *)src->Bits();
srows = src->Bounds().IntegerHeight()+1;
scols = src->Bounds().IntegerWidth()+1;
drows = dest->Bounds().IntegerHeight()+1;
dcols = dest->Bounds().IntegerWidth()+1;
slb = src->BytesPerRow();
dlb = dest->BytesPerRow();
// Compute scale factors and inverse scale factors
xfac = xFactor;
yfac = yFactor;
if (xfac < 0.0)
xfac = (float) dcols / (float) scols;
if (yfac < 0.0)
yfac = (float) drows / (float) srows;
xfac_inv = 1.0 / xfac;
yfac_inv = 1.0 / yfac;
// Allocate buffer for storing the values of ma and m1
rptr = r = (row_values *)malloc (sizeof(row_values) * dcols);
// Fill up the buffer once, to be used for each row
for (i=0; i<dcols; i++)
{
x_f = i*xfac_inv;
rptr->x_i = (long)x_f;
rptr->p = x_f - (float) rptr->x_i;
rptr->p1 = 1.0 - rptr->p;
rptr++;
}
// Perform the scaling by inverse mapping from dest to source
// That is, for each point in the destination, find the
// corresponding point in the source.
for (i=0; *running && i<drows-1; i++)
{
src_y_f = i * yfac_inv;
src_y_i = (long) src_y_f;
q = src_y_f - (float)src_y_i;
q1 = 1.0 - q;
spix1 = spixptr + src_y_i*slb;
spix2 = spixptr + (src_y_i+1)*slb;
rptr = r;
for (j =0; j<dcols-1; j++,rptr++)
{
src_x_i = rptr->x_i;
p = rptr->p;
p1 = rptr->p1;
// Get the four corner pixels
a = *(spix1 + src_x_i);
b = *(spix1 + src_x_i + 1);
c = *(spix2 + src_x_i);
d = *(spix2 + src_x_i + 1);
// Compute the interpolated pixel value
result = (((float)8*p1 + (float)b*p)*q1
+ ((float)c*p1 + (float)d*p)*q);
*dpix++ = (unsigned char) result;
}
// Advance to the next destination line
dpix = (dpixptr += dlb);
}
free(r);
}
static void
scale_bilinear_32(const BBitmap *src, BBitmap *dest,
const float xFactor, const float yFactor,
volatile bool *running)
{
register long drows, dcols, srows, scols;
register unsigned long *spixptr, *spix1, *spix2;
register unsigned char *dpixptr, *dpix;
register unsigned long slb, dlb;
register long i, j;
float p, q, p1, q1;
float xfac = xFactor, yfac = yFactor;
float xfac_inv, yfac_inv;
float src_y_f;
long src_y_i, src_x_i;
register unsigned char *a, *b, *c, *d;
row_values *r, *rptr;
float x_f;
float rred, rgreen, rblue;
srows = src->Bounds().IntegerHeight()+1;
scols = src->Bounds().IntegerWidth()+1;
drows = dest->Bounds().IntegerHeight()+1;
dcols = dest->Bounds().IntegerWidth()+1;
if (xFactor < 0.0)
xfac = (float) dcols / (float) scols;
else
dcols = (long) ceil(scols * xfac);
if (yFactor < 0.0)
yfac = (float) drows / (float) srows;
else
drows = (long) ceil(srows * yfac);
// Get values from image
dpixptr = (unsigned char *)dest->Bits();
dpix = (unsigned char *)dpixptr;
spixptr = (unsigned long *)src->Bits();
slb = src->BytesPerRow()/4;
dlb = dest->BytesPerRow();
xfac_inv = 1.0 / xfac;
yfac_inv = 1.0 / yfac;
// Allocate buffer for storing the values of ma and m1
rptr = r = (row_values *)malloc (sizeof(row_values) * dcols);
// Fill up the buffer once, to be used for each row
for (i=0; i<dcols; i++)
{
x_f = i*xfac_inv;
rptr->x_i = (long)x_f;
rptr->p = x_f - (float) rptr->x_i;
rptr->p1 = 1.0 - rptr->p;
rptr++;
}
// Perform the scaling by inverse mapping from dest to source
// That is, for each point in the destination, find the
// corresponding point in the source.
for (i=0; *running && i<drows-1; i++)
{
src_y_f = i * yfac_inv;
src_y_i = (long) src_y_f;
q = src_y_f - (float)src_y_i;
q1 = 1.0 - q;
spix1 = spixptr + src_y_i*slb;
spix2 = spixptr + (src_y_i+1)*slb;
rptr = r;
for (j =0; j<dcols-1; j++,rptr++)
{
src_x_i = rptr->x_i;
p = rptr->p;
p1 = rptr->p1;
// Get the four corner pixels
a = (unsigned char *)(spix1 + src_x_i);
b = (unsigned char *)(spix1 + src_x_i + 1);
c = (unsigned char *)(spix2 + src_x_i);
d = (unsigned char *)(spix2 + src_x_i + 1);
// Compute the interpolated pixel value
rblue = (((float)a[0]*p1 + (float)b[0]*p)*q1
+ ((float)c[0]*p1 + (float)d[0]*p)*q);
rgreen = (((float)a[1]*p1 + (float)b[1]*p)*q1
+ ((float)c[1]*p1 + (float)d[1]*p)*q);
rred = (((float)a[2]*p1 + (float)b[2]*p)*q1
+ ((float)c[2]*p1 + (float)d[2]*p)*q);
dpix[0] = (unsigned char) rblue;
dpix[1] = (unsigned char) rgreen;
dpix[2] = (unsigned char) rred;
dpix += 4;
}
// Advance to the next destination line
dpix = (dpixptr += dlb);
}
free(r);
}
status_t scale(const BBitmap *src, BBitmap *dst,
volatile bool* running,
const float xFactor, const float yFactor,
scale_method scmethod)
{
if (src->ColorSpace() != dst->ColorSpace())
return -1;
switch (scmethod)
{
case IMG_SCALE_BILINEAR:
{
switch (src->ColorSpace())
{
case B_COLOR_8_BIT:
case B_GRAYSCALE_8_BIT:
scale_bilinear_8(src, dst, xFactor, yFactor, running);
break;
case B_RGB32:
case B_RGBA32:
scale_bilinear_32(src, dst, xFactor, yFactor, running);
break;
default: // color space we can't deal with
return -1;
break;
}
}
}
return B_NO_ERROR;
}
-22
View File
@@ -1,22 +0,0 @@
/*
Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
*/
#include <Bitmap.h>
enum scale_method {
IMG_SCALE_BILINEAR = 1
};
class BBitmap;
// Scale an image. It will work in either direction.
// Scaling up or down. Scaling by integer values will be
// most optimal.
status_t scale(const BBitmap *source, BBitmap *dst,
volatile bool *running,
const float xFactor = -1, const float yFactor = -1,
scale_method = IMG_SCALE_BILINEAR);