#include "G4Tiff.h" #if defined(WIN32) || defined(_WIN64) #include #else #include #include #include #define _access access #define _fileno fileno #define _lseek lseek #endif G4Tiff::G4Tiff(cv::Mat & mat, Mode mode,std::string path , int threshold,int res, int compression) : m_threshold(threshold), m_res(res), m_mode(mode) , compression_(compression) { m_tmppath = mode == Mode::MemoryMode ? cv::tempfile(".tif").c_str() : path; m_mat = mat; if (mode == Mode::MemoryMode) save(mat); } G4Tiff::~G4Tiff() { if (m_mode == Mode::MemoryMode) { if (_access(m_tmppath.c_str(), 0) == 0) { if (!std::remove(m_tmppath.c_str())) {}//ɾ³ý³É¹¦ else throw std::runtime_error("File is not exist"); } } } uchar* G4Tiff::load_mini_file(const char* file, size_t* bytes, void* (*mem_alloc)(size_t, const char*)) { uchar* buf = nullptr; if (bytes) *bytes = 0; FILE* src = fopen(file, "rb"); if (src) { int filesize = _lseek(_fileno(src), 0, SEEK_END); // seek to EOF fseek(src, 0, SEEK_SET); std::vector ifh(8, 0); fread(ifh.data(), 1, ifh.size(), src); int size = (int)(*(int*)(ifh.data() + 4)); fseek(src, 8, SEEK_SET); if (filesize) { if (bytes) *bytes = size; buf = (uchar*)mem_alloc(size, ""); if (buf) fread(buf, 1, size, src); } fclose(src); } return buf; } void G4Tiff::GetCompressedData(std::vector& cmpeddata) { if (m_tmppath.empty()) throw std::runtime_error("file is not exist"); FILE* file = fopen(m_tmppath.c_str(), "rb"); if (file) { int filesize = _lseek(_fileno(file), 0, SEEK_END); // seek to EOF fseek(file, 0, SEEK_SET); std::vector ifh(8, 0); fread(ifh.data(), 1, ifh.size(), file); int size = (int)(*(int*)(ifh.data() + 4)); fseek(file, 8, SEEK_SET); if (filesize) { cmpeddata.resize(size); fread(cmpeddata.data(), 1, size, file); } } fclose(file); } uchar* G4Tiff::get_compressed_data(size_t* bytes, void* (*mem_alloc)(size_t, const char*)) { if (m_tmppath.empty()) throw std::runtime_error("file is not exist"); return G4Tiff::load_mini_file(m_tmppath.c_str(), bytes, mem_alloc); } void G4Tiff::SaveG4Tiff() { save(m_mat); } void G4Tiff::save(cv::Mat& mat) { if (compression_ == COMPRESSION_CCITT_T6 && mat.channels() != 1) throw std::runtime_error("mat channel error"); TIFF* pTiffHandle = TIFFOpen(m_tmppath.c_str(), "w"); if (!pTiffHandle) { printf("can't open TIFF descriptor\n"); } int width = mat.cols; int height = mat.rows; try { except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width), "width"); except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height), "length"); if (compression_ == COMPRESSION_CCITT_T6) { except(TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, 1), "bits per sample"); except(TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, 1), "samples per pixel"); } else { except(TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, /*mat.depth()*/8), "bits per sample"); except(TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, mat.channels()), "samples per pixel"); } except(TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, height), "rows per strip"); except(TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, compression_), "compression"); except(TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE), "photometric"); except(TIFFSetField(pTiffHandle, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB), "photometric"); except(TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG), "planar config"); // not necessary except(TIFFSetField(pTiffHandle, TIFFTAG_XRESOLUTION, (float)m_res), "res x"); except(TIFFSetField(pTiffHandle, TIFFTAG_YRESOLUTION, (float)m_res), "res y"); except(TIFFSetField(pTiffHandle, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH), "res unit"); if (compression_ == COMPRESSION_CCITT_T6) { std::vector _buffer(width / 8 + 8, 0); //std::vector _buffer(width / 8 + 1, 0); uchar* buffer = &_buffer[0]; //int bytes = int(width / 8.0 + 0.5); for (int y = 0; y < height; ++y) { uint8_t* src_row = mat.ptr(y); for (int x = 0; x < width; ++x, ++src_row) { uint8_t eight_pixels = buffer[x / 8]; eight_pixels = eight_pixels << 1; if (*src_row < m_threshold) eight_pixels = eight_pixels | 1; // buffer[x / 8] = eight_pixels; } except(TIFFWriteScanline(pTiffHandle, buffer, y, 0) != -1, "write scanline"); } } else { int l = mat.total() / mat.rows * mat.channels(); for (int y = 0; y < height; ++y) { uint8_t* src = mat.ptr(y); except(TIFFWriteScanline(pTiffHandle, src, y, 0) != -1, "write scanline"); } } } catch (const std::runtime_error& e) { printf("TIFF writing: %s\n", e.what()); // TIFFClose(pTiffHandle); } TIFFClose(pTiffHandle); } void G4Tiff::except(bool condition, const std::string & message) { if (!condition) throw std::runtime_error("Error " + message); }