Add rgbx, xrgb, bgr, etc. formats (#234)

pull/235/head
Martin Dørum 2019-05-24 03:03:48 +02:00 committed by Michael Stapelberg
parent 0be11444bc
commit aa7984f215
2 changed files with 51 additions and 18 deletions

View File

@ -79,8 +79,8 @@ Display the given PNG image instead of a blank screen.
.TP
.BI \fB\-\-raw= format
Read the image given by \-\-image as a raw image instead of PNG. The argument is the image's format
as <width>x<height>:<pixfmt>. The supported pixel formats are 'native' and 'rgb'.
The "rgb" pixel format expects a pixel to be three bytes; red, green, and blue.
as <width>x<height>:<pixfmt>. The supported pixel formats are:
\'native', 'rgb', 'xrgb', 'rgbx', 'bgr', 'xbgr', and 'bgrx'.
The "native" pixel format expects a pixel as a 32-bit (4-byte) integer in
the machine's native endianness, with the upper 8 bits unused. Red, green and blue are stored in
the remaining bits, in that order.

View File

@ -657,24 +657,32 @@ static ssize_t read_raw_image_native(uint32_t *dest, FILE *src, size_t width, si
return count;
}
static ssize_t read_raw_image_rgb(uint32_t *dest, FILE *src, size_t width, size_t height, int pixstride) {
unsigned char *buf = malloc(width * 3);
struct raw_pixel_format {
int bpp;
int red;
int green;
int blue;
};
static ssize_t read_raw_image_fmt(uint32_t *dest, FILE *src, size_t width, size_t height, int pixstride,
struct raw_pixel_format fmt) {
unsigned char *buf = malloc(width * fmt.bpp);
if (buf == NULL)
return -1;
ssize_t count = 0;
for (size_t y = 0; y < height; y++) {
size_t n = fread(buf, 1, width * 3, src);
size_t n = fread(buf, 1, width * fmt.bpp, src);
count += n;
if (n < (size_t)(width * 3))
if (n < (size_t)(width * fmt.bpp))
break;
for (size_t x = 0; x < width; ++x) {
int idx = x * 3;
int idx = x * fmt.bpp;
dest[y * pixstride + x] = 0 |
(buf[idx + 0] << 16) |
(buf[idx + 1] << 8) |
(buf[idx + 2]);
(buf[idx + fmt.red]) << 16 |
(buf[idx + fmt.green]) << 8 |
(buf[idx + fmt.blue]);
}
}
@ -682,6 +690,14 @@ static ssize_t read_raw_image_rgb(uint32_t *dest, FILE *src, size_t width, size_
return count;
}
// Pre-defind pixel formats (<bytes per pixel>, <red pixel>, <green pixel>, <blue pixel>)
static const struct raw_pixel_format raw_fmt_rgb = {3, 0, 1, 2};
static const struct raw_pixel_format raw_fmt_rgbx = {4, 0, 1, 2};
static const struct raw_pixel_format raw_fmt_xrgb = {4, 1, 2, 3};
static const struct raw_pixel_format raw_fmt_bgr = {3, 2, 1, 0};
static const struct raw_pixel_format raw_fmt_bgrx = {4, 2, 1, 0};
static const struct raw_pixel_format raw_fmt_xbgr = {4, 3, 2, 1};
static cairo_surface_t *read_raw_image(const char *image_path, const char *image_raw_format) {
cairo_surface_t *img;
@ -727,16 +743,33 @@ static cairo_surface_t *read_raw_image(const char *image_path, const char *image
/* If the pixfmt is 'native', just read each line directly into the buffer */
size = w * h * 4;
count = read_raw_image_native(data, f, w, h, pixstride);
} else if (strcmp(pixfmt, "rgb") == 0) {
/* If the pixfmt is 'rgb', we have to convert it to the native pixfmt */
size = w * h * 3;
count = read_raw_image_rgb(data, f, w, h, pixstride);
} else {
fprintf(stderr, "Unknown raw pixel pixfmt: %s\n", pixfmt);
fclose(f);
cairo_surface_destroy(img);
return NULL;
const struct raw_pixel_format *fmt = NULL;
if (strcmp(pixfmt, "rgb") == 0)
fmt = &raw_fmt_rgb;
else if (strcmp(pixfmt, "rgbx") == 0)
fmt = &raw_fmt_rgbx;
else if (strcmp(pixfmt, "xrgb") == 0)
fmt = &raw_fmt_xrgb;
else if (strcmp(pixfmt, "bgr") == 0)
fmt = &raw_fmt_bgr;
else if (strcmp(pixfmt, "bgrx") == 0)
fmt = &raw_fmt_bgrx;
else if (strcmp(pixfmt, "xbgr") == 0)
fmt = &raw_fmt_xbgr;
if (fmt == NULL) {
fprintf(stderr, "Unknown raw pixel format: %s\n", pixfmt);
fclose(f);
cairo_surface_destroy(img);
return NULL;
}
size = w * h * fmt->bpp;
count = read_raw_image_fmt(data, f, w, h, pixstride, *fmt);
}
cairo_surface_mark_dirty(img);
if (count < size) {