C++转换函数
请直接将下面的几个函数修改成处理libtiff库打开1位深度的图像test.tif数据的处理代码不用Opencv函数,不要将图像处理转成8位深度做处理,直接对1位深度图像进行处理,处理完成后保存为2400dpi的1位深度文件,不使用类// 精确识别纯黑色块区域(像素值为0)
Mat identifyPureBlackBlocks(const Mat& binary) {
Mat black_blocks;
// 直接识别值为0的纯黑色像素
threshold(binary, black_blocks, 1, 255, THRESH_BINARY_INV);
// 使用形态学闭操作连接相邻的黑色像素
Mat kernel_connect = getStructuringElement(MORPH_RECT, Size(30, 30));
morphologyEx(black_blocks, black_blocks, MORPH_CLOSE, kernel_connect);
return black_blocks;
}
// 精确选择性膨胀函数
void preciseSelectiveDilate(const Mat& src, Mat& dst, int kernel_size) {
// 步骤1:识别纯黑色块区域
Mat black_blocks = identifyPureBlackBlocks(src);
// 步骤2:在黑色块区域内识别白色像素(值为255)
Mat white_pixels_in_black;
threshold(src, white_pixels_in_black, 200, 255, THRESH_BINARY);
// 步骤3:创建精确的膨胀目标掩膜
Mat dilate_target = Mat::zeros(src.size(), CV_8UC1);
// 精确遍历每个像素
for (int i = 0; i < src.rows; i++) {
for (int j = 0; j < src.cols; j++) {
// 如果当前像素在纯黑色块内且是白色像素,则标记为膨胀目标
if (black_blocks.at<uchar>(i, j) == 255 && src.at<uchar>(i, j) == 255) {
dilate_target.at<uchar>(i, j) = 255;
}
}
}
// 步骤4:对膨胀目标进行精确膨胀
Mat kernel = getStructuringElement(MORPH_CROSS, Size(kernel_size, kernel_size));
Mat dilated_target;
dilate(dilate_target, dilated_target, kernel);
// 步骤5:创建最终结果
dst = src.clone();
// 精确应用膨胀结果
for (int i = 0; i < src.rows; i++) {
for (int j = 0; j < src.cols; j++) {
// 只有在膨胀目标区域的像素才被修改为白色
if (dilated_target.at<uchar>(i, j) == 255) {
dst.at<uchar>(i, j) = 255;
}
}
}
}
以下是使用libtiff库直接处理1位深度TIFF图像的代码:
#include <tiffio.h>
#include <vector>
#include <algorithm>
// 精确识别纯黑色块区域(像素值为0)
std::vector<uint8_t> identifyPureBlackBlocks(const std::vector<uint8_t>& binary, int width, int height) {
std::vector<uint8_t> black_blocks(binary.size(), 0);
// 直接识别值为0的纯黑色像素
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * (width / 8) + j / 8;
int bit_pos = j % 8;
uint8_t pixel = (binary >> (7 - bit_pos)) & 1;
if (pixel == 0) {
black_blocks |= (1 << (7 - bit_pos));
}
}
}
// 形态学闭操作连接相邻黑色像素
int kernel_size = 30;
std::vector<uint8_t> temp = black_blocks;
// 膨胀
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * (width / 8) + j / 8;
int bit_pos = j % 8;
if ((black_blocks >> (7 - bit_pos)) & 1) {
for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
int ni = i + ki;
int nj = j + kj;
if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
int n_byte_pos = ni * (width / 8) + nj / 8;
int n_bit_pos = nj % 8;
temp |= (1 << (7 - n_bit_pos));
}
}
}
}
}
}
// 腐蚀
black_blocks = temp;
temp = std::vector<uint8_t>(binary.size(), 0);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * (width / 8) + j / 8;
int bit_pos = j % 8;
bool all_black = true;
for (int ki = -kernel_size/2; ki <= kernel_size/2 && all_black; ki++) {
for (int kj = -kernel_size/2; kj <= kernel_size/2 && all_black; kj++) {
int ni = i + ki;
int nj = j + kj;
if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
int n_byte_pos = ni * (width / 8) + nj / 8;
int n_bit_pos = nj % 8;
if (!((black_blocks >> (7 - n_bit_pos)) & 1)) {
all_black = false;
}
} else {
all_black = false;
}
}
}
if (all_black) {
temp |= (1 << (7 - bit_pos));
}
}
}
return temp;
}
// 精确选择性膨胀函数
void preciseSelectiveDilate(std::vector<uint8_t>& src, int width, int height, int kernel_size) {
// 识别纯黑色块区域
std::vector<uint8_t> black_blocks = identifyPureBlackBlocks(src, width, height);
// 在黑色块区域内识别白色像素
std::vector<uint8_t> dilate_target(src.size(), 0);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * (width / 8) + j / 8;
int bit_pos = j % 8;
// 如果在纯黑色块内且是白色像素
if (((black_blocks >> (7 - bit_pos)) & 1) &&
((src >> (7 - bit_pos)) & 1)) {
dilate_target |= (1 << (7 - bit_pos));
}
}
}
// 对目标像素进行膨胀
std::vector<uint8_t> result = src;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * (width / 8) + j / 8;
int bit_pos = j % 8;
if ((dilate_target >> (7 - bit_pos)) & 1) {
for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
int ni = i + ki;
int nj = j + kj;
if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
int n_byte_pos = ni * (width / 8) + nj / 8;
int n_bit_pos = nj % 8;
result |= (1 << (7 - n_bit_pos));
}
}
}
}
}
}
src = result;
}
// 主处理函数
int main() {
TIFF* tif_in = TIFFOpen("test.tif", "r");
if (!tif_in) return -1;
uint32 width, height;
TIFFGetField(tif_in, TIFFTAG_IMAGEWIDTH, &width);
TIFFGetField(tif_in, TIFFTAG_IMAGELENGTH, &height);
// 读取1位图像数据
std::vector<uint8_t> buffer(TIFFScanlineSize(tif_in) * height);
for (uint32 row = 0; row < height; row++) {
TIFFReadScanline(tif_in, &buffer, row);
}
TIFFClose(tif_in);
// 处理图像
preciseSelectiveDilate(buffer, width, height, 3);
// 保存为2400dpi的1位图像
TIFF* tif_out = TIFFOpen("output.tif", "w");
TIFFSetField(tif_out, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tif_out, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif_out, TIFFTAG_BITSPERSAMPLE, 1);
TIFFSetField(tif_out, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif_out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(tif_out, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
TIFFSetField(tif_out, TIFFTAG_XRESOLUTION, 2400.0);
TIFFSetField(tif_out, TIFFTAG_YRESOLUTION, 2400.0);
TIFFSetField(tif_out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
TIFFSetField(tif_out, TIFFTAG_ROWSPERSTRIP, height);
TIFFSetField(tif_out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
for (uint32 row = 0; row < height; row++) {
TIFFWriteScanline(tif_out, &buffer, row);
}
TIFFClose(tif_out);
return 0;
}
主要修改说明:
1. 使用 std::vector<uint8_t> 存储1位图像数据
2. 直接操作位数据,保持1位深度不变
3. 手动实现形态学操作(膨胀、腐蚀)
4. 使用libtiff库读写TIFF文件
5. 设置输出分辨率为2400dpi
6. 使用CCITT FAX4压缩保持1位深度
编译时需要链接libtiff库:
-ltiff
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 FishC 发表于 2025-11-14 18:34
以下是使用libtiff库直接处理1位深度TIFF图像的代码:
忘了说了,我TIFF文件打开后是memset函数将数据存放于 unsigned char* chunk_output_1bit = (unsigned char*)_TIFFmalloc(bytes_per_row * actual_height);里面,请修改一下
cxnet 发表于 2025-11-14 18:37
FishC 发表于 2025-11-14 18:34
以下是使用libtiff库 ...
以下是修改后的代码,直接处理1位深度TIFF数据:
#include <tiffio.h>
#include <vector>
#include <algorithm>
#include <cstring>
// 精确识别纯黑色块区域(像素值为0)
void identifyPureBlackBlocks(unsigned char* src_data, unsigned char* black_blocks,
int width, int height, int bytes_per_row) {
// 直接识别值为0的纯黑色像素
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * bytes_per_row + j / 8;
int bit_pos = j % 8;
uint8_t pixel = (src_data >> (7 - bit_pos)) & 1;
if (pixel == 0) {
black_blocks |= (1 << (7 - bit_pos));
}
}
}
// 形态学闭操作连接相邻黑色像素
int kernel_size = 30;
std::vector<uint8_t> temp_buffer(bytes_per_row * height, 0);
// 膨胀操作
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * bytes_per_row + j / 8;
int bit_pos = j % 8;
if ((black_blocks >> (7 - bit_pos)) & 1) {
for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
int ni = i + ki;
int nj = j + kj;
if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
int n_byte_pos = ni * bytes_per_row + nj / 8;
int n_bit_pos = nj % 8;
temp_buffer |= (1 << (7 - n_bit_pos));
}
}
}
}
}
}
// 腐蚀操作
memcpy(black_blocks, temp_buffer.data(), bytes_per_row * height);
memset(temp_buffer.data(), 0, bytes_per_row * height);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * bytes_per_row + j / 8;
int bit_pos = j % 8;
bool all_set = true;
for (int ki = -kernel_size/2; ki <= kernel_size/2 && all_set; ki++) {
for (int kj = -kernel_size/2; kj <= kernel_size/2 && all_set; kj++) {
int ni = i + ki;
int nj = j + kj;
if (ni < 0 || ni >= height || nj < 0 || nj >= width) {
all_set = false;
continue;
}
int n_byte_pos = ni * bytes_per_row + nj / 8;
int n_bit_pos = nj % 8;
if (!((black_blocks >> (7 - n_bit_pos)) & 1)) {
all_set = false;
}
}
}
if (all_set) {
temp_buffer |= (1 << (7 - bit_pos));
}
}
}
memcpy(black_blocks, temp_buffer.data(), bytes_per_row * height);
}
// 精确选择性膨胀函数
void preciseSelectiveDilate(unsigned char* src_data, unsigned char* dst_data,
int width, int height, int bytes_per_row, int kernel_size) {
// 步骤1:识别纯黑色块区域
unsigned char* black_blocks = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
memset(black_blocks, 0, bytes_per_row * height);
identifyPureBlackBlocks(src_data, black_blocks, width, height, bytes_per_row);
// 步骤2:在黑色块区域内识别白色像素(值为1)
unsigned char* white_pixels_in_black = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
memset(white_pixels_in_black, 0, bytes_per_row * height);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * bytes_per_row + j / 8;
int bit_pos = j % 8;
// 如果当前像素在纯黑色块内且是白色像素,则标记
if (((black_blocks >> (7 - bit_pos)) & 1) &&
((src_data >> (7 - bit_pos)) & 1)) {
white_pixels_in_black |= (1 << (7 - bit_pos));
}
}
}
// 步骤3:创建精确的膨胀目标掩膜
memcpy(dst_data, src_data, bytes_per_row * height);
// 在白色像素位置进行膨胀
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int byte_pos = i * bytes_per_row + j / 8;
int bit_pos = j % 8;
if ((white_pixels_in_black >> (7 - bit_pos)) & 1) {
// 对当前白色像素进行膨胀
for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
int ni = i + ki;
int nj = j + kj;
if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
int n_byte_pos = ni * bytes_per_row + nj / 8;
int n_bit_pos = nj % 8;
dst_data |= (1 << (7 - n_bit_pos));
}
}
}
}
}
}
_TIFFfree(black_blocks);
_TIFFfree(white_pixels_in_black);
}
// 保存为2400dpi的1位深度TIFF
void saveAs2400DPI(const char* filename, unsigned char* data, int width, int height, int bytes_per_row) {
TIFF* tif = TIFFOpen(filename, "w");
if (!tif) return;
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 1);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, height);
// 设置2400dpi分辨率
TIFFSetField(tif, TIFFTAG_XRESOLUTION, 2400.0);
TIFFSetField(tif, TIFFTAG_YRESOLUTION, 2400.0);
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
for (int row = 0; row < height; row++) {
TIFFWriteScanline(tif, &data, row, 0);
}
TIFFClose(tif);
}
使用示例:
// 读取1位深度TIFF
TIFF* tif = TIFFOpen("test.tif", "r");
if (tif) {
uint32 width, height;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
int bytes_per_row = TIFFScanlineSize(tif);
unsigned char* chunk_output_1bit = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
for (int row = 0; row < height; row++) {
TIFFReadScanline(tif, &chunk_output_1bit, row);
}
// 处理图像
unsigned char* result_data = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
preciseSelectiveDilate(chunk_output_1bit, result_data, width, height, bytes_per_row, 5);
// 保存结果
saveAs2400DPI("output.tif", result_data, width, height, bytes_per_row);
_TIFFfree(chunk_output_1bit);
_TIFFfree(result_data);
TIFFClose(tif);
}
主要修改点:
[*]使用 unsigned char* chunk_output_1bit 作为输入数据指针
[*]所有操作都直接在1位深度数据上进行,不转换为8位
[*]使用位操作来处理单个像素
[*]手动实现了形态学操作(膨胀、腐蚀)
[*]保存时设置2400dpi分辨率和1位深度
[*]使用CCITT FAX4压缩来保持1位深度
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]