PO/Library/PackageCache/com.unity.2d.psdimporter@4.1.0/Editor/Tasks/FlattenImageTask.cs

126 lines
5.3 KiB
C#

using System;
using System.Collections.Generic;
using PDNWrapper;
using UnityEngine;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
namespace UnityEditor.U2D.PSD
{
static class FlattenImageTask
{
static unsafe public void Execute(List<BitmapLayer> layer, bool importHiddenLayer, int width, int height, NativeArray<Color32> output)
{
UnityEngine.Profiling.Profiler.BeginSample("FlattenImage");
List<IntPtr> buffers = new List<IntPtr>();
for (int i = layer.Count - 1; i >= 0; --i)
{
GetBuffersToMergeFromLayer(layer[i], importHiddenLayer, buffers);
}
if (buffers.Count == 0)
return;
var layersPerJob = buffers.Count / (SystemInfo.processorCount == 0 ? 8 : SystemInfo.processorCount);
layersPerJob = Mathf.Max(layersPerJob, 1);
var job = new FlattenImageInternalJob();
var combineJob = new FlattenImageInternalJob();
job.buffers = new NativeArray<IntPtr>(buffers.ToArray(), Allocator.TempJob);
for (int i = 0; i < buffers.Count; ++i)
job.buffers[i] = buffers[i];
combineJob.width = job.width = width;
combineJob.height = job.height = height;
job.layersPerJob = layersPerJob;
job.flipY = false;
combineJob.flipY = true;
int jobCount = buffers.Count / layersPerJob + (buffers.Count % layersPerJob > 0 ? 1 : 0);
combineJob.layersPerJob = jobCount;
NativeArray<byte>[] premergedBuffer = new NativeArray<byte>[jobCount];
job.output = new NativeArray<IntPtr>(jobCount, Allocator.TempJob);
combineJob.buffers = new NativeArray<IntPtr>(jobCount, Allocator.TempJob);
for (int i = 0; i < jobCount; ++i)
{
premergedBuffer[i] = new NativeArray<byte>(width * height * 4, Allocator.TempJob);
job.output[i] = new IntPtr(premergedBuffer[i].GetUnsafePtr());
combineJob.buffers[i] = new IntPtr(premergedBuffer[i].GetUnsafeReadOnlyPtr());
}
combineJob.output = new NativeArray<IntPtr>(new[] {new IntPtr(output.GetUnsafePtr()), }, Allocator.TempJob);
var handle = job.Schedule(jobCount, 1);
combineJob.Schedule(1, 1, handle).Complete();
foreach (var b in premergedBuffer)
{
if (b.IsCreated)
b.Dispose();
}
UnityEngine.Profiling.Profiler.EndSample();
}
static unsafe void GetBuffersToMergeFromLayer(BitmapLayer layer, bool importHiddenLayer, List<IntPtr> buffers)
{
if (!layer.Visible && importHiddenLayer == false)
return;
if (layer.IsGroup)
{
for (int i = layer.ChildLayer.Count - 1; i >= 0; --i)
GetBuffersToMergeFromLayer(layer.ChildLayer[i], importHiddenLayer, buffers);
}
if (layer.Surface != null)
buffers.Add(new IntPtr(layer.Surface.color.GetUnsafeReadOnlyPtr()));
else
Debug.LogWarning(string.Format("Layer {0} has no color buffer", layer.Name));
}
struct FlattenImageInternalJob : IJobParallelFor
{
[ReadOnly]
[DeallocateOnJobCompletion]
public NativeArray<IntPtr> buffers;
[ReadOnly]
public int layersPerJob;
[ReadOnly]
public int width;
[ReadOnly]
public int height;
[ReadOnly]
public bool flipY;
[DeallocateOnJobCompletion]
public NativeArray<IntPtr> output;
public unsafe void Execute(int index)
{
var premerge = (Color32*)output[index].ToPointer();
for (int layerIndex = index * layersPerJob; layerIndex < (index * layersPerJob) + layersPerJob; ++layerIndex)
{
if (buffers.Length <= layerIndex)
break;
var buffer = (Color32*)buffers[layerIndex].ToPointer();
for (int i = 0; i < height; ++i)
{
int sourceYIndex = i * width;
int destYIndex = flipY ? (height - 1 - i) * width : sourceYIndex;
for (int j = 0; j < width; ++j)
{
int sourceIndex = sourceYIndex + j;
int destIndex = destYIndex + j;
float alpha = buffer[sourceIndex].a / 255.0f;
premerge[destIndex].r = (byte)(alpha * (float)(buffer[sourceIndex].r) + (float)((1.0f - alpha) * (float)premerge[destIndex].r));
premerge[destIndex].g = (byte)(alpha * (float)(buffer[sourceIndex].g) + (float)((1.0f - alpha) * (float)premerge[destIndex].g));
premerge[destIndex].b = (byte)(alpha * (float)(buffer[sourceIndex].b) + (float)((1.0f - alpha) * (float)premerge[destIndex].b));
premerge[destIndex].a = (byte)(alpha * (float)(buffer[sourceIndex].a) + (float)((1.0f - alpha) * (float)premerge[destIndex].a));
}
}
}
}
}
}
}