OpencvSharp 的使用 以及配合 BitMiracle.LibTiff.NET 从内存读取多页的TIF
需要同时安装 OpenCvSharp4 和 OpenCvSharp4 runtime,作者 shimat,地址: https://github.com/shimat/opencvsharp
using OpenCvSharp; Mat image1 = Cv2.ImRead("..\272b4318-9a46-ac9d-1675-e7696b9087d1_1.tif", ImreadModes.Color);
cv::Mat 在可以直接转换为 C# Bitmap,速度极快,4ms
var bitmap = new Bitmap(image1Result.Cols, image1Result.Rows, (int)image1Result.Step(), System.Drawing.Imaging.PixelFormat.Format24bppRgb, image1Result.Data);
使用 BitMiracle.LibTiff.NET 从上传文件读取多页 TIF
using System.IO; using System.Web; using BitMiracle.LibTiff.Classic; using OpenCvSharp; class Program { static void Main(HttpPostedFileBase httpPostedFile) { // 从 HttpPostedFile 对象获取图像数据流 Stream stream = httpPostedFile.InputStream; // 将图像数据流读取为字节数组 byte[] imageData; using (var memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); imageData = memoryStream.ToArray(); } // 使用 BitMiracle.LibTiff.NET 加载多页 TIFF 文件 using (var tiff = Tiff.ClientOpen("in-memory", "r", new MemoryStream(imageData), new TiffStream())) { if (tiff != null) { // 获取 TIFF 文件的页数 int pageCount = tiff.NumberOfDirectories(); // 加载所有页面的图像 Mat[] images = new Mat[pageCount]; for (int i = 0; i < pageCount; i++) { tiff.SetDirectory((short)i); int width = tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt(); int height = tiff.GetField(TiffTag.IMAGELENGTH)[0].ToInt(); int bitsPerPixel = tiff.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt(); int samplesPerPixel = tiff.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt(); int bytesPerLine = width * bitsPerPixel / 8; int imageSize = height * bytesPerLine; byte[] buffer = new byte[imageSize]; tiff.ReadScanline(buffer, 0); Mat image = new Mat(height, width, MatType.CV_8UC(samplesPerPixel)); Marshal.Copy(buffer, 0, image.Data, imageSize); images[i] = image; } // 在这里可以使用 OpenCvSharp 对多页 TIFF 文件进行处理 // ... // 释放图像资源 foreach (var image in images) { image.Dispose(); } tiff.Close(); } else { Console.WriteLine("无法加载 TIFF 文件"); } } } }
保存图像位深度为1:
var inputMat = OpenCvSharp.Cv2.ImRead(@"6622df65-c19d-184a-d47f-be2fdf7d72ce_01.tif", OpenCvSharp.ImreadModes.Color); // 将图像转换为灰度 OpenCvSharp.Cv2.CvtColor(inputMat, inputMat, OpenCvSharp.ColorConversionCodes.BGR2GRAY); // 将图像二值化为黑白图像 OpenCvSharp.Cv2.Threshold(inputMat, inputMat, 128, 255, OpenCvSharp.ThresholdTypes.Binary); // 将位深度从8位转换为1位 OpenCvSharp.Cv2.ConvertScaleAbs(inputMat, inputMat, 1.0 / 255.0, 0); // 现在inputMat是一个位深度为1的黑白Mat对象 var saveParams = new OpenCvSharp.ImageEncodingParam[] { new OpenCvSharp.ImageEncodingParam(OpenCvSharp.ImwriteFlags.PngCompression, 3), // 设置 PNG 压缩方式,3 表示 PNG_COMPRESSION_3 new OpenCvSharp.ImageEncodingParam(OpenCvSharp.ImwriteFlags.PngBilevel, 1), // 设置 PNG 位深度为 1 }; // 要将其保存到磁盘,请使用以下代码: inputMat.ImWrite(Server.MapPath("output.png"), saveParams);
转换 Bitmap 为灰度图像:
private Bitmap ConvertToGrayscale(Bitmap bmp) { // Convert input bitmap to Mat object OpenCvSharp.Mat src = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmp); // Create grayscale output mat OpenCvSharp.Mat gray = new OpenCvSharp.Mat(); // Convert input mat to grayscale OpenCvSharp.Cv2.CvtColor(src, gray, OpenCvSharp.ColorConversionCodes.BGR2GRAY, 1); // Convert output mat back to bitmap return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(gray); }
桂棹兮兰桨,击空明兮溯流光。