在最近项目中,因为特殊需要,底层相机往外输出了i420 也就是yuv420p,输出的bytes 需要转成换h264,同时某个时间还需要保存一张图片,如何将i420 转jpeg ?可以ffmpeg 也可以libjpeg 但是我不需要这些库,仅仅为了一个图片 加载一个库 没有必要,同时对图片处理眉头特殊需求,所以 目前的方式是: i420 -argb-jpeg
public static void generateWarnPic(final byte[] picData,final int width,final int height){
new Thread(new Runnable() {
@Override
public void run() {
try {
String fileName = System.currentTimeMillis() + ".jpg";
File file = new File(GlobalDefineUtil.WARN_PIC_PATH + fileName);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
int [] argb=ColorConversion.I420toARGB(picData,width, height);
Bitmap bitmap = Bitmap.createBitmap(argb,width,height, Bitmap.Config.ARGB_8888);
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileOutputStream);
fileOutputStream.close();
} catch (IOException e) {
}
//update db
// WarnPicDao dao = new WarnPicDao();
// dao.updateImages(fileName);
} catch (Exception e) {
Log.i("yy", e.getMessage());
}
}
}).start();
}
public static int[] I420toARGB(byte[] yuv, int width, int height)
{
boolean invertHeight=false;
if (height<0)
{
height=-height;
invertHeight=true;
}
boolean invertWidth=false;
if (width<0)
{
width=-width;
invertWidth=true;
}
int iterations=width*height;
//if ((iterations*3)/2 > yuv.length){throw new IllegalArgumentException();}
int[] rgb = new int[iterations];
for (int i = 0; i<iterations;i++)
{
/*int y = yuv[i] & 0x000000ff;
int u = yuv[iterations+(i/4)] & 0x000000ff;
int v = yuv[iterations + iterations/4 + (i/4)] & 0x000000ff;*/
int nearest = (i/width)/2 * (width/2) + (i%width)/2;
int y = yuv[i] & 0x000000ff;
int u = yuv[iterations+nearest] & 0x000000ff;
int v = yuv[iterations + iterations/4 + nearest] & 0x000000ff;
//int b = (int)(1.164*(y-16) + 2.018*(u-128));
//int g = (int)(1.164*(y-16) - 0.813*(v-128) - 0.391*(u-128));
//int r = (int)(1.164*(y-16) + 1.596*(v-128));
//double Y = (y/255.0);
//double Pr = (u/255.0-0.5);
//double Pb = (v/255.0-0.5);
/*int b = (int)(1.164*(y-16)+1.8556*(u-128));
int g = (int)(1.164*(y-16) - (0.4681*(v-128) + 0.1872*(u-128)));
int r = (int)(1.164*(y-16)+1.5748*(v-128));*/
int b = (int)(y+1.8556*(u-128));
int g = (int)(y - (0.4681*(v-128) + 0.1872*(u-128)));
int r = (int)(y+1.5748*(v-128));
/*double B = Y+1.8556*Pb;
double G = Y - (0.4681*Pr + 0.1872*Pb);
double R = Y+1.5748*Pr;*/
//int b = (int)B*255;
//int g = (int)G*255;
//int r = (int)R*255;
if (b>255){b=255;}
else if (b<0 ){b = 0;}
if (g>255){g=255;}
else if (g<0 ){g = 0;}
if (r>255){r=255;}
else if (r<0 ){r = 0;}
/*rgb[i]=(byte)b;
rgb[i+1]=(byte)g;
rgb[i+2]=(byte)r;*/
int targetPosition=i;
if (invertHeight)
{
targetPosition=((height-1)-targetPosition/width)*width + (targetPosition%width);
}
if (invertWidth)
{
targetPosition=(targetPosition/width)*width + (width-1)-(targetPosition%width);
}
rgb[targetPosition] = (0xff000000) | (0x00ff0000 & r << 16) | (0x0000ff00 & g << 8) | (0x000000ff & b);
}
return rgb;
}
如果你输出格式是nv21 或者 yuy2 转图片就很简单了
FileOutputStream outStream = null;
try {
YuvImage yuvimage = new YuvImage(bytes,ImageFormat.YUY2,camera.getParameters().getPreviewSize().width,camera.getParameters().getPreviewSize().height,null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0,0,camera.getParameters().getPreviewSize().width,camera.getParameters().getPreviewSize().height), 80, baos);
outStream = new FileOutputStream("/mnt/sdcard/" +System.currentTimeMillis()+".jpg");
outStream.write(baos.toByteArray());
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i("yy", "1111111111111111111");
} catch (IOException e) {
e.printStackTrace();
} finally {
}