- 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:
Michael Pfeiffer
2003-11-13 06:54:48 +00:00
parent 8afbc3212d
commit 81b9c77691
12 changed files with 581 additions and 24 deletions
+134
View File
@@ -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);
}
+77
View File
@@ -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
+2
View File
@@ -8,6 +8,8 @@ App ShowImage : ShowImageApp.cpp
ShowImageView.cpp
ShowImageWindow.cpp
PrintOptionsWindow.cpp
Filter.cpp
Scale.cpp
;
LinkSharedOSLibs ShowImage : be tracker translation ;
+1 -1
View File
@@ -1,6 +1,6 @@
/*****************************************************************************/
// PrintOptionsWindow
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
// Written by Michael Pfeiffer
//
// PrintOptionsWindow.cpp
//
+1 -1
View File
@@ -1,6 +1,6 @@
/*****************************************************************************/
// PrintOptionsWindow
// Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
// Written by Michael Pfeiffer
//
// PrintOptionsWindow.h
//
+253
View File
@@ -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;
}
+22
View File
@@ -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);
+2
View File
@@ -67,6 +67,8 @@ const uint32 MSG_PRINT = 'mPRT';
const uint32 MSG_ZOOM_IN = 'mZIN';
const uint32 MSG_ZOOM_OUT = 'mZOU';
const uint32 MSG_ORIGINAL_SIZE = 'mOSZ';
const uint32 MSG_INVALIDATE = 'mIVD';
const uint32 MSG_SCALE_BILINEAR = 'mSBL';
extern const char *APP_SIG;
+66 -15
View File
@@ -167,6 +167,8 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode,
fShowCaption = false;
fZoom = 1.0;
fMovesImage = false;
fScaleBilinear = false;
fScaler = NULL;
SetViewColor(B_TRANSPARENT_COLOR);
SetHighColor(kborderColor);
@@ -176,8 +178,7 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode,
ShowImageView::~ShowImageView()
{
delete fpBitmap;
fpBitmap = NULL;
DeleteBitmap();
}
bool
@@ -225,10 +226,20 @@ ShowImageView::AddToRecentDocuments()
}
void
ShowImageView::SetImage(const entry_ref *pref)
ShowImageView::DeleteBitmap()
{
if (fScaler) {
delete fScaler;
fScaler = NULL;
}
delete fpBitmap;
fpBitmap = NULL;
}
void
ShowImageView::SetImage(const entry_ref *pref)
{
DeleteBitmap();
fbHasSelection = false;
fMakesSelection = false;
@@ -355,6 +366,14 @@ ShowImageView::FlushToLeftTop()
ScrollTo(p);
}
void
ShowImageView::SetScaleBilinear(bool s)
{
if (fScaleBilinear != s) {
fScaleBilinear = s; Invalidate();
}
}
void
ShowImageView::AttachedToWindow()
{
@@ -362,7 +381,7 @@ ShowImageView::AttachedToWindow()
}
BRect
ShowImageView::AlignBitmap() const
ShowImageView::AlignBitmap()
{
BRect rect(fpBitmap->Bounds());
float width, height;
@@ -374,20 +393,22 @@ ShowImageView::AlignBitmap() const
s = width / rect.Width();
if (s * rect.Height() <= height) {
fZoom = s;
rect.right = width;
rect.bottom = s * rect.Height();
// center vertically
rect.OffsetBy(0, (height - rect.Height()) / 2);
} else {
rect.right = height / rect.Height() * rect.Width();
fZoom = height / rect.Height();
rect.right = fZoom * rect.Width();
rect.bottom = height;
// center horizontally
rect.OffsetBy((width - rect.Width()) / 2, 0);
}
} else {
// zoom image
rect.right = (rect.right+1)*fZoom-1;
rect.bottom = (rect.bottom+1)*fZoom-1;
rect.right = ((int)(rect.right+1)*fZoom)-1;
rect.bottom = ((int)(rect.bottom+1)*fZoom)-1;
// align
switch (fHAlignment) {
case B_ALIGN_CENTER:
@@ -423,11 +444,8 @@ ShowImageView::Setup(BRect rect)
{
fLeft = rect.left;
fTop = rect.top;
fScaleX = rect.Width() / fpBitmap->Bounds().Width();
fScaleY = rect.Height() / fpBitmap->Bounds().Height();
// XXX Is Width/Height off by one?
// fScaleX = (rect.Width()+1) / (fpBitmap->Bounds().Width()+1);
// fScaleY = (rect.Width()+1) / (fpBitmap->Bounds().Height()+1);
fScaleX = (rect.Width()+1.0) / (fpBitmap->Bounds().Width()+1.0);
fScaleY = (rect.Height()+1.0) / (fpBitmap->Bounds().Height()+1.0);
}
BPoint
@@ -511,6 +529,32 @@ ShowImageView::DrawCaption()
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
ShowImageView::Draw(BRect updateRect)
{
@@ -527,8 +571,8 @@ ShowImageView::Draw(BRect updateRect)
// Draw black rectangle around image
StrokeRect(border);
// Draw image
DrawBitmap(fpBitmap, fpBitmap->Bounds(), rect);
// Draw image
DrawImage(rect);
if (fShowCaption && !fMovesImage) {
// to avoid flickering, disabled during moving with mouse
@@ -1020,6 +1064,9 @@ ShowImageView::MessageReceived(BMessage *pmsg)
case B_MOUSE_WHEEL_CHANGED:
MouseWheelChanged(pmsg);
break;
case MSG_INVALIDATE:
Invalidate();
break;
default:
BView::MessageReceived(pmsg);
break;
@@ -1284,6 +1331,9 @@ ShowImageView::FirstFile()
void
ShowImageView::SetZoom(float zoom)
{
if (fScaleBilinear && fZoom != zoom) {
delete fScaler; fScaler = NULL;
}
fZoom = zoom;
FixupScrollBars();
Invalidate();
@@ -1453,7 +1503,8 @@ ShowImageView::DoImageOperation(image_operation op)
}
// set new bitmap
delete fpBitmap; fpBitmap = bm;
DeleteBitmap();
fpBitmap = bm;
// remove selection
fbHasSelection = false;
Notify(NULL);
+10 -1
View File
@@ -35,6 +35,8 @@
#include <String.h>
#include <TranslatorRoster.h>
#include "Filter.h"
class ShowImageView : public BView {
public:
ShowImageView(BRect rect, const char *name, uint32 resizingMode,
@@ -52,6 +54,8 @@ public:
void GetName(BString *name);
void GetPath(BString *name);
void FlushToLeftTop();
void SetScaleBilinear(bool b);
bool GetScaleBilinear() { return fScaleBilinear; }
virtual void AttachedToWindow();
virtual void Draw(BRect updateRect);
@@ -106,11 +110,12 @@ private:
void AnimateSelection(bool a);
void Notify(const char* status);
void AddToRecentDocuments();
void DeleteBitmap();
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 InvertPixel(int32 x, int32 y, uchar* dest, int32 destBPR, uchar* src, int32 bpr, int32 bpp);
void DoImageOperation(image_operation op);
BRect AlignBitmap() const;
BRect AlignBitmap();
void Setup(BRect r);
BPoint ImageToView(BPoint p) const;
BPoint ViewToImage(BPoint p) const;
@@ -135,6 +140,8 @@ private:
void DrawBorder(BRect border);
void DrawCaption();
void DrawSelectionBox(BRect &rect);
Scaler* GetScaler();
void DrawImage(BRect rect);
float LimitToRange(float v, orientation o, bool absolute);
void ScrollRestricted(float x, float y, bool absolute);
void ScrollRestrictedTo(float x, float y);
@@ -147,6 +154,8 @@ private:
int32 fDocumentCount;
BBitmap *fpBitmap;
float fZoom;
bool fScaleBilinear;
Scaler* fScaler;
bool fResizeToViewBounds;
alignment fHAlignment;
vertical_alignment fVAlignment;
+13 -6
View File
@@ -166,12 +166,13 @@ ShowImageWindow::UpdateRecentDocumentsMenu()
be_roster->GetRecentDocuments(&list, 20, NULL, APP_SIG);
for (int i = 0; list.FindRef("refs", i, &ref) == B_OK; i++) {
BEntry entry(&ref);
entry.GetName(name);
msg = new BMessage(B_REFS_RECEIVED);
msg->AddRef("refs", &ref);
item = new BMenuItem(name, msg, 0, 0);
fpOpenMenu->AddItem(item);
item->SetTarget(be_app, NULL);
if (entry.GetName(name) == B_OK) {
msg = new BMessage(B_REFS_RECEIVED);
msg->AddRef("refs", &ref);
item = new BMenuItem(name, msg, 0, 0);
fpOpenMenu->AddItem(item);
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, "Zoom In", MSG_ZOOM_IN, '+', 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();
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);
MarkMenuItem(pmenu, MSG_FULL_SCREEN, fFullScreen);
AddItemMenu(pmenu, "Show Caption in Full Screen Mode", MSG_SHOW_CAPTION, 0, 0, 'W', true);
MarkMenuItem(pmenu, MSG_SHOW_CAPTION, fShowCaption);
if (fpImageView) {
MarkMenuItem(pmenu, MSG_SCALE_BILINEAR, fpImageView->GetScaleBilinear());
bool resize = fpImageView->GetResizeToViewBounds();
MarkMenuItem(pmenu, MSG_FIT_TO_WINDOW_SIZE, resize);
EnableMenuItem(pmenu, MSG_ORIGINAL_SIZE, !resize);
@@ -640,6 +644,9 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
case MSG_ORIGINAL_SIZE:
fpImageView->SetZoom(1.0);
break;
case MSG_SCALE_BILINEAR:
fpImageView->SetScaleBilinear(ToggleMenuItem(pmsg->what));
break;
default:
BWindow::MessageReceived(pmsg);
Binary file not shown.