FlattenImageTask.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. using System;
  2. using System.Collections.Generic;
  3. using PDNWrapper;
  4. using UnityEngine;
  5. using Unity.Collections;
  6. using Unity.Collections.LowLevel.Unsafe;
  7. using Unity.Jobs;
  8. namespace UnityEditor.U2D.PSD
  9. {
  10. static class FlattenImageTask
  11. {
  12. static unsafe public void Execute(List<BitmapLayer> layer, bool importHiddenLayer, int width, int height, NativeArray<Color32> output)
  13. {
  14. UnityEngine.Profiling.Profiler.BeginSample("FlattenImage");
  15. List<IntPtr> buffers = new List<IntPtr>();
  16. for (int i = layer.Count - 1; i >= 0; --i)
  17. {
  18. GetBuffersToMergeFromLayer(layer[i], importHiddenLayer, buffers);
  19. }
  20. if (buffers.Count == 0)
  21. return;
  22. var layersPerJob = buffers.Count / (SystemInfo.processorCount == 0 ? 8 : SystemInfo.processorCount);
  23. layersPerJob = Mathf.Max(layersPerJob, 1);
  24. var job = new FlattenImageInternalJob();
  25. var combineJob = new FlattenImageInternalJob();
  26. job.buffers = new NativeArray<IntPtr>(buffers.ToArray(), Allocator.TempJob);
  27. for (int i = 0; i < buffers.Count; ++i)
  28. job.buffers[i] = buffers[i];
  29. combineJob.width = job.width = width;
  30. combineJob.height = job.height = height;
  31. job.layersPerJob = layersPerJob;
  32. job.flipY = false;
  33. combineJob.flipY = true;
  34. int jobCount = buffers.Count / layersPerJob + (buffers.Count % layersPerJob > 0 ? 1 : 0);
  35. combineJob.layersPerJob = jobCount;
  36. NativeArray<byte>[] premergedBuffer = new NativeArray<byte>[jobCount];
  37. job.output = new NativeArray<IntPtr>(jobCount, Allocator.TempJob);
  38. combineJob.buffers = new NativeArray<IntPtr>(jobCount, Allocator.TempJob);
  39. for (int i = 0; i < jobCount; ++i)
  40. {
  41. premergedBuffer[i] = new NativeArray<byte>(width * height * 4, Allocator.TempJob);
  42. job.output[i] = new IntPtr(premergedBuffer[i].GetUnsafePtr());
  43. combineJob.buffers[i] = new IntPtr(premergedBuffer[i].GetUnsafeReadOnlyPtr());
  44. }
  45. combineJob.output = new NativeArray<IntPtr>(new[] {new IntPtr(output.GetUnsafePtr()), }, Allocator.TempJob);
  46. var handle = job.Schedule(jobCount, 1);
  47. combineJob.Schedule(1, 1, handle).Complete();
  48. foreach (var b in premergedBuffer)
  49. {
  50. if (b.IsCreated)
  51. b.Dispose();
  52. }
  53. UnityEngine.Profiling.Profiler.EndSample();
  54. }
  55. static unsafe void GetBuffersToMergeFromLayer(BitmapLayer layer, bool importHiddenLayer, List<IntPtr> buffers)
  56. {
  57. if (!layer.Visible && importHiddenLayer == false)
  58. return;
  59. if (layer.IsGroup)
  60. {
  61. for (int i = layer.ChildLayer.Count - 1; i >= 0; --i)
  62. GetBuffersToMergeFromLayer(layer.ChildLayer[i], importHiddenLayer, buffers);
  63. }
  64. if (layer.Surface != null)
  65. buffers.Add(new IntPtr(layer.Surface.color.GetUnsafeReadOnlyPtr()));
  66. else
  67. Debug.LogWarning(string.Format("Layer {0} has no color buffer", layer.Name));
  68. }
  69. struct FlattenImageInternalJob : IJobParallelFor
  70. {
  71. [ReadOnly]
  72. [DeallocateOnJobCompletion]
  73. public NativeArray<IntPtr> buffers;
  74. [ReadOnly]
  75. public int layersPerJob;
  76. [ReadOnly]
  77. public int width;
  78. [ReadOnly]
  79. public int height;
  80. [ReadOnly]
  81. public bool flipY;
  82. [DeallocateOnJobCompletion]
  83. public NativeArray<IntPtr> output;
  84. public unsafe void Execute(int index)
  85. {
  86. var premerge = (Color32*)output[index].ToPointer();
  87. for (int layerIndex = index * layersPerJob; layerIndex < (index * layersPerJob) + layersPerJob; ++layerIndex)
  88. {
  89. if (buffers.Length <= layerIndex)
  90. break;
  91. var buffer = (Color32*)buffers[layerIndex].ToPointer();
  92. for (int i = 0; i < height; ++i)
  93. {
  94. int sourceYIndex = i * width;
  95. int destYIndex = flipY ? (height - 1 - i) * width : sourceYIndex;
  96. for (int j = 0; j < width; ++j)
  97. {
  98. int sourceIndex = sourceYIndex + j;
  99. int destIndex = destYIndex + j;
  100. float alpha = buffer[sourceIndex].a / 255.0f;
  101. premerge[destIndex].r = (byte)(alpha * (float)(buffer[sourceIndex].r) + (float)((1.0f - alpha) * (float)premerge[destIndex].r));
  102. premerge[destIndex].g = (byte)(alpha * (float)(buffer[sourceIndex].g) + (float)((1.0f - alpha) * (float)premerge[destIndex].g));
  103. premerge[destIndex].b = (byte)(alpha * (float)(buffer[sourceIndex].b) + (float)((1.0f - alpha) * (float)premerge[destIndex].b));
  104. premerge[destIndex].a = (byte)(alpha * (float)(buffer[sourceIndex].a) + (float)((1.0f - alpha) * (float)premerge[destIndex].a));
  105. }
  106. }
  107. }
  108. }
  109. }
  110. }
  111. }