Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpdf_sampledfunc.cpp
Go to the documentation of this file.
1// Copyright 2017 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "core/fpdfapi/page/cpdf_sampledfunc.h"
8
9#include <algorithm>
10#include <utility>
11
12#include "core/fpdfapi/parser/cpdf_array.h"
13#include "core/fpdfapi/parser/cpdf_dictionary.h"
14#include "core/fpdfapi/parser/cpdf_stream.h"
15#include "core/fpdfapi/parser/cpdf_stream_acc.h"
16#include "core/fxcrt/cfx_bitstream.h"
17#include "core/fxcrt/fx_memory_wrappers.h"
18#include "core/fxcrt/fx_safe_types.h"
19#include "third_party/abseil-cpp/absl/container/inlined_vector.h"
20
21namespace {
22
23// See PDF Reference 1.7, page 170, table 3.36.
24bool IsValidBitsPerSample(uint32_t x) {
25 switch (x) {
26 case 1:
27 case 2:
28 case 4:
29 case 8:
30 case 12:
31 case 16:
32 case 24:
33 case 32:
34 return true;
35 default:
36 return false;
37 }
38}
39
40} // namespace
41
43
44CPDF_SampledFunc::~CPDF_SampledFunc() = default;
45
46bool CPDF_SampledFunc::v_Init(const CPDF_Object* pObj, VisitedSet* pVisited) {
47 RetainPtr<const CPDF_Stream> pStream(pObj->AsStream());
48 if (!pStream)
49 return false;
50
51 RetainPtr<const CPDF_Dictionary> pDict = pStream->GetDict();
52 RetainPtr<const CPDF_Array> pSize = pDict->GetArrayFor("Size");
53 if (!pSize || pSize->IsEmpty())
54 return false;
55
56 m_nBitsPerSample = pDict->GetIntegerFor("BitsPerSample");
57 if (!IsValidBitsPerSample(m_nBitsPerSample))
58 return false;
59
60 FX_SAFE_UINT32 nTotalSampleBits = m_nBitsPerSample;
61 nTotalSampleBits *= m_nOutputs;
62 RetainPtr<const CPDF_Array> pEncode = pDict->GetArrayFor("Encode");
63 m_EncodeInfo.resize(m_nInputs);
64 for (uint32_t i = 0; i < m_nInputs; i++) {
65 int size = pSize->GetIntegerAt(i);
66 if (size <= 0)
67 return false;
68
69 m_EncodeInfo[i].sizes = size;
70 nTotalSampleBits *= m_EncodeInfo[i].sizes;
71 if (pEncode) {
72 m_EncodeInfo[i].encode_min = pEncode->GetFloatAt(i * 2);
73 m_EncodeInfo[i].encode_max = pEncode->GetFloatAt(i * 2 + 1);
74 } else {
75 m_EncodeInfo[i].encode_min = 0;
76 m_EncodeInfo[i].encode_max =
77 m_EncodeInfo[i].sizes == 1 ? 1 : m_EncodeInfo[i].sizes - 1;
78 }
79 }
80 FX_SAFE_UINT32 nTotalSampleBytes = (nTotalSampleBits + 7) / 8;
81 if (!nTotalSampleBytes.IsValid() || nTotalSampleBytes.ValueOrDie() == 0)
82 return false;
83
84 m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample);
85 m_pSampleStream = pdfium::MakeRetain<CPDF_StreamAcc>(std::move(pStream));
86 m_pSampleStream->LoadAllDataFiltered();
87 if (nTotalSampleBytes.ValueOrDie() > m_pSampleStream->GetSize())
88 return false;
89
90 RetainPtr<const CPDF_Array> pDecode = pDict->GetArrayFor("Decode");
91 m_DecodeInfo.resize(m_nOutputs);
92 for (uint32_t i = 0; i < m_nOutputs; i++) {
93 if (pDecode) {
94 m_DecodeInfo[i].decode_min = pDecode->GetFloatAt(2 * i);
95 m_DecodeInfo[i].decode_max = pDecode->GetFloatAt(2 * i + 1);
96 } else {
97 m_DecodeInfo[i].decode_min = m_Ranges[i * 2];
98 m_DecodeInfo[i].decode_max = m_Ranges[i * 2 + 1];
99 }
100 }
101 return true;
102}
103
104bool CPDF_SampledFunc::v_Call(pdfium::span<const float> inputs,
105 pdfium::span<float> results) const {
106 int pos = 0;
107 absl::InlinedVector<float, 16, FxAllocAllocator<float>> encoded_input_buf(
108 m_nInputs);
109 absl::InlinedVector<uint32_t, 32, FxAllocAllocator<uint32_t>> int_buf(
110 m_nInputs * 2);
111 float* encoded_input = encoded_input_buf.data();
112 uint32_t* index = int_buf.data();
113 uint32_t* blocksize = index + m_nInputs;
114 for (uint32_t i = 0; i < m_nInputs; i++) {
115 if (i == 0)
116 blocksize[i] = 1;
117 else
118 blocksize[i] = blocksize[i - 1] * m_EncodeInfo[i - 1].sizes;
119 encoded_input[i] =
120 Interpolate(inputs[i], m_Domains[i * 2], m_Domains[i * 2 + 1],
121 m_EncodeInfo[i].encode_min, m_EncodeInfo[i].encode_max);
122 index[i] = std::clamp(static_cast<uint32_t>(encoded_input[i]), 0U,
123 m_EncodeInfo[i].sizes - 1);
124 pos += index[i] * blocksize[i];
125 }
126 FX_SAFE_INT32 bits_to_output = m_nOutputs;
127 bits_to_output *= m_nBitsPerSample;
128 if (!bits_to_output.IsValid())
129 return false;
130
131 int bits_to_skip;
132 {
133 FX_SAFE_INT32 bitpos = pos;
134 bitpos *= bits_to_output.ValueOrDie();
135 bits_to_skip = bitpos.ValueOrDefault(-1);
136 if (bits_to_skip < 0)
137 return false;
138
139 FX_SAFE_INT32 range_check = bitpos;
140 range_check += bits_to_output.ValueOrDie();
141 if (!range_check.IsValid())
142 return false;
143 }
144
145 pdfium::span<const uint8_t> pSampleData = m_pSampleStream->GetSpan();
146 if (pSampleData.empty())
147 return false;
148
149 CFX_BitStream bitstream(pSampleData);
150 bitstream.SkipBits(bits_to_skip);
151 for (uint32_t i = 0; i < m_nOutputs; ++i) {
152 uint32_t sample = bitstream.GetBits(m_nBitsPerSample);
153 float encoded = sample;
154 for (uint32_t j = 0; j < m_nInputs; ++j) {
155 if (index[j] == m_EncodeInfo[j].sizes - 1) {
156 if (index[j] == 0)
157 encoded = encoded_input[j] * sample;
158 } else {
159 FX_SAFE_INT32 bitpos2 = blocksize[j];
160 bitpos2 += pos;
161 bitpos2 *= m_nOutputs;
162 bitpos2 += i;
163 bitpos2 *= m_nBitsPerSample;
164 int bits_to_skip2 = bitpos2.ValueOrDefault(-1);
165 if (bits_to_skip2 < 0)
166 return false;
167
168 CFX_BitStream bitstream2(pSampleData);
169 bitstream2.SkipBits(bits_to_skip2);
170 float sample2 =
171 static_cast<float>(bitstream2.GetBits(m_nBitsPerSample));
172 encoded += (encoded_input[j] - index[j]) * (sample2 - sample);
173 }
174 }
175 results[i] =
176 Interpolate(encoded, 0, m_SampleMax, m_DecodeInfo[i].decode_min,
177 m_DecodeInfo[i].decode_max);
178 }
179 return true;
180}
181
182#if defined(PDF_USE_SKIA)
183RetainPtr<CPDF_StreamAcc> CPDF_SampledFunc::GetSampleStream() const {
184 return m_pSampleStream;
185}
186#endif
uint32_t GetBits(uint32_t nBits)
uint32_t m_nOutputs
uint32_t m_nInputs
CPDF_Function(Type type)
bool v_Call(pdfium::span< const float > inputs, pdfium::span< float > results) const override
~CPDF_SampledFunc() override
bool v_Init(const CPDF_Object *pObj, VisitedSet *pVisited) override