第十章:PNG 输出

PNG格式概述

便携式网络图形工,或者说PNG,基于一个无损的压缩算法,支持多种颜色方案,包括真彩色。这使它成为JPEG和GIF格式的一个可行的替代。

JPEG的有损压缩算法,在照片中工作得很好,但是在带有锐利边缘的图像中,比如说在绘图、图标和图形中,实现得很糟糕。下面的“随机艺术”图像分别被保存为JPEG和PNG。前者显得有些不雅观的人工痕迹,而后者看起来很棒很干净。

JPEGPNG

除非需要用到动画,否则PNG也是GIF的一个很好的替用品。虽然后者使用无损的压缩方法,但是它只支持最多256色的调色板,因此不适合于高品质的照片图像。另一方面,PNG既支持基于调色板的颜色,也支持真彩色。PNG对透明色的支持也比GIF更好。

和别的常见的图形格式不一样,PNG允许每个像素的部分透明色,只要视情况需要,为每个像素在RGB数据之外,再存储第四个数据通道,该通道也被称为Alpha通道。在本用户手册的第六章第三节讲解了针对图像印戳Alpha通道的用法。

AspJpeg的PNG输出支持

从v2.1版开始,AspJpeg可以把图像保存为PNG格式了。你所需要做的是在调用Save方法或SendBinary方法、属性Binary之前,把属性PNGOutput设置为True。

如果当前打开的图像已经具有Alpha通道,当图像被保存为PNG的时候,Alpha通道会自动保留。如果图像被缩放了,alpha通道也会跟着缩放。

以下代码示例把第六章中用过的示例PNG图像realty.png缩放大小,并保留它的Alpha通道。

VB Script:

Set Jpeg = Server.CreateObject("Persits.Jpeg")
Jpeg.Open Server.MapPath("../images/realty.png")

' resize by 50%
Jpeg.PreserveAspectRatio = True
Jpeg.Width = Jpeg.OriginalWidth / 2

' Output as PNG
Jpeg.PNGOutput = True

' Save
Jpeg.Save Server.MapPath("realty_small.png")

C#:

IASPJpeg objJpeg = new ASPJpeg();
objJpeg.Open( Server.MapPath("../images/realty.png") );

// resize by 50%
objJpeg.PreserveAspectRatio = 1;
objJpeg.Width = objJpeg.OriginalWidth / 2;

// Output as PNG
objJpeg.PNGOutput = 1;

// Save
objJpeg.Save( Server.MapPath("realty_small.png") );

点击以下链接以运行该代码示例:

http://localhost/aspjpeg/manual_10/10_png.asp

http://localhost/aspjpeg/manual_10/10_png.aspx

Alpha通道管理

AspJpeg通过SetAlpha方法和RemoveAlpha方法,使你能够分别为图像设置一个新Alpha通道,以及为图像移除一个已有的Alpha通道。它还允许你用几种方法修改Alpha通道。

SetAlpha方法和RemoveAlpha方法

SetAlpha方法需要两个参数:一个代表Alpha通道的AspJpeg对象的实例,以及一个布尔标记,指定了Alpha值是否需要被反转。

代表了Alpha通道的图像必须与它要指定的图像具有相同的维度(宽和高),而且必须是在灰度颜色空间内(亦即,每像素只有一字节)。如果第二个参数被设置为False,则Alpha通道图像的颜色值为0(黑色)对应到完全透明,而颜色值为255(白色)对应完全不透明。如果第二个参数是True,255对应于完全透明,0对应于完全不透明。

举个例子,以下代码片段利用其它带一个填充的圆的图像作为Alpha通道,生成了一个红色的图像,带有完全透明的圆洞。

VB Script:

Set Jpeg = Server.CreateObject("Persits.Jpeg")
Jpeg.New 100, 100, &HFFFF0000 ' red background
Set Alpha = Server.CreateObject("Persits.Jpeg")
Alpha.New 100, 100, &HFFFFFFFF
Alpha.Canvas.DrawCircle 50, 50, 30
Alpha.ToGrayscale (0)

Jpeg.SetAlpha Alpha, False

Jpeg.PNGOutput = True
Jpeg.Save "c:\path\out.png"

C#:

IASPJpeg objJpeg = new ASPJpeg();
IASPJpeg objAlpha = new ASPJpeg();
objJpeg.New( 100, 100, 0xFFFF0000 );

