将每采样8位图像转换为每采样1位图像
本文关键字:图像 采样 1位 8位 转换 | 更新日期: 2023-09-27 18:24:06
我有每个样本8位的图像灰度。我想使用Libtiff.net:进行转换
using (Tiff input = Tiff.Open(fileIn, "r"))
{
using (Tiff output = Tiff.Open(fileOut, "w"))
{
for (short page = 0; page < input.NumberOfDirectories(); page++)
{
input.SetDirectory(page);
output.SetDirectory(page);
if (input.GetField(TiffTag.COMPRESSION)[0].ToInt() == (int)Compression.LZW)
{
int width = input.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
int height = input.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
int xres = input.GetField(TiffTag.XRESOLUTION)[0].ToInt();
int yres = input.GetField(TiffTag.YRESOLUTION)[0].ToInt();
int samplesPerPixel = input.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt();
int bitsPerSample = input.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt();
int photo = input.GetField(TiffTag.PHOTOMETRIC)[0].ToInt();
int scanlineSize = input.ScanlineSize();
byte[][] buffer = new byte[height][];
for (int i = 0; i < height; ++i){
buffer[i] = new byte[scanlineSize];
input.ReadScanline(buffer[i], i);
}
output.SetField(TiffTag.IMAGEWIDTH, width);
output.SetField(TiffTag.IMAGELENGTH, height);
output.SetField(TiffTag.COMPRESSION, Compression.CCITTFAX4);
output.SetField(TiffTag.PHOTOMETRIC, Photometric.MINISBLACK);
output.SetField(TiffTag.SAMPLESPERPIXEL, 1);
output.SetField(TiffTag.BITSPERSAMPLE, 1);
output.SetField(TiffTag.XRESOLUTION, xres);
output.SetField(TiffTag.YRESOLUTION, yres);
for (int i = 0; i < height; ++i)
output.WriteScanline(buffer[i], i);
output.WriteDirectory();
}
}
}
}
如何获取8位数组到1位数组的图像?我想在不将字节数组转换为位图对象的情况下完成此操作。什么是正确的方法?感谢
首先,如果您选择每个像素1位,请注意,您得到的图像具有纯黑白像素。
如果您的源是灰度图像,则可以将其上限设置为127,并将所有>127的值设置为"1"和all<=127个值"0",但为了获得更准确的表示,研究抖动函数可能会很有用。
不过,对于127截止方式,您只需制作一个8位数据的数组,该数组的每个像素的亮度应在每个字节的0-255范围内。转换为黑白是相当琐碎的:
for (Int32 i=0; i > imagedata.Length; i++)
imagedata[i] = imagedata[i] > 127 ? 1 : 0;
然后,要将其转换为1位数据的数组,可以使用此函数。"步幅"是您在代码中获得的scanlineSize
。请注意,此函数只为步幅分配所需的最小字节数。
/// <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="newBpp">The new amount of bits per pixel</param>
/// <param name="stride">Stride used in the original image data. Will be adjusted to the new stride value.</param>
/// <param name="bigEndian">Values inside a single byte are read from the largest to the smallest bit.</param>
/// <returns>The image data converted to the requested amount of bits per pixel.</returns>
private static Byte[] ConvertFrom8Bit(Byte[] data8bit, Int32 width, Int32 height, Int32 bitsLength, Boolean bigEndian)
{
if (newBpp > 8)
throw new ArgumentException("Cannot convert to bit format greater than 8!", "newBpp");
if (stride < width)
throw new ArgumentException("Stride is too small for the given width!", "stride");
if (data8bit.Length < stride * height)
throw new ArgumentException("Data given data is too small to contain an 8-bit image of the given dimensions", "data8bit");
Int32 parts = 8 / bitsLength;
// Amount of bytes to write per width
Int32 stride = ((bpp * 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[stride * 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 * stride + x / parts;
// This will always get a new index
Int32 index8bit = y * width + 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);
}
}
return dataXbit;
}
然后,只需要创建一个新的具有正确尺寸的1位tiff,获取其步幅,并将这些字节逐行写入tiff,记住步幅。
注意:我不知道tiff是怎么回事,但在.Net中,1位图像是调色板,所以你可能需要给新图像一个包含黑白的调色板。