Aspose.Imaging for .NET更新至最新版v20.6,支持APNG(动画PNG)文件格式,支持BMP的新压缩方法DXT1 ,支持批量导出到WebP以获得多页图像,欢迎下载体验。
事实证明,Aspose.Imaging是处理各种图像格式的强大API。除单页图像外,Aspose.Imaging还支持处理多页图像,包括GIF,TIFF,PSD,DICOM,CDR和WebP。
近期发布了Aspose.Imaging for .NET v20.6,支持APNG(动画PNG)文件格式,支持BMP的新压缩方法DXT1 ,支持批量导出到WebP以获得多页图像,还没使用过的朋友可以最新版Aspose.Imaging
新增与改善
key | 概述 | 类别 |
---|---|---|
IMAGINGNET-3618 | 实现对APNG(动画PNG)文件格式的支持 | 功能 |
IMAGINGNET-3849 | 支持BMP的新压缩方法DXT1 | 功能 |
IMAGINGNET-3781 | 支持批量导出到WebP以获得多页图像 | 功能 |
IMAGINGNET-3882 | 无法从XMP元数据提取Azure标签信息 | 增强功能 |
IMAGINGNET-3804 | 将WMF保存为PNG时形状崩溃 | 增强功能 |
新功能用法示例
IMAGINGNET-3618实现对APNG(动画PNG)文件格式的支持
创建图像并设置其像素。
// Example 1. Creating an image and setting its pixels.using System.Diagnostics;using Aspose.Imaging;using Aspose.Imaging.ImageOptions;using Aspose.Imaging.FileFormats.Png;using Aspose.Imaging.FileFormats.Apng;// Load pixels from source raster imageSize imageSize;int[] imagePixels;using (RasterImage sourceImage = (RasterImage)Image.Load("not_animated.png")){ imageSize = sourceImage.Size; imagePixels = sourceImage.LoadArgb32Pixels(sourceImage.Bounds);}// Create APNG image and set its pixelsusing (ApngImage image = (ApngImage)Image.Create( new ApngOptions() { Source = new FileCreateSource("created_apng.png", false), ColorType = PngColorType.TruecolorWithAlpha }, imageSize.Width, imageSize.Height)){ image.SaveArgb32Pixels(image.Bounds, imagePixels); image.Save();}// Check output file formatusing (Image image = Image.Load("created_apng.png")) { Debug.Assert(image.FileFormat == FileFormat.Apng); Debug.Assert(image is ApngImage);}
栅格图像操作
// The brightness adjustment operationusing Aspose.Imaging;using Aspose.Imaging.FileFormats.Apng;using (ApngImage image = (ApngImage)Image.Load("elephant.png")){ image.AdjustBrightness(100); image.Save("AdjustBrightness.png");}
从另一个单页图像创建动画图像
// Create an animated image from another single-page imageusing Aspose.Imaging;using Aspose.Imaging.ImageOptions;using Aspose.Imaging.FileFormats.Apng;const int AnimationDuration = 1000; // 1 sconst int FrameDuration = 70; // 70 msusing (RasterImage sourceImage = (RasterImage)Image.Load("not_animated.png")){ ApngOptions createOptions = new ApngOptions { Source = new FileCreateSource("raster_animation.png", false), DefaultFrameTime = (uint)FrameDuration, ColorType = PngColorType.TruecolorWithAlpha, }; using (ApngImage apngImage = (ApngImage)Image.Create( createOptions, sourceImage.Width, sourceImage.Height)) { int numOfFrames = AnimationDuration / FrameDuration; int numOfFrames2 = numOfFrames / 2; apngImage.RemoveAllFrames(); // add first frame apngImage.AddFrame(sourceImage, FrameDuration); // add intermediate frames for (int frameIndex = 1; frameIndex < numOfFrames - 1; ++frameIndex) { apngImage.AddFrame(sourceImage, FrameDuration); ApngFrame lastFrame = (ApngFrame)apngImage.Pages[apngImage.PageCount - 1]; float gamma = frameIndex >= numOfFrames2 numOfFrames - frameIndex - 1 : frameIndex; lastFrame.AdjustGamma(gamma); } // add last frame apngImage.AddFrame(sourceImage, FrameDuration); apngImage.Save(); }}
根据矢量图形操作创建APNG动画
// Create APNG animation based on vector graphics operationsusing Aspose.Imaging;using Aspose.Imaging.FileFormats.Apng;// preparing the animation sceneconst int SceneWidth = 400;const int SceneHeigth = 400;const uint ActDuration = 1000; // Act duration, in millisecondsconst uint TotalDuration = 4000; // Total duration, in millisecondsconst uint FrameDuration = 50; // Frame duration, in millisecondsScene scene = new Scene();Ellipse ellipse = new Ellipse { FillColor = Color.FromArgb(128, 128, 128), CenterPoint = new PointF(SceneWidth / 2f, SceneHeigth / 2f), RadiusX = 80, RadiusY = 80 };scene.AddObject(ellipse);Line line = new Line { Color = Color.Blue, LineWidth = 10, StartPoint = new PointF(30, 30), EndPoint = new PointF(SceneWidth - 30, 30) };scene.AddObject(line);IAnimation lineAnimation1 = new LinearAnimation( delegate(float progress) { line.StartPoint = new PointF( 30 + (progress * (SceneWidth - 60)), 30 + (progress * (SceneHeigth - 60))); line.Color = Color.FromArgb( (int)(progress * 255), 0, 255 - (int)(progress * 255)); }) { Duration = ActDuration };IAnimation lineAnimation2 = new LinearAnimation( delegate(float progress) { line.EndPoint = new PointF( SceneWidth - 30 - (progress * (SceneWidth - 60)), 30 + (progress * (SceneHeigth - 60))); line.Color = Color.FromArgb( 255, (int)(progress * 255), 0); }) { Duration = ActDuration };IAnimation lineAnimation3 = new LinearAnimation( delegate(float progress) { line.StartPoint = new PointF( SceneWidth - 30 - (progress * (SceneWidth - 60)), SceneHeigth - 30 - (progress * (SceneHeigth - 60))); line.Color = Color.FromArgb( 255 - (int)(progress * 255), 255, 0); }) { Duration = ActDuration };IAnimation lineAnimation4 = new LinearAnimation( delegate(float progress) { line.EndPoint = new PointF( 30 + (progress * (SceneWidth - 60)), SceneHeigth - 30 - (progress * (SceneHeigth - 60))); line.Color = Color.FromArgb( 0, 255 - (int)(progress * 255), (int)(progress * 255)); }) { Duration = ActDuration };IAnimation fullLineAnimation = new SequentialAnimation() { lineAnimation1, lineAnimation2, lineAnimation3, lineAnimation4 };IAnimation ellipseAnimation1 = new LinearAnimation( delegate(float progress) { ellipse.RadiusX += progress * 10; ellipse.RadiusY += progress * 10; int compValue = (int)(128 + (progress * 112)); ellipse.FillColor = Color.FromArgb( compValue, compValue, compValue); }) { Duration = ActDuration };IAnimation ellipseAnimation2 = new Delay() { Duration = ActDuration };IAnimation ellipseAnimation3 = new LinearAnimation( delegate(float progress) { ellipse.RadiusX -= progress * 10; int compValue = (int)(240 - (progress * 224)); ellipse.FillColor = Color.FromArgb( compValue, compValue, compValue); }) { Duration = ActDuration };IAnimation ellipseAnimation4 = new LinearAnimation( delegate(float progress) { ellipse.RadiusY -= progress * 10; int compValue = (int)(16 + (progress * 112)); ellipse.FillColor = Color.FromArgb( compValue, compValue, compValue); }) { Duration = ActDuration };IAnimation fullEllipseAnimation = new SequentialAnimation() { ellipseAnimation1, ellipseAnimation2, ellipseAnimation3, ellipseAnimation4 };scene.Animation = new ParallelAnimation() { fullLineAnimation, fullEllipseAnimation };// playing the scene on the newly created ApngImageApngOptions createOptions = new ApngOptions { Source = new FileCreateSource("vector_animation.png", false), ColorType = PngColorType.TruecolorWithAlpha, };using (ApngImage image = (ApngImage)Image.Create(createOptions, SceneWidth, SceneHeigth)){ image.DefaultFrameTime = FrameDuration; scene.Play(image, TotalDuration); image.Save();}/////////////////////////// Scene.cs /////////////////////////////using System.Collections.Generic;using Aspose.Imaging.FileFormats.Apng;using Graphics = Aspose.Imaging.Graphics;// The graphics scenepublic class Scene{ private readonly ListgraphicsObjects = new List(); public IAnimation Animation { get; set; } public void AddObject(IGraphicsObject graphicsObject) { this.graphicsObjects.Add(graphicsObject); } public void Play(ApngImage animationImage, uint totalDuration) { uint frameDuration = animationImage.DefaultFrameTime; uint numFrames = totalDuration / frameDuration; uint totalElapsed = 0; for (uint frameIndex = 0; frameIndex < numFrames; frameIndex++) { if (this.Animation != null) { this.Animation.Update(totalElapsed); } ApngFrame frame = animationImage.PageCount == 0 || frameIndex > 0 animationImage.AddFrame() : (ApngFrame)animationImage.Pages[0]; Graphics graphics = new Graphics(frame); graphics.SmoothingMode = SmoothingMode.AntiAlias; foreach (IGraphicsObject graphicsObject in this.graphicsObjects) { graphicsObject.Render(graphics); } totalElapsed += frameDuration; } }}/////////////////////////// IGraphicsObject.cs /////////////////////////////using Graphics = Aspose.Imaging.Graphics;// The graphics objectpublic interface IGraphicsObject{ void Render(Graphics graphics);}/////////////////////////// Line.cs /////////////////////////////using Graphics = Aspose.Imaging.Graphics;// The linepublic class Line : IGraphicsObject{ public PointF StartPoint { get; set; } public PointF EndPoint { get; set; } public float LineWidth { get; set; } public Color Color { get; set; } public void Render(Graphics graphics) { graphics.DrawLine(new Pen(this.Color, this.LineWidth), this.StartPoint, this.EndPoint); }}/////////////////////////// Ellipse.cs /////////////////////////////using Aspose.Imaging.Brushes;using Graphics = Aspose.Imaging.Graphics;// The ellipsepublic class Ellipse : IGraphicsObject{ public Color FillColor { get; set; } public PointF CenterPoint { get; set; } public float RadiusX { get; set; } public float RadiusY { get; set; } public void Render(Graphics graphics) { graphics.FillEllipse( new SolidBrush(this.FillColor), this.CenterPoint.X - this.RadiusX, this.CenterPoint.Y - this.RadiusY, this.RadiusX * 2, this.RadiusY * 2); }}/////////////////////////// IAnimation.cs /////////////////////////////// The animationpublic interface IAnimation{// The animation duration, in milliseconds. uint Duration { get; set; } void Update(uint elapsed);}/////////////////////////// LinearAnimation.cs /////////////////////////////// The linear animationpublic class LinearAnimation : IAnimation{ private readonly AnimationProgressHandler progressHandler; public delegate void AnimationProgressHandler(float progress); public LinearAnimation(AnimationProgressHandler progressHandler) { if (progressHandler == null) { throw new System.ArgumentNullException("progressHandler"); } this.progressHandler = progressHandler; } public uint Duration { get; set; } public void Update(uint elapsed) { if (elapsed <= this.Duration) { this.progressHandler.Invoke((float)elapsed / this.Duration); } } } /////////////////////////// Delay.cs ///////////////////////////// // The simple delay between other animations public class Delay : IAnimation { public uint Duration { get; set; } public void Update(uint elapsed) { // nop } } /////////////////////////// ParallelAnimation.cs ///////////////////////////// using System.Collections.Generic; // The parallel animation processor public class ParallelAnimation : List, IAnimation{ public uint Duration { get { uint maxDuration = 0; foreach (IAnimation animation in this) { if (maxDuration < animation.Duration) { maxDuration = animation.Duration; } } return maxDuration; } set { throw new System.NotSupportedException(); } } public void Update(uint elapsed) { foreach (IAnimation animation in this) { animation.Update(elapsed); } } } /////////////////////////// SequentialAnimation.cs ///////////////////////////// using System.Collections.Generic; // The sequential animation processor public class SequentialAnimation : List, IAnimation{ public uint Duration { get { uint summDuration = 0; foreach (IAnimation animation in this) { summDuration += animation.Duration; } return summDuration; } set { throw new System.NotSupportedException(); } } public void Update(uint elapsed) { uint totalDuration = 0; foreach (IAnimation animation in this) { if (totalDuration > elapsed) { break; } animation.Update(elapsed - totalDuration); totalDuration += animation.Duration; } }}
IMAGINGNET-3781支持批量导出到WebP以获得多页图像
using (TiffImage tiffImage = (TiffImage)Image.Load("10MB_Tif.tif")){ // Set batch operation for pages tiffImage.PageExportingAction = delegate(int index, Image page) { // Fires garbage collection to avoid unnecessary garbage storage from previous pages GC.Collect(); ((RasterImage)page).Rotate(90); }; tiffImage.Save("rotated.webp", new WebPOptions()); /* Attention! In batch mode all pages will be released in this line! If you want to further perform operations on the original image, you should reload it from the source to another instance. */}
IMAGINGNET-3849-支持针对BMP的新压缩方法DXT1
DXT1压缩
DXTn是一组相关的有损纹理压缩算法。该算法有五种变体(命名为DXT1至DXT5),每种变体均针对特定类型的图像数据而设计。全部将4X4像素块转换为64位或128位量,对于24位RGB输入数据,压缩率为6:1;对于32位RGBA输入数据,压缩率为4:1。它包含在Microsoft的DirectX 6.0和OpenGL 1.3中,导致该技术在硬件和软件制造商中得到广泛采用。
DXT1算法
DXT1(也称为块压缩1或BC1)是最简单的压缩,也是其他类型DXT算法的基础。它是DXT的最小变体,在64位输出中存储16个输入像素,包括两个16位颜色值和一个4X4 2位查找表。颜色信息也以压缩方式存储,因此每种颜色仅使用16位。这意味着纹理的这16个像素仅占用64位(调色板使用32位,索引使用32位)。那是1:8的压缩比。
如何使用DXT1压缩
以下代码演示了如何使用DXT1压缩来压缩现有图像:
using (var image = Image.Load("Tiger.bmp")){ image.Save("CompressedTiger.bmp", new BmpOptions { Compression = BitmapCompression.Dxt1 });}
如何解压缩图像
以下代码显示了如何解压缩先前压缩的图像:
using (var image = Image.Load("CompressedTiger.bmp")){ image.Save("DecompressedTiger.bmp", new BmpOptions());}
还想要更多吗可以点击阅读【2019 · Aspose最新资源整合】,查找需要的教程资源。如果您有任何疑问或需求,请随时加入Aspose技术交流群(),我们很高兴为您提供查询和咨询。
标签:
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!