import
android.graphics.ImageFormat;
import
android.graphics.Rect;
import
android.graphics.YuvImage;
import
android.media.Image;
import
android.text.Spanned;
import
android.util.Log;
import
com.android.internal.logging.nano.MetricsProto;
import
java.io.ByteArrayOutputStream;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.nio.ByteBuffer;
public
class
ImageUtil {
public static final
int
COLOR_FormatI420
=
1
;
public static final
int
COLOR_FormatNV21
=
2
;
public static final
int
NV21
=
2
;
private static final String TAG
=
"ImageUtil"
;
public static final
int
YUV420P
=
0
;
public static final
int
YUV420SP
=
1
;
private static boolean isImageFormatSupported(Image image) {
int
format
=
image.getFormat();
if
(
format
=
=
17
||
format
=
=
35
||
format
=
=
842094169
) {
return
true;
}
return
false;
}
public static void dumpFile(String
str
, byte[] bArr) {
try
{
FileOutputStream fileOutputStream
=
new FileOutputStream(
str
);
try
{
fileOutputStream.write(bArr);
fileOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(
"failed writing data to file "
+
str
, e);
}
} catch (IOException e2) {
throw new RuntimeException(
"Unable to create output file "
+
str
, e2);
}
}
public static void compressToJpeg(String
str
, Image image) {
try
{
FileOutputStream fileOutputStream
=
new FileOutputStream(
str
);
Rect cropRect
=
image.getCropRect();
new YuvImage(getDataFromImage(image,
2
),
17
, cropRect.width(), cropRect.height(), (
int
[]) null).compressToJpeg(cropRect,
100
, fileOutputStream);
} catch (IOException e) {
throw new RuntimeException(
"Unable to create output file "
+
str
, e);
}
}
public static byte[] yuvToCompressedJPEG(byte[] bArr, Rect rect) {
ByteArrayOutputStream byteArrayOutputStream
=
new ByteArrayOutputStream();
new YuvImage(bArr,
17
, rect.width(), rect.height(), (
int
[]) null).compressToJpeg(rect,
100
, byteArrayOutputStream);
return
byteArrayOutputStream.toByteArray();
}
public static byte[] getDataFromImage(Image image,
int
i) {
Rect rect;
int
i2;
int
i3
=
i;
int
i4
=
2
;
int
i5
=
1
;
if
(i3 !
=
1
&& i3 !
=
2
) {
throw new IllegalArgumentException(
"only support COLOR_FormatI420 and COLOR_FormatNV21"
);
}
else
if
(isImageFormatSupported(image)) {
Rect cropRect
=
image.getCropRect();
int
format
=
image.getFormat();
int
width
=
cropRect.width();
int
height
=
cropRect.height();
Image.Plane[] planes
=
image.getPlanes();
int
i6
=
width
*
height;
byte[] bArr
=
new byte[((ImageFormat.getBitsPerPixel(
format
)
*
i6)
/
8
)];
int
i7
=
0
;
byte[] bArr2
=
new byte[planes[
0
].getRowStride()];
int
i8
=
1
;
int
i9
=
0
;
int
i10
=
0
;
while
(i9 < planes.length) {
switch (i9) {
case
0
:
i8
=
i5;
i10
=
i7;
break
;
case
1
:
if
(i3 !
=
i5) {
if
(i3
=
=
i4) {
i10
=
i6
+
1
;
i8
=
i4;
break
;
}
}
else
{
i8
=
i5;
i10
=
i6;
break
;
}
break
;
case
2
:
if
(i3 !
=
i5) {
if
(i3
=
=
i4) {
i8
=
i4;
i10
=
i6;
break
;
}
}
else
{
i10
=
(
int
) (((double) i6)
*
1.25d
);
i8
=
i5;
break
;
}
break
;
}
ByteBuffer
buffer
=
planes[i9].getBuffer();
int
rowStride
=
planes[i9].getRowStride();
int
pixelStride
=
planes[i9].getPixelStride();
int
i11
=
i9
=
=
0
? i7 : i5;
int
i12
=
width >> i11;
int
i13
=
height >> i11;
int
i14
=
width;
buffer
.position(((cropRect.top >> i11)
*
rowStride)
+
((cropRect.left >> i11)
*
pixelStride));
int
i15
=
0
;
while
(i15 < i13) {
if
(pixelStride
=
=
1
&& i8
=
=
1
) {
buffer
.get(bArr, i10, i12);
i10
+
=
i12;
rect
=
cropRect;
i2
=
i12;
}
else
{
i2
=
((i12
-
1
)
*
pixelStride)
+
1
;
rect
=
cropRect;
buffer
.get(bArr2,
0
, i2);
int
i16
=
i10;
for
(
int
i17
=
0
; i17 < i12; i17
+
+
) {
bArr[i16]
=
bArr2[i17
*
pixelStride];
i16
+
=
i8;
}
i10
=
i16;
}
if
(i15 < i13
-
1
) {
buffer
.position((
buffer
.position()
+
rowStride)
-
i2);
}
i15
+
+
;
cropRect
=
rect;
}
Log.v(TAG,
"Finished reading data from plane "
+
i9);
i9
+
+
;
i5
=
1
;
width
=
i14;
i3
=
i;
i4
=
2
;
i7
=
0
;
}
return
bArr;
}
else
{
throw new RuntimeException(
"can't convert Image to byte array, format "
+
image.getFormat());
}
}
public static byte[] getBytesFromImageAsType(Image image,
int
i) {
Image.Plane[] planeArr;
Image.Plane[] planeArr2;
try
{
Image.Plane[] planes
=
image.getPlanes();
int
width
=
image.getWidth();
int
height
=
image.getHeight();
int
i2
=
width
*
height;
byte[] bArr
=
new byte[((ImageFormat.getBitsPerPixel(
35
)
*
i2)
/
8
)];
byte[] bArr2
=
new byte[(i2
/
4
)];
byte[] bArr3
=
new byte[(i2
/
4
)];
int
i3
=
0
;
int
i4
=
0
;
int
i5
=
0
;
int
i6
=
0
;
while
(i3 < planes.length) {
int
pixelStride
=
planes[i3].getPixelStride();
int
rowStride
=
planes[i3].getRowStride();
ByteBuffer
buffer
=
planes[i3].getBuffer();
byte[] bArr4
=
new byte[
buffer
.capacity()];
buffer
.get(bArr4);
if
(i3
=
=
0
) {
int
i7
=
i4;
int
i8
=
0
;
for
(
int
i9
=
0
; i9 < height; i9
+
+
) {
System.arraycopy(bArr4, i8, bArr, i7, width);
i8
+
=
rowStride;
i7
+
=
width;
}
planeArr
=
planes;
i4
=
i7;
}
else
if
(i3
=
=
1
) {
int
i10
=
i5;
int
i11
=
0
;
for
(
int
i12
=
0
; i12 < height
/
2
; i12
+
+
) {
int
i13
=
0
;
while
(i13 < width
/
2
) {
bArr2[i10]
=
bArr4[i11];
i11
+
=
pixelStride;
i13
+
+
;
i10
+
+
;
}
if
(pixelStride
=
=
2
) {
i11
+
=
rowStride
-
width;
}
else
if
(pixelStride
=
=
1
) {
i11
+
=
rowStride
-
(width
/
2
);
}
}
planeArr
=
planes;
i5
=
i10;
}
else
if
(i3
=
=
2
) {
int
i14
=
i6;
int
i15
=
0
;
int
i16
=
0
;
while
(i15 < height
/
2
) {
int
i17
=
i16;
int
i18
=
0
;
while
(true) {
planeArr2
=
planes;
if
(i18 >
=
width
/
2
) {
break
;
}
bArr3[i14]
=
bArr4[i17];
i17
+
=
pixelStride;
i18
+
+
;
i14
+
+
;
planes
=
planeArr2;
}
if
(pixelStride
=
=
2
) {
i17
+
=
rowStride
-
width;
}
else
if
(pixelStride
=
=
1
) {
i17
+
=
rowStride
-
(width
/
2
);
}
i15
+
+
;
i16
=
i17;
planes
=
planeArr2;
}
planeArr
=
planes;
i6
=
i14;
}
else
{
planeArr
=
planes;
}
i3
+
+
;
planes
=
planeArr;
}
switch (i) {
case
0
:
System.arraycopy(bArr2,
0
, bArr, i4, bArr2.length);
System.arraycopy(bArr3,
0
, bArr, i4
+
bArr2.length, bArr3.length);
break
;
case
1
:
for
(
int
i19
=
0
; i19 < bArr3.length; i19
+
+
) {
int
i20
=
i4
+
1
;
bArr[i4]
=
bArr2[i19];
i4
=
i20
+
1
;
bArr[i20]
=
bArr3[i19];
}
break
;
case
2
:
for
(
int
i21
=
0
; i21 < bArr3.length; i21
+
+
) {
int
i22
=
i4
+
1
;
bArr[i4]
=
bArr3[i21];
i4
=
i22
+
1
;
bArr[i22]
=
bArr2[i21];
}
break
;
}
return
bArr;
} catch (Exception e) {
if
(image
=
=
null) {
return
null;
}
image.close();
return
null;
}
}
public static
int
[] decodeYUV420SP(byte[] bArr,
int
i,
int
i2) {
int
i3
=
i;
int
i4
=
i2;
int
i5
=
i3
*
i;
int
[] iArr
=
new
int
[i5];
int
i6
=
0
;
int
i7
=
0
;
while
(i6 < i4) {
int
i8
=
((i6 >>
1
)
*
i3)
+
i5;
int
i9
=
0
;
int
i10
=
0
;
int
i11
=
i7;
int
i12
=
0
;
while
(i12 < i3) {
int
i13
=
(bArr[i11] &
255
)
-
16
;
if
(i13 <
0
) {
i13
=
0
;
}
if
((i12 &
1
)
=
=
0
) {
int
i14
=
i8
+
1
;
int
i15
=
i14
+
1
;
int
i16
=
(bArr[i14] &
255
)
-
128
;
i9
=
(bArr[i8] &
255
)
-
128
;
i8
=
i15;
i10
=
i16;
}
int
i17
=
1192
*
i13;
int
i18
=
(
1634
*
i9)
+
i17;
int
i19
=
(i17
-
(MetricsProto.MetricsEvent.FIELD_CONTEXT
*
i9))
-
(
400
*
i10);
int
i20
=
i17
+
(
2066
*
i10);
if
(i18 <
0
) {
i18
=
0
;
}
else
if
(i18 >
262143
) {
i18
=
262143
;
}
if
(i19 <
0
) {
i19
=
0
;
}
else
if
(i19 >
262143
) {
i19
=
262143
;
}
if
(i20 <
0
) {
i20
=
0
;
}
else
if
(i20 >
262143
) {
i20
=
262143
;
}
iArr[i11]
=
-
16777216
| ((i18 <<
6
) & Spanned.SPAN_PRIORITY) | ((i19 >>
2
) &
65280
) | ((i20 >>
10
) &
255
);
i11
+
+
;
}
i6
+
+
;
i7
=
i11;
}
return
iArr;
}
}