ReplaceColorOperation.cs 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. using ChunkyImageLib.DataHolders;
  2. using PixiEditor.DrawingApi.Core.ColorsImpl;
  3. using PixiEditor.DrawingApi.Core.Numerics;
  4. using PixiEditor.DrawingApi.Core.Surface;
  5. namespace ChunkyImageLib.Operations;
  6. internal class ReplaceColorOperation : IDrawOperation
  7. {
  8. private readonly Color oldColor;
  9. private readonly Color newColor;
  10. private readonly ColorBounds oldColorBounds;
  11. private readonly ulong newColorBits;
  12. public bool IgnoreEmptyChunks => true;
  13. public ReplaceColorOperation(Color oldColor, Color newColor)
  14. {
  15. this.oldColor = oldColor;
  16. this.newColor = newColor;
  17. oldColorBounds = new ColorBounds(oldColor);
  18. newColorBits = newColor.ToULong();
  19. }
  20. public void DrawOnChunk(Chunk targetChunk, VecI chunkPos)
  21. {
  22. ReplaceColor(oldColorBounds, newColorBits, targetChunk);
  23. }
  24. private static unsafe void ReplaceColor(ColorBounds oldColorBounds, ulong newColorBits, Chunk chunk)
  25. {
  26. int maxThreads = Environment.ProcessorCount;
  27. VecI imageSize = chunk.PixelSize;
  28. int rowsPerThread = imageSize.Y / maxThreads;
  29. using Pixmap pixmap = chunk.Surface.DrawingSurface.PeekPixels();
  30. IntPtr pixels = pixmap.GetPixels();
  31. Half* endOffset = (Half*)(pixels + pixmap.BytesSize);
  32. for (Half* i = (Half*)pixels; i < endOffset; i += 4)
  33. {
  34. if (oldColorBounds.IsWithinBounds(i))
  35. {
  36. *(ulong*)i = newColorBits;
  37. }
  38. }
  39. }
  40. public AffectedArea FindAffectedArea(VecI imageSize)
  41. {
  42. RectI rect = new(VecI.Zero, imageSize);
  43. return new AffectedArea(OperationHelper.FindChunksTouchingRectangle(rect, ChunkyImage.FullChunkSize), rect);
  44. }
  45. public void Dispose()
  46. {
  47. }
  48. }