1 // Copyright 2014 PDFium Authors. All rights reserved.
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/fxge/dib/dib_int.h"
8
9 #include "core/fxge/include/fx_dib.h"
10
11 namespace {
12
bilinear_interpol(const uint8_t * buf,int row_offset_l,int row_offset_r,int src_col_l,int src_col_r,int res_x,int res_y,int bpp,int c_offset)13 uint8_t bilinear_interpol(const uint8_t* buf,
14 int row_offset_l,
15 int row_offset_r,
16 int src_col_l,
17 int src_col_r,
18 int res_x,
19 int res_y,
20 int bpp,
21 int c_offset) {
22 int i_resx = 255 - res_x;
23 int col_bpp_l = src_col_l * bpp;
24 int col_bpp_r = src_col_r * bpp;
25 const uint8_t* buf_u = buf + row_offset_l + c_offset;
26 const uint8_t* buf_d = buf + row_offset_r + c_offset;
27 const uint8_t* src_pos0 = buf_u + col_bpp_l;
28 const uint8_t* src_pos1 = buf_u + col_bpp_r;
29 const uint8_t* src_pos2 = buf_d + col_bpp_l;
30 const uint8_t* src_pos3 = buf_d + col_bpp_r;
31 uint8_t r_pos_0 = (*src_pos0 * i_resx + *src_pos1 * res_x) >> 8;
32 uint8_t r_pos_1 = (*src_pos2 * i_resx + *src_pos3 * res_x) >> 8;
33 return (r_pos_0 * (255 - res_y) + r_pos_1 * res_y) >> 8;
34 }
35
bicubic_interpol(const uint8_t * buf,int pitch,int pos_pixel[],int u_w[],int v_w[],int res_x,int res_y,int bpp,int c_offset)36 uint8_t bicubic_interpol(const uint8_t* buf,
37 int pitch,
38 int pos_pixel[],
39 int u_w[],
40 int v_w[],
41 int res_x,
42 int res_y,
43 int bpp,
44 int c_offset) {
45 int s_result = 0;
46 for (int i = 0; i < 4; i++) {
47 int a_result = 0;
48 for (int j = 0; j < 4; j++) {
49 a_result += u_w[j] * (*(uint8_t*)(buf + pos_pixel[i + 4] * pitch +
50 pos_pixel[j] * bpp + c_offset));
51 }
52 s_result += a_result * v_w[i];
53 }
54 s_result >>= 16;
55 return (uint8_t)(s_result < 0 ? 0 : s_result > 255 ? 255 : s_result);
56 }
57
bicubic_get_pos_weight(int pos_pixel[],int u_w[],int v_w[],int src_col_l,int src_row_l,int res_x,int res_y,int stretch_width,int stretch_height)58 void bicubic_get_pos_weight(int pos_pixel[],
59 int u_w[],
60 int v_w[],
61 int src_col_l,
62 int src_row_l,
63 int res_x,
64 int res_y,
65 int stretch_width,
66 int stretch_height) {
67 pos_pixel[0] = src_col_l - 1;
68 pos_pixel[1] = src_col_l;
69 pos_pixel[2] = src_col_l + 1;
70 pos_pixel[3] = src_col_l + 2;
71 pos_pixel[4] = src_row_l - 1;
72 pos_pixel[5] = src_row_l;
73 pos_pixel[6] = src_row_l + 1;
74 pos_pixel[7] = src_row_l + 2;
75 for (int i = 0; i < 4; i++) {
76 if (pos_pixel[i] < 0) {
77 pos_pixel[i] = 0;
78 }
79 if (pos_pixel[i] >= stretch_width) {
80 pos_pixel[i] = stretch_width - 1;
81 }
82 if (pos_pixel[i + 4] < 0) {
83 pos_pixel[i + 4] = 0;
84 }
85 if (pos_pixel[i + 4] >= stretch_height) {
86 pos_pixel[i + 4] = stretch_height - 1;
87 }
88 }
89 u_w[0] = SDP_Table[256 + res_x];
90 u_w[1] = SDP_Table[res_x];
91 u_w[2] = SDP_Table[256 - res_x];
92 u_w[3] = SDP_Table[512 - res_x];
93 v_w[0] = SDP_Table[256 + res_y];
94 v_w[1] = SDP_Table[res_y];
95 v_w[2] = SDP_Table[256 - res_y];
96 v_w[3] = SDP_Table[512 - res_y];
97 }
98
GetTransformedFormat(const CFX_DIBSource * pDrc)99 FXDIB_Format GetTransformedFormat(const CFX_DIBSource* pDrc) {
100 FXDIB_Format format = pDrc->GetFormat();
101 if (pDrc->IsAlphaMask()) {
102 format = FXDIB_8bppMask;
103 } else if (format >= 1025) {
104 format = FXDIB_Cmyka;
105 } else if (format <= 32 || format == FXDIB_Argb) {
106 format = FXDIB_Argb;
107 } else {
108 format = FXDIB_Rgba;
109 }
110 return format;
111 }
112
113 } // namespace
114
115 const int16_t SDP_Table[513] = {
116 256, 256, 256, 256, 256, 256, 256, 256, 256, 255, 255, 255, 255, 255, 255,
117 254, 254, 254, 254, 253, 253, 253, 252, 252, 252, 251, 251, 251, 250, 250,
118 249, 249, 249, 248, 248, 247, 247, 246, 246, 245, 244, 244, 243, 243, 242,
119 242, 241, 240, 240, 239, 238, 238, 237, 236, 236, 235, 234, 233, 233, 232,
120 231, 230, 230, 229, 228, 227, 226, 226, 225, 224, 223, 222, 221, 220, 219,
121 218, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205,
122 204, 203, 202, 201, 200, 199, 198, 196, 195, 194, 193, 192, 191, 190, 189,
123 188, 186, 185, 184, 183, 182, 181, 179, 178, 177, 176, 175, 173, 172, 171,
124 170, 169, 167, 166, 165, 164, 162, 161, 160, 159, 157, 156, 155, 154, 152,
125 151, 150, 149, 147, 146, 145, 143, 142, 141, 140, 138, 137, 136, 134, 133,
126 132, 130, 129, 128, 126, 125, 124, 122, 121, 120, 119, 117, 116, 115, 113,
127 112, 111, 109, 108, 107, 105, 104, 103, 101, 100, 99, 97, 96, 95, 93,
128 92, 91, 89, 88, 87, 85, 84, 83, 81, 80, 79, 77, 76, 75, 73,
129 72, 71, 69, 68, 67, 66, 64, 63, 62, 60, 59, 58, 57, 55, 54,
130 53, 52, 50, 49, 48, 47, 45, 44, 43, 42, 40, 39, 38, 37, 36,
131 34, 33, 32, 31, 30, 28, 27, 26, 25, 24, 23, 21, 20, 19, 18,
132 17, 16, 15, 14, 13, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
133 1, 0, 0, -1, -2, -3, -4, -5, -6, -7, -7, -8, -9, -10, -11,
134 -12, -12, -13, -14, -15, -15, -16, -17, -17, -18, -19, -19, -20, -21, -21,
135 -22, -22, -23, -24, -24, -25, -25, -26, -26, -27, -27, -27, -28, -28, -29,
136 -29, -30, -30, -30, -31, -31, -31, -32, -32, -32, -33, -33, -33, -33, -34,
137 -34, -34, -34, -35, -35, -35, -35, -35, -36, -36, -36, -36, -36, -36, -36,
138 -36, -36, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37, -37,
139 -37, -37, -37, -37, -37, -37, -37, -37, -36, -36, -36, -36, -36, -36, -36,
140 -36, -36, -35, -35, -35, -35, -35, -35, -34, -34, -34, -34, -34, -33, -33,
141 -33, -33, -33, -32, -32, -32, -32, -31, -31, -31, -31, -30, -30, -30, -30,
142 -29, -29, -29, -29, -28, -28, -28, -27, -27, -27, -27, -26, -26, -26, -25,
143 -25, -25, -24, -24, -24, -23, -23, -23, -22, -22, -22, -22, -21, -21, -21,
144 -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16, -16, -16,
145 -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -12, -11, -11, -11,
146 -10, -10, -10, -9, -9, -9, -9, -8, -8, -8, -7, -7, -7, -7, -6,
147 -6, -6, -6, -5, -5, -5, -5, -4, -4, -4, -4, -3, -3, -3, -3,
148 -3, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, 0, 0, 0,
149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
150 0, 0, 0,
151 };
152
153 class CFX_BilinearMatrix : public CPDF_FixedMatrix {
154 public:
CFX_BilinearMatrix(const CFX_Matrix & src,int bits)155 CFX_BilinearMatrix(const CFX_Matrix& src, int bits)
156 : CPDF_FixedMatrix(src, bits) {}
Transform(int x,int y,int & x1,int & y1,int & res_x,int & res_y)157 inline void Transform(int x,
158 int y,
159 int& x1,
160 int& y1,
161 int& res_x,
162 int& res_y) {
163 x1 = a * x + c * y + e + base / 2;
164 y1 = b * x + d * y + f + base / 2;
165 res_x = x1 % base;
166 res_y = y1 % base;
167 if (res_x < 0 && res_x > -base) {
168 res_x = base + res_x;
169 }
170 if (res_y < 0 && res_x > -base) {
171 res_y = base + res_y;
172 }
173 x1 /= base;
174 y1 /= base;
175 }
176 };
SwapXY(FX_BOOL bXFlip,FX_BOOL bYFlip,const FX_RECT * pDestClip) const177 CFX_DIBitmap* CFX_DIBSource::SwapXY(FX_BOOL bXFlip,
178 FX_BOOL bYFlip,
179 const FX_RECT* pDestClip) const {
180 FX_RECT dest_clip(0, 0, m_Height, m_Width);
181 if (pDestClip) {
182 dest_clip.Intersect(*pDestClip);
183 }
184 if (dest_clip.IsEmpty()) {
185 return nullptr;
186 }
187 CFX_DIBitmap* pTransBitmap = new CFX_DIBitmap;
188 int result_height = dest_clip.Height(), result_width = dest_clip.Width();
189 if (!pTransBitmap->Create(result_width, result_height, GetFormat())) {
190 delete pTransBitmap;
191 return nullptr;
192 }
193 pTransBitmap->CopyPalette(m_pPalette);
194 int dest_pitch = pTransBitmap->GetPitch();
195 uint8_t* dest_buf = pTransBitmap->GetBuffer();
196 int row_start = bXFlip ? m_Height - dest_clip.right : dest_clip.left;
197 int row_end = bXFlip ? m_Height - dest_clip.left : dest_clip.right;
198 int col_start = bYFlip ? m_Width - dest_clip.bottom : dest_clip.top;
199 int col_end = bYFlip ? m_Width - dest_clip.top : dest_clip.bottom;
200 if (GetBPP() == 1) {
201 FXSYS_memset(dest_buf, 0xff, dest_pitch * result_height);
202 for (int row = row_start; row < row_end; row++) {
203 const uint8_t* src_scan = GetScanline(row);
204 int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
205 dest_clip.left;
206 uint8_t* dest_scan = dest_buf;
207 if (bYFlip) {
208 dest_scan += (result_height - 1) * dest_pitch;
209 }
210 int dest_step = bYFlip ? -dest_pitch : dest_pitch;
211 for (int col = col_start; col < col_end; col++) {
212 if (!(src_scan[col / 8] & (1 << (7 - col % 8)))) {
213 dest_scan[dest_col / 8] &= ~(1 << (7 - dest_col % 8));
214 }
215 dest_scan += dest_step;
216 }
217 }
218 } else {
219 int nBytes = GetBPP() / 8;
220 int dest_step = bYFlip ? -dest_pitch : dest_pitch;
221 if (nBytes == 3) {
222 dest_step -= 2;
223 }
224 for (int row = row_start; row < row_end; row++) {
225 int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
226 dest_clip.left;
227 uint8_t* dest_scan = dest_buf + dest_col * nBytes;
228 if (bYFlip) {
229 dest_scan += (result_height - 1) * dest_pitch;
230 }
231 if (nBytes == 4) {
232 uint32_t* src_scan = (uint32_t*)GetScanline(row) + col_start;
233 for (int col = col_start; col < col_end; col++) {
234 *(uint32_t*)dest_scan = *src_scan++;
235 dest_scan += dest_step;
236 }
237 } else {
238 const uint8_t* src_scan = GetScanline(row) + col_start * nBytes;
239 if (nBytes == 1) {
240 for (int col = col_start; col < col_end; col++) {
241 *dest_scan = *src_scan++;
242 dest_scan += dest_step;
243 }
244 } else {
245 for (int col = col_start; col < col_end; col++) {
246 *dest_scan++ = *src_scan++;
247 *dest_scan++ = *src_scan++;
248 *dest_scan = *src_scan++;
249 dest_scan += dest_step;
250 }
251 }
252 }
253 }
254 }
255 if (m_pAlphaMask) {
256 dest_pitch = pTransBitmap->m_pAlphaMask->GetPitch();
257 dest_buf = pTransBitmap->m_pAlphaMask->GetBuffer();
258 int dest_step = bYFlip ? -dest_pitch : dest_pitch;
259 for (int row = row_start; row < row_end; row++) {
260 int dest_col = (bXFlip ? dest_clip.right - (row - row_start) - 1 : row) -
261 dest_clip.left;
262 uint8_t* dest_scan = dest_buf + dest_col;
263 if (bYFlip) {
264 dest_scan += (result_height - 1) * dest_pitch;
265 }
266 const uint8_t* src_scan = m_pAlphaMask->GetScanline(row) + col_start;
267 for (int col = col_start; col < col_end; col++) {
268 *dest_scan = *src_scan++;
269 dest_scan += dest_step;
270 }
271 }
272 }
273 return pTransBitmap;
274 }
275 #define FIX16_005 0.05f
FXDIB_SwapClipBox(FX_RECT & clip,int width,int height,FX_BOOL bFlipX,FX_BOOL bFlipY)276 FX_RECT FXDIB_SwapClipBox(FX_RECT& clip,
277 int width,
278 int height,
279 FX_BOOL bFlipX,
280 FX_BOOL bFlipY) {
281 FX_RECT rect;
282 if (bFlipY) {
283 rect.left = height - clip.top;
284 rect.right = height - clip.bottom;
285 } else {
286 rect.left = clip.top;
287 rect.right = clip.bottom;
288 }
289 if (bFlipX) {
290 rect.top = width - clip.left;
291 rect.bottom = width - clip.right;
292 } else {
293 rect.top = clip.left;
294 rect.bottom = clip.right;
295 }
296 rect.Normalize();
297 return rect;
298 }
299
TransformTo(const CFX_Matrix * pDestMatrix,int & result_left,int & result_top,uint32_t flags,const FX_RECT * pDestClip) const300 CFX_DIBitmap* CFX_DIBSource::TransformTo(const CFX_Matrix* pDestMatrix,
301 int& result_left,
302 int& result_top,
303 uint32_t flags,
304 const FX_RECT* pDestClip) const {
305 CFX_ImageTransformer transformer(this, pDestMatrix, flags, pDestClip);
306 transformer.Start();
307 transformer.Continue(nullptr);
308 result_left = transformer.result().left;
309 result_top = transformer.result().top;
310 return transformer.DetachBitmap().release();
311 }
312
StretchTo(int dest_width,int dest_height,uint32_t flags,const FX_RECT * pClip) const313 CFX_DIBitmap* CFX_DIBSource::StretchTo(int dest_width,
314 int dest_height,
315 uint32_t flags,
316 const FX_RECT* pClip) const {
317 FX_RECT clip_rect(0, 0, FXSYS_abs(dest_width), FXSYS_abs(dest_height));
318 if (pClip)
319 clip_rect.Intersect(*pClip);
320
321 if (clip_rect.IsEmpty())
322 return nullptr;
323
324 if (dest_width == m_Width && dest_height == m_Height)
325 return Clone(&clip_rect);
326
327 CFX_BitmapStorer storer;
328 CFX_ImageStretcher stretcher(&storer, this, dest_width, dest_height,
329 clip_rect, flags);
330 if (stretcher.Start())
331 stretcher.Continue(nullptr);
332 return storer.Detach().release();
333 }
334
CFX_ImageTransformer(const CFX_DIBSource * pSrc,const CFX_Matrix * pMatrix,int flags,const FX_RECT * pClip)335 CFX_ImageTransformer::CFX_ImageTransformer(const CFX_DIBSource* pSrc,
336 const CFX_Matrix* pMatrix,
337 int flags,
338 const FX_RECT* pClip)
339 : m_pSrc(pSrc),
340 m_pMatrix(pMatrix),
341 m_pClip(pClip),
342 m_Flags(flags),
343 m_Status(0) {}
344
~CFX_ImageTransformer()345 CFX_ImageTransformer::~CFX_ImageTransformer() {}
346
Start()347 FX_BOOL CFX_ImageTransformer::Start() {
348 CFX_FloatRect unit_rect = m_pMatrix->GetUnitRect();
349 FX_RECT result_rect = unit_rect.GetClosestRect();
350 FX_RECT result_clip = result_rect;
351 if (m_pClip)
352 result_clip.Intersect(*m_pClip);
353
354 if (result_clip.IsEmpty())
355 return FALSE;
356
357 m_result = result_clip;
358 if (FXSYS_fabs(m_pMatrix->a) < FXSYS_fabs(m_pMatrix->b) / 20 &&
359 FXSYS_fabs(m_pMatrix->d) < FXSYS_fabs(m_pMatrix->c) / 20 &&
360 FXSYS_fabs(m_pMatrix->a) < 0.5f && FXSYS_fabs(m_pMatrix->d) < 0.5f) {
361 int dest_width = result_rect.Width();
362 int dest_height = result_rect.Height();
363 result_clip.Offset(-result_rect.left, -result_rect.top);
364 result_clip = FXDIB_SwapClipBox(result_clip, dest_width, dest_height,
365 m_pMatrix->c > 0, m_pMatrix->b < 0);
366 m_Stretcher.reset(new CFX_ImageStretcher(&m_Storer, m_pSrc, dest_height,
367 dest_width, result_clip, m_Flags));
368 m_Stretcher->Start();
369 m_Status = 1;
370 return TRUE;
371 }
372 if (FXSYS_fabs(m_pMatrix->b) < FIX16_005 &&
373 FXSYS_fabs(m_pMatrix->c) < FIX16_005) {
374 int dest_width = m_pMatrix->a > 0 ? (int)FXSYS_ceil(m_pMatrix->a)
375 : (int)FXSYS_floor(m_pMatrix->a);
376 int dest_height = m_pMatrix->d > 0 ? (int)-FXSYS_ceil(m_pMatrix->d)
377 : (int)-FXSYS_floor(m_pMatrix->d);
378 result_clip.Offset(-result_rect.left, -result_rect.top);
379 m_Stretcher.reset(new CFX_ImageStretcher(
380 &m_Storer, m_pSrc, dest_width, dest_height, result_clip, m_Flags));
381 m_Stretcher->Start();
382 m_Status = 2;
383 return TRUE;
384 }
385 int stretch_width = (int)FXSYS_ceil(FXSYS_sqrt2(m_pMatrix->a, m_pMatrix->b));
386 int stretch_height = (int)FXSYS_ceil(FXSYS_sqrt2(m_pMatrix->c, m_pMatrix->d));
387 CFX_Matrix stretch2dest(1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
388 (FX_FLOAT)(stretch_height));
389 stretch2dest.Concat(
390 m_pMatrix->a / stretch_width, m_pMatrix->b / stretch_width,
391 m_pMatrix->c / stretch_height, m_pMatrix->d / stretch_height,
392 m_pMatrix->e, m_pMatrix->f);
393 m_dest2stretch.SetReverse(stretch2dest);
394 CFX_FloatRect clip_rect_f(result_clip);
395 clip_rect_f.Transform(&m_dest2stretch);
396 m_StretchClip = clip_rect_f.GetOutterRect();
397 m_StretchClip.Intersect(0, 0, stretch_width, stretch_height);
398 m_Stretcher.reset(new CFX_ImageStretcher(&m_Storer, m_pSrc, stretch_width,
399 stretch_height, m_StretchClip,
400 m_Flags));
401 m_Stretcher->Start();
402 m_Status = 3;
403 return TRUE;
404 }
405
Continue(IFX_Pause * pPause)406 FX_BOOL CFX_ImageTransformer::Continue(IFX_Pause* pPause) {
407 if (m_Status == 1) {
408 if (m_Stretcher->Continue(pPause))
409 return TRUE;
410
411 if (m_Storer.GetBitmap()) {
412 std::unique_ptr<CFX_DIBitmap> swapped(
413 m_Storer.GetBitmap()->SwapXY(m_pMatrix->c > 0, m_pMatrix->b < 0));
414 m_Storer.Replace(std::move(swapped));
415 }
416 return FALSE;
417 }
418
419 if (m_Status == 2)
420 return m_Stretcher->Continue(pPause);
421
422 if (m_Status != 3)
423 return FALSE;
424
425 if (m_Stretcher->Continue(pPause))
426 return TRUE;
427
428 int stretch_width = m_StretchClip.Width();
429 int stretch_height = m_StretchClip.Height();
430 if (!m_Storer.GetBitmap())
431 return FALSE;
432
433 const uint8_t* stretch_buf = m_Storer.GetBitmap()->GetBuffer();
434 const uint8_t* stretch_buf_mask = nullptr;
435 if (m_Storer.GetBitmap()->m_pAlphaMask)
436 stretch_buf_mask = m_Storer.GetBitmap()->m_pAlphaMask->GetBuffer();
437
438 int stretch_pitch = m_Storer.GetBitmap()->GetPitch();
439 std::unique_ptr<CFX_DIBitmap> pTransformed(new CFX_DIBitmap);
440 FXDIB_Format transformF = GetTransformedFormat(m_Stretcher->source());
441 if (!pTransformed->Create(m_result.Width(), m_result.Height(), transformF))
442 return FALSE;
443
444 pTransformed->Clear(0);
445 if (pTransformed->m_pAlphaMask)
446 pTransformed->m_pAlphaMask->Clear(0);
447
448 CFX_Matrix result2stretch(1.0f, 0.0f, 0.0f, 1.0f, (FX_FLOAT)(m_result.left),
449 (FX_FLOAT)(m_result.top));
450 result2stretch.Concat(m_dest2stretch);
451 result2stretch.TranslateI(-m_StretchClip.left, -m_StretchClip.top);
452 if (!stretch_buf_mask && pTransformed->m_pAlphaMask) {
453 pTransformed->m_pAlphaMask->Clear(0xff000000);
454 } else if (pTransformed->m_pAlphaMask) {
455 int stretch_pitch_mask = m_Storer.GetBitmap()->m_pAlphaMask->GetPitch();
456 if (!(m_Flags & FXDIB_DOWNSAMPLE) && !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
457 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
458 for (int row = 0; row < m_result.Height(); row++) {
459 uint8_t* dest_pos_mask =
460 (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row);
461 for (int col = 0; col < m_result.Width(); col++) {
462 int src_col_l, src_row_l, res_x, res_y;
463 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
464 res_y);
465 if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
466 src_row_l <= stretch_height) {
467 if (src_col_l == stretch_width) {
468 src_col_l--;
469 }
470 if (src_row_l == stretch_height) {
471 src_row_l--;
472 }
473 int src_col_r = src_col_l + 1;
474 int src_row_r = src_row_l + 1;
475 if (src_col_r == stretch_width) {
476 src_col_r--;
477 }
478 if (src_row_r == stretch_height) {
479 src_row_r--;
480 }
481 int row_offset_l = src_row_l * stretch_pitch_mask;
482 int row_offset_r = src_row_r * stretch_pitch_mask;
483 *dest_pos_mask =
484 bilinear_interpol(stretch_buf_mask, row_offset_l, row_offset_r,
485 src_col_l, src_col_r, res_x, res_y, 1, 0);
486 }
487 dest_pos_mask++;
488 }
489 }
490 } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
491 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
492 for (int row = 0; row < m_result.Height(); row++) {
493 uint8_t* dest_pos_mask =
494 (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row);
495 for (int col = 0; col < m_result.Width(); col++) {
496 int src_col_l, src_row_l, res_x, res_y;
497 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
498 res_y);
499 if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
500 src_row_l <= stretch_height) {
501 int pos_pixel[8];
502 int u_w[4], v_w[4];
503 if (src_col_l == stretch_width) {
504 src_col_l--;
505 }
506 if (src_row_l == stretch_height) {
507 src_row_l--;
508 }
509 bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
510 res_x, res_y, stretch_width, stretch_height);
511 *dest_pos_mask =
512 bicubic_interpol(stretch_buf_mask, stretch_pitch_mask,
513 pos_pixel, u_w, v_w, res_x, res_y, 1, 0);
514 }
515 dest_pos_mask++;
516 }
517 }
518 } else {
519 CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
520 for (int row = 0; row < m_result.Height(); row++) {
521 uint8_t* dest_pos_mask =
522 (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row);
523 for (int col = 0; col < m_result.Width(); col++) {
524 int src_col, src_row;
525 result2stretch_fix.Transform(col, row, src_col, src_row);
526 if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
527 src_row <= stretch_height) {
528 if (src_col == stretch_width) {
529 src_col--;
530 }
531 if (src_row == stretch_height) {
532 src_row--;
533 }
534 *dest_pos_mask =
535 stretch_buf_mask[src_row * stretch_pitch_mask + src_col];
536 }
537 dest_pos_mask++;
538 }
539 }
540 }
541 }
542 if (m_Storer.GetBitmap()->IsAlphaMask()) {
543 if (!(m_Flags & FXDIB_DOWNSAMPLE) && !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
544 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
545 for (int row = 0; row < m_result.Height(); row++) {
546 uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row);
547 for (int col = 0; col < m_result.Width(); col++) {
548 int src_col_l, src_row_l, res_x, res_y;
549 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
550 res_y);
551 if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
552 src_row_l <= stretch_height) {
553 if (src_col_l == stretch_width) {
554 src_col_l--;
555 }
556 if (src_row_l == stretch_height) {
557 src_row_l--;
558 }
559 int src_col_r = src_col_l + 1;
560 int src_row_r = src_row_l + 1;
561 if (src_col_r == stretch_width) {
562 src_col_r--;
563 }
564 if (src_row_r == stretch_height) {
565 src_row_r--;
566 }
567 int row_offset_l = src_row_l * stretch_pitch;
568 int row_offset_r = src_row_r * stretch_pitch;
569 *dest_scan =
570 bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
571 src_col_l, src_col_r, res_x, res_y, 1, 0);
572 }
573 dest_scan++;
574 }
575 }
576 } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
577 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
578 for (int row = 0; row < m_result.Height(); row++) {
579 uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row);
580 for (int col = 0; col < m_result.Width(); col++) {
581 int src_col_l, src_row_l, res_x, res_y;
582 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
583 res_y);
584 if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
585 src_row_l <= stretch_height) {
586 int pos_pixel[8];
587 int u_w[4], v_w[4];
588 if (src_col_l == stretch_width) {
589 src_col_l--;
590 }
591 if (src_row_l == stretch_height) {
592 src_row_l--;
593 }
594 bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
595 res_x, res_y, stretch_width, stretch_height);
596 *dest_scan = bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
597 u_w, v_w, res_x, res_y, 1, 0);
598 }
599 dest_scan++;
600 }
601 }
602 } else {
603 CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
604 for (int row = 0; row < m_result.Height(); row++) {
605 uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row);
606 for (int col = 0; col < m_result.Width(); col++) {
607 int src_col, src_row;
608 result2stretch_fix.Transform(col, row, src_col, src_row);
609 if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
610 src_row <= stretch_height) {
611 if (src_col == stretch_width) {
612 src_col--;
613 }
614 if (src_row == stretch_height) {
615 src_row--;
616 }
617 const uint8_t* src_pixel =
618 stretch_buf + stretch_pitch * src_row + src_col;
619 *dest_scan = *src_pixel;
620 }
621 dest_scan++;
622 }
623 }
624 }
625 } else {
626 int Bpp = m_Storer.GetBitmap()->GetBPP() / 8;
627 if (Bpp == 1) {
628 uint32_t argb[256];
629 FX_ARGB* pPal = m_Storer.GetBitmap()->GetPalette();
630 if (pPal) {
631 for (int i = 0; i < 256; i++) {
632 argb[i] = pPal[i];
633 }
634 } else {
635 if (m_Storer.GetBitmap()->IsCmykImage()) {
636 for (int i = 0; i < 256; i++) {
637 argb[i] = 255 - i;
638 }
639 } else {
640 for (int i = 0; i < 256; i++) {
641 argb[i] = 0xff000000 | (i * 0x010101);
642 }
643 }
644 }
645 int destBpp = pTransformed->GetBPP() / 8;
646 if (!(m_Flags & FXDIB_DOWNSAMPLE) &&
647 !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
648 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
649 for (int row = 0; row < m_result.Height(); row++) {
650 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
651 for (int col = 0; col < m_result.Width(); col++) {
652 int src_col_l, src_row_l, res_x, res_y;
653 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
654 res_y);
655 if (src_col_l >= 0 && src_col_l <= stretch_width &&
656 src_row_l >= 0 && src_row_l <= stretch_height) {
657 if (src_col_l == stretch_width) {
658 src_col_l--;
659 }
660 if (src_row_l == stretch_height) {
661 src_row_l--;
662 }
663 int src_col_r = src_col_l + 1;
664 int src_row_r = src_row_l + 1;
665 if (src_col_r == stretch_width) {
666 src_col_r--;
667 }
668 if (src_row_r == stretch_height) {
669 src_row_r--;
670 }
671 int row_offset_l = src_row_l * stretch_pitch;
672 int row_offset_r = src_row_r * stretch_pitch;
673 uint32_t r_bgra_cmyk = argb[bilinear_interpol(
674 stretch_buf, row_offset_l, row_offset_r, src_col_l, src_col_r,
675 res_x, res_y, 1, 0)];
676 if (transformF == FXDIB_Rgba) {
677 dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24);
678 dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16);
679 dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8);
680 } else {
681 *(uint32_t*)dest_pos = r_bgra_cmyk;
682 }
683 }
684 dest_pos += destBpp;
685 }
686 }
687 } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
688 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
689 for (int row = 0; row < m_result.Height(); row++) {
690 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
691 for (int col = 0; col < m_result.Width(); col++) {
692 int src_col_l, src_row_l, res_x, res_y;
693 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
694 res_y);
695 if (src_col_l >= 0 && src_col_l <= stretch_width &&
696 src_row_l >= 0 && src_row_l <= stretch_height) {
697 int pos_pixel[8];
698 int u_w[4], v_w[4];
699 if (src_col_l == stretch_width) {
700 src_col_l--;
701 }
702 if (src_row_l == stretch_height) {
703 src_row_l--;
704 }
705 bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
706 res_x, res_y, stretch_width,
707 stretch_height);
708 uint32_t r_bgra_cmyk =
709 argb[bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
710 u_w, v_w, res_x, res_y, 1, 0)];
711 if (transformF == FXDIB_Rgba) {
712 dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24);
713 dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16);
714 dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8);
715 } else {
716 *(uint32_t*)dest_pos = r_bgra_cmyk;
717 }
718 }
719 dest_pos += destBpp;
720 }
721 }
722 } else {
723 CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
724 for (int row = 0; row < m_result.Height(); row++) {
725 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
726 for (int col = 0; col < m_result.Width(); col++) {
727 int src_col, src_row;
728 result2stretch_fix.Transform(col, row, src_col, src_row);
729 if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
730 src_row <= stretch_height) {
731 if (src_col == stretch_width) {
732 src_col--;
733 }
734 if (src_row == stretch_height) {
735 src_row--;
736 }
737 uint32_t r_bgra_cmyk =
738 argb[stretch_buf[src_row * stretch_pitch + src_col]];
739 if (transformF == FXDIB_Rgba) {
740 dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24);
741 dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16);
742 dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8);
743 } else {
744 *(uint32_t*)dest_pos = r_bgra_cmyk;
745 }
746 }
747 dest_pos += destBpp;
748 }
749 }
750 }
751 } else {
752 FX_BOOL bHasAlpha = m_Storer.GetBitmap()->HasAlpha();
753 int destBpp = pTransformed->GetBPP() / 8;
754 if (!(m_Flags & FXDIB_DOWNSAMPLE) &&
755 !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
756 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
757 for (int row = 0; row < m_result.Height(); row++) {
758 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
759 for (int col = 0; col < m_result.Width(); col++) {
760 int src_col_l, src_row_l, res_x, res_y, r_pos_k_r = 0;
761 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
762 res_y);
763 if (src_col_l >= 0 && src_col_l <= stretch_width &&
764 src_row_l >= 0 && src_row_l <= stretch_height) {
765 if (src_col_l == stretch_width) {
766 src_col_l--;
767 }
768 if (src_row_l == stretch_height) {
769 src_row_l--;
770 }
771 int src_col_r = src_col_l + 1;
772 int src_row_r = src_row_l + 1;
773 if (src_col_r == stretch_width) {
774 src_col_r--;
775 }
776 if (src_row_r == stretch_height) {
777 src_row_r--;
778 }
779 int row_offset_l = src_row_l * stretch_pitch;
780 int row_offset_r = src_row_r * stretch_pitch;
781 uint8_t r_pos_red_y_r =
782 bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
783 src_col_l, src_col_r, res_x, res_y, Bpp, 2);
784 uint8_t r_pos_green_m_r =
785 bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
786 src_col_l, src_col_r, res_x, res_y, Bpp, 1);
787 uint8_t r_pos_blue_c_r =
788 bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
789 src_col_l, src_col_r, res_x, res_y, Bpp, 0);
790 if (bHasAlpha) {
791 if (transformF != FXDIB_Argb) {
792 if (transformF == FXDIB_Rgba) {
793 dest_pos[0] = r_pos_blue_c_r;
794 dest_pos[1] = r_pos_green_m_r;
795 dest_pos[2] = r_pos_red_y_r;
796 } else {
797 r_pos_k_r = bilinear_interpol(
798 stretch_buf, row_offset_l, row_offset_r, src_col_l,
799 src_col_r, res_x, res_y, Bpp, 3);
800 *(uint32_t*)dest_pos =
801 FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
802 r_pos_red_y_r, r_pos_k_r));
803 }
804 } else {
805 uint8_t r_pos_a_r = bilinear_interpol(
806 stretch_buf, row_offset_l, row_offset_r, src_col_l,
807 src_col_r, res_x, res_y, Bpp, 3);
808 *(uint32_t*)dest_pos = FXARGB_TODIB(
809 FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, r_pos_green_m_r,
810 r_pos_blue_c_r));
811 }
812 } else {
813 r_pos_k_r = 0xff;
814 if (transformF == FXDIB_Cmyka) {
815 r_pos_k_r = bilinear_interpol(
816 stretch_buf, row_offset_l, row_offset_r, src_col_l,
817 src_col_r, res_x, res_y, Bpp, 3);
818 *(uint32_t*)dest_pos =
819 FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
820 r_pos_red_y_r, r_pos_k_r));
821 } else {
822 *(uint32_t*)dest_pos = FXARGB_TODIB(
823 FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, r_pos_green_m_r,
824 r_pos_blue_c_r));
825 }
826 }
827 }
828 dest_pos += destBpp;
829 }
830 }
831 } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
832 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
833 for (int row = 0; row < m_result.Height(); row++) {
834 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
835 for (int col = 0; col < m_result.Width(); col++) {
836 int src_col_l, src_row_l, res_x, res_y, r_pos_k_r = 0;
837 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
838 res_y);
839 if (src_col_l >= 0 && src_col_l <= stretch_width &&
840 src_row_l >= 0 && src_row_l <= stretch_height) {
841 int pos_pixel[8];
842 int u_w[4], v_w[4];
843 if (src_col_l == stretch_width) {
844 src_col_l--;
845 }
846 if (src_row_l == stretch_height) {
847 src_row_l--;
848 }
849 bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
850 res_x, res_y, stretch_width,
851 stretch_height);
852 uint8_t r_pos_red_y_r =
853 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w,
854 v_w, res_x, res_y, Bpp, 2);
855 uint8_t r_pos_green_m_r =
856 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w,
857 v_w, res_x, res_y, Bpp, 1);
858 uint8_t r_pos_blue_c_r =
859 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w,
860 v_w, res_x, res_y, Bpp, 0);
861 if (bHasAlpha) {
862 if (transformF != FXDIB_Argb) {
863 if (transformF == FXDIB_Rgba) {
864 dest_pos[0] = r_pos_blue_c_r;
865 dest_pos[1] = r_pos_green_m_r;
866 dest_pos[2] = r_pos_red_y_r;
867 } else {
868 r_pos_k_r =
869 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
870 u_w, v_w, res_x, res_y, Bpp, 3);
871 *(uint32_t*)dest_pos =
872 FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
873 r_pos_red_y_r, r_pos_k_r));
874 }
875 } else {
876 uint8_t r_pos_a_r =
877 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
878 u_w, v_w, res_x, res_y, Bpp, 3);
879 *(uint32_t*)dest_pos = FXARGB_TODIB(
880 FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, r_pos_green_m_r,
881 r_pos_blue_c_r));
882 }
883 } else {
884 r_pos_k_r = 0xff;
885 if (transformF == FXDIB_Cmyka) {
886 r_pos_k_r =
887 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
888 u_w, v_w, res_x, res_y, Bpp, 3);
889 *(uint32_t*)dest_pos =
890 FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
891 r_pos_red_y_r, r_pos_k_r));
892 } else {
893 *(uint32_t*)dest_pos = FXARGB_TODIB(
894 FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, r_pos_green_m_r,
895 r_pos_blue_c_r));
896 }
897 }
898 }
899 dest_pos += destBpp;
900 }
901 }
902 } else {
903 CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
904 for (int row = 0; row < m_result.Height(); row++) {
905 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
906 for (int col = 0; col < m_result.Width(); col++) {
907 int src_col, src_row;
908 result2stretch_fix.Transform(col, row, src_col, src_row);
909 if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
910 src_row <= stretch_height) {
911 if (src_col == stretch_width) {
912 src_col--;
913 }
914 if (src_row == stretch_height) {
915 src_row--;
916 }
917 const uint8_t* src_pos =
918 stretch_buf + src_row * stretch_pitch + src_col * Bpp;
919 if (bHasAlpha) {
920 if (transformF != FXDIB_Argb) {
921 if (transformF == FXDIB_Rgba) {
922 dest_pos[0] = src_pos[0];
923 dest_pos[1] = src_pos[1];
924 dest_pos[2] = src_pos[2];
925 } else {
926 *(uint32_t*)dest_pos = FXCMYK_TODIB(CmykEncode(
927 src_pos[0], src_pos[1], src_pos[2], src_pos[3]));
928 }
929 } else {
930 *(uint32_t*)dest_pos = FXARGB_TODIB(FXARGB_MAKE(
931 src_pos[3], src_pos[2], src_pos[1], src_pos[0]));
932 }
933 } else {
934 if (transformF == FXDIB_Cmyka) {
935 *(uint32_t*)dest_pos = FXCMYK_TODIB(CmykEncode(
936 src_pos[0], src_pos[1], src_pos[2], src_pos[3]));
937 } else {
938 *(uint32_t*)dest_pos = FXARGB_TODIB(
939 FXARGB_MAKE(0xff, src_pos[2], src_pos[1], src_pos[0]));
940 }
941 }
942 }
943 dest_pos += destBpp;
944 }
945 }
946 }
947 }
948 }
949 m_Storer.Replace(std::move(pTransformed));
950 return FALSE;
951 }
952
DetachBitmap()953 std::unique_ptr<CFX_DIBitmap> CFX_ImageTransformer::DetachBitmap() {
954 return m_Storer.Detach();
955 }
956