File: png_image.cpp

package info (click to toggle)
amoeba 1.1-13
  • links: PTS
  • area: contrib
  • in suites: sarge
  • size: 732 kB
  • ctags: 971
  • sloc: cpp: 8,315; makefile: 178
file content (148 lines) | stat: -rw-r--r-- 3,893 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Based on libpng's example.c (so it needs libpng)
 */

#include <stdio.h>
#include <stdlib.h>

#include <png.h>
#include "png_image.h"
#include "../exception.h"
#include "../demolib_prefs.h"

#if DEMOLIB_IMAGE_PNG

/* ugly, but works (unless there is corrupted data :-D) */
char *curr_png_ptr = NULL;
void read_mem(png_structp png_ptr, png_bytep data, png_size_t length)
{
	memcpy(data, curr_png_ptr, length);
	curr_png_ptr += length;
}   

PNGImage::PNGImage(File *file)
{
	png_structp png_ptr;
	png_infop info_ptr;
	int bit_depth, color_type, interlace_type;
//	png_color_16 my_background, *image_background;
	png_info intent;
	png_bytep *row_pointers;
	float screen_gamma;
	unsigned int row;

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (png_ptr == NULL) {
		throw new FatalException("png_create_read_struct() failed");
	}

	/* Allocate/initialize the memory for image information. */
	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		throw new FatalException("png_create_info_struct() failed");
	}

	/* Set up error handling. */
	if (setjmp(png_ptr->jmpbuf)) {
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		throw new FatalException("PNG decompression failed");
	}

	/* Set up the memory reader. */
	curr_png_ptr = file->get_data();
	png_set_read_fn(png_ptr, NULL, read_mem);

	png_uint_32 width, height;
	png_read_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr,
		&width, &height,
		&bit_depth, &color_type, &interlace_type, NULL, NULL);

	this->width = width;
	this->height = height;

	if (color_type == PNG_COLOR_TYPE_GRAY) {
		this->bpp = 8;
	}
	if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		this->bpp = 16;
	}
	if (color_type == PNG_COLOR_TYPE_PALETTE) {
		this->bpp = 32;
	}
	if (color_type == PNG_COLOR_TYPE_RGB) {
		this->bpp = 24;
	}
	if (color_type == PNG_COLOR_TYPE_RGBA) {
		this->bpp = 32;
	}

	/* Allocate memory if needed */
        this->image_buf = (unsigned char *)(malloc(this->width * this->height * this->bpp / 8));
        if (this->image_buf == NULL) {
                throw new FatalException("Couldn't allocate memory for JPEG image");
        }
						
//	png_set_strip_16(png_ptr);
	png_set_packing(png_ptr);
	if (color_type == PNG_COLOR_TYPE_PALETTE)
		png_set_expand(png_ptr);
	if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
		png_set_expand(png_ptr);
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_expand(png_ptr);

	
/*	if (png_get_bKGD(png_ptr, info_ptr, &image_background))
		png_set_background(png_ptr, image_background,
			PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
	else
		png_set_background(png_ptr, &my_background,
			PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); */

	screen_gamma = 2.2;
	if (png_get_sRGB(png_ptr, info_ptr, (int *)(&intent))) {
		png_set_sRGB(png_ptr, &intent, 0);
	} else {
		double image_gamma;
		if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
			png_set_gamma(png_ptr, screen_gamma, image_gamma);
		else
			png_set_gamma(png_ptr, screen_gamma, 0.45455);
	}

//	png_set_bgr(png_ptr);

/*	if (color_type != PNG_COLOR_TYPE_RGBA)
		png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); */

	/* Allocate the row pointers (ick!) */
	row_pointers = (png_bytep *)(malloc(sizeof(png_bytep) * this->height));
	if (row_pointers == NULL) {
		throw new FatalException("Out of memory");
	}
	for (row = 0; row < height; row++) {
		row_pointers[row] = this->image_buf + (this->width * row * this->bpp / 8);
	}

	/* Read the image in one pass. */
	png_read_image(png_ptr, row_pointers);

	free(row_pointers);
	
	png_read_end(png_ptr, info_ptr);
	png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
}

PNGImage::~PNGImage()
{
	free(this->image_buf);
}

unsigned char *PNGImage::get_pixel_data()
{
	return this->image_buf;
}

#endif /* DEMOLIB_IMAGE_PNG */