Я думаю, что я на что-то. Я взял изображение, сделал его серым, записал это изображение в массив, каждый байт которого представляет собой пиксель. Затем, используя этот массив, я генерирую другой массив, где каждый байт составляет 8 пикселей, и из этого я либо генерирую окончательное изображение. Это изображение для сравнения:
А вот пример:
xaml
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="500">
<Grid>
<Image x:Name="originalImage" HorizontalAlignment="Left" Height="100" Margin="30,100,0,0" VerticalAlignment="Top" Width="200" />
<Image x:Name="convertedImage" HorizontalAlignment="Left" Height="100" Margin="250,39,0,0" VerticalAlignment="Top" Width="200" />
<Image x:Name="CustomConvertedImage" HorizontalAlignment="Left" Height="100" Margin="250,156,0,0" VerticalAlignment="Top" Width="200" />
</Grid>
</Window>
xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DrawingVisual visual = new DrawingVisual();
using (DrawingContext dc = visual.RenderOpen())
{
int fs = 28;
string textContain = "Testing 123";
Point p = new Point(10, 10);
dc.DrawRectangle(Brushes.Black, null, new Rect(0, 0, originalImage.Width, originalImage.Height));
dc.DrawText(new FormattedText(textContain, System.Globalization.CultureInfo.InvariantCulture, FlowDirection.LeftToRight,
new Typeface("Arial"), fs, Brushes.White, VisualTreeHelper.GetDpi(visual).PixelsPerDip), p);
dc.DrawLine(new Pen(Brushes.White, 3), new Point(5, 5), new Point(originalImage.Width - 5, 5));
dc.DrawLine(new Pen(Brushes.White, 3), new Point(5, originalImage.Height - 5), new Point(originalImage.Width - 5, originalImage.Height - 5));
dc.DrawLine(new Pen(Brushes.White, 3), new Point(5, 5), new Point(5, originalImage.Height));
dc.DrawLine(new Pen(Brushes.White, 3), new Point(originalImage.Width - 5, 0), new Point(originalImage.Width - 5, originalImage.Height - 5));
}
RenderTargetBitmap target =
new RenderTargetBitmap((int)originalImage.Width, (int)originalImage.Height, 96, 96, PixelFormats.Default);
target.Render(visual);
FormatConvertedBitmap grayBitmapSource1 =
new FormatConvertedBitmap(target as BitmapSource, PixelFormats.Bgr24, null, 0);
var grayBitmapSource = new FormatConvertedBitmap();
grayBitmapSource.BeginInit();
grayBitmapSource.Source = grayBitmapSource1.Source as BitmapSource;
grayBitmapSource.DestinationFormat = PixelFormats.BlackWhite;
grayBitmapSource.EndInit();
originalImage.Source = target;
convertedImage.Source = grayBitmapSource;
CustomConvertedImage.Source = ConvertToBlackAndWhiteAliased(originalImage, 80).Item1;
}
private Tuple<System.Windows.Media.Imaging.BitmapSource, byte[]> ConvertToBlackAndWhiteAliased(Image _sourceImage, int _grayFilter = 80)
{
FormatConvertedBitmap grayed8Image = new FormatConvertedBitmap(_sourceImage.Source as BitmapSource, PixelFormats.Gray8, null, 0);
double bytePerPixel_Test = grayed8Image.Format.BitsPerPixel / 8.0;
int width_Test = grayed8Image.PixelWidth;
int height_Test = grayed8Image.PixelHeight;
int stride_Test = (int)(width_Test * bytePerPixel_Test);
byte[] resultLine_Test = new byte[height_Test * stride_Test];
grayed8Image.CopyPixels(resultLine_Test, stride_Test, 0);
double bytePerPixel = 1 / 8.0;
int width = grayed8Image.PixelWidth;
int height = grayed8Image.PixelHeight;
int stride = (int)(width * bytePerPixel);
byte[] resultLine = new byte[height * stride];
byte tempByter;
for (int enum8bpp = 0; enum8bpp < resultLine_Test.Length; enum8bpp += 8)
{
tempByter = 0;
for (int tempByterEnumer = 0; tempByterEnumer < 8; tempByterEnumer++)
{
tempByter |= (byte)(((resultLine_Test[enum8bpp + tempByterEnumer] > _grayFilter) ? 1 : 0) << 7 - tempByterEnumer);
}
resultLine[enum8bpp / 8] = tempByter;
}
WriteableBitmap bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.BlackWhite, null);
bitmap.WritePixels(new Int32Rect(0, 0, width, height), resultLine, (int)(width * (bitmap.Format.BitsPerPixel / 8.0)), 0);
return new Tuple<System.Windows.Media.Imaging.BitmapSource, byte[]>(bitmap, resultLine);
}
}
}
Вы можете получить изображение из функции (с .item1) или напрямую из массива (item2). _grayFilter указывает, насколько чувствительным должен быть конвертер (от 0 до 255 для 256 оттенков серого в формате grey8 pixel). Проблема, которая у меня есть, и по какой-то причине (мозг, вероятно, похож на mu sh potato из-за блокировки), я не могу ее решить, это то, что исходная ширина изображения должна делиться на 8, иначе она выдает исключение , Я имею в виду, я понимаю, почему вам нужно 8 байтов исходного изображения, чтобы сделать байт во втором массиве, но я не могу найти способ добавить нули. Наверное, разберемся завтра, но не стесняйтесь помочь :)