[英]C# Convert an image from color to a black and white
我從這里嘗試了幾個例子,但沒有找到任何有效的方法。
我需要能夠將彩色圖像轉換為黑白圖像,以便我可以獲取該數據並將其發送到熱敏打印機。
將圖像從彩色變為黑白似乎很麻煩,因為我在 C# 庫中沒有找到任何方法。
我正在測試的圖像是 PixelFormat.Format32bppArgb,我相信我想將其轉換為 PixelFormat.Format1bppIndexed
編輯:不知道如何讓它更清楚。 我不想要灰度,我想要黑白,這就是“PixelFormst.Format1bppIndexed”
您可以使用 ImageMagick 來實現,它安裝在大多數 Linux 發行版上,可免費用於 OSX(最好是通過homebrew
),也可從此處免費用於 Windows。
如果您從這個平滑的灰度漸變開始:
在命令行中,您可以將其用於 Floyd-Steinberg 抖動:
convert grey.png -dither FloydSteinberg -monochrome fs.bmp
或者,這對於Riemersma抖動:
convert grey.png -dither Riemersma -monochrome riem.bmp
Glenn 所指的 Ordered Dither 可以像這樣使用不同的平鋪選項:
convert grey.png -ordered-dither o8x8 -monochrome od8.bmp
convert grey.png -ordered-dither o2x2 -monochrome od2.bmp
檢查格式顯示它是 1bpp,帶有 2 個調色板:
identify -verbose riem.bmp
Image: riem.bmp
Format: BMP (Microsoft Windows bitmap image)
Class: PseudoClass
Geometry: 262x86+0+0
Units: PixelsPerCentimeter
Type: Bilevel
Base type: Bilevel <--- 1 bpp
Endianess: Undefined
Colorspace: Gray
Depth: 1-bit <--- 1 bpp
Channel depth:
gray: 1-bit
Channel statistics:
Pixels: 22532
Gray:
min: 0 (0)
max: 1 (1)
mean: 0.470486 (0.470486)
standard deviation: 0.499128 (0.499128)
kurtosis: -1.98601
skewness: 0.118261
entropy: 0.997485
Colors: 2
Histogram:
11931: ( 0, 0, 0) #000000 gray(0)
10601: (255,255,255) #FFFFFF gray(255)
Colormap entries: 2
Colormap:
0: ( 0, 0, 0) #000000 gray(0) <--- colourmap has only black...
1: (255,255,255) #FFFFFF gray(255) <--- ... and white
如果您從這樣的彩色圖像開始:
並像這樣處理:
convert colour.png -ordered-dither o8x8 -monochrome od8.bmp
你會得到這個
正如格倫所說,ImageMagick 有 C# 綁定 - 或者您可以只在批處理文件中使用上述命令,或者使用 C# 等效的system()
調用來執行上述 ImageMagick 命令。
Imagemagick 可以通過各種方法將圖像轉換為黑白圖像,包括抖動 (-dither) 和有序抖動 (-ordered-dither)。 我通常使用命令行界面,但您可以嘗試使用名為 magick.net 的 C# 綁定。 參見magick.codeplex.com 。
有關一些示例,請參閱codegolf.stackexchange.com 上的此問答
您可以使用此代碼將圖像轉換為黑白。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Converting_Image_to__Black_and_White
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static int siyahbeyazsinirnoktasi=0;
public static string DosyaYolu = "";
#region resim üzerinde işlemler yapma (siyah beyaz)
Bitmap BlackandWhite(Bitmap Goruntu)
{
Bitmap yeniGoruntu = new Bitmap(Goruntu.Width,
Goruntu.Height);//Bitmap sınıfımızı oluşturduk.
double toplampikselsayisi = Goruntu.Width * Goruntu.Height;
int GriTonlama;
for (int i = 0; i < Goruntu.Width; i++)//resmi yatay olarak
taramak için
{
for (int j = 0; j < Goruntu.Height; j++)//resmi dikey olarak
taramak için
{
Color Pixel = Goruntu.GetPixel(i, j);//color sınıfını ile
pixel rengini alıyoruz.
GriTonlama = (Pixel.R + Pixel.G + Pixel.B) / 3;//almış
olduğumuz renk değerini gri tona çevirmek için kullanmamız gereken
formül.
if (GriTonlama < siyahbeyazsinirnoktasi)
{
yeniGoruntu.SetPixel(i, j, Color.FromArgb(0, 0,
0));//yeni görüntümüze gri tonlamadaki pixel değerini veriyoruz.
}
if (GriTonlama >= siyahbeyazsinirnoktasi)
{
yeniGoruntu.SetPixel(i, j, Color.FromArgb(255, 255,
255));//yeni görüntümüze gri tonlamadaki pixel değerini veriyoruz.
}
}
}
return yeniGoruntu;
}
#endregion
private void btnLoadImage_Click(object sender, EventArgs e)
{
FolderBrowserDialog Klasor = new FolderBrowserDialog();
openFileDialog1.Title = "Resimdosyası seçiniz.";
openFileDialog1.Filter = "Image files (*.jpg)|*.jpg|Tüm
dosyalar(*.*)|*.*";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
DosyaYolu = openFileDialog1.FileName;
var dosyaboyutu = new FileInfo(DosyaYolu).Length;
if (dosyaboyutu <= 500000)
{
pictureBox1.Image = new
Bitmap(openFileDialog1.OpenFile());
btnConvertBlackandWhite.Enabled = true;
label1.Visible = true;
label2.Visible= true;
label3.Visible = true;
label4.Visible = true;
label5.Visible = true;
label6.Visible = true;
trackBar1.Visible = true;
}
else
{
MessageBox.Show("Seçtiğiniz resim boyutu 500 KB'nın
altında olmalıdır.");
}
}
}
private void btnConvertBlackandWhite_Click(object sender, EventArgs
e)
{
pictureBox1.Image = BlackandWhite(new Bitmap(DosyaYolu));
btnSave.Enabled = true;
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
siyahbeyazsinirnoktasi = trackBar1.Value ;
label3.Text = Convert.ToString(siyahbeyazsinirnoktasi);
}
private void Form1_Load(object sender, EventArgs e)
{
label3.Text = "130";
siyahbeyazsinirnoktasi = 130;
}
private void btnSave_Click(object sender, EventArgs e)
{
{
Image pngoptikform = new Bitmap(pictureBox1.Image);
SaveFileDialog sf = new SaveFileDialog();//yeni bir kaydetme
diyaloğu oluşturuyoruz.
sf.Filter = "Image file (Jpg dosyası (*.jpg)|*.jpg ";//.bmp
veya .jpg olarak kayıt imkanı sağlıyoruz.
sf.Title = "Kayıt";//diğaloğumuzun başlığını belirliyoruz.
sf.CheckPathExists = true;
sf.DefaultExt = "jpg";
sf.FilterIndex = 1;
DialogResult sonuc = sf.ShowDialog();
if (sonuc == DialogResult.OK)
{
if (sf.FilterIndex == 1)
{
pngoptikform.Save(sf.FileName);
System.Diagnostics.Process.Start(sf.FileName);
}
}
}
}
}
}
我相信您可以通過合適的抖動算法獲得相當好的結果。 這里有一個類似的帖子,看看是否對你有幫助:
我個人會分兩步完成:
我之前已經解釋過的第一步,在這個答案中。 (您可能希望使用此處其他答案中所述的更詳細的抖動方法,但即便如此,其將圖像轉換和操作為字節數組的方法也需要答案。)
詳細的基本方法是:
width * height
字節)。 這將使您的圖片轉換為黑白8 位圖像。 現在,獲得1 位圖像所需要做的就是在最后一步之前添加一個新步驟,將 8 位數據壓縮為 1 位數據,然后使用PixelFormat.Format1bppIndexed
對BuildImage
函數進行最后調用PixelFormat.Format1bppIndexed
代替。
這是將圖像減少到較低位長度的函數。 它需要原始圖像數據和步幅,並將返回轉換后的圖像數據和新步幅。
請注意,我不確定普通 dotNet 1 位圖像的數據字節內的位順序是什么,因為我僅使用此函數來轉換自定義游戲文件格式,因此您只需對其進行測試即可查看您需要提供bigEndian
參數。 如果你給出錯誤的值,每列 8 個像素都會被左右鏡像,所以在結果中應該很明顯。
/// <summary>
/// Converts given raw image data for a paletted 8-bit image to lower amount of bits per pixel.
/// </summary>
/// <param name="data8bit">The eight bit per pixel image data</param>
/// <param name="width">The width of the image</param>
/// <param name="height">The height of the image</param>
/// <param name="bitsLength">The new amount of bits per pixel</param>
/// <param name="bigEndian">True if the bits in the new image data are to be stored as big-endian.</param>
/// <param name="stride">Stride used in the original image data. Will be adjusted to the new stride value.</param>
/// <returns>The image data converted to the requested amount of bits per pixel.</returns>
public static Byte[] ConvertFrom8Bit(Byte[] data8bit, Int32 width, Int32 height, Int32 bitsLength, Boolean bigEndian, ref Int32 stride)
{
Int32 parts = 8 / bitsLength;
// Amount of bytes to write per width. This rounds the bits up to the nearest byte.
Int32 newStride = ((bitsLength * width) + 7) / 8;
// Bit mask for reducing original data to actual bits maximum.
// Should not be needed if data is correct, but eh.
Int32 bitmask = (1 << bitsLength) - 1;
Byte[] dataXbit = new Byte[newStride * height];
// Actual conversion porcess.
for (Int32 y = 0; y < height; y++)
{
for (Int32 x = 0; x < width; x++)
{
// This will hit the same byte multiple times
Int32 indexXbit = y * newStride + x / parts;
// This will always get a new index
Int32 index8bit = y * stride + x;
// Amount of bits to shift the data to get to the current pixel data
Int32 shift = (x % parts) * bitsLength;
// Reversed for big-endian
if (bigEndian)
shift = 8 - shift - bitsLength;
// Get data, reduce to bit rate, shift it and store it.
dataXbit[indexXbit] |= (Byte)((data8bit[index8bit] & bitmask) << shift);
}
}
stride = newStride;
return dataXbit;
}
顯示顏色的術語稱為灰度:
快速搜索: color to gray scale converter c#
產生了以下網站: http : //www.codeproject.com/Questions/315939/How-To-Convert-Grayscale-Image-to-Color-Image-in-c
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.