|
|
以下是修改后的代码,直接处理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[byte_pos] >> (7 - bit_pos)) & 1;
-
- if (pixel == 0) {
- black_blocks[byte_pos] |= (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[byte_pos] >> (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[n_byte_pos] |= (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[n_byte_pos] >> (7 - n_bit_pos)) & 1)) {
- all_set = false;
- }
- }
- }
-
- if (all_set) {
- temp_buffer[byte_pos] |= (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[byte_pos] >> (7 - bit_pos)) & 1) &&
- ((src_data[byte_pos] >> (7 - bit_pos)) & 1)) {
- white_pixels_in_black[byte_pos] |= (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[byte_pos] >> (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[n_byte_pos] |= (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 * bytes_per_row], 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 * bytes_per_row], 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 小助理,如未能正确解答您的问题,请继续追问。 |
|