ImageOperation.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. using ChunkyImageLib.DataHolders;
  2. using SkiaSharp;
  3. namespace ChunkyImageLib.Operations;
  4. internal class ImageOperation : IDrawOperation
  5. {
  6. private SKMatrix transformMatrix;
  7. private ShapeCorners corners;
  8. private Surface toPaint;
  9. private bool imageWasCopied = false;
  10. private readonly SKPaint? customPaint;
  11. public bool IgnoreEmptyChunks => false;
  12. public ImageOperation(VecI pos, Surface image, SKPaint? paint = null, bool copyImage = true)
  13. {
  14. if (paint is not null)
  15. customPaint = paint.Clone();
  16. corners = new()
  17. {
  18. TopLeft = pos,
  19. TopRight = new(pos.X + image.Size.X, pos.Y),
  20. BottomRight = pos + image.Size,
  21. BottomLeft = new VecD(pos.X, pos.Y + image.Size.Y)
  22. };
  23. transformMatrix = SKMatrix.CreateIdentity();
  24. transformMatrix.TransX = pos.X;
  25. transformMatrix.TransY = pos.Y;
  26. // copying is needed for thread safety
  27. if (copyImage)
  28. toPaint = new Surface(image);
  29. else
  30. toPaint = image;
  31. imageWasCopied = copyImage;
  32. }
  33. public ImageOperation(ShapeCorners corners, Surface image, SKPaint? paint = null, bool copyImage = true)
  34. {
  35. if (paint is not null)
  36. customPaint = paint.Clone();
  37. this.corners = corners;
  38. transformMatrix = OperationHelper.CreateMatrixFromPoints(corners, image.Size);
  39. // copying is needed for thread safety
  40. if (copyImage)
  41. toPaint = new Surface(image);
  42. else
  43. toPaint = image;
  44. imageWasCopied = copyImage;
  45. }
  46. public ImageOperation(SKMatrix transformMatrix, Surface image, SKPaint? paint = null, bool copyImage = true)
  47. {
  48. if (paint is not null)
  49. customPaint = paint.Clone();
  50. this.corners = new ShapeCorners()
  51. {
  52. TopLeft = transformMatrix.MapPoint(0, 0),
  53. TopRight = transformMatrix.MapPoint(image.Size.X, 0),
  54. BottomLeft = transformMatrix.MapPoint(0, image.Size.Y),
  55. BottomRight = transformMatrix.MapPoint(image.Size),
  56. };
  57. this.transformMatrix = transformMatrix;
  58. // copying is needed for thread safety
  59. if (copyImage)
  60. toPaint = new Surface(image);
  61. else
  62. toPaint = image;
  63. imageWasCopied = copyImage;
  64. }
  65. public void DrawOnChunk(Chunk chunk, VecI chunkPos)
  66. {
  67. //customPaint.FilterQuality = chunk.Resolution != ChunkResolution.Full;
  68. float scaleMult = (float)chunk.Resolution.Multiplier();
  69. VecD trans = -chunkPos * ChunkPool.FullChunkSize;
  70. var scaleTrans = SKMatrix.CreateScaleTranslation(scaleMult, scaleMult, (float)trans.X * scaleMult, (float)trans.Y * scaleMult);
  71. var finalMatrix = SKMatrix.Concat(scaleTrans, transformMatrix);
  72. chunk.Surface.SkiaSurface.Canvas.Save();
  73. chunk.Surface.SkiaSurface.Canvas.SetMatrix(finalMatrix);
  74. chunk.Surface.SkiaSurface.Canvas.DrawSurface(toPaint.SkiaSurface, 0, 0, customPaint);
  75. chunk.Surface.SkiaSurface.Canvas.Restore();
  76. }
  77. public HashSet<VecI> FindAffectedChunks(VecI imageSize)
  78. {
  79. return OperationHelper.FindChunksTouchingQuadrilateral(corners, ChunkPool.FullChunkSize);
  80. }
  81. public void Dispose()
  82. {
  83. if (imageWasCopied)
  84. toPaint.Dispose();
  85. customPaint?.Dispose();
  86. }
  87. public IDrawOperation AsMirrored(int? verAxisX, int? horAxisY)
  88. {
  89. if (verAxisX is not null && horAxisY is not null)
  90. return new ImageOperation
  91. (corners.AsMirroredAcrossVerAxis((int)verAxisX).AsMirroredAcrossHorAxis((int)horAxisY), toPaint, customPaint, imageWasCopied);
  92. if (verAxisX is not null)
  93. return new ImageOperation
  94. (corners.AsMirroredAcrossVerAxis((int)verAxisX), toPaint, customPaint, imageWasCopied);
  95. if (horAxisY is not null)
  96. return new ImageOperation
  97. (corners.AsMirroredAcrossHorAxis((int)horAxisY), toPaint, customPaint, imageWasCopied);
  98. return new ImageOperation(corners, toPaint, customPaint, imageWasCopied);
  99. }
  100. }