mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 19:08:59 +00:00
Add Pl_TIFFPredictor
This commit is contained in:
parent
d9c9049708
commit
53971d50be
123
libqpdf/Pl_TIFFPredictor.cc
Normal file
123
libqpdf/Pl_TIFFPredictor.cc
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#include <qpdf/Pl_TIFFPredictor.hh>
|
||||||
|
#include <qpdf/QTC.hh>
|
||||||
|
#include <qpdf/BitStream.hh>
|
||||||
|
#include <qpdf/BitWriter.hh>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
Pl_TIFFPredictor::Pl_TIFFPredictor(char const* identifier, Pipeline* next,
|
||||||
|
action_e action, unsigned int columns,
|
||||||
|
unsigned int samples_per_pixel,
|
||||||
|
unsigned int bits_per_sample) :
|
||||||
|
Pipeline(identifier, next),
|
||||||
|
action(action),
|
||||||
|
columns(columns),
|
||||||
|
samples_per_pixel(samples_per_pixel),
|
||||||
|
bits_per_sample(bits_per_sample),
|
||||||
|
cur_row(0),
|
||||||
|
pos(0)
|
||||||
|
{
|
||||||
|
if (samples_per_pixel < 1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
"TIFFPredictor created with invalid samples_per_pixel");
|
||||||
|
}
|
||||||
|
if ((bits_per_sample < 1) ||
|
||||||
|
(bits_per_sample > (8 * (sizeof(unsigned long long)))))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
"TIFFPredictor created with invalid bits_per_sample");
|
||||||
|
}
|
||||||
|
unsigned long long bpr =
|
||||||
|
((columns * bits_per_sample * samples_per_pixel) + 7) / 8;
|
||||||
|
if ((bpr == 0) || (bpr > (UINT_MAX - 1)))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
"TIFFPredictor created with invalid columns value");
|
||||||
|
}
|
||||||
|
this->bytes_per_row = bpr & UINT_MAX;
|
||||||
|
this->cur_row = new unsigned char[this->bytes_per_row];
|
||||||
|
memset(this->cur_row, 0, this->bytes_per_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
Pl_TIFFPredictor::~Pl_TIFFPredictor()
|
||||||
|
{
|
||||||
|
delete [] cur_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Pl_TIFFPredictor::write(unsigned char* data, size_t len)
|
||||||
|
{
|
||||||
|
size_t left = this->bytes_per_row - this->pos;
|
||||||
|
size_t offset = 0;
|
||||||
|
while (len >= left)
|
||||||
|
{
|
||||||
|
// finish off current row
|
||||||
|
memcpy(this->cur_row + this->pos, data + offset, left);
|
||||||
|
offset += left;
|
||||||
|
len -= left;
|
||||||
|
|
||||||
|
processRow();
|
||||||
|
|
||||||
|
// Prepare for next row
|
||||||
|
memset(this->cur_row, 0, this->bytes_per_row);
|
||||||
|
left = this->bytes_per_row;
|
||||||
|
this->pos = 0;
|
||||||
|
}
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
memcpy(this->cur_row + this->pos, data + offset, len);
|
||||||
|
}
|
||||||
|
this->pos += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Pl_TIFFPredictor::processRow()
|
||||||
|
{
|
||||||
|
QTC::TC("libtests", "Pl_TIFFPredictor processRow",
|
||||||
|
(action == a_decode ? 0 : 1));
|
||||||
|
BitWriter bw(this->getNext());
|
||||||
|
BitStream in(this->cur_row, this->bytes_per_row);
|
||||||
|
std::vector<long long> prev;
|
||||||
|
for (unsigned int i = 0; i < this->samples_per_pixel; ++i)
|
||||||
|
{
|
||||||
|
long long sample = in.getBitsSigned(this->bits_per_sample);
|
||||||
|
bw.writeBitsSigned(sample, this->bits_per_sample);
|
||||||
|
prev.push_back(sample);
|
||||||
|
}
|
||||||
|
for (unsigned int col = 1; col < this->columns; ++col)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < this->samples_per_pixel; ++i)
|
||||||
|
{
|
||||||
|
long long sample = in.getBitsSigned(this->bits_per_sample);
|
||||||
|
long long new_sample = sample;
|
||||||
|
if (action == a_encode)
|
||||||
|
{
|
||||||
|
new_sample -= prev[i];
|
||||||
|
prev[i] = sample;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_sample += prev[i];
|
||||||
|
prev[i] = new_sample;
|
||||||
|
}
|
||||||
|
bw.writeBitsSigned(new_sample, this->bits_per_sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bw.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Pl_TIFFPredictor::finish()
|
||||||
|
{
|
||||||
|
if (this->pos)
|
||||||
|
{
|
||||||
|
// write partial row
|
||||||
|
processRow();
|
||||||
|
}
|
||||||
|
this->pos = 0;
|
||||||
|
memset(this->cur_row, 0, this->bytes_per_row);
|
||||||
|
getNext()->finish();
|
||||||
|
}
|
@ -32,6 +32,7 @@ SRCS_libqpdf = \
|
|||||||
libqpdf/Pl_RunLength.cc \
|
libqpdf/Pl_RunLength.cc \
|
||||||
libqpdf/Pl_SHA2.cc \
|
libqpdf/Pl_SHA2.cc \
|
||||||
libqpdf/Pl_StdioFile.cc \
|
libqpdf/Pl_StdioFile.cc \
|
||||||
|
libqpdf/Pl_TIFFPredictor.cc \
|
||||||
libqpdf/QPDF.cc \
|
libqpdf/QPDF.cc \
|
||||||
libqpdf/QPDFExc.cc \
|
libqpdf/QPDFExc.cc \
|
||||||
libqpdf/QPDFObjGen.cc \
|
libqpdf/QPDFObjGen.cc \
|
||||||
|
39
libqpdf/qpdf/Pl_TIFFPredictor.hh
Normal file
39
libqpdf/qpdf/Pl_TIFFPredictor.hh
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __PL_TIFFPREDICTOR_HH__
|
||||||
|
#define __PL_TIFFPREDICTOR_HH__
|
||||||
|
|
||||||
|
// This pipeline reverses the application of a TIFF predictor as
|
||||||
|
// described in the TIFF specification.
|
||||||
|
|
||||||
|
#include <qpdf/Pipeline.hh>
|
||||||
|
|
||||||
|
class Pl_TIFFPredictor: public Pipeline
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum action_e { a_encode, a_decode };
|
||||||
|
|
||||||
|
QPDF_DLL
|
||||||
|
Pl_TIFFPredictor(char const* identifier, Pipeline* next,
|
||||||
|
action_e action, unsigned int columns,
|
||||||
|
unsigned int samples_per_pixel = 1,
|
||||||
|
unsigned int bits_per_sample = 8);
|
||||||
|
QPDF_DLL
|
||||||
|
virtual ~Pl_TIFFPredictor();
|
||||||
|
|
||||||
|
QPDF_DLL
|
||||||
|
virtual void write(unsigned char* data, size_t len);
|
||||||
|
QPDF_DLL
|
||||||
|
virtual void finish();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void processRow();
|
||||||
|
|
||||||
|
action_e action;
|
||||||
|
unsigned int columns;
|
||||||
|
unsigned int bytes_per_row;
|
||||||
|
unsigned int samples_per_pixel;
|
||||||
|
unsigned int bits_per_sample;
|
||||||
|
unsigned char* cur_row;
|
||||||
|
size_t pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // __PL_TIFFPREDICTOR_HH__
|
@ -33,3 +33,4 @@ Pl_PNGFilter decodeSub 0
|
|||||||
Pl_PNGFilter decodeUp 0
|
Pl_PNGFilter decodeUp 0
|
||||||
Pl_PNGFilter decodeAverage 0
|
Pl_PNGFilter decodeAverage 0
|
||||||
Pl_PNGFilter decodePaeth 0
|
Pl_PNGFilter decodePaeth 0
|
||||||
|
Pl_TIFFPredictor processRow 1
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <qpdf/Pl_PNGFilter.hh>
|
#include <qpdf/Pl_PNGFilter.hh>
|
||||||
|
#include <qpdf/Pl_TIFFPredictor.hh>
|
||||||
#include <qpdf/Pl_StdioFile.hh>
|
#include <qpdf/Pl_StdioFile.hh>
|
||||||
#include <qpdf/QUtil.hh>
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
@ -23,6 +24,13 @@ void run(char const* filename, char const* filter,
|
|||||||
encode ? Pl_PNGFilter::a_encode : Pl_PNGFilter::a_decode,
|
encode ? Pl_PNGFilter::a_encode : Pl_PNGFilter::a_decode,
|
||||||
columns, samples_per_pixel, bits_per_sample);
|
columns, samples_per_pixel, bits_per_sample);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(filter, "tiff") == 0)
|
||||||
|
{
|
||||||
|
pl = new Pl_TIFFPredictor(
|
||||||
|
"png", out,
|
||||||
|
encode ? Pl_TIFFPredictor::a_encode : Pl_TIFFPredictor::a_decode,
|
||||||
|
columns, samples_per_pixel, bits_per_sample);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "unknown filter " << filter << std::endl;
|
std::cerr << "unknown filter " << filter << std::endl;
|
||||||
|
@ -53,7 +53,7 @@ $td->runtest("check output",
|
|||||||
{$td->FILE => "out"},
|
{$td->FILE => "out"},
|
||||||
{$td->FILE => "in2"});
|
{$td->FILE => "in2"});
|
||||||
|
|
||||||
my @other = (
|
my @other_png = (
|
||||||
'01--32-3-16',
|
'01--32-3-16',
|
||||||
'02--32-1-8',
|
'02--32-1-8',
|
||||||
'03--32-3-8',
|
'03--32-3-8',
|
||||||
@ -68,7 +68,7 @@ my @other = (
|
|||||||
'12--32-1-4',
|
'12--32-1-4',
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach my $i (@other)
|
foreach my $i (@other_png)
|
||||||
{
|
{
|
||||||
$i =~ m/^.*?--(\d+)-(\d+)-(\d+)$/ or die;
|
$i =~ m/^.*?--(\d+)-(\d+)-(\d+)$/ or die;
|
||||||
my $columns = $1;
|
my $columns = $1;
|
||||||
@ -85,9 +85,41 @@ foreach my $i (@other)
|
|||||||
{$td->FILE => "$i.decoded"});
|
{$td->FILE => "$i.decoded"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my @tiff = (
|
||||||
|
'01--16-1-8',
|
||||||
|
'02--8-2-4',
|
||||||
|
'03--4-1-16',
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach my $i (@tiff)
|
||||||
|
{
|
||||||
|
$i =~ m/^.*?--(\d+)-(\d+)-(\d+)$/ or die;
|
||||||
|
my $columns = $1;
|
||||||
|
my $samples_per_pixel = $2;
|
||||||
|
my $bits_per_sample = $3;
|
||||||
|
$td->runtest("decode tiff $i",
|
||||||
|
{$td->COMMAND => "predictors tiff decode tiff-$i.data" .
|
||||||
|
" $columns $samples_per_pixel $bits_per_sample"},
|
||||||
|
{$td->STRING => "done\n",
|
||||||
|
$td->EXIT_STATUS => 0},
|
||||||
|
$td->NORMALIZE_NEWLINES);
|
||||||
|
$td->runtest("check output for tiff-$i",
|
||||||
|
{$td->FILE => "out"},
|
||||||
|
{$td->FILE => "tiff-$i.decoded"});
|
||||||
|
$td->runtest("encode tiff $i",
|
||||||
|
{$td->COMMAND => "predictors tiff encode tiff-$i.decoded" .
|
||||||
|
" $columns $samples_per_pixel $bits_per_sample"},
|
||||||
|
{$td->STRING => "done\n",
|
||||||
|
$td->EXIT_STATUS => 0},
|
||||||
|
$td->NORMALIZE_NEWLINES);
|
||||||
|
$td->runtest("check output for tiff-$i",
|
||||||
|
{$td->FILE => "out"},
|
||||||
|
{$td->FILE => "tiff-$i.data"});
|
||||||
|
}
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
$td->report(8 + (2 * scalar(@other)));
|
$td->report(8 + (2 * scalar(@other_png)) + (4 * scalar(@tiff)));
|
||||||
|
|
||||||
sub cleanup
|
sub cleanup
|
||||||
{
|
{
|
||||||
|
BIN
libtests/qtest/predictors/tiff-01--16-1-8.data
Normal file
BIN
libtests/qtest/predictors/tiff-01--16-1-8.data
Normal file
Binary file not shown.
3
libtests/qtest/predictors/tiff-01--16-1-8.decoded
Normal file
3
libtests/qtest/predictors/tiff-01--16-1-8.decoded
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
WXWVUTSRQG=33467
|
BIN
libtests/qtest/predictors/tiff-02--8-2-4.data
Normal file
BIN
libtests/qtest/predictors/tiff-02--8-2-4.data
Normal file
Binary file not shown.
1
libtests/qtest/predictors/tiff-02--8-2-4.decoded
Normal file
1
libtests/qtest/predictors/tiff-02--8-2-4.decoded
Normal file
@ -0,0 +1 @@
|
|||||||
|
Ş›Ś}__wŞ›Ś}__w
|
1
libtests/qtest/predictors/tiff-03--4-1-16.data
Normal file
1
libtests/qtest/predictors/tiff-03--4-1-16.data
Normal file
@ -0,0 +1 @@
|
|||||||
|
UUヘ<EFBFBD> 9[
|
1
libtests/qtest/predictors/tiff-03--4-1-16.decoded
Normal file
1
libtests/qtest/predictors/tiff-03--4-1-16.decoded
Normal file
@ -0,0 +1 @@
|
|||||||
|
UU#E‡eÀÀ
|
Loading…
Reference in New Issue
Block a user