cb200005rh_f.asp.htm
来自「C++builder学习资料C++builder」· HTM 代码 · 共 956 行 · 第 1/3 页
HTM
956 行
<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=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>if</b> (SourceAsBitmap) </span></p>
<p class=Code><span class=Code> SourceAsBitmap->Assign(bmp); </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> <b> delete</b>
mask; </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=Captions><b>Figure
4: </b>Code for the <i>GrayScale</i>
function. </p>
<p class=BodyText> </p>
<p class=BodyText> <i>GrayScale</i> accepts an image in any supported
graphic format. If the source image isn't a bitmap, then a destination bitmap
must be supplied. The resulting grayscaled image will always be a bitmap, no
matter what type of image is passed in as the source. If a destination bitmap
is supplied, the grayscaled bitmap will be assigned to it. If not, then the grayscaled
bitmap will be copied back into the source image. During the grayscale process,
the image may be lightened or darkened using the <i>Brightness</i> parameter. </p>
<p class=BodyText> </p>
<p class=BodyText> You may
have noticed the reference to the <i>Graphics::TBitmap</i> data type in the
source code in Figure 4. The compiler will encounter two different <i
style='mso-bidi-font-style:normal'>TBitmap</i> data types. If we don't specify
a qualifier, an error will occur stating that there's an ambiguity. The <i
style='mso-bidi-font-style:normal'>TBitmap</i> we want is defined in the
Graphics unit, and the other one is in the Windows unit. </p>
<p class=BodyText> </p>
<p class=BodyText> Two
local bitmaps are used to encapsulate the process: <i>bmp</i> holds a copy of the source and will be processed in place; <i>mask</i>
holds a copy of <i>bmp</i>, which is turned
into a monochrome mask using the <i>Mask</i> method. </p>
<p class=BodyText> </p>
<p class=BodyText> The
logic can be separated into five primary steps: </p>
<p class=BodyText> 1)
Ensure
there is a place to put the processed bitmap. </p>
<p class=BodyText> 2)
Copy
the source image to a local bitmap. </p>
<p class=BodyText> 3)
Generate
a mask from the local bitmap. </p>
<p class=BodyText> 4)
For
every pixel in the local bitmap, check the mask. If the corresponding pixel in
the mask is black, convert its color to a shade of gray in the local bitmap. </p>
<p class=BodyText> 5)
Copy
the local bitmap to the destination bitmap, if supplied, or back into the
source. </p>
<p class=BodyText> </p>
<p class=BodyText> <b>Ensure
there is a place to put the processed bitmap.</b> If you're unfamiliar with the <b>dynamic_cast </b>construct, then
the code shown in Figure 5 may be confusing. </p>
<p class=BodyText> </p>
<p class=Code><span class=Code>Graphics::TBitmap
* SourceAsBitmap =</span></p>
<p class=Code><span class=Code> <b> dynamic_cast</b><Graphics::TBitmap*>(Source); </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code><b>if</b>
(Source && (SourceAsBitmap || Dest)) </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> try</b></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=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> <b> delete</b>
mask; </span></p>
<p class=Code><span class=Code> } </span></p>
<p class=Code><span class=Code>}</span></p>
<p class=Captions><b>Figure
5:</b> Placing the
processed bitmap. </p>
<p class=BodyText> </p>
<p class=BodyText> This
simply uses run-time type identification (RTTI) to determine whether an object
is of a given type. In this case, <i>Source</i>
is a <i>TGraphic</i>, but we don't know which kind. <i>TGraphic</i> is an abstract class from which <i>TBitmap</i>, <i>TIcon</i>, and <i
style='mso-bidi-font-style:normal'>TMetaFile</i> descend. The local variable, <i
style='mso-bidi-font-style:normal'>SourceAsBitmap</i>, will be assigned NULL unless <i>Source</i> is actually a <i>TBitmap</i>.
This way we can test whether we should even process the image, because it would
be a waste of processor cycles if there's no place to put the result. Note the
use of the <b>try..finally</b> block to ensure our local variables are always
properly destroyed. </p>
<p class=BodyText> </p>
<p class=BodyText> <b>Copy
the source image to a local bitmap.</b> When copying one bitmap to another, we can simply call the <i>Assign</i>
method: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code>bmp->Assign(Source); </span></p>
<p class=BodyText> </p>
<p class=BodyText> Because
we don't know what kind of image <i>Source</i>
is, however, we may need to do some extra work. The code in <i
style='mso-bidi-font-style:normal'>CopyGraphicToBitmap</i> was initially a part
of <i>GrayScale</i>, but it's useful in its
own right (see Figure 6). </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><b>void</b>
CopyGraphicToBitmap(TGraphic *Source, </span></p>
<p class=Code><span class=Code> Graphics::TBitmap *Dest, TColor
TransparentColor) </span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code> Graphics::TBitmap * SourceAsBmp =</span></p>
<p class=Code><span class=Code> <b> dynamic_cast</b><Graphics::TBitmap
*>(Source); </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> <b> if</b>
(Source && Dest) </span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> <b> if</b>
(SourceAsBmp) </span></p>
<p class=Code><span class=Code> Dest->Assign(Source); </span></p>
<p class=Code><span class=Code> <b> else</b></span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> Dest->Height = Source->Height; </span></p>
<p class=Code><span class=Code> Dest->Width = Source->Width; </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> Dest->Canvas->Brush->Color =
TransparentColor; </span></p>
<p class=Code><span class=Code> </span></p>
<p class=Code><span class=Code> Dest->Canvas->FillRect(Dest->Canvas->ClipRect); </span></p>
<p class=Code><span class=Code> Dest->Canvas->Draw(0, 0, Source); </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=Captions><b>Figure
6:</b> The <i>CopyGraphicToBitmap</i>
function. </p>
<p class=BodyText> </p>
<p class=BodyText> The
purpose of this function is to end up with a bitmap that preserves the
transparency of the original image. If the source image is a bitmap, it can
simply be assigned to the destination bitmap. The <i>Assign</i> method is introduced in <i>TPersistent</i>
as a way of copying one object to another. For most persistent objects, only
objects of the same type can be copied. This holds true for <i
style='mso-bidi-font-style:normal'>TBitmap</i>, which will only accept another <i>TBitmap</i> in its <i>Assign</i>
method. </p>
<p class=BodyText> </p>
<p class=BodyText> If the
source image is not a bitmap, then we need to draw it onto the destination.
This is done in three steps: </p>
<p class=BodyText> 1)
Ensure
the copy is sized to match the source image. We're going to use the <i>Canvas</i>
<i>Draw</i> method, which will only draw on the available surface area of the
copy. </p>
<p class=BodyText> 2)
Fill
the copy with the <i>TransparentColor</i>. <i>ClipRect</i> returns the area on
which any kind of drawing will have an effect. </p>
<p class=BodyText> 3)
Draw
the source image onto the copy. </p>
<p class=BodyText> </p>
<p class=BodyText> The
important thing to remember as you look at this code is that icons and
metafiles only draw the areas that are not transparent. If a background color
isn't provided, it will likely be white. When the resulting bitmap is used in a
context that requires transparency, white will likely be chosen as the
transparent color. If the image itself uses white, those areas will wash out. </p>
<p class=BodyText> </p>
<p class=BodyText> <b>Generate
a mask from the local bitmap.</b> This is pretty straightforward. First we copy the local bitmap
into the mask bitmap. Then the <i>Mask</i> method uses a given color to convert
from a color bitmap into a monochrome bitmap. <i>TransparentColor</i> will be the color we used to fill in the
background if the source image isn't a bitmap: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code>mask->Assign(bmp); </span></p>
<p class=Code><span class=Code>mask->Mask(bmp->TransparentColor); </span></p>
<p class=Code><span class=Code> </span></p>
<p class=BodyText> Keep in
mind that the <i>TransparentColor</i>
property is retrieved from the lower-left pixel. Occasionally, an image may
actually include that pixel as part of the drawing. This code doesn't handle
that case. <i>TransparentColor</i> would
have to be set to a fixed value. I'll leave that case as an exercise for you. </p>
<p class=BodyText> </p>
<p class=BodyText> <b>For
every pixel in the local bitmap, check the mask. </b>The code below is the source for
this step: </p>
<p class=BodyText> </p>
<p class=Code><span class=Code><b>for</b> (<b
style='mso-bidi-font-weight:normal'>int</b> y = 0; y < bmp->Canvas->ClipRect.Bottom;
y++)</span></p>
<p class=Code><span class=Code>{</span></p>
<p class=Code><span class=Code> <b> for</b>
(<b>int</b> x = 0; x <
bmp->Canvas->ClipRect.Right; x++)</span></p>
<p class=Code><span class=Code> { </span></p>
<p class=Code><span class=Code> <b> if</b>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?