Hi, just a quick thing that may be useful if you’re trying to save memory while using libwebp to encode a monochrome image.
We assume that you already have the monochrome data, and you just want to encode it. Your data size is width*height*1, and is 100% equivalent to the Y channel in YUV.
Allocating a bunch of memory (width*height/2) for the UV part would be silly, but looks like it’s required, right?
Well, we can actually get away with just width/2, by doing this:
picture.y = y_data; // straightforward
picture.y_stride = width; // straightforward
picture.u = dummy_uv_data; // array of length width/2 full of 0x80 bytes
picture.v = dummy_uv_data; // it's the same array!
picture.uv_stride = 0; // stride is 0! this means we'll always read UV from the same location for every single pixel row
BTW, you can generate your y_data with the following ImageMagick command:
convert test.jpg y:test.y
Below is the full code demonstrating the use of this trick. Note that the code is about 90% generated by ChatGPT, and I haven’t cleaned it up beyond the minimum necessary to get it to work. Don’t forget to adjust the width and height variables to match your input image.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <webp/encode.h>
int main() {
int width = 3024;
int height = 4032;
int stride = width;
uint8_t *y_data = malloc(width*height);
uint8_t *dummy_uv_data = malloc(width/2);
memset(dummy_uv_data, 0x80, width/2);
FILE *infile = fopen("test.y", "r");
if (!infile) {
fprintf(stderr, "Error opening output file.\n");
return 1;
}
fread(y_data, width*height, 1, infile);
fclose(infile);
FILE* outfile = fopen("output.webp", "wb");
if (!outfile) {
fprintf(stderr, "Error opening output file.\n");
return 1;
}
WebPConfig config;
WebPPicture picture;
WebPMemoryWriter writer;
WebPConfigInit(&config);
config.lossless = 0; // Set to 1 for lossless encoding
config.quality = 75; // Set the desired quality value (0-100)
WebPMemoryWriterInit(&writer);
if (!WebPPictureInit(&picture)) {
fprintf(stderr, "Error initializing WebP structures.\n");
return 1;
}
picture.width = width;
picture.height = height;
picture.use_argb = 0;
picture.y = y_data;
picture.u = dummy_uv_data;
picture.v = dummy_uv_data;
picture.y_stride = width;
picture.uv_stride = 0;
picture.writer = WebPMemoryWrite;
picture.custom_ptr = &writer;
if (!WebPEncode(&config, &picture)) {
fprintf(stderr, "Error encoding WebP.\n");
return 1;
}
fwrite(writer.mem, 1, writer.size, outfile);
free(y_data);
WebPMemoryWriterClear(&writer);
WebPPictureFree(&picture);
fclose(outfile);
return 0;
}
Compile with: cc -o encode_webp encode_webp.c -lwebp
Execute with: ./encode_webp