bool CCodec_ScanlineDecoder::ImageDataCache::AllocateCache() { if (m_Pitch == 0 || m_Height < 0) return false; FX_SAFE_SIZE_T size = m_Pitch; size *= m_Height; if (!size.IsValid()) return false; m_Data.reset(FX_TryAlloc(uint8_t, size.ValueOrDie())); return IsValid(); }
void CCodec_ScanlineDecoder::DownScale(int dest_width, int dest_height) { if (dest_width < 0) { dest_width = -dest_width; } if (dest_height < 0) { dest_height = -dest_height; } v_DownScale(dest_width, dest_height); if (m_pDataCache) { if (m_pDataCache->m_Height == m_OutputHeight && m_pDataCache->m_Width == m_OutputWidth) { return; } FX_Free(m_pDataCache); m_pDataCache = NULL; } m_pDataCache = (CCodec_ImageDataCache*)FX_TryAlloc(uint8_t, sizeof(CCodec_ImageDataCache) + m_Pitch * m_OutputHeight); if (m_pDataCache == NULL) { return; } m_pDataCache->m_Height = m_OutputHeight; m_pDataCache->m_Width = m_OutputWidth; m_pDataCache->m_nCachedLines = 0; }
void CWeightTable::Calc(int dest_len, int dest_min, int dest_max, int src_len, int src_min, int src_max, int flags) { if (m_pWeightTables) { FX_Free(m_pWeightTables); m_pWeightTables = NULL; } double scale, base; scale = FXSYS_Div((FX_FLOAT)(src_len), (FX_FLOAT)(dest_len)); if (dest_len < 0) { base = (FX_FLOAT)(src_len); } else { base = 0; } int ext_size = flags & FXDIB_BICUBIC_INTERPOL ? 3 : 1; m_ItemSize = sizeof(int) * 2 + (int)(sizeof(int) * (FXSYS_ceil(FXSYS_fabs((FX_FLOAT)scale)) + ext_size)); m_DestMin = dest_min; if ((dest_max - dest_min) > (int)((1U << 30) - 4) / m_ItemSize) { return; } m_pWeightTables = FX_TryAlloc(FX_BYTE, (dest_max - dest_min) * m_ItemSize + 4); if (m_pWeightTables == NULL) { return; } if ((flags & FXDIB_NOSMOOTH) != 0 || FXSYS_fabs((FX_FLOAT)scale) < 1.0f) { for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel ++) { PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); double src_pos = dest_pixel * scale + scale / 2 + base; if (flags & FXDIB_INTERPOL) { pixel_weights.m_SrcStart = (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); if (pixel_weights.m_SrcStart < src_min) { pixel_weights.m_SrcStart = src_min; } if (pixel_weights.m_SrcEnd >= src_max) { pixel_weights.m_SrcEnd = src_max - 1; } if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { pixel_weights.m_Weights[0] = 65536; } else { pixel_weights.m_Weights[1] = FXSYS_round((FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 65536); pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1]; } } else if (flags & FXDIB_BICUBIC_INTERPOL) { pixel_weights.m_SrcStart = (int)FXSYS_floor((FX_FLOAT)src_pos - 1.0f / 2); pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos + 1.0f / 2); int start = pixel_weights.m_SrcStart - 1; int end = pixel_weights.m_SrcEnd + 1; if (start < src_min) { start = src_min; } if (end >= src_max) { end = src_max - 1; } if (pixel_weights.m_SrcStart < src_min) { src_pos += src_min - pixel_weights.m_SrcStart; pixel_weights.m_SrcStart = src_min; } if (pixel_weights.m_SrcEnd >= src_max) { pixel_weights.m_SrcEnd = src_max - 1; } int weight; weight = FXSYS_round((FX_FLOAT)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 256); if (start == end) { pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_Table[weight] + SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; } else if ((start == pixel_weights.m_SrcStart && (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd || end == pixel_weights.m_SrcEnd) && start < end) || (start < pixel_weights.m_SrcStart && pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd && end == pixel_weights.m_SrcEnd)) { if (start < pixel_weights.m_SrcStart) { pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; pixel_weights.m_Weights[1] = (SDP_Table[weight] + SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; } else { if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_Table[weight] + SDP_Table[256 - weight]) << 8; pixel_weights.m_Weights[1] = SDP_Table[512 - weight] << 8; } else { pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; pixel_weights.m_Weights[1] = (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; } } if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) { pixel_weights.m_SrcEnd = end; } if (start < pixel_weights.m_SrcStart) { pixel_weights.m_SrcStart = start; } } else if (start == pixel_weights.m_SrcStart && start < pixel_weights.m_SrcEnd && pixel_weights.m_SrcEnd < end) { pixel_weights.m_Weights[0] = (SDP_Table[256 + weight] + SDP_Table[weight]) << 8; pixel_weights.m_Weights[1] = SDP_Table[256 - weight] << 8; pixel_weights.m_Weights[2] = SDP_Table[512 - weight] << 8; pixel_weights.m_SrcEnd = end; } else if (start < pixel_weights.m_SrcStart && pixel_weights.m_SrcStart < pixel_weights.m_SrcEnd && pixel_weights.m_SrcEnd == end) { pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; pixel_weights.m_Weights[2] = (SDP_Table[256 - weight] + SDP_Table[512 - weight]) << 8; pixel_weights.m_SrcStart = start; } else { pixel_weights.m_Weights[0] = SDP_Table[256 + weight] << 8; pixel_weights.m_Weights[1] = SDP_Table[weight] << 8; pixel_weights.m_Weights[2] = SDP_Table[256 - weight] << 8; pixel_weights.m_Weights[3] = SDP_Table[512 - weight] << 8; pixel_weights.m_SrcStart = start; pixel_weights.m_SrcEnd = end; } } else { pixel_weights.m_SrcStart = pixel_weights.m_SrcEnd = (int)FXSYS_floor((FX_FLOAT)src_pos); if (pixel_weights.m_SrcStart < src_min) { pixel_weights.m_SrcStart = src_min; } if (pixel_weights.m_SrcEnd >= src_max) { pixel_weights.m_SrcEnd = src_max - 1; } pixel_weights.m_Weights[0] = 65536; } } return; } for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel ++) { PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel); double src_start = dest_pixel * scale + base; double src_end = src_start + scale; int start_i, end_i; if (src_start < src_end) { start_i = (int)FXSYS_floor((FX_FLOAT)src_start); end_i = (int)FXSYS_ceil((FX_FLOAT)src_end); } else { start_i = (int)FXSYS_floor((FX_FLOAT)src_end); end_i = (int)FXSYS_ceil((FX_FLOAT)src_start); } if (start_i < src_min) { start_i = src_min; } if (end_i >= src_max) { end_i = src_max - 1; } if (start_i > end_i) { if (start_i >= src_max) { start_i = src_max - 1; } pixel_weights.m_SrcStart = start_i; pixel_weights.m_SrcEnd = start_i; continue; } pixel_weights.m_SrcStart = start_i; pixel_weights.m_SrcEnd = end_i; for (int j = start_i; j <= end_i; j ++) { double dest_start = FXSYS_Div((FX_FLOAT)(j) - base, scale); double dest_end = FXSYS_Div((FX_FLOAT)(j + 1) - base, scale); if (dest_start > dest_end) { double temp = dest_start; dest_start = dest_end; dest_end = temp; } double area_start = dest_start > (FX_FLOAT)(dest_pixel) ? dest_start : (FX_FLOAT)(dest_pixel); double area_end = dest_end > (FX_FLOAT)(dest_pixel + 1) ? (FX_FLOAT)(dest_pixel + 1) : dest_end; double weight = area_start >= area_end ? 0.0f : area_end - area_start; if (weight == 0 && j == end_i) { pixel_weights.m_SrcEnd --; break; } pixel_weights.m_Weights[j - start_i] = FXSYS_round((FX_FLOAT)(weight * 65536)); } } }
CStretchEngine::CStretchEngine(IFX_ScanlineComposer* pDestBitmap, FXDIB_Format dest_format, int dest_width, int dest_height, const FX_RECT& clip_rect, const CFX_DIBSource* pSrcBitmap, int flags) { m_State = 0; m_DestFormat = dest_format; m_DestBpp = dest_format & 0xff; m_SrcBpp = pSrcBitmap->GetFormat() & 0xff; m_bHasAlpha = pSrcBitmap->GetFormat() & 0x200; m_pSrcPalette = pSrcBitmap->GetPalette(); m_pDestBitmap = pDestBitmap; m_DestWidth = dest_width; m_DestHeight = dest_height; m_pInterBuf = NULL; m_pExtraAlphaBuf = NULL; m_pDestMaskScanline = NULL; m_DestClip = clip_rect; FX_DWORD size = clip_rect.Width(); if (size && m_DestBpp > (int)(INT_MAX / size)) { return; } size *= m_DestBpp; if (size > INT_MAX - 31) { return; } size += 31; size = size / 32 * 4; m_pDestScanline = FX_TryAlloc(FX_BYTE, size); if (m_pDestScanline == NULL) { return; } if (dest_format == FXDIB_Rgb32) { FXSYS_memset8(m_pDestScanline, 255, size); } m_InterPitch = (m_DestClip.Width() * m_DestBpp + 31) / 32 * 4; m_ExtraMaskPitch = (m_DestClip.Width() * 8 + 31) / 32 * 4; m_pInterBuf = NULL; m_pSource = pSrcBitmap; m_SrcWidth = pSrcBitmap->GetWidth(); m_SrcHeight = pSrcBitmap->GetHeight(); m_SrcPitch = (m_SrcWidth * m_SrcBpp + 31) / 32 * 4; if ((flags & FXDIB_NOSMOOTH) == 0) { FX_BOOL bInterpol = flags & FXDIB_INTERPOL || flags & FXDIB_BICUBIC_INTERPOL; if (!bInterpol && FXSYS_abs(dest_width) != 0 && FXSYS_abs(dest_height) < m_SrcWidth * m_SrcHeight * 8 / FXSYS_abs(dest_width)) { flags = FXDIB_INTERPOL; } m_Flags = flags; } else { m_Flags = FXDIB_NOSMOOTH; if (flags & FXDIB_DOWNSAMPLE) { m_Flags |= FXDIB_DOWNSAMPLE; } } double scale_x = FXSYS_Div((FX_FLOAT)(m_SrcWidth), (FX_FLOAT)(m_DestWidth)); double scale_y = FXSYS_Div((FX_FLOAT)(m_SrcHeight), (FX_FLOAT)(m_DestHeight)); double base_x = m_DestWidth > 0 ? 0.0f : (FX_FLOAT)(m_DestWidth); double base_y = m_DestHeight > 0 ? 0.0f : (FX_FLOAT)(m_DestHeight); double src_left = FXSYS_Mul(scale_x, (FX_FLOAT)(clip_rect.left) + base_x); double src_right = FXSYS_Mul(scale_x, (FX_FLOAT)(clip_rect.right) + base_x); double src_top = FXSYS_Mul(scale_y, (FX_FLOAT)(clip_rect.top) + base_y); double src_bottom = FXSYS_Mul(scale_y, (FX_FLOAT)(clip_rect.bottom) + base_y); if (src_left > src_right) { double temp = src_left; src_left = src_right; src_right = temp; } if (src_top > src_bottom) { double temp = src_top; src_top = src_bottom; src_bottom = temp; } m_SrcClip.left = (int)FXSYS_floor((FX_FLOAT)src_left); m_SrcClip.right = (int)FXSYS_ceil((FX_FLOAT)src_right); m_SrcClip.top = (int)FXSYS_floor((FX_FLOAT)src_top); m_SrcClip.bottom = (int)FXSYS_ceil((FX_FLOAT)src_bottom); FX_RECT src_rect(0, 0, m_SrcWidth, m_SrcHeight); m_SrcClip.Intersect(src_rect); if (m_SrcBpp == 1) { if (m_DestBpp == 8) { m_TransMethod = 1; } else { m_TransMethod = 2; } } else if (m_SrcBpp == 8) { if (m_DestBpp == 8) { if (!m_bHasAlpha) { m_TransMethod = 3; } else { m_TransMethod = 4; } } else { if (!m_bHasAlpha) { m_TransMethod = 5; } else { m_TransMethod = 6; } } } else { if (!m_bHasAlpha) { m_TransMethod = 7; } else { m_TransMethod = 8; } } }
static void _JpegEncode(const CFX_DIBSource* pSource, FX_LPBYTE& dest_buf, FX_STRSIZE& dest_size, int quality, FX_LPCBYTE icc_buf, FX_DWORD icc_length) { struct jpeg_error_mgr jerr; jerr.error_exit = _error_do_nothing; jerr.emit_message = _error_do_nothing1; jerr.output_message = _error_do_nothing; jerr.format_message = _error_do_nothing2; jerr.reset_error_mgr = _error_do_nothing; struct jpeg_compress_struct cinfo; memset(&cinfo, 0, sizeof(cinfo)); cinfo.err = &jerr; jpeg_create_compress(&cinfo); int Bpp = pSource->GetBPP() / 8; FX_DWORD nComponents = Bpp >= 3 ? (pSource->IsCmykImage() ? 4 : 3) : 1; FX_DWORD pitch = pSource->GetPitch(); FX_DWORD width = pdfium::base::checked_cast<FX_DWORD>(pSource->GetWidth()); FX_DWORD height = pdfium::base::checked_cast<FX_DWORD>(pSource->GetHeight()); FX_SAFE_DWORD safe_buf_len = width; safe_buf_len *= height; safe_buf_len *= nComponents; safe_buf_len += 1024; if (icc_length) { safe_buf_len += 255 * 18; safe_buf_len += icc_length; } FX_DWORD dest_buf_length = 0; if (!safe_buf_len.IsValid()) { dest_buf = nullptr; } else { dest_buf_length = safe_buf_len.ValueOrDie(); dest_buf = FX_TryAlloc(FX_BYTE, dest_buf_length); const int MIN_TRY_BUF_LEN = 1024; while (!dest_buf && dest_buf_length > MIN_TRY_BUF_LEN) { dest_buf_length >>= 1; dest_buf = FX_TryAlloc(FX_BYTE, dest_buf_length); } } if (!dest_buf) { FX_OutOfMemoryTerminate(); } struct jpeg_destination_mgr dest; dest.init_destination = _dest_do_nothing; dest.term_destination = _dest_do_nothing; dest.empty_output_buffer = _dest_empty; dest.next_output_byte = dest_buf; dest.free_in_buffer = dest_buf_length; cinfo.dest = &dest; cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = nComponents; if (nComponents == 1) { cinfo.in_color_space = JCS_GRAYSCALE; } else if (nComponents == 3) { cinfo.in_color_space = JCS_RGB; } else { cinfo.in_color_space = JCS_CMYK; } FX_LPBYTE line_buf = NULL; if (nComponents > 1) { line_buf = FX_Alloc2D(FX_BYTE, width, nComponents); } jpeg_set_defaults(&cinfo); if(quality != 75) { jpeg_set_quality(&cinfo, quality, TRUE); } jpeg_start_compress(&cinfo, TRUE); _JpegEmbedIccProfile(&cinfo, icc_buf, icc_length); JSAMPROW row_pointer[1]; JDIMENSION row; while (cinfo.next_scanline < cinfo.image_height) { FX_LPCBYTE src_scan = pSource->GetScanline(cinfo.next_scanline); if (nComponents > 1) { FX_LPBYTE dest_scan = line_buf; if (nComponents == 3) { for (int i = 0; i < width; i ++) { dest_scan[0] = src_scan[2]; dest_scan[1] = src_scan[1]; dest_scan[2] = src_scan[0]; dest_scan += 3; src_scan += Bpp; } } else { for (int i = 0; i < pitch; i ++) { *dest_scan++ = ~*src_scan++; } } row_pointer[0] = line_buf; } else { row_pointer[0] = (FX_LPBYTE)src_scan; } row = cinfo.next_scanline; jpeg_write_scanlines(&cinfo, row_pointer, 1); if (cinfo.next_scanline == row) { dest_buf = FX_Realloc(FX_BYTE, dest_buf, dest_buf_length + JPEG_BLOCK_SIZE); dest.next_output_byte = dest_buf + dest_buf_length - dest.free_in_buffer; dest_buf_length += JPEG_BLOCK_SIZE; dest.free_in_buffer += JPEG_BLOCK_SIZE; } } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); if (line_buf) { FX_Free(line_buf); } dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer; }