android camera 编码通道,Android之Camera拍照插值算法

一、rgb插值算法

说明:验证可用,算法效率一般;其中pDest为扩帧后内存地址,nDestWidth和nDestHeight为扩帧后分辨率,nDestBits为色深(如rgb24则为24)。

void rgbInterpolation(void* pDest, int nDestWidth, int nDestHeight, int nDestBits, void* pSrc, int nSrcWidth, int nSrcHeight, int nSrcBits)

{

//ASSERT_EXP(pDest != NULL);

//ASSERT_EXP((nDestBits == 32) || (nDestBits == 24));

//ASSERT_EXP((nDestWidth > 0) && (nDestHeight > 0));

//ASSERT_EXP(pSrc != NULL);

//ASSERT_EXP((nSrcBits == 32) || (nSrcBits == 24));

//ASSERT_EXP((nSrcWidth > 0) && (nSrcHeight > 0));

double dfAmplificationX = ((double)nDestWidth)/nSrcWidth;

double dfAmplificationY = ((double)nDestHeight)/nSrcHeight;

const int nSrcColorLen = nSrcBits/8;

const int nDestColorLen = nDestBits/8;

for(int i = 0; i0.5)

++nLine;

if(nLine >= nSrcHeight)

--nLine;

tmp = j/dfAmplificationX;

int nRow = (int)tmp;

if(tmp - nRow > 0.5)

++nRow;

if(nRow >= nSrcWidth)

--nRow;

unsigned char *pSrcPos = (unsigned char*)pSrc + (nLine*nSrcWidth + nRow)*nSrcColorLen;

unsigned char *pDestPos = (unsigned char*)pDest + (i*nDestWidth + j)*nDestColorLen;

*pDestPos++ = *pSrcPos++;

*pDestPos++ = *pSrcPos++;

*pDestPos++ = *pSrcPos++;

if(nDestColorLen == 4)

*pDestPos = 0;

}

}二、yuyv转rgb并jpeg编码的插帧算法

说明:该算法经过验证可行;效率较上边略高,是将rgb的转化省略、进而嵌套在jpeg编码中。

/* private member functions */

/*

struct params {

uint8_t* src;

int src_size;

uint8_t* dst; //需要插帧时,该buffer大小为3264*2448*3Byte

int dst_size; //需要插帧时,大小为3264*2448*3Byte

int quality;

int in_width;

int in_height;

int out_width; //需要插帧时,该位为3264

int out_height; //需要插帧时,该位为2448

const char* format;

size_t jpeg_size;

};

*/

size_t Encoder_libjpeg::encode(params* input) {

jpeg_compress_struct cinfo;

jpeg_error_mgr jerr;

jpeg_destination_mgr jdest;

uint8_t* src = NULL, *resize_src = NULL;

uint8_t* row_tmp = NULL;

uint8_t* row_src = NULL;

uint8_t* row_uv = NULL; // used only for NV12

int row_stride;

int out_width = 0, in_width = 0;

int out_height = 0, in_height = 0;

int bpp = 2; // for uyvy

Encoder_libjpeg::format informat = Encoder_libjpeg::YUV422I;

if (!input) {

return 0;

}

out_width = input->out_width;

in_width = input->in_width;

out_height = input->out_height;

in_height = input->in_height;

src = input->src;

input->jpeg_size = 0;

libjpeg_destination_mgr dest_mgr(input->dst, input->dst_size);

// param check...

if ((in_width < 2) || (out_width < 2) || (in_height < 2) || (out_height < 2) ||

(src == NULL) || (input->dst == NULL) || (input->quality < 1) || (input->src_size < 1) ||

(input->dst_size < 1) || (input->format == NULL)) {

goto exit;

}

if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV420SP) == 0) {

//add by tankai

if(in_width < out_height){

informat = Encoder_libjpeg::RGB24;

}

else{

//end tankai

informat = Encoder_libjpeg::YUV420SP;

bpp = 1;

if ((in_width != out_width) || (in_height != out_height)) {

resize_src = (uint8_t*) malloc(input->dst_size);

resize_nv12(input, resize_src);

if (resize_src) src = resize_src;

}

}//add by tankai

} else if (strcmp(input->format, CameraProperties::PIXEL_FORMAT_RGB24) == 0) {

informat = Encoder_libjpeg::RGB24;

bpp = 1;

if ((in_width != out_width) || (in_height != out_height)) {

resize_src = (uint8_t*) malloc(input->dst_size);

if(NULL != resize_src){

extraSmallImg(input->src, in_width, in_height,

resize_src, out_width, out_height);

src = resize_src;

}else{

CAMHAL_LOGDA("failed to malloc space to extra thumbnail\n");

goto exit;

}

}

} else if ((in_width != out_width) || (in_height != out_height)) {

CAMHAL_LOGEB("Encoder: resizing is not supported for this format: %s", input->format);

goto exit;

} else if (strcmp(input->format, CameraParameters::PIXEL_FORMAT_YUV422I)) {

// we currently only support yuv422i and yuv420sp

CAMHAL_LOGEB("Encoder: format not supported: %s", input->format);

goto exit;

}

