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 "dib_int.h"
8
9 #include "core/include/fxge/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 NULL;
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 NULL;
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 FX_DWORD* src_scan = (FX_DWORD*)GetScanline(row) + col_start;
233 for (int col = col_start; col < col_end; col++) {
234 *(FX_DWORD*)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 }
TransformTo(const CFX_Matrix * pDestMatrix,int & result_left,int & result_top,FX_DWORD flags,const FX_RECT * pDestClip) const299 CFX_DIBitmap* CFX_DIBSource::TransformTo(const CFX_Matrix* pDestMatrix,
300 int& result_left,
301 int& result_top,
302 FX_DWORD flags,
303 const FX_RECT* pDestClip) const {
304 CFX_ImageTransformer transformer;
305 transformer.Start(this, pDestMatrix, flags, pDestClip);
306 transformer.Continue(NULL);
307 result_left = transformer.m_ResultLeft;
308 result_top = transformer.m_ResultTop;
309 CFX_DIBitmap* pTransformed = transformer.m_Storer.Detach();
310 return pTransformed;
311 }
StretchTo(int dest_width,int dest_height,FX_DWORD flags,const FX_RECT * pClip) const312 CFX_DIBitmap* CFX_DIBSource::StretchTo(int dest_width,
313 int dest_height,
314 FX_DWORD flags,
315 const FX_RECT* pClip) const {
316 FX_RECT clip_rect(0, 0, FXSYS_abs(dest_width), FXSYS_abs(dest_height));
317 if (pClip) {
318 clip_rect.Intersect(*pClip);
319 }
320 if (clip_rect.IsEmpty()) {
321 return NULL;
322 }
323 if (dest_width == m_Width && dest_height == m_Height) {
324 return Clone(&clip_rect);
325 }
326 CFX_ImageStretcher stretcher;
327 CFX_BitmapStorer storer;
328 if (stretcher.Start(&storer, this, dest_width, dest_height, clip_rect,
329 flags)) {
330 stretcher.Continue(NULL);
331 }
332 return storer.Detach();
333 }
CFX_ImageTransformer()334 CFX_ImageTransformer::CFX_ImageTransformer() {
335 m_Status = 0;
336 m_pMatrix = NULL;
337 }
~CFX_ImageTransformer()338 CFX_ImageTransformer::~CFX_ImageTransformer() {}
Start(const CFX_DIBSource * pSrc,const CFX_Matrix * pDestMatrix,int flags,const FX_RECT * pDestClip)339 FX_BOOL CFX_ImageTransformer::Start(const CFX_DIBSource* pSrc,
340 const CFX_Matrix* pDestMatrix,
341 int flags,
342 const FX_RECT* pDestClip) {
343 m_pMatrix = (CFX_Matrix*)pDestMatrix;
344 CFX_FloatRect unit_rect = pDestMatrix->GetUnitRect();
345 FX_RECT result_rect = unit_rect.GetClosestRect();
346 FX_RECT result_clip = result_rect;
347 if (pDestClip) {
348 result_clip.Intersect(*pDestClip);
349 }
350 if (result_clip.IsEmpty()) {
351 return FALSE;
352 }
353 m_ResultLeft = result_clip.left;
354 m_ResultTop = result_clip.top;
355 m_ResultWidth = result_clip.Width();
356 m_ResultHeight = result_clip.Height();
357 m_Flags = flags;
358 if (FXSYS_fabs(pDestMatrix->a) < FXSYS_fabs(pDestMatrix->b) / 20 &&
359 FXSYS_fabs(pDestMatrix->d) < FXSYS_fabs(pDestMatrix->c) / 20 &&
360 FXSYS_fabs(pDestMatrix->a) < 0.5f && FXSYS_fabs(pDestMatrix->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 pDestMatrix->c > 0, pDestMatrix->b < 0);
366 m_Stretcher.Start(&m_Storer, pSrc, dest_height, dest_width, result_clip,
367 flags);
368 m_Status = 1;
369 return TRUE;
370 }
371 if (FXSYS_fabs(pDestMatrix->b) < FIX16_005 &&
372 FXSYS_fabs(pDestMatrix->c) < FIX16_005) {
373 int dest_width = pDestMatrix->a > 0 ? (int)FXSYS_ceil(pDestMatrix->a)
374 : (int)FXSYS_floor(pDestMatrix->a);
375 int dest_height = pDestMatrix->d > 0 ? (int)-FXSYS_ceil(pDestMatrix->d)
376 : (int)-FXSYS_floor(pDestMatrix->d);
377 result_clip.Offset(-result_rect.left, -result_rect.top);
378 m_Stretcher.Start(&m_Storer, pSrc, dest_width, dest_height, result_clip,
379 flags);
380 m_Status = 2;
381 return TRUE;
382 }
383 int stretch_width =
384 (int)FXSYS_ceil(FXSYS_sqrt2(pDestMatrix->a, pDestMatrix->b));
385 int stretch_height =
386 (int)FXSYS_ceil(FXSYS_sqrt2(pDestMatrix->c, pDestMatrix->d));
387 CFX_Matrix stretch2dest(1.0f, 0.0f, 0.0f, -1.0f, 0.0f,
388 (FX_FLOAT)(stretch_height));
389 stretch2dest.Concat(
390 pDestMatrix->a / stretch_width, pDestMatrix->b / stretch_width,
391 pDestMatrix->c / stretch_height, pDestMatrix->d / stretch_height,
392 pDestMatrix->e, pDestMatrix->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.Start(&m_Storer, pSrc, stretch_width, stretch_height,
399 m_StretchClip, flags);
400 m_Status = 3;
401 return TRUE;
402 }
403
Continue(IFX_Pause * pPause)404 FX_BOOL CFX_ImageTransformer::Continue(IFX_Pause* pPause) {
405 if (m_Status == 1) {
406 if (m_Stretcher.Continue(pPause)) {
407 return TRUE;
408 }
409 if (m_Storer.GetBitmap()) {
410 m_Storer.Replace(
411 m_Storer.GetBitmap()->SwapXY(m_pMatrix->c > 0, m_pMatrix->b < 0));
412 }
413 return FALSE;
414 }
415 if (m_Status == 2) {
416 return m_Stretcher.Continue(pPause);
417 }
418 if (m_Status != 3) {
419 return FALSE;
420 }
421 if (m_Stretcher.Continue(pPause)) {
422 return TRUE;
423 }
424 int stretch_width = m_StretchClip.Width();
425 int stretch_height = m_StretchClip.Height();
426 if (!m_Storer.GetBitmap()) {
427 return FALSE;
428 }
429 const uint8_t* stretch_buf = m_Storer.GetBitmap()->GetBuffer();
430 const uint8_t* stretch_buf_mask = NULL;
431 if (m_Storer.GetBitmap()->m_pAlphaMask) {
432 stretch_buf_mask = m_Storer.GetBitmap()->m_pAlphaMask->GetBuffer();
433 }
434 int stretch_pitch = m_Storer.GetBitmap()->GetPitch();
435 CFX_DIBitmap* pTransformed = new CFX_DIBitmap;
436 FXDIB_Format transformF = GetTransformedFormat(m_Stretcher.m_pSource);
437 if (!pTransformed->Create(m_ResultWidth, m_ResultHeight, transformF)) {
438 delete pTransformed;
439 return FALSE;
440 }
441 pTransformed->Clear(0);
442 if (pTransformed->m_pAlphaMask) {
443 pTransformed->m_pAlphaMask->Clear(0);
444 }
445 CFX_Matrix result2stretch(1.0f, 0.0f, 0.0f, 1.0f, (FX_FLOAT)(m_ResultLeft),
446 (FX_FLOAT)(m_ResultTop));
447 result2stretch.Concat(m_dest2stretch);
448 result2stretch.TranslateI(-m_StretchClip.left, -m_StretchClip.top);
449 if (!stretch_buf_mask && pTransformed->m_pAlphaMask) {
450 pTransformed->m_pAlphaMask->Clear(0xff000000);
451 } else if (pTransformed->m_pAlphaMask) {
452 int stretch_pitch_mask = m_Storer.GetBitmap()->m_pAlphaMask->GetPitch();
453 if (!(m_Flags & FXDIB_DOWNSAMPLE) && !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
454 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
455 for (int row = 0; row < m_ResultHeight; row++) {
456 uint8_t* dest_pos_mask =
457 (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row);
458 for (int col = 0; col < m_ResultWidth; col++) {
459 int src_col_l, src_row_l, res_x, res_y;
460 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
461 res_y);
462 if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
463 src_row_l <= stretch_height) {
464 if (src_col_l == stretch_width) {
465 src_col_l--;
466 }
467 if (src_row_l == stretch_height) {
468 src_row_l--;
469 }
470 int src_col_r = src_col_l + 1;
471 int src_row_r = src_row_l + 1;
472 if (src_col_r == stretch_width) {
473 src_col_r--;
474 }
475 if (src_row_r == stretch_height) {
476 src_row_r--;
477 }
478 int row_offset_l = src_row_l * stretch_pitch_mask;
479 int row_offset_r = src_row_r * stretch_pitch_mask;
480 *dest_pos_mask =
481 bilinear_interpol(stretch_buf_mask, row_offset_l, row_offset_r,
482 src_col_l, src_col_r, res_x, res_y, 1, 0);
483 }
484 dest_pos_mask++;
485 }
486 }
487 } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
488 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
489 for (int row = 0; row < m_ResultHeight; row++) {
490 uint8_t* dest_pos_mask =
491 (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row);
492 for (int col = 0; col < m_ResultWidth; col++) {
493 int src_col_l, src_row_l, res_x, res_y;
494 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
495 res_y);
496 if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
497 src_row_l <= stretch_height) {
498 int pos_pixel[8];
499 int u_w[4], v_w[4];
500 if (src_col_l == stretch_width) {
501 src_col_l--;
502 }
503 if (src_row_l == stretch_height) {
504 src_row_l--;
505 }
506 bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
507 res_x, res_y, stretch_width, stretch_height);
508 *dest_pos_mask =
509 bicubic_interpol(stretch_buf_mask, stretch_pitch_mask,
510 pos_pixel, u_w, v_w, res_x, res_y, 1, 0);
511 }
512 dest_pos_mask++;
513 }
514 }
515 } else {
516 CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
517 for (int row = 0; row < m_ResultHeight; row++) {
518 uint8_t* dest_pos_mask =
519 (uint8_t*)pTransformed->m_pAlphaMask->GetScanline(row);
520 for (int col = 0; col < m_ResultWidth; col++) {
521 int src_col, src_row;
522 result2stretch_fix.Transform(col, row, src_col, src_row);
523 if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
524 src_row <= stretch_height) {
525 if (src_col == stretch_width) {
526 src_col--;
527 }
528 if (src_row == stretch_height) {
529 src_row--;
530 }
531 *dest_pos_mask =
532 stretch_buf_mask[src_row * stretch_pitch_mask + src_col];
533 }
534 dest_pos_mask++;
535 }
536 }
537 }
538 }
539 if (m_Storer.GetBitmap()->IsAlphaMask()) {
540 if (!(m_Flags & FXDIB_DOWNSAMPLE) && !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
541 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
542 for (int row = 0; row < m_ResultHeight; row++) {
543 uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row);
544 for (int col = 0; col < m_ResultWidth; col++) {
545 int src_col_l, src_row_l, res_x, res_y;
546 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
547 res_y);
548 if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
549 src_row_l <= stretch_height) {
550 if (src_col_l == stretch_width) {
551 src_col_l--;
552 }
553 if (src_row_l == stretch_height) {
554 src_row_l--;
555 }
556 int src_col_r = src_col_l + 1;
557 int src_row_r = src_row_l + 1;
558 if (src_col_r == stretch_width) {
559 src_col_r--;
560 }
561 if (src_row_r == stretch_height) {
562 src_row_r--;
563 }
564 int row_offset_l = src_row_l * stretch_pitch;
565 int row_offset_r = src_row_r * stretch_pitch;
566 *dest_scan =
567 bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
568 src_col_l, src_col_r, res_x, res_y, 1, 0);
569 }
570 dest_scan++;
571 }
572 }
573 } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
574 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
575 for (int row = 0; row < m_ResultHeight; row++) {
576 uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row);
577 for (int col = 0; col < m_ResultWidth; col++) {
578 int src_col_l, src_row_l, res_x, res_y;
579 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
580 res_y);
581 if (src_col_l >= 0 && src_col_l <= stretch_width && src_row_l >= 0 &&
582 src_row_l <= stretch_height) {
583 int pos_pixel[8];
584 int u_w[4], v_w[4];
585 if (src_col_l == stretch_width) {
586 src_col_l--;
587 }
588 if (src_row_l == stretch_height) {
589 src_row_l--;
590 }
591 bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
592 res_x, res_y, stretch_width, stretch_height);
593 *dest_scan = bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
594 u_w, v_w, res_x, res_y, 1, 0);
595 }
596 dest_scan++;
597 }
598 }
599 } else {
600 CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
601 for (int row = 0; row < m_ResultHeight; row++) {
602 uint8_t* dest_scan = (uint8_t*)pTransformed->GetScanline(row);
603 for (int col = 0; col < m_ResultWidth; col++) {
604 int src_col, src_row;
605 result2stretch_fix.Transform(col, row, src_col, src_row);
606 if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
607 src_row <= stretch_height) {
608 if (src_col == stretch_width) {
609 src_col--;
610 }
611 if (src_row == stretch_height) {
612 src_row--;
613 }
614 const uint8_t* src_pixel =
615 stretch_buf + stretch_pitch * src_row + src_col;
616 *dest_scan = *src_pixel;
617 }
618 dest_scan++;
619 }
620 }
621 }
622 } else {
623 int Bpp = m_Storer.GetBitmap()->GetBPP() / 8;
624 int destBpp = pTransformed->GetBPP() / 8;
625 if (Bpp == 1) {
626 FX_DWORD argb[256];
627 FX_ARGB* pPal = m_Storer.GetBitmap()->GetPalette();
628 if (pPal) {
629 for (int i = 0; i < 256; i++) {
630 argb[i] = pPal[i];
631 }
632 } else {
633 if (m_Storer.GetBitmap()->IsCmykImage()) {
634 for (int i = 0; i < 256; i++) {
635 argb[i] = 255 - i;
636 }
637 } else {
638 for (int i = 0; i < 256; i++) {
639 argb[i] = 0xff000000 | (i * 0x010101);
640 }
641 }
642 }
643 if (!(m_Flags & FXDIB_DOWNSAMPLE) &&
644 !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
645 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
646 for (int row = 0; row < m_ResultHeight; row++) {
647 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
648 for (int col = 0; col < m_ResultWidth; col++) {
649 int src_col_l, src_row_l, res_x, res_y;
650 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
651 res_y);
652 if (src_col_l >= 0 && src_col_l <= stretch_width &&
653 src_row_l >= 0 && src_row_l <= stretch_height) {
654 if (src_col_l == stretch_width) {
655 src_col_l--;
656 }
657 if (src_row_l == stretch_height) {
658 src_row_l--;
659 }
660 int src_col_r = src_col_l + 1;
661 int src_row_r = src_row_l + 1;
662 if (src_col_r == stretch_width) {
663 src_col_r--;
664 }
665 if (src_row_r == stretch_height) {
666 src_row_r--;
667 }
668 int row_offset_l = src_row_l * stretch_pitch;
669 int row_offset_r = src_row_r * stretch_pitch;
670 FX_DWORD r_bgra_cmyk = argb[bilinear_interpol(
671 stretch_buf, row_offset_l, row_offset_r, src_col_l, src_col_r,
672 res_x, res_y, 1, 0)];
673 if (transformF == FXDIB_Rgba) {
674 dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24);
675 dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16);
676 dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8);
677 } else {
678 *(FX_DWORD*)dest_pos = r_bgra_cmyk;
679 }
680 }
681 dest_pos += destBpp;
682 }
683 }
684 } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
685 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
686 for (int row = 0; row < m_ResultHeight; row++) {
687 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
688 for (int col = 0; col < m_ResultWidth; col++) {
689 int src_col_l, src_row_l, res_x, res_y;
690 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
691 res_y);
692 if (src_col_l >= 0 && src_col_l <= stretch_width &&
693 src_row_l >= 0 && src_row_l <= stretch_height) {
694 int pos_pixel[8];
695 int u_w[4], v_w[4];
696 if (src_col_l == stretch_width) {
697 src_col_l--;
698 }
699 if (src_row_l == stretch_height) {
700 src_row_l--;
701 }
702 bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
703 res_x, res_y, stretch_width,
704 stretch_height);
705 FX_DWORD r_bgra_cmyk =
706 argb[bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
707 u_w, v_w, res_x, res_y, 1, 0)];
708 if (transformF == FXDIB_Rgba) {
709 dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24);
710 dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16);
711 dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8);
712 } else {
713 *(FX_DWORD*)dest_pos = r_bgra_cmyk;
714 }
715 }
716 dest_pos += destBpp;
717 }
718 }
719 } else {
720 CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
721 for (int row = 0; row < m_ResultHeight; row++) {
722 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
723 for (int col = 0; col < m_ResultWidth; col++) {
724 int src_col, src_row;
725 result2stretch_fix.Transform(col, row, src_col, src_row);
726 if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
727 src_row <= stretch_height) {
728 if (src_col == stretch_width) {
729 src_col--;
730 }
731 if (src_row == stretch_height) {
732 src_row--;
733 }
734 FX_DWORD r_bgra_cmyk =
735 argb[stretch_buf[src_row * stretch_pitch + src_col]];
736 if (transformF == FXDIB_Rgba) {
737 dest_pos[0] = (uint8_t)(r_bgra_cmyk >> 24);
738 dest_pos[1] = (uint8_t)(r_bgra_cmyk >> 16);
739 dest_pos[2] = (uint8_t)(r_bgra_cmyk >> 8);
740 } else {
741 *(FX_DWORD*)dest_pos = r_bgra_cmyk;
742 }
743 }
744 dest_pos += destBpp;
745 }
746 }
747 }
748 } else {
749 FX_BOOL bHasAlpha = m_Storer.GetBitmap()->HasAlpha();
750 int destBpp = pTransformed->GetBPP() / 8;
751 if (!(m_Flags & FXDIB_DOWNSAMPLE) &&
752 !(m_Flags & FXDIB_BICUBIC_INTERPOL)) {
753 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
754 for (int row = 0; row < m_ResultHeight; row++) {
755 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
756 for (int col = 0; col < m_ResultWidth; col++) {
757 int src_col_l, src_row_l, res_x, res_y, r_pos_k_r = 0;
758 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
759 res_y);
760 if (src_col_l >= 0 && src_col_l <= stretch_width &&
761 src_row_l >= 0 && src_row_l <= stretch_height) {
762 if (src_col_l == stretch_width) {
763 src_col_l--;
764 }
765 if (src_row_l == stretch_height) {
766 src_row_l--;
767 }
768 int src_col_r = src_col_l + 1;
769 int src_row_r = src_row_l + 1;
770 if (src_col_r == stretch_width) {
771 src_col_r--;
772 }
773 if (src_row_r == stretch_height) {
774 src_row_r--;
775 }
776 int row_offset_l = src_row_l * stretch_pitch;
777 int row_offset_r = src_row_r * stretch_pitch;
778 uint8_t r_pos_red_y_r =
779 bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
780 src_col_l, src_col_r, res_x, res_y, Bpp, 2);
781 uint8_t r_pos_green_m_r =
782 bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
783 src_col_l, src_col_r, res_x, res_y, Bpp, 1);
784 uint8_t r_pos_blue_c_r =
785 bilinear_interpol(stretch_buf, row_offset_l, row_offset_r,
786 src_col_l, src_col_r, res_x, res_y, Bpp, 0);
787 if (bHasAlpha) {
788 if (transformF != FXDIB_Argb) {
789 if (transformF == FXDIB_Rgba) {
790 dest_pos[0] = r_pos_blue_c_r;
791 dest_pos[1] = r_pos_green_m_r;
792 dest_pos[2] = r_pos_red_y_r;
793 } else {
794 r_pos_k_r = bilinear_interpol(
795 stretch_buf, row_offset_l, row_offset_r, src_col_l,
796 src_col_r, res_x, res_y, Bpp, 3);
797 *(FX_DWORD*)dest_pos =
798 FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
799 r_pos_red_y_r, r_pos_k_r));
800 }
801 } else {
802 uint8_t r_pos_a_r = bilinear_interpol(
803 stretch_buf, row_offset_l, row_offset_r, src_col_l,
804 src_col_r, res_x, res_y, Bpp, 3);
805 *(FX_DWORD*)dest_pos = FXARGB_TODIB(
806 FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, r_pos_green_m_r,
807 r_pos_blue_c_r));
808 }
809 } else {
810 r_pos_k_r = 0xff;
811 if (transformF == FXDIB_Cmyka) {
812 r_pos_k_r = bilinear_interpol(
813 stretch_buf, row_offset_l, row_offset_r, src_col_l,
814 src_col_r, res_x, res_y, Bpp, 3);
815 *(FX_DWORD*)dest_pos =
816 FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
817 r_pos_red_y_r, r_pos_k_r));
818 } else {
819 *(FX_DWORD*)dest_pos = FXARGB_TODIB(
820 FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, r_pos_green_m_r,
821 r_pos_blue_c_r));
822 }
823 }
824 }
825 dest_pos += destBpp;
826 }
827 }
828 } else if (m_Flags & FXDIB_BICUBIC_INTERPOL) {
829 CFX_BilinearMatrix result2stretch_fix(result2stretch, 8);
830 for (int row = 0; row < m_ResultHeight; row++) {
831 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
832 for (int col = 0; col < m_ResultWidth; col++) {
833 int src_col_l, src_row_l, res_x, res_y, r_pos_k_r = 0;
834 result2stretch_fix.Transform(col, row, src_col_l, src_row_l, res_x,
835 res_y);
836 if (src_col_l >= 0 && src_col_l <= stretch_width &&
837 src_row_l >= 0 && src_row_l <= stretch_height) {
838 int pos_pixel[8];
839 int u_w[4], v_w[4];
840 if (src_col_l == stretch_width) {
841 src_col_l--;
842 }
843 if (src_row_l == stretch_height) {
844 src_row_l--;
845 }
846 bicubic_get_pos_weight(pos_pixel, u_w, v_w, src_col_l, src_row_l,
847 res_x, res_y, stretch_width,
848 stretch_height);
849 uint8_t r_pos_red_y_r =
850 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w,
851 v_w, res_x, res_y, Bpp, 2);
852 uint8_t r_pos_green_m_r =
853 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w,
854 v_w, res_x, res_y, Bpp, 1);
855 uint8_t r_pos_blue_c_r =
856 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel, u_w,
857 v_w, res_x, res_y, Bpp, 0);
858 if (bHasAlpha) {
859 if (transformF != FXDIB_Argb) {
860 if (transformF == FXDIB_Rgba) {
861 dest_pos[0] = r_pos_blue_c_r;
862 dest_pos[1] = r_pos_green_m_r;
863 dest_pos[2] = r_pos_red_y_r;
864 } else {
865 r_pos_k_r =
866 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
867 u_w, v_w, res_x, res_y, Bpp, 3);
868 *(FX_DWORD*)dest_pos =
869 FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
870 r_pos_red_y_r, r_pos_k_r));
871 }
872 } else {
873 uint8_t r_pos_a_r =
874 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
875 u_w, v_w, res_x, res_y, Bpp, 3);
876 *(FX_DWORD*)dest_pos = FXARGB_TODIB(
877 FXARGB_MAKE(r_pos_a_r, r_pos_red_y_r, r_pos_green_m_r,
878 r_pos_blue_c_r));
879 }
880 } else {
881 r_pos_k_r = 0xff;
882 if (transformF == FXDIB_Cmyka) {
883 r_pos_k_r =
884 bicubic_interpol(stretch_buf, stretch_pitch, pos_pixel,
885 u_w, v_w, res_x, res_y, Bpp, 3);
886 *(FX_DWORD*)dest_pos =
887 FXCMYK_TODIB(CmykEncode(r_pos_blue_c_r, r_pos_green_m_r,
888 r_pos_red_y_r, r_pos_k_r));
889 } else {
890 *(FX_DWORD*)dest_pos = FXARGB_TODIB(
891 FXARGB_MAKE(r_pos_k_r, r_pos_red_y_r, r_pos_green_m_r,
892 r_pos_blue_c_r));
893 }
894 }
895 }
896 dest_pos += destBpp;
897 }
898 }
899 } else {
900 CPDF_FixedMatrix result2stretch_fix(result2stretch, 8);
901 for (int row = 0; row < m_ResultHeight; row++) {
902 uint8_t* dest_pos = (uint8_t*)pTransformed->GetScanline(row);
903 for (int col = 0; col < m_ResultWidth; col++) {
904 int src_col, src_row;
905 result2stretch_fix.Transform(col, row, src_col, src_row);
906 if (src_col >= 0 && src_col <= stretch_width && src_row >= 0 &&
907 src_row <= stretch_height) {
908 if (src_col == stretch_width) {
909 src_col--;
910 }
911 if (src_row == stretch_height) {
912 src_row--;
913 }
914 const uint8_t* src_pos =
915 stretch_buf + src_row * stretch_pitch + src_col * Bpp;
916 if (bHasAlpha) {
917 if (transformF != FXDIB_Argb) {
918 if (transformF == FXDIB_Rgba) {
919 dest_pos[0] = src_pos[0];
920 dest_pos[1] = src_pos[1];
921 dest_pos[2] = src_pos[2];
922 } else {
923 *(FX_DWORD*)dest_pos = FXCMYK_TODIB(CmykEncode(
924 src_pos[0], src_pos[1], src_pos[2], src_pos[3]));
925 }
926 } else {
927 *(FX_DWORD*)dest_pos = FXARGB_TODIB(FXARGB_MAKE(
928 src_pos[3], src_pos[2], src_pos[1], src_pos[0]));
929 }
930 } else {
931 if (transformF == FXDIB_Cmyka) {
932 *(FX_DWORD*)dest_pos = FXCMYK_TODIB(CmykEncode(
933 src_pos[0], src_pos[1], src_pos[2], src_pos[3]));
934 } else {
935 *(FX_DWORD*)dest_pos = FXARGB_TODIB(
936 FXARGB_MAKE(0xff, src_pos[2], src_pos[1], src_pos[0]));
937 }
938 }
939 }
940 dest_pos += destBpp;
941 }
942 }
943 }
944 }
945 }
946 m_Storer.Replace(pTransformed);
947 return FALSE;
948 }
949