objAlpha.New( 100, 100, 0xFFFFFFFF );
objAlpha.Canvas.DrawCircle( 50, 50, 30 );
objAlpha.ToGrayscale(0);

objJpeg.SetAlpha( (ASPJpeg)objAlpha, false );

objJpeg.PNGOutput = 1;
objJpeg.SaveUnique( @"c:\path\out.png" );

这里是输出的图像,显示为蓝色的背景,使它的透明度更加明显:

如果SetAlpha方法的第二个参数被设置为True,输出将如下所示:

Alpha通道图像必须在灰度颜色空间内。这就是为什么上面的脚本调用了ToGrayscale方法。调用这个方法失败,会导致一个产生一个意外,因为用New方法创造的图像总会是RGB模式的。

SetAlpha方法还允许第一个参数被设置为Nothing(空缺)。如果那样的话,如果第二个参数是False,针对每个像素Alpha通道将均匀地被设置为255(完全不透明),如果第二个参数是True,针对每个像素Alpha通道将均匀地被设置为(完全透明)。

要想移除已有的Alpha通道,可以调用RemoveAlpha。该方法没有参数。如果当前图像没有Alpha通道,调用这个方法没有什么效果。要想检查当前图像是否有一个Alpha通道,请使用布尔属性AlphaExists

属性AlphaPixels

你可以通过参数化的属性AlphaPixels来读取并改变当前alpha通道的单个像素,例如:

val = Jpeg.AlphaPixels(10, 20)

或者

Jpeg.AlphaPixels(10, 20) = 20

该属性设置并返回在0到255范围内的值。

在带Alpha通道的图像上绘制

多种Canvas方法,比如说DrawLine方法或PrintTextEx方法,可以用在一个图像上,无论它是否具有Alpha通道。然而,如果绘制的图形或文本文件落在图像中完全透明的区域,它在结果的PNG中不可见。

为了确保绘制的文本或图像100%可见,必须修改Alpha通道,为绘制提供一个不透明的背景。同样的文本或图形需要用白色独立绘制在Alpha通道上(白色意指完全不透明)。

AlphaToImage方法把一个图像的alpha通道变成本身带有一个Canvas对象的独立的图像,可以在上面绘制内容。

以下代码片段打开了一个带有Alpha通道的PNG图像,分离出它的Alpha通道,把这个通道变成一个独立的AspJpeg对象,在原始图像和alpha通道图像上面绘制一些文本,然后把已经修改过的Alpha通道与原始图像合并,从而确保文字在结果PNG中完全可见。

VB Script:

Set Jpeg = Server.CreateObject("Persits.Jpeg")
Jpeg.Open Server.MapPath("../images/realty.png")

Font = Jpeg.WindowsDirectory & "\Fonts\Arial.ttf"

' Print on image
Jpeg.Canvas.PrintTextEx "Some text", 50, 20, Font

' Print on alpha channel by creating a separate object
Set Alpha = Server.CreateObject("Persits.Jpeg")
Alpha.Open Server.MapPath("../images/realty.png")
Alpha.AlphaToImage ' populate image with alpha channel
Alpha.ToRGB ' make it RGB so that we can print on it
Alpha.Canvas.Font.Color = &HFFFFFFFF ' white color!

Alpha.Canvas.PrintTextEx "Some text", 50, 20, Font

Alpha.ToGrayscale(1) ' turn back into grayscale

Jpeg.SetAlpha Alpha, False

' Output as PNG
Jpeg.PNGOutput = True

' Save
Jpeg.Save Server.MapPath("realty_small.png")

C#:

IASPJpeg objJpeg = new ASPJpeg();
string strFont = objJpeg.WindowsDirectory + @"\Fonts\Arial.ttf";

objJpeg.Open( Server.MapPath("../images/realty.png") );

// Print on image
objJpeg.Canvas.PrintTextEx( "Some text", 50, 20, strFont );

// Print on alpha channel by creating a separate object
IASPJpeg objAlpha = new ASPJpeg();
objAlpha.Open( Server.MapPath("../images/realty.png") );
objAlpha.AlphaToImage(); // populate image with alpha channel
objAlpha.ToRGB(); // make it RGB so that we can print on it
objAlpha.Canvas.Font.Color = 0xFFFFFF; // white color!

objAlpha.Canvas.PrintTextEx( "Some text", 50, 20, strFont );

objAlpha.ToGrayscale(1); // turn back into grayscale

objJpeg.SetAlpha( (ASPJpeg)objAlpha, false );

