Add image processing and memory management features
Added new namespace `Misaki.HighPerformance.Image` for image processing, including classes for animated GIF handling and memory management. Added `AnimatedFrameResult` class for individual frames in animated images. Added `AnimatedGifEnumerator` class for enumerating frames in animated GIFs. Added `ColorComponents` enum for different color formats. Added `ImageInfo` struct for image dimensions and color components. Added `CRuntime` class for low-level memory management functions. Added `MemoryStats` class to track memory allocation statistics. Added utility functions for creating multi-dimensional arrays. Added new structures for fixed-size UTF-8 encoded strings. Added benchmarking classes to test new memory management features. Changed `StbImage.cs` to include new namespaces and functionality for image data manipulation. Changed project files to target .NET 9.0 and enable new features. Changed `Arena.cs` and `DynamicArena.cs` to use `nuint` for size parameters. Changed `BitSet.cs` to enhance bit manipulation methods. Changed `Program.cs` to run `FunctionPtrBenchmark` for performance testing. Removed memory tracking code from `AllocationManager.cs`, including the `_allocated` dictionary and related logic. Removed `Free` method from `IAllocator.cs` interface. Removed `UNSAFE_COLLECTION_CHECK` preprocessor directive from the codebase. Refactored various files to improve organization, moving from `Unsafe` to `LowLevel` namespace. Refactored `MemoryUtilities` class to include new memory operation methods. Refactored `UnsafeUtilities.cs` to support new collection structures.
This commit is contained in:
149
Misaki.HighPerformance.Image/AnimatedGifEnumerator.cs
Normal file
149
Misaki.HighPerformance.Image/AnimatedGifEnumerator.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using Misaki.HighPerformance.Image.Runtime;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Misaki.HighPerformance.Image
|
||||
{
|
||||
internal class AnimatedGifEnumerator : IEnumerator<AnimatedFrameResult>
|
||||
{
|
||||
private readonly StbImage.stbi__context _context;
|
||||
private StbImage.stbi__gif _gif;
|
||||
private readonly ColorComponents _colorComponents;
|
||||
|
||||
public AnimatedGifEnumerator(Stream input, ColorComponents colorComponents)
|
||||
{
|
||||
if (input == null)
|
||||
throw new ArgumentNullException("input");
|
||||
|
||||
_context = new StbImage.stbi__context(input);
|
||||
|
||||
if (StbImage.stbi__gif_test(_context) == 0)
|
||||
throw new Exception("Input stream is not GIF file.");
|
||||
|
||||
_gif = new StbImage.stbi__gif();
|
||||
_colorComponents = colorComponents;
|
||||
}
|
||||
|
||||
public ColorComponents ColorComponents
|
||||
{
|
||||
get
|
||||
{
|
||||
return _colorComponents;
|
||||
}
|
||||
}
|
||||
|
||||
public AnimatedFrameResult Current
|
||||
{
|
||||
get; private set;
|
||||
}
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public unsafe bool MoveNext()
|
||||
{
|
||||
// Read next frame
|
||||
int ccomp;
|
||||
byte two_back;
|
||||
var result = StbImage.stbi__gif_load_next(_context, _gif, &ccomp, (int)ColorComponents, &two_back);
|
||||
if (result == null)
|
||||
return false;
|
||||
|
||||
if (Current == null)
|
||||
{
|
||||
Current = new AnimatedFrameResult
|
||||
{
|
||||
Width = (uint)_gif.w,
|
||||
Height = (uint)_gif.h,
|
||||
SourceComponent = (ColorComponents)ccomp,
|
||||
Component = ColorComponents == ColorComponents.Default ? (ColorComponents)ccomp : ColorComponents
|
||||
};
|
||||
|
||||
Current.SetData(result);
|
||||
}
|
||||
|
||||
Current.DelayInMs = _gif.delay;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
~AnimatedGifEnumerator()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected unsafe virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_gif != null)
|
||||
{
|
||||
if (_gif._out_ != null)
|
||||
{
|
||||
CRuntime.free(_gif._out_);
|
||||
_gif._out_ = null;
|
||||
}
|
||||
|
||||
if (_gif.history != null)
|
||||
{
|
||||
CRuntime.free(_gif.history);
|
||||
_gif.history = null;
|
||||
}
|
||||
|
||||
if (_gif.background != null)
|
||||
{
|
||||
CRuntime.free(_gif.background);
|
||||
_gif.background = null;
|
||||
}
|
||||
|
||||
_gif = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class AnimatedGifEnumerable : IEnumerable<AnimatedFrameResult>
|
||||
{
|
||||
private readonly Stream _input;
|
||||
private readonly ColorComponents _colorComponents;
|
||||
|
||||
public AnimatedGifEnumerable(Stream input, ColorComponents colorComponents)
|
||||
{
|
||||
_input = input;
|
||||
_colorComponents = colorComponents;
|
||||
}
|
||||
|
||||
public ColorComponents ColorComponents
|
||||
{
|
||||
get
|
||||
{
|
||||
return _colorComponents;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<AnimatedFrameResult> GetEnumerator()
|
||||
{
|
||||
return new AnimatedGifEnumerator(_input, ColorComponents);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user