mirror of
https://gitee.com/csharpui/CPF.git
synced 2025-04-04 23:39:26 +08:00
295 lines
8.7 KiB
C#
295 lines
8.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using SkiaSharp;
|
|
using System.IO;
|
|
using CPF.Drawing;
|
|
|
|
namespace CPF.Skia
|
|
{
|
|
public class SkiaImage : IImageImpl
|
|
{
|
|
int frameCount;
|
|
Stream stream;
|
|
//SKBitmap[] bitmaps;
|
|
SKCodec codec;
|
|
SKBitmap bitmap;
|
|
|
|
public SkiaImage(string path)
|
|
{
|
|
stream = File.OpenRead(path);
|
|
//#if Net4
|
|
using (SKData data = SKData.Create(path))
|
|
{
|
|
codec = SKCodec.Create(data);
|
|
}
|
|
//#else
|
|
// codec = SKCodec.Create(stream);
|
|
//#endif
|
|
frameCount = Math.Max(1, codec.FrameCount);
|
|
bitmap = SKBitmap.Decode(codec);
|
|
Codec();
|
|
}
|
|
|
|
public SkiaImage(Stream stream)
|
|
{
|
|
this.stream = new MemoryStream();
|
|
stream.CopyTo(this.stream);
|
|
this.stream.Position = 0;
|
|
//#if Net4
|
|
using (SKData data = SKData.Create(this.stream))
|
|
{
|
|
codec = SKCodec.Create(data);
|
|
}
|
|
//#else
|
|
// codec = SKCodec.Create(this.stream);
|
|
//#endif
|
|
if (codec == null)
|
|
{
|
|
this.stream.Position = 0;
|
|
codec = SKCodec.Create(this.stream, out var result);
|
|
if (codec == null)
|
|
{
|
|
throw new Exception("图片解码失败" + result);
|
|
}
|
|
}
|
|
frameCount = Math.Max(1, codec.FrameCount);
|
|
bitmap = SKBitmap.Decode(codec);
|
|
Codec();
|
|
}
|
|
|
|
int[] durations;
|
|
|
|
public int[] FrameDelay { get { return durations; } }
|
|
|
|
void Codec()
|
|
{
|
|
if (frameCount > 1)
|
|
{
|
|
durations = new int[frameCount];
|
|
for (int frame = 0; frame < frameCount; frame++)
|
|
{
|
|
// From the FrameInfo collection, get the duration of each frame
|
|
durations[frame] = codec.FrameInfo[frame].Duration;
|
|
}
|
|
Duration = 0;
|
|
// Sum up the total duration
|
|
for (int frame = 0; frame < durations.Length; frame++)
|
|
{
|
|
Duration += durations[frame];
|
|
}
|
|
}
|
|
if (bitmap == null)
|
|
{
|
|
throw new Exception("图片解析失败");
|
|
}
|
|
}
|
|
|
|
//void Codec(SKCodec codec)
|
|
//{
|
|
// // Get frame count and allocate bitmaps
|
|
// frameCount = codec.FrameCount;
|
|
// if (frameCount == 0)
|
|
// {
|
|
// frameCount = 1;
|
|
// bitmaps = new SKBitmap[frameCount];
|
|
// bitmaps[0] = SKBitmap.Decode(codec);
|
|
// }
|
|
// else
|
|
// {
|
|
// bitmaps = new SKBitmap[frameCount];
|
|
// var durations = new int[frameCount];
|
|
// //var accumulatedDurations = new int[frameCount];
|
|
|
|
// // Note: There's also a RepetitionCount property of SKCodec not used here
|
|
|
|
// // Loop through the frames
|
|
// for (int frame = 0; frame < frameCount; frame++)
|
|
// {
|
|
// // From the FrameInfo collection, get the duration of each frame
|
|
// durations[frame] = codec.FrameInfo[frame].Duration;
|
|
|
|
// // Create a full-color bitmap for each frame
|
|
// SKImageInfo imageInfo = new SKImageInfo(codec.Info.Width, codec.Info.Height);
|
|
// bitmaps[frame] = new SKBitmap(imageInfo);
|
|
|
|
// // Get the address of the pixels in that bitmap
|
|
// IntPtr pointer = bitmaps[frame].GetPixels();
|
|
|
|
// // Create an SKCodecOptions value to specify the frame
|
|
// SKCodecOptions codecOptions = new SKCodecOptions(frame);
|
|
|
|
// // Copy pixels from the frame into the bitmap
|
|
// codec.GetPixels(imageInfo, pointer, codecOptions);
|
|
// }
|
|
// Duration = 0;
|
|
// // Sum up the total duration
|
|
// for (int frame = 0; frame < durations.Length; frame++)
|
|
// {
|
|
// Duration += durations[frame];
|
|
// }
|
|
|
|
// // Calculate the accumulated durations
|
|
// //for (int frame = 0; frame < durations.Length; frame++)
|
|
// //{
|
|
// // accumulatedDurations[frame] = durations[frame] +
|
|
// // (frame == 0 ? 0 : accumulatedDurations[frame - 1]);
|
|
// //}
|
|
// }
|
|
//}
|
|
|
|
public SKBitmap Image
|
|
{
|
|
get
|
|
{
|
|
if (needUpdate)
|
|
{
|
|
needUpdate = false;
|
|
|
|
IntPtr pointer = bitmap.GetPixels();
|
|
|
|
// Create an SKCodecOptions value to specify the frame
|
|
#if Net4
|
|
SKCodecOptions codecOptions = new SKCodecOptions((int)index, true);
|
|
#else
|
|
SKCodecOptions codecOptions = new SKCodecOptions((int)index, (int)index - 1);
|
|
#endif
|
|
SKImageInfo imageInfo = new SKImageInfo(codec.Info.Width, codec.Info.Height);
|
|
// Copy pixels from the frame into the bitmap
|
|
codec.GetPixels(imageInfo, pointer, codecOptions);
|
|
bitmap.NotifyPixelsChanged();
|
|
}
|
|
return bitmap;
|
|
}
|
|
}
|
|
|
|
public int Width
|
|
{
|
|
get
|
|
{
|
|
return Image.Width;
|
|
}
|
|
}
|
|
|
|
public int Height
|
|
{
|
|
get
|
|
{
|
|
return Image.Height;
|
|
}
|
|
}
|
|
|
|
public uint FrameCount
|
|
{
|
|
get
|
|
{
|
|
return (uint)frameCount;
|
|
}
|
|
}
|
|
|
|
bool needUpdate;
|
|
uint index;
|
|
public uint Index
|
|
{
|
|
get { return index; }
|
|
set
|
|
{
|
|
if (index != value)
|
|
{
|
|
index = value;
|
|
needUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
~SkiaImage()
|
|
{
|
|
Dispose();
|
|
}
|
|
public int Duration { get; set; }
|
|
|
|
public void Dispose()
|
|
{
|
|
if (bitmap != null)
|
|
{
|
|
bitmap.Dispose();
|
|
bitmap = null;
|
|
}
|
|
if (codec != null)
|
|
{
|
|
codec.Dispose();
|
|
codec = null;
|
|
}
|
|
if (stream != null)
|
|
{
|
|
stream.Dispose();
|
|
stream = null;
|
|
}
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
public Stream SaveToStream(ImageFormat format)
|
|
{
|
|
var f = SKEncodedImageFormat.Jpeg;
|
|
switch (format)
|
|
{
|
|
case ImageFormat.Bmp:
|
|
f = SKEncodedImageFormat.Bmp;
|
|
break;
|
|
case ImageFormat.Gif:
|
|
f = SKEncodedImageFormat.Gif;
|
|
break;
|
|
case ImageFormat.Jpeg:
|
|
f = SKEncodedImageFormat.Jpeg;
|
|
break;
|
|
case ImageFormat.Png:
|
|
f = SKEncodedImageFormat.Png;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
using (var image = SKImage.FromBitmap(Image))
|
|
{
|
|
var data = image.Encode(f, 100);
|
|
var d = data.AsStream();
|
|
return d;
|
|
}
|
|
}
|
|
public void SaveToStream(ImageFormat format, Stream m)
|
|
{
|
|
var f = SKEncodedImageFormat.Jpeg;
|
|
switch (format)
|
|
{
|
|
case ImageFormat.Bmp:
|
|
f = SKEncodedImageFormat.Bmp;
|
|
break;
|
|
case ImageFormat.Gif:
|
|
f = SKEncodedImageFormat.Gif;
|
|
break;
|
|
case ImageFormat.Jpeg:
|
|
f = SKEncodedImageFormat.Jpeg;
|
|
break;
|
|
case ImageFormat.Png:
|
|
f = SKEncodedImageFormat.Png;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
using (var image = SKImage.FromBitmap(Image))
|
|
{
|
|
var data = image.Encode(f, 100);
|
|
//var d = data.AsStream();
|
|
//return d;
|
|
data.SaveTo(m);
|
|
data.Dispose();
|
|
}
|
|
}
|
|
|
|
public object Clone()
|
|
{
|
|
stream.Position = 0;
|
|
return new SkiaImage(stream);
|
|
}
|
|
}
|
|
}
|