diff options
Diffstat (limited to 'libqpdf/Pl_PNGFilter.cc')
-rw-r--r-- | libqpdf/Pl_PNGFilter.cc | 89 |
1 files changed, 57 insertions, 32 deletions
diff --git a/libqpdf/Pl_PNGFilter.cc b/libqpdf/Pl_PNGFilter.cc index edcc34cb..5504112e 100644 --- a/libqpdf/Pl_PNGFilter.cc +++ b/libqpdf/Pl_PNGFilter.cc @@ -2,32 +2,54 @@ #include <stdexcept> #include <string.h> #include <limits.h> -#include <math.h> Pl_PNGFilter::Pl_PNGFilter(char const* identifier, Pipeline* next, action_e action, unsigned int columns, - unsigned int bytes_per_pixel) : + unsigned int samples_per_pixel, + unsigned int bits_per_sample) : Pipeline(identifier, next), action(action), - columns(columns), cur_row(0), prev_row(0), buf1(0), buf2(0), - bytes_per_pixel(bytes_per_pixel), pos(0) { - if ((columns == 0) || (columns > UINT_MAX - 1)) + if ((samples_per_pixel < 1) || (samples_per_pixel > 4)) + { + throw std::runtime_error( + "PNGFilter created with invalid samples_per_pixel not from 1 to 4"); + } + if (! ((bits_per_sample == 1) || + (bits_per_sample == 2) || + (bits_per_sample == 4) || + (bits_per_sample == 8) || + (bits_per_sample == 16))) + { + throw std::runtime_error( + "PNGFilter created with invalid bits_per_sample not" + " 1, 2, 4, 8, or 16"); + } + this->bytes_per_pixel = ((bits_per_sample * samples_per_pixel) + 7) / 8; + unsigned long long bpr = + ((columns * bits_per_sample * samples_per_pixel) + 7) / 8; + if ((bpr == 0) || (bpr > (UINT_MAX - 1))) { throw std::runtime_error( "PNGFilter created with invalid columns value"); } - this->buf1 = new unsigned char[columns + 1]; - this->buf2 = new unsigned char[columns + 1]; - this->cur_row = buf1; + this->bytes_per_row = bpr & UINT_MAX; + this->buf1 = new unsigned char[this->bytes_per_row + 1]; + this->buf2 = new unsigned char[this->bytes_per_row + 1]; + memset(this->buf1, 0, this->bytes_per_row + 1); + memset(this->buf2, 0, this->bytes_per_row + 1); + this->cur_row = this->buf1; + this->prev_row = this->buf2; // number of bytes per incoming row - this->incoming = (action == a_encode ? columns : columns + 1); + this->incoming = (action == a_encode ? + this->bytes_per_row : + this->bytes_per_row + 1); } Pl_PNGFilter::~Pl_PNGFilter() @@ -54,7 +76,7 @@ Pl_PNGFilter::write(unsigned char* data, size_t len) unsigned char* t = this->prev_row; this->prev_row = this->cur_row; this->cur_row = t ? t : this->buf2; - memset(this->cur_row, 0, this->columns + 1); + memset(this->cur_row, 0, this->bytes_per_row + 1); left = this->incoming; this->pos = 0; } @@ -106,16 +128,16 @@ Pl_PNGFilter::decodeRow() } } - getNext()->write(this->cur_row + 1, this->columns); + getNext()->write(this->cur_row + 1, this->bytes_per_row); } void Pl_PNGFilter::decodeSub() { unsigned char* buffer = this->cur_row + 1; - unsigned int bpp = this->bytes_per_pixel != 0 ? this->bytes_per_pixel : 1; + unsigned int bpp = this->bytes_per_pixel; - for (unsigned int i = 0; i < this->columns; ++i) + for (unsigned int i = 0; i < this->bytes_per_row; ++i) { unsigned char left = 0; @@ -134,7 +156,7 @@ Pl_PNGFilter::decodeUp() unsigned char* buffer = this->cur_row + 1; unsigned char* above_buffer = this->prev_row + 1; - for (unsigned int i = 0; i < this->columns; ++i) + for (unsigned int i = 0; i < this->bytes_per_row; ++i) { unsigned char up = above_buffer[i]; buffer[i] += up; @@ -144,13 +166,14 @@ Pl_PNGFilter::decodeUp() void Pl_PNGFilter::decodeAverage() { - unsigned char* buffer = this->cur_row+1; - unsigned char* above_buffer = this->prev_row+1; - unsigned int bpp = this->bytes_per_pixel != 0 ? this->bytes_per_pixel : 1; + unsigned char* buffer = this->cur_row + 1; + unsigned char* above_buffer = this->prev_row + 1; + unsigned int bpp = this->bytes_per_pixel; - for (unsigned int i = 0; i < this->columns; ++i) + for (unsigned int i = 0; i < this->bytes_per_row; ++i) { - int left = 0, up = 0; + int left = 0; + int up = 0; if (i >= bpp) { @@ -158,22 +181,22 @@ Pl_PNGFilter::decodeAverage() } up = above_buffer[i]; - buffer[i] += floor((left+up) / 2); + buffer[i] += (left+up) / 2; } } void Pl_PNGFilter::decodePaeth() { - unsigned char* buffer = this->cur_row+1; - unsigned char* above_buffer = this->prev_row+1; - unsigned int bpp = this->bytes_per_pixel != 0 ? this->bytes_per_pixel : 1; + unsigned char* buffer = this->cur_row + 1; + unsigned char* above_buffer = this->prev_row + 1; + unsigned int bpp = this->bytes_per_pixel; - for (unsigned int i = 0; i < this->columns; ++i) + for (unsigned int i = 0; i < this->bytes_per_row; ++i) { - int left = 0, - up = above_buffer[i], - upper_left = 0; + int left = 0; + int up = above_buffer[i]; + int upper_left = 0; if (i >= bpp) { @@ -193,10 +216,12 @@ Pl_PNGFilter::PaethPredictor(int a, int b, int c) int pb = std::abs(p - b); int pc = std::abs(p - c); - if (pa <= pb && pa <= pc) { + if (pa <= pb && pa <= pc) + { return a; } - if (pb <= pc) { + if (pb <= pc) + { return b; } return c; @@ -210,7 +235,7 @@ Pl_PNGFilter::encodeRow() getNext()->write(&ch, 1); if (this->prev_row) { - for (unsigned int i = 0; i < this->columns; ++i) + for (unsigned int i = 0; i < this->bytes_per_row; ++i) { ch = this->cur_row[i] - this->prev_row[i]; getNext()->write(&ch, 1); @@ -218,7 +243,7 @@ Pl_PNGFilter::encodeRow() } else { - getNext()->write(this->cur_row, this->columns); + getNext()->write(this->cur_row, this->bytes_per_row); } } @@ -233,7 +258,7 @@ Pl_PNGFilter::finish() this->prev_row = 0; this->cur_row = buf1; this->pos = 0; - memset(this->cur_row, 0, this->columns + 1); + memset(this->cur_row, 0, this->bytes_per_row + 1); getNext()->finish(); } |