#wpf #image #shader
#wpf #изображение #шейдер
Вопрос:
Этот:
BitmapSource originalImage;
byte[] _originalPixels;
_originalPixels = new byte[(int) originalImage.Width*(int) originalImage.Height*4];
originalImage.CopyPixels(_originalPixels, 4*(int) originalImage.Width, 0);
копирует байты изображения перед применением фильтра, и в этом нет ничего удивительного.
Как получить байты с уже примененным эффектом?
Как программно применить эффект шейдера к byte[] или какому-либо низкоуровневому массиву пиксельной структуры?
Ответ №1:
Помощник:
public static class ImageRenderingHelper
{
public static BitmapSource RenderToBitmap(FrameworkElement target)
{
int actualWidth = (int)target.ActualWidth;
int actualHeight = (int)target.ActualHeight;
Rect boundary = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap renderBitmap = new RenderTargetBitmap(actualWidth, actualHeight, 96, 96, PixelFormats.Pbgra32);
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext context = drawingVisual.RenderOpen())
{
VisualBrush visualBrush = new VisualBrush(target);
context.DrawRectangle(visualBrush, null, new Rect(new Point(), boundary.Size));
}
renderBitmap.Render(drawingVisual);
return renderBitmap;
}
private static void Arrange(UIElement element, int width, int height)
{
element.Measure(new Size(width, height));
element.Arrange(new Rect(0, 0, width, height));
element.UpdateLayout();
}
public static byte[] RenderImageWithEffects(ImageSource image, IEnumerable<ShaderEffect> effects)
{
effects = effects.Reverse();
Grid root = new Grid();
Arrange(root, (int)image.Width, (int)image.Height);
Grid current = root;
foreach (var shaderEffect in effects)
{
var effect = new Grid();
Arrange(effect, (int)image.Width, (int)image.Height);
effect.Effect = shaderEffect;
current.Children.Add(effect);
current = effect;
}
Image img = new Image();
img.Source = image;
Arrange(img, (int)image.Width, (int)image.Height);
current.Children.Add(img);
BitmapSource bs = RenderToBitmap(root);
byte[] buffer = new byte[(int)bs.Width * (int)bs.Height * 4];
bs.CopyPixels(buffer, 4 * (int)bs.Width, 0);
return buffer;
}
public static byte[] RenderImageWithEffects(string imagePath, IEnumerable<ShaderEffect> effects)
{
BitmapImage bmp = new BitmapImage(new Uri(imagePath, UriKind.Absolute));
return RenderImageWithEffects(bmp, effects);
}
}
Ответ №2:
Как насчет рендеринга вашего изображения в RenderTargetBitmap
и получения пикселей, используемых CopyPixels
на RenderTargetBitmap
? Помогает ли это?