diff options
-rw-r--r-- | core/fxge/dib/cfx_imagetransformer.cpp | 227 | ||||
-rw-r--r-- | core/fxge/dib/cfx_imagetransformer.h | 4 |
2 files changed, 75 insertions, 156 deletions
diff --git a/core/fxge/dib/cfx_imagetransformer.cpp b/core/fxge/dib/cfx_imagetransformer.cpp index 6fd25689d8..1904c3a0d6 100644 --- a/core/fxge/dib/cfx_imagetransformer.cpp +++ b/core/fxge/dib/cfx_imagetransformer.cpp @@ -17,6 +17,7 @@ namespace { constexpr int kBase = 256; constexpr float kFix16 = 0.05f; +constexpr uint8_t kOpaqueAlpha = 0xff; uint8_t bilinear_interpol(const uint8_t* buf, int row_offset_l, @@ -107,6 +108,10 @@ FXDIB_Format GetTransformedFormat(const RetainPtr<CFX_DIBSource>& pDrc) { return FXDIB_Rgba; } +bool NeedAlpha(bool bHasAlpha, FXDIB_Format format) { + return bHasAlpha || format == FXDIB_Cmyka; +} + 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); @@ -117,6 +122,37 @@ void WriteMonoResult(uint32_t r_bgra_cmyk, FXDIB_Format format, uint8_t* dest) { } } +void WriteColorResult(std::function<uint8_t(int offset)> func, + bool bHasAlpha, + FXDIB_Format format, + uint8_t* dest) { + uint8_t blue_c = func(0); + uint8_t green_m = func(1); + uint8_t red_y = func(2); + uint8_t alpha_k = NeedAlpha(bHasAlpha, format) ? func(3) : kOpaqueAlpha; + + uint32_t* dest32 = reinterpret_cast<uint32_t*>(dest); + if (bHasAlpha) { + if (format == FXDIB_Argb) { + *dest32 = FXARGB_TODIB(FXARGB_MAKE(alpha_k, red_y, green_m, blue_c)); + } else if (format == FXDIB_Rgba) { + dest[0] = blue_c; + dest[1] = green_m; + dest[2] = red_y; + } else { + *dest32 = FXCMYK_TODIB(CmykEncode(blue_c, green_m, red_y, alpha_k)); + } + return; + } + + if (format == FXDIB_Cmyka) { + *dest32 = FXCMYK_TODIB(CmykEncode(blue_c, green_m, red_y, alpha_k)); + } else { + ASSERT(alpha_k == kOpaqueAlpha); + *dest32 = FXARGB_TODIB(FXARGB_MAKE(kOpaqueAlpha, red_y, green_m, blue_c)); + } +} + class CPDF_FixedMatrix { public: explicit CPDF_FixedMatrix(const CFX_Matrix& src) @@ -297,16 +333,10 @@ bool CFX_ImageTransformer::Continue(IFX_PauseIndicator* pPause) { CalcAlpha(cdata); } else { int Bpp = m_Storer.GetBitmap()->GetBPP() / 8; - if (Bpp == 1) { + if (Bpp == 1) CalcMono(cdata, format); - } else { - if (IsBilinear()) - CalcColorBilinear(cdata, format, Bpp); - else if (IsBiCubic()) - CalcColorBicubic(cdata, format, Bpp); - else - CalcColorDownSample(cdata, format, Bpp); - } + else + CalcColor(cdata, format, Bpp); } m_Storer.Replace(std::move(pTransformed)); return false; @@ -407,152 +437,43 @@ void CFX_ImageTransformer::CalcMono(const CalcData& cdata, } } -void CFX_ImageTransformer::CalcColorBilinear(const CalcData& cdata, - FXDIB_Format format, - int Bpp) { +void CFX_ImageTransformer::CalcColor(const CalcData& cdata, + FXDIB_Format format, + int Bpp) { bool bHasAlpha = m_Storer.GetBitmap()->HasAlpha(); - auto func = [&cdata, format, Bpp, bHasAlpha](const BilinearData& data, - uint8_t* dest) { - uint8_t r_pos_red_y_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, 2); - uint8_t r_pos_green_m_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, 1); - 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 = reinterpret_cast<uint32_t*>(dest); - if (bHasAlpha) { - if (format != FXDIB_Argb) { - if (format == FXDIB_Rgba) { - dest[0] = r_pos_blue_c_r; - dest[1] = r_pos_green_m_r; - dest[2] = r_pos_red_y_r; - } else { - uint8_t r_pos_k_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, 3); - *dest32 = FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r, - r_pos_red_y_r, r_pos_k_r)); - } - } else { - uint8_t r_pos_a_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, 3); - *dest32 = FXARGB_TODIB(FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, - r_pos_green_m_r, r_pos_blue_c_r)); - } - } else { - if (format == FXDIB_Cmyka) { - uint8_t r_pos_k_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, 3); - *dest32 = FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r, - r_pos_red_y_r, r_pos_k_r)); - } else { - uint8_t r_pos_k_r = 0xff; - *dest32 = FXARGB_TODIB(FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, - r_pos_green_m_r, r_pos_blue_c_r)); - } - } - }; - int destBpp = cdata.bitmap->GetBPP() / 8; - DoBilinearLoop(cdata, destBpp, func); -} - -void CFX_ImageTransformer::CalcColorBicubic(const CalcData& cdata, - FXDIB_Format format, - int Bpp) { - bool bHasAlpha = m_Storer.GetBitmap()->HasAlpha(); - auto func = [&cdata, format, Bpp, bHasAlpha](const BicubicData& data, - uint8_t* dest) { - uint8_t r_pos_red_y_r = - bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, - data.v_w, data.res_x, data.res_y, Bpp, 2); - uint8_t r_pos_green_m_r = - bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, - data.v_w, data.res_x, data.res_y, Bpp, 1); - 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 = reinterpret_cast<uint32_t*>(dest); - if (bHasAlpha) { - if (format != FXDIB_Argb) { - if (format == FXDIB_Rgba) { - dest[0] = r_pos_blue_c_r; - dest[1] = r_pos_green_m_r; - dest[2] = r_pos_red_y_r; - } else { - uint8_t r_pos_k_r = - bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, - data.v_w, data.res_x, data.res_y, Bpp, 3); - *dest32 = FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r, - r_pos_red_y_r, r_pos_k_r)); - } - } else { - uint8_t r_pos_a_r = - bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, - data.v_w, data.res_x, data.res_y, Bpp, 3); - *dest32 = FXARGB_TODIB(FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, - r_pos_green_m_r, r_pos_blue_c_r)); - } - } else { - if (format == FXDIB_Cmyka) { - uint8_t r_pos_k_r = - bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, data.u_w, - data.v_w, data.res_x, data.res_y, Bpp, 3); - *dest32 = FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r, - r_pos_red_y_r, r_pos_k_r)); - } else { - uint8_t r_pos_k_r = 0xff; - *dest32 = FXARGB_TODIB(FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, - r_pos_green_m_r, r_pos_blue_c_r)); - } - } - }; - - int destBpp = cdata.bitmap->GetBPP() / 8; - DoBicubicLoop(cdata, destBpp, func); -} - -void CFX_ImageTransformer::CalcColorDownSample(const CalcData& cdata, - FXDIB_Format format, - int Bpp) { - bool bHasAlpha = m_Storer.GetBitmap()->HasAlpha(); - auto func = [&cdata, format, bHasAlpha, Bpp](const DownSampleData& data, - uint8_t* dest) { - const uint8_t* src_pos = - cdata.buf + data.src_row * cdata.pitch + data.src_col * Bpp; - uint32_t* dest32 = reinterpret_cast<uint32_t*>(dest); - if (bHasAlpha) { - if (format != FXDIB_Argb) { - if (format == FXDIB_Rgba) { - dest[0] = src_pos[0]; - dest[1] = src_pos[1]; - dest[2] = src_pos[2]; - } else { - *dest32 = FXCMYK_TODIB( - CmykEncode(src_pos[0], src_pos[1], src_pos[2], src_pos[3])); - } - } else { - *dest32 = FXARGB_TODIB( - FXARGB_MAKE(src_pos[3], src_pos[2], src_pos[1], src_pos[0])); - } - } else { - if (format == FXDIB_Cmyka) { - *dest32 = FXCMYK_TODIB( - CmykEncode(src_pos[0], src_pos[1], src_pos[2], src_pos[3])); - } else { - *dest32 = - FXARGB_TODIB(FXARGB_MAKE(0xff, src_pos[2], src_pos[1], src_pos[0])); - } - } - }; - - int destBpp = cdata.bitmap->GetBPP() / 8; - DoDownSampleLoop(cdata, destBpp, func); + if (IsBilinear()) { + auto func = [&cdata, format, Bpp, bHasAlpha](const BilinearData& data, + uint8_t* dest) { + auto bilinear_interpol_func = [&cdata, &data, Bpp](int offset) { + return 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, offset); + }; + WriteColorResult(bilinear_interpol_func, bHasAlpha, format, dest); + }; + DoBilinearLoop(cdata, destBpp, func); + } else if (IsBiCubic()) { + auto func = [&cdata, format, Bpp, bHasAlpha](const BicubicData& data, + uint8_t* dest) { + auto bicubic_interpol_func = [&cdata, &data, Bpp](int offset) { + return bicubic_interpol(cdata.buf, cdata.pitch, data.pos_pixel, + data.u_w, data.v_w, data.res_x, data.res_y, Bpp, + offset); + }; + WriteColorResult(bicubic_interpol_func, bHasAlpha, format, dest); + }; + DoBicubicLoop(cdata, destBpp, func); + } else { + auto func = [&cdata, format, bHasAlpha, Bpp](const DownSampleData& data, + uint8_t* dest) { + const uint8_t* src_pos = + cdata.buf + data.src_row * cdata.pitch + data.src_col * Bpp; + auto sample_func = [src_pos](int offset) { return src_pos[offset]; }; + WriteColorResult(sample_func, bHasAlpha, format, dest); + }; + DoDownSampleLoop(cdata, destBpp, func); + } } void CFX_ImageTransformer::AdjustCoords(int* col, int* row) const { diff --git a/core/fxge/dib/cfx_imagetransformer.h b/core/fxge/dib/cfx_imagetransformer.h index 2a54ae1841..bf5e7dcfd4 100644 --- a/core/fxge/dib/cfx_imagetransformer.h +++ b/core/fxge/dib/cfx_imagetransformer.h @@ -70,9 +70,7 @@ class CFX_ImageTransformer { void CalcMask(const CalcData& cdata); void CalcAlpha(const CalcData& cdata); void CalcMono(const CalcData& cdata, FXDIB_Format format); - void CalcColorBilinear(const CalcData& cdata, FXDIB_Format format, int Bpp); - void CalcColorBicubic(const CalcData& cdata, FXDIB_Format format, int Bpp); - void CalcColorDownSample(const CalcData& cdata, FXDIB_Format format, int Bpp); + void CalcColor(const CalcData& cdata, FXDIB_Format format, int Bpp); bool IsBilinear() const { return !(m_Flags & FXDIB_DOWNSAMPLE) && !IsBiCubic(); |