原創(chuàng)|產(chǎn)品更新|編輯:李顯亮|2020-06-18 10:19:49.870|閱讀 306 次
概述:Aspose.Imaging for .NET更新至最新版v20.6,支持APNG(動(dòng)畫PNG)文件格式,支持BMP的新壓縮方法DXT1 ,支持批量導(dǎo)出到WebP以獲得多頁圖像,歡迎下載體驗(yàn)。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
Aspose.Imaging for .NET一種高級(jí)圖像處理控件,允許開發(fā)人員創(chuàng)建,編輯,繪制或轉(zhuǎn)換圖像。圖像導(dǎo)出和轉(zhuǎn)換是API核心功能之一,它允許在不安裝Photoshop應(yīng)用程序或任何其他圖像編輯器的情況下保存為AdobePhotoshop®本機(jī)格式。
事實(shí)證明,Aspose.Imaging是處理各種圖像格式的強(qiáng)大API。除單頁圖像外,Aspose.Imaging還支持處理多頁圖像,包括GIF,TIFF,PSD,DICOM,CDR和WebP。
近期發(fā)布了Aspose.Imaging for .NET v20.6,支持APNG(動(dòng)畫PNG)文件格式,支持BMP的新壓縮方法DXT1 ,支持批量導(dǎo)出到WebP以獲得多頁圖像,還沒使用過的朋友可以點(diǎn)擊下載最新版Aspose.Imaging
key | 概述 | 類別 |
---|---|---|
IMAGINGNET-3618 | 實(shí)現(xiàn)對(duì)APNG(動(dòng)畫PNG)文件格式的支持 | 功能 |
IMAGINGNET-3849 | 支持BMP的新壓縮方法DXT1 | 功能 |
IMAGINGNET-3781 | 支持批量導(dǎo)出到WebP以獲得多頁圖像 | 功能 |
IMAGINGNET-3882 | 無法從XMP元數(shù)據(jù)提取Azure標(biāo)簽信息 | 增強(qiáng)功能 |
IMAGINGNET-3804 | 將WMF保存為PNG時(shí)形狀崩潰 | 增強(qiáng)功能 |
創(chuàng)建圖像并設(shè)置其像素。
// 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 image Size 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 pixels using (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 format using (Image image = Image.Load("created_apng.png")) { Debug.Assert(image.FileFormat == FileFormat.Apng); Debug.Assert(image is ApngImage); }
柵格圖像操作
// The brightness adjustment operation using Aspose.Imaging; using Aspose.Imaging.FileFormats.Apng; using (ApngImage image = (ApngImage)Image.Load("elephant.png")) { image.AdjustBrightness(100); image.Save("AdjustBrightness.png"); }
從另一個(gè)單頁圖像創(chuàng)建動(dòng)畫圖像
// Create an animated image from another single-page image using Aspose.Imaging; using Aspose.Imaging.ImageOptions; using Aspose.Imaging.FileFormats.Apng; const int AnimationDuration = 1000; // 1 s const int FrameDuration = 70; // 70 ms using (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(); } }
根據(jù)矢量圖形操作創(chuàng)建APNG動(dòng)畫
// Create APNG animation based on vector graphics operations using Aspose.Imaging; using Aspose.Imaging.FileFormats.Apng; // preparing the animation scene const int SceneWidth = 400; const int SceneHeigth = 400; const uint ActDuration = 1000; // Act duration, in milliseconds const uint TotalDuration = 4000; // Total duration, in milliseconds const uint FrameDuration = 50; // Frame duration, in milliseconds Scene 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 ApngImage ApngOptions 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 scene public 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 object public interface IGraphicsObject { void Render(Graphics graphics); } /////////////////////////// Line.cs ///////////////////////////// using Graphics = Aspose.Imaging.Graphics; // The line public 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 ellipse public 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 animation public interface IAnimation { // The animation duration, in milliseconds. uint Duration { get; set; } void Update(uint elapsed); } /////////////////////////// LinearAnimation.cs ///////////////////////////// // The linear animation public 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; } } }
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. */ }
DXT1壓縮
DXTn是一組相關(guān)的有損紋理壓縮算法。該算法有五種變體(命名為DXT1至DXT5),每種變體均針對(duì)特定類型的圖像數(shù)據(jù)而設(shè)計(jì)。全部將4X4像素塊轉(zhuǎn)換為64位或128位量,對(duì)于24位RGB輸入數(shù)據(jù),壓縮率為6:1;對(duì)于32位RGBA輸入數(shù)據(jù),壓縮率為4:1。它包含在Microsoft的DirectX 6.0和OpenGL 1.3中,導(dǎo)致該技術(shù)在硬件和軟件制造商中得到廣泛采用。
DXT1算法
DXT1(也稱為塊壓縮1或BC1)是最簡單的壓縮,也是其他類型DXT算法的基礎(chǔ)。它是DXT的最小變體,在64位輸出中存儲(chǔ)16個(gè)輸入像素,包括兩個(gè)16位顏色值和一個(gè)4X4 2位查找表。顏色信息也以壓縮方式存儲(chǔ),因此每種顏色僅使用16位。這意味著紋理的這16個(gè)像素僅占用64位(調(diào)色板使用32位,索引使用32位)。那是1:8的壓縮比。
如何使用DXT1壓縮
以下代碼演示了如何使用DXT1壓縮來壓縮現(xiàn)有圖像:
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()); }
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn