Hi,
I am trying to read PNG image data into a WebP file with Lossless compression and also read the image data back from the stored WebP file.
I am able to read write the file but it seems that it is lossy rather than lossless.
Below is the code for the same.
I have used WebPEncodeLosslessRGBA to encode the image data and WebPDecode for decoding it back.
The for loop below it is to compare the decoded data with the input data from cv::Mat img.
PS:
Config and Pic is for WebPEncode() which did not work well for me either.
void ReadWrite(cv::Mat img, std::string fileName)
{
// Setup a config, starting form a preset and tuning some additional
// parameters
WebPConfig config;
if (!WebPConfigInit(&config))
{
return; // version error
}
// Setup the input data
WebPPicture pic;
if (!WebPPictureInit(&pic)) {
return; // version error
}
// Set up a byte-output write method. WebPMemoryWriter, for instance.
WebPMemoryWriter wrt;
WebPMemoryWriterInit(&wrt); // initialize 'wrt'
pic.user_data = (void*)&fileName;
pic.writer = WebPWriterFunction1;
pic.custom_ptr = (&wrt);
pic.width = (int)img.cols;
pic.height = (int)img.rows;
//pic.argb_stride = (int)img.cols;
//pic.use_argb = 1;
config.lossless = 1;
config.quality = 100;
WebPConfigLosslessPreset(&config, 0);
auto config_error = WebPValidateConfig(&config); // not mandatory, but useful*/
// allocated picture of dimension width x height
if (!WebPPictureAlloc(&pic)) {
return; // memory error
}
// at this point, 'pic' has been initialized as a container,
// and can receive the Y/U/V samples.
// Alternatively, one could use ready-made import functions like
// WebPPictureImportRGB(), which will take care of memory allocation.
// In any case, past this point, one will have to call
// WebPPictureFree(&pic) to reclaim memory.
pic.y = img.data;
//pic.argb = (uint32_t *)img.data;
// Compress!
uchar * output = nullptr;
auto size = WebPEncodeLosslessRGBA(img.data, img.cols, img.rows, img.cols, &output); // pic.y);
FILE *file = fopen(fileName.c_str(), "ab");
if (!file) {
std::cout << "Could not open JPEG file: " << strerror(errno);
}
if (fwrite(output, size, 1, file) < 1) {
cerr << "Could not write JPEG file: " << strerror(errno);
}
fclose(file);
//auto size = WebPEncode(&config, &pic);
unsigned char* jpegBuf = nullptr;
jpegBuf = new unsigned char[jpegSize];
int WebPGetInfo(output, size, width, height);
jpegBuf = output;
WebPDecoderConfig config1;
WebPInitDecoderConfig(&config1);
WebPGetFeatures(jpegBuf, size, &config1.input);
config1.output.colorspace = MODE_RGBA;
config1.options.bypass_filtering = 1;
config1.input.has_alpha = 1;
config1.output.u.RGBA.size = size;
config1.output.u.RGBA.stride = img.cols;
config1.options.use_threads = 1;
WebPDecode(jpegBuf, size, &config1);
for (int n = 0; n < img.rows*img.cols; ++n)
{
if (img.data[n] != config1.output.u.RGBA.rgba[n])
{
std::cout << "Failed\n";
}
}
WebPPictureFree(&pic); // must be called independently of the 'ok' result.
// output data should have been handled by the writer at that point.
// -> compressed data is the memory buffer described by wrt.mem / wrt.size
// deallocate the memory used by compressed data
WebPMemoryWriterClear(&wrt);
}