xref: /haiku/src/apps/showimage/Filter.h (revision 93a78ecaa45114d68952d08c4778f073515102f2)
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, int32 i, int32 n, bool runInCurrentThread = false);
67 	~FilterThread();
68 
69 private:
70 	status_t Run();
71 	static status_t worker_thread(void* data);
72 
73 	Filter* fFilter;
74 	int32   fI;
75 	int32   fN;
76 };
77 
78 class Filter {
79 public:
80 	// The filter uses the input "image" as source image
81 	// for an operation executed in Run() method which
82 	// writes into the destination image, that can be
83 	// retrieve using GetBitmap() method.
84 	// GetBitmap() must be called either before Start(),
85 	// or after Start() and IsRunning() returns false.
86 	// To start the operation Start() method has to
87 	// be called. The operation is executed in as many
88 	// threads as GetMaxNumberOfThreads() returns.
89 	// The implementation of GetMaxNumberOfThreads()
90 	// can use CPUCount() to retrieve the number of
91 	// active CPUs at the time the Filter was created.
92 	// IsRunning() is true as long as there are any
93 	// threads running.
94 	// The operation is complete when IsRunning() is false
95 	// and Stop() has not been called.
96 	// To abort an operation Stop() method has to
97 	// be called. Stop() has to be called after Start().
98 	// When the operation is done Completed() is called.
99 	// and only if it has not been aborted, then the listener
100 	// receives a message with the specified "what" value.
101 	Filter(BBitmap* image, BMessenger listener, uint32 what);
102 	virtual ~Filter();
103 
104 	// The bitmap the filter writes into
105 	BBitmap* GetBitmap();
106 	// Removes the destination image from Filter (caller is new owner of image)
107 	BBitmap* DetachBitmap();
108 
109 	// Starts one or more FilterThreads. Returns immediately if async is true.
110 	// Either Wait() or Stop() has to be called if async is true!
111 	void Start(bool async = true);
112 	// Wait for completion of operation
113 	void Wait();
114 	// Has to be called after Start() (even if IsRunning() is false)
115 	void Stop();
116 	// Are there any running FilterThreads?
117 	bool IsRunning() const;
118 
119 	// To be implemented by inherited class (methods are called in this order):
120 	virtual BBitmap* CreateDestImage(BBitmap* srcImage) = 0;
121 	// The number of processing units
122 	virtual int32 GetNumberOfUnits() = 0;
123 	// Should calculate part i of n of the image. i starts with zero
124 	virtual void Run(int32 i, int32 n) = 0;
125 	// Completed() is called when the last FilterThread has completed its work.
126 	virtual void Completed();
127 
128 	// Used by FilterThread only!
129 	void FilterThreadDone();
130 	void FilterThreadInitFailed();
131 
132 	bool IsBitmapValid(BBitmap* bitmap) const;
133 
134 protected:
135 	// Number of threads to be used to perform the operation
136 	int32 NumberOfThreads();
137 	BBitmap* GetSrcImage();
138 	BBitmap* GetDestImage();
139 
140 private:
141 	int32 NumberOfActiveCPUs() const;
142 	// Returns the number of active CPUs
143 	int32 CPUCount() const { return fCPUCount; }
144 
145 	BMessenger     fListener;
146 	uint32         fWhat;
147 	int32          fCPUCount; // the number of active CPUs
148 	bool           fStarted; // has Start() been called?
149 	sem_id         fWaitForThreads; // to exit
150 	int32          fN; // the number of used filter threads
151 	volatile int32 fNumberOfThreads; // the current number of FilterThreads
152 	volatile bool  fIsRunning; // FilterThreads should process data as long as it is true
153 	BBitmap*       fSrcImage;
154 	bool           fDestImageInitialized;
155 	BBitmap*       fDestImage;
156 #if TIME_FILTER
157 	BStopWatch*    fStopWatch;
158 #endif
159 };
160 
161 // Scales and optionally dithers an image
162 class Scaler : public Filter {
163 public:
164 	Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what, bool dither);
165 	~Scaler();
166 
167 	BBitmap* CreateDestImage(BBitmap* srcImage);
168 	int32 GetNumberOfUnits();
169 	void Run(int32 i, int32 n);
170 	void Completed();
171 	bool Matches(BRect rect, bool dither) const;
172 
173 private:
174 	void ScaleBilinear(int32 fromRow, int32 toRow);
175 	void ScaleBilinearFP(int32 fromRow, int32 toRow);
176 	inline void RowValues(float* sum, const uchar* srcData, intType srcW, intType fromX, intType toX, const float a0X, const float a1X, const int32 kBPP);
177 	void DownScaleBilinear(int32 fromRow, int32 toRow);
178 	static inline uchar Limit(intType value);
179 	void Dither(int32 fromRow, int32 toRow);
180 
181 	BBitmap* fScaledImage;
182 	BRect fRect;
183 	bool fDither;
184 };
185 
186 // Rotates, mirrors or inverts an image
187 class ImageProcessor : public Filter {
188 public:
189 	enum operation {
190 		kRotateClockwise,
191 		kRotateCounterClockwise,
192 		kFlipLeftToRight,
193 		kFlipTopToBottom,
194 		kInvert,
195 		kNumberOfAffineTransformations = 4
196 	};
197 
198 	ImageProcessor(enum operation op, BBitmap* image, BMessenger listener, uint32 what);
199 	BBitmap* CreateDestImage(BBitmap* srcImage);
200 	int32 GetNumberOfUnits();
201 	void Run(int32 i, int32 n);
202 
203 private:
204 	int32 BytesPerPixel(color_space cs) const;
205 	inline void CopyPixel(uchar* dest, int32 destX, int32 destY, const uchar* src, int32 x, int32 y);
206 	inline void InvertPixel(int32 x, int32 y, uchar* dest, const uchar* src);
207 
208 	enum operation fOp;
209 	int32 fBPP;
210 	int32 fWidth;
211 	int32 fHeight;
212 	int32 fSrcBPR;
213 	int32 fDestBPR;
214 };
215 
216 #endif
217