I have a problem with my code in implementing the JPEG compression using OpenCV and C++. On the encoder and after the code does the DCT when I add a line of code, which converts the planes from 32-bit floating-point to 8-bit unsigned, I get some weird output as you can see below. After this conversion, besides the fact that the result is not acceptable (cause I didn't even write the quantization part yet) even the original image is affected by this line of code. When changing this conversion to 16-bit unsigned, the original image is untouched and the decoded image becomes better, but the result is still not acceptable.
constexpr int blocksize = 8;
struct block {
cv::Rect roi;
cv::Mat subimage;
};
int main()
{
//Reading the image and storing its necessary information
std::string addr("C:\\Users\\lena.jpg");
const cv::Mat img = cv::imread(addr, cv::IMREAD_COLOR);
if (img.empty()) {
std::cerr << "Could not open the image!" << std::endl;
return -1;
}
int height = img.size().height;
int width = img.size().width;
std::cout << "width * height: " << width << " * " << height << std::endl;
//Constructing 8 by 8 blocks
std::vector<block> blocks;
for (int y = 0; y < height; y += blocksize){
for (int x = 0; x < width; x += blocksize){
int block_width = std::min(blocksize, width - x);
int block_height = std::min(blocksize, height - y);
block temp;
cv::Rect newROI(x, y, block_width, block_height);
temp.roi = newROI;
temp.subimage = img(newROI);
blocks.push_back(temp);
}
}
//Discrete Cosine Transformation and Quantization
for (int bIdx = 0; bIdx < blocks.size(); ++bIdx) {
std::vector<cv::Mat> planes;
cv::split(blocks[bIdx].subimage, planes);
std::vector<cv::Mat> resultPlanes(planes.size());
for (int k = 0; k < planes.size(); ++k) {
planes[k].convertTo(planes[k], CV_32FC1);
cv::dct(planes[k], resultPlanes[k]);
//The line that I mentioned above
resultPlanes[k].convertTo(resultPlanes[k], CV_8UC1);
}
cv::merge(resultPlanes, blocks[bIdx].subimage);
}
//Inverse of DCT and Quantization
for (int bIdx = 0; bIdx < blocks.size(); ++bIdx) {
std::vector<cv::Mat> planes;
cv::split(blocks[bIdx].subimage, planes);
std::vector<cv::Mat> resultPlanes(planes.size());
for (int k = 0; k < planes.size(); ++k) {
planes[k].convertTo(planes[k], CV_32FC1);
cv::idct(planes[k], resultPlanes[k]);
resultPlanes[k].convertTo(resultPlanes[k], CV_8UC1);
}
cv::merge(resultPlanes, blocks[bIdx].subimage);
}
//Reconstructing the whole image
cv::Mat modifiedImg = img.clone();
for (int bIdx = 0; bIdx < blocks.size(); ++bIdx) {
blocks[bIdx].subimage.copyTo(modifiedImg(blocks[bIdx].roi));
}
//Show the result
cv::imshow("JPEG", img);
cv::imshow("My JPEG", modifiedImg);
cv::waitKey(0);
}


