1 /*****************************************************************************/ 2 // Filter 3 // Written by Michael Pfeiffer 4 // 5 // Filter.h 6 // 7 // 8 // Copyright (c) 2003 OpenBeOS 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 39 class Filter; 40 41 typedef int32 intType; 42 typedef int64 long_fixed_point; 43 typedef 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 57 const int32 kFPPrecision = 8; // (32-kFPPrecision).kFPPrecision 58 const int32 kFPPrecisionFactor = (1 << kFPPrecision); 59 const int32 kFPPrecisionMask = ((kFPPrecisionFactor)-1); 60 const int32 kFPInverseMask = (~kFPPrecisionMask); 61 const int32 kFPOne = to_fixed_point(1); 62 63 // Used by class Filter 64 class FilterThread { 65 public: 66 FilterThread(Filter* filter, int i); 67 ~FilterThread(); 68 69 private: 70 status_t Run(); 71 static status_t worker_thread(void* data); 72 thread_id fWorkerThread; 73 Filter* fFilter; 74 int fI; 75 }; 76 77 class Filter { 78 public: 79 // The filter uses the input "image" as source image 80 // for an operation executed in Run() method which 81 // writes into the destination image, that can be 82 // retrieve using GetBitmap() method. 83 // GetBitmap() can be called any time, but it 84 // may contain "invalid" pixels. 85 // To start the operation Start() method has to 86 // be called. The operation is executed in as many 87 // threads as CPUs are active. 88 // IsRunning() is true as long as there are any 89 // threads running. 90 // The operation is complete when IsRunning() is false 91 // and Stop() has not been called. 92 // To abort an operation Stop() method has to 93 // be called. Stop() has to be called after Start(). 94 // When the operation is done (and has not been aborted). 95 // Then listener receives a message with the specified "what" value. 96 Filter(BBitmap* image, BMessenger listener, uint32 what); 97 virtual ~Filter(); 98 99 // The bitmap the filter writes into 100 BBitmap* GetBitmap(); 101 102 // Starts one or more FilterThreads 103 void Start(); 104 // Has to be called after Start() (even if IsRunning() is false) 105 void Stop(); 106 // Are there any running FilterThreads? 107 bool IsRunning() const; 108 109 // To be implemented by inherited class 110 virtual BBitmap* CreateDestImage(BBitmap* srcImage) = 0; 111 // Should calculate part i of n of the image. i starts with zero 112 virtual void Run(int i, int n) = 0; 113 114 // Used by FilterThread only! 115 void Done(); 116 int32 CPUCount() const { return fCPUCount; } 117 118 protected: 119 BBitmap* GetSrcImage(); 120 BBitmap* GetDestImage(); 121 122 private: 123 BMessenger fListener; 124 uint32 fWhat; 125 int32 fCPUCount; 126 bool fStarted; 127 sem_id fWaitForThreads; 128 volatile int32 fNumberOfThreads; 129 volatile bool fIsRunning; 130 BBitmap* fSrcImage; 131 BBitmap* fDestImage; 132 #if TIME_FILTER 133 BStopWatch* fStopWatch; 134 #endif 135 }; 136 137 class Scaler : public Filter { 138 public: 139 Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what); 140 ~Scaler(); 141 142 BBitmap* CreateDestImage(BBitmap* srcImage); 143 void Run(int i, int n); 144 bool Matches(BRect rect) const; 145 146 private: 147 void ScaleBilinear(int32 fromRow, int32 toRow); 148 void ScaleBilinearFP(int32 fromRow, int32 toRow); 149 inline void RowValues(float* sum, const uchar* srcData, intType srcW, intType fromX, intType toX, const float a0X, const float a1X, const float deltaX, const int32 kBPP); 150 void DownScaleBilinear(int32 fromRow, int32 toRow); 151 152 BRect fRect; 153 }; 154 155 #endif 156