-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Mohammad Umair <[email protected]>
- Loading branch information
1 parent
69c47db
commit 55e1e6c
Showing
1 changed file
with
122 additions
and
0 deletions.
There are no files selected for viewing
122 changes: 122 additions & 0 deletions
122
PixelViewer/Media/ImageRenderers/RgbPlanar888ImageRenderer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
using CarinaStudio; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Carina.PixelViewer.Media.ImageRenderers | ||
{ | ||
/// <summary> | ||
/// <see cref="IImageRenderer"/> which supports rendering image with YUV422p based format. | ||
/// </summary> | ||
class RgbPlanar888ImageRenderer : BaseImageRenderer | ||
{ | ||
/// <summary> | ||
/// Initialize new <see cref="RgbPlanar888ImageRenderer"/> instance. | ||
/// </summary> | ||
/// <param name="format">Supported format.</param> | ||
public RgbPlanar888ImageRenderer() : base(new ImageFormat(ImageFormatCategory.ARGB, "RGB_Planar_888", new ImagePlaneDescriptor[] { | ||
new ImagePlaneDescriptor(1), | ||
new ImagePlaneDescriptor(1), | ||
new ImagePlaneDescriptor(1), | ||
}, new string[]{ "RGBPlanar888" })) | ||
{ } | ||
|
||
|
||
// Create default plane options. | ||
public override IList<ImagePlaneOptions> CreateDefaultPlaneOptions(int width, int height) => new List<ImagePlaneOptions>().Also((it) => | ||
{ | ||
it.Add(new ImagePlaneOptions(1, width)); | ||
it.Add(new ImagePlaneOptions(1, width)); | ||
it.Add(new ImagePlaneOptions(1, width)); | ||
}); | ||
|
||
|
||
// Evaluate pixel count. | ||
public override int EvaluatePixelCount(IImageDataSource source) => (int)(source.Size / 3); | ||
|
||
|
||
// Evaluate source data size. | ||
public override long EvaluateSourceDataSize(int width, int height, ImageRenderingOptions renderingOptions, IList<ImagePlaneOptions> planeOptions) | ||
{ | ||
return planeOptions[0].RowStride * height * 3; | ||
} | ||
|
||
|
||
// Render. | ||
protected override unsafe ImageRenderingResult OnRender(IImageDataSource source, Stream imageStream, IBitmapBuffer bitmapBuffer, ImageRenderingOptions renderingOptions, IList<ImagePlaneOptions> planeOptions, CancellationToken cancellationToken) | ||
{ | ||
// get parameters | ||
if (planeOptions.Count != 3) | ||
throw new ArgumentException($"Invalid number of plane options: {planeOptions.Count}."); | ||
var width = bitmapBuffer.Width; | ||
var height = bitmapBuffer.Height; | ||
var pixelStride = planeOptions[0].PixelStride; | ||
var rowStride = planeOptions[0].RowStride; | ||
if (pixelStride <= 0 || rowStride <= 0) | ||
throw new ArgumentException($"Invalid pixel/row stride: {pixelStride}/{rowStride}."); | ||
|
||
// render | ||
bitmapBuffer.Memory.Pin((bitmapBaseAddress) => | ||
{ | ||
var srcRow = new byte[rowStride]; | ||
fixed (byte* srcRowPtr = srcRow) | ||
{ | ||
var bitmapRowPtr = (byte*)bitmapBaseAddress; | ||
var bitmapRowStride = bitmapBuffer.RowBytes; | ||
//Read R values | ||
for (var y = height; ; --y, bitmapRowPtr += bitmapRowStride) | ||
{ | ||
var isLastRow = (imageStream.Read(srcRow) < rowStride || y == 1); | ||
var srcPixelPtr = srcRowPtr; | ||
var bitmapPixelPtr = bitmapRowPtr; | ||
for (var x = width; x > 0; --x, srcPixelPtr += pixelStride, bitmapPixelPtr += 4) | ||
{ | ||
bitmapPixelPtr[0] = srcPixelPtr[0]; | ||
bitmapPixelPtr[3] = 255; | ||
} | ||
if (isLastRow || cancellationToken.IsCancellationRequested) | ||
break; | ||
Array.Clear(srcRow, 0, rowStride); | ||
} | ||
// Read G values | ||
bitmapRowPtr = (byte*)bitmapBaseAddress; | ||
for (var y = height; ; --y, bitmapRowPtr += bitmapRowStride) | ||
{ | ||
var isLastRow = (imageStream.Read(srcRow) < rowStride || y == 1); | ||
var srcPixelPtr = srcRowPtr; | ||
var bitmapPixelPtr = bitmapRowPtr; | ||
for (var x = width; x > 0; --x, srcPixelPtr += pixelStride, bitmapPixelPtr += 4) | ||
{ | ||
bitmapPixelPtr[1] = srcPixelPtr[0]; | ||
} | ||
if (isLastRow || cancellationToken.IsCancellationRequested) | ||
break; | ||
Array.Clear(srcRow, 0, rowStride); | ||
} | ||
// Read B values | ||
bitmapRowPtr = (byte*)bitmapBaseAddress; | ||
for (var y = height; ; --y, bitmapRowPtr += bitmapRowStride) | ||
{ | ||
var isLastRow = (imageStream.Read(srcRow) < rowStride || y == 1); | ||
var srcPixelPtr = srcRowPtr; | ||
var bitmapPixelPtr = bitmapRowPtr; | ||
for (var x = width; x > 0; --x, srcPixelPtr += pixelStride, bitmapPixelPtr += 4) | ||
{ | ||
bitmapPixelPtr[2] = srcPixelPtr[0]; | ||
} | ||
if (isLastRow || cancellationToken.IsCancellationRequested) | ||
break; | ||
Array.Clear(srcRow, 0, rowStride); | ||
} | ||
} | ||
}); | ||
|
||
//complete | ||
return new ImageRenderingResult(); | ||
} | ||
} | ||
} |