1d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Copyright 2017 PDFium Authors. All rights reserved. 2d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Use of this source code is governed by a BSD-style license that can be 3d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// found in the LICENSE file. 4d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 5d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 7d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fpdfapi/page/cpdf_sampledfunc.h" 8d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 9d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fpdfapi/parser/cpdf_array.h" 10d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcrt/cfx_fixedbufgrow.h" 11d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcrt/fx_extension.h" 12d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcrt/fx_safe_types.h" 13d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 14d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannnamespace { 15d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 16d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann// See PDF Reference 1.7, page 170, table 3.36. 17d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool IsValidBitsPerSample(uint32_t x) { 18d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann switch (x) { 19d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann case 1: 20d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann case 2: 21d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann case 4: 22d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann case 8: 23d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann case 12: 24d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann case 16: 25d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann case 24: 26d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann case 32: 27d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return true; 28d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann default: 29d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return false; 30d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 31d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann} 32d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 33d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann} // namespace 34d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 35d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) {} 36d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 37d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_SampledFunc::~CPDF_SampledFunc() {} 38d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 39d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool CPDF_SampledFunc::v_Init(CPDF_Object* pObj) { 40d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Stream* pStream = pObj->AsStream(); 41d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!pStream) 42d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return false; 43d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 44d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Dictionary* pDict = pStream->GetDict(); 45d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Array* pSize = pDict->GetArrayFor("Size"); 46d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Array* pEncode = pDict->GetArrayFor("Encode"); 47d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Array* pDecode = pDict->GetArrayFor("Decode"); 48d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_nBitsPerSample = pDict->GetIntegerFor("BitsPerSample"); 49d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!IsValidBitsPerSample(m_nBitsPerSample)) 50d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return false; 51d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 52d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_SampleMax = 0xffffffff >> (32 - m_nBitsPerSample); 53d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_pSampleStream = pdfium::MakeRetain<CPDF_StreamAcc>(pStream); 54d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_pSampleStream->LoadAllDataFiltered(); 55d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann FX_SAFE_UINT32 nTotalSampleBits = 1; 56d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo.resize(m_nInputs); 57d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann for (uint32_t i = 0; i < m_nInputs; i++) { 58d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo[i].sizes = pSize ? pSize->GetIntegerAt(i) : 0; 59d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!pSize && i == 0) 60d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo[i].sizes = pDict->GetIntegerFor("Size"); 61d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann nTotalSampleBits *= m_EncodeInfo[i].sizes; 62d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (pEncode) { 63d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo[i].encode_min = pEncode->GetFloatAt(i * 2); 64d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo[i].encode_max = pEncode->GetFloatAt(i * 2 + 1); 65d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } else { 66d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo[i].encode_min = 0; 67d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo[i].encode_max = 68d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo[i].sizes == 1 ? 1 : (float)m_EncodeInfo[i].sizes - 1; 69d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 70d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 71d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann nTotalSampleBits *= m_nBitsPerSample; 72d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann nTotalSampleBits *= m_nOutputs; 73d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann FX_SAFE_UINT32 nTotalSampleBytes = nTotalSampleBits; 74d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann nTotalSampleBytes += 7; 75d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann nTotalSampleBytes /= 8; 76d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!nTotalSampleBytes.IsValid() || nTotalSampleBytes.ValueOrDie() == 0 || 77d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann nTotalSampleBytes.ValueOrDie() > m_pSampleStream->GetSize()) { 78d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return false; 79d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 80d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_DecodeInfo.resize(m_nOutputs); 81d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann for (uint32_t i = 0; i < m_nOutputs; i++) { 82d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (pDecode) { 83d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_DecodeInfo[i].decode_min = pDecode->GetFloatAt(2 * i); 84d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_DecodeInfo[i].decode_max = pDecode->GetFloatAt(2 * i + 1); 85d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } else { 86d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_DecodeInfo[i].decode_min = m_pRanges[i * 2]; 87d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_DecodeInfo[i].decode_max = m_pRanges[i * 2 + 1]; 88d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 89d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 90d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return true; 91d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann} 92d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 93d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannbool CPDF_SampledFunc::v_Call(float* inputs, float* results) const { 94d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann int pos = 0; 95d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CFX_FixedBufGrow<float, 16> encoded_input_buf(m_nInputs); 96d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann float* encoded_input = encoded_input_buf; 97d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CFX_FixedBufGrow<uint32_t, 32> int_buf(m_nInputs * 2); 98d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann uint32_t* index = int_buf; 99d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann uint32_t* blocksize = index + m_nInputs; 100d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann for (uint32_t i = 0; i < m_nInputs; i++) { 101d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (i == 0) 102d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann blocksize[i] = 1; 103d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann else 104d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann blocksize[i] = blocksize[i - 1] * m_EncodeInfo[i - 1].sizes; 105d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann encoded_input[i] = 106d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann Interpolate(inputs[i], m_pDomains[i * 2], m_pDomains[i * 2 + 1], 107d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo[i].encode_min, m_EncodeInfo[i].encode_max); 108d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann index[i] = pdfium::clamp(static_cast<uint32_t>(encoded_input[i]), 0U, 109d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_EncodeInfo[i].sizes - 1); 110d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann pos += index[i] * blocksize[i]; 111d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 112d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann FX_SAFE_INT32 bits_to_output = m_nOutputs; 113d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann bits_to_output *= m_nBitsPerSample; 114d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!bits_to_output.IsValid()) 115d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return false; 116d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 117d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann FX_SAFE_INT32 bitpos = pos; 118d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann bitpos *= bits_to_output.ValueOrDie(); 119d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!bitpos.IsValid()) 120d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return false; 121d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 122d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann FX_SAFE_INT32 range_check = bitpos; 123d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann range_check += bits_to_output.ValueOrDie(); 124d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!range_check.IsValid()) 125d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return false; 126d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 127d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann const uint8_t* pSampleData = m_pSampleStream->GetData(); 128d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!pSampleData) 129d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return false; 130d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 131d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann for (uint32_t j = 0; j < m_nOutputs; j++, bitpos += m_nBitsPerSample) { 132d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann uint32_t sample = 133d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann GetBits32(pSampleData, bitpos.ValueOrDie(), m_nBitsPerSample); 134d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann float encoded = (float)sample; 135d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann for (uint32_t i = 0; i < m_nInputs; i++) { 136d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (index[i] == m_EncodeInfo[i].sizes - 1) { 137d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (index[i] == 0) 138d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann encoded = encoded_input[i] * (float)sample; 139d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } else { 140d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann FX_SAFE_INT32 bitpos2 = blocksize[i]; 141d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann bitpos2 += pos; 142d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann bitpos2 *= m_nOutputs; 143d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann bitpos2 += j; 144d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann bitpos2 *= m_nBitsPerSample; 145d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!bitpos2.IsValid()) 146d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return false; 147d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann uint32_t sample1 = 148d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann GetBits32(pSampleData, bitpos2.ValueOrDie(), m_nBitsPerSample); 149d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann encoded += 150d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann (encoded_input[i] - index[i]) * ((float)sample1 - (float)sample); 151d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 152d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 153d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann results[j] = 154d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann Interpolate(encoded, 0, (float)m_SampleMax, m_DecodeInfo[j].decode_min, 155d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_DecodeInfo[j].decode_max); 156d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 157d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return true; 158d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann} 159