00001
00002
00003
#include "PNG.hpp"
00004
00005
00006
00007 PNG::PNG(string fileName){
00008
p =
new PNG_Reader(fileName);
00009 }
00010 PNG::PNG(
int width,
int height, EPNG_TYPE type, string fileName){
00011
p =
new PNG_Writer(width, height, type, fileName);
00012 }
00013 PNG::PNG(
const PNG& png){
00014
p = png.
p;
00015 ++
p->
use;
00016 }
00017 PNG&
PNG::operator=(
const PNG& rhs){
00018 rhs.
p->
use++;
00019
if(--
p->
use == 0){
00020
delete p;
00021 }
00022
p = rhs.
p;
00023
return *
this;
00024 }
00025 PNG::~PNG(){
00026
if(--
p->
use == 0){
00027
delete p;
00028 }
00029 }
00030 EPNG_TYPE PNG::getType()const{
00031
return p->
getType();
00032 }
00033 string
PNG::toString()const{
00034
return p->
toString();
00035 }
00036 int PNG::getWidth()const{
00037
return p->
getWidth();
00038 }
00039 int PNG::getHeight()const{
00040
return p->
getHeight();
00041 }
00042
00043
00044
00045
00046
00047 Color PNG::getColor(
int i,
int j)
const{
00048
return p->
getColor(i, j);
00049 }
00050 void PNG::setColor(
int i,
int j,
Color color){
00051
p->
setColor(i, j, color);
00052 }
00053 void PNG::setColor(
int i,
int j,
float gray){
00054
p->
setColor(i, j , gray);
00055 }
00056 void PNG::setColor(
int i,
int j,
float red,
float green,
float blue){
00057
p->
setColor(i, j, red, green, blue);
00058 }
00059 void PNG::read(){
00060
p->
read();
00061 }
00062
00063 void PNG::write(){
00064
p->
write();
00065 }
00066 Histogram*
PNG::getHistogram()const{
00067
return p->
getHistogram();
00068 }
00069
00070
00071
00072 PNG_Base::PNG_Base():
00073 use(1),
00074 fp(NULL),
00075 png_ptr(NULL),
00076 info_ptr(NULL)
00077 {}
00078 int PNG_Base::getWidth()const{
00079
return width;
00080 };
00081 int PNG_Base::getHeight()const{
00082
return height;
00083 }
00084 EPNG_TYPE PNG_Base::getType()const{
00085
switch(
color_type){
00086
case 0 :
00087 {
00088
return PNG_GRAY;
00089 }
00090
break;
00091
case 2 :
00092 {
00093
return PNG_COLOR;
00094 }
00095
break;
00096 }
00097 }
00098 string
PNG_Base::toString()const{
00099 std::ostringstream o;
00100 o <<
"width\t\t" <<
width << endl;
00101 o <<
"height\t\t" <<
height << endl;
00102 o <<
"bit_depth\t" << (
int)
bit_depth << endl;
00103 o <<
"color_type\t" << (
int)
color_type << endl;
00104 o <<
"rowbytes\t" << (
int)
rowbytes << endl;
00105
return o.str();
00106 }
00107 Histogram*
PNG_Base::getHistogram()const{
00108
Histogram* ret =
new Histogram();
00109
for(
int j = 0; j <
height; j++){
00110
for(
int i = 0; i <
width; i++){
00111
Pixel pixel(i, j,
getColor(i, j));
00112 ret->
addPixel(pixel);
00113 }
00114 }
00115
return ret;
00116 }
00117
00118
00119
00120
00121 void PNG_Reader::read(){
00122
const int PNG_BYTES_TO_CHECK = 4;
00123 png_structp png_ptr;
00124 png_infop info_ptr;
00125
00126 FILE *fp = fopen(fileName.c_str(),
"rb");
00127
if(fp == NULL){
00128
throw std::runtime_error(
" IMPOSSIBLE D'OUVRIE LE FICHIER " + fileName);
00129 }
00130
unsigned char buf[PNG_BYTES_TO_CHECK];
00131
if(fread(buf, 1, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK){
00132
throw std::runtime_error(
" LE FICHIER " + fileName +
" N'EST PAS AU FORMAT PNG ");
00133 }
00134
if(png_sig_cmp(&buf[0], (png_size_t)0, PNG_BYTES_TO_CHECK)){
00135
throw std::runtime_error(
" LE FICHIER " + fileName +
" N'EST PAS AU FORMAT PNG ");
00136 }
00137 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00138
if (png_ptr == NULL) {
00139 fclose(fp);
00140
throw std::runtime_error(
" ERREUR A LA CREATION DE LA STRUCTURE PNG ");
00141 }
00142 info_ptr = png_create_info_struct(png_ptr);
00143
if (info_ptr == NULL) {
00144 fclose(fp);
00145 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
00146
throw std::runtime_error(
" ERRUUR A LA CREATION D'INFORMATION PNG ");
00147 }
00148
if(setjmp(png_jmpbuf(png_ptr))) {
00149 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00150 fclose(fp);
00151
throw std::runtime_error(
" ERREUR A LA CREATION DE LA STRUCTURE INTERNE PNG ");
00152 }
00153 png_init_io(png_ptr, fp);
00154 png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
00155
00156
00157 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);
00158 width = (
int)png_get_image_width(png_ptr, info_ptr);
00159 height = (
int)png_get_image_height(png_ptr, info_ptr);
00160 bit_depth = (
int)png_get_bit_depth(png_ptr, info_ptr);
00161 color_type = (
int)png_get_color_type(png_ptr, info_ptr);
00162 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
00163
00164 fclose(fp);
00165 pData = png_get_rows(png_ptr, info_ptr);
00166 }
00167 Color PNG_Reader::getColor(
int x,
int y)
const{
00168 x = (x < 0 ? 0 : x);
00169 x = (x >= width ? width - 1 : x);
00170
00171 y = (y < 0 ? 0 : y);
00172 y = (y >= height ? height - 1 : y);
00173
00174
switch(color_type){
00175
case 0 :
00176 {
00177
int gray = pData[y][x];
00178
return Color(gray);
00179 }
00180
break;
00181
case 2 :
00182 {
00183
int r = pData[y][x * 3];
00184
int g = pData[y][x * 3 + 1];
00185
int b = pData[y][x * 3 + 2];
00186
return Color(r, g, b,
true);
00187
00188 }
00189
break;
00190 }
00191 }
00192
00193
00194
00195 PNG_Writer::PNG_Writer(
int _width,
int _height, EPNG_TYPE type, string _fileName){
00196 width = _width;
00197 height = _height;
00198 fileName = _fileName;
00199
00200
buffer.resize(width * height);
00201
switch(type){
00202
case PNG_GRAY:
00203 color_type = 0;
00204 bit_depth = 8;
00205 rowbytes = width;
00206
break;
00207
case PNG_COLOR:
00208 color_type = 2;
00209 bit_depth = 8;
00210 rowbytes = width * 3;
00211
break;
00212
default:
00213
throw std::runtime_error(
" TYPE DE FICHIER PNG NON SUPPORTE ");
00214 }
00215 pData =
make_pixels();
00216 }
00217 void PNG_Writer::write(){
00218
for(
int i = 0; i < height; i++){
00219
for(
int j = 0; j < width; j++){
00220
_setColor(j, i,
buffer[j + i * width]);
00221 }
00222 }
00223 FILE *fp;
00224 png_structp png_ptr;
00225 png_infop info_ptr;
00226
00227 fp = fopen(fileName.c_str(),
"wb");
00228
if (fp == NULL){
00229
throw std::runtime_error(
" ECRITURE FICHIER PNG " + fileName);
00230 }
00231 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00232
if (png_ptr == NULL) {
00233 fclose(fp);
00234
throw std::runtime_error(
" CREATION STRUCTURE D'ECRITURE PNG ");
00235 }
00236 info_ptr = png_create_info_struct(png_ptr);
00237
if (info_ptr == NULL) {
00238 fclose(fp);
00239 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
00240
throw std::runtime_error(
" CREATION INFORMATION PNG ");
00241 }
00242
00243
if (setjmp(png_jmpbuf(png_ptr))) {
00244 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00245 fclose(fp);
00246
throw std::runtime_error(
" CREATION INFORMATION INTERNE PNG ");
00247 }
00248 png_init_io(png_ptr, fp);
00249
switch(color_type){
00250
case 0:
00251 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_GRAY,
00252 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00253
break;
00254
case 2:
00255 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_RGB,
00256 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00257
break;
00258 }
00259 png_set_rows(png_ptr, info_ptr, pData);
00260 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);
00261
00262 fclose(fp);
00263 }
00264
00265 png_bytep*
PNG_Writer::make_pixels() {
00266 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00267
if (png_ptr == NULL) {
00268
throw std::runtime_error(
" CREATION INFORMATION PNG ");
00269 }
00270 png_bytep *row_pointers = (
unsigned char **)png_malloc(png_ptr, height*
sizeof(png_bytep));
00271
for (
int i = 0; i < height; i++)
00272 row_pointers[i] = (
unsigned char *)png_malloc(png_ptr, rowbytes);
00273
return row_pointers;
00274 }
00275 void PNG_Writer::_setColor(
int x,
int y,
float gray){
00276
switch(color_type){
00277
case 0 :
00278 {
00279 pData[y][x] = (
int)gray;
00280 }
00281
break;
00282
case 2 :
00283 {
00284 pData[y][x * 3] = (
int)gray;
00285 pData[y][x * 3 + 1] = (
int)gray;
00286 pData[y][x * 3 + 2] = (
int)gray;
00287 }
00288
break;
00289 }
00290 }
00291 void PNG_Writer::_setColor(
int x,
int y,
float r,
float g,
float b){
00292
Color p =
Color(r, g, b,
true);
00293
switch(color_type){
00294
case 0 :
00295 {
00296 pData[y][x] = (
int)p.
getGray();
00297 }
00298
break;
00299
case 2 :
00300 {
00301 pData[y][x * 3] = (
int)p.
getRed();
00302 pData[y][x * 3 + 1] = (
int)p.
getGreen();
00303 pData[y][x * 3 + 2] = (
int)p.
getBlue();
00304 }
00305
break;
00306 }
00307 }
00308 void PNG_Writer::_setColor(
int x,
int y,
Color c){
00309
switch(color_type){
00310
case 0 :
00311 {
00312 pData[y][x] = (
int)c.
getGray();
00313 }
00314
break;
00315
case 2 :
00316 {
00317 pData[y][x * 3] = (
int)c.
getRed();
00318 pData[y][x * 3 + 1] = (
int)c.
getGreen();
00319 pData[y][x * 3 + 2] = (
int)c.
getBlue();
00320 }
00321
break;
00322 }
00323 }
00324 void PNG_Writer::setColor(
int x,
int y,
Color color){
00325
buffer[y * width + x] = color;
00326 }
00327 void PNG_Writer::setColor(
int x,
int y,
float gray){
00328
Color c =
Color(gray);
00329
buffer[y * width + x] = c;
00330 }
00331 void PNG_Writer::setColor(
int x,
int y,
float r,
float g,
float b){
00332
Color c =
Color(r, g, b,
true);
00333
buffer[y * width + x] = c;
00334 }
00335
00336 Color PNG_Writer::getColor(
int x,
int y)
const{
00337
return buffer[width * y + x];
00338 }