cinfo.err = jpeg_std_error(&jerr);

jpeg_create_compress(&cinfo);

CAMHAL_LOGDB("encoding... \n\t"

"width: %d \n\t"

"height:%d \n\t"

"dest %p \n\t"

"dest size:%d \n\t"

"mSrc %p",

out_width, out_height, input->dst,

input->dst_size, src);

cinfo.dest = &dest_mgr;

cinfo.image_width = out_width;

cinfo.image_height = out_height;

cinfo.input_components = 3;

if (informat == Encoder_libjpeg::RGB24)

cinfo.in_color_space = JCS_RGB;

else

cinfo.in_color_space = JCS_YCbCr;

cinfo.input_gamma = 1;

jpeg_set_defaults(&cinfo);

jpeg_set_quality(&cinfo, input->quality, TRUE);

cinfo.dct_method = JDCT_IFAST;

jpeg_start_compress(&cinfo, TRUE);

row_tmp = (uint8_t*)malloc(out_width * 3);

row_src = src;

row_uv = src + out_width * out_height * bpp;

row_stride = out_width * 3;

//add by tankai 插帧部分

if(in_width < out_height){

int i,j,z,ratex,ratey=0; unsigned char *ptr;

while ((cinfo.next_scanline < cinfo.image_height) && !mCancelEncoding) {

JSAMPROW row_pointer[1];

if ((ratey-=10)<0){

ratey+=51;

ratex=0;

ptr=row_tmp;

z = 0;

for (j=0; j<3264; j++){

if ((ratex-=10)<0){

ratex+=51;

{

int r, g, b;

int y, u, v;

if (!z)

y = src[0] << 8;

else

y = src[2] << 8;

u = src[1] - 128;

v = src[3] - 128;

r = (y + (359 * v)) >> 8;

g = (y - (88 * u) - (183 * v)) >> 8;

b = (y + (454 * u)) >> 8;

*(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);

*(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);

*(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);

if (z++){

z = 0;

src += 4;

}

}

}else{

register unsigned char rgbchar;

rgbchar=*(ptr-3);

*(ptr++)=rgbchar;

rgbchar=*(ptr-3);

*(ptr++)=rgbchar;

rgbchar=*(ptr-3);

*(ptr++)=rgbchar;

}

}

}

row_pointer[0] = row_tmp;

jpeg_write_scanlines (&cinfo, row_pointer, 1);

}

}

else

//end tankai 插帧部分

while ((cinfo.next_scanline < cinfo.image_height) && !mCancelEncoding) {

JSAMPROW row[1]; /* pointer to JSAMPLE row[s] */

if (informat == Encoder_libjpeg::RGB24) {

row[0] = &src[cinfo.next_scanline * row_stride];

(void) jpeg_write_scanlines(&cinfo, row, 1);

} else {

// convert input yuv format to yuv444

if (informat == Encoder_libjpeg::YUV420SP) {

nv21_to_yuv(row_tmp, row_src, row_uv, out_width);

} else if (informat == Encoder_libjpeg::YUV422I) {

//uyvy_to_yuv(row_tmp, (uint32_t*)row_src, out_width);

yuyv_to_yuv(row_tmp, (uint32_t*)row_src, out_width);

}

row[0] = row_tmp;

jpeg_write_scanlines(&cinfo, row, 1);

row_src = row_src + out_width*bpp;

// move uv row if input format needs it

if (informat == Encoder_libjpeg::YUV420SP) {

if (!(cinfo.next_scanline % 2))

row_uv = row_uv + out_width * bpp;

}

}

}

// no need to finish encoding routine if we are prematurely stopping

// we will end up crashing in dest_mgr since data is incomplete

if (!mCancelEncoding)

jpeg_finish_compress(&cinfo);

jpeg_destroy_compress(&cinfo);

if (resize_src) free(resize_src);

if (row_tmp) free(row_tmp);

exit:

input->jpeg_size = dest_mgr.jpegsize;

return dest_mgr.jpegsize;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值