Commit b1ec5ba88333f173888a4dbdaa65e30fe9f557df

Authored by Jay Berkenbilt
2 parents 3279c21e d946ad6c

Merge branch 'fz' of github.com:m-holger/qpdf into fz

libqpdf/Pl_TIFFPredictor.cc
@@ -3,12 +3,9 @@ @@ -3,12 +3,9 @@
3 #include <qpdf/BitStream.hh> 3 #include <qpdf/BitStream.hh>
4 #include <qpdf/BitWriter.hh> 4 #include <qpdf/BitWriter.hh>
5 #include <qpdf/QTC.hh> 5 #include <qpdf/QTC.hh>
6 -#include <qpdf/QUtil.hh>  
7 6
8 #include <climits> 7 #include <climits>
9 -#include <cstring>  
10 #include <stdexcept> 8 #include <stdexcept>
11 -#include <vector>  
12 9
13 Pl_TIFFPredictor::Pl_TIFFPredictor( 10 Pl_TIFFPredictor::Pl_TIFFPredictor(
14 char const* identifier, 11 char const* identifier,
@@ -22,7 +19,7 @@ Pl_TIFFPredictor::Pl_TIFFPredictor( @@ -22,7 +19,7 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(
22 columns(columns), 19 columns(columns),
23 samples_per_pixel(samples_per_pixel), 20 samples_per_pixel(samples_per_pixel),
24 bits_per_sample(bits_per_sample), 21 bits_per_sample(bits_per_sample),
25 - pos(0) 22 + p_next(getNext())
26 { 23 {
27 if (samples_per_pixel < 1) { 24 if (samples_per_pixel < 1) {
28 throw std::runtime_error("TIFFPredictor created with invalid samples_per_pixel"); 25 throw std::runtime_error("TIFFPredictor created with invalid samples_per_pixel");
@@ -35,71 +32,83 @@ Pl_TIFFPredictor::Pl_TIFFPredictor( @@ -35,71 +32,83 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(
35 throw std::runtime_error("TIFFPredictor created with invalid columns value"); 32 throw std::runtime_error("TIFFPredictor created with invalid columns value");
36 } 33 }
37 this->bytes_per_row = bpr & UINT_MAX; 34 this->bytes_per_row = bpr & UINT_MAX;
38 - this->cur_row = QUtil::make_shared_array<unsigned char>(this->bytes_per_row);  
39 - memset(this->cur_row.get(), 0, this->bytes_per_row);  
40 } 35 }
41 36
42 void 37 void
43 Pl_TIFFPredictor::write(unsigned char const* data, size_t len) 38 Pl_TIFFPredictor::write(unsigned char const* data, size_t len)
44 { 39 {
45 - size_t left = this->bytes_per_row - this->pos;  
46 - size_t offset = 0;  
47 - while (len >= left) { 40 + auto end = data + len;
  41 + auto row_end = data + (bytes_per_row - cur_row.size());
  42 + while (row_end <= end) {
48 // finish off current row 43 // finish off current row
49 - memcpy(this->cur_row.get() + this->pos, data + offset, left);  
50 - offset += left;  
51 - len -= left; 44 + cur_row.insert(cur_row.end(), data, row_end);
  45 + data = row_end;
  46 + row_end += bytes_per_row;
52 47
53 processRow(); 48 processRow();
54 49
55 // Prepare for next row 50 // Prepare for next row
56 - memset(this->cur_row.get(), 0, this->bytes_per_row);  
57 - left = this->bytes_per_row;  
58 - this->pos = 0; 51 + cur_row.clear();
59 } 52 }
60 - if (len) {  
61 - memcpy(this->cur_row.get() + this->pos, data + offset, len);  
62 - }  
63 - this->pos += len; 53 +
  54 + cur_row.insert(cur_row.end(), data, end);
64 } 55 }
65 56
66 void 57 void
67 Pl_TIFFPredictor::processRow() 58 Pl_TIFFPredictor::processRow()
68 { 59 {
69 QTC::TC("libtests", "Pl_TIFFPredictor processRow", (action == a_decode ? 0 : 1)); 60 QTC::TC("libtests", "Pl_TIFFPredictor processRow", (action == a_decode ? 0 : 1));
70 - BitWriter bw(this->getNext());  
71 - BitStream in(this->cur_row.get(), this->bytes_per_row);  
72 - std::vector<long long> prev;  
73 - for (unsigned int i = 0; i < this->samples_per_pixel; ++i) {  
74 - long long sample = in.getBitsSigned(this->bits_per_sample);  
75 - bw.writeBitsSigned(sample, this->bits_per_sample);  
76 - prev.push_back(sample);  
77 - }  
78 - for (unsigned int col = 1; col < this->columns; ++col) {  
79 - for (unsigned int i = 0; i < this->samples_per_pixel; ++i) {  
80 - long long sample = in.getBitsSigned(this->bits_per_sample);  
81 - long long new_sample = sample;  
82 - if (action == a_encode) {  
83 - new_sample -= prev[i];  
84 - prev[i] = sample;  
85 - } else {  
86 - new_sample += prev[i];  
87 - prev[i] = new_sample; 61 + previous.assign(samples_per_pixel, 0);
  62 + if (bits_per_sample != 8) {
  63 + BitWriter bw(p_next);
  64 + BitStream in(cur_row.data(), cur_row.size());
  65 + for (unsigned int col = 0; col < this->columns; ++col) {
  66 + for (auto& prev: previous) {
  67 + long long sample = in.getBitsSigned(this->bits_per_sample);
  68 + long long new_sample = sample;
  69 + if (action == a_encode) {
  70 + new_sample -= prev;
  71 + prev = sample;
  72 + } else {
  73 + new_sample += prev;
  74 + prev = new_sample;
  75 + }
  76 + bw.writeBitsSigned(new_sample, this->bits_per_sample);
  77 + }
  78 + }
  79 + bw.flush();
  80 + } else {
  81 + out.clear();
  82 + auto next = cur_row.begin();
  83 + auto cr_end = cur_row.end();
  84 + auto pr_end = previous.end();
  85 +
  86 + while (next != cr_end) {
  87 + for (auto prev = previous.begin(); prev != pr_end && next != cr_end; ++prev, ++next) {
  88 + long long sample = *next;
  89 + long long new_sample = sample;
  90 + if (action == a_encode) {
  91 + new_sample -= *prev;
  92 + *prev = sample;
  93 + } else {
  94 + new_sample += *prev;
  95 + *prev = new_sample;
  96 + }
  97 + out.push_back(static_cast<unsigned char>(255U & new_sample));
88 } 98 }
89 - bw.writeBitsSigned(new_sample, this->bits_per_sample);  
90 } 99 }
  100 + p_next->write(out.data(), out.size());
91 } 101 }
92 - bw.flush();  
93 } 102 }
94 103
95 void 104 void
96 Pl_TIFFPredictor::finish() 105 Pl_TIFFPredictor::finish()
97 { 106 {
98 - if (this->pos) { 107 + if (!cur_row.empty()) {
99 // write partial row 108 // write partial row
  109 + cur_row.insert(cur_row.end(), bytes_per_row - cur_row.size(), 0);
100 processRow(); 110 processRow();
101 } 111 }
102 - this->pos = 0;  
103 - memset(this->cur_row.get(), 0, this->bytes_per_row);  
104 - getNext()->finish(); 112 + cur_row.clear();
  113 + p_next->finish();
105 } 114 }
libqpdf/qpdf/Pl_TIFFPredictor.hh
@@ -6,6 +6,8 @@ @@ -6,6 +6,8 @@
6 6
7 #include <qpdf/Pipeline.hh> 7 #include <qpdf/Pipeline.hh>
8 8
  9 +#include<vector>
  10 +
9 class Pl_TIFFPredictor: public Pipeline 11 class Pl_TIFFPredictor: public Pipeline
10 { 12 {
11 public: 13 public:
@@ -31,8 +33,10 @@ class Pl_TIFFPredictor: public Pipeline @@ -31,8 +33,10 @@ class Pl_TIFFPredictor: public Pipeline
31 unsigned int bytes_per_row; 33 unsigned int bytes_per_row;
32 unsigned int samples_per_pixel; 34 unsigned int samples_per_pixel;
33 unsigned int bits_per_sample; 35 unsigned int bits_per_sample;
34 - std::shared_ptr<unsigned char> cur_row;  
35 - size_t pos; 36 + std::vector<unsigned char> cur_row;
  37 + std::vector<long long> previous;
  38 + std::vector<unsigned char> out;
  39 + Pipeline* p_next;
36 }; 40 };
37 41
38 #endif // PL_TIFFPREDICTOR_HH 42 #endif // PL_TIFFPREDICTOR_HH