mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +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_SHA2.cc \
|
||||
libqpdf/Pl_StdioFile.cc \
|
||||
libqpdf/Pl_TIFFPredictor.cc \
|
||||
libqpdf/QPDF.cc \
|
||||
libqpdf/QPDFExc.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 decodeAverage 0
|
||||
Pl_PNGFilter decodePaeth 0
|
||||
Pl_TIFFPredictor processRow 1
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <qpdf/Pl_PNGFilter.hh>
|
||||
#include <qpdf/Pl_TIFFPredictor.hh>
|
||||
#include <qpdf/Pl_StdioFile.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,
|
||||
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
|
||||
{
|
||||
std::cerr << "unknown filter " << filter << std::endl;
|
||||
|
@ -53,7 +53,7 @@ $td->runtest("check output",
|
||||
{$td->FILE => "out"},
|
||||
{$td->FILE => "in2"});
|
||||
|
||||
my @other = (
|
||||
my @other_png = (
|
||||
'01--32-3-16',
|
||||
'02--32-1-8',
|
||||
'03--32-3-8',
|
||||
@ -68,7 +68,7 @@ my @other = (
|
||||
'12--32-1-4',
|
||||
);
|
||||
|
||||
foreach my $i (@other)
|
||||
foreach my $i (@other_png)
|
||||
{
|
||||
$i =~ m/^.*?--(\d+)-(\d+)-(\d+)$/ or die;
|
||||
my $columns = $1;
|
||||
@ -85,9 +85,41 @@ foreach my $i (@other)
|
||||
{$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();
|
||||
|
||||
$td->report(8 + (2 * scalar(@other)));
|
||||
$td->report(8 + (2 * scalar(@other_png)) + (4 * scalar(@tiff)));
|
||||
|
||||
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