1 /*****************************************************************************/
3 // Written by Michael Pfeiffer
8 // Copyright (c) 2003 OpenBeOS Project
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:
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
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 /*****************************************************************************/
34 #include <Messenger.h>
35 #include <StopWatch.h>
41 typedef int32 intType
;
42 typedef int64 long_fixed_point
;
43 typedef int32 fixed_point
;
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))
51 #define int_value(number) ((number) & kFPInverseMask)
52 #define tail_value(number) ((number) & kFPPrecisionMask)
54 // Has to be called after muliplication of two fixed point values
55 #define mult_correction(number) ((number) / kFPPrecisionFactor)
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);
63 // Used by class Filter
66 FilterThread(Filter
* filter
, int32 i
, int32 n
,
67 bool runInCurrentThread
= false);
72 static status_t
worker_thread(void* data
);
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
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
);
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();
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
115 // Has to be called after Start() (even if IsRunning() is false)
117 // Are there any running FilterThreads?
118 bool IsRunning() const;
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();
129 // Used by FilterThread only!
130 void FilterThreadDone();
131 void FilterThreadInitFailed();
133 bool IsBitmapValid(BBitmap
* bitmap
) const;
136 // Number of threads to be used to perform the operation
137 int32
NumberOfThreads();
138 BBitmap
* GetSrcImage();
139 BBitmap
* GetDestImage();
142 int32
NumberOfActiveCPUs() const;
143 // Returns the number of active CPUs
144 int32
CPUCount() const { return fCPUCount
; }
146 BMessenger fListener
;
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
155 bool fDestImageInitialized
;
158 BStopWatch
* fStopWatch
;
162 // Scales and optionally dithers an image
163 class Scaler
: public Filter
{
165 Scaler(BBitmap
* image
, BRect rect
, BMessenger listener
, uint32 what
,
169 BBitmap
* CreateDestImage(BBitmap
* srcImage
);
170 int32
GetNumberOfUnits();
171 void Run(int32 i
, int32 n
);
173 bool Matches(BRect rect
, bool dither
) const;
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
);
185 BBitmap
* fScaledImage
;
190 // Rotates, mirrors or inverts an image
191 class ImageProcessor
: public Filter
{
195 kRotateCounterClockwise
,
199 kNumberOfAffineTransformations
= 4
202 ImageProcessor(enum operation op
, BBitmap
* image
, BMessenger listener
,
204 BBitmap
* CreateDestImage(BBitmap
* srcImage
);
205 int32
GetNumberOfUnits();
206 void Run(int32 i
, int32 n
);
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
);