GDI+学习之路6--图象、位图和图元文件

   Microsoft Windows GDI+提供了Image类用于进行光栅图像(位图)和矢量图像(图元文件)。Bitmap类和 Metafile 类都是继承自Image类。Bitmap类通过提供加载、储存和管理光栅图像的其它方法,增强了Image类的功能。Metafile类别通过提供记录和检验矢量图像的其它方法,增强Image类别的功能。

位图类型(Types of Bitmaps)

位图是像素的矩形阵列,而每个像素都由位数组指定其颜色。单个像素的组成位数将决定指派给该像素的色彩数目。例如,如果每个像素都是由 4 个字节成,则可将16种不同的颜色指派给该像素 (2^4 = 16)。下表将显示一些范例,说明可指派给由指定位数所表示的像素的色彩数目。

Bits per pixel

Number of colors that can be assigned to a pixel

1

2^1 = 2

2

2^2 = 4

4

2^4 = 16

8

2^8 = 256

16

2^16 = 65,536

24

2^24 = 16, 777, 216

储存位图的磁盘文件通常都会包含一个或多个信息区块,其中存放每个像素位数、每行的像素数目和数组的行数等信息。这类文件可能也会包含颜色表(又称为调色板)。颜色表会将位图中的数字映射为特定色彩。下图显示一个放大的影像及其位图和色表。每个像素都是由 4 位数字来表示,因此色表中共有 2^4 = 16 个色彩。表格中的每一个色彩都是用 24 位数字来表示:8 位用来表示红色、8 位用来表示绿色,还有 8 位用来表示蓝色。这些数字是以十六进制格式显示:A = 10、B = 11、C = 12、D = 13、E = 14、F = 15。

    请看图片的第 3 行第 5 列的像素。位图中对应的数字为 1。我们可由色表得知 1 代表红色,因此该像素为红色。位图顶端列的所有项目都是 3。我们可由色表得知 3 表示蓝色,因此影像顶端列的所有像素都是蓝色。

注意事项:有些位图是以由下到上的格式储存;位图首行的数目表示的是图片末行的像素

         将索引储存至色彩表的位图称为索引色位图。有些位图并不需要色表。例如,如果位图使用每像素 24 位,则该位图可储存色彩本身,而非存入色表的索引。下图显示直接储存色彩的位图 (每像素 24 位),而不是使用色表。该图同时显示对应影像的放大画面。在位图中,FFFFFF 表示白色、FF0000 代表红色、00FF00 为绿色,而 0000FF 则为蓝色。

图片文件格式

         您可以使用许多标准格式将位图储存在磁盘文件中。GDI+ 支持以下各种图片文件格式。

位图(BMP)

         位图是 Windows 用来储存设备无关和与应用程序无关的图片的标准格式。文件头决定了指定的位图文件的每个像素位数 (1、4、8、15、24、32 或 64)。常见的位图文件为每像素 24 位。通常 BMP 档不会被压缩,因此并不适合透过因特网传输。

图像交换格式(GIF)

         GIF是Web网页上常见的图片格式。GIF非常适用于线条图形,具有实色块的图片和色彩之间具有明显界线的图片。GIF可被压缩而且不会在压缩过程中遗失任何信息;解压后的影像将和原始影像完全相同。GIF的色彩可指定为透明,这样一来影像则可以显示该影像的Web网页作为背景色彩。GIF影像的序列可储存在单一档案中,作为动画GIF。GIF最多储存为每像素8位,这样便将它们限制在256色彩。

联合图像专家组(JPEG)

JPEG是一种压缩结构,适用于自然景观图片,例如扫描的照片。有些信息可能会在压缩过程中丧失,但肉眼并无法看出变化。JPEG可储存每像素24位,因此它们可以显示超过1千6百万个色彩。JPEG不支持透明效果或动画。

您可以设定JPEG图片文件的压缩比,但压缩比越高 (档案越小),便会丢失更多信息。通常肉眼无法辨识以20:1的压缩比所产生的图片和源文件之间的差异。下图将显示BMP图片和两个从该BMP图片压缩而来的JPEG图片。第一个JPEG的压缩比率为4:1,第二个JPEG的压缩比率约为8:1。

JPEG 压缩不适用于线条图形、实色块和明显的界线。下图将显示一个BMP和两个JPEG及一个 GIF。这两个JPEG和GIF都是从BMP压缩而来的。GIF的压缩比率为4:1、较小的JPEG 为4:1,较大的JPEG为8:3。请注意,GIF中的线条间仍然出现明显边界,但JPEG中的边界似乎比较模糊。


         JPEG 是一种压缩公式,而非文件格式。JPEG档案交换格式(JFIF)才是通常来储存和传送图片的文件格式,它们是根据JPEG公式进行压缩。Web浏览器显示的JFIF文件将使用.jpg扩展名。

