1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: DrawingTidbits.cpp,v 1.2.4.1 2002/09/03 12:00:24 tcastley Exp $
7 * Authors: Tony Castley <tcastley@mail.powerup.com.au>
8 * Stephan Aßmus <stippi@yellowbites.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
29 #include "DrawingTidbits.h"
33 ShiftComponent(uchar component, float percent)
35 // change the color by <percent>, make sure we aren't rounding
36 // off significant bits
38 return (uchar)(component * (2 - percent));
40 return (uchar)(255 - percent * (255 - component));
45 ShiftColor(rgb_color color, float percent)
48 ShiftComponent(color.red, percent),
49 ShiftComponent(color.green, percent),
50 ShiftComponent(color.blue, percent),
59 CompareColors(const rgb_color a, const rgb_color b)
64 && a.alpha == b.alpha;
69 operator==(const rgb_color &a, const rgb_color &b)
71 return CompareColors(a, b);
76 operator!=(const rgb_color &a, const rgb_color &b)
78 return !CompareColors(a, b);
83 ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to)
85 ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet
87 BScreen screen(B_MAIN_SCREEN_ID);
88 uint32 fromIndex = screen.IndexForColor(from);
89 uint32 toIndex = screen.IndexForColor(to);
91 uchar *bits = (uchar *)bitmap->Bits();
92 int32 bitsLength = bitmap->BitsLength();
93 for (int32 index = 0; index < bitsLength; index++)
94 if (bits[index] == fromIndex)
95 bits[index] = toIndex;
98 // ReplaceTransparentColor
100 ReplaceTransparentColor(BBitmap *bitmap, rgb_color with)
102 ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet
104 BScreen screen(B_MAIN_SCREEN_ID);
105 uint32 withIndex = screen.IndexForColor(with);
107 uchar *bits = (uchar *)bitmap->Bits();
108 int32 bitsLength = bitmap->BitsLength();
109 for (int32 index = 0; index < bitsLength; index++)
110 if (bits[index] == B_TRANSPARENT_8_BIT)
111 bits[index] = withIndex;
117 convert_bitmap(BBitmap* inBitmap, BBitmap* outBitmap)
119 status_t status = B_BAD_VALUE;
120 /* // see that we got valid bitmaps
121 if (inBitmap && inBitmap->IsValid()
122 && outBitmap && outBitmap->IsValid())
124 status = B_MISMATCHED_VALUES;
125 // see that bitmaps are compatible and that we support the conversion
126 if (inBitmap->Bounds().Width() == outBitmap->Bounds().Width()
127 && inBitmap->Bounds().Height() == outBitmap->Bounds().Height()
128 && (outBitmap->ColorSpace() == B_RGB32
129 || outBitmap->ColorSpace() == B_RGBA32))
131 int32 width = inBitmap->Bounds().IntegerWidth() + 1;
132 int32 height = inBitmap->Bounds().IntegerHeight() + 1;
133 int32 srcBpr = inBitmap->BytesPerRow();
134 int32 dstBpr = outBitmap->BytesPerRow();
135 uint8* srcbits = (uint8*)inbitmap->bits();
136 uint8* dstbits = (uint8*)outbitmap->bits();
137 switch (inBitmap->ColorSpace())
140 for (int32 y = 0; y < height; y ++)
142 for (int32 x = 0; x < width; x += 2)
160 memcpy(dstBits, srcBits, inBitmap->BitsLength());
164 status = B_MISMATCHED_VALUES;
174 clip_float(float value)
185 dim_bitmap(BBitmap* bitmap, rgb_color center, float dimLevel)
187 status_t status = B_BAD_VALUE;
188 if (bitmap && bitmap->IsValid())
190 switch (bitmap->ColorSpace())
194 BScreen screen(B_MAIN_SCREEN_ID);
195 if (screen.IsValid())
197 // iterate over each pixel, get the respective
198 // color from the screen object, find the distance
199 // to the "center" color and shorten the distance
201 int32 length = bitmap->BitsLength();
202 uint8* bits = (uint8*)bitmap->Bits();
203 for (int32 i = 0; i < length; i++)
205 // preserve transparent pixels
206 if (bits[i] != B_TRANSPARENT_MAGIC_CMAP8)
208 // get color for this index
209 rgb_color c = screen.ColorForIndex(bits[i]);
211 float dist = (c.red - center.red) * dimLevel;
212 c.red = clip_float(center.red + dist);
214 dist = (c.green - center.green) * dimLevel;
215 c.green = clip_float(center.green + dist);
217 dist = (c.blue - center.blue) * dimLevel;
218 c.blue = clip_float(center.blue + dist);
219 // write correct index of the dimmed color
220 // back into bitmap (and hope the match is close...)
221 bits[i] = screen.IndexForColor(c);
231 // iterate over each color component, find the distance
232 // to the "center" color and shorten the distance
234 uint8* bits = (uint8*)bitmap->Bits();
235 int32 bpr = bitmap->BytesPerRow();
236 int32 pixels = bitmap->Bounds().IntegerWidth() + 1;
237 int32 lines = bitmap->Bounds().IntegerHeight() + 1;
238 // iterate over color components
239 for (int32 y = 0; y < lines; y++) {
240 for (int32 x = 0; x < pixels; x++) {
241 int32 offset = 4 * x; // four bytes per pixel
243 float dist = (bits[offset + 0] - center.blue) * dimLevel;
244 bits[offset + 0] = clip_float(center.blue + dist);
246 dist = (bits[offset + 1] - center.green) * dimLevel;
247 bits[offset + 1] = clip_float(center.green + dist);
249 dist = (bits[offset + 2] - center.red) * dimLevel;
250 bits[offset + 2] = clip_float(center.red + dist);
251 // ignore alpha channel
267 // dimmed_color_cmap8
269 dimmed_color_cmap8(rgb_color color, rgb_color center, float dimLevel)
271 BScreen screen(B_MAIN_SCREEN_ID);
272 if (screen.IsValid())
275 float dist = (color.red - center.red) * dimLevel;
276 color.red = clip_float(center.red + dist);
278 dist = (color.green - center.green) * dimLevel;
279 color.green = clip_float(center.green + dist);
281 dist = (color.blue - center.blue) * dimLevel;
282 color.blue = clip_float(center.blue + dist);
283 // get color index for dimmed color
284 int32 index = screen.IndexForColor(color);
285 // put color at index (closest match in palette
286 // to dimmed result) into returned color
287 color = screen.ColorForIndex(index);