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; i<nDestHeight; i++)     
  for(int j = 0; j<nDestWidth; j++)  
  {
   double tmp = i/dfAmplificationY;
   int nLine = (int)tmp;
   
   if(tmp - nLine > 0.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;
}

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值