cb200005rh_f.asp.htm
来自「C++builder学习资料C++builder」· HTM 代码 · 共 956 行 · 第 1/3 页
HTM
956 行
(mask->Canvas->Pixels[x][y] == clBlack) </span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> bmp->Canvas->Pixels[x][y] =</span></p>
<p class=Code><span class=Code> ShadeOfGray(bmp->Canvas->Pixels[x][y], Brightness); </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code>}</span></p>
<p class=BodyText> </p>
<p class=BodyText> The <i
style='mso-bidi-font-style:normal'>ShadeOfGray</i> function is named for each
pixel that is masked. This is the real workhorse of the <i>GrayScale</i> function (see Figure 7). </p>
<p class=BodyText> </p>
<p class=Code><span class=Code>TColor
ShadeOfGray(TColor Color, Shortint Brightness) </span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code> Byte r = RED(Color), </span></p>
<p class=Code><span class=Code> g = GREEN(Color), </span></p>
<p class=Code><span class=Code> b = BLUE(Color); </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> <b> int</b>
avg = ((r + g + b) / 3) + Brightness; </span></p>
<p class=Code><span class=Code> Byte gray = (Byte) LIMIT(avg, 0, 255); </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> <b> return</b>
(TColor) RGB(gray, gray, gray); </span></p>
<p class=Code><span class=Code>}</span></p>
<p class=Captions><b>Figure
7: </b>The <i>ShadeOfGray</i>
function. </p>
<p class=BodyText> </p>
<p class=BodyText> To
understand the <i>ShadeOfGray</i> function,
it's necessary to understand the macros that support it. Given a composite
color value, the RED, GREEN, and BLUE macros determine the intensity of each of
the corresponding constituent colors. <i>TColor</i>
is defined as an enumerated data type, which is, of course, compatible with an
integer. In reality, though, the 32-bit value is mapped into four separate
bytes (see Figure 8). </p>
<p class=BodyText> </p>
<p class=Captions><img width=330 height=213
src="images/cb200005rh_f_image005.gif" tppabs="http://www.cbuilderzine.com/features/2000/05/cb200005rh_f/cb200005rh_f_image005.gif"> <br>
<b>Figure 8:</b> Byte layout of a color value
(values are hexadecimal). </p>
<p class=BodyText> </p>
<p class=BodyText> For
example, the value 0x000000FF is pure Red, 0x0000FF00 is pure Green, and
0x00FF0000 is pure Blue. When all three colors are at the same intensity, the
result is a shade of gray. Using this definition, black is the darkest shade of
gray (0x00000000) and white is the brightest (0x00FFFFFF). </p>
<p class=BodyText> </p>
<p class=BodyText> The
value of any color intensity can be obtained by isolating its byte position.
For Red this means simply <b>and</b>ing the value with 0xFF, the highest value
a byte can hold. This has the effect of trimming off the byte positions to the
left leaving only the Red value. For Green, we need to shift the color value to
the right by 8 bits (1 byte) and, again, with 0xFF to zero out the other bytes.
The same process applies to Blue, except that we shift to the right by 16 bits
(2 bytes): </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><span Class=CodeGrn>#define
RED(value) (Byte) (value & 0xFF) </span></span></p>
<p class=Code><span class=Code><span Class=CodeGrn>#define
GREEN(value) (Byte) ((value >> 8) & 0xFF) </span></span></p>
<p class=Code><span class=Code><span Class=CodeGrn>#define
BLUE(value) (Byte) ((value >> 16) & 0xFF) </span></span></p>
<p class=BodyText> </p>
<p class=BodyText> In the <i
style='mso-bidi-font-style:normal'>ShadeOfGray</i> function, we use these
macros to get the intensities for each of the Red, Green, and Blue values. Then
we average them and add the <i>Brightness</i> value. Many images tend to be
darker when grayscaled. Adding or subtracting a value to the average of the
colors will lighten or darken the resulting shade of gray. Adding or
subtracting to the average can also cause the value to go below zero, or above
255 (the maximum value of a byte). The LIMIT macro resolves this issue: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><span Class=CodeGrn>#define
LIMIT(value, low, high) ((value < low) ? low : ((value > high) ? high :
value)) </span></span></p>
<p class=BodyText> </p>
<p class=BodyText> Casting
a signed ordinal value (<i>int</i>) to an unsigned value (<i>Byte</i>) can
result in the value "wrapping." For example, the integer value -10 becomes the <i>Byte</i>
value 245, and the integer value 300 becomes the <i>Byte</i> value 45. This is
undesirable in the case where we are attempting to lighten or darken our
grayscale value. We want negative values to come out as zero, and positive
values greater than 255 to be 255. </p>
<p class=BodyText> </p>
<p class=BodyText> The RGB
macro from the Windows API is used to create a composite color from individual
red, green, and blue values. Once the gray value has been determined, the RGB
macro is called passing the same value - the grayscale value - for each color. </p>
<p class=BodyText> </p>
<p class=BodyText> Once all
of the masked pixels have been processed, we're ready for the last step. </p>
<p class=BodyText> </p>
<p class=BodyText> <b>Copy
the local bitmap to the destination bitmap, if supplied, or back into the
source.</b> Here's the
source code for this step: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><b>if</b>
(Dest) </span></p>
<p class=Code><span class=Code> Dest->Assign(bmp); </span></p>
<p class=Code><span class=Code><b>else</b> <b
style='mso-bidi-font-weight:normal'>if</b> (SourceAsBitmap) </span></p>
<p class=Code><span class=Code> SourceAsBitmap->Assign(bmp); </span></p>
<p class=BodyText> </p>
<p class=BodyText> Now that
the local bitmap has been placed, the grayscale process is complete. It's time
to apply this process to ImageLists. </p>
<p class=BodyText> </p>
<p class=Subheads>The
Grayscaled ImageList Component</p>
<p class=BodyText> The <i
style='mso-bidi-font-style:normal'>TGSImageList</i> component included with
this article is derived from <i>TCustomImageList</i>. Therefore, it has all of
the capabilities of an ImageList, but many of the properties are protected.
This allows us to surface only the properties we want. We don't want the
component user to change the images. We've added one key property: <i>ImageList</i>.
When the <i>ImageList</i> property is assigned to point to a normal ImageList,
the normal images are automatically copied and grayscaled. </p>
<p class=BodyText> </p>
<p class=BodyText> The
dynamic nature of <i>GSImageList</i> is important, because images are often
added at run time. Using the <i>SHGetFileInfo</i> function, "system" ImageLists
containing file icons can be accessed. (Further discussion of system ImageLists
is beyond the scope of this article.) Assigning the <i>ImageList</i> property
causes the <i>Refresh</i> method to be called (see Figure 9). </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><b>void</b> <b
style='mso-bidi-font-weight:normal'>__fastcall</b> TGSImageList::Refresh(<b
style='mso-bidi-font-weight:normal'>void</b>)</span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code> Graphics::TBitmap * bmp; </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> Clear();</span></p>
<p class=Code><span class=Code> bmp = <b>new</b>
Graphics::TBitmap; </span></p>
<p class=Code><span class=Code> bmp->Height = ImageList->Height; </span></p>
<p class=Code><span class=Code> bmp->Width = ImageList->Width; </span></p>
<p class=Code><span class=Code> bmp->TransparentColor = clPurple; </span></p>
<p class=Code><span class=Code> <b> try</b></span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> <b> for</b>
(<b>int</b> i = 0; i < ImageList->Count;
i++)</span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> bmp->Canvas->Brush->Color =
bmp->TransparentColor; </span></p>
<p class=Code><span class=Code> bmp->Canvas->FillRect(bmp->Canvas->ClipRect); </span></p>
<p class=Code><span class=Code> ImageList->GetBitmap(i, bmp); </span></p>
<p class=Code><span class=Code> GrayScale(bmp, NULL, 20); </span></p>
<p class=Code><span class=Code> AddMasked(bmp,
bmp->TransparentColor); </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code> <b> __finally</b></span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> <b> delete</b>
bmp; </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code>}</span></p>
<p class=Captions><b>Figure
9:</b> The <i>Refresh</i>
method of <i>TGSImageList</i>.</p>
<p class=BodyText> </p>
<p class=BodyText> The <i>Refresh</i>
method can be separated into three steps: </p>
<p class=BodyText> 1)
Empty
the current bitmap list. </p>
<p class=BodyText> 2)
Create
a bitmap that is the size specified by the <i>Height</i> and <i>Width</i>
properties. All images in an ImageList are exactly the same size. This bitmap
will be re-used for each bitmap in the assigned (full-color) ImageList. The
default color for transparency will be purple (applies to images other than
bitmaps, such as icons). </p>
<p class=BodyText> 3)
For
each image in the full-color ImageList, <i>GrayScale</i>
it and add it the internal list using the <i>AddMasked</i>
method. The temporary bitmap is filled with the default <i>TransparentColor</i>, so an icon or metafile will retain its
transparency when converted to a bitmap. </p>
<p class=BodyText> </p>
<p class=BodyText> You may
install this component and use it any way you please. When you install it, make
sure all three <i>GSImageLists</i> source files (.cpp, .h and .dcr) are in the
same directory. The .dcr file contains a bitmap resource that will be
associated with the GSImageList component on the Component palette. </p>
<p class=BodyText> </p>
<p class=Subheads>Conclusion</p>
<p class=BodyText> Just a
few touches can often have a big impact on how a user perceives a given piece
of software. Microsoft has mastered the art of making a product seem fresh by
changing its visual aspects. The grayscaled ImageList isn't a major
enhancement, and doesn't even add appreciable functionality. But using such
subtle visual enhancements implies an attention to detail that can help assure
- or convince - your users that you're on top of the latest technologies. </p>
<p class=BodyText> </p>
<p class=BodyText> Updates
to this article and the accompanying source code can be found in the Reusable
Objects library at <span Class=CodeBlue><a
href="http://reusable.com/Library">http://reusable.com/Library</a></span>.<span Class=CodeBlue></span></p>
<p class=BodyText> </p>
<p class=BodyText> <i>The
files accompanying this article are available for <a href="download/cb200005rh_f.zip" tppabs="http://www.cbuilderzine.com/features/2000/05/cb200005rh_f/cb200005rh_d.asp">download</a>. </i></p>
<p class=BodyText> </p>
</td>
</TR>
</TABLE>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?