// Output as PNG
objJpeg.PNGOutput = 1;

// Save
objJpeg.Save( Server.MapPath("realty_small.png") );

点击以下链接以运行该代码示例:

http://localhost/aspjpeg/manual_10/10_alpha.asp

http://localhost/aspjpeg/manual_10/10_alpha.aspx

Alpha通道压平

从v2.7版以来,AspJpeg提供了FlattenAlpha方法,它把图像的allpha通道应用到它的像素上,与指定的背景色结合,然后移除alpha通道。因此有效地“压平”了这个图形。这个方法的效果与在具有在相同尺寸的单色背景上绘制图像的效果相同。

FlattenAlpha方法需要一个参数,即背景色,以一个长整型的形式表示。如果图像没有alpha通道,这个方法没有效果。把任意PNG图像(无论是否存在Alpha通道)转换成JPEG格式的时候,这个方法也很有用。

举个例子:

Jpeg.FlattenAlpha( &HFFFFFFFF ) ' White background

GIF图像的Alpha通道

从v2.7版以来,AspJpeg会把GIF图像视为透明色,就像它们是带有alpha通道的PNG图像。那是说,当在一个包含了透明色的GIF图像上调用了Jpeg.Open方法或Jpeg.OpenBinary方法的时候,属性Jpeg.AlphaExists返回True,上面讲到的所有的Alpha相关的方法都可用了。这使它容易把带透明色的GIF图像转换成带Alpha通道的PNG图像,并实施裁剪、旋转以及其它在GIF图像上的操作,与此同时保留它的透明色信息。

为图像旋转使用PNG格式

从v2.3版以来,AspJpeg可以利用Rotate方法,以任意角度旋转图像。这个方法需要两个参数:以degree计的旋转角度,以及填充色。在调用了这个方法的时候,原始的图像被旋转了,图像的画布在水平和垂直方向上增加了,以适应倾斜的图像。因此形成的这四个三角形的角落区域用指定的颜色填充。比如:

jpeg.Rotate 24, &HFF0000 ' 24 degrees, red color

如果旋转的图像被绘制在另一个图像的上面,脚落区域通常需要整个被移除。Rotate方法通过为旋转的图像创建一个Alpha通道来实现这,它使角落区域完全透明。为了利用Alpha通道,旋转像需要保存为PNG格式(亦即,属性PNGOutput属性必须设置为True)。

PNG图像可以绘制在另一个图像的顶端,如第六章第三节所述。为了避免在磁盘上创建一个临时文件,可以利用属性Binary把PNG保存到内存中,然后通过DrawPNGBinary方法来绘制。

以下图像用以下脚本来创建:

VB Script:

Set RotatedImg = Server.CreateObject("Persits.Jpeg")
RotatedImg.Open Server.MapPath(".") & "/../images/porsche.jpg"

' Rotate 24 degrees, black background
RotatedImg.Rotate 24, 0

' Output as PNG to take advantage of alpha channel hiding corners
RotatedImg.PNGOutput = True

' Create another instance of AspJpeg
Set Jpeg = Server.CreateObject("Persits.Jpeg")

Jpeg.Open Server.MapPath(".") & "/../images/photo.jpg"

Jpeg.Canvas.DrawPNGBinary 410, 50, RotatedImg.Binary

Jpeg.Save Server.MapPath("rotatedinpicture.jpg")

C#:

// Create instance of AspJpeg
IASPJpeg objRotatedImg = new ASPJpeg();
objRotatedImg.Open( Server.MapPath("../images/porsche.jpg" ) );

// Rotate 24 degrees, black background
objRotatedImg.Rotate( 24, 0x00 );

// Output as PNG to take advantage of alpha channel hiding corners
objRotatedImg.PNGOutput = 1;

// Create another instance of AspJpeg
IASPJpeg objJpeg = new ASPJpeg();

objJpeg.Open( Server.MapPath("../images/photo.jpg") );

objJpeg.Canvas.DrawPNGBinary( 410, 50, objRotatedImg.Binary );

objJpeg.Save( Server.MapPath("rotatedinpicture.jpg") );

点击以下链接以运行该代码示例:

http://localhost/aspjpeg/manual_10/10_rotate.asp

http://localhost/aspjpeg/manual_10/10_rotate.aspx

如果你喜欢这篇文章,敬请给站长打赏↑

除特别注明外,本站所有文章均为本站站长原译,转载请注明出处。