5#include "core/fxge/dib/cfx_dibbase.h"
14#include "core/fxcrt/fx_2d_size.h"
15#include "core/fxcrt/fx_memory.h"
16#include "core/fxcrt/fx_memory_wrappers.h"
17#include "core/fxcrt/fx_safe_types.h"
18#include "core/fxcrt/retain_ptr.h"
19#include "core/fxge/calculate_pitch.h"
20#include "core/fxge/dib/cfx_dibitmap.h"
21#include "core/fxge/dib/fx_dib.h"
22#include "third_party/base/check_op.h"
23#include "third_party/base/containers/span.h"
24#include "third_party/base/notreached.h"
25#include "third_party/skia/include/core/SkAlphaType.h"
26#include "third_party/skia/include/core/SkColor.h"
27#include "third_party/skia/include/core/SkColorPriv.h"
28#include "third_party/skia/include/core/SkColorType.h"
29#include "third_party/skia/include/core/SkImage.h"
30#include "third_party/skia/include/core/SkImageInfo.h"
31#include "third_party/skia/include/core/SkPixmap.h"
32#include "third_party/skia/include/core/SkRefCnt.h"
37void ReleaseRetainedHeldBySkImage(
const void* ,
38 SkImages::ReleaseContext context) {
39 RetainPtr<
const CFX_DIBitmap> realized_bitmap;
40 realized_bitmap.Unleak(
reinterpret_cast<
const CFX_DIBitmap*>(context));
44sk_sp<SkImage> CreateSkiaImageFromDib(
const CFX_DIBBase* source,
45 SkColorType color_type,
46 SkAlphaType alpha_type) {
48 RetainPtr<
const CFX_DIBitmap> realized_bitmap = source->RealizeIfNeeded();
49 if (!realized_bitmap) {
52 CHECK(!realized_bitmap->GetBuffer().empty());
56 const CFX_DIBitmap* bitmap = realized_bitmap.Leak();
57 SkImageInfo info = SkImageInfo::Make(bitmap->GetWidth(), bitmap->GetHeight(),
58 color_type, alpha_type);
59 auto result = SkImages::RasterFromPixmap(
60 SkPixmap(info, bitmap->GetBuffer().data(), bitmap->GetPitch()),
61 ReleaseRetainedHeldBySkImage,
62 const_cast<CFX_DIBitmap*>(bitmap));
68void ReleaseAllocatedHeldBySkImage(
const void* pixels,
69 SkImages::ReleaseContext ) {
70 FX_Free
(const_cast<
void*>(pixels));
74template <size_t source_bits_per_pixel,
typename PixelTransform>
75class PixelTransformTraits;
77template <
typename PixelTransform>
78class PixelTransformTraits<1, PixelTransform> {
80 using Result = std::invoke_result_t<PixelTransform,
bool>;
82 static Result Invoke(PixelTransform&& pixel_transform,
83 const uint8_t* scanline,
85 uint8_t kMask = 1 << (7 - column % 8);
86 return pixel_transform(!!(scanline[column / 8] & kMask));
90template <
typename PixelTransform>
91class PixelTransformTraits<8, PixelTransform> {
93 using Result = std::invoke_result_t<PixelTransform, uint8_t>;
95 static Result Invoke(PixelTransform&& pixel_transform,
96 const uint8_t* scanline,
98 return pixel_transform(scanline[column]);
102template <
typename PixelTransform>
103class PixelTransformTraits<24, PixelTransform> {
106 std::invoke_result_t<PixelTransform, uint8_t, uint8_t, uint8_t>;
108 static Result Invoke(PixelTransform&& pixel_transform,
109 const uint8_t* scanline,
111 size_t offset = column * 3;
112 return pixel_transform(scanline[offset + 2], scanline[offset + 1],
117void ValidateScanlineSize(pdfium::span<
const uint8_t> scanline,
118 size_t min_row_bytes) {
119 DCHECK_GE(scanline.size(), min_row_bytes);
126template <size_t source_bits_per_pixel,
typename PixelTransform>
127sk_sp<SkImage> CreateSkiaImageFromTransformedDib(
129 SkColorType color_type,
130 SkAlphaType alpha_type,
131 PixelTransform&& pixel_transform) {
132 using Traits = PixelTransformTraits<source_bits_per_pixel, PixelTransform>;
133 using Result =
typename Traits::Result;
138 SkImageInfo info = SkImageInfo::Make(width, height, color_type, alpha_type);
139 DCHECK_EQ(info.minRowBytes(), width *
sizeof(Result));
141 size_t output_size = Fx2DSizeOrDie(info.minRowBytes(), height);
143 FX_TryAlloc(uint8_t, output_size));
149 Result* output_cursor =
reinterpret_cast<Result*>(output.get());
150 const size_t min_row_bytes =
151 fxge::CalculatePitch8OrDie(source.GetBPP(), 1, width);
155 for (
int row = 0; row < height; ++row) {
156 pdfium::span<
const uint8_t> scanline = source.GetScanline(line++);
157 ValidateScanlineSize(scanline, min_row_bytes);
159 for (
int column = 0; column < width; ++column) {
161 Traits::Invoke(
std::forward<PixelTransform>(pixel_transform),
162 scanline.data(), column);
167 return SkImages::RasterFromPixmap(
168 SkPixmap(info, output.release(), info.minRowBytes()),
169 ReleaseAllocatedHeldBySkImage,
173bool IsRGBColorGrayScale(uint32_t color) {
180sk_sp<SkImage>
CFX_DIBBase::RealizeSkImage()
const {
185 uint8_t color0 = 0x00;
186 uint8_t color1 = 0xFF;
191 bool use_gray_colors = IsRGBColorGrayScale(palette_color0) &&
192 IsRGBColorGrayScale(palette_color1);
193 if (!use_gray_colors) {
194 return CreateSkiaImageFromTransformedDib<1>(
195 *
this, kBGRA_8888_SkColorType, kPremul_SkAlphaType,
196 [palette_color0, palette_color1](
bool bit) {
197 return bit ? palette_color1 : palette_color0;
205 return CreateSkiaImageFromTransformedDib<1>(
206 *
this, IsMaskFormat() ? kAlpha_8_SkColorType : kGray_8_SkColorType,
208 [color0, color1](
bool bit) {
return bit ? color1 : color0; });
214 return CreateSkiaImageFromTransformedDib<8>(
215 *
this, kBGRA_8888_SkColorType, kPremul_SkAlphaType,
216 [palette = GetPaletteSpan().first(GetRequiredPaletteSize())](
218 if (index >= palette.size()) {
221 return palette[index];
224 return CreateSkiaImageFromDib(
225 this, IsMaskFormat() ? kAlpha_8_SkColorType : kGray_8_SkColorType,
226 kPremul_SkAlphaType);
229 return CreateSkiaImageFromTransformedDib<24>(
230 *
this, kBGRA_8888_SkColorType, kOpaque_SkAlphaType,
231 [](uint8_t red, uint8_t green, uint8_t blue) {
232 return SkPackARGB32NoCheck(0xFF, red, green, blue);
236 return CreateSkiaImageFromDib(
237 this, kBGRA_8888_SkColorType,
238 IsPremultiplied() ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
241 NOTREACHED_NORETURN();
FXDIB_Format GetFormat() const
uint32_t GetPitch() const
uint32_t GetPaletteArgb(int index) const