xref: /haiku/src/apps/showimage/Filter.h (revision d5cd5d63ff0ad395989db6cf4841a64d5b545d1d)
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