1/*****************************************************************************/ 2// Filter 3// Written by Michael Pfeiffer 4// 5// Filter.h 6// 7// 8// Copyright (c) 2003 Haiku Project 9// 10// Permission is hereby granted, free of charge, to any person obtaining a 11// copy of this software and associated documentation files (the "Software"), 12// to deal in the Software without restriction, including without limitation 13// the rights to use, copy, modify, merge, publish, distribute, sublicense, 14// and/or sell copies of the Software, and to permit persons to whom the 15// Software is furnished to do so, subject to the following conditions: 16// 17// The above copyright notice and this permission notice shall be included 18// in all copies or substantial portions of the Software. 19// 20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26// DEALINGS IN THE SOFTWARE. 27/*****************************************************************************/ 28 29#ifndef _Filter_h 30#define _Filter_h 31 32#include <OS.h> 33#include <Bitmap.h> 34#include <Messenger.h> 35#include <StopWatch.h> 36 37#define TIME_FILTER 0 38 39class Filter; 40 41typedef int32 intType; 42typedef int64 long_fixed_point; 43typedef int32 fixed_point; 44 45// Could use shift operator instead of multiplication and division, 46// but compiler will optimize it for use anyway. 47#define to_fixed_point(number) static_cast<fixed_point>((number) * kFPPrecisionFactor) 48#define from_fixed_point(number) ((number) / kFPPrecisionFactor) 49#define to_float(number) from_fixed_point(static_cast<float>(number)) 50 51#define int_value(number) ((number) & kFPInverseMask) 52#define tail_value(number) ((number) & kFPPrecisionMask) 53 54// Has to be called after muliplication of two fixed point values 55#define mult_correction(number) ((number) / kFPPrecisionFactor) 56 57const int32 kFPPrecision = 8; // (32-kFPPrecision).kFPPrecision 58const int32 kFPPrecisionFactor = (1 << kFPPrecision); 59const int32 kFPPrecisionMask = ((kFPPrecisionFactor)-1); 60const int32 kFPInverseMask = (~kFPPrecisionMask); 61const int32 kFPOne = to_fixed_point(1); 62 63// Used by class Filter 64class FilterThread { 65public: 66 FilterThread(Filter* filter, int32 i, int32 n, 67 bool runInCurrentThread = false); 68 ~FilterThread(); 69 70private: 71 status_t Run(); 72 static status_t worker_thread(void* data); 73 74 Filter* fFilter; 75 int32 fI; 76 int32 fN; 77}; 78 79class Filter { 80public: 81 // The filter uses the input "image" as source image 82 // for an operation executed in Run() method which 83 // writes into the destination image, that can be 84 // retrieve using GetBitmap() method. 85 // GetBitmap() must be called either before Start(), 86 // or after Start() and IsRunning() returns false. 87 // To start the operation Start() method has to 88 // be called. The operation is executed in as many 89 // threads as GetMaxNumberOfThreads() returns. 90 // The implementation of GetMaxNumberOfThreads() 91 // can use CPUCount() to retrieve the number of 92 // active CPUs at the time the Filter was created. 93 // IsRunning() is true as long as there are any 94 // threads running. 95 // The operation is complete when IsRunning() is false 96 // and Stop() has not been called. 97 // To abort an operation Stop() method has to 98 // be called. Stop() has to be called after Start(). 99 // When the operation is done Completed() is called. 100 // and only if it has not been aborted, then the listener 101 // receives a message with the specified "what" value. 102 Filter(BBitmap* image, BMessenger listener, uint32 what); 103 virtual ~Filter(); 104 105 // The bitmap the filter writes into 106 BBitmap* GetBitmap(); 107 // Removes the destination image from Filter (caller is new owner of image) 108 BBitmap* DetachBitmap(); 109 110 // Starts one or more FilterThreads. Returns immediately if async is true. 111 // Either Wait() or Stop() has to be called if async is true! 112 void Start(bool async = true); 113 // Wait for completion of operation 114 void Wait(); 115 // Has to be called after Start() (even if IsRunning() is false) 116 void Stop(); 117 // Are there any running FilterThreads? 118 bool IsRunning() const; 119 120 // To be implemented by inherited class (methods are called in this order): 121 virtual BBitmap* CreateDestImage(BBitmap* srcImage) = 0; 122 // The number of processing units 123 virtual int32 GetNumberOfUnits() = 0; 124 // Should calculate part i of n of the image. i starts with zero 125 virtual void Run(int32 i, int32 n) = 0; 126 // Completed() is called when the last FilterThread has completed its work. 127 virtual void Completed(); 128 129 // Used by FilterThread only! 130 void FilterThreadDone(); 131 void FilterThreadInitFailed(); 132 133 bool IsBitmapValid(BBitmap* bitmap) const; 134 135protected: 136 // Number of threads to be used to perform the operation 137 int32 NumberOfThreads(); 138 BBitmap* GetSrcImage(); 139 BBitmap* GetDestImage(); 140 141private: 142 int32 NumberOfActiveCPUs() const; 143 // Returns the number of active CPUs 144 int32 CPUCount() const { return fCPUCount; } 145 146 BMessenger fListener; 147 uint32 fWhat; 148 int32 fCPUCount; // the number of active CPUs 149 bool fStarted; // has Start() been called? 150 sem_id fWaitForThreads; // to exit 151 int32 fN; // the number of used filter threads 152 int32 fNumberOfThreads; // the current number of FilterThreads 153 volatile bool fIsRunning; // FilterThreads should process data as long as it is true 154 BBitmap* fSrcImage; 155 bool fDestImageInitialized; 156 BBitmap* fDestImage; 157#if TIME_FILTER 158 BStopWatch* fStopWatch; 159#endif 160}; 161 162// Scales and optionally dithers an image 163class Scaler : public Filter { 164public: 165 Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what, 166 bool dither); 167 ~Scaler(); 168 169 BBitmap* CreateDestImage(BBitmap* srcImage); 170 int32 GetNumberOfUnits(); 171 void Run(int32 i, int32 n); 172 void Completed(); 173 bool Matches(BRect rect, bool dither) const; 174 175private: 176 void ScaleBilinear(int32 fromRow, int32 toRow); 177 void ScaleBilinearFP(int32 fromRow, int32 toRow); 178 inline void RowValues(float* sum, const uchar* srcData, intType srcW, 179 intType fromX, intType toX, const float a0X, 180 const float a1X, const int32 kBPP); 181 void DownScaleBilinear(int32 fromRow, int32 toRow); 182 static inline uchar Limit(intType value); 183 void Dither(int32 fromRow, int32 toRow); 184 185 BBitmap* fScaledImage; 186 BRect fRect; 187 bool fDither; 188}; 189 190// Rotates, mirrors or inverts an image 191class ImageProcessor : public Filter { 192public: 193 enum operation { 194 kRotateClockwise, 195 kRotateCounterClockwise, 196 kFlipLeftToRight, 197 kFlipTopToBottom, 198 kInvert, 199 kNumberOfAffineTransformations = 4 200 }; 201 202 ImageProcessor(enum operation op, BBitmap* image, BMessenger listener, 203 uint32 what); 204 BBitmap* CreateDestImage(BBitmap* srcImage); 205 int32 GetNumberOfUnits(); 206 void Run(int32 i, int32 n); 207 208private: 209 int32 BytesPerPixel(color_space cs) const; 210 inline void CopyPixel(uchar* dest, int32 destX, int32 destY, 211 const uchar* src, int32 x, int32 y); 212 inline void InvertPixel(int32 x, int32 y, uchar* dest, const uchar* src); 213 214 enum operation fOp; 215 int32 fBPP; 216 int32 fWidth; 217 int32 fHeight; 218 int32 fSrcBPR; 219 int32 fDestBPR; 220}; 221 222#endif 223