using SkiaSharp;
using System;
using System.IO;
using Vinno.IUS.Common.Log;
namespace Vinno.vCloud.Common.Vid2.Codec
{
public class VinnoImageEncoder
{
private readonly float _xScale;
private readonly float _yScale;
private int _currentIndex;
public VinnoImageEncoder(float xScale = 1.0f, float yScale = 1.0f)
{
_currentIndex = -1;
_xScale = xScale;
_yScale = yScale;
}
///
/// Convert bitmap to jpeg image bytes.
///
///
/// The compress level for image, default is 75
///
private byte[] ImageToBytes(SKBitmap image, long compressLevel = 80)
{
try
{
var newWidth = (int)(image.Width * _xScale);
var newHeight = (int)(image.Height * _yScale);
SKBitmap tempImage = image;
if (image.Width != newWidth || image.Height != newHeight)
{
tempImage = image.Resize(new SKImageInfo(newWidth, newHeight), SKFilterQuality.None);
}
try
{
using (var map = new SKPixmap(new SKImageInfo(tempImage.Width, tempImage.Height, tempImage.ColorType), tempImage.GetPixels()))
{
using (var stream = new SKDynamicMemoryWStream())
{
SKPixmap.Encode(stream, map, SKEncodedImageFormat.Jpeg, (int)compressLevel);
return stream.CopyToData().ToArray();
}
}
}
catch (Exception exception)
{
throw new Exception($"ImageToBytes error:{exception}");
}
finally
{
tempImage.Dispose();
}
}
catch (Exception e)
{
Logger.WriteLineError(
$"Vinno image encode error image width :{image.Width}, image height :{image.Height}, stack is {e}");
}
return new byte[0];
}
///
/// Encode a bitmap to VinnoImage.
///
/// The bitmap to be encoded.
/// The VinnoImage
public VinnoImage Encode(SKBitmap image)
{
_currentIndex++;
return new VinnoImage(_currentIndex, image.Width, image.Height, ImageToBytes(image));
}
///
/// Compress a VinnoImage to a 480p image with 50 quality.
///
///
///
public VinnoImage Compress(VinnoImage vinnoImage)
{
byte[] compressedData = vinnoImage.ImageData;
using (var ms = new MemoryStream(compressedData))
{
using (var image = SKBitmap.Decode(ms))
{
//Get 480p ratio
var ratio = (double)480 / image.Height;
if (ratio < 1)
{
var width = (int)(image.Width * ratio);
var height = (int)(image.Height * ratio);
SKBitmap tempImage = image;
if (image.Width != width || image.Height != height)
{
tempImage = image.Resize(new SKImageInfo(width, height), SKFilterQuality.High);
}
try
{
using (var map = new SKPixmap(new SKImageInfo(tempImage.Width, tempImage.Height, tempImage.ColorType), tempImage.GetPixels()))
{
using (var stream = new SKDynamicMemoryWStream())
{
SKPixmap.Encode(stream, map, SKEncodedImageFormat.Jpeg, 50);
compressedData = stream.CopyToData().ToArray();
}
}
}
catch (Exception exception)
{
throw new Exception($"Compress error:{exception}");
}
finally
{
tempImage.Dispose();
}
}
}
}
var updater = new VinnoImageUpdater(vinnoImage);
updater.Update(compressedData);
return vinnoImage;
}
}
}