File: png_image.cpp

package info (click to toggle)
amoeba 1.1-19
  • links: PTS
  • area: contrib
  • in suites: lenny
  • size: 816 kB
  • ctags: 966
  • sloc: cpp: 8,286; makefile: 173
file content (144 lines) | stat: -rw-r--r-- 3,866 bytes parent folder | download | duplicates (9)
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
/*
 * 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, unsigned int 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_read_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr,
		(png_uint_32 *)(&this->width), (png_uint_32 *)(&this->height),
		&bit_depth, &color_type, &interlace_type, NULL, NULL);

	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 */