可交换图像文件(Exif)

         EXIF 是用于数字相机所拍摄的相片文件格式。EXIF 文件包含一个根据 JPEG规范来压缩的图片。EXIF文件同时还包含了照片信息 (拍摄日期、快门速度、曝光时间等信息) 和相机信息 (制造商、型号等信息)。

可移植网络图片(PNG)

         PNG格式保留了许多GIF格式的优点,同时提供比GIF更强大的功能。PNG文件和GIF文件同样都不会在压缩过程中丧失任何信息。PNG文件可储存每像素8、24或48位的色彩,以及每像素1、2、4、8或16位的灰阶。相较之下,GIF档只能使用每像素1、2、4或8位。PNG文件还可储存每个像素的Alpha值,指定该像素与背景色彩混合的程度。

         PNG改进了GIF渐进式显示影像的功能;当PNG收到透过网络联机传送的影像时,可以显示较佳的影像效果。PNG文件可包含Gamma修正和色彩修正信息,这样一来可将影像正确地对应到各种不同的显示装置。

标记图像文件格式(TIFF)

         TIFF 是一种灵活且可扩充的格式,各种平台和图片处理应用程序都支持这种格式。TIFF 文件可储存每像素任意位数的图片,并可使用各种压缩算法。单一、多页的TIFF文件可储存数个影像。影像相关信息 (扫描仪制作、主机计算机、压缩类型、方向、每像素范例等等)也可储存在档案中,并可使用标记进行排列。TIFF格式可按照需要(如情况允许而且必须增加新的标记)进行扩充。

图元文件(MetaFiles)

         Microsoft Windows GDI+提供Metafile类来记录和显示图元文件。图元文件又称为矢量图片,这种图片被储存为一种绘图命令和设定的序列。Metafile对象中所记录的命令和设定可储存于内存或储存至文件或数据流。

         GDI+ 可显示储存为下列格式的图元文件:

 

Windows Metafile Format (WMF)

Enhanced Metafile (EMF)

EMF+

GDI+可记录EMF和EMF+格式的图元文件,但无法记录WMF格式的图元文件。

EMF+是EMF的功能扩充,可用来储存GDI+记录。EMF+格式有两种变化:EMF+ Only 和 EMF+ Dual。EMF+ Only图元文件仅包含GDI+记录。此类图元文件可由GDI+显示,但无法使用GDI显示。EMF+ Dual图元文件包含GDI+和GD记录。EMF+ Dual图元文件的每个GDI+数据录都会与替代GDI记录配对。此类图元文件可同时由GDI+或GDI显示。

下列范例将存储一个设置语句和一条绘图命令到一个磁盘文件中。注意这里构造一个Graphics对象,而且是通过在构造函数中传递一个MetaFile对象作为参数来构造的。

myMetafile = new Metafile(L"MyDiskFile.emf", hdc);

myGraphics = new Graphics(myMetafile);

myPen = new Pen(Color(255, 0, 0, 200));

myGraphics->SetSmoothingMode(SmoothingModeAntiAlias);

myGraphics->DrawLine(myPen, 0, 0, 60, 40);

delete myGraphics;

delete myPen;

delete myMetafile;

         如上例所示,Graphics类是将指令和设置保存到Metafile对象的关键。任何对Graphics对象进行的方法调用均被记录到Metafile对象中。同样地,您可以设置任何Graphics对象的属性并将这个设置保存到Metafile对象中。在Graphics对象被删除或者超出作用域的时候,将停止记录。

         下列范例显示先前储存为档案的图元文件。图元文件的左上角显示在 (100, 100)。

Graphics myGraphics(hdc);

Image myImage(L"MyDiskFile.emf");

myGraphics.DrawImage(&myImage, 100, 100);

         下列范例记录多个属性设置(剪切区域、世界变换和平滑模式)到Metafile对象中。然后代码将记录多个绘图指令,然后将这些指令和设置都保存到一个磁盘文件中。

myMetafile = new Metafile(L"MyDiskFile2.emf", hdc);

myGraphics = new Graphics(myMetafile);

myGraphics->SetSmoothingMode(SmoothingModeAntiAlias);

myGraphics->RotateTransform(30);

 

// Create an elliptical clipping region.

GraphicsPath myPath;

myPath.AddEllipse(0, 0, 200, 100);

Region myRegion(&myPath);

myGraphics->SetClip(&myRegion);

 

Pen myPen(Color(255, 0, 0, 255));

myGraphics->DrawPath(&myPen, &myPath);

 

for(INT j = 0; j <= 300; j += 10)

{

   myGraphics->DrawLine(&myPen, 0, 0, 300 - j, j);

}

delete myGraphics;

delete myMetafile;

下列范例显示先前储存为档案的图元文件。

myGraphics = new Graphics(hdc);

myMetafile = new Metafile(L"MyDiskFile.emf");

myGraphics->DrawImage(myMetafile, 10, 10);

下图显示了前面代码的执行结果。注意观察抗锯齿效果、椭圆形裁剪和30度角旋转。

