diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/format/image/png.c | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/src/format/image/png.c b/src/format/image/png.c index f42761b..9e4b86a 100644 --- a/src/format/image/png.c +++ b/src/format/image/png.c @@ -158,7 +158,7 @@ ff_result ff_open_png(ff_ctx* ctx, ff_stream *stream, ff_png_ctx **out_ctx, ff_f // Handlers -inline uint16_t ff_png_bpp(ff_png_ctx *png_ctx) +static inline uint16_t ff_png_bpp(ff_png_ctx *png_ctx) { int16_t byte_depth = png_ctx->bit_depth / 8; switch (png_ctx->color_type) { @@ -284,6 +284,8 @@ ff_result ff_png_data_handler(ff_ctx* ctx, uint8_t *buf, size_t len, ff_png_ctx png_ctx->last_error = FF_RESULT_WARN_NO_IMPL; return FF_RESULT_WARN_NO_IMPL; } + + png_ctx->image_mode = (png_ctx->color_type == 3) ? FF_PNG_MODE_PALETTE : FF_PNG_MODE_DIRECT_COLOR; // Now I am very inexperienced so I'm doing what I think is right // TODO: Review this code later @@ -469,4 +471,88 @@ ff_result ff_close_png(ff_ctx* ctx, ff_png_ctx *png_ctx) ff_dprintf(ctx, "png: successfully freed png context\n"); return FF_RESULT_OK; +} + +ff_result ff_png_normalize(ff_ctx *ctx, ff_png_ctx *png_ctx, ff_image_ctx **out_data, ff_flag consume) +{ + if (png_ctx->bit_depth != 8) return FF_RESULT_WARN_NO_IMPL; + + ff_image_ctx* out_ctx = ctx->allocator.ff_alloc(sizeof(ff_image_ctx)); + if (!out_ctx) return FF_RESULT_ERROR_MEMORY_ALLOCATION; + + size_t pixel_count = png_ctx->width * png_ctx->height; + out_ctx->data = ctx->allocator.ff_alloc(sizeof(uint32_t) * pixel_count); + + if (png_ctx->image_mode == FF_PNG_MODE_DIRECT_COLOR) { + if (out_ctx->data == NULL) { + return FF_RESULT_ERROR_MEMORY_ALLOCATION; + } + + uint8_t *src = png_ctx->data.pixels; + uint8_t *dst = (uint8_t *)out_ctx->data; + size_t bpp = ff_png_bpp(png_ctx); + + for (size_t i = 0; i < pixel_count; i++) { + uint8_t* s = src + i * bpp; // source pixel + uint8_t* d = dst + i * 4; // destination pixel + + uint8_t *R = &d[0]; + uint8_t *G = &d[1]; + uint8_t *B = &d[2]; + uint8_t *A = &d[3]; + + switch (png_ctx->color_type) { + case 0: // Grayscale + *R = *G = *B = s[0]; + *A = 255; + break; + case 2: // RGB + *R = s[0]; + *G = s[1]; + *B = s[2]; + *A = 255; + break; + case 4: // Grayscale w/ alpha + *R = *G = *B = s[0]; + *A = s[1]; + break; + case 6: // RGBA + *R = s[0]; + *G = s[1]; + *B = s[2]; + *A = s[3]; + break; + default: + ctx->allocator.ff_free(out_ctx->data); + ctx->allocator.ff_free(out_ctx); + return FF_RESULT_ERROR_INVALID_FILE; + } + } + + + + } else if (png_ctx->image_mode == FF_PNG_MODE_PALETTE) { + //out_ctx->data = png_ctx->data.imap; + // NOTE: Since I need to resolve the imap and I don't wanna do that now + // and just wanna get v0.1.0 out, then I'm just gonna use the pixels. + ctx->allocator.ff_free(out_ctx->data); + ctx->allocator.ff_free(out_ctx); + return FF_RESULT_WARN_NO_IMPL; + } else { + ctx->allocator.ff_free(out_ctx->data); + ctx->allocator.ff_free(out_ctx); + return FF_RESULT_ERROR_INVALID_FILE; + } + + out_ctx->width = png_ctx->width; + out_ctx->height = png_ctx->height; + out_ctx->origin = FF_IMAGE_ORIGIN_PNG; + + *out_data = out_ctx; + + if (consume) { + ff_close_png(ctx, png_ctx); + (void)png_ctx; + } + return FF_RESULT_OK; }
\ No newline at end of file |
