# 把Mono12Packed的buffer
邮箱:yiyangyu1314@outlook.com
作者:易陽羽
时间:2023-06-08
2
3
4
5
# 1.用C#把Mono12Packed的buffer 保存为16位的tiff 图
以下是将Mono12Packed缓冲区保存为16位TIFF图像的C#代码示例。在这个例子中,我们使用了FreeImage库来处理图像数据和文件IO。
using System;
using System.Runtime.InteropServices;
using FreeImageAPI;
// 定义Mono12Packed数据结构
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Mono12PackedPixel
{
public byte LSB;
public byte MSB;
}
class Program
{
static void Main(string[] args)
{
// 假设我们已经有了Mono12Packed的数据缓冲区和图像尺寸信息
Mono12PackedPixel[] imageData; // 缓冲区
int width, height; // 图像宽高
// 转换到16位灰度
ushort[] imageData16 = new ushort[width * height];
for(int i = 0; i < imageData.Length; i++)
{
Mono12PackedPixel pixel = imageData[i];
ushort value = (ushort)((pixel.MSB << 8) | pixel.LSB);
imageData16[i] = value << 4; // 由12位转换成16位,左移4位
}
// 使用FreeImage创建一个16位灰度图像
FIBITMAP image = FreeImage.AllocateT(FREE_IMAGE_TYPE.FIT_UINT16, width, height, 16);
// 将数据缓冲区写入图像
FreeImage.ConvertFromRawBitsEx(true, imageData16, image, width * sizeof(ushort), 16, 0xFF00, 0x00FF, 0xFF0000);
// 保存图像为TIFF文件
FreeImage.Save(FREE_IMAGE_FORMAT.FIF_TIFF, image, "output.tif", FREE_IMAGE_SAVE_FLAGS.TIFF_DEFAULT);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
这个例子中,我们将Mono12Packed缓冲区的数据先转换为16位灰度值,然后使用FreeImage库来创建一个16位灰度图 像,最后将数据写入并保存为TIFF格式的文件。请注意,这里将数据由
# 2用C++ 把Mono12的buffer 保存为16位的bmp,tiff,png,raw,jpeg 文件,封装为动态库dll,并使用C#,JAVA Jna调用存图接口
用C#把Mono12Packed的buffer 保存为16位的tiff 图像
要将Mono12Packed格式的缓冲区保存为16位的TIFF图像,可以使用以下步骤:
- 安装System.Drawing.Common和BitMiracle.LibTiff.Net库,以处理TIFF图 像。在Visual Studio中,转到“工具”>“NuGet包管理器”>“管理解决方案的NuGet包”,然后搜 索并安装这两个库。或者,在命令行中使用以下命令:
dotnet add package System.Drawing.Common
dotnet add package BitMiracle.LibTiff.NET
2
- 使用以下代码将Mono12Packed缓冲区转换为16位缓冲区:
public static ushort[] ConvertMono12PackedTo16Bit(byte[] mono12PackedBuffer, int width, int height)
{
int pixelCount = width * height;
ushort[] outputBuffer = new ushort[pixelCount];
int packedIndex = 0;
int outputIndex = 0;
while (outputIndex < pixelCount)
{
// Unpack 3 bytes into 2 12-bit values
ushort firstPixel = (ushort)(((mono12PackedBuffer[packedIndex] << 4) | (mono12PackedBuffer[packedIndex + 1] & 0x0F)));
ushort secondPixel = (ushort)(((mono12PackedBuffer[packedIndex + 2] << 4) | (mono12PackedBuffer[packedIndex + 1] >> 4)));
outputBuffer[outputIndex++] = firstPixel;
outputBuffer[outputIndex++] = secondPixel;
packedIndex += 3;
}
return outputBuffer;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 使用以下代码将16位缓冲区保存为TIFF图像:
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using BitMiracle.LibTiff.Classic;
public static void Save16BitBufferToTiff(ushort[] buffer, int width, int height, string fileName)
{
using (Tiff tiff = Tiff.Open(fileName, "w"))
{
tiff.SetField(TiffTag.IMAGEWIDTH, width);
tiff.SetField(TiffTag.IMAGELENGTH, height);
tiff.SetField(TiffTag.BITSPERSAMPLE, 16);
tiff.SetField(TiffTag.SAMPLESPERPIXEL, 1);
tiff.SetField(TiffTag.ROWSPERSTRIP, height);
tiff.SetField(TiffTag.COMPRESSION, Compression.NONE);
tiff.SetField(TiffTag.PHOTOMETRIC, Photometric.MINISBLACK);
tiff.SetField(TiffTag.FILLORDER, FillOrder.MSB2LSB);
tiff.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
byte[] outputBuffer = new byte[width * height * 2];
Buffer.BlockCopy(buffer, 0, outputBuffer, 0, outputBuffer.Length);
tiff.WriteRawStrip(0, outputBuffer, outputBuffer.Length);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 3.用C#把Mono12Packed的buffer 保存为16位的tiff 图像
为了将 Mono12Packed 缓冲区保存为 16 位的 TIFF 图像,我们需要执行以下步骤:
- 将 Mono12Packed 缓冲区转换为 16 位的数据。
- 使用支持 16 位 TIFF 图像的库(如
ImageSharp
)创建一个新的图像。 - 将数据写入新的 TIFF 图像。
- 将 TIFF 图像保存到文件。
- 首先,你需要在项目中安装
ImageSharp
库。在 Visual Studio 中,右键单击项目并选 择 "Manage NuGet Packages",搜索 "ImageSharp" 并安装它。或者,你可以使用以下命令在命令行中安装:
dotnet add package SixLabors.ImageSharp
一旦安装了
ImageSharp
,你可以使用以下代码将 Mono12Packed 缓冲区保存为 16 位的 TIFF 图像:using System; using System.IO; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; public static void SaveMono12PackedBufferAsTiff(byte[] mono12PackedBuffer, int width, int height, string outputPath) { // Step 1: Convert Mono12Packed buffer to 16-bit data. ushort[] data16Bit = ConvertMono12PackedTo16Bit(mono12PackedBuffer, width, height); // Step 2: Create a new image with the 16-bit data. using Image<Gray16> image = new Image<Gray16>(Configuration.Default, width, height); // Step 3: Write the 16-bit data to the image. for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int dataIndex = y * width + x; image[x, y] = new Gray16(data16Bit[dataIndex]); } } // Step 4: Save the image as a TIFF file. using FileStream output = File.OpenWrite(outputPath); image.Save(output, new SixLabors.ImageSharp.Formats.Tiff.TiffEncoder()); } public static ushort[] ConvertMono12PackedTo16Bit(byte[] mono12PackedBuffer, int width, int height) { int inputLength = width * height * 3 / 2; if (mono12PackedBuffer.Length != inputLength) { throw new ArgumentException("Invalid buffer length for the specified width and height."); } ushort[] output = new ushort[width * height]; int outputIndex = 0; for (int i = 0; i < inputLength; i += 3) { ushort firstPixel = (ushort)(((mono12PackedBuffer[i] << 4) | (mono12PackedBuffer[i + 1] & 0x0F))); ushort secondPixel = (ushort)(((mono12PackedBuffer[i + 1] & 0xF0) >> 4) | (mono12PackedBuffer[i + 2] << 4)); output[outputIndex++] = firstPixel; output[outputIndex++] = secondPixel; } return output; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
- 现在你可以使用 `SaveMono12PackedBufferAsTiff` 函数将 Mono12Packed 缓冲区保存为 16 位的 TIFF 图像。例如:
```csharp
byte[] mono12PackedBuffer = ...; // Your Mono12Packed data
int width = ...; // Image width
int height = ...; // Image height
string outputPath = "output.tif";
SaveMono12PackedBufferAsTiff(mono12PackedBuffer, width, height, outputPath);
2
3
4
5
6
7
8
9
10
这将会将 Mono12Packed 缓冲区保存为 16 位的 TIFF 图像。
# 4.用C++ 把Mono12的buffer 保存为16位的bmp,tiff,png,raw,jpeg 文件,封装为动态库dll,并使用C#,JAVA Jna调用存图接口
用于将Mono12的buffer保存为16位的bmp、tiff、png、raw和jpeg文件。然后提供C#和Java的示例代码,展示如何调用这个动态库。
首先,创建一个C++项目并将其设置为动态库。
- 使用以下代码编写
ImageSaver.h
文件:
#pragma once
#include <cstdint>
#ifdef IMAGESAVER_EXPORTS
#define IMAGESAVER_API __declspec(dllexport)
#else
#define IMAGESAVER_API __declspec(dllimport)
#endif
extern "C" {
IMAGESAVER_API bool SaveAsBMP(const char* filename, const uint8_t *buffer, int width, int height);
IMAGESAVER_API bool SaveAsTIFF(const char* filename, const uint8_t *buffer, int width, int height);
IMAGESAVER_API bool SaveAsPNG(const char* filename, const uint8_t *buffer, int width, int height);
IMAGESAVER_API bool SaveAsRAW(const char* filename, const uint8_t *buffer, int width, int height);
IMAGESAVER_API bool SaveAsJPEG(const char* filename, const uint8_t *buffer, int width, int height);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 使用以下代码编写
ImageSaver.cpp
文件:
#include "ImageSaver.h"
#include <fstream>
#include <opencv2/opencv.hpp>
bool SaveImage(const char* filename, const uint8_t *buffer, int width, int height, int format) {
cv::Mat image(height, width, CV_16UC1, const_cast<uint8_t*>(buffer));
return cv::imwrite(filename, image, { cv::IMWRITE_PNG_COMPRESSION, 9, cv::IMWRITE_JPEG_QUALITY, 95, cv::IMWRITE_JPEG_PROGRESSIVE, 0, cv::IMWRITE_JPEG_OPTIMIZE, 1, cv::IMWRITE_TIFF_COMPRESSION, 1 });
}
bool SaveAsBMP(const char* filename, const uint8_t *buffer, int width, int height) {
return SaveImage(filename, buffer, width, height, cv::IMWRITE_BMP);
}
bool SaveAsTIFF(const char* filename, const uint8_t *buffer, int width, int height) {
return SaveImage(filename, buffer, width, height, cv::IMWRITE_TIFF);
}
bool SaveAsPNG(const char* filename, const uint8_t *buffer, int width, int height) {
return SaveImage(filename, buffer, width, height, cv::IMWRITE_PNG);
}
bool SaveAsRAW(const char* filename, const uint8_t *buffer, int width, int height) {
std::ofstream file(filename, std::ios::binary);
if (!file.is_open()) {
return false;
}
file.write(reinterpret_cast<const char*>(buffer), width * height * sizeof(uint16_t));
file.close();
return true;
}
bool SaveAsJPEG(const char* filename, const uint8_t *buffer, int width, int height) {
return SaveImage(filename, buffer, width, height, cv::IMWRITE_JPEG);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
- 编译项目以生成动态库(例如
ImageSaver.dll
)。
接下来,使用C#和Java调用动态库。C# 代码示例:
using System;
using System.Runtime.InteropServices;
class ImageSaver {
[DllImport("ImageSaver.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool SaveAsBMP(string filename, byte[] buffer, int width, int height);
[DllImport
2
3
4
5
6
7
8
# 6.用C++ 把Mono12的buffer 保存为16位的bmp,tiff,png,raw,jpeg 文件,封装为动态库dll,并使用C#,JAVA Jna调用存图接口
首先,我们需要使用C++创建一个动态库,它可以将Mono12格式的缓冲区保存为16位的bmp, tiff, png, raw, jpeg文件。 然后,我们将使用C#和Java JNA调用此动态库中的函数。
# 6.1 C++ 动态库
- 创建一个新的C++项目,将其命名为
Mono12ToImage
,并将其类型设置为“动态库”。 - 添加以下依赖库:
- OpenCV(用于图像处理和保存)
- libtiff(用于处理tiff文件)
- 在项目中创建一个名为
Mono12ToImage.h
的头文件,并添加以下内容:
#pragma once
#include <string>
#ifdef MONO12TOIMAGE_EXPORTS
#define MONO12TOIMAGE_API __declspec(dllexport)
#else
#define MONO12TOIMAGE_API __declspec(dllimport)
#endif
extern "C" {
MONO12TOIMAGE_API int saveImage(const unsigned char* mono12Buffer, int width, int height, const char* outputPath, const char* format);
}
2
3
4
5
6
7
8
9
10
11
12
13
- 创建一个名为
Mono12ToImage.cpp
的源文件,并添加以下内容:
#include "Mono12ToImage.h"
#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>
int saveImage(const unsigned char* mono12Buffer, int width, int height, const char* outputPath, const char* format) {
// 将Mono12的buffer转换为16位的cv::Mat
cv::Mat mono12Image(height, width, CV_16UC1);
// TODO: 将mono12Buffer转换为mono12Image
// 保存图像
std::vector<int> compression_params;
std::string formatStr(format);
if (formatStr == "bmp") {
compression_params.push_back(cv::IMWRITE_BMP_DEPTH);
compression_params.push_back(16);
}
else if (formatStr == "tiff") {
compression_params.push_back(cv::IMWRITE_TIFF_COMPRESSION);
compression_params.push_back(cv::IMWRITE_TIFF_DEFLATE);
}
else if (formatStr == "png") {
compression_params.push_back(cv::IMWRITE_PNG_COMPRESSION);
compression_params.push_back(3);
}
else if (formatStr == "jpeg") {
compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
compression_params.push_back(95);
}
else if (formatStr == "raw") {
// TODO: 保存为raw格式
}
return cv::imwrite(outputPath, mono12Image, compression_params) ? 0 : -1;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
注意:这段代码仅仅提供了一个框架,您需要自行实现将mono12Buffer转换为mono12Image的代码。
- 编译项目以生成Mono12ToImage.dll。
# 6.2 C# 调用
- 在C#项目中添加对Mono12ToImage.dll的引用:
using System.Runtime.InteropServices;
public class Mono12ToImageWrapper {
[DllImport("Mono12ToImage.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int saveImage(byte[] mono12Buffer, int width, int height, string outputPath, string format);
}
2
3
4
5
6
- 调用Mono12ToImageWrapper.saveImage方法将Mono12的缓冲区保存为图像:
byte[] mono12Buffer = new byte[width * height * 2]; // 示例缓冲区
string outputPath = "output.bmp";
string format = "bmp";
int result = Mono12ToImageWrapper.saveImage(mono12Buffer, width, height, outputPath, format);
if (result == 0) {
Console.WriteLine("Image saved successfully!");
} else {
Console.WriteLine("Failed to save image.");
}
2
3
4
5
6
7
8
9
10
# 6.3 Java JNA 调用
- 添加JNA依赖库(Maven):
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.8.0</version>
</dependency>
2
3
4
5
- 创建一个名为
Mono12ToImageLibrary.java
的接口,并添加以下内容:
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface Mono12ToImageLibrary extends Library {
Mono12ToImageLibrary INSTANCE = (Mono12ToImageLibrary) Native.load("Mono12ToImage", Mono12ToImageLibrary.class);
int saveImage(byte[] mono12Buffer, int width, int height, String outputPath, String format);
}
2
3
4
5
6
7
8
- 调用Mono12ToImageLibrary.INSTANCE.saveImage方法将Mono12的缓冲区保存为图像:
byte[] mono12Buffer = new byte[width * height * 2]; // 示例缓冲区
String outputPath = "output.bmp";
String format = "bmp";
int result = Mono12ToImageLibrary.INSTANCE.saveImage(mono12Buffer, width, height, outputPath, format);
if (result == 0) {
System.out.println("Image saved successfully!");
} else {
System.out.println("Failed to save image.");
}
2
3
4
5
6
7
8
9
10
注意:在运行Java程序之前,请确保Mono12ToImage.dll位于系统路径或Java库路径中。
# 7 用C++ 把Mono12Packed的buffer 保存为16位的bmp,tiff,png,raw,jpeg 文件,封装为动态库dll,并使用C#调用存图接口
为了实现这个功能,我们将使用以下库:
- OpenCV:用于图像处理和转换。
- CMake:用于生成跨平台的编译系统。
首先,确保已经在系统中安装了OpenCV。接下来,创建一个名为SaveImage
的项目,并在其中创建以下文件:
CMakeLists.txt
:CMake配置文件。save_image.h
:头文件,声明导出函数。save_image.cpp
:源文件,实现保存图像的功能。test_save_image.cs
:C#测试程序。
以下是每个文件的内容:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.1)
project(SaveImage)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_library(SaveImage SHARED save_image.cpp)
target_link_libraries(SaveImage ${OpenCV_LIBS})
2
3
4
5
6
7
8
9
10
11
12
save_image.h:
#ifndef SAVE_IMAGE_H
#define SAVE_IMAGE_H
#ifdef _WIN32
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
extern "C" {
EXPORT bool SaveMono12PackedToImage(const unsigned char* buffer, int width, int height, const char* filename);
}
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
save_image.cpp:
#include "save_image.h"
#include <opencv2/opencv.hpp>
bool SaveMono12PackedToImage(const unsigned char* buffer, int width, int height, const char* filename) {
cv::Mat rawImage(height, width, CV_16UC1);
// Convert Mono12Packed buffer to 16-bit image
// ...
// Save image
std::vector<int> compression_params;
compression_params.push_back(cv::IMWRITE_PNG_COMPRESSION);
compression_params.push_back(3);
try {
cv::imwrite(filename, rawImage, compression_params);
} catch (const cv::Exception& ex) {
fprintf(stderr, "Error saving image: %s\n", ex.what());
return false;
}
return true;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
注意,在save_image.cpp
中,你需要实现Mono12Packed到16位图像的转换。这取决于你的Mono12Packed格式。
test_save_image.cs:
using System;
using System.Runtime.InteropServices;
class TestSaveImage {
[DllImport("SaveImage.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool SaveMono12PackedToImage(byte[] buffer, int width, int height, string filename);
static void Main() {
byte[] buffer = new byte[100 * 100 * 3 / 2]; // Mono12Packed buffer
int width = 100;
int height = 100;
string filename = "output.png";
if (SaveMono12PackedToImage(buffer, width, height, filename)) {
Console.WriteLine("Image saved successfully.");
} else {
Console.WriteLine("Failed to save image.");
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
现在,你可以使用CMake生成项目,编译动态库,并使用C#程序测试它。注意,你可能需要将动态
库(例如:SaveImage.dll
)复制到C#程序的输出目录。
# 7.用C++ 把Mono12Packed的buffer 保存为16位的bmp,tiff,png,raw,jpeg 文件,封装为动态库dll,并使用C#调用存图接口
- 为了实现这个需求,我们需要完成以下步骤:
- 使用C++创建一个动态库(DLL),该库将负责将Mono12Packed格式的数据转换为16位的图像并保存为不同的文件格式。
- 使用C#编写一个程序,调用上述C++ DLL中的函数。
- 首先,我们来创建一个C++ DLL:
- 使用Visual Studio创建一个新的C++ DLL项目,例如命名为
Mono12PackedConverter
。 - 在项目中添加一个新的C++源文件,例如命名为
Mono12PackedConverter.cpp
。 - 在
Mono12PackedConverter.cpp
中,添加以下代码:
#include <Windows.h>
#include <cstdint>
#include <fstream>
#include <string>
#include <opencv2/opencv.hpp>
extern "C" __declspec(dllexport) int SaveImage(uint8_t* buffer, int width, int height, const char* filename, const char* format)
{
cv::Mat image(height, width, CV_16UC1);
// Convert Mono12Packed to 16-bit image
// ...
std::string file_format(format);
if (file_format == "bmp")
{
cv::imwrite(filename, image, { cv::IMWRITE_BMP_COLOR16 });
}
else if (file_format == "tiff")
{
cv::imwrite(filename, image, { cv::IMWRITE_TIFF_COMPRESSION, cv::IMWRITE_TIFF_LZW });
}
else if (file_format == "png")
{
cv::imwrite(filename, image, { cv::IMWRITE_PNG_COMPRESSION, 9 });
}
else if (file_format == "jpeg")
{
cv::imwrite(filename, image, { cv::IMWRITE_JPEG_QUALITY, 95 });
}
else if (file_format == "raw")
{
std::ofstream outfile(filename, std::ios::binary);
outfile.write(reinterpret_cast<const char*>(image.data), width * height * 2);
outfile.close();
}
else
{
return -1;
}
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
注意:在这个示例中,我们使用了OpenCV库来处理图像。确保在项目中安装并链接OpenCV库。
- 现在,我们使用C#编写一个程序来调用这个C++ DLL:
- 使用Visual Studio创建一个新的C#控制台应用程序项目,例如命名为
Mono12PackedConverterTest
。 - 在项目中,添加一个新的C#类,例如命名为
Mono12PackedConverterWrapper.cs
。 - 在
Mono12PackedConverterWrapper.cs
中,添加以下代码:
using System;
using System.Runtime.InteropServices;
public class Mono12PackedConverterWrapper
{
[DllImport("Mono12PackedConverter.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SaveImage(byte[] buffer, int width, int height, string filename, string format);
}
2
3
4
5
6
7
8
- 在
Program.cs
中,添加以下代码来测试DLL:
using System;
namespace Mono12PackedConverterTest
{
class Program
{
static void Main(string[] args)
{
// Create a sample buffer with Mono12Packed data
byte[] buffer = new byte[100 * 100 * 3 / 2]; // width * height * 1.5
// Call the C++ DLL to save the image
int result = Mono12PackedConverterWrapper.SaveImage(buffer, 100, 100, "output.bmp", "bmp");
if (result == 0)
{
Console.WriteLine("Image saved successfully.");
}
else
{
Console.WriteLine("Failed to save image.");
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
现在,当你运行C#程序时,它将调用C++ DLL中的SaveImage
函数,并将Mono12Packed格式的数据保存
为指定的图像格式。请注意,这个示例中的buffer
只是一个空的示例数据,您需要将其替换为实际的Mono12Packed数据。