VinnoImageEncoder.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using SkiaSharp;
  2. using Vinno.vCloud.Common.Vid2;
  3. namespace VidProcessService.Utilities
  4. {
  5. public class VinnoImageEncoder
  6. {
  7. private readonly float _xScale;
  8. private readonly float _yScale;
  9. private int _currentIndex;
  10. public VinnoImageEncoder(float xScale = 1.0f, float yScale = 1.0f)
  11. {
  12. _currentIndex = -1;
  13. _xScale = xScale;
  14. _yScale = yScale;
  15. }
  16. /// <summary>
  17. /// Convert bitmap to jpeg image bytes.
  18. /// </summary>
  19. /// <param name="image"></param>
  20. /// <param name="compressLevel">The compress level for image, default is 75</param>
  21. /// <returns></returns>
  22. private byte[] ImageToBytes(SKBitmap image, long compressLevel = 80)
  23. {
  24. try
  25. {
  26. var newWidth = (int)(image.Width * _xScale);
  27. var newHeight = (int)(image.Height * _yScale);
  28. SKBitmap tempImage = image;
  29. if (image.Width != newWidth || image.Height != newHeight)
  30. {
  31. tempImage = image.Resize(new SKImageInfo(newWidth, newHeight), SKFilterQuality.None);
  32. }
  33. try
  34. {
  35. using (var map = new SKPixmap(new SKImageInfo(tempImage.Width, tempImage.Height, tempImage.ColorType), tempImage.GetPixels()))
  36. {
  37. using (var stream = new SKDynamicMemoryWStream())
  38. {
  39. SKPixmap.Encode(stream, map, SKEncodedImageFormat.Jpeg, (int)compressLevel);
  40. return stream.CopyToData().ToArray();
  41. }
  42. }
  43. }
  44. catch (Exception exception)
  45. {
  46. throw new Exception($"ImageToBytes error:{exception}");
  47. }
  48. finally
  49. {
  50. tempImage.Dispose();
  51. }
  52. }
  53. catch (Exception e)
  54. {
  55. // Logger.WriteLineError(
  56. // $"Vinno image encode error image width :{image.Width}, image height :{image.Height}, stack is {e}");
  57. }
  58. return new byte[0];
  59. }
  60. /// <summary>
  61. /// Encode a bitmap to VinnoImage.
  62. /// </summary>
  63. /// <param name="image">The bitmap to be encoded.</param>
  64. /// <returns>The VinnoImage</returns>
  65. public VinnoImage Encode(SKBitmap image)
  66. {
  67. _currentIndex++;
  68. return new VinnoImage(_currentIndex, image.Width, image.Height, ImageToBytes(image));
  69. }
  70. /// <summary>
  71. /// Compress a VinnoImage to a 480p image with 50 quality.
  72. /// </summary>
  73. /// <param name="vinnoImage"></param>
  74. /// <returns></returns>
  75. public VinnoImage Compress(VinnoImage vinnoImage)
  76. {
  77. byte[] compressedData = vinnoImage.ImageData;
  78. using (var ms = new MemoryStream(compressedData))
  79. {
  80. using (var image = SKBitmap.Decode(ms))
  81. {
  82. //Get 480p ratio
  83. var ratio = (double)480 / image.Height;
  84. if (ratio < 1)
  85. {
  86. var width = (int)(image.Width * ratio);
  87. var height = (int)(image.Height * ratio);
  88. SKBitmap tempImage = image;
  89. if (image.Width != width || image.Height != height)
  90. {
  91. tempImage = image.Resize(new SKImageInfo(width, height), SKFilterQuality.High);
  92. }
  93. try
  94. {
  95. using (var map = new SKPixmap(new SKImageInfo(tempImage.Width, tempImage.Height, tempImage.ColorType), tempImage.GetPixels()))
  96. {
  97. using (var stream = new SKDynamicMemoryWStream())
  98. {
  99. SKPixmap.Encode(stream, map, SKEncodedImageFormat.Jpeg, 50);
  100. compressedData = stream.CopyToData().ToArray();
  101. }
  102. }
  103. }
  104. catch (Exception exception)
  105. {
  106. throw new Exception($"Compress error:{exception}");
  107. }
  108. finally
  109. {
  110. tempImage.Dispose();
  111. }
  112. }
  113. }
  114. }
  115. var updater = new VinnoImageUpdater(vinnoImage);
  116. updater.Update(compressedData);
  117. return vinnoImage;
  118. }
  119. }
  120. }