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