EnhancedImage 项目






4.94/5 (21投票s)
2005年9月1日
4分钟阅读

70805

2939
一篇关于如何增强当前图像特性的文章。
引言
众所周知,栅格图像的缩放效果并不理想。如果您尝试缩放图像,会遇到锯齿状像素化的问题。当然,您可以使用矢量图像来解决这个问题。然而,我们仍然需要处理栅格图像。现在,引入EnhancedImage
项目:它通过引入Insets(内边距)概念,巧妙地帮助我们缩放图像。
我曾多次被问及如何缩放栅格图像。我相信,那些从事过Web开发程序员一定遇到过类似的情况。而且,很可能他们多次通过编写自定义代码来实现定制的外观和感觉,来达成临时的解决方案。我将使用一种广为人知的技术来实现所需的效果。这种方法的核心思想很简单:将图片分成几个区域,然后单独绘制它们。关键在于:保持某些区域不变,而拉伸另一些区域以满足所需的图像尺寸。
现在,让我们看一下下面的图片。您可以看到,图像被分成了9个区域。我将它们命名为NW、N、NE、W、Center、E、SW、S和SE,其中N代表北(North),S代表南(South),E代表东(East),W代表西(West)。
为了实现良好的缩放效果,我们将保持所有角部图像不变。然而,中间的区域(如N、W、E、S和Center)都将被缩放(拉伸)。因此,L1、L3、L4和L6是固定的,而L2和L5则需要正确计算。此时,让我向您介绍Insets
类。它只是一个简单的类,用于存储左、上、下和右的值。在之前的图片中,在EnhancedImage
类构造函数中需要的Insets
对象将是中心区域的边框。以下代码提供了关于Insets
用法的详细信息。
总之,EnhancedImage
类可以实现这种平滑的缩放效果。此外,开发人员还可以调整图像的透明度。这里有几点需要解释。您可能知道,.NET中的Image
是一个抽象基类
。然而,它在System.Drawing
命名空间中被定义为一个internal
类。这意味着我们不能简单地基于它派生出一个新类。它为System.Drawing.Bitmap
和System.Drawing.Imaging.Metafile
提供了功能。猜猜看?这两个具体类也是sealed
的,因此不能被扩展!哇!我们该怎么办?这一切都意味着我们不能建立“**是**”(IS-A)的关系,但没有任何东西可以阻止我们建立“**拥有**”(HAS-A)的关系。而这正是我在这里要做的事情。在我的实现中,我有一个名为mPeer
的private
数据成员,用于代表一个基础图像。
代码中最有趣的部分是PrepareRegions()
方法。
//----------------- Regions -----------------
// 0,0 ----- L,0 -------------- R,0 ---- W,0
// | | | |
// | NW | N | NE |
// | | | |
// 0,T ----- L,T -------------- R,T ---- W,T
// | | | |
// | W | C | E |
// | | | |
// 0,B ----- L,B -------------- R,B ---- W,B
// | | | |
// | SW | S | SE |
// | | | |
// 0,H ----- L,H -------------- R,H ---- W,H
//--------------------------------------------
Insets sourceNW = new Insets(0, 0, L, T); // North West
Insets sourceN = new Insets(L, 0, R, T); // North
Insets sourceNE = new Insets(R, 0, W, T); // North East
Insets sourceW = new Insets(0, T, L, B); // West
Insets sourceC = new Insets(L, T, R, B); // Center
Insets sourceE = new Insets(R, T, W, B); // East
Insets sourceSW = new Insets(0, B, L, H); // South West
Insets sourceS = new Insets(L, B, R, H); // South
Insets sourceSE = new Insets(R, B, W, H); // South East
// Update values for destination regions
// (some values don't need to be changed!)
W = Width; // Width (EnhacedImage)
H = Height; // Height (EnhacedImage)
R = W - sourceSE.Width; // Right
B = H - sourceSE.Height; // Bottom
Insets destinationNW = new Insets(0, 0, L, T); // North West
Insets destinationN = new Insets(L, 0, R, T); // North
Insets destinationNE = new Insets(R, 0, W, T); // North East
Insets destinationW = new Insets(0, T, L, B); // West
Insets destinationC = new Insets(L, T, R, B); // Center
Insets destinationE = new Insets(R, T, W, B); // East
Insets destinationSW = new Insets(0, B, L, H); // South West
Insets destinationS = new Insets(L, B, R, H); // South
Insets destinationSE = new Insets(R, B, W, H); // South East
// Now, let's draw all regional pairs one by one...
DrawInsetsOn(g, sourceNW, destinationNW); // North West
DrawInsetsOn(g, sourceN, destinationN); // North
DrawInsetsOn(g, sourceNE, destinationNE); // North East
DrawInsetsOn(g, sourceW, destinationW); // West
DrawInsetsOn(g, sourceE, destinationE); // East
DrawInsetsOn(g, sourceSW, destinationSW); // South West
DrawInsetsOn(g, sourceS, destinationS); // South
DrawInsetsOn(g, sourceSE, destinationSE); // South East
// Should we draw the center piece?
if (mDrawCenter)
DrawInsetsOn(g, sourceC, destinationC); // Center
.
.
.
如果您对细节感兴趣,我建议您仔细研究代码的这一部分。
Using the Code
好的,我们如何使用这个新类?实际上,这非常简单。首先,根据一个*基础图像*创建您的增强图像,提供内边距、您增强图像的所需宽度和高度,当然,还有透明度值。然后,就大功告成了!您就可以使用了。:)
Insets insets = new Insets(left, top, right, bottom);
EnhacedImage enhancedImage = new EnhancedImage(baseImage,
width, height, insets, opacity);
.
.
.
// Let's draw the image somewhere in our program
Graphics g; // Obtain a graphics object here
// We need to obtain the regular representation
// of the enhanced image here
Image reqularImage = enhancedImage.RegularImage;
// And draw it just like any other image.
g.DrawImage(regularImage, x, y); // Draw it as usual at x, y.
关注点
现在是时候看看提供的程序了。它有一些您可以调整的参数。您可以使用内边距调整器(Insets Adjuster)直观地更改内边距点。还可以通过滑动滑块(trackbars)动态更改透明度、宽度和高度。您会发现,通过更改内边距可以实现有趣的效果。同时,请查看名为Scale
Properly(正确缩放)的复选框来查看缩放效果。您会立即意识到常规缩放与正确缩放图像的区别。另外,别忘了尝试应用程序中提供的不同示例图像。
历史
我在Java应用程序中也使用了类似的技术。现在,我已将相同的功能添加到我的C#库中。您可以随时提供反馈和功能请求,以便我们做得更好。
玩得开心!:)
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。