summaryrefslogtreecommitdiffstats
path: root/lisiblepng/src
diff options
context:
space:
mode:
authorClement Sibille <clements+git@lisible.xyz>2024-03-08 01:16:53 +0900
committerClement Sibille <clements+git@lisible.xyz>2024-03-08 01:16:53 +0900
commit943bcac90e5e3aaee0647b070e760c0985d03d0d (patch)
tree135bb1a1a20c7655f5ecfd94ea36c82750f61f7f /lisiblepng/src
parent665e6155ac8b055d89cead210300ab22a91f74ff (diff)
Add LisPng_write_RGBA8_data()
Diffstat (limited to 'lisiblepng/src')
-rw-r--r--lisiblepng/src/lisiblepng.c66
-rw-r--r--lisiblepng/src/lisiblepng.h9
2 files changed, 74 insertions, 1 deletions
diff --git a/lisiblepng/src/lisiblepng.c b/lisiblepng/src/lisiblepng.c
index bf1c27c..ffd2342 100644
--- a/lisiblepng/src/lisiblepng.c
+++ b/lisiblepng/src/lisiblepng.c
@@ -521,8 +521,72 @@ cleanup_data:
err:
return NULL;
}
-
#undef PARSE_FIELD
+
+void LisPng_write_RGBA8_data(const LisPng *png, uint8_t *output_data) {
+ ASSERT(png != NULL);
+ ASSERT(output_data != NULL);
+ static const int TARGET_BYTES_PER_PIXEL = 4;
+ size_t sample_count = LisPngColourType_sample_count(png->colour_type);
+ size_t bits_per_pixel = png->bits_per_sample * sample_count;
+ size_t bytes_per_pixel = bits_per_pixel / 8;
+ if (png->bits_per_sample < 8) {
+ bytes_per_pixel = 1;
+ }
+
+ for (size_t pixel_index = 0; pixel_index < png->width * png->height;
+ pixel_index++) {
+ size_t source_pixel_base = pixel_index * bytes_per_pixel;
+ size_t target_pixel_base = pixel_index * TARGET_BYTES_PER_PIXEL;
+
+ if (png->colour_type == LisPngColourType_Greyscale) {
+ if (bits_per_pixel == 16) {
+ uint16_t grey = (png->data[source_pixel_base] << 8) |
+ png->data[source_pixel_base + 1];
+ output_data[target_pixel_base] = grey / 2;
+ output_data[target_pixel_base + 1] = grey / 2;
+ output_data[target_pixel_base + 2] = grey / 2;
+ output_data[target_pixel_base + 3] = 0xFF;
+ } else {
+ size_t absolute_bit_offset = pixel_index * bits_per_pixel;
+ size_t byte_offset = absolute_bit_offset / 8;
+ size_t relative_bit_offset = absolute_bit_offset % 8;
+ uint8_t grey = (png->data[byte_offset] >>
+ (7 - relative_bit_offset - (bits_per_pixel - 1))) &
+ ((1 << bits_per_pixel) - 1);
+ output_data[target_pixel_base] = grey;
+ output_data[target_pixel_base + 1] = grey;
+ output_data[target_pixel_base + 2] = grey;
+ output_data[target_pixel_base + 3] = 0xFF;
+ }
+ } else if (png->colour_type == LisPngColourType_Truecolour) {
+ if (png->bits_per_sample == 16) {
+ uint16_t r = (png->data[source_pixel_base] << 8) |
+ png->data[source_pixel_base + 1];
+ uint16_t g = (png->data[source_pixel_base + 2] << 8) |
+ png->data[source_pixel_base + 3];
+ uint16_t b = (png->data[source_pixel_base + 4] << 8) |
+ png->data[source_pixel_base + 5];
+ output_data[target_pixel_base] = r / 2;
+ output_data[target_pixel_base + 1] = g / 2;
+ output_data[target_pixel_base + 2] = b / 2;
+ output_data[target_pixel_base + 3] = 0xFF;
+ } else {
+ uint8_t r = png->data[source_pixel_base];
+ uint8_t g = png->data[source_pixel_base + 1];
+ uint8_t b = png->data[source_pixel_base + 2];
+ output_data[target_pixel_base] = r;
+ output_data[target_pixel_base + 1] = g;
+ output_data[target_pixel_base + 2] = b;
+ output_data[target_pixel_base + 3] = 0xFF;
+ }
+ } else {
+ LPNG_LOG_ERR0("Unsupported colour type");
+ exit(1);
+ }
+ }
+}
+
void LisPng_destroy(LisPng *png) {
free(png->data);
free(png);
diff --git a/lisiblepng/src/lisiblepng.h b/lisiblepng/src/lisiblepng.h
index a23ac91..e7f94ec 100644
--- a/lisiblepng/src/lisiblepng.h
+++ b/lisiblepng/src/lisiblepng.h
@@ -24,6 +24,15 @@ typedef struct LisPng LisPng;
/// The returned PNG is owned by the caller and must be destroyed with
/// Png_destroy.
LisPng *LisPng_decode(FILE *stream);
+
+/// Writes the PNG image data as RGBA8 data to a buffer
+///
+/// Note: The output_data buffer must be allocated with enough memory
+/// (width*height*32)
+/// @param png The png
+/// @param output_data The output buffer
+void LisPng_write_RGBA8_data(const LisPng *png, uint8_t *output_data);
+
/// Outputs the provided Png struct as a PPM image to stdout
///
/// @param png The png
Go back to lisible.xyz