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 3 #include <qpdf/BitStream.hh>
4 4 #include <qpdf/BitWriter.hh>
5 5 #include <qpdf/QTC.hh>
6   -#include <qpdf/QUtil.hh>
7 6  
8 7 #include <climits>
9   -#include <cstring>
10 8 #include <stdexcept>
11   -#include <vector>
12 9  
13 10 Pl_TIFFPredictor::Pl_TIFFPredictor(
14 11 char const* identifier,
... ... @@ -22,7 +19,7 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(
22 19 columns(columns),
23 20 samples_per_pixel(samples_per_pixel),
24 21 bits_per_sample(bits_per_sample),
25   - pos(0)
  22 + p_next(getNext())
26 23 {
27 24 if (samples_per_pixel < 1) {
28 25 throw std::runtime_error("TIFFPredictor created with invalid samples_per_pixel");
... ... @@ -35,71 +32,83 @@ Pl_TIFFPredictor::Pl_TIFFPredictor(
35 32 throw std::runtime_error("TIFFPredictor created with invalid columns value");
36 33 }
37 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 37 void
43 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 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 48 processRow();
54 49  
55 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 57 void
67 58 Pl_TIFFPredictor::processRow()
68 59 {
69 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 104 void
96 105 Pl_TIFFPredictor::finish()
97 106 {
98   - if (this->pos) {
  107 + if (!cur_row.empty()) {
99 108 // write partial row
  109 + cur_row.insert(cur_row.end(), bytes_per_row - cur_row.size(), 0);
100 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  
7 7 #include <qpdf/Pipeline.hh>
8 8  
  9 +#include<vector>
  10 +
9 11 class Pl_TIFFPredictor: public Pipeline
10 12 {
11 13 public:
... ... @@ -31,8 +33,10 @@ class Pl_TIFFPredictor: public Pipeline
31 33 unsigned int bytes_per_row;
32 34 unsigned int samples_per_pixel;
33 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 42 #endif // PL_TIFFPREDICTOR_HH
... ...