ImageOperation.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using ChunkyImageLib.DataHolders;
  2. using Drawie.Backend.Core;
  3. using Drawie.Backend.Core.Numerics;
  4. using Drawie.Backend.Core.Surfaces.PaintImpl;
  5. using Drawie.Numerics;
  6. namespace ChunkyImageLib.Operations;
  7. internal class ImageOperation : IMirroredDrawOperation
  8. {
  9. private Matrix3X3 transformMatrix;
  10. private ShapeCorners corners;
  11. private Surface toPaint;
  12. private bool imageWasCopied = false;
  13. private readonly Paint? customPaint;
  14. public bool IgnoreEmptyChunks => false;
  15. public ImageOperation(VecI pos, Surface image, Paint? paint = null, bool copyImage = true)
  16. {
  17. if (paint is not null)
  18. customPaint = paint.Clone();
  19. corners = new()
  20. {
  21. TopLeft = pos,
  22. TopRight = new(pos.X + image.Size.X, pos.Y),
  23. BottomRight = pos + image.Size,
  24. BottomLeft = new VecD(pos.X, pos.Y + image.Size.Y)
  25. };
  26. transformMatrix = Matrix3X3.CreateIdentity();
  27. transformMatrix.TransX = pos.X;
  28. transformMatrix.TransY = pos.Y;
  29. // copying is needed for thread safety
  30. if (copyImage)
  31. toPaint = new Surface(image);
  32. else
  33. toPaint = image;
  34. imageWasCopied = copyImage;
  35. }
  36. public ImageOperation(ShapeCorners corners, Surface image, Paint? paint = null, bool copyImage = true)
  37. {
  38. if (paint is not null)
  39. customPaint = paint.Clone();
  40. this.corners = corners;
  41. transformMatrix = OperationHelper.CreateMatrixFromPoints(corners, image.Size);
  42. // copying is needed for thread safety
  43. if (copyImage)
  44. toPaint = new Surface(image);
  45. else
  46. toPaint = image;
  47. imageWasCopied = copyImage;
  48. }
  49. public ImageOperation(Matrix3X3 transformMatrix, Surface image, Paint? paint = null, bool copyImage = true)
  50. {
  51. if (paint is not null)
  52. customPaint = paint.Clone();
  53. this.corners = new ShapeCorners()
  54. {
  55. TopLeft = transformMatrix.MapPoint(0, 0),
  56. TopRight = transformMatrix.MapPoint(image.Size.X, 0),
  57. BottomLeft = transformMatrix.MapPoint(0, image.Size.Y),
  58. BottomRight = transformMatrix.MapPoint(image.Size),
  59. };
  60. this.transformMatrix = transformMatrix;
  61. // copying is needed for thread safety
  62. if (copyImage)
  63. toPaint = new Surface(image);
  64. else
  65. toPaint = image;
  66. imageWasCopied = copyImage;
  67. }
  68. public void DrawOnChunk(Chunk targetChunk, VecI chunkPos)
  69. {
  70. //customPaint.FilterQuality = chunk.Resolution != ChunkResolution.Full;
  71. float scaleMult = (float)targetChunk.Resolution.Multiplier();
  72. VecD trans = -chunkPos * ChunkPool.FullChunkSize;
  73. var scaleTrans = Matrix3X3.CreateScaleTranslation(scaleMult, scaleMult, (float)trans.X * scaleMult, (float)trans.Y * scaleMult);
  74. var finalMatrix = Matrix3X3.Concat(scaleTrans, transformMatrix);
  75. using var snapshot = toPaint.DrawingSurface.Snapshot();
  76. ShapeCorners chunkCorners = new ShapeCorners(new RectD(VecD.Zero, targetChunk.PixelSize));
  77. RectD rect = chunkCorners.WithMatrix(finalMatrix.Invert()).AABBBounds;
  78. targetChunk.Surface.DrawingSurface.Canvas.Save();
  79. targetChunk.Surface.DrawingSurface.Canvas.SetMatrix(finalMatrix);
  80. targetChunk.Surface.DrawingSurface.Canvas.DrawImage(snapshot, rect, rect, customPaint);
  81. targetChunk.Surface.DrawingSurface.Canvas.Restore();
  82. }
  83. public AffectedArea FindAffectedArea(VecI imageSize)
  84. {
  85. return new AffectedArea(OperationHelper.FindChunksTouchingQuadrilateral(corners, ChunkPool.FullChunkSize),
  86. (RectI)corners.AABBBounds.RoundOutwards());
  87. }
  88. public void Dispose()
  89. {
  90. if (imageWasCopied)
  91. toPaint.Dispose();
  92. customPaint?.Dispose();
  93. }
  94. public IDrawOperation AsMirrored(double? verAxisX, double? horAxisY)
  95. {
  96. if (verAxisX is not null && horAxisY is not null)
  97. {
  98. return new ImageOperation
  99. (corners.AsMirroredAcrossVerAxis((double)verAxisX).AsMirroredAcrossHorAxis((double)horAxisY), toPaint,
  100. customPaint, imageWasCopied);
  101. }
  102. if (verAxisX is not null)
  103. {
  104. return new ImageOperation
  105. (corners.AsMirroredAcrossVerAxis((double)verAxisX), toPaint, customPaint, imageWasCopied);
  106. }
  107. if (horAxisY is not null)
  108. {
  109. return new ImageOperation
  110. (corners.AsMirroredAcrossHorAxis((double)horAxisY), toPaint, customPaint, imageWasCopied);
  111. }
  112. return new ImageOperation(corners, toPaint, customPaint, imageWasCopied);
  113. }
  114. }