lukevp / ESC-POS-.NET

Efficient, Easy to Use Thermal Printing & POS (Windows/Linux/OSX, WiFi/BT/USB/Ethernet)
MIT License
503 stars 166 forks source link

Optimization for printing tall images #205

Open jjxtra opened 1 year ago

jjxtra commented 1 year ago

In some cases you have to chunk through images that are very tall (> 2048 pixels height). This allows to print from the raw bit pixel buffers of those images rather than having to save them to png and then pass the png bytes to the print image command.

Chunking code, for reference:

private static IEnumerable<Image<Rgba32>> ExtractChunks(Image<Rgba32> sourceImage)
{
    const int chunkSize = 256;
    for (var y = 0; y < sourceImage.Height; y += chunkSize)
    {
        Rectangle sourceArea = new(0, y, sourceImage.Width, Math.Min(sourceImage.Height - y, chunkSize));
        if (sourceArea.Height < 1)
        {
            yield break;
        }
        Image<Rgba32> targetImage = new(sourceArea.Width, sourceArea.Height);
        int height = sourceArea.Height;
        sourceImage.ProcessPixelRows(targetImage, (sourceAccessor, targetAccessor) =>
        {
            for (int i = 0; i < height; i++)
            {
                Span<Rgba32> sourceRow = sourceAccessor.GetRowSpan(sourceArea.Y + i);
                Span<Rgba32> targetRow = targetAccessor.GetRowSpan(i);
                sourceRow.Slice(sourceArea.X, sourceArea.Width).CopyTo(targetRow);
            }
        });
        yield return targetImage;
    }
}

And example usage:

var mainImage = SixLabors.ImageSharp.Image.Load<Rgba32>(img);
List<byte[]> items = new(16)
{
    e.CenterAlign(),
    e.PrintLine("CENTERED TEXT")
};
foreach (var image in ExtractChunks(mainImage))
{
    var bitPixels = image.ToSingleBitPixelByteArray();
    var bitPixelCommand = e.PrintImageSingleBitPixelByteArray(bitPixels, image.Width, image.Height, false, true);
    items.Add(bitPixelCommand);
}
items.Add(e.FullCutAfterFeed(4));
items.Add(e.FeedLines(4));
await printer.WriteAsync(items.ToArray());
nivle commented 1 year ago

I couldn't get this to work, so I did this