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;
}
示例#2
0
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_compress_struct cinfo;
    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;
    cinfo.err = &jerr;
    jpeg_create_compress(&cinfo);
    int Bpp = pSource->GetBPP() / 8;
    int nComponents = Bpp >= 3 ? (pSource->IsCmykImage() ? 4 : 3) : 1;
    int pitch = pSource->GetPitch();
    int width = pSource->GetWidth();
    int height = pSource->GetHeight();
    FX_DWORD dest_buf_length = width * height * nComponents + 1024 + (icc_length ? (icc_length + 255 * 18) : 0);
    dest_buf = FX_Alloc(FX_BYTE, dest_buf_length);
    while (dest_buf == NULL) {
        dest_buf_length >>= 1;
        dest_buf = FX_Alloc(FX_BYTE, dest_buf_length);
    }
    FXSYS_memset32(dest_buf, 0, dest_buf_length);
    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_Alloc(FX_BYTE, width * nComponents);
        if (line_buf == NULL) {
            return;
        }
    }
    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);
            if (dest_buf == NULL) {
                FX_Free(line_buf);
                return;
            }
            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;
}