绘制、定位和复制图片(Drawing, Positioning, and Cloning Images)

         您可以使用Image类来加载和显示点阵图片(位图)和矢量图片(图元文件)。若要显示图片,您需要一个Graphics对象和一个Image对象。Graphics对象提供DrawImage方法来接收Image对象作为它的一个参数。

         下列代码示例会示范如何从Climber.jpg文件建立一个Image对象并显示此图片。图片左上角目标点 (10, 10) 是由第二个和第三个参数指定。

Image myImage(L"Climber.jpg");

myGraphics.DrawImage(&myImage, 10, 10);

         上面的代码执行效果如图:

         您可以使用下列各种图形文件格式来建构Image对象:BMP、GIF、JPEG、EXIF、PNG、TIFF 和 ICON。

         下列代码示例会示范如何从各种文件类型建立Image对象,并显示该图片。

Image myBMP(L"SpaceCadet.bmp");

Image myEMF(L"Metafile1.emf");

Image myGIF(L"Soda.gif");

Image myJPEG(L"Mango.jpg");

Image myPNG(L"Flowers.png");

Image myTIFF(L"MS.tif");

 

myGraphics.DrawImage(&myBMP, 10, 10);

myGraphics.DrawImage(&myEMF, 220, 10);

myGraphics.DrawImage(&myGIF, 320, 10);

myGraphics.DrawImage(&myJPEG, 380, 10);

myGraphics.DrawImage(&myPNG, 150, 200);

myGraphics.DrawImage(&myTIFF, 300, 200);

         Image类提供Clone方法,可用来制作现有Image、Metafile或者Bitmap对象的副本。Clone方法在Bitmap类中进行了重载,变体之一具有来源矩形参数,可指定您要复制的原始位图区域。下列程序代码范例会示范如何藉由复制现有Bitmap上半部来建立Bitmap。然后同时显示这两个图象。

Bitmap* originalBitmap = new Bitmap(L"Spiral.png");

RectF sourceRect(

   0.0f,

   0.0f,

   (REAL)(originalBitmap->GetWidth()),

   (REAL)(originalBitmap->GetHeight())/2.0f);

 

Bitmap* secondBitmap = originalBitmap->Clone(sourceRect, PixelFormatDontCare);

 

myGraphics.DrawImage(originalBitmap, 10, 10);

myGraphics.DrawImage(secondBitmap, 100, 10);

         上面的代码执行效果如图:

裁剪和缩放图象(Cropping and Scaling Images)

         您可以使用Graphics类的DrawImage方法来绘制并定位图像。DrawImage是一个重载方法,因此可使用许多种方法提供自变量给它。DrawImage方法的其中一个变体可接收Image对象的地址和Rectangle对象的引用。矩形可指定绘图操作的目标位置;也就是说,它可以指定绘制图片的位置。如果目的矩形的大小和原始图片大小并不相同,该图片将缩放至适合目的矩形的大小。下列程序代码范例会示范如何绘制三次相同的图片:一次不使用缩放、一次使用放大,还有一次使用缩小:

Bitmap myBitmap(L"Spiral.png");

Rect expansionRect(80, 10, 2 * myBitmap.GetWidth(), myBitmap.GetHeight());

Rect compressionRect(210, 10, myBitmap.GetWidth() / 2,  myBitmap.GetHeight() / 2);

myGraphics.DrawImage(&myBitmap, 10, 10);

myGraphics.DrawImage(&myBitmap, expansionRect);

myGraphics.DrawImage(&myBitmap, compressionRect);

上面代码执行效果如图:

         有些DrawImage方法的变体具有来源矩形参数和目的矩形参数。来源矩形参数指定要绘制的原始图片区域。目的矩形指定用来绘制该图片区域的位置。如果目的矩形大小和来源矩形大小并不相同,图片将缩放至适合目的矩形的大小。

         下列程序代码范例会示范如何从Runner.jpg文档构造一个Bitmap对象。整个图片从 (0, 0) 开始绘制,且不进行缩放。接着图片中的一小部分会绘制两次:一次使用缩小,另一次使用放大。

Bitmap myBitmap(L"Runner.jpg");

 

// The rectangle (in myBitmap) with upper-left corner (80, 70),

// width 80, and height 45, encloses one of the runner's hands.

 

// Small destination rectangle for compressed hand.

Rect destRect1(200, 10, 20, 16);

 

// Large destination rectangle for expanded hand.

Rect destRect2(200, 40, 200, 160);

 

// Draw the original image at (0, 0).

myGraphics.DrawImage(&myBitmap, 0, 0);

 

// Draw the compressed hand.

myGraphics.DrawImage(&myBitmap, destRect1, 80, 70, 80, 45, UnitPixel);

 

// Draw the expanded hand.

myGraphics.DrawImage(&myBitmap, destRect2, 80, 70, 80, 45, UnitPixel);

         下列图标将显示未缩放的影像,以及经过缩小和放大的影像部分。

http://blog.csdn.net/backo880607/article/details/6400339

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值