PassOwnPtr<JPEGImageEncoderState> JPEGImageEncoderState::create(const IntSize& imageSize, const double& quality, Vector<unsigned char>* output) { if (imageSize.width() <= 0 || imageSize.height() <= 0) return nullptr; OwnPtr<JPEGImageEncoderStateImpl> encoderState = adoptPtr(new JPEGImageEncoderStateImpl()); jpeg_compress_struct* cinfo = encoderState->cinfo(); jpeg_error_mgr* error = encoderState->error(); cinfo->err = jpeg_std_error(error); error->error_exit = handleError; jmp_buf jumpBuffer; cinfo->client_data = &jumpBuffer; if (setjmp(jumpBuffer)) { return nullptr; } JPEGOutputBuffer* destination = encoderState->outputBuffer(); destination->output = output; jpeg_create_compress(cinfo); cinfo->dest = destination; cinfo->dest->init_destination = prepareOutput; cinfo->dest->empty_output_buffer = writeOutput; cinfo->dest->term_destination = finishOutput; cinfo->image_height = imageSize.height(); cinfo->image_width = imageSize.width(); cinfo->in_color_space = JCS_RGB; cinfo->input_components = 3; jpeg_set_defaults(cinfo); int compressionQuality = JPEGImageEncoder::computeCompressionQuality(quality); jpeg_set_quality(cinfo, compressionQuality, TRUE); disableSubsamplingForHighQuality(cinfo, compressionQuality); jpeg_start_compress(cinfo, TRUE); cinfo->client_data = 0; return encoderState.release(); }
static bool encodePixels(IntSize imageSize, unsigned char* inputPixels, bool premultiplied, int quality, Vector<unsigned char>* output) { JPEGOutputBuffer destination; destination.output = output; Vector<JSAMPLE> row; jpeg_compress_struct cinfo; jpeg_error_mgr error; cinfo.err = jpeg_std_error(&error); error.error_exit = handleError; jmp_buf jumpBuffer; cinfo.client_data = &jumpBuffer; if (setjmp(jumpBuffer)) { jpeg_destroy_compress(&cinfo); return false; } jpeg_create_compress(&cinfo); cinfo.dest = &destination; cinfo.dest->init_destination = prepareOutput; cinfo.dest->empty_output_buffer = writeOutput; cinfo.dest->term_destination = finishOutput; imageSize.clampNegativeToZero(); cinfo.image_height = imageSize.height(); cinfo.image_width = imageSize.width(); #if defined(JCS_EXTENSIONS) if (premultiplied) { cinfo.in_color_space = SK_B32_SHIFT ? JCS_EXT_RGBX : JCS_EXT_BGRX; cinfo.input_components = 4; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); disableSubsamplingForHighQuality(&cinfo, quality); jpeg_start_compress(&cinfo, TRUE); unsigned char* pixels = inputPixels; const size_t pixelRowStride = cinfo.image_width * 4; while (cinfo.next_scanline < cinfo.image_height) { jpeg_write_scanlines(&cinfo, &pixels, 1); pixels += pixelRowStride; } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); return true; } #endif cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3; void (*extractRowRGB)(const unsigned char*, unsigned int, unsigned char* output); extractRowRGB = &RGBAtoRGB; if (premultiplied) extractRowRGB = &preMultipliedBGRAtoRGB; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, quality, TRUE); disableSubsamplingForHighQuality(&cinfo, quality); jpeg_start_compress(&cinfo, TRUE); unsigned char* pixels = inputPixels; row.resize(cinfo.image_width * cinfo.input_components); const size_t pixelRowStride = cinfo.image_width * 4; while (cinfo.next_scanline < cinfo.image_height) { JSAMPLE* rowData = row.data(); extractRowRGB(pixels, cinfo.image_width, rowData); jpeg_write_scanlines(&cinfo, &rowData, 1); pixels += pixelRowStride; } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); return true; }