2019-09-07 18:44:48 +00:00
|
|
|
/*
|
|
|
|
* This is not a part of the library. It's only used in tests, examples and
|
|
|
|
* benchmarks.
|
|
|
|
*/
|
|
|
|
|
2019-08-29 21:47:02 +00:00
|
|
|
#include "neatvnc.h"
|
2019-08-25 19:10:35 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <png.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <assert.h>
|
2019-08-29 21:47:02 +00:00
|
|
|
#include <libdrm/drm_fourcc.h>
|
2019-08-25 19:10:35 +00:00
|
|
|
|
2019-10-20 22:13:51 +00:00
|
|
|
struct nvnc_fb* read_png_file(const char* filename)
|
|
|
|
{
|
2019-08-25 19:10:35 +00:00
|
|
|
int width, height;
|
|
|
|
png_byte color_type;
|
|
|
|
png_byte bit_depth;
|
2019-10-20 22:13:51 +00:00
|
|
|
png_bytep* row_pointers = NULL;
|
2019-08-25 19:10:35 +00:00
|
|
|
|
2019-10-20 22:13:51 +00:00
|
|
|
FILE* fp = fopen(filename, "rb");
|
2019-08-25 19:10:35 +00:00
|
|
|
|
2019-10-20 22:13:51 +00:00
|
|
|
png_structp png =
|
|
|
|
png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
|
|
if (!png)
|
|
|
|
abort();
|
2019-08-25 19:10:35 +00:00
|
|
|
|
|
|
|
png_infop info = png_create_info_struct(png);
|
2019-10-20 22:13:51 +00:00
|
|
|
if (!info)
|
|
|
|
abort();
|
2019-08-25 19:10:35 +00:00
|
|
|
|
2019-10-20 22:13:51 +00:00
|
|
|
if (setjmp(png_jmpbuf(png)))
|
|
|
|
abort();
|
2019-08-25 19:10:35 +00:00
|
|
|
|
|
|
|
png_init_io(png, fp);
|
|
|
|
|
|
|
|
png_read_info(png, info);
|
|
|
|
|
|
|
|
width = png_get_image_width(png, info);
|
|
|
|
height = png_get_image_height(png, info);
|
|
|
|
color_type = png_get_color_type(png, info);
|
2019-10-20 22:13:51 +00:00
|
|
|
bit_depth = png_get_bit_depth(png, info);
|
2019-08-25 19:10:35 +00:00
|
|
|
|
|
|
|
// Read any color_type into 8bit depth, RGBA format.
|
|
|
|
// See http://www.libpng.org/pub/png/libpng-manual.txt
|
|
|
|
|
2019-10-20 22:13:51 +00:00
|
|
|
if (bit_depth == 16)
|
2019-08-25 19:10:35 +00:00
|
|
|
png_set_strip_16(png);
|
|
|
|
|
2019-10-20 22:13:51 +00:00
|
|
|
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
2019-08-25 19:10:35 +00:00
|
|
|
png_set_palette_to_rgb(png);
|
|
|
|
|
|
|
|
// PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
|
2019-10-20 22:13:51 +00:00
|
|
|
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
2019-08-25 19:10:35 +00:00
|
|
|
png_set_expand_gray_1_2_4_to_8(png);
|
|
|
|
|
2019-10-20 22:13:51 +00:00
|
|
|
if (png_get_valid(png, info, PNG_INFO_tRNS))
|
2019-08-25 19:10:35 +00:00
|
|
|
png_set_tRNS_to_alpha(png);
|
|
|
|
|
|
|
|
// These color_type don't have an alpha channel then fill it with 0xff.
|
2019-10-20 22:13:51 +00:00
|
|
|
if (color_type == PNG_COLOR_TYPE_RGB ||
|
|
|
|
color_type == PNG_COLOR_TYPE_GRAY ||
|
|
|
|
color_type == PNG_COLOR_TYPE_PALETTE)
|
2019-08-25 19:10:35 +00:00
|
|
|
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
|
|
|
|
|
2019-10-20 22:13:51 +00:00
|
|
|
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
|
|
|
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
2019-08-25 19:10:35 +00:00
|
|
|
png_set_gray_to_rgb(png);
|
|
|
|
|
|
|
|
png_read_update_info(png, info);
|
|
|
|
|
|
|
|
size_t row_bytes = png_get_rowbytes(png, info);
|
2019-10-07 17:39:54 +00:00
|
|
|
assert(row_bytes == width * 4);
|
2019-10-07 20:32:34 +00:00
|
|
|
struct nvnc_fb* fb = nvnc_fb_new(width, height, DRM_FORMAT_ABGR8888);
|
2019-10-07 17:39:54 +00:00
|
|
|
assert(fb);
|
|
|
|
|
2019-10-20 22:13:51 +00:00
|
|
|
uint8_t* addr = nvnc_fb_get_addr(fb);
|
2019-08-25 19:10:35 +00:00
|
|
|
|
|
|
|
row_pointers = malloc(sizeof(png_bytep) * height);
|
|
|
|
assert(row_pointers);
|
|
|
|
|
|
|
|
for (int y = 0; y < height; ++y)
|
|
|
|
row_pointers[y] = addr + y * row_bytes;
|
|
|
|
|
|
|
|
png_read_image(png, row_pointers);
|
|
|
|
|
|
|
|
free(row_pointers);
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
png_destroy_read_struct(&png, &info, NULL);
|
|
|
|
|
2019-10-07 17:39:54 +00:00
|
|
|
return fb;
|
2019-08-25 19:10:35 +00:00
|
|
|
}
|