//picturesize must a multiple of 16
public static byte[] getYUVBuffer(Image image) {
Image.Plane Y = image.getPlanes()[0];
Image.Plane U = image.getPlanes()[1];
Image.Plane V = image.getPlanes()[2];
int pixelStrideY = Y.getPixelStride();
int rowOffsetY = Y.getRowStride();
int pixelStrideU = U.getPixelStride();
int rowOffsetU = U.getRowStride();
int pixelStrideV = V.getPixelStride();
int rowOffsetV = V.getRowStride();
Log.i(TAG, "nzq_c--[getYUVBuffer] pixelStrideY="+pixelStrideY+" rowOffsetY="+rowOffsetY);
Log.i(TAG, "nzq_c--[getYUVBuffer] pixelStrideU="+pixelStrideU+" rowOffsetU="+rowOffsetU);
Log.i(TAG, "nzq_c--[getYUVBuffer] pixelStrideV="+pixelStrideV+" rowOffsetV="+rowOffsetV);
Log.i(TAG, "nzq_c--image.getWidth()="+image.getWidth() +"& image.getHeight()="+image.getHeight());
int Yb = Y.getBuffer().remaining();
int Ub = U.getBuffer().remaining();
int Vb = V.getBuffer().remaining();
Log.i(TAG, "nzq_c--[getYUVBuffer] Yb = " + Yb + " Ub = " + Ub + " Vb = " + Vb);
byte[] imageBuffer = new byte[Yb + Ub + Vb];
Y.getBuffer().get(imageBuffer, 0, Yb);
U.getBuffer().get(imageBuffer, Yb, Ub);
V.getBuffer().get(imageBuffer, Yb + Ub, Vb);
FileOutputStream out = null;
try {
// Write to a temporary file and rename it to the final name.
// This
// avoids other apps reading incomplete data.
Log.d(TAG, "save the data to SD Card");
String outputPath = new File(ConfigManager.DUMP_DIR, "image.getWidth()="+image.getWidth() +"& image.getHeight()="+image.getHeight()+
"yuv")
.getAbsolutePath();
out = new FileOutputStream(outputPath);
out.write(imageBuffer);
out.close();
} catch (IOException e) {
Log.e(TAG, "Failed to write image,ex:", e);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
Log.e(TAG, "IOException:", e);
}
}
}
return imageBuffer;
}
//picturesize must a multiple of 16
public static byte[] I420Tonv21(Image image, int width, int height) {
byte[] data = getYUVBuffer(image);
// if(ret==null){
ret = new byte[data.length];
// }
int total = width * height;
for(int i=0;i<total;i++){
ret[i]=data[i];
}
for(int i=0;i<total/4;i++){//u
ret[total+2*i+1]=data[total+i];
}
for(int i=0;i<total/4;i++){//v
ret[total+2*i]=data[total+total/4+i];
}
dumpFile("/sdcard/DCIM/"+ width+"x"+height + "_I420.yuv", data);
dumpFile("/sdcard/DCIM/"+ width+"x"+height + "_NV21.yuv", ret);
return ret;
}
/**
* only support YUV_420_888 to NV21.
* @param image the image form capture surface
* @return the byte array.
*/
public static byte[] getYUVBuffer2(Image image) {
Rect crop = image.getCropRect();
int format = image.getFormat();
int width = crop.width();
int height = crop.height();
Image.Plane[] planes = image.getPlanes();
byte[] data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
byte[] rowData = new byte[planes[0].getRowStride()];
Log.v(TAG, "[getYUVBuffer2] get data from " + planes.length + " planes"+ " width="+width+" height="+height);
int channelOffset = 0;
int outputStride = 1;
for (int i = 0; i < planes.length; i++) {
switch (i) {
case 0:
channelOffset = 0;
outputStride = 1;
break;
case 1:
channelOffset = width * height + 1;
outputStride = 2;
break;
case 2:
channelOffset = width * height;
outputStride = 2;
break;
}
ByteBuffer buffer = planes[i].getBuffer();
int rowStride = planes[i].getRowStride();
int pixelStride = planes[i].getPixelStride();
Log.v(TAG, "[getYUVBuffer] pixelStride " + pixelStride);
Log.v(TAG, "[getYUVBuffer] rowStride " + rowStride);
Log.v(TAG, "[getYUVBuffer] width " + width);
Log.v(TAG, "[getYUVBuffer] height " + height);
Log.v(TAG, "[getYUVBuffer] buffer size " + buffer.remaining());
int shift = (i == 0) ? 0 : 1;
int w = width >> shift;
int h = height >> shift;
buffer.position(rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift));
for (int row = 0; row < h; row++) {
int length;
if (pixelStride == 1 && outputStride == 1) {
length = w;
buffer.get(data, channelOffset, length);
channelOffset += length;
} else {
length = (w - 1) * pixelStride + 1;
buffer.get(rowData, 0, length);
for (int col = 0; col < w; col++) {
data[channelOffset] = rowData[col * pixelStride];
channelOffset += outputStride;
}
}
if (row < h - 1) {
buffer.position(buffer.position() + rowStride - length);
}
}
Log.v(TAG, "[getYUVBuffer] Finished reading data from plane " + i);
}
return data;
}
//for QCOM platform, and picturesize must a multiple of 64
public static byte[] Qcom_I420Tonv21(Image image, int width, int height) {
byte[] data = getYUVBuffer(image);
byte[] ret= new byte[width*height];
int total = width * height;
int offset=0;
for(int i=0;i<height;i++){
for(int j=0;j<width;j++){
ret[j+i*height]=data[j+i*height+offset];
}
offset=offset+32;
}
for(int i=0;i<total/4;i++){//u
ret[total+2*i+1]=data[total+i];
}
for(int i=0;i<total/4;i++){//v
ret[total+2*i]=data[total+total/4+i];
}
dumpFile("/sdcard/DCIM/"+ width+"x"+height + "_I420.yuv", data);
dumpFile("/sdcard/DCIM/"+ width+"x"+height + "_NV21.yuv", ret);
return ret;
}
public static void dumpFile(String fileName, byte[] data) {
File file = new File(fileName);
if (!file.exists()) {
file.getParentFile().mkdirs();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileOutputStream outStream;
try {
outStream = new FileOutputStream(fileName);
} catch (IOException ioe) {
throw new RuntimeException("Unable to create output file " + fileName, ioe);
}
try {
outStream.write(data);
outStream.close();
} catch (IOException ioe) {
throw new RuntimeException("failed writing data to file " + fileName, ioe);
}
}
public static byte[] convertImageToNV21RemoveReduction(Image img) {
Log.e(TAG, "nzq_c--convertImageToNV21RemoveReduction: img.getFormat()="+img.getFormat());
if(img.getFormat() != ImageFormat.YUV_420_888 ) {
return new byte[0];
}
Image.Plane[] planes = img.getPlanes();
ByteBuffer yBuffer = planes[0].getBuffer();
ByteBuffer vuBuffer = planes[2].getBuffer();
int sizeY = yBuffer.capacity();
int sizeNV21 = img.getWidth() * img.getHeight() * 3 / 2;
byte[] data = new byte[sizeNV21];
int yStride = planes[0].getRowStride();
byte[] yByteArray = new byte[yBuffer.capacity()];
yBuffer.rewind();
yBuffer.get(yByteArray);
int imageWidth = img.getWidth();
int imageHeight = img.getHeight();
int srcOffset = 0;
int dstOffset = 0;
for(int i=0; i<imageHeight; i++) {
if(srcOffset + imageWidth > sizeY) {
System.arraycopy(yByteArray, srcOffset, data, dstOffset, srcOffset + imageWidth - sizeY);
break;
} else {
System.arraycopy(yByteArray, srcOffset, data, dstOffset, imageWidth);
}
srcOffset += yStride;
dstOffset += imageWidth;
}
int vuStride = planes[2].getRowStride();
int sizeVU = vuBuffer.capacity();
byte[] vuByteArray = new byte[vuBuffer.capacity()];
vuBuffer.rewind();
vuBuffer.get(vuByteArray);
srcOffset = 0;
for(int i=0; i<imageHeight/2; i++) {
if(srcOffset + imageWidth > sizeVU) {
System.arraycopy(vuByteArray, srcOffset - vuStride, data, dstOffset, imageWidth);
break;
} else {
System.arraycopy(vuByteArray, srcOffset, data, dstOffset, imageWidth);
}
srcOffset += vuStride;
dstOffset += imageWidth;
}
return data;
}
public static void saveNV21ToFile(byte[] data, String postfix, int width, int height) {
Log.e(TAG,"saveNV21ToFile");
String path = ConfigManager.DUMP_DIR;
File directory = new File(path);
if (!directory.exists()) {
directory.mkdirs();
}
String filePath = directory.toString() + "/" + postfix +"_"+ width + "x" + height + "_nv21.yuv";
File file = new File(filePath);
saveByteArrayToFile(data, file);
}
public static boolean saveByteArrayToFile(byte[] data, String fileName) {
String path = ConfigManager.DUMP_DIR;
File directory = new File(path);
if (!directory.exists()) {
directory.mkdirs();
}
String filePath = directory.toString() + "/" + fileName;
File file = new File(filePath);
return saveByteArrayToFile(data,file);
}
public static boolean saveByteArrayToFile(byte[] data, File file) {
boolean success = false;
if (null != file) {
try {
FileOutputStream fs = new FileOutputStream(file);
fs.write(data, 0, data.length);
fs.close();
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return success;
} else {
return success;
}
}
public static byte[] loadByteArrayFromFilePath(String filePath, int length) {
File file = new File(filePath);
if (null != file) {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
byte[] data = new byte[length];
int readLength = inputStream.read(data);
inputStream.close();
return readLength == length ? data : null;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public static void makeDirectory(String filePath) {
File file = null;
try {
file = new File(filePath);
if (!file.exists()) {
file.mkdir();
}
} catch (Exception e) {
e.printStackTrace();
}
}