/ Split Y, U, V planes in YUV420P file. @param jstr_url Location of Input YUV file. @param w Width of Input YUV file. @param h Height of Input YUV file. @param num Number of frames to process. 分离YUV420P像素数据中的Y、U、V分量 如果视频帧的宽和高分别为w和h,那么一帧YUV420P像素数据一共占用wh3/2 Byte的数据。其中前wh Byte存储Y,接着的wh1/4 Byte存储U,最后wh1/4 Byte存储V /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_yuv420Split( JNIEnv env,jobject / this /, jstring jstr_url, jint w, jint h, jint num) { char input_url[100] = {0}; const char str = env->GetStringUTFChars(jstr_url, NULL); sprintf(input_url,"%s",str); env->ReleaseStringUTFChars(jstr_url,str); FILE fp = fopen(input_url,"rb+"); if(fp == NULL) return -1; strcpy(input_url+strlen(input_url)-4,"_y.y"); FILE fp1 = fopen(input_url,"wb+"); strcpy(input_url+strlen(input_url)-4,"_u.y"); FILE fp2 = fopen(input_url,"wb+"); strcpy(input_url+strlen(input_url)-4,"_v.y"); FILE fp3 = fopen(input_url,"wb+"); unsigned char pic = (unsigned char )malloc(wh3/2); for(int i = 0;i < num;i++) { fread(pic, 1, w h 3 / 2, fp); //Y fwrite(pic, 1, w h, fp1); //U fwrite(pic + w h, 1, w h / 4, fp2); //V fwrite(pic + w h 5 / 4, 1, w h / 4, fp3); } free(pic); fclose(fp); fclose(fp1); fclose(fp2); fclose(fp3); return 0;}
函数调用AVUtils.getInstance().yuv420Split(ROOT+"lena_256x256_yuv420p.yuv",256,256,1);
运行上面代码后会在同目录下生成y、u、v三个文件,工具查看要改为对应格式和分辨率大小查看lena_256x256_yuv420p_y.y: Y数据, 分辨率为256x256lena_256x256_yuv420p_u.y: U数据, 分辨率为128x128lena_256x256_yuv420p_v.y: V数据, 分辨率为128x128
原始图片:lena_256x256_yuv420p.yuv生成的y、u、v分量图片如下:lena_256x256_yuv420p_y.ylena_256x256_yuv420p_u.ylena_256x256_yuv420p_v.y2) 分离YUV444P像素数据中的Y、U、V分量/ Split Y, U, V planes in YUV444P file. @param jstr_url Location of YUV file. @param w Width of Input YUV file. @param h Height of Input YUV file. @param num Number of frames to process. 分离YUV444P像素数据中的Y、U、V分量 如果视频帧的宽和高分别为w和h,那么一帧YUV444P像素数据一共占用wh3 Byte的数据。其中前wh Byte存储Y,接着的wh Byte存储U,最后wh Byte存储V /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_yuv444Split( JNIEnv env,jobject / this /, jstring jstr_url, jint w, jint h, jint num) { char input_url[100] = {0}; const char str = env->GetStringUTFChars(jstr_url, NULL); sprintf(input_url,"%s",str); env->ReleaseStringUTFChars(jstr_url,str); FILE fp = fopen(input_url,"rb+"); if(fp == NULL) return -1; strcpy(input_url+strlen(input_url)-4,"_y.y"); FILE fp1 = fopen(input_url,"wb+"); strcpy(input_url+strlen(input_url)-4,"_u.y"); FILE fp2 = fopen(input_url,"wb+"); strcpy(input_url+strlen(input_url)-4,"_v.y"); FILE fp3 = fopen(input_url,"wb+"); unsigned char pic = (unsigned char ) malloc(w h 3); for(int i = 0;i < num;i++) { fread(pic, 1, w h 3, fp); //Y fwrite(pic, 1, w h, fp1); //U fwrite(pic + w h, 1, w h, fp2); //V fwrite(pic + w h 2, 1, w h, fp3); } free(pic); fclose(fp); fclose(fp1); fclose(fp2); fclose(fp3); return 0;}
函数调用AVUtils.getInstance().yuv444Split(ROOT+"lena_256x256_yuv444p.yuv",256,256,1);
运行上面代码后会在同目录下生成y、u、v三个文件lena_256x256_yuv444p_u.y: Y数据, 分辨率为256x256lena_256x256_yuv444p_u.y: U数据, 分辨率为256x256lena_256x256_yuv444p_v.y: V数据, 分辨率为256x256
原始图片lena_256x256_yuv444p.yuv生成的y、u、v分量图片如下:lena_256x256_yuv444p_y.ylena_256x256_yuv444p_u.ylena_256x256_yuv444p_v.y3) 将YUV420P像素数据去掉颜色,变成灰度图/ Convert YUV420P file to gray picture @param jstr_url Location of Input YUV file. @param w Width of Input YUV file. @param h Height of Input YUV file. @param num Number of frames to process. 将YUV420P像素数据去掉颜色,变成灰度图 如果想把YUV格式像素数据变成灰度图像,只需要将U、V分量设置成128即可。 这是因为U、V是图像中的经过偏置处理的色度分量。色度分量在偏置处理前的取值范围是-128至127,这时候的无色对应的是0值。经过偏置后色度分量取值变成了0至255,因而此时的无色对应的就是128了 /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_yuv420Gray( JNIEnv env,jobject / this /, jstring jstr_url, jint w, jint h, jint num) { char input_url[100] = {0}; const char str = env->GetStringUTFChars(jstr_url, NULL); sprintf(input_url,"%s",str); env->ReleaseStringUTFChars(jstr_url,str); FILE fp = fopen(input_url,"rb+"); if(fp == NULL) return -1; strcpy(input_url+strlen(input_url)-4,"_gray.yuv"); FILE fp1 = fopen(input_url,"wb+"); unsigned char pic=(unsigned char )malloc(wh3/2); for(int i = 0;i < num;i++) { fread(pic, 1, w h 3 / 2, fp); //Gray memset(pic + w h, 128, w h / 2); fwrite(pic, 1, w h 3 / 2, fp1); } free(pic); fclose(fp); fclose(fp1); return 0;}
函数调用AVUtils.getInstance().yuv420Gray(ROOT+"lena_256x256_yuv420p.yuv",256,256,1);
原始图片lena_256x256_yuv420p.yuv生成的灰度图如下:lena_256x256_yuv420p_gray.yuv4) 将YUV420P像素数据的亮度减半/ Halve Y value of YUV420P file @param jstr_url Location of Input YUV file. @param w Width of Input YUV file. @param h Height of Input YUV file. @param num Number of frames to process. 将YUV420P像素数据的亮度减半 如果打算将图像的亮度减半,只要将图像的每个像素的Y值取出来分别进行除以2就可以了 /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_yuv420Halfy( JNIEnv env,jobject / this /, jstring jstr_url, jint w, jint h, jint num) { char input_url[100] = {0}; const char str = env->GetStringUTFChars(jstr_url, NULL); sprintf(input_url,"%s",str); env->ReleaseStringUTFChars(jstr_url,str); FILE fp = fopen(input_url,"rb+"); if(fp == NULL) return -1; strcpy(input_url+strlen(input_url)-4,"_halfy.yuv"); FILE fp1 = fopen(input_url,"wb+"); unsigned char pic=(unsigned char )malloc(wh3/2); for(int i = 0;i < num;i++) { fread(pic, 1, w h 3 / 2, fp); //Half for (int j = 0; j < w h; j++) { unsigned char temp = pic[j] / 2; pic[j] = temp; } fwrite(pic, 1, w h 3 / 2, fp1); } free(pic); fclose(fp); fclose(fp1); return 0;}
函数调用AVUtils.getInstance().yuv420Halfy(ROOT+"lena_256x256_yuv420p.yuv",256,256,1);
原始图片lena_256x256_yuv420p.yuv生成的亮度减半图如下:lena_256x256_yuv420p_halfy.yuv5) 将YUV420P像素数据的周围加上边框/ Add border for YUV420P file @param jstr_url Location of Input YUV file. @param w Width of Input YUV file. @param h Height of Input YUV file. @param border Width of Border. @param num Number of frames to process. 将YUV420P像素数据的周围加上边框 图像的边框的宽度为border,本程序将距离图像边缘border范围内的像素的亮度分量Y的取值设置成了亮度最大值255 /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_yuv420Border( JNIEnv env,jobject / this /, jstring jstr_url, jint w, jint h, jint border, jint num) { char input_url[100] = {0}; const char str = env->GetStringUTFChars(jstr_url, NULL); sprintf(input_url,"%s",str); env->ReleaseStringUTFChars(jstr_url,str); FILE fp = fopen(input_url,"rb+"); if(fp == NULL) return -1; strcpy(input_url+strlen(input_url)-4,"_border.yuv"); FILE fp1 = fopen(input_url,"wb+"); unsigned char pic=(unsigned char )malloc(wh3/2); for(int i = 0;i < num;i++){ fread(pic,1,wh3/2,fp); //Y for(int j = 0;j < h;j++){ for(int k = 0;k < w;k++){ if(k < border || k >= (w-border) || j < border || j >= (h-border)){ pic[jw+k]=255; //pic[jw+k]=0; } } } fwrite(pic,1,wh3/2,fp1); } free(pic); fclose(fp); fclose(fp1); return 0;}
函数调用AVUtils.getInstance().yuv420Border(ROOT+"lena_256x256_yuv420p.yuv",256,256,20,1);
原始图片lena_256x256_yuv420p.yuv生成的周围加上边框图如下:lena_256x256_yuv420p_border.yuv6) 生成YUV420P格式的灰阶测试图/ Generate YUV420P gray scale bar. @param width Width of Output YUV file. @param height Height of Output YUV file. @param ymin Max value of Y @param ymax Min value of Y @param barnum Number of bars @param jstr_url_out Location of Output YUV file. 生成YUV420P格式的灰阶测试图 通过灰阶测试图的亮度最小值ymin,亮度最大值ymax,灰阶数量barnum确定每一个灰度条中像素的亮度分量Y的取值。 还要根据图像的宽度width和图像的高度height以及灰阶数量barnum确定每一个灰度条的宽度 /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_yuv420GrayBar( JNIEnv env,jobject / this /, jstring jstr_url_out, jint width, jint height, jint ymin,jint ymax,jint barnum) { int barwidth; float lum_inc; unsigned char lum_temp; int uv_width,uv_height; FILE fp=NULL; unsigned char data_y = NULL; unsigned char data_u = NULL; unsigned char data_v = NULL; int t = 0,i = 0,j = 0; barwidth = width/barnum; lum_inc = ((float)(ymax-ymin))/((float)(barnum-1)); uv_width = width/2; uv_height = height/2; data_y = (unsigned char )malloc(widthheight); data_u = (unsigned char )malloc(uv_widthuv_height); data_v = (unsigned char )malloc(uv_widthuv_height); char input_url[100] = {0}; const char str = env->GetStringUTFChars(jstr_url_out, NULL); sprintf(input_url,"%s",str); env->ReleaseStringUTFChars(jstr_url_out,str); if((fp=fopen(input_url,"wb+")) == NULL){ LOGE("Error: Cannot create file!"); return -1; } //Output Info LOGI("Y, U, V value from picture's left to right:\n"); for(t = 0;t < barnum;t++){ lum_temp = ymin+(char)(tlum_inc); LOGI("%3d, 128, 128\n",lum_temp); } //Gen Data for(j = 0;j < height;j++){ for(i = 0;i < width;i++){ t = i/barwidth; lum_temp = ymin+(char)(tlum_inc); data_y[jwidth+i] = lum_temp; } } for(j = 0;j < uv_height;j++){ for(i = 0;i < uv_width;i++){ data_u[juv_width+i] = 128; } } for(j = 0;j < uv_height;j++){ for(i = 0;i < uv_width;i++){ data_v[juv_width+i] = 128; } } fwrite(data_y,widthheight,1,fp); fwrite(data_u,uv_widthuv_height,1,fp); fwrite(data_v,uv_widthuv_height,1,fp); fclose(fp); free(data_y); free(data_u); free(data_v); return 0;}
函数调用AVUtils.getInstance().yuv420GrayBar(ROOT+"graybar_640x360_yuv420p.yuv",640, 360,0,255,10);
生成的灰阶测试图如下:graybar_640x360_yuv420p.yuv7) 计算两个YUV420P像素数据的PSNR/ Calculate PSNR between 2 YUV420P file @param jstr_url1 Location of first Input YUV file. @param jstr_url2 Location of another Input YUV file. @param w Width of Input YUV file. @param h Height of Input YUV file. @param num Number of frames to process. 计算两个YUV420P像素数据的PSNR PSNR是最基本的视频质量评价方法 程序计算后得到的PSNR取值为26.693。PSNR取值通常情况下都在20-50的范围内,取值越高,代表两张图像越接近,反映出受损图像质量越好 /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_yuv420Psnr( JNIEnv env,jobject / this /, jstring jstr_url1,jstring jstr_url2, jint w, jint h,jint num) { const char str1 = env->GetStringUTFChars(jstr_url1, NULL); FILE fp1 = fopen(str1,"rb+"); env->ReleaseStringUTFChars(jstr_url1,str1); if(fp1 == NULL) return -1; const char str2 = env->GetStringUTFChars(jstr_url2, NULL); FILE fp2 = fopen(str2,"rb+"); env->ReleaseStringUTFChars(jstr_url2,str2); if(fp2 == NULL) return -1; unsigned char pic1 = (unsigned char )malloc(wh); unsigned char pic2 = (unsigned char )malloc(wh); for(int i = 0;i < num;i++){ fread(pic1,1,wh,fp1); fread(pic2,1,wh,fp2); double mse_sum = 0,mse = 0,psnr = 0; for(int j = 0;j < wh;j++){ mse_sum += pow((double)(pic1[j]-pic2[j]),2); } mse = mse_sum/(wh); psnr = 10log10(255.0255.0/mse); LOGI("%5.3f\n",psnr); fseek(fp1,wh/2,SEEK_CUR); fseek(fp2,wh/2,SEEK_CUR); } free(pic1); free(pic2); fclose(fp1); fclose(fp2); return 0;}
函数调用AVUtils.getInstance().yuv420Psnr(ROOT+"lena_256x256_yuv420p.yuv",ROOT+"lena_distort_256x256_yuv420p.yuv",256,256,1);
对于8bit量化的像素数据来说,PSNR的计算公式PSNR的计算公式原始图和受损图如下:程序计算后得到的PSNR取值为26.693。PSNR取值通常情况下都在20-50的范围内,取值越高,代表两张图像越接近,反映出受损图像质量越好。8) 分离RGB24像素数据中的R、G、B分量/ Split R, G, B planes in RGB24 file. @param jstr_url Location of Input RGB file. @param w Width of Input RGB file. @param h Height of Input RGB file. @param num Number of frames to process. 分离RGB24像素数据中的R、G、B分量 RGB24格式的每个像素的三个分量是连续存储的。一帧宽高分别为w、h的RGB24图像一共占用wh3 Byte的存储空间。 RGB24格式规定首先存储第一个像素的R、G、B,然后存储第二个像素的R、G、B…以此类推。 类似于YUV420P的存储方式称为Planar方式,而类似于RGB24的存储方式称为Packed方式 /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_rgb24Split( JNIEnv env,jobject / this /, jstring jstr_url, jint w, jint h,jint num) { char input_url[100] = {0}; const char str = env->GetStringUTFChars(jstr_url, NULL); sprintf(input_url,"%s",str); env->ReleaseStringUTFChars(jstr_url,str); FILE fp = fopen(input_url,"rb+"); if(fp == NULL) return -1; strcpy(input_url+strlen(input_url)-4,"_r.y"); FILE fp1 = fopen(input_url,"wb+"); strcpy(input_url+strlen(input_url)-4,"_g.y"); FILE fp2 = fopen(input_url,"wb+"); strcpy(input_url+strlen(input_url)-4,"_b.y"); FILE fp3 = fopen(input_url,"wb+"); unsigned char pic=(unsigned char )malloc(wh3); for(int i = 0;i < num;i++){ fread(pic,1,wh3,fp); for(int j = 0;j < wh3;j = j+3){ //R fwrite(pic+j,1,1,fp1); //G fwrite(pic+j+1,1,1,fp2); //B fwrite(pic+j+2,1,1,fp3); } } free(pic); fclose(fp); fclose(fp1); fclose(fp2); fclose(fp3); return 0;}
函数调用AVUtils.getInstance().rgb24Split(ROOT+"cie1931_500x500.rgb",500,500,1);
运行上面代码后会在同目录下生成r、g、b三个文件cie1931_500x500_r.y: R数据,分辨率为500x500cie1931_500x500_g.y:G数据,分辨率为500x500cie1931_500x500_b.y:B数据,分辨率为500x500
输入的原图是一张标准的CIE 1931色度图。该色度图右下为红色,上方为绿色,左下为蓝色cie1931_500x500.rgb生成的r、g、b分量图片如下:cie1931_500x500_r.ycie1931_500x500_g.ycie1931_500x500_b.y9) 将RGB24格式像素数据封装为BMP图像/ Convert RGB24 file to BMP file @param jstr_rgb24path Location of input RGB file. @param width Width of input RGB file. @param height Height of input RGB file. @param jstr_bmppath Location of Output BMP file. 将RGB24格式像素数据封装为BMP图像 BMP采用的是小端(Little Endian)存储方式。这种存储方式中“RGB24”格式的像素的分量存储的先后顺序为B、G、R。由于RGB24格式存储的顺序是R、G、B,所以需要将“R”和“B”顺序作一个调换再进行存储 该程序完成了主要完成了两个工作: 1)将RGB数据素的“B”和“前面加上文件头。 2)将RGB数据中每个像R”的位置互换。 BMP文件是由BITMAPFILEHEADER、BITMAPINFOHEADER、RGB像素数据共3个部分构成,它的结构如下所示。 BITMAPFILEHEADER BITMAPINFOHEADER RGB像素数据 /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_rgb24ToBmp( JNIEnv env,jobject / this /, jstring jstr_rgb24path, jint width, jint height,jstring jstr_bmppath) { typedef struct { long imageSize; long blank; long startPosition; }BmpHead; typedef struct { long Length; long width; long height; unsigned short colorPlane; unsigned short bitColor; long zipFormat; long realSize; long xPels; long yPels; long colorUse; long colorImportant; }InfoHead; int i = 0,j = 0; BmpHead m_BMPHeader={0}; InfoHead m_BMPInfoHeader={0}; char bfType[2] = {'B','M'}; int header_size = sizeof(bfType)+sizeof(BmpHead)+sizeof(InfoHead); unsigned char rgb24_buffer = NULL; FILE fp_rgb24 = NULL,fp_bmp = NULL; const char rgb24path = env->GetStringUTFChars(jstr_rgb24path, NULL); if((fp_rgb24=fopen(rgb24path,"rb")) == NULL){ LOGE("Error: Cannot open input RGB24 file.\n"); env->ReleaseStringUTFChars(jstr_rgb24path,rgb24path); return -1; } env->ReleaseStringUTFChars(jstr_rgb24path,rgb24path); const char bmppath = env->GetStringUTFChars(jstr_bmppath, NULL); if((fp_bmp=fopen(bmppath,"wb")) == NULL){ LOGE("Error: Cannot open output BMP file.\n"); env->ReleaseStringUTFChars(jstr_bmppath,bmppath); return -1; } rgb24_buffer = (unsigned char )malloc(widthheight3); fread(rgb24_buffer,1,widthheight3,fp_rgb24); m_BMPHeader.imageSize = 3widthheight+header_size; m_BMPHeader.startPosition = header_size; m_BMPInfoHeader.Length = sizeof(InfoHead); m_BMPInfoHeader.width = width; //BMP storage pixel data in opposite direction of Y-axis (from bottom to top). m_BMPInfoHeader.height = -height; m_BMPInfoHeader.colorPlane = 1; m_BMPInfoHeader.bitColor = 24; m_BMPInfoHeader.realSize = 3widthheight; fwrite(bfType,1,sizeof(bfType),fp_bmp); fwrite(&m_BMPHeader,1,sizeof(m_BMPHeader),fp_bmp); fwrite(&m_BMPInfoHeader,1,sizeof(m_BMPInfoHeader),fp_bmp); //BMP save R1|G1|B1,R2|G2|B2 as B1|G1|R1,B2|G2|R2 //It saves pixel data in Little Endian //So we change 'R' and 'B' for(j = 0;j < height;j++){ for(i = 0;i < width;i++){ char temp = rgb24_buffer[(jwidth+i)3+2]; rgb24_buffer[(jwidth+i)3+2] = rgb24_buffer[(jwidth+i)3+0]; rgb24_buffer[(jwidth+i)3+0] = temp; } } fwrite(rgb24_buffer,3widthheight,1,fp_bmp); fclose(fp_rgb24); fclose(fp_bmp); free(rgb24_buffer); LOGI("Finish generate %s!\n",bmppath); env->ReleaseStringUTFChars(jstr_bmppath,bmppath); return 0;}
函数调用AVUtils.getInstance().rgb24ToBmp(ROOT+"lena_256x256_rgb24.rgb",256,256,ROOT+"lena_256x256.bmp");
原始图片lena_256x256_rgb24.rgb生成的bmp可以用自带看图软件打开:lena_256x256.bmp10) 将RGB24格式像素数据转换为YUV420P格式像素数据unsigned char clip_value(unsigned char x,unsigned char min_val,unsigned char max_val){ if(x > max_val){ return max_val; }else if(x < min_val){ return min_val; }else{ return x; }}//RGB to YUV420bool RGB24_TO_YUV420(unsigned char RgbBuf,int w,int h,unsigned char yuvBuf){ unsigned charptrY, ptrU, ptrV, ptrRGB; LOGI("pic_rgb24 [ "); ptrRGB = RgbBuf; for(int ll = 0;ll < wh3;ll++){ LOGI("%c ",ptrRGB++); if(ll%50 == 0){LOGI("\n");} } LOGI("]\n"); memset(yuvBuf,0,wh3/2); ptrY = yuvBuf; ptrU = yuvBuf + wh; ptrV = ptrU + (wh1/4); unsigned char y, u, v, r, g, b; for (int j = 0; j < h;j++){ ptrRGB = RgbBuf + wj3 ; //ptrRGB = RgbBuf + w (h - 1 - j) 3 ; for (int i = 0;i < w;i++){ r = (ptrRGB++); g = (ptrRGB++); b = (ptrRGB++); /y = (unsigned char)( ( 66 r + 129 g + 25 b + 128) >> 8) + 16 ; u = (unsigned char)( ( -38 r - 74 g + 112 b + 128) >> 8) + 128 ; v = (unsigned char)( ( 112 r - 94 g - 18 b + 128) >> 8) + 128 ;/ y = (unsigned char)( ( 66 r + 129 g + 25 b) >> 8) + 16 ; u = (unsigned char)( ( -38 r - 74 g + 112 b) >> 8) + 128 ; v = (unsigned char)( ( 112 r - 94 g - 18 b) >> 8) + 128 ; (ptrY++) = clip_value(y,0,255); if (j%2==0 && i%2 ==0){ (ptrU++) = clip_value(u,0,255); } else{ if (i%2==0){ (ptrV++) = clip_value(v,0,255); } } } } return true;}/ Convert RGB24 file to YUV420P file @param url_in Location of Input RGB file. @param w Width of Input RGB file. @param h Height of Input RGB file. @param num Number of frames to process. @param url_out Location of Output YUV file. RGB24格式像素数据转换为YUV420P格式像素数据 RGB到YUV的转换公式: Y = 0.257R' + 0.504G' + 0.098B' + 16 U = -0.148R' - 0.291G' + 0.439B' + 128 V = 0.439R' - 0.368G' - 0.071B' + 128 转换的过程中有以下几点需要注意: 1) RGB24存储方式是Packed,YUV420P存储方式是Planar。 2) U,V在水平和垂直方向的取样数是Y的一半 /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_rgb24ToYuv420( JNIEnv env,jobject / this /, jstring jstr_urlin, jint w, jint h, jint num,jstring jstr_urlout) { const char url_in = env->GetStringUTFChars(jstr_urlin, NULL); LOGI("url_in : %s\n",url_in); FILE fp = fopen(url_in,"rb+"); env->ReleaseStringUTFChars(jstr_urlin,url_in); if(fp == NULL){ return -1; } const char urlout = env->GetStringUTFChars(jstr_urlout, NULL); LOGI("urlout : %s\n",urlout); FILE fp1 = fopen(urlout,"wb+"); env->ReleaseStringUTFChars(jstr_urlout,urlout); if(fp1 == NULL){ return -1; } unsigned char pic_rgb24 = (unsigned char )malloc(wh3); unsigned char pic_yuv420 = (unsigned char )malloc(wh3/2); for(int i = 0;i < num;i++){ fread(pic_rgb24,1,wh3,fp); RGB24_TO_YUV420(pic_rgb24,w,h,pic_yuv420); fwrite(pic_yuv420,1,wh3/2,fp1); } free(pic_rgb24); free(pic_yuv420); fclose(fp); fclose(fp1); return 0;}
函数调用AVUtils.getInstance().rgb24ToYuv420(ROOT+"lena_256x256_rgb24.rgb",256,256,1,ROOT+"lena_256x256_rgb24ToYuv420.yuv");
原始图片lena_256x256_rgb24.rgb转换后的YUV420P格式的图片:lena_256x256_rgb24ToYuv420.yuv11) 生成RGB24格式的彩条测试图/ Generate RGB24 colorbar. @param width Width of Output RGB file. @param height Height of Output RGB file. @param url_out Location of Output RGB file. 生成RGB24格式的彩条测试图 /extern "C" JNIEXPORT jint JNICALLJava_com_xohn_ffmpeg_AVUtils_rgb24ColorBar( JNIEnv env,jobject / this /, jint width, jint height,jstring jstr_urlout) { unsigned char data = NULL; int barwidth; FILE fp = NULL; int i = 0,j = 0; data = (unsigned char )malloc(widthheight3); barwidth = width/8; const char url_out = env->GetStringUTFChars(jstr_urlout, NULL); fp = fopen(url_out,"wb+"); env->ReleaseStringUTFChars(jstr_urlout,url_out); if(fp == NULL){ return -1; } for(j = 0;j < height;j++){ for(i = 0;i < width;i++){ int barnum = i/barwidth; switch(barnum){ case 0:{ data[(jwidth+i)3+0] = 255; data[(jwidth+i)3+1] = 255; data[(jwidth+i)3+2] = 255; break; } case 1:{ data[(jwidth+i)3+0] = 255; data[(jwidth+i)3+1] = 255; data[(jwidth+i)3+2] = 0; break; } case 2:{ data[(jwidth+i)3+0] = 0; data[(jwidth+i)3+1] = 255; data[(jwidth+i)3+2] = 255; break; } case 3:{ data[(jwidth+i)3+0] = 0; data[(jwidth+i)3+1] = 255; data[(jwidth+i)3+2] = 0; break; } case 4:{ data[(jwidth+i)3+0] = 255; data[(jwidth+i)3+1] = 0; data[(jwidth+i)3+2] = 255; break; } case 5:{ data[(jwidth+i)3+0] = 255; data[(jwidth+i)3+1] = 0; data[(jwidth+i)3+2] = 0; break; } case 6:{ data[(jwidth+i)3+0] = 0; data[(jwidth+i)3+1] = 0; data[(jwidth+i)3+2] = 255; break; } case 7:{ data[(jwidth+i)3+0] = 0; data[(jwidth+i)3+1] = 0; data[(jwidth+i)3+2] = 0; break; } } } } fwrite(data,widthheight3,1,fp); fclose(fp); free(data); return 0;}
函数调用AVUtils.getInstance().rgb24ColorBar(640, 360,ROOT+"rgb24colorbar_640x360.rgb");
生成“白黄青绿品红蓝黑”8种颜色的彩条,如下图:rgb24colorbar_640x360.rgb参考文章:雷神文章 https://blog.csdn.net/leixiaohua1020/article/details/50534150RGB到YUV的转换公式 https://blog.csdn.net/xiaoyafang123/article/details/82153279项目git地址:https://gitee.com/xohn/FFmpeg.git 中的FFMpeg1(图片来源网络,侵删)
0 评论