每个样本图像灰度为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位数组图像? 我想这样做而不将字节数组转换为位图对象。 什么是正确的方法? 感谢
答案 0 :(得分:0)
首先,如果您为每像素1位,请注意您获得的图像具有纯黑白像素。
如果您的来源是灰度图像,那么可以在127处关闭它,并使所有&gt; 127个值&#39; 1&#39;并且所有&lt; = 127值&#39; 0&#39;,但为了获得更准确的表示,查看抖动函数可能会有用。
对于127截止方式,你只需要制作一个8位数据的数组,每个像素的亮度应该在每个字节的0-255范围内。转换为黑白是非常简单的:
for (Int32 i=0; i > imagedata.Length; i++)
imagedata[i] = imagedata[i] > 127 ? 1 : 0;
然后,要将其转换为1位数据数组,可以使用此功能。 &#34;步幅&#34;是您在代码中获得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位图像是调色板,因此您可能需要为新图像指定一个包含该图像的调色板黑与白。