diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/fxge/dib/cfx_imagetransformer.cpp | 209 |
1 files changed, 92 insertions, 117 deletions
diff --git a/core/fxge/dib/cfx_imagetransformer.cpp b/core/fxge/dib/cfx_imagetransformer.cpp index e7f60c4991..6fd25689d8 100644 --- a/core/fxge/dib/cfx_imagetransformer.cpp +++ b/core/fxge/dib/cfx_imagetransformer.cpp @@ -15,6 +15,9 @@ namespace { +constexpr int kBase = 256; +constexpr float kFix16 = 0.05f; + uint8_t bilinear_interpol(const uint8_t* buf, int row_offset_l, int row_offset_r, @@ -51,8 +54,9 @@ uint8_t bicubic_interpol(const uint8_t* buf, for (int i = 0; i < 4; i++) { int a_result = 0; for (int j = 0; j < 4; j++) { - a_result += u_w[j] * (*(uint8_t*)(buf + pos_pixel[i + 4] * pitch + - pos_pixel[j] * bpp + c_offset)); + uint8_t val = + *(buf + pos_pixel[i + 4] * pitch + pos_pixel[j] * bpp + c_offset); + a_result += u_w[j] * val; } s_result += a_result * v_w[i]; } @@ -78,18 +82,8 @@ void bicubic_get_pos_weight(int pos_pixel[], pos_pixel[6] = src_row_l + 1; pos_pixel[7] = src_row_l + 2; for (int i = 0; i < 4; i++) { - if (pos_pixel[i] < 0) { - pos_pixel[i] = 0; - } - if (pos_pixel[i] >= stretch_width) { - pos_pixel[i] = stretch_width - 1; - } - if (pos_pixel[i + 4] < 0) { - pos_pixel[i + 4] = 0; - } - if (pos_pixel[i + 4] >= stretch_height) { - pos_pixel[i + 4] = stretch_height - 1; - } + pos_pixel[i] = pdfium::clamp(pos_pixel[i], 0, stretch_width - 1); + pos_pixel[i + 4] = pdfium::clamp(pos_pixel[i + 4], 0, stretch_height - 1); } u_w[0] = SDP_Table[256 + res_x]; u_w[1] = SDP_Table[res_x]; @@ -102,79 +96,83 @@ void bicubic_get_pos_weight(int pos_pixel[], } FXDIB_Format GetTransformedFormat(const RetainPtr<CFX_DIBSource>& pDrc) { + if (pDrc->IsAlphaMask()) + return FXDIB_8bppMask; + FXDIB_Format format = pDrc->GetFormat(); - if (pDrc->IsAlphaMask()) { - format = FXDIB_8bppMask; - } else if (format >= 1025) { - format = FXDIB_Cmyka; - } else if (format <= 32 || format == FXDIB_Argb) { - format = FXDIB_Argb; + if (format >= 1025) + return FXDIB_Cmyka; + if (format <= 32 || format == FXDIB_Argb) + return FXDIB_Argb; + return FXDIB_Rgba; +} + +void WriteMonoResult(uint32_t r_bgra_cmyk, FXDIB_Format format, uint8_t* dest) { + if (format == FXDIB_Rgba) { + dest[0] = static_cast<uint8_t>(r_bgra_cmyk >> 24); + dest[1] = static_cast<uint8_t>(r_bgra_cmyk >> 16); + dest[2] = static_cast<uint8_t>(r_bgra_cmyk >> 8); } else { - format = FXDIB_Rgba; + *reinterpret_cast<uint32_t*>(dest) = r_bgra_cmyk; } - return format; } class CPDF_FixedMatrix { public: - CPDF_FixedMatrix(const CFX_Matrix& src, int bits) { - base = 1 << bits; - a = FXSYS_round(src.a * base); - b = FXSYS_round(src.b * base); - c = FXSYS_round(src.c * base); - d = FXSYS_round(src.d * base); - e = FXSYS_round(src.e * base); - f = FXSYS_round(src.f * base); - } - - void Transform(int x, int y, int* x1, int* y1) { - *x1 = (a * x + c * y + e + base / 2) / base; - *y1 = (b * x + d * y + f + base / 2) / base; + explicit CPDF_FixedMatrix(const CFX_Matrix& src) + : a(FXSYS_round(src.a * kBase)), + b(FXSYS_round(src.b * kBase)), + c(FXSYS_round(src.c * kBase)), + d(FXSYS_round(src.d * kBase)), + e(FXSYS_round(src.e * kBase)), + f(FXSYS_round(src.f * kBase)) {} + + void Transform(int x, int y, int* x1, int* y1) const { + *x1 = (a * x + c * y + e + kBase / 2) / kBase; + *y1 = (b * x + d * y + f + kBase / 2) / kBase; } - int a; - int b; - int c; - int d; - int e; - int f; - int base; + protected: + const int a; + const int b; + const int c; + const int d; + const int e; + const int f; }; class CFX_BilinearMatrix : public CPDF_FixedMatrix { public: - CFX_BilinearMatrix(const CFX_Matrix& src, int bits) - : CPDF_FixedMatrix(src, bits) {} - void Transform(int x, int y, int* x1, int* y1, int* res_x, int* res_y) { + explicit CFX_BilinearMatrix(const CFX_Matrix& src) : CPDF_FixedMatrix(src) {} + + void Transform(int x, int y, int* x1, int* y1, int* res_x, int* res_y) const { pdfium::base::CheckedNumeric<int> val = a; pdfium::base::CheckedNumeric<int> val2 = c; val *= x; val2 *= y; - val += val2 + e + (base >> 1); + val += val2 + e + (kBase / 2); *x1 = val.ValueOrDefault(0); val = b; val2 = d; val *= x; val2 *= y; - val += val2 + f + (base >> 1); + val += val2 + f + (kBase / 2); *y1 = val.ValueOrDefault(0); - *res_x = *x1 % base; - *res_y = *y1 % base; + *res_x = *x1 % kBase; + *res_y = *y1 % kBase; - if (*res_x < 0 && *res_x > -base) - *res_x = base + *res_x; - if (*res_y < 0 && *res_x > -base) - *res_y = base + *res_y; + if (*res_x < 0 && *res_x > -kBase) + *res_x = kBase + *res_x; + if (*res_y < 0 && *res_x > -kBase) + *res_y = kBase + *res_y; - *x1 /= base; - *y1 /= base; + *x1 /= kBase; + *y1 /= kBase; } }; -#define FIX16_005 0.05f - } // namespace CFX_ImageTransformer::CFX_ImageTransformer(const RetainPtr<CFX_DIBSource>& pSrc, @@ -209,7 +207,7 @@ CFX_ImageTransformer::CFX_ImageTransformer(const RetainPtr<CFX_DIBSource>& pSrc, m_Status = 1; return; } - if (fabs(m_pMatrix->b) < FIX16_005 && fabs(m_pMatrix->c) < FIX16_005) { + if (fabs(m_pMatrix->b) < kFix16 && fabs(m_pMatrix->c) < kFix16) { int dest_width = static_cast<int>(m_pMatrix->a > 0 ? ceil(m_pMatrix->a) : floor(m_pMatrix->a)); int dest_height = static_cast<int>(m_pMatrix->d > 0 ? -ceil(m_pMatrix->d) @@ -265,28 +263,28 @@ bool CFX_ImageTransformer::Continue(IFX_PauseIndicator* pPause) { if (!m_Storer.GetBitmap()) return false; - const uint8_t* stretch_buf_mask = nullptr; - if (m_Storer.GetBitmap()->m_pAlphaMask) - stretch_buf_mask = m_Storer.GetBitmap()->m_pAlphaMask->GetBuffer(); - auto pTransformed = pdfium::MakeRetain<CFX_DIBitmap>(); - FXDIB_Format transformF = GetTransformedFormat(m_Stretcher->source()); - if (!pTransformed->Create(m_result.Width(), m_result.Height(), transformF)) + FXDIB_Format format = GetTransformedFormat(m_Stretcher->source()); + if (!pTransformed->Create(m_result.Width(), m_result.Height(), format)) return false; + const auto& pSrcMask = m_Storer.GetBitmap()->m_pAlphaMask; + const uint8_t* pSrcMaskBuf = pSrcMask ? pSrcMask->GetBuffer() : nullptr; + pTransformed->Clear(0); - if (pTransformed->m_pAlphaMask) - pTransformed->m_pAlphaMask->Clear(0); + auto& pDestMask = pTransformed->m_pAlphaMask; + if (pDestMask) + pDestMask->Clear(0); - CFX_Matrix result2stretch(1.0f, 0.0f, 0.0f, 1.0f, (float)(m_result.left), - (float)(m_result.top)); + CFX_Matrix result2stretch(1.0f, 0.0f, 0.0f, 1.0f, m_result.left, + m_result.top); result2stretch.Concat(m_dest2stretch); result2stretch.Translate(-m_StretchClip.left, -m_StretchClip.top); - if (!stretch_buf_mask && pTransformed->m_pAlphaMask) { - pTransformed->m_pAlphaMask->Clear(0xff000000); - } else if (pTransformed->m_pAlphaMask) { + if (!pSrcMaskBuf && pDestMask) { + pDestMask->Clear(0xff000000); + } else if (pDestMask) { CalcData cdata = { - pTransformed->m_pAlphaMask.Get(), result2stretch, stretch_buf_mask, + pDestMask.Get(), result2stretch, pSrcMaskBuf, m_Storer.GetBitmap()->m_pAlphaMask->GetPitch(), }; CalcMask(cdata); @@ -300,14 +298,14 @@ bool CFX_ImageTransformer::Continue(IFX_PauseIndicator* pPause) { } else { int Bpp = m_Storer.GetBitmap()->GetBPP() / 8; if (Bpp == 1) { - CalcMono(cdata, transformF); + CalcMono(cdata, format); } else { if (IsBilinear()) - CalcColorBilinear(cdata, transformF, Bpp); + CalcColorBilinear(cdata, format, Bpp); else if (IsBiCubic()) - CalcColorBicubic(cdata, transformF, Bpp); + CalcColorBicubic(cdata, format, Bpp); else - CalcColorDownSample(cdata, transformF, Bpp); + CalcColorDownSample(cdata, format, Bpp); } } m_Storer.Replace(std::move(pTransformed)); @@ -369,19 +367,14 @@ void CFX_ImageTransformer::CalcMono(const CalcData& cdata, uint32_t argb[256]; FX_ARGB* pPal = m_Storer.GetBitmap()->GetPalette(); if (pPal) { - for (int i = 0; i < 256; i++) { + for (size_t i = 0; i < FX_ArraySize(argb); i++) argb[i] = pPal[i]; - } + } else if (m_Storer.GetBitmap()->IsCmykImage()) { + for (size_t i = 0; i < FX_ArraySize(argb); i++) + argb[i] = 255 - i; } else { - if (m_Storer.GetBitmap()->IsCmykImage()) { - for (int i = 0; i < 256; i++) { - argb[i] = 255 - i; - } - } else { - for (int i = 0; i < 256; i++) { - argb[i] = 0xff000000 | (i * 0x010101); - } - } + for (size_t i = 0; i < FX_ArraySize(argb); i++) + argb[i] = 0xff000000 | (i * 0x010101); } int destBpp = cdata.bitmap->GetBPP() / 8; if (IsBilinear()) { @@ -391,13 +384,7 @@ void CFX_ImageTransformer::CalcMono(const CalcData& cdata, cdata.buf, data.row_offset_l, data.row_offset_r, data.src_col_l, data.src_col_r, data.res_x, data.res_y, 1, 0); uint32_t r_bgra_cmyk = argb[idx]; - if (format == FXDIB_Rgba) { - dest[0] = (uint8_t)(r_bgra_cmyk >> 24); - dest[1] = (uint8_t)(r_bgra_cmyk >> 16); - dest[2] = (uint8_t)(r_bgra_cmyk >> 8); - } else { - *(uint32_t*)dest = r_bgra_cmyk; - } + WriteMonoResult(r_bgra_cmyk, format, dest); }; DoBilinearLoop(cdata, destBpp, func); } else if (IsBiCubic()) { @@ -406,13 +393,7 @@ void CFX_ImageTransformer::CalcMono(const CalcData& cdata, uint32_t r_bgra_cmyk = argb[bicubic_interpol( cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, data.v_w, data.res_x, data.res_y, 1, 0)]; - if (format == FXDIB_Rgba) { - dest[0] = (uint8_t)(r_bgra_cmyk >> 24); - dest[1] = (uint8_t)(r_bgra_cmyk >> 16); - dest[2] = (uint8_t)(r_bgra_cmyk >> 8); - } else { - *(uint32_t*)dest = r_bgra_cmyk; - } + WriteMonoResult(r_bgra_cmyk, format, dest); }; DoBicubicLoop(cdata, destBpp, func); } else { @@ -420,13 +401,7 @@ void CFX_ImageTransformer::CalcMono(const CalcData& cdata, uint8_t* dest) { uint32_t r_bgra_cmyk = argb[cdata.buf[data.src_row * cdata.pitch + data.src_col]]; - if (format == FXDIB_Rgba) { - dest[0] = (uint8_t)(r_bgra_cmyk >> 24); - dest[1] = (uint8_t)(r_bgra_cmyk >> 16); - dest[2] = (uint8_t)(r_bgra_cmyk >> 8); - } else { - *(uint32_t*)dest = r_bgra_cmyk; - } + WriteMonoResult(r_bgra_cmyk, format, dest); }; DoDownSampleLoop(cdata, destBpp, func); } @@ -447,7 +422,7 @@ void CFX_ImageTransformer::CalcColorBilinear(const CalcData& cdata, uint8_t r_pos_blue_c_r = bilinear_interpol( cdata.buf, data.row_offset_l, data.row_offset_r, data.src_col_l, data.src_col_r, data.res_x, data.res_y, Bpp, 0); - uint32_t* dest32 = (uint32_t*)dest; + uint32_t* dest32 = reinterpret_cast<uint32_t*>(dest); if (bHasAlpha) { if (format != FXDIB_Argb) { if (format == FXDIB_Rgba) { @@ -502,7 +477,7 @@ void CFX_ImageTransformer::CalcColorBicubic(const CalcData& cdata, uint8_t r_pos_blue_c_r = bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, data.v_w, data.res_x, data.res_y, Bpp, 0); - uint32_t* dest32 = (uint32_t*)dest; + uint32_t* dest32 = reinterpret_cast<uint32_t*>(dest); if (bHasAlpha) { if (format != FXDIB_Argb) { if (format == FXDIB_Rgba) { @@ -550,7 +525,7 @@ void CFX_ImageTransformer::CalcColorDownSample(const CalcData& cdata, uint8_t* dest) { const uint8_t* src_pos = cdata.buf + data.src_row * cdata.pitch + data.src_col * Bpp; - uint32_t* dest32 = (uint32_t*)dest; + uint32_t* dest32 = reinterpret_cast<uint32_t*>(dest); if (bHasAlpha) { if (format != FXDIB_Argb) { if (format == FXDIB_Rgba) { @@ -593,9 +568,9 @@ void CFX_ImageTransformer::DoBilinearLoop( const CalcData& cdata, int increment, std::function<void(const BilinearData&, uint8_t*)> func) { - CFX_BilinearMatrix matrix_fix(cdata.matrix, 8); + CFX_BilinearMatrix matrix_fix(cdata.matrix); for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest = (uint8_t*)cdata.bitmap->GetScanline(row); + uint8_t* dest = const_cast<uint8_t*>(cdata.bitmap->GetScanline(row)); for (int col = 0; col < m_result.Width(); col++) { BilinearData d; d.res_x = 0; @@ -622,9 +597,9 @@ void CFX_ImageTransformer::DoBicubicLoop( const CalcData& cdata, int increment, std::function<void(const BicubicData&, uint8_t*)> func) { - CFX_BilinearMatrix matrix_fix(cdata.matrix, 8); + CFX_BilinearMatrix matrix_fix(cdata.matrix); for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest = (uint8_t*)cdata.bitmap->GetScanline(row); + uint8_t* dest = const_cast<uint8_t*>(cdata.bitmap->GetScanline(row)); for (int col = 0; col < m_result.Width(); col++) { BicubicData d; d.res_x = 0; @@ -649,9 +624,9 @@ void CFX_ImageTransformer::DoDownSampleLoop( const CalcData& cdata, int increment, std::function<void(const DownSampleData&, uint8_t*)> func) { - CPDF_FixedMatrix matrix_fix(cdata.matrix, 8); + CPDF_FixedMatrix matrix_fix(cdata.matrix); for (int row = 0; row < m_result.Height(); row++) { - uint8_t* dest = (uint8_t*)cdata.bitmap->GetScanline(row); + uint8_t* dest = const_cast<uint8_t*>(cdata.bitmap->GetScanline(row)); for (int col = 0; col < m_result.Width(); col++) { DownSampleData d; d.src_col = 0; |