- scale bilinear (experimental: scaled image is too small by one pixel)
- bug fixes git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5347 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,134 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
// Filter
|
||||||
|
// Written by Michael Pfeiffer
|
||||||
|
//
|
||||||
|
// Filter.cpp
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003 OpenBeOS Project
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included
|
||||||
|
// in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#include <scheduler.h>
|
||||||
|
#include "Filter.h"
|
||||||
|
#include "Scale.h"
|
||||||
|
|
||||||
|
Filter::Filter(BBitmap* image, BMessenger listener, uint32 what)
|
||||||
|
: fListener(listener)
|
||||||
|
, fWhat(what)
|
||||||
|
, fIsRunning(false)
|
||||||
|
, fWorkerThread(-1)
|
||||||
|
, fSrcImage(image)
|
||||||
|
, fDestImage(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Filter::~Filter()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
delete fDestImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
BBitmap*
|
||||||
|
Filter::GetBitmap()
|
||||||
|
{
|
||||||
|
if (fDestImage == NULL) {
|
||||||
|
fDestImage = CreateDestImage(fSrcImage);
|
||||||
|
}
|
||||||
|
return fDestImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Filter::worker_thread(void* data)
|
||||||
|
{
|
||||||
|
Filter* filter = (Filter*)data;
|
||||||
|
filter->Run();
|
||||||
|
if (filter->fIsRunning) {
|
||||||
|
filter->fListener.SendMessage(filter->fWhat);
|
||||||
|
filter->fIsRunning = false;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Filter::Start()
|
||||||
|
{
|
||||||
|
GetBitmap();
|
||||||
|
if (fSrcImage == NULL || fDestImage == NULL) return;
|
||||||
|
fWorkerThread = spawn_thread(worker_thread, "filter", suggest_thread_priority(B_STATUS_RENDERING), this);
|
||||||
|
if (fWorkerThread >= 0) {
|
||||||
|
fIsRunning = true;
|
||||||
|
resume_thread(fWorkerThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Filter::Stop()
|
||||||
|
{
|
||||||
|
if (fIsRunning) {
|
||||||
|
fIsRunning = false;
|
||||||
|
status_t st;
|
||||||
|
wait_for_thread(fWorkerThread, &st);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Filter::IsRunning() const
|
||||||
|
{
|
||||||
|
return fIsRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
BBitmap*
|
||||||
|
Filter::GetSrcImage()
|
||||||
|
{
|
||||||
|
return fSrcImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
BBitmap*
|
||||||
|
Filter::GetDestImage()
|
||||||
|
{
|
||||||
|
return fDestImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaler::Scaler(BBitmap* image, float scale, BMessenger listener, uint32 what)
|
||||||
|
: Filter(image, listener, what)
|
||||||
|
, fScale(scale)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaler::~Scaler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BBitmap*
|
||||||
|
Scaler::CreateDestImage(BBitmap* srcImage)
|
||||||
|
{
|
||||||
|
if (srcImage == NULL || srcImage->ColorSpace() != B_RGB32 && srcImage->ColorSpace() !=B_RGBA32) return NULL;
|
||||||
|
BRect src(srcImage->Bounds());
|
||||||
|
BRect dest(0, 0, (src.Width()+1)*fScale - 1, (src.Height()+1)*fScale - 1);
|
||||||
|
BBitmap* destImage = new BBitmap(dest, srcImage->ColorSpace());
|
||||||
|
return destImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Scaler::Run()
|
||||||
|
{
|
||||||
|
scale(GetSrcImage(), GetDestImage(), IsRunningAddr(), fScale, fScale);
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
// Filter
|
||||||
|
// Written by Michael Pfeiffer
|
||||||
|
//
|
||||||
|
// Filter.h
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003 OpenBeOS Project
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included
|
||||||
|
// in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _Filter_h
|
||||||
|
#define _Filter_h
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
#include <Bitmap.h>
|
||||||
|
#include <Messenger.h>
|
||||||
|
|
||||||
|
class Filter {
|
||||||
|
public:
|
||||||
|
Filter(BBitmap* image, BMessenger listener, uint32 what);
|
||||||
|
virtual ~Filter();
|
||||||
|
|
||||||
|
BBitmap* GetBitmap();
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
void Stop();
|
||||||
|
bool IsRunning() const;
|
||||||
|
volatile bool *IsRunningAddr() { return &fIsRunning; }
|
||||||
|
|
||||||
|
virtual BBitmap* CreateDestImage(BBitmap* srcImage) = 0;
|
||||||
|
virtual void Run() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BBitmap* GetSrcImage();
|
||||||
|
BBitmap* GetDestImage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
BMessenger fListener;
|
||||||
|
uint32 fWhat;
|
||||||
|
static status_t worker_thread(void* data);
|
||||||
|
volatile bool fIsRunning;
|
||||||
|
thread_id fWorkerThread;
|
||||||
|
BBitmap* fSrcImage;
|
||||||
|
BBitmap* fDestImage;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Scaler : public Filter {
|
||||||
|
public:
|
||||||
|
Scaler(BBitmap* image, float scale, BMessenger listener, uint32 what);
|
||||||
|
~Scaler();
|
||||||
|
|
||||||
|
BBitmap* CreateDestImage(BBitmap* srcImage);
|
||||||
|
void Run();
|
||||||
|
float Scale() const { return fScale; }
|
||||||
|
private:
|
||||||
|
float fScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -8,6 +8,8 @@ App ShowImage : ShowImageApp.cpp
|
|||||||
ShowImageView.cpp
|
ShowImageView.cpp
|
||||||
ShowImageWindow.cpp
|
ShowImageWindow.cpp
|
||||||
PrintOptionsWindow.cpp
|
PrintOptionsWindow.cpp
|
||||||
|
Filter.cpp
|
||||||
|
Scale.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
LinkSharedOSLibs ShowImage : be tracker translation ;
|
LinkSharedOSLibs ShowImage : be tracker translation ;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
// PrintOptionsWindow
|
// PrintOptionsWindow
|
||||||
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
|
// Written by Michael Pfeiffer
|
||||||
//
|
//
|
||||||
// PrintOptionsWindow.cpp
|
// PrintOptionsWindow.cpp
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
// PrintOptionsWindow
|
// PrintOptionsWindow
|
||||||
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
|
// Written by Michael Pfeiffer
|
||||||
//
|
//
|
||||||
// PrintOptionsWindow.h
|
// PrintOptionsWindow.h
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
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);
|
||||||
|
|
||||||
@@ -67,6 +67,8 @@ const uint32 MSG_PRINT = 'mPRT';
|
|||||||
const uint32 MSG_ZOOM_IN = 'mZIN';
|
const uint32 MSG_ZOOM_IN = 'mZIN';
|
||||||
const uint32 MSG_ZOOM_OUT = 'mZOU';
|
const uint32 MSG_ZOOM_OUT = 'mZOU';
|
||||||
const uint32 MSG_ORIGINAL_SIZE = 'mOSZ';
|
const uint32 MSG_ORIGINAL_SIZE = 'mOSZ';
|
||||||
|
const uint32 MSG_INVALIDATE = 'mIVD';
|
||||||
|
const uint32 MSG_SCALE_BILINEAR = 'mSBL';
|
||||||
|
|
||||||
extern const char *APP_SIG;
|
extern const char *APP_SIG;
|
||||||
|
|
||||||
|
|||||||
@@ -167,6 +167,8 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode,
|
|||||||
fShowCaption = false;
|
fShowCaption = false;
|
||||||
fZoom = 1.0;
|
fZoom = 1.0;
|
||||||
fMovesImage = false;
|
fMovesImage = false;
|
||||||
|
fScaleBilinear = false;
|
||||||
|
fScaler = NULL;
|
||||||
|
|
||||||
SetViewColor(B_TRANSPARENT_COLOR);
|
SetViewColor(B_TRANSPARENT_COLOR);
|
||||||
SetHighColor(kborderColor);
|
SetHighColor(kborderColor);
|
||||||
@@ -176,8 +178,7 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode,
|
|||||||
|
|
||||||
ShowImageView::~ShowImageView()
|
ShowImageView::~ShowImageView()
|
||||||
{
|
{
|
||||||
delete fpBitmap;
|
DeleteBitmap();
|
||||||
fpBitmap = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@@ -225,10 +226,20 @@ ShowImageView::AddToRecentDocuments()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ShowImageView::SetImage(const entry_ref *pref)
|
ShowImageView::DeleteBitmap()
|
||||||
{
|
{
|
||||||
|
if (fScaler) {
|
||||||
|
delete fScaler;
|
||||||
|
fScaler = NULL;
|
||||||
|
}
|
||||||
delete fpBitmap;
|
delete fpBitmap;
|
||||||
fpBitmap = NULL;
|
fpBitmap = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ShowImageView::SetImage(const entry_ref *pref)
|
||||||
|
{
|
||||||
|
DeleteBitmap();
|
||||||
fbHasSelection = false;
|
fbHasSelection = false;
|
||||||
fMakesSelection = false;
|
fMakesSelection = false;
|
||||||
|
|
||||||
@@ -355,6 +366,14 @@ ShowImageView::FlushToLeftTop()
|
|||||||
ScrollTo(p);
|
ScrollTo(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ShowImageView::SetScaleBilinear(bool s)
|
||||||
|
{
|
||||||
|
if (fScaleBilinear != s) {
|
||||||
|
fScaleBilinear = s; Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ShowImageView::AttachedToWindow()
|
ShowImageView::AttachedToWindow()
|
||||||
{
|
{
|
||||||
@@ -362,7 +381,7 @@ ShowImageView::AttachedToWindow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BRect
|
BRect
|
||||||
ShowImageView::AlignBitmap() const
|
ShowImageView::AlignBitmap()
|
||||||
{
|
{
|
||||||
BRect rect(fpBitmap->Bounds());
|
BRect rect(fpBitmap->Bounds());
|
||||||
float width, height;
|
float width, height;
|
||||||
@@ -374,20 +393,22 @@ ShowImageView::AlignBitmap() const
|
|||||||
s = width / rect.Width();
|
s = width / rect.Width();
|
||||||
|
|
||||||
if (s * rect.Height() <= height) {
|
if (s * rect.Height() <= height) {
|
||||||
|
fZoom = s;
|
||||||
rect.right = width;
|
rect.right = width;
|
||||||
rect.bottom = s * rect.Height();
|
rect.bottom = s * rect.Height();
|
||||||
// center vertically
|
// center vertically
|
||||||
rect.OffsetBy(0, (height - rect.Height()) / 2);
|
rect.OffsetBy(0, (height - rect.Height()) / 2);
|
||||||
} else {
|
} else {
|
||||||
rect.right = height / rect.Height() * rect.Width();
|
fZoom = height / rect.Height();
|
||||||
|
rect.right = fZoom * rect.Width();
|
||||||
rect.bottom = height;
|
rect.bottom = height;
|
||||||
// center horizontally
|
// center horizontally
|
||||||
rect.OffsetBy((width - rect.Width()) / 2, 0);
|
rect.OffsetBy((width - rect.Width()) / 2, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// zoom image
|
// zoom image
|
||||||
rect.right = (rect.right+1)*fZoom-1;
|
rect.right = ((int)(rect.right+1)*fZoom)-1;
|
||||||
rect.bottom = (rect.bottom+1)*fZoom-1;
|
rect.bottom = ((int)(rect.bottom+1)*fZoom)-1;
|
||||||
// align
|
// align
|
||||||
switch (fHAlignment) {
|
switch (fHAlignment) {
|
||||||
case B_ALIGN_CENTER:
|
case B_ALIGN_CENTER:
|
||||||
@@ -423,11 +444,8 @@ ShowImageView::Setup(BRect rect)
|
|||||||
{
|
{
|
||||||
fLeft = rect.left;
|
fLeft = rect.left;
|
||||||
fTop = rect.top;
|
fTop = rect.top;
|
||||||
fScaleX = rect.Width() / fpBitmap->Bounds().Width();
|
fScaleX = (rect.Width()+1.0) / (fpBitmap->Bounds().Width()+1.0);
|
||||||
fScaleY = rect.Height() / fpBitmap->Bounds().Height();
|
fScaleY = (rect.Height()+1.0) / (fpBitmap->Bounds().Height()+1.0);
|
||||||
// XXX Is Width/Height off by one?
|
|
||||||
// fScaleX = (rect.Width()+1) / (fpBitmap->Bounds().Width()+1);
|
|
||||||
// fScaleY = (rect.Width()+1) / (fpBitmap->Bounds().Height()+1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BPoint
|
BPoint
|
||||||
@@ -511,6 +529,32 @@ ShowImageView::DrawCaption()
|
|||||||
PopState();
|
PopState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scaler*
|
||||||
|
ShowImageView::GetScaler()
|
||||||
|
{
|
||||||
|
if (fScaler == NULL || fScaler->Scale() != fZoom) {
|
||||||
|
delete fScaler;
|
||||||
|
BMessenger msgr(this, Window());
|
||||||
|
fScaler = new Scaler(fpBitmap, fZoom, msgr, MSG_INVALIDATE);
|
||||||
|
fScaler->Start();
|
||||||
|
}
|
||||||
|
return fScaler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ShowImageView::DrawImage(BRect rect)
|
||||||
|
{
|
||||||
|
if (fScaleBilinear) {
|
||||||
|
Scaler* scaler = GetScaler();
|
||||||
|
if (scaler != NULL && scaler->GetBitmap() != NULL && !scaler->IsRunning()) {
|
||||||
|
BBitmap* bitmap = scaler->GetBitmap();
|
||||||
|
DrawBitmap(bitmap, BPoint(rect.left, rect.top));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DrawBitmap(fpBitmap, fpBitmap->Bounds(), rect);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ShowImageView::Draw(BRect updateRect)
|
ShowImageView::Draw(BRect updateRect)
|
||||||
{
|
{
|
||||||
@@ -527,8 +571,8 @@ ShowImageView::Draw(BRect updateRect)
|
|||||||
// Draw black rectangle around image
|
// Draw black rectangle around image
|
||||||
StrokeRect(border);
|
StrokeRect(border);
|
||||||
|
|
||||||
// Draw image
|
// Draw image
|
||||||
DrawBitmap(fpBitmap, fpBitmap->Bounds(), rect);
|
DrawImage(rect);
|
||||||
|
|
||||||
if (fShowCaption && !fMovesImage) {
|
if (fShowCaption && !fMovesImage) {
|
||||||
// to avoid flickering, disabled during moving with mouse
|
// to avoid flickering, disabled during moving with mouse
|
||||||
@@ -1020,6 +1064,9 @@ ShowImageView::MessageReceived(BMessage *pmsg)
|
|||||||
case B_MOUSE_WHEEL_CHANGED:
|
case B_MOUSE_WHEEL_CHANGED:
|
||||||
MouseWheelChanged(pmsg);
|
MouseWheelChanged(pmsg);
|
||||||
break;
|
break;
|
||||||
|
case MSG_INVALIDATE:
|
||||||
|
Invalidate();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
BView::MessageReceived(pmsg);
|
BView::MessageReceived(pmsg);
|
||||||
break;
|
break;
|
||||||
@@ -1284,6 +1331,9 @@ ShowImageView::FirstFile()
|
|||||||
void
|
void
|
||||||
ShowImageView::SetZoom(float zoom)
|
ShowImageView::SetZoom(float zoom)
|
||||||
{
|
{
|
||||||
|
if (fScaleBilinear && fZoom != zoom) {
|
||||||
|
delete fScaler; fScaler = NULL;
|
||||||
|
}
|
||||||
fZoom = zoom;
|
fZoom = zoom;
|
||||||
FixupScrollBars();
|
FixupScrollBars();
|
||||||
Invalidate();
|
Invalidate();
|
||||||
@@ -1453,7 +1503,8 @@ ShowImageView::DoImageOperation(image_operation op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set new bitmap
|
// set new bitmap
|
||||||
delete fpBitmap; fpBitmap = bm;
|
DeleteBitmap();
|
||||||
|
fpBitmap = bm;
|
||||||
// remove selection
|
// remove selection
|
||||||
fbHasSelection = false;
|
fbHasSelection = false;
|
||||||
Notify(NULL);
|
Notify(NULL);
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
#include <String.h>
|
#include <String.h>
|
||||||
#include <TranslatorRoster.h>
|
#include <TranslatorRoster.h>
|
||||||
|
|
||||||
|
#include "Filter.h"
|
||||||
|
|
||||||
class ShowImageView : public BView {
|
class ShowImageView : public BView {
|
||||||
public:
|
public:
|
||||||
ShowImageView(BRect rect, const char *name, uint32 resizingMode,
|
ShowImageView(BRect rect, const char *name, uint32 resizingMode,
|
||||||
@@ -52,6 +54,8 @@ public:
|
|||||||
void GetName(BString *name);
|
void GetName(BString *name);
|
||||||
void GetPath(BString *name);
|
void GetPath(BString *name);
|
||||||
void FlushToLeftTop();
|
void FlushToLeftTop();
|
||||||
|
void SetScaleBilinear(bool b);
|
||||||
|
bool GetScaleBilinear() { return fScaleBilinear; }
|
||||||
|
|
||||||
virtual void AttachedToWindow();
|
virtual void AttachedToWindow();
|
||||||
virtual void Draw(BRect updateRect);
|
virtual void Draw(BRect updateRect);
|
||||||
@@ -106,11 +110,12 @@ private:
|
|||||||
void AnimateSelection(bool a);
|
void AnimateSelection(bool a);
|
||||||
void Notify(const char* status);
|
void Notify(const char* status);
|
||||||
void AddToRecentDocuments();
|
void AddToRecentDocuments();
|
||||||
|
void DeleteBitmap();
|
||||||
int32 BytesPerPixel(color_space cs) const;
|
int32 BytesPerPixel(color_space cs) const;
|
||||||
inline void CopyPixel(uchar* dest, int32 destX, int32 destY, int32 destBPR, uchar* src, int32 x, int32 y, int32 bpr, int32 bpp);
|
inline void CopyPixel(uchar* dest, int32 destX, int32 destY, int32 destBPR, uchar* src, int32 x, int32 y, int32 bpr, int32 bpp);
|
||||||
inline void InvertPixel(int32 x, int32 y, uchar* dest, int32 destBPR, uchar* src, int32 bpr, int32 bpp);
|
inline void InvertPixel(int32 x, int32 y, uchar* dest, int32 destBPR, uchar* src, int32 bpr, int32 bpp);
|
||||||
void DoImageOperation(image_operation op);
|
void DoImageOperation(image_operation op);
|
||||||
BRect AlignBitmap() const;
|
BRect AlignBitmap();
|
||||||
void Setup(BRect r);
|
void Setup(BRect r);
|
||||||
BPoint ImageToView(BPoint p) const;
|
BPoint ImageToView(BPoint p) const;
|
||||||
BPoint ViewToImage(BPoint p) const;
|
BPoint ViewToImage(BPoint p) const;
|
||||||
@@ -135,6 +140,8 @@ private:
|
|||||||
void DrawBorder(BRect border);
|
void DrawBorder(BRect border);
|
||||||
void DrawCaption();
|
void DrawCaption();
|
||||||
void DrawSelectionBox(BRect &rect);
|
void DrawSelectionBox(BRect &rect);
|
||||||
|
Scaler* GetScaler();
|
||||||
|
void DrawImage(BRect rect);
|
||||||
float LimitToRange(float v, orientation o, bool absolute);
|
float LimitToRange(float v, orientation o, bool absolute);
|
||||||
void ScrollRestricted(float x, float y, bool absolute);
|
void ScrollRestricted(float x, float y, bool absolute);
|
||||||
void ScrollRestrictedTo(float x, float y);
|
void ScrollRestrictedTo(float x, float y);
|
||||||
@@ -147,6 +154,8 @@ private:
|
|||||||
int32 fDocumentCount;
|
int32 fDocumentCount;
|
||||||
BBitmap *fpBitmap;
|
BBitmap *fpBitmap;
|
||||||
float fZoom;
|
float fZoom;
|
||||||
|
bool fScaleBilinear;
|
||||||
|
Scaler* fScaler;
|
||||||
bool fResizeToViewBounds;
|
bool fResizeToViewBounds;
|
||||||
alignment fHAlignment;
|
alignment fHAlignment;
|
||||||
vertical_alignment fVAlignment;
|
vertical_alignment fVAlignment;
|
||||||
|
|||||||
@@ -166,12 +166,13 @@ ShowImageWindow::UpdateRecentDocumentsMenu()
|
|||||||
be_roster->GetRecentDocuments(&list, 20, NULL, APP_SIG);
|
be_roster->GetRecentDocuments(&list, 20, NULL, APP_SIG);
|
||||||
for (int i = 0; list.FindRef("refs", i, &ref) == B_OK; i++) {
|
for (int i = 0; list.FindRef("refs", i, &ref) == B_OK; i++) {
|
||||||
BEntry entry(&ref);
|
BEntry entry(&ref);
|
||||||
entry.GetName(name);
|
if (entry.GetName(name) == B_OK) {
|
||||||
msg = new BMessage(B_REFS_RECEIVED);
|
msg = new BMessage(B_REFS_RECEIVED);
|
||||||
msg->AddRef("refs", &ref);
|
msg->AddRef("refs", &ref);
|
||||||
item = new BMenuItem(name, msg, 0, 0);
|
item = new BMenuItem(name, msg, 0, 0);
|
||||||
fpOpenMenu->AddItem(item);
|
fpOpenMenu->AddItem(item);
|
||||||
item->SetTarget(be_app, NULL);
|
item->SetTarget(be_app, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,13 +210,16 @@ ShowImageWindow::BuildViewMenu(BMenu *pmenu)
|
|||||||
AddItemMenu(pmenu, "Original Size", MSG_ORIGINAL_SIZE, 0, 0, 'W', true);
|
AddItemMenu(pmenu, "Original Size", MSG_ORIGINAL_SIZE, 0, 0, 'W', true);
|
||||||
AddItemMenu(pmenu, "Zoom In", MSG_ZOOM_IN, '+', 0, 'W', true);
|
AddItemMenu(pmenu, "Zoom In", MSG_ZOOM_IN, '+', 0, 'W', true);
|
||||||
AddItemMenu(pmenu, "Zoom Out", MSG_ZOOM_OUT, '-', 0, 'W', true);
|
AddItemMenu(pmenu, "Zoom Out", MSG_ZOOM_OUT, '-', 0, 'W', true);
|
||||||
|
AddItemMenu(pmenu, "Scale Bilinear", MSG_SCALE_BILINEAR, 0, 0, 'W', true);
|
||||||
pmenu->AddSeparatorItem();
|
pmenu->AddSeparatorItem();
|
||||||
AddItemMenu(pmenu, "Fit To Window Size", MSG_FIT_TO_WINDOW_SIZE, 0, 0, 'W', true);
|
AddItemMenu(pmenu, "Fit To Window Size", MSG_FIT_TO_WINDOW_SIZE, 0, 0, 'W', true);
|
||||||
AddItemMenu(pmenu, "Full Screen", MSG_FULL_SCREEN, B_ENTER, 0, 'W', true);
|
AddItemMenu(pmenu, "Full Screen", MSG_FULL_SCREEN, B_ENTER, 0, 'W', true);
|
||||||
|
MarkMenuItem(pmenu, MSG_FULL_SCREEN, fFullScreen);
|
||||||
AddItemMenu(pmenu, "Show Caption in Full Screen Mode", MSG_SHOW_CAPTION, 0, 0, 'W', true);
|
AddItemMenu(pmenu, "Show Caption in Full Screen Mode", MSG_SHOW_CAPTION, 0, 0, 'W', true);
|
||||||
MarkMenuItem(pmenu, MSG_SHOW_CAPTION, fShowCaption);
|
MarkMenuItem(pmenu, MSG_SHOW_CAPTION, fShowCaption);
|
||||||
|
|
||||||
if (fpImageView) {
|
if (fpImageView) {
|
||||||
|
MarkMenuItem(pmenu, MSG_SCALE_BILINEAR, fpImageView->GetScaleBilinear());
|
||||||
bool resize = fpImageView->GetResizeToViewBounds();
|
bool resize = fpImageView->GetResizeToViewBounds();
|
||||||
MarkMenuItem(pmenu, MSG_FIT_TO_WINDOW_SIZE, resize);
|
MarkMenuItem(pmenu, MSG_FIT_TO_WINDOW_SIZE, resize);
|
||||||
EnableMenuItem(pmenu, MSG_ORIGINAL_SIZE, !resize);
|
EnableMenuItem(pmenu, MSG_ORIGINAL_SIZE, !resize);
|
||||||
@@ -640,6 +644,9 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
|
|||||||
case MSG_ORIGINAL_SIZE:
|
case MSG_ORIGINAL_SIZE:
|
||||||
fpImageView->SetZoom(1.0);
|
fpImageView->SetZoom(1.0);
|
||||||
break;
|
break;
|
||||||
|
case MSG_SCALE_BILINEAR:
|
||||||
|
fpImageView->SetScaleBilinear(ToggleMenuItem(pmsg->what));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BWindow::MessageReceived(pmsg);
|
BWindow::MessageReceived(pmsg);
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user