7#include "core/fxcodec/jbig2/JBig2_Image.h"
15#include "core/fxcrt/fx_2d_size.h"
16#include "core/fxcrt/fx_coordinates.h"
17#include "core/fxcrt/fx_memory.h"
18#include "core/fxcrt/fx_safe_types.h"
19#include "third_party/base/check.h"
21#define JBIG2_GETDWORD(buf)
22 ((static_cast<uint32_t>((buf)[0
]) << 24
) |
23 (static_cast<uint32_t>((buf)[1
]) << 16
) |
24 (static_cast<uint32_t>((buf)[2
]) << 8
) |
25 (static_cast<uint32_t>((buf)[3
]) << 0
))
27#define JBIG2_PUTDWORD(buf, val)
28 ((buf)[0
] = static_cast<uint8_t>((val) >> 24
),
29 (buf)[1
] = static_cast<uint8_t>((val) >> 16
),
30 (buf)[2
] = static_cast<uint8_t>((val) >> 8
),
31 (buf)[3
] = static_cast<uint8_t>((val) >> 0
))
35const int kMaxImagePixels = INT_MAX - 31;
36const int kMaxImageBytes = kMaxImagePixels / 8;
38int BitIndexToByte(
int index) {
42int BitIndexToAlignedByte(
int index) {
43 return index / 32 * 4;
49 if (w <= 0 || h <= 0 || w > kMaxImagePixels)
52 int32_t stride_pixels = FxAlignToBoundary<32>(w);
53 if (h > kMaxImagePixels / stride_pixels)
58 m_nStride = stride_pixels / 8;
59 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>(
60 FX_Alloc2D(uint8_t, m_nStride, m_nHeight)));
66 pdfium::span<uint8_t> pBuf) {
71 if (stride < 0 || stride > kMaxImageBytes || stride % 4 != 0)
74 int32_t stride_pixels = 8 * stride;
75 if (stride_pixels < w || h > kMaxImagePixels / stride_pixels)
81 m_pData.Reset(pBuf.data());
85 : m_nWidth(other.m_nWidth),
86 m_nHeight(other.m_nHeight),
87 m_nStride(other.m_nStride) {
89 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>(
90 FX_Alloc2D(uint8_t, m_nStride, m_nHeight)));
106 if (x < 0 || x >= m_nWidth)
113 int32_t m = BitIndexToByte(x);
115 return ((pLine[m] >> (7 - n)) & 1);
122 if (x < 0 || x >= m_nWidth)
129 int32_t m = BitIndexToByte(x);
130 int32_t n = 1 << (7 - (x & 7));
147 memset(pDst, 0, m_nStride);
150 memcpy(pDst, pSrc, m_nStride);
157 memset(
data(), v ? 0xff : 0, Fx2DSizeOrDie(m_nStride, m_nHeight));
165 ComposeToInternal(pDst, x, y, op, FX_RECT(0, 0, m_nWidth, m_nHeight));
173 return m_pData && ComposeToInternal(pDst, x, y, op, rtSrc);
180 return m_pData && pSrc->ComposeTo(
this, x, y, op);
188 return m_pData && pSrc->ComposeToWithRect(
this, x, y, rtSrc, op);
196 if (!pImage->data() || !m_pData)
199 if (x < 0 || x >= m_nWidth || y < 0 || y >= m_nHeight)
204 SubImageFast(x, y, w, h, pImage.get());
206 SubImageSlow(x, y, w, h, pImage.get());
216 int32_t m = BitIndexToByte(x);
217 int32_t bytes_to_copy =
std::min(pImage->m_nStride, m_nStride - m);
218 int32_t lines_to_copy =
std::min(pImage->m_nHeight, m_nHeight - y);
219 for (int32_t j = 0; j < lines_to_copy; j++)
228 int32_t m = BitIndexToAlignedByte(x);
230 int32_t bytes_to_copy =
std::min(pImage->m_nStride, m_nStride - m);
231 int32_t lines_to_copy =
std::min(pImage->m_nHeight, m_nHeight - y);
232 for (int32_t j = 0; j < lines_to_copy; j++) {
235 const uint8_t* pSrc = pLineSrc + m;
236 const uint8_t* pSrcEnd = pLineSrc + m_nStride;
237 uint8_t* pDstEnd = pLineDst + bytes_to_copy;
238 for (uint8_t* pDst = pLineDst; pDst < pDstEnd; pSrc += 4, pDst += 4) {
240 if (pSrc + 4 < pSrcEnd)
248 if (!m_pData || h <= m_nHeight || h > kMaxImageBytes / m_nStride)
252 const size_t current_size = Fx2DSizeOrDie(m_nHeight, m_nStride);
253 const size_t desired_size = Fx2DSizeOrDie(h, m_nStride);
255 if (m_pData.IsOwned()) {
256 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>(FX_Realloc(
257 uint8_t, m_pData.ReleaseAndClear().release(), desired_size)));
259 uint8_t* pExternalBuffer =
data();
260 m_pData.Reset(std::unique_ptr<uint8_t, FxFreeDeleter>(
261 FX_Alloc(uint8_t, desired_size)));
262 memcpy(
data(), pExternalBuffer, current_size);
264 memset(
data() + current_size, v ? 0xff : 0, desired_size - current_size);
276 if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576)
282 int32_t xs0 = x < 0 ? -x : 0;
284 FX_SAFE_INT32 iChecked = pDst->m_nWidth;
286 if (iChecked.IsValid() && sw > iChecked.ValueOrDie())
287 xs1 = iChecked.ValueOrDie();
291 int32_t ys0 = y < 0 ? -y : 0;
293 iChecked = pDst->m_nHeight;
295 if (iChecked.IsValid() && sh > iChecked.ValueOrDie())
296 ys1 = iChecked.ValueOrDie();
300 if (ys0 >= ys1 || xs0 >= xs1)
303 int32_t xd0 =
std::max(x, 0);
304 int32_t yd0 =
std::max(y, 0);
305 int32_t w = xs1 - xs0;
306 int32_t h = ys1 - ys0;
307 int32_t xd1 = xd0 + w;
308 int32_t yd1 = yd0 + h;
309 uint32_t d1 = xd0 & 31;
310 uint32_t d2 = xd1 & 31;
311 uint32_t s1 = xs0 & 31;
312 uint32_t maskL = 0xffffffff >> d1;
313 uint32_t maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
314 uint32_t maskM = maskL & maskR;
315 const uint8_t* lineSrc =
317 const uint8_t* lineSrcEnd =
data() + Fx2DSizeOrDie(m_nHeight, m_nStride);
318 int32_t lineLeft = m_nStride - BitIndexToAlignedByte(xs0);
320 if ((xd0 & ~31) == ((xd1 - 1) & ~31)) {
321 if ((xs0 & ~31) == ((xs1 - 1) & ~31)) {
323 uint32_t shift = s1 - d1;
324 for (int32_t yy = yd0; yy < yd1; yy++) {
325 if (lineSrc >= lineSrcEnd)
332 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
335 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
338 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
341 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
344 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
348 lineSrc += m_nStride;
349 lineDst += pDst->m_nStride;
352 uint32_t shift = d1 - s1;
353 for (int32_t yy = yd0; yy < yd1; yy++) {
354 if (lineSrc >= lineSrcEnd)
361 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
364 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
367 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
370 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
373 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
377 lineSrc += m_nStride;
378 lineDst += pDst->m_nStride;
382 uint32_t shift1 = s1 - d1;
383 uint32_t shift2 = 32 - shift1;
384 for (int32_t yy = yd0; yy < yd1; yy++) {
385 if (lineSrc >= lineSrcEnd)
393 tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
396 tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
399 tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
402 tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
405 tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
409 lineSrc += m_nStride;
410 lineDst += pDst->m_nStride;
415 uint32_t shift1 = s1 - d1;
416 uint32_t shift2 = 32 - shift1;
417 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
418 for (int32_t yy = yd0; yy < yd1; yy++) {
419 if (lineSrc >= lineSrcEnd)
421 const uint8_t* sp = lineSrc;
422 uint8_t* dp = lineDst;
430 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
433 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
436 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
439 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
442 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
449 for (int32_t xx = 0; xx < middleDwords; xx++) {
465 tmp = ~(tmp1 ^ tmp2);
484 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
487 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
490 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
493 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
496 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
501 lineSrc += m_nStride;
502 lineDst += pDst->m_nStride;
504 }
else if (s1 == d1) {
505 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
506 for (int32_t yy = yd0; yy < yd1; yy++) {
507 if (lineSrc >= lineSrcEnd)
509 const uint8_t* sp = lineSrc;
510 uint8_t* dp = lineDst;
517 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
520 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
523 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
526 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
529 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
536 for (int32_t xx = 0; xx < middleDwords; xx++) {
551 tmp = ~(tmp1 ^ tmp2);
567 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
570 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
573 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
576 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
579 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
584 lineSrc += m_nStride;
585 lineDst += pDst->m_nStride;
588 uint32_t shift1 = d1 - s1;
589 uint32_t shift2 = 32 - shift1;
590 int32_t middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
591 for (int32_t yy = yd0; yy < yd1; yy++) {
592 if (lineSrc >= lineSrcEnd)
594 const uint8_t* sp = lineSrc;
595 uint8_t* dp = lineDst;
602 tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
605 tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
608 tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
611 tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
614 tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
620 for (int32_t xx = 0; xx < middleDwords; xx++) {
636 tmp = ~(tmp1 ^ tmp2);
655 tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
658 tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
661 tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
664 tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
667 tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
672 lineSrc += m_nStride;
673 lineDst += pDst->m_nStride;
constexpr int32_t kJBig2MaxImageSize
#define JBIG2_PUTDWORD(buf, val)
#define JBIG2_GETDWORD(buf)
CJBig2_Image(int32_t w, int32_t h, int32_t stride, pdfium::span< uint8_t > pBuf)
bool ComposeFrom(int32_t x, int32_t y, CJBig2_Image *pSrc, JBig2ComposeOp op)
void SetPixel(int32_t x, int32_t y, int v)
std::unique_ptr< CJBig2_Image > SubImage(int32_t x, int32_t y, int32_t w, int32_t h)
CJBig2_Image(int32_t w, int32_t h)
uint8_t * GetLine(int32_t y) const
void CopyLine(int32_t hTo, int32_t hFrom)
CJBig2_Image(const CJBig2_Image &other)
bool ComposeToWithRect(CJBig2_Image *pDst, int32_t x, int32_t y, const FX_RECT &rtSrc, JBig2ComposeOp op)
static bool IsValidImageSize(int32_t w, int32_t h)
int GetPixel(int32_t x, int32_t y) const
bool ComposeTo(CJBig2_Image *pDst, int32_t x, int32_t y, JBig2ComposeOp op)
uint8_t * GetLineUnsafe(int32_t y) const
void Expand(int32_t h, bool v)
bool ComposeFromWithRect(int32_t x, int32_t y, CJBig2_Image *pSrc, const FX_RECT &rtSrc, JBig2ComposeOp op)