1bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include "CreateJavaOutputStreamAdaptor.h" 279ad7bedcfaec8ccce22589eb62b342fd0de05afMatt Sarett#include "SkJPEGWriteUtility.h" 3bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include "YuvToJpegEncoder.h" 48f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian#include <ui/PixelFormat.h> 58f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian#include <hardware/hardware.h> 6bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 7ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h" 8ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe 9bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen#include <jni.h> 10bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 11bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuvToJpegEncoder* YuvToJpegEncoder::create(int format, int* strides) { 12a696f5d667227365da732481770767dcb330dd23Mathias Agopian // Only ImageFormat.NV21 and ImageFormat.YUY2 are supported 13bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // for now. 14a696f5d667227365da732481770767dcb330dd23Mathias Agopian if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP) { 15bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return new Yuv420SpToJpegEncoder(strides); 168f2423e8f394ae0666f1b61f83df4c0c7a4782d9Mathias Agopian } else if (format == HAL_PIXEL_FORMAT_YCbCr_422_I) { 17bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return new Yuv422IToJpegEncoder(strides); 18bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } else { 19bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return NULL; 20bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 21bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 22bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 23bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuvToJpegEncoder::YuvToJpegEncoder(int* strides) : fStrides(strides) { 24bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 25bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 26bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenbool YuvToJpegEncoder::encode(SkWStream* stream, void* inYuv, int width, 27bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int height, int* offsets, int jpegQuality) { 28bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_compress_struct cinfo; 29bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen skjpeg_error_mgr sk_err; 30bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen skjpeg_destination_mgr sk_wstream(stream); 31bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 32bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo.err = jpeg_std_error(&sk_err); 33bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen sk_err.error_exit = skjpeg_error_exit; 34bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen if (setjmp(sk_err.fJmpBuf)) { 35bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return false; 36bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 37bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_create_compress(&cinfo); 38bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 39bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo.dest = &sk_wstream; 40bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 41bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen setJpegCompressStruct(&cinfo, width, height, jpegQuality); 42bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 43bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_start_compress(&cinfo, TRUE); 44bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 45bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen compress(&cinfo, (uint8_t*) inYuv, offsets); 46bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 47bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_finish_compress(&cinfo); 48bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 49bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen return true; 50bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 51bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 52bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid YuvToJpegEncoder::setJpegCompressStruct(jpeg_compress_struct* cinfo, 53bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int width, int height, int quality) { 54bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->image_width = width; 55bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->image_height = height; 56bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->input_components = 3; 57bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->in_color_space = JCS_YCbCr; 58bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_set_defaults(cinfo); 59aa86859b1035f865147b4f76ad2a9eed7ee098a5Chia-chi Yeh 60aa86859b1035f865147b4f76ad2a9eed7ee098a5Chia-chi Yeh jpeg_set_quality(cinfo, quality, TRUE); 61bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_set_colorspace(cinfo, JCS_YCbCr); 62bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->raw_data_in = TRUE; 63bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->dct_method = JDCT_IFAST; 64bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen configSamplingFactors(cinfo); 65bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 66bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 67bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen/////////////////////////////////////////////////////////////////// 68bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuv420SpToJpegEncoder::Yuv420SpToJpegEncoder(int* strides) : 69bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen YuvToJpegEncoder(strides) { 70bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen fNumPlanes = 2; 71bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 72bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 73bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv420SpToJpegEncoder::compress(jpeg_compress_struct* cinfo, 74bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yuv, int* offsets) { 75bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen SkDebugf("onFlyCompress"); 76bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW y[16]; 77bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW cb[8]; 78bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW cr[8]; 79bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPARRAY planes[3]; 80bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[0] = y; 81bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[1] = cb; 82bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[2] = cr; 83bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 84bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int width = cinfo->image_width; 85bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int height = cinfo->image_height; 86bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yPlanar = yuv + offsets[0]; 87bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vuPlanar = yuv + offsets[1]; //width * height; 88bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* uRows = new uint8_t [8 * (width >> 1)]; 89bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vRows = new uint8_t [8 * (width >> 1)]; 90bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 91bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 92bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // process 16 lines of Y and 8 lines of U/V each time. 93bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen while (cinfo->next_scanline < cinfo->image_height) { 94bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen //deitnerleave u and v 954b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li deinterleave(vuPlanar, uRows, vRows, cinfo->next_scanline, width, height); 96bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 974b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li // Jpeg library ignores the rows whose indices are greater than height. 98bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen for (int i = 0; i < 16; i++) { 99bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // y row 100bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen y[i] = yPlanar + (cinfo->next_scanline + i) * fStrides[0]; 101bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 102bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // construct u row and v row 103bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen if ((i & 1) == 0) { 104bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // height and width are both halved because of downsampling 105bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int offset = (i >> 1) * (width >> 1); 106bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cb[i/2] = uRows + offset; 107bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cr[i/2] = vRows + offset; 108bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 109bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 110bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_write_raw_data(cinfo, planes, 16); 111bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 112bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] uRows; 113bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] vRows; 114bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 115bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 116bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 117bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv420SpToJpegEncoder::deinterleave(uint8_t* vuPlanar, uint8_t* uRows, 1184b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li uint8_t* vRows, int rowIndex, int width, int height) { 1194b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li int numRows = (height - rowIndex) / 2; 1204b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li if (numRows > 8) numRows = 8; 1214b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li for (int row = 0; row < numRows; ++row) { 122bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int offset = ((rowIndex >> 1) + row) * fStrides[1]; 123bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vu = vuPlanar + offset; 124bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen for (int i = 0; i < (width >> 1); ++i) { 125bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int index = row * (width >> 1) + i; 126bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uRows[index] = vu[1]; 127bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen vRows[index] = vu[0]; 128bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen vu += 2; 129bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 130bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 131bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 132bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 133bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv420SpToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) { 134bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // cb and cr are horizontally downsampled and vertically downsampled as well. 135bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[0].h_samp_factor = 2; 136bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[0].v_samp_factor = 2; 137bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[1].h_samp_factor = 1; 138bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[1].v_samp_factor = 1; 139bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[2].h_samp_factor = 1; 140bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[2].v_samp_factor = 1; 141bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 142bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 143bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen/////////////////////////////////////////////////////////////////////////////// 144bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta ChenYuv422IToJpegEncoder::Yuv422IToJpegEncoder(int* strides) : 145bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen YuvToJpegEncoder(strides) { 146bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen fNumPlanes = 1; 147bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 148bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 149bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv422IToJpegEncoder::compress(jpeg_compress_struct* cinfo, 150bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yuv, int* offsets) { 151bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen SkDebugf("onFlyCompress_422"); 152bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW y[16]; 153bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW cb[16]; 154bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPROW cr[16]; 155bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen JSAMPARRAY planes[3]; 156bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[0] = y; 157bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[1] = cb; 158bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen planes[2] = cr; 159bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 160bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int width = cinfo->image_width; 161bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int height = cinfo->image_height; 162bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yRows = new uint8_t [16 * width]; 163bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* uRows = new uint8_t [16 * (width >> 1)]; 164bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vRows = new uint8_t [16 * (width >> 1)]; 165bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 166bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yuvOffset = yuv + offsets[0]; 167bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 168bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // process 16 lines of Y and 16 lines of U/V each time. 169bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen while (cinfo->next_scanline < cinfo->image_height) { 170bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen deinterleave(yuvOffset, yRows, uRows, vRows, cinfo->next_scanline, width, height); 171bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 1724b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li // Jpeg library ignores the rows whose indices are greater than height. 173bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen for (int i = 0; i < 16; i++) { 174bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // y row 175bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen y[i] = yRows + i * width; 176bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 177bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // construct u row and v row 178bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // width is halved because of downsampling 179bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int offset = i * (width >> 1); 180bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cb[i] = uRows + offset; 181bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cr[i] = vRows + offset; 182bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 183bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 184bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jpeg_write_raw_data(cinfo, planes, 16); 185bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 186bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] yRows; 187bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] uRows; 188bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen delete [] vRows; 189bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 190bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 191bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 192bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv422IToJpegEncoder::deinterleave(uint8_t* yuv, uint8_t* yRows, uint8_t* uRows, 193bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* vRows, int rowIndex, int width, int height) { 1944b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li int numRows = height - rowIndex; 1954b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li if (numRows > 16) numRows = 16; 1964b63f14c96841d02b6bffce987f7705b6aa8e2a9Wu-cheng Li for (int row = 0; row < numRows; ++row) { 197bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uint8_t* yuvSeg = yuv + (rowIndex + row) * fStrides[0]; 198bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen for (int i = 0; i < (width >> 1); ++i) { 199bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int indexY = row * width + (i << 1); 200bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen int indexU = row * (width >> 1) + i; 201bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen yRows[indexY] = yuvSeg[0]; 202bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen yRows[indexY + 1] = yuvSeg[2]; 203bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen uRows[indexU] = yuvSeg[1]; 204bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen vRows[indexU] = yuvSeg[3]; 205bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen yuvSeg += 4; 206bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 207bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 208bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 209bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 210bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenvoid Yuv422IToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) { 211bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen // cb and cr are horizontally downsampled and vertically downsampled as well. 212bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[0].h_samp_factor = 2; 213bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[0].v_samp_factor = 2; 214bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[1].h_samp_factor = 1; 215bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[1].v_samp_factor = 2; 216bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[2].h_samp_factor = 1; 217bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen cinfo->comp_info[2].v_samp_factor = 2; 218bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 219bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen/////////////////////////////////////////////////////////////////////////////// 220bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 221bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenstatic jboolean YuvImage_compressToJpeg(JNIEnv* env, jobject, jbyteArray inYuv, 22239029b29906fb064fc1e408983809b9b7ad74095Ashok Bhat jint format, jint width, jint height, jintArray offsets, 22339029b29906fb064fc1e408983809b9b7ad74095Ashok Bhat jintArray strides, jint jpegQuality, jobject jstream, 224bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jbyteArray jstorage) { 225bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jbyte* yuv = env->GetByteArrayElements(inYuv, NULL); 226bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); 227bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 228bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jint* imgOffsets = env->GetIntArrayElements(offsets, NULL); 229bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen jint* imgStrides = env->GetIntArrayElements(strides, NULL); 230bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen YuvToJpegEncoder* encoder = YuvToJpegEncoder::create(format, imgStrides); 2317c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn jboolean result = JNI_FALSE; 2327c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn if (encoder != NULL) { 2337c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn encoder->encode(strm, yuv, width, height, imgOffsets, jpegQuality); 2347c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn delete encoder; 2357c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn result = JNI_TRUE; 236bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen } 237bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 238bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen env->ReleaseByteArrayElements(inYuv, yuv, 0); 239bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen env->ReleaseIntArrayElements(offsets, imgOffsets, 0); 240bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen env->ReleaseIntArrayElements(strides, imgStrides, 0); 241d865900425d9593974aac640bc4deb93865dcfbeMartin Wallgren delete strm; 2427c68a4076e1ef141db5ac338d675646a278f0eb8Pawel Augustyn return result; 243bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 244bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen/////////////////////////////////////////////////////////////////////////////// 245bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 24676f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gYuvImageMethods[] = { 247bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen { "nativeCompressToJpeg", "([BIII[I[IILjava/io/OutputStream;[B)Z", 248bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen (void*)YuvImage_compressToJpeg } 249bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen}; 250bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen 251bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chenint register_android_graphics_YuvImage(JNIEnv* env) 252bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen{ 253ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe return android::RegisterMethodsOrDie(env, "android/graphics/YuvImage", gYuvImageMethods, 254ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe NELEM(gYuvImageMethods)); 255bca2d613e0d6d2630fedd302c0d779b7610adbcfWei-Ta Chen} 256