Fixed access to invalid bitmap bug.

Refactored code a little bit.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5746 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer 2003-12-24 10:14:28 +00:00
parent 5aa7212658
commit 491eb383e0
3 changed files with 97 additions and 39 deletions

View File

@ -55,7 +55,7 @@ FilterThread::FilterThread(Filter* filter, int32 i, int32 n, bool runInCurrentTh
FilterThread::~FilterThread()
{
fFilter->Done();
fFilter->FilterThreadDone();
}
status_t
@ -69,8 +69,13 @@ status_t
FilterThread::Run()
{
if (fI == 0) {
BBitmap* bm;
// create destination image in first thread
fFilter->GetBitmap();
bm = fFilter->GetBitmap();
if (bm == NULL) {
fFilter->FilterThreadInitFailed();
return B_ERROR;
}
// and start other filter threads
for (int32 i = fI + 1; i < fN; i ++) {
new FilterThread(fFilter, i, fN);
@ -92,22 +97,10 @@ Filter::Filter(BBitmap* image, BMessenger listener, uint32 what)
, fNumberOfThreads(0)
, fIsRunning(false)
, fSrcImage(image)
, fDestImageInitialized(false)
, fDestImage(NULL)
{
// get the number of active CPUs
int count;
system_info info;
get_system_info(&info);
count = info.cpu_count;
fCPUCount = 0;
for (int i = 0; i < count; i ++) {
if (_kget_cpu_state_(i)) {
fCPUCount ++;
}
}
if (fCPUCount == 0) {
fCPUCount = 1;
}
fCPUCount = NumberOfActiveCPUs();
fWaitForThreads = create_sem(0, "wait_for_threads");
@ -125,7 +118,8 @@ Filter::~Filter()
BBitmap*
Filter::GetBitmap()
{
if (fDestImage == NULL) {
if (!fDestImageInitialized) {
fDestImageInitialized = true;
fDestImage = CreateDestImage(fSrcImage);
}
return fDestImage;
@ -180,8 +174,19 @@ Filter::Stop()
Wait();
}
bool
Filter::IsRunning() const
{
return fIsRunning;
}
void
Filter::Done()
Filter::Completed()
{
}
void
Filter::FilterThreadDone()
{
if (atomic_add(&fNumberOfThreads, -1) == 1) {
#if TIME_FILTER
@ -196,15 +201,20 @@ Filter::Done()
release_sem(fWaitForThreads);
}
bool
Filter::IsRunning() const
void
Filter::FilterThreadInitFailed()
{
return fIsRunning;
ASSERT(fNumberOfThreads == fN);
fNumberOfThreads = 0;
Completed();
fIsRunning = false;
release_sem_etc(fWaitForThreads, fN, 0);
}
void
Filter::Completed()
bool
Filter::IsBitmapValid(BBitmap* bitmap) const
{
return bitmap != NULL && bitmap->InitCheck() == B_OK && bitmap->IsValid();
}
int32
@ -233,6 +243,25 @@ Filter::GetDestImage()
return fDestImage;
}
int32
Filter::NumberOfActiveCPUs() const
{
int count;
system_info info;
get_system_info(&info);
count = info.cpu_count;
int32 CPUCount = 0;
for (int i = 0; i < count; i ++) {
if (_kget_cpu_state_(i)) {
CPUCount ++;
}
}
if (CPUCount == 0) {
CPUCount = 1;
}
return CPUCount;
}
// Implementation of (bilinear) Scaler
Scaler::Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what, bool dither)
: Filter(image, listener, what)
@ -253,14 +282,28 @@ BBitmap*
Scaler::CreateDestImage(BBitmap* srcImage)
{
if (srcImage == NULL || srcImage->ColorSpace() != B_RGB32 && srcImage->ColorSpace() !=B_RGBA32) return NULL;
BRect dest(0, 0, fRect.IntegerWidth(), fRect.IntegerHeight());
BBitmap* destImage = new BBitmap(dest, fDither ? B_CMAP8 : srcImage->ColorSpace());
if (!IsBitmapValid(destImage)) {
delete destImage;
return NULL;
}
if (fDither) {
BRect dest(0, 0, fRect.IntegerWidth(), fRect.IntegerHeight());
fScaledImage = new BBitmap(dest, srcImage->ColorSpace());
if (!IsBitmapValid(fScaledImage)) {
delete destImage;
delete fScaledImage;
fScaledImage = NULL;
return NULL;
}
} else {
fScaledImage = destImage;
}
return destImage;
}
@ -906,7 +949,10 @@ ImageProcessor::CreateDestImage(BBitmap* srcImage)
}
bm = new BBitmap(rect, cs);
if (bm == NULL) return NULL;
if (!IsBitmapValid(bm)) {
delete bm;
return NULL;
}
fSrcBPR = GetSrcImage()->BytesPerRow();
fDestBPR = bm->BytesPerRow();

View File

@ -69,9 +69,10 @@ public:
private:
status_t Run();
static status_t worker_thread(void* data);
Filter* fFilter;
int32 fI;
int32 fN;
int32 fI;
int32 fN;
};
class Filter {
@ -125,7 +126,10 @@ public:
virtual void Completed();
// Used by FilterThread only!
void Done();
void FilterThreadDone();
void FilterThreadInitFailed();
bool IsBitmapValid(BBitmap* bitmap) const;
protected:
// Number of threads to be used to perform the operation
@ -134,21 +138,23 @@ protected:
BBitmap* GetDestImage();
private:
int32 NumberOfActiveCPUs() const;
// Returns the number of active CPUs
int32 CPUCount() const { return fCPUCount; }
BMessenger fListener;
uint32 fWhat;
int32 fCPUCount; // the number of active CPUs
bool fStarted; // has Start() been called?
sem_id fWaitForThreads; // to exit
int32 fN; // the number of used filter threads
BMessenger fListener;
uint32 fWhat;
int32 fCPUCount; // the number of active CPUs
bool fStarted; // has Start() been called?
sem_id fWaitForThreads; // to exit
int32 fN; // the number of used filter threads
volatile int32 fNumberOfThreads; // the current number of FilterThreads
volatile bool fIsRunning; // FilterThreads should process data as long as it is true
BBitmap* fSrcImage;
BBitmap* fDestImage;
volatile bool fIsRunning; // FilterThreads should process data as long as it is true
BBitmap* fSrcImage;
bool fDestImageInitialized;
BBitmap* fDestImage;
#if TIME_FILTER
BStopWatch* fStopWatch;
BStopWatch* fStopWatch;
#endif
};
@ -201,8 +207,10 @@ private:
enum operation fOp;
int32 fBPP;
int32 fWidth, fHeight;
int32 fSrcBPR, fDestBPR;
int32 fWidth;
int32 fHeight;
int32 fSrcBPR;
int32 fDestBPR;
};
#endif

View File

@ -1945,6 +1945,10 @@ ShowImageView::DoImageOperation(ImageProcessor::operation op, bool quiet)
ImageProcessor imageProcessor(op, fBitmap, msgr, 0);
imageProcessor.Start(false);
BBitmap* bm = imageProcessor.DetachBitmap();
if (bm == NULL) {
// operation failed
return;
}
// update orientation state
if (op != ImageProcessor::kInvert) {