0

每个样本图像灰度我有 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 位数组图像?我想在不将字节数组转换为位图对象的情况下做到这一点。什么是正确的方法?谢谢

4

1 回答 1

0

首先,如果您选择每像素 1 位,请注意您会得到一张纯黑白像素的图像。

如果您的源是灰度图像,您可以将其上限设置为 127,并将所有 > 127 的值设为“1”,将所有 <= 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 位图像调色板,因此您可能需要为新图像提供一个包含黑色和白色的调色板。

于 2017-07-06T09:11:26.000 回答