private void PackBatchInternal(AtlasImageBatch batch) { foreach (var img in batch.Images) { if (img.Width > MaxSize || img.Height > MaxSize) { _singles.Add(img); continue; } int index = 0; TryInsert: AtlasPackerState state = _states[index]; if (!state.Insert(img, out Rect rect)) { if (!state.Step()) { index++; while (index < _states.Count && _states[index].IsSingle) { index++; } if (index == _states.Count) { _states.Add(new AtlasPackerState(MaxSize, Spacing, false)); } } goto TryInsert; } state.Items.Add(new AtlasPackerState.Item(rect, img)); } }
public unsafe AtlasData Serialize( AtlasPacker packer, DirectoryInfo output, TextureDelegate onTexture, ProgressDelegate onProgress) { int stateCount = packer._states.Count; int singleCount = packer._singles.Count; var textures = new string[stateCount + singleCount]; int totalItemCount = packer.TotalItemCount; var items = new List <AtlasData.Item>(totalItemCount); if (!output.Exists) { output.Create(); } void AddItem(AtlasData.Item item) { items.Add(item); onProgress.Invoke(items.Count / (float)totalItemCount); } for (int textureIndex = 0; textureIndex < stateCount; textureIndex++) { AtlasPackerState state = packer._states[textureIndex]; int width = state.Width; int height = state.Height; using (var result = new Image <Rgba32>(width, height)) { Span <Rgba32> resultSpan = result.GetPixelSpan(); foreach (AtlasPackerState.Item item in state.Items) { using (var img = Image.Load <Rgba32>(item.AtlasImage.File.OpenRead())) { var srcRect = new Rect(0, 0, img.Width, img.Height); var input32 = img.GetPixelSpan(); Copy(input32, inputStride: srcRect.W, srcRect, resultSpan, outputStride: width, item.Rect); AddItem(new AtlasData.Item(item.AtlasImage.RelativePath, textureIndex, item.Rect)); } } using (var fs = GetFileStream(textures, textureIndex, output)) result.Save(fs, SaveFormat); onTexture?.Invoke(resultSpan, new Size(width, height), textureIndex); } } for (int singleIndex = 0; singleIndex < singleCount; singleIndex++) { AtlasImage item = packer._singles[singleIndex]; using (var img = Image.Load <Rgba32>(item.File.OpenRead())) { int index = singleIndex + stateCount; // add amount of states as offset using (var fs = GetFileStream(textures, index, output)) img.Save(fs, SaveFormat); AddItem(new AtlasData.Item(item.RelativePath, index, 0, 0, item.Width, item.Height)); onTexture?.Invoke(img.GetPixelSpan(), new Size(item.Width, item.Height), index); } } return(new AtlasData(textures, items)); }