~ruther/CTU-FEE-B0B35APO-Semestral-project

8da5a0f2c5bb9adcb48ce2aa7baaf1a552b19dd4 — František Boháček 4 years ago a7c219c
feat: add jpeg and png load
1 files changed, 133 insertions(+), 2 deletions(-)

M image-viewer/src/image_loader.c
M image-viewer/src/image_loader.c => image-viewer/src/image_loader.c +133 -2
@@ 3,7 3,9 @@

#include <asm-generic/errno-base.h>
#include <errno.h>
#include <jpeglib.h>
#include <magic.h>
#include <png.h>
#include <stdio.h>
#include <stdlib.h>



@@ 79,11 81,140 @@ image_error_t image_loader_load_ppm(image_t *image) {


image_error_t image_loader_load_jpeg(image_t *image) {
  return IMERR_WRONG_FORMAT;
  struct jpeg_decompress_struct cinfo;
  struct jpeg_error_mgr jerr;

  JSAMPROW row_pointer[1];

  FILE *infile = fopen(image->path, "r");
  if (infile == NULL) {
    return image_error_from_errno();
  }

  cinfo.err = jpeg_std_error(&jerr);

  jpeg_create_decompress(&cinfo);
  jpeg_stdio_src(&cinfo, infile);
  jpeg_read_header(&cinfo, TRUE);
  // handle errors

  image->width = cinfo.image_width;
  image->height = cinfo.image_height;

  int image_size = cinfo.image_width * cinfo.image_height * 2;
  unsigned char *out = malloc(image_size);
  if (out == NULL) {
    return IMERR_UNKNOWN;
    fclose(infile);
  }

  cinfo.out_color_space = JCS_RGB565;
  jpeg_start_decompress(&cinfo);

  while (cinfo.output_scanline < cinfo.output_height) {
    row_pointer[0] = &out[cinfo.output_scanline * cinfo.image_width * 2];
    jpeg_read_scanlines(&cinfo, row_pointer, 1);
  }

  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);
  fclose(infile);
  
  image->pixels = (display_pixel_t*)out;
  return IMERR_SUCCESS;
}

image_error_t image_loader_load_png(image_t *image) {
  return IMERR_WRONG_FORMAT;
  FILE *infile = fopen(image->path, "r");
  if (infile == NULL) {
    return image_error_from_errno();
  }

  png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png == NULL) {
    return IMERR_UNKNOWN;
  }

  png_infop info = png_create_info_struct(png);
  if (info == NULL) {
    return IMERR_WRONG_FORMAT;
  }

  png_init_io(png, infile);
  png_read_info(png, info);

  image->width = png_get_image_width(png, info);
  image->height = png_get_image_height(png, info);
  png_byte color_type = png_get_color_type(png, info);
  png_byte bit_depth = png_get_bit_depth(png, info);

  if (bit_depth == 16) {
    png_set_strip_16(png);
  }

  if (color_type == PNG_COLOR_TYPE_PALETTE) {
    png_set_palette_to_rgb(png);
  }

  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
    png_set_expand_gray_1_2_4_to_8(png);
  }

  if (png_get_valid(png, info, PNG_INFO_tRNS))
    png_set_tRNS_to_alpha(png);

  if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_PALETTE) {
    png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
  }

  if (color_type == PNG_COLOR_TYPE_GRAY ||
      color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
    png_set_gray_to_rgb(png);
  }

  png_read_update_info(png, info);

  png_bytep *row_pointers = malloc(sizeof(png_bytep) * image->height);
  if (row_pointers == NULL) {
    png_destroy_read_struct(&png, &info, NULL);
    fclose(infile);
    return IMERR_UNKNOWN;
  }

  for (int i = 0; i < image->height; i++) {
    row_pointers[i] = malloc(png_get_rowbytes(png, info));
  }

  png_read_image(png, row_pointers);

  fclose(infile);
  png_destroy_read_struct(&png, &info, NULL);

  display_pixel_t *pixels = malloc(sizeof(display_pixel_t) * image->width * image->height);
  if (pixels == NULL) {
    png_destroy_read_struct(&png, &info, NULL);
    free(row_pointers);
    fclose(infile);
    return IMERR_UNKNOWN;
  }

  for (int y = 0; y < image->height; y++) {
    png_bytep row = row_pointers[y];
    for (int x = 0; x < image->width; x++) {
      png_bytep px = &(row[x * 4]);
      int alpha = px[3];

      int coef = 255 * 255;
      pixels[y * image->width + x].fields.r = ((double)px[0] * alpha / coef) * DISPLAY_MAX_RED;
      pixels[y * image->width + x].fields.g = ((double)px[1] * alpha / coef) * DISPLAY_MAX_GREEN;
      pixels[y * image->width + x].fields.b = ((double)px[2] * alpha / coef) * DISPLAY_MAX_BLUE;
    }
  }

  image->pixels = pixels;

  return IMERR_SUCCESS;
}

image_error_t image_deduce_type(image_t *image) {