Work on DPX file import. Currently breaking
This commit is contained in:
parent
e293c3168d
commit
095ed397b2
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef DPX_HPP
|
||||||
|
#define DPX_HPP
|
||||||
|
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace cv;
|
||||||
|
|
||||||
|
class DPX {
|
||||||
|
public:
|
||||||
|
DPX();
|
||||||
|
|
||||||
|
bool read(const string& filename);
|
||||||
|
Mat getMat() const;
|
||||||
|
Mat getMatBitDepth(int targetBitDepth) const;
|
||||||
|
|
||||||
|
int getWidth() const;
|
||||||
|
int getHeight() const;
|
||||||
|
int getBitDepth() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct DPXHeader {
|
||||||
|
uint32_t magic; // Magic number (0x53445058 "SDPX" or 0x58504453 "XPDS")
|
||||||
|
uint32_t imageOffset; // Offset to image data
|
||||||
|
uint16_t width;
|
||||||
|
uint16_t height;
|
||||||
|
uint8_t descriptor; // Image descriptor
|
||||||
|
uint8_t bitDepth; // Bits per component
|
||||||
|
uint8_t imageElements; // Number of image elements
|
||||||
|
bool isBigEndian; // File endianness
|
||||||
|
};
|
||||||
|
|
||||||
|
DPXHeader header;
|
||||||
|
Mat image;
|
||||||
|
|
||||||
|
bool readHeader(ifstream& file);
|
||||||
|
void readImageData(ifstream& file);
|
||||||
|
uint32_t swapEndian(uint32_t value);
|
||||||
|
uint16_t swapEndian(uint16_t value);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Example usage
|
||||||
|
int main() {
|
||||||
|
try {
|
||||||
|
DPX dpx;
|
||||||
|
dpx.read("image.dpx");
|
||||||
|
|
||||||
|
// Get the original 16-bit Mat
|
||||||
|
Mat mat16 = dpx.getMat();
|
||||||
|
|
||||||
|
// Get 8-bit version
|
||||||
|
Mat mat8 = dpx.getMatBitDepth(8);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
catch (const exception& e) {
|
||||||
|
cerr << "Error: " << e.what() << endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}*/
|
|
@ -1,80 +0,0 @@
|
||||||
#include <opencv2/opencv.hpp>
|
|
||||||
#include <fstream>
|
|
||||||
#include <vector>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
using namespace cv;
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
struct DXFHeader {
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
uint8_t bitDepth;
|
|
||||||
uint8_t version;
|
|
||||||
uint8_t flags;
|
|
||||||
uint8_t reserved;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DXF {
|
|
||||||
public:
|
|
||||||
explicit DXF(const string& filepath) :
|
|
||||||
_filepath(filepath),
|
|
||||||
_width(0),
|
|
||||||
_height(0),
|
|
||||||
_bitDepth(0) {
|
|
||||||
analyzeFile();
|
|
||||||
loadImageData();
|
|
||||||
}
|
|
||||||
|
|
||||||
int getWidth() const { return _width; }
|
|
||||||
int getHeight() const { return _height; }
|
|
||||||
int getBitDepth() const { return _bitDepth; }
|
|
||||||
bool hasDXFHeader() const { return true; }
|
|
||||||
|
|
||||||
Mat to8bitBGR() const;
|
|
||||||
Mat to10bitBGR() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
string _filepath;
|
|
||||||
int _width;
|
|
||||||
int _height;
|
|
||||||
int _bitDepth;
|
|
||||||
Mat _imageData;
|
|
||||||
|
|
||||||
void analyzeFile();
|
|
||||||
bool readDXFHeader(ifstream& file);
|
|
||||||
void analyzeDXFContent(ifstream& file);
|
|
||||||
int detectBitDepth(const vector<uint8_t>& sample);
|
|
||||||
void loadImageData();
|
|
||||||
void unpackBits(const std::vector<uint8_t>& rawData);
|
|
||||||
void calculateDimensions(streamsize fileSize);
|
|
||||||
void validateImageProperties();
|
|
||||||
|
|
||||||
static uint16_t extractBits(const std::vector<uint8_t>& buffer, size_t bitPos, int bitDepth, uint16_t maxValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Example usage
|
|
||||||
int main() {
|
|
||||||
try {
|
|
||||||
DXF dxf("sample.dxf");
|
|
||||||
|
|
||||||
cout << "Image dimensions: " << dxf.getWidth() << "x" <<
|
|
||||||
dxf.getHeight() << endl;
|
|
||||||
cout << "Original bit depth: " << dxf.getBitDepth() << endl;
|
|
||||||
|
|
||||||
Mat bgr8bit = dxf.to8BitBGR();
|
|
||||||
Mat bgr10bit = dxf.to10BitBGR();
|
|
||||||
|
|
||||||
|
|
||||||
imwrite("output_8bit_bgr.png", bgr8bit);
|
|
||||||
imwrite("output_10bit_bgr.png", bgr10bit);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
catch (const exception& e) {
|
|
||||||
cerr << "Error: " << e.what() << endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}*/
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include <opencv2/highgui.hpp>
|
#include <opencv2/highgui.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "dxf.hpp"
|
#include "dpx.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace cv;
|
using namespace cv;
|
||||||
|
|
|
@ -0,0 +1,226 @@
|
||||||
|
#include "dpx.hpp"
|
||||||
|
|
||||||
|
DPX::DPX() {}
|
||||||
|
|
||||||
|
uint32_t DPX::swapEndian(uint32_t value) {
|
||||||
|
return ((value & 0xFF000000) >> 24) |
|
||||||
|
((value & 0x00FF0000) >> 8) |
|
||||||
|
((value & 0x0000FF00) << 8) |
|
||||||
|
((value & 0x000000FF) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t DPX::swapEndian(uint16_t value) {
|
||||||
|
return ((value & 0xFF00) >> 8) |
|
||||||
|
((value & 0x00FF) << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DPX::readHeader(ifstream& file) {
|
||||||
|
// Read magic number
|
||||||
|
file.read(reinterpret_cast<char*>(&header.magic), sizeof(header.magic));
|
||||||
|
|
||||||
|
// Check for both possible magic numbers (big and little endian)
|
||||||
|
const uint32_t MAGIC_BE = 0x53445058; // "SDPX" in big endian
|
||||||
|
const uint32_t MAGIC_LE = 0x58504453; // "XPDS" in little endian
|
||||||
|
|
||||||
|
cout << "{ \"dpx_magic_number\" : \"" << hex << header.magic << "\" }" << endl;
|
||||||
|
|
||||||
|
if (header.magic == MAGIC_BE) {
|
||||||
|
header.isBigEndian = true;
|
||||||
|
} else if (header.magic == MAGIC_LE) {
|
||||||
|
header.isBigEndian = false;
|
||||||
|
} else {
|
||||||
|
uint32_t swapped_magic = swapEndian(header.magic);
|
||||||
|
cout << "{ \"dpx_swapped_magic_number\" : \"0x" << hex << swapped_magic << "\" }" << endl;
|
||||||
|
|
||||||
|
if (swapped_magic == MAGIC_BE) {
|
||||||
|
header.isBigEndian = true;
|
||||||
|
header.magic = swapped_magic;
|
||||||
|
} else if (swapped_magic == MAGIC_LE) {
|
||||||
|
header.isBigEndian = false;
|
||||||
|
header.magic = swapped_magic;
|
||||||
|
} else {
|
||||||
|
throw runtime_error("Not a valid DPX file - Invalid magic number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read image data offset
|
||||||
|
file.seekg(4);
|
||||||
|
file.read(reinterpret_cast<char*>(&header.imageOffset), sizeof(header.imageOffset));
|
||||||
|
if (header.isBigEndian) {
|
||||||
|
header.imageOffset = swapEndian(header.imageOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek to image information offset (768 bytes from start)
|
||||||
|
file.seekg(768);
|
||||||
|
file.read(reinterpret_cast<char*>(&header.width), sizeof(header.width));
|
||||||
|
file.read(reinterpret_cast<char*>(&header.height), sizeof(header.height));
|
||||||
|
|
||||||
|
if (header.isBigEndian) {
|
||||||
|
header.width = swapEndian(header.width);
|
||||||
|
header.height = swapEndian(header.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "{ \"dimensions\" : { \"width\" : " << header.width << ", \"height\" :" << header.height << " }, ";
|
||||||
|
|
||||||
|
// Read image element information (1556 bytes from start)
|
||||||
|
file.seekg(1556);
|
||||||
|
file.read(reinterpret_cast<char*>(&header.descriptor), sizeof(header.descriptor));
|
||||||
|
file.read(reinterpret_cast<char*>(&header.bitDepth), sizeof(header.bitDepth));
|
||||||
|
file.read(reinterpret_cast<char*>(&header.imageElements), sizeof(header.imageElements));
|
||||||
|
|
||||||
|
cout << " \"bit_depth\" : " << static_cast<int>(header.bitDepth) << ", ";
|
||||||
|
cout << " \"offset\": " << header.imageOffset << " }" << endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DPX::readImageData(ifstream& file) {
|
||||||
|
file.seekg(header.imageOffset);
|
||||||
|
|
||||||
|
image = Mat(header.height, header.width, CV_16UC3);
|
||||||
|
|
||||||
|
if (header.bitDepth == 10) {
|
||||||
|
size_t packedSize = ((header.width * header.height * 3 * 10 + 31) / 32) * 4;
|
||||||
|
vector<uint8_t> buffer(packedSize);
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(buffer.data()), packedSize);
|
||||||
|
|
||||||
|
uint16_t* imgPtr = reinterpret_cast<uint16_t*>(image.data);
|
||||||
|
size_t pixelCount = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < packedSize - 3; i += 4) {
|
||||||
|
// Extract four bytes
|
||||||
|
uint32_t b0 = buffer[i];
|
||||||
|
uint32_t b1 = buffer[i + 1];
|
||||||
|
uint32_t b2 = buffer[i + 2];
|
||||||
|
uint32_t b3 = buffer[i + 3];
|
||||||
|
|
||||||
|
// Combine bytes according to endianness
|
||||||
|
uint32_t packed;
|
||||||
|
if (header.isBigEndian) {
|
||||||
|
packed = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
|
||||||
|
} else {
|
||||||
|
packed = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract three 10-bit values
|
||||||
|
uint16_t pix1 = (packed >> 22) & 0x3FF;
|
||||||
|
uint16_t pix2 = (packed >> 12) & 0x3FF;
|
||||||
|
uint16_t pix3 = (packed >> 2) & 0x3FF;
|
||||||
|
|
||||||
|
// Scale to 16-bit
|
||||||
|
pix1 <<= 6;
|
||||||
|
pix2 <<= 6;
|
||||||
|
pix3 <<= 6;
|
||||||
|
|
||||||
|
if (pixelCount < header.width * header.height * 3) {
|
||||||
|
size_t row = (pixelCount / 3) / header.width;
|
||||||
|
size_t col = (pixelCount / 3) % header.width;
|
||||||
|
size_t channel = pixelCount % 3;
|
||||||
|
|
||||||
|
size_t idx = row * header.width * 3 + col * 3 + (2 - channel);
|
||||||
|
imgPtr[idx] = pix1;
|
||||||
|
|
||||||
|
if (pixelCount + 1 < header.width * header.height * 3) {
|
||||||
|
channel = (pixelCount + 1) % 3;
|
||||||
|
idx = ((pixelCount + 1) / 3) / header.width * header.width * 3 +
|
||||||
|
((pixelCount + 1) / 3) % header.width * 3 + (2 - channel);
|
||||||
|
imgPtr[idx] = pix2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixelCount + 2 < header.width * header.height * 3) {
|
||||||
|
channel = (pixelCount + 2) % 3;
|
||||||
|
idx = ((pixelCount + 2) / 3) / header.width * header.width * 3 +
|
||||||
|
((pixelCount + 2) / 3) % header.width * 3 + (2 - channel);
|
||||||
|
imgPtr[idx] = pix3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pixelCount += 3;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle other bit depths (8, 12, 16)
|
||||||
|
size_t bytesPerPixel = (header.bitDepth + 7) / 8;
|
||||||
|
vector<uint8_t> buffer(header.width * header.height * 3 * bytesPerPixel);
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char*>(buffer.data()), buffer.size());
|
||||||
|
|
||||||
|
uint16_t* imgPtr = reinterpret_cast<uint16_t*>(image.data);
|
||||||
|
|
||||||
|
for (int y = 0; y < header.height; y++) {
|
||||||
|
for (int x = 0; x < header.width; x++) {
|
||||||
|
for (int c = 0; c < 3; c++) {
|
||||||
|
size_t idx = (y * header.width * 3 + x * 3 + c) * bytesPerPixel;
|
||||||
|
uint16_t pixel = 0;
|
||||||
|
|
||||||
|
switch (header.bitDepth) {
|
||||||
|
case 8:
|
||||||
|
pixel = buffer[idx] << 8;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
if (header.isBigEndian) {
|
||||||
|
pixel = ((uint16_t)buffer[idx] << 8) | buffer[idx + 1];
|
||||||
|
} else {
|
||||||
|
pixel = ((uint16_t)buffer[idx + 1] << 8) | buffer[idx];
|
||||||
|
}
|
||||||
|
pixel = pixel << 4;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
if (header.isBigEndian) {
|
||||||
|
pixel = ((uint16_t)buffer[idx] << 8) | buffer[idx + 1];
|
||||||
|
} else {
|
||||||
|
pixel = ((uint16_t)buffer[idx + 1] << 8) | buffer[idx];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
imgPtr[y * header.width * 3 + x * 3 + (2 - c)] = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DPX::read(const string& filename) {
|
||||||
|
ifstream file(filename, ios::binary);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
throw runtime_error("Could not open file: " + filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!readHeader(file)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
readImageData(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat DPX::getMat() const {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat DPX::getMatBitDepth(int targetBitDepth) const {
|
||||||
|
if (targetBitDepth != 8 && targetBitDepth != 10) {
|
||||||
|
throw invalid_argument("Target bit depth must be 8 or 10");
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat result;
|
||||||
|
if (targetBitDepth == 8) {
|
||||||
|
image.convertTo(result, CV_8UC3, 1.0/256.0);
|
||||||
|
} else if (targetBitDepth == 10) {
|
||||||
|
image.convertTo(result, CV_16UC3, 1.0/64.0);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DPX::getWidth() const {
|
||||||
|
return header.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DPX::getHeight() const {
|
||||||
|
return header.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DPX::getBitDepth() const {
|
||||||
|
return header.bitDepth;
|
||||||
|
}
|
186
src/dxf.cpp
186
src/dxf.cpp
|
@ -1,186 +0,0 @@
|
||||||
#include "dxf.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
Mat DXF::to8bitBGR() const {
|
|
||||||
if (_imageData.empty()) {
|
|
||||||
throw runtime_error("No image data loaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat output(_height, _width, CV_8UC3);
|
|
||||||
|
|
||||||
double scale = 255.0 / ((1 << _bitDepth) - 1);
|
|
||||||
|
|
||||||
for (int y = 0; y < _height; ++y) {
|
|
||||||
const uint16_t* srcRow = _imageData.ptr<uint16_t>(y);
|
|
||||||
uint8_t* dstRow = output.ptr<uint8_t>(y);
|
|
||||||
|
|
||||||
for (int x = 0; x < _width; ++x) {
|
|
||||||
uint8_t value = static_cast<uint8_t>(srcRow[x] * scale + 0.5);
|
|
||||||
dstRow[x * 3] = value; // B
|
|
||||||
dstRow[x * 3 + 1] = value; // G
|
|
||||||
dstRow[x * 3 + 2] = value; // R
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat DXF::to10bitBGR() const {
|
|
||||||
if (_imageData.empty()) {
|
|
||||||
throw runtime_error("No image data loaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat output(_height, _width, CV_16UC3);
|
|
||||||
|
|
||||||
double scale = 1023.0 / ((1 << _bitDepth) - 1);
|
|
||||||
|
|
||||||
for (int y = 0; y < _height; ++y) {
|
|
||||||
const uint16_t* srcRow = _imageData.ptr<uint16_t>(y);
|
|
||||||
uint16_t* dstRow = output.ptr<uint16_t>(y);
|
|
||||||
|
|
||||||
for (int x = 0; x < _width; ++x) {
|
|
||||||
uint16_t value = static_cast<uint16_t>(srcRow[x] * scale + 0.5);
|
|
||||||
value = min(value, static_cast<uint16_t>(1023));
|
|
||||||
|
|
||||||
uint16_t shiftedValue = value << 6;
|
|
||||||
|
|
||||||
dstRow[x * 3] = shiftedValue; // B
|
|
||||||
dstRow[x * 3 + 1] = shiftedValue; // G
|
|
||||||
dstRow[x * 3 + 2] = shiftedValue; // R
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DXF::analyzeFile() {
|
|
||||||
ifstream file(_filepath, ios::binary);
|
|
||||||
if (!file.is_open()) {
|
|
||||||
throw runtime_error("Could not open file: " + _filepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!readDXFHeader(file)) {
|
|
||||||
analyzeDXFContent(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
validateImageProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DXF::readDXFHeader(ifstream& file) {
|
|
||||||
struct DXFHeader {
|
|
||||||
uint32_t magic;
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
uint8_t bitDepth;
|
|
||||||
uint8_t version;
|
|
||||||
uint16_t flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
DXFHeader header;
|
|
||||||
file.read(reinterpret_cast<char*>(&header), sizeof(header));
|
|
||||||
|
|
||||||
if (file.gcount() != sizeof(header)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (header.magic != 0x44584631) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_width = header.width;
|
|
||||||
_height = header.height;
|
|
||||||
_bitDepth = header.bitDepth;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DXF::analyzeDXFContent(ifstream& file) {
|
|
||||||
file.seekg(0, ios::end);
|
|
||||||
streamsize fileSize = file.tellg();
|
|
||||||
file.seekg(0, ios::beg);
|
|
||||||
|
|
||||||
vector<uint8_t> sample(min(static_cast<streamsize>(1024), fileSize));
|
|
||||||
file.read(reinterpret_cast<char*>(sample.data()), sample.size());
|
|
||||||
|
|
||||||
_bitDepth = detectBitDepth(sample);
|
|
||||||
|
|
||||||
calculateDimensions(fileSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DXF::detectBitDepth(const vector<uint8_t>& sample) {
|
|
||||||
uint16_t maxValue = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sample.size() - 1; i += 2) {
|
|
||||||
uint16_t value = (static_cast<uint16_t>(sample[i + 1]) << 8) | sample[i];
|
|
||||||
maxValue = max(maxValue, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
int bitDepth = 16;
|
|
||||||
while (bitDepth > 8 && maxValue < (1 << (bitDepth - 1))) {
|
|
||||||
bitDepth--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bitDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DXF::loadImageData() {
|
|
||||||
ifstream file(_filepath, ios::binary);
|
|
||||||
if (!file.is_open()) {
|
|
||||||
throw runtime_error("Could not open file: " + _filepath);
|
|
||||||
}
|
|
||||||
if (hasDXFHeader()) {
|
|
||||||
file.seekg(sizeof(struct DXFHeader));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t dataSize = static_cast<size_t>(ceil(_width * _height * _bitDepth / 8.0));
|
|
||||||
vector<uint8_t> rawData(dataSize);
|
|
||||||
|
|
||||||
file.read(reinterpret_cast<char*>(rawData.data()), dataSize);
|
|
||||||
|
|
||||||
_imageData = Mat(_height, _width, CV_16UC1);
|
|
||||||
|
|
||||||
unpackBits(rawData);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DXF::unpackBits(const vector<uint8_t>& rawData) {
|
|
||||||
size_t bitPos = 0;
|
|
||||||
const uint16_t maxValue = (1 << _bitDepth) - 1;
|
|
||||||
|
|
||||||
for (int y = 0; y < _height; ++y) {
|
|
||||||
uint16_t* row = _imageData.ptr<uint16_t>(y);
|
|
||||||
for (int x = 0; x < _width; ++x) {
|
|
||||||
row[x] = extractBits(rawData, bitPos, _bitDepth, maxValue);
|
|
||||||
bitPos += _bitDepth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t DXF::extractBits(const vector<uint8_t>& buffer, size_t bitPos, int bitDepth, uint16_t maxValue) {
|
|
||||||
size_t bytePos = bitPos / 8;
|
|
||||||
size_t bitOffset = bitPos % 8;
|
|
||||||
|
|
||||||
uint32_t temp = 0;
|
|
||||||
for (int i = 0; i < 3 && bytePos + i < buffer.size(); ++i) {
|
|
||||||
temp |= static_cast<uint32_t>(buffer[bytePos + i]) << (16 - (i * 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
temp >>= (24 - (bitOffset + bitDepth));
|
|
||||||
return static_cast<uint16_t>(temp & maxValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DXF::calculateDimensions(streamsize fileSize) {
|
|
||||||
int pixelCount = (fileSize * 8) / _bitDepth;
|
|
||||||
_width = static_cast<int>(sqrt(pixelCount));
|
|
||||||
_height = _width;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DXF::validateImageProperties() {
|
|
||||||
if (_width <= 0 || _height <= 0 ||
|
|
||||||
_width > 65536 || _height > 65536) {
|
|
||||||
throw runtime_error("Invalid image dimensions");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_bitDepth < 8 || _bitDepth > 16) {
|
|
||||||
throw runtime_error("Unsupported bit depth: " + to_string(_bitDepth));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,9 +13,13 @@ Mat Image::getBlank () {
|
||||||
|
|
||||||
Mat Image::loadImage (string& image_path, uint64_t& x, uint64_t& y, uint64_t& w, uint64_t& h) {
|
Mat Image::loadImage (string& image_path, uint64_t& x, uint64_t& y, uint64_t& w, uint64_t& h) {
|
||||||
string located_path = samples::findFile(image_path);
|
string located_path = samples::findFile(image_path);
|
||||||
if (getExtLower(located_path) == ".dxf") {
|
string ext = getExtLower(located_path);
|
||||||
DXF dxf(located_path);
|
//cout << "{ \"image_extension\" : \"" << ext << "\" }" << endl;
|
||||||
loaded = dxf.to8bitBGR();
|
if (ext == "dpx") {
|
||||||
|
DPX dpx;
|
||||||
|
dpx.read(located_path);
|
||||||
|
loaded = dpx.getMatBitDepth(8);
|
||||||
|
cout << "{ \"dpx\" : \"" << image_path << "\" }" << endl;
|
||||||
} else {
|
} else {
|
||||||
loaded = imread(located_path, IMREAD_COLOR);
|
loaded = imread(located_path, IMREAD_COLOR);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue