├── .gitignore ├── README.md ├── README_cn.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── luoye │ │ └── bzyuvlib │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── luoye │ │ │ └── bzyuvlib │ │ │ ├── Bitmap2YUVActivity.java │ │ │ ├── Camera1YUVCropActivity.java │ │ │ ├── Camera2Activity.java │ │ │ ├── Camera2YUVCropActivity.java │ │ │ ├── CameraActivity.java │ │ │ ├── GreyImageTestActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── PermissionUtil.java │ │ │ ├── RGBAHandleActivity.java │ │ │ ├── YUV420ToNV21Activity.java │ │ │ └── ZoomYUVActivity.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ ├── timg.jpeg │ │ └── timg_2.jpeg │ │ ├── layout │ │ ├── activity_bitmap2_y_u_v.xml │ │ ├── activity_camera.xml │ │ ├── activity_camera1_y_u_v_crop.xml │ │ ├── activity_camera2.xml │ │ ├── activity_camera2_y_u_v_crop.xml │ │ ├── activity_grey_image_test.xml │ │ ├── activity_main.xml │ │ ├── activity_r_g_b_a_handle.xml │ │ ├── activity_yuv420_to_nv_21.xml │ │ └── activity_zoom_yuv.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── luoye │ └── bzyuvlib │ └── ExampleUnitTest.java ├── build.gradle ├── bzyuv ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── luoye │ │ └── bzyuv │ │ └── ExampleInstrumentedTest.java │ └── main │ ├── AndroidManifest.xml │ ├── cpp │ ├── BZLogUtil.cpp │ ├── BZLogUtil.h │ ├── CMakeLists.txt │ ├── bz_time.cpp │ ├── bz_time.h │ ├── include │ │ ├── libyuv.h │ │ └── libyuv │ │ │ ├── basic_types.h │ │ │ ├── compare.h │ │ │ ├── compare_row.h │ │ │ ├── convert.h │ │ │ ├── convert_argb.h │ │ │ ├── convert_from.h │ │ │ ├── convert_from_argb.h │ │ │ ├── cpu_id.h │ │ │ ├── macros_msa.h │ │ │ ├── mjpeg_decoder.h │ │ │ ├── planar_functions.h │ │ │ ├── rotate.h │ │ │ ├── rotate_argb.h │ │ │ ├── rotate_row.h │ │ │ ├── row.h │ │ │ ├── scale.h │ │ │ ├── scale_argb.h │ │ │ ├── scale_row.h │ │ │ ├── version.h │ │ │ └── video_common.h │ ├── lib │ │ ├── arm64-v8a │ │ │ └── libyuv_static.a │ │ ├── armeabi-v7a │ │ │ └── libyuv_static.a │ │ ├── x86 │ │ │ └── libyuv_static.a │ │ └── x86_64 │ │ │ └── libyuv_static.a │ └── native-lib.cpp │ └── java │ └── com │ └── luoye │ └── bzyuvlib │ ├── BZYUVSoLoadingUtil.java │ └── BZYUVUtil.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | ### JetBrains template 11 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 12 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 13 | 14 | 15 | 16 | # Gradle and Maven with auto-import 17 | # When using Gradle or Maven with auto-import, you should exclude module files, 18 | # since they will be recreated, and may cause churn. Uncomment if using 19 | # auto-import. 20 | # .idea/modules.xml 21 | # .idea/*.iml 22 | # .idea/modules 23 | # *.iml 24 | # *.ipr 25 | 26 | # CMake 27 | cmake-build-*/ 28 | 29 | # Mongo Explorer plugin 30 | .idea/**/mongoSettings.xml 31 | 32 | # File-based project format 33 | *.iws 34 | 35 | # IntelliJ 36 | out/ 37 | 38 | # mpeltonen/sbt-idea plugin 39 | .idea_modules/ 40 | 41 | # JIRA plugin 42 | atlassian-ide-plugin.xml 43 | 44 | # Cursive Clojure plugin 45 | .idea/replstate.xml 46 | 47 | # Crashlytics plugin (for Android Studio and IntelliJ) 48 | com_crashlytics_export_strings.xml 49 | crashlytics.properties 50 | crashlytics-build.properties 51 | fabric.properties 52 | 53 | # Editor-based Rest Client 54 | .idea/httpRequests 55 | 56 | # Android studio 3.1+ serialized cache file 57 | .idea/caches/build_file_checksums.ser 58 | 59 | ### Android template 60 | # Built application files 61 | *.apk 62 | *.ap_ 63 | *.aab 64 | 65 | # Files for the ART/Dalvik VM 66 | *.dex 67 | 68 | # Java class files 69 | *.class 70 | 71 | # Generated files 72 | bin/ 73 | gen/ 74 | release/ 75 | 76 | # Gradle files 77 | .gradle/ 78 | build/ 79 | 80 | # Local configuration file (sdk path, etc) 81 | local.properties 82 | 83 | # Proguard folder generated by Eclipse 84 | proguard/ 85 | 86 | # Log Files 87 | *.log 88 | 89 | # Android Studio Navigation editor temp files 90 | .navigation/ 91 | 92 | # Android Studio captures folder 93 | captures/ 94 | 95 | # IntelliJ 96 | .idea/workspace.xml 97 | .idea/tasks.xml 98 | .idea/gradle.xml 99 | .idea/assetWizardSettings.xml 100 | .idea/dictionaries 101 | .idea/libraries 102 | # Android Studio 3 in .gitignore file. 103 | .idea/caches 104 | .idea/modules.xml 105 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 106 | .idea/navEditor.xml 107 | 108 | # Keystore files 109 | # Uncomment the following lines if you do not want to check your keystore files in. 110 | #*.jks 111 | #*.keystore 112 | 113 | # External native build folder generated in Android Studio 2.2 and later 114 | 115 | # Google Services (e.g. APIs or Firebase) 116 | # google-services.json 117 | 118 | # Freeline 119 | freeline.py 120 | freeline/ 121 | freeline_project_description.json 122 | 123 | # fastlane 124 | fastlane/report.xml 125 | fastlane/Preview.html 126 | fastlane/screenshots 127 | fastlane/test_output 128 | fastlane/readme.md 129 | 130 | # Version control 131 | vcs.xml 132 | 133 | # lint 134 | lint/intermediates/ 135 | lint/generated/ 136 | lint/outputs/ 137 | lint/tmp/ 138 | # lint/reports/ 139 | Thumbs.db 140 | Thumbs.db:encryptable 141 | ehthumbs.db 142 | ehthumbs_vista.db 143 | *.stackdump 144 | [Dd]esktop.ini 145 | $RECYCLE.BIN/ 146 | *.cab 147 | *.msi 148 | *.msix 149 | *.msm 150 | *.msp 151 | *.lnk 152 | .DS_Store 153 | .AppleDouble 154 | .LSOverride 155 | Icon 156 | ._* 157 | .DocumentRevisions-V100 158 | .fseventsd 159 | .Spotlight-V100 160 | .TemporaryItems 161 | .Trashes 162 | .VolumeIcon.icns 163 | .com.apple.timemachine.donotpresent 164 | .AppleDB 165 | .AppleDesktop 166 | Network Trash Folder 167 | Temporary Items 168 | .apdisk 169 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | I previously wrote a YUV to RGBA project based on RenderScript, address: https://www.raoyunsoft.com/wordpress/index.php/2020/01/19/yuvrenderscript/ If you like it, you can go here to find it, than Android native ScriptIntrinsicYuvToRGB is much more powerful, but recently found that RenderScript is much slower than Google ’s libyuv, so I wrote a YUV conversion project based on libyuv, and also supported the YUV conversion of Camera1 and Camera2 output, and the YUV mirror , Rotation, supported functions are as follows: 2 | 3 | 1. yuv420pToRGBA/yuv420pToBGRA 4 | 2. preHandleYUV 5 | 3. yv12ToRGBA/yv12ToBGRA 6 | 4. nv21ToRGBA/nv21ToBGRA 7 | 5. cropNV21/cropYUV420 8 | 6. zoomYUV420 9 | 7. bitmapToYUV420 10 | 8. yuvToGrey 11 | 9. greyToRGBA 12 | 10. translationSingleChannel 13 | 11. Support RGBA rotation and mirroring 14 | 12. yuvI420ToNV21 15 | 13. yuvI420ToNV12 16 | 17 | 18 | 19 | #### How to use: 20 | 21 | ##### 1.First add mavenCentral() as shown below 22 | 23 | ``` 24 | allprojects { 25 | repositories { 26 | maven { url "https://nexus.raoyunsoft.com/repository/maven-releases/" } 27 | } 28 | } 29 | ``` 30 | 31 | ##### 2. implementation 'com.guaishou.bzlib:bzyuv:1.1.19@aar' 32 | 33 | 34 | 35 | If it helps you, please give me a start 36 | 37 | 38 | 39 | [中文文档(Chinese DOC)](https://github.com/bookzhan/bzyuvlib/blob/master/README_cn.md) 40 | 41 | -------------------------------------------------------------------------------- /README_cn.md: -------------------------------------------------------------------------------- 1 | 之前基于RenderScript写了一个YUV转RGBA的工程,地址:https://www.raoyunsoft.com/wordpress/index.php/2020/01/19/yuvrenderscript/ 喜欢的可以去看看,比Android原生的ScriptIntrinsicYuvToRGB要强大很多,但是近期在使用的过程中发现RenderScript比Google的libyuv速度要慢很多,于是我又基于libyuv写了一个YUV转换的工程,同时支持Camera1,Camera2输出的YUV转换,以及对YUV镜像,旋转,从YUV输出灰度图,灰度图转成RGBA, 单通道平移,具体支持的功能如下: 2 | 3 | 1. yuv420pToRGBA/yuv420pToBGRA 4 | 2. preHandleYUV 5 | 3. yv12ToRGBA/yv12ToBGRA 6 | 4. nv21ToRGBA/nv21ToBGRA 7 | 5. cropNV21/cropYUV420 8 | 6. zoomYUV420 9 | 7. bitmapToYUV420 10 | 8. yuvToGrey 11 | 9. greyToRGBA 12 | 10. translationSingleChannel 13 | 11. 支持RGBA的旋转,镜像 14 | 12. yuvI420ToNV21 15 | 13. yuvI420ToNV12 16 | 17 | 18 | 19 | #### 如何使用: 20 | 21 | ##### 1.先添加mavenCentral(),如下所示 22 | 23 | ``` 24 | allprojects { 25 | repositories { 26 | maven { url "https://nexus.raoyunsoft.com/repository/maven-releases/" } 27 | } 28 | } 29 | ``` 30 | 31 | ##### 2.然后implementation 'com.guaishou.bzlib:bzyuv:1.1.19@aar' 32 | 33 | 34 | 35 | 如果帮到了你,请给一个star 36 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 33 5 | 6 | defaultConfig { 7 | applicationId "com.luoye.bzyuvlib" 8 | minSdkVersion 21 9 | targetSdkVersion 33 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | 21 | lintOptions { 22 | abortOnError false 23 | } 24 | namespace 'com.luoye.bzyuvlib' 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(dir: 'libs', include: ['*.jar']) 29 | implementation 'androidx.appcompat:appcompat:1.4.1' 30 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 31 | testImplementation 'junit:junit:4.13.2' 32 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 33 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 34 | 35 | implementation 'com.guaishou.bzlib:bzcommon:1.1.24@aar' 36 | implementation 'com.guaishou.bzlib:bzcamera:1.0.24@aar' 37 | implementation project(path: ':bzyuv') 38 | } 39 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/luoye/bzyuvlib/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.luoye.bzyuvlib", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/Bitmap2YUVActivity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.nfc.Tag; 8 | import android.os.Bundle; 9 | import android.util.Log; 10 | import android.widget.ImageView; 11 | 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | import java.io.FileOutputStream; 15 | import java.nio.ByteBuffer; 16 | 17 | public class Bitmap2YUVActivity extends AppCompatActivity { 18 | 19 | private static final String TAG = "bz_Bitmap2YUVActivity"; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_bitmap2_y_u_v); 25 | ImageView ivImageSrc = findViewById(R.id.iv_image_src); 26 | ImageView ivImageDis = findViewById(R.id.iv_image_dis); 27 | Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.timg); 28 | 29 | // bitmap = convertRGB565(bitmap); 30 | 31 | ivImageSrc.setImageBitmap(bitmap); 32 | Log.d(TAG, "getWidth=" + bitmap.getWidth() + " getHeight=" + bitmap.getHeight()); 33 | 34 | byte[] yuvBuffer = new byte[bitmap.getWidth() * bitmap.getHeight() * 3 / 2]; 35 | BZYUVUtil.bitmapToYUV420(bitmap, yuvBuffer); 36 | 37 | 38 | byte[] rgbaBuffer = new byte[bitmap.getWidth() * bitmap.getHeight() * 4]; 39 | BZYUVUtil.yuv420ToRGBA(yuvBuffer, rgbaBuffer, bitmap.getWidth(), bitmap.getHeight(), false, 0); 40 | Bitmap disBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); 41 | disBitmap.copyPixelsFromBuffer(ByteBuffer.wrap(rgbaBuffer)); 42 | 43 | ivImageDis.setImageBitmap(disBitmap); 44 | } 45 | 46 | private Bitmap convertRGB565(Bitmap bitmap) { 47 | Bitmap disBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565); 48 | Canvas canvas = new Canvas(disBitmap); 49 | canvas.drawBitmap(bitmap, 0, 0, new Paint()); 50 | return disBitmap; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/Camera1YUVCropActivity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.ImageFormat; 5 | import android.hardware.Camera; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.widget.ImageView; 9 | 10 | import androidx.appcompat.app.AppCompatActivity; 11 | 12 | import com.luoye.bzcamera.BZCameraView; 13 | import com.luoye.bzcamera.listener.OnCameraStateListener; 14 | 15 | import java.nio.ByteBuffer; 16 | 17 | public class Camera1YUVCropActivity extends AppCompatActivity { 18 | private static final String TAG = "bz_Camera1YUVCrop"; 19 | 20 | private BZCameraView bz_camera_view; 21 | private ImageView bz_image_view; 22 | private byte[] yuvBuffer = null; 23 | private byte[] argbByteBuffer = null; 24 | private byte[] cropYuvBuffer = null; 25 | private int index = 0; 26 | private Bitmap bitmap = null; 27 | private long totalTime = 0; 28 | private int cropStartX = 100; 29 | private int cropStartY = 100; 30 | private int cropWidth = 240; 31 | private int cropHeight = 320; 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.activity_camera1_y_u_v_crop); 37 | bz_camera_view = findViewById(R.id.bz_camera_view); 38 | bz_camera_view.setPreviewTargetSize(480, 640); 39 | bz_image_view = findViewById(R.id.bz_image_view); 40 | 41 | 42 | // bz_image_view.setScaleX(-1); 43 | // bz_image_view.setScaleY(-1); 44 | bz_camera_view.setPreviewFormat(ImageFormat.NV21); 45 | bz_camera_view.setNeedCallBackData(true); 46 | bz_camera_view.setOnCameraStateListener(new OnCameraStateListener() { 47 | @Override 48 | public void onPreviewSuccess(Camera camera, int width, int height) { 49 | 50 | } 51 | 52 | @Override 53 | public void onPreviewFail(String message) { 54 | 55 | } 56 | 57 | @Override 58 | public void onPreviewDataUpdate(byte[] data, int width, int height, int displayOrientation, int cameraId) { 59 | if (width < cropWidth + cropStartX || height < cropHeight + cropStartY) { 60 | Log.e(TAG, "width < cropWidth + cropStartX || height < cropHeight + cropStartY"); 61 | return; 62 | } 63 | long startTime = System.currentTimeMillis(); 64 | if (null == yuvBuffer) { 65 | yuvBuffer = new byte[width * height * 3 / 2]; 66 | } 67 | if (null == argbByteBuffer) { 68 | argbByteBuffer = new byte[cropWidth * cropHeight * 4]; 69 | } 70 | if (null == cropYuvBuffer) { 71 | cropYuvBuffer = new byte[cropWidth * cropHeight * 3 / 2]; 72 | } 73 | //Correct angle and mirror image to facilitate crop coordinate calculation 74 | BZYUVUtil.preHandleNV21(data, yuvBuffer, width, height, cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT, displayOrientation); 75 | if (displayOrientation == 270 || displayOrientation == 90) { 76 | BZYUVUtil.cropYUV420(yuvBuffer, cropYuvBuffer, height, width, cropStartX, cropStartY, cropWidth, cropHeight); 77 | } else { 78 | BZYUVUtil.cropYUV420(yuvBuffer, cropYuvBuffer, width, height, cropStartX, cropStartY, cropWidth, cropHeight); 79 | } 80 | BZYUVUtil.yuv420ToRGBA(cropYuvBuffer, argbByteBuffer, cropWidth, cropHeight, false, 0); 81 | index++; 82 | totalTime += (System.currentTimeMillis() - startTime); 83 | Log.d(TAG, "time cost=" + (totalTime / index)); 84 | 85 | if (null == bitmap) { 86 | bitmap = Bitmap.createBitmap(cropWidth, cropHeight, Bitmap.Config.ARGB_8888); 87 | } 88 | bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(argbByteBuffer)); 89 | bz_image_view.post(new Runnable() { 90 | @Override 91 | public void run() { 92 | bz_image_view.setImageBitmap(bitmap); 93 | } 94 | }); 95 | } 96 | 97 | @Override 98 | public void onCameraClose() { 99 | 100 | } 101 | }); 102 | } 103 | 104 | @Override 105 | protected void onResume() { 106 | super.onResume(); 107 | bz_camera_view.onResume(); 108 | } 109 | 110 | @Override 111 | protected void onPause() { 112 | super.onPause(); 113 | bz_camera_view.onPause(); 114 | } 115 | 116 | @Override 117 | protected void onDestroy() { 118 | super.onDestroy(); 119 | Log.d("onDestroy", "yuvFileOutputStream.close"); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/Camera2Activity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.annotation.TargetApi; 4 | import android.graphics.Bitmap; 5 | import android.hardware.camera2.CameraCharacteristics; 6 | import android.hardware.camera2.CameraDevice; 7 | import android.media.Image; 8 | import android.os.Build; 9 | import android.os.Bundle; 10 | import android.util.Log; 11 | import android.widget.ImageView; 12 | 13 | import androidx.appcompat.app.AppCompatActivity; 14 | 15 | import com.luoye.bzcamera.BZCamera2View; 16 | 17 | import java.nio.ByteBuffer; 18 | 19 | @TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP) 20 | public class Camera2Activity extends AppCompatActivity { 21 | private static final String TAG = "bz_Camera2Activity"; 22 | private BZCamera2View bz_camera2_view; 23 | private ImageView iv_preview; 24 | private BZYUVUtil bzyuvUtil; 25 | private Bitmap bitmap; 26 | private long spaceTime; 27 | private int index; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_camera2); 33 | iv_preview = findViewById(R.id.iv_preview); 34 | bz_camera2_view = findViewById(R.id.bz_camera2_view); 35 | bz_camera2_view.setPreviewTargetSize(480,640); 36 | bz_camera2_view.setCheckCameraCapacity(false); 37 | bzyuvUtil = new BZYUVUtil(); 38 | bz_camera2_view.setOnStatusChangeListener(new BZCamera2View.OnStatusChangeListener() { 39 | @Override 40 | public void onPreviewSuccess(CameraDevice mCameraDevice, int width, int height) { 41 | 42 | } 43 | 44 | @Override 45 | public void onImageAvailable(Image image, int displayOrientation, float fps) { 46 | int height = image.getHeight(); 47 | int width = image.getWidth(); 48 | if (displayOrientation == 270 || displayOrientation == 90) { 49 | width = image.getHeight(); 50 | height = image.getWidth(); 51 | } 52 | long startTime = System.currentTimeMillis(); 53 | byte[] pixData = bzyuvUtil.yuv420pToRGBA(image, bz_camera2_view.getCurrentCameraLensFacing() == CameraCharacteristics.LENS_FACING_FRONT, displayOrientation); 54 | 55 | spaceTime += (System.currentTimeMillis() - startTime); 56 | index++; 57 | Log.d(TAG, "time cost=" + (spaceTime / index) + " bitmap.width=" + width + " height=" + height); 58 | if (null == bitmap) { 59 | bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 60 | } 61 | bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(pixData)); 62 | iv_preview.post(new Runnable() { 63 | @Override 64 | public void run() { 65 | iv_preview.setImageBitmap(bitmap); 66 | } 67 | }); 68 | } 69 | }); 70 | 71 | } 72 | 73 | @Override 74 | protected void onResume() { 75 | super.onResume(); 76 | bz_camera2_view.onResume(); 77 | } 78 | 79 | @Override 80 | protected void onPause() { 81 | super.onPause(); 82 | bz_camera2_view.onPause(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/Camera2YUVCropActivity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.annotation.TargetApi; 4 | import android.graphics.Bitmap; 5 | import android.hardware.camera2.CameraCharacteristics; 6 | import android.hardware.camera2.CameraDevice; 7 | import android.media.Image; 8 | import android.os.Bundle; 9 | import android.util.Log; 10 | import android.widget.ImageView; 11 | 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | import com.luoye.bzcamera.BZCamera2View; 15 | 16 | import java.io.FileOutputStream; 17 | import java.nio.ByteBuffer; 18 | 19 | @TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP) 20 | public class Camera2YUVCropActivity extends AppCompatActivity { 21 | private static final String TAG = "bz_Camera2YUVCrop"; 22 | private BZCamera2View bz_camera2_view; 23 | private ImageView iv_preview; 24 | private BZYUVUtil bzyuvUtil; 25 | private Bitmap bitmap; 26 | private long spaceTime; 27 | private int index; 28 | private int cropStartX = 100; 29 | private int cropStartY = 100; 30 | private int cropWidth = 240; 31 | private int cropHeight = 320; 32 | private byte[] argbByteBuffer = null; 33 | private byte[] cropYuvBuffer = null; 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_camera2_y_u_v_crop); 39 | iv_preview = findViewById(R.id.iv_preview); 40 | bz_camera2_view = findViewById(R.id.bz_camera2_view); 41 | bz_camera2_view.setCheckCameraCapacity(false); 42 | bzyuvUtil = new BZYUVUtil(); 43 | bz_camera2_view.setOnStatusChangeListener(new BZCamera2View.OnStatusChangeListener() { 44 | 45 | private FileOutputStream fileOutputStream; 46 | 47 | @Override 48 | public void onPreviewSuccess(CameraDevice mCameraDevice, int width, int height) { 49 | 50 | } 51 | 52 | @Override 53 | public void onImageAvailable(Image image, int displayOrientation, float fps) { 54 | int height = image.getHeight(); 55 | int width = image.getWidth(); 56 | if (displayOrientation == 270 || displayOrientation == 90) { 57 | width = image.getHeight(); 58 | height = image.getWidth(); 59 | } 60 | if (width < cropWidth + cropStartX || height < cropHeight + cropStartY) { 61 | Log.e(TAG, "width < cropWidth + cropStartX || height < cropHeight + cropStartY"); 62 | return; 63 | } 64 | if (null == argbByteBuffer) { 65 | argbByteBuffer = new byte[cropWidth * cropHeight * 4]; 66 | } 67 | if (null == cropYuvBuffer) { 68 | cropYuvBuffer = new byte[cropWidth * cropHeight * 3 / 2]; 69 | } 70 | long startTime = System.currentTimeMillis(); 71 | byte[] yuv420 = bzyuvUtil.preHandleYUV420(image, bz_camera2_view.getCurrentCameraLensFacing() == CameraCharacteristics.LENS_FACING_FRONT, displayOrientation); 72 | if (null == fileOutputStream) { 73 | try { 74 | fileOutputStream = new FileOutputStream("/sdcard/bzmedia/kk.yuv"); 75 | fileOutputStream.write(yuv420, 0, yuv420.length); 76 | fileOutputStream.flush(); 77 | fileOutputStream.close(); 78 | } catch (Exception e) { 79 | e.printStackTrace(); 80 | } 81 | } 82 | 83 | BZYUVUtil.cropYUV420(yuv420, cropYuvBuffer, width, height, cropStartX, cropStartY, cropWidth, cropHeight); 84 | 85 | BZYUVUtil.yuv420ToRGBA(cropYuvBuffer, argbByteBuffer, cropWidth, cropHeight, false, 0); 86 | 87 | spaceTime += (System.currentTimeMillis() - startTime); 88 | index++; 89 | Log.d(TAG, "time cost=" + (spaceTime / index) + " bitmap.width=" + width + " height=" + height); 90 | if (null == bitmap) { 91 | bitmap = Bitmap.createBitmap(cropWidth, cropHeight, Bitmap.Config.ARGB_8888); 92 | } 93 | bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(argbByteBuffer)); 94 | iv_preview.post(new Runnable() { 95 | @Override 96 | public void run() { 97 | iv_preview.setImageBitmap(bitmap); 98 | } 99 | }); 100 | } 101 | }); 102 | } 103 | 104 | @Override 105 | protected void onResume() { 106 | super.onResume(); 107 | bz_camera2_view.onResume(); 108 | } 109 | 110 | @Override 111 | protected void onPause() { 112 | super.onPause(); 113 | bz_camera2_view.onPause(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/CameraActivity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.ImageFormat; 5 | import android.hardware.Camera; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.widget.ImageView; 9 | 10 | import androidx.appcompat.app.AppCompatActivity; 11 | 12 | import com.luoye.bzcamera.BZCameraView; 13 | import com.luoye.bzcamera.listener.OnCameraStateListener; 14 | 15 | import java.nio.ByteBuffer; 16 | 17 | public class CameraActivity extends AppCompatActivity { 18 | private static final String TAG = "bz_CameraActivity"; 19 | 20 | private BZCameraView bz_camera_view; 21 | private ImageView bz_image_view; 22 | private byte[] argbByteBuffer = null; 23 | private int index = 0; 24 | private Bitmap bitmap = null; 25 | private long totalTime = 0; 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_camera); 31 | bz_camera_view = findViewById(R.id.bz_camera_view); 32 | bz_camera_view.setPreviewTargetSize(480, 640); 33 | bz_image_view = findViewById(R.id.bz_image_view); 34 | 35 | 36 | // bz_image_view.setScaleX(-1); 37 | // bz_image_view.setScaleY(-1); 38 | bz_camera_view.setPreviewFormat(ImageFormat.NV21); 39 | bz_camera_view.setNeedCallBackData(true); 40 | bz_camera_view.setOnCameraStateListener(new OnCameraStateListener() { 41 | @Override 42 | public void onPreviewSuccess(Camera camera, int width, int height) { 43 | 44 | } 45 | 46 | @Override 47 | public void onPreviewFail(String message) { 48 | 49 | } 50 | 51 | @Override 52 | public void onPreviewDataUpdate(byte[] data, int width, int height, int displayOrientation, int cameraId) { 53 | if (null == argbByteBuffer) { 54 | argbByteBuffer = new byte[width * height * 4]; 55 | } 56 | index++; 57 | long startTime = System.currentTimeMillis(); 58 | BZYUVUtil.nv21ToRGBA(data, argbByteBuffer, width, height, cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT, displayOrientation); 59 | totalTime += (System.currentTimeMillis() - startTime); 60 | Log.d(TAG, "time cost=" + (totalTime / index)); 61 | 62 | if (null == bitmap) { 63 | if (displayOrientation == 270 || displayOrientation == 90) { 64 | bitmap = Bitmap.createBitmap(height, width, Bitmap.Config.ARGB_8888); 65 | } else { 66 | bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 67 | } 68 | } 69 | bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(argbByteBuffer)); 70 | bz_image_view.post(new Runnable() { 71 | @Override 72 | public void run() { 73 | bz_image_view.setImageBitmap(bitmap); 74 | } 75 | }); 76 | } 77 | 78 | @Override 79 | public void onCameraClose() { 80 | 81 | } 82 | }); 83 | } 84 | 85 | @Override 86 | protected void onResume() { 87 | super.onResume(); 88 | bz_camera_view.onResume(); 89 | } 90 | 91 | @Override 92 | protected void onPause() { 93 | super.onPause(); 94 | bz_camera_view.onPause(); 95 | } 96 | 97 | @Override 98 | protected void onDestroy() { 99 | super.onDestroy(); 100 | Log.d("onDestroy", "yuvFileOutputStream.close"); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/GreyImageTestActivity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import androidx.annotation.RequiresApi; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | 6 | import android.graphics.Bitmap; 7 | import android.hardware.camera2.CameraDevice; 8 | import android.media.Image; 9 | import android.os.Build; 10 | import android.os.Bundle; 11 | import android.util.Log; 12 | import android.view.View; 13 | import android.widget.ImageView; 14 | 15 | import com.luoye.bzcamera.BZCamera2View; 16 | 17 | import java.nio.ByteBuffer; 18 | 19 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 20 | public class GreyImageTestActivity extends AppCompatActivity { 21 | 22 | private BZCamera2View bz_camera2_view; 23 | private ImageView image_view; 24 | private BZYUVUtil bzyuvUtil; 25 | private byte[] outDataRGBA = null; 26 | private Bitmap bitmap = null; 27 | private byte[] greyBuffer = null; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_grey_image_test); 33 | bzyuvUtil = new BZYUVUtil(); 34 | image_view = findViewById(R.id.image_view); 35 | bz_camera2_view = findViewById(R.id.bz_camera2_view); 36 | bz_camera2_view.setPreviewTargetSize(480, 640); 37 | bz_camera2_view.setDisplayOrientation(90); 38 | bz_camera2_view.switchCamera(); 39 | bz_camera2_view.setOnStatusChangeListener(new BZCamera2View.OnStatusChangeListener() { 40 | @Override 41 | public void onPreviewSuccess(CameraDevice mCameraDevice, int width, int height) { 42 | 43 | } 44 | 45 | @Override 46 | public void onImageAvailable(Image image, int displayOrientation, float fps) { 47 | if (null == outDataRGBA) { 48 | outDataRGBA = new byte[image.getWidth() * image.getHeight() * 4]; 49 | } 50 | if (null == greyBuffer) { 51 | greyBuffer = new byte[image.getWidth() * image.getHeight()]; 52 | } 53 | int width = image.getWidth(); 54 | int height = image.getHeight(); 55 | if (displayOrientation == 90 || displayOrientation == 270) { 56 | width = image.getHeight(); 57 | height = image.getWidth(); 58 | } 59 | byte[] toGrey = bzyuvUtil.yuv420pToGrey(image, true, displayOrientation); 60 | BZYUVUtil.translationSingleChannel(toGrey, greyBuffer, width, height, -60,60); 61 | 62 | BZYUVUtil.greyToRGBA(greyBuffer, outDataRGBA, width, height); 63 | if (null == bitmap) { 64 | bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 65 | } 66 | bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(outDataRGBA)); 67 | image_view.post(new Runnable() { 68 | @Override 69 | public void run() { 70 | image_view.setImageBitmap(bitmap); 71 | } 72 | }); 73 | } 74 | }); 75 | } 76 | 77 | @Override 78 | protected void onResume() { 79 | super.onResume(); 80 | bz_camera2_view.onResume(); 81 | } 82 | 83 | @Override 84 | protected void onPause() { 85 | super.onPause(); 86 | bz_camera2_view.onPause(); 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.Manifest; 4 | import android.content.Intent; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.widget.Toast; 10 | 11 | import androidx.appcompat.app.AppCompatActivity; 12 | 13 | import com.bzcommon.utils.BZPermissionUtil; 14 | 15 | import java.util.ArrayList; 16 | 17 | public class MainActivity extends AppCompatActivity { 18 | private static final String TAG = "bz_MainActivity"; 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_main); 24 | BZPermissionUtil.requestPermissionIfNot(this, Manifest.permission.CAMERA, BZPermissionUtil.CODE_REQ_PERMISSION); 25 | } 26 | 27 | @Override 28 | protected void onResume() { 29 | super.onResume(); 30 | } 31 | 32 | private boolean noPermission() { 33 | if (!BZPermissionUtil.requestPermissionIfNot(this, Manifest.permission.CAMERA, BZPermissionUtil.CODE_REQ_PERMISSION)) { 34 | Toast.makeText(this, "Please give App sufficient permissions", Toast.LENGTH_LONG).show(); 35 | return true; 36 | } 37 | return false; 38 | } 39 | 40 | public void Camera2Activity(View view) { 41 | if (noPermission()) { 42 | return; 43 | } 44 | startActivity(new Intent(this, Camera2Activity.class)); 45 | } 46 | 47 | public void CameraActivity(View view) { 48 | if (noPermission()) { 49 | return; 50 | } 51 | startActivity(new Intent(this, CameraActivity.class)); 52 | } 53 | 54 | public void Camera1YUVCropActivity(View view) { 55 | if (noPermission()) { 56 | return; 57 | } 58 | startActivity(new Intent(this, Camera1YUVCropActivity.class)); 59 | } 60 | 61 | public void Camera2YUVCropActivity(View view) { 62 | if (noPermission()) { 63 | return; 64 | } 65 | startActivity(new Intent(this, Camera2YUVCropActivity.class)); 66 | } 67 | 68 | public void zoomYUV(View view) { 69 | if (noPermission()) { 70 | return; 71 | } 72 | startActivity(new Intent(this, ZoomYUVActivity.class)); 73 | } 74 | 75 | public void Bitmap2YUVActivity(View view) { 76 | if (noPermission()) { 77 | return; 78 | } 79 | startActivity(new Intent(this, Bitmap2YUVActivity.class)); 80 | } 81 | 82 | public void GreyImageTestActivity(View view) { 83 | if (noPermission()) { 84 | return; 85 | } 86 | startActivity(new Intent(this, GreyImageTestActivity.class)); 87 | } 88 | 89 | public void RGBAHandleActivity(View view) { 90 | if (noPermission()) { 91 | return; 92 | } 93 | startActivity(new Intent(this, RGBAHandleActivity.class)); 94 | } 95 | 96 | public void YUV420ToNV21Activity(View view) { 97 | if (noPermission()) { 98 | return; 99 | } 100 | startActivity(new Intent(this, YUV420ToNV21Activity.class)); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/PermissionUtil.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.pm.PackageManager; 6 | 7 | import androidx.core.app.ActivityCompat; 8 | import androidx.core.content.ContextCompat; 9 | 10 | 11 | public class PermissionUtil { 12 | private static final String TAG = "PermissionUtil"; 13 | public static final int CODE_REQ_PERMISSION = 1100; 14 | public static final int CODE_REQ_AUDIO_PERMISSION = 601; 15 | public static final int CODE_REQ_CAMERA_PERMISSION = 602; 16 | 17 | 18 | public static void requestPermission(Activity activity, String[] permissionArr, int requestCode) { 19 | if (permissionArr != null) { 20 | ActivityCompat.requestPermissions(activity, permissionArr, requestCode); 21 | } 22 | 23 | } 24 | 25 | public static void requestPermission(Activity activity, String permissionArr, int requestCode) { 26 | if (permissionArr != null) { 27 | ActivityCompat.requestPermissions(activity, new String[]{permissionArr}, requestCode); 28 | } 29 | } 30 | 31 | public static void requestPermissionIFNot(Activity activity, String permissionArr, int requestCode) { 32 | if (permissionArr != null && !isPermissionGranted(activity, permissionArr)) { 33 | requestPermission(activity, permissionArr, requestCode); 34 | } 35 | } 36 | 37 | public static boolean isPermissionGranted(Context context, String permission) { 38 | if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED) { 39 | return true; 40 | } else { 41 | return false; 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/RGBAHandleActivity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.BitmapFactory; 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.ImageView; 9 | 10 | import androidx.appcompat.app.AppCompatActivity; 11 | 12 | import java.nio.ByteBuffer; 13 | 14 | public class RGBAHandleActivity extends AppCompatActivity { 15 | private final static String TAG = "bz_RGBAHandle"; 16 | private ImageView iv_rgba_dis; 17 | private Bitmap bitmapSrc; 18 | 19 | 20 | @Override 21 | protected void onCreate(Bundle savedInstanceState) { 22 | super.onCreate(savedInstanceState); 23 | setContentView(R.layout.activity_r_g_b_a_handle); 24 | ImageView iv_rgba_src = findViewById(R.id.iv_rgba_src); 25 | iv_rgba_dis = findViewById(R.id.iv_rgba_dis); 26 | 27 | bitmapSrc = BitmapFactory.decodeResource(getResources(), R.drawable.timg_2); 28 | iv_rgba_src.setImageBitmap(bitmapSrc); 29 | } 30 | 31 | public void testRgba(View view) { 32 | Log.d(TAG,"Width="+bitmapSrc.getWidth()+" Height="+bitmapSrc.getHeight()); 33 | byte[] srcBuffer = new byte[bitmapSrc.getWidth() * bitmapSrc.getHeight() * 4]; 34 | bitmapSrc.copyPixelsToBuffer(ByteBuffer.wrap(srcBuffer)); 35 | 36 | byte[] outBuffer = new byte[bitmapSrc.getWidth() * bitmapSrc.getHeight() * 4]; 37 | 38 | int rotate = 90; 39 | long startTime = System.currentTimeMillis(); 40 | BZYUVUtil.handleRGBA(srcBuffer, bitmapSrc.getWidth() * 4, outBuffer, bitmapSrc.getWidth(), bitmapSrc.getHeight(), true, rotate); 41 | Log.d(TAG, "time cost=" + (System.currentTimeMillis() - startTime)); 42 | Bitmap bitmapDis; 43 | if (rotate == 90 || rotate == 270) { 44 | bitmapDis = Bitmap.createBitmap(bitmapSrc.getHeight(), bitmapSrc.getWidth(), Bitmap.Config.ARGB_8888); 45 | } else { 46 | bitmapDis = Bitmap.createBitmap(bitmapSrc.getWidth(), bitmapSrc.getHeight(), Bitmap.Config.ARGB_8888); 47 | } 48 | bitmapDis.copyPixelsFromBuffer(ByteBuffer.wrap(outBuffer)); 49 | iv_rgba_dis.setImageBitmap(bitmapDis); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/YUV420ToNV21Activity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.annotation.TargetApi; 4 | import android.graphics.Bitmap; 5 | import android.hardware.camera2.CameraCharacteristics; 6 | import android.hardware.camera2.CameraDevice; 7 | import android.media.Image; 8 | import android.os.Build; 9 | import android.os.Bundle; 10 | import android.util.Log; 11 | import android.widget.ImageView; 12 | 13 | import androidx.appcompat.app.AppCompatActivity; 14 | 15 | import com.luoye.bzcamera.BZCamera2View; 16 | 17 | import java.nio.ByteBuffer; 18 | 19 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 20 | public class YUV420ToNV21Activity extends AppCompatActivity { 21 | private static final String TAG = "bz_Camera2Activity"; 22 | private BZCamera2View bz_camera2_view; 23 | private ImageView iv_preview; 24 | private BZYUVUtil bzyuvUtil; 25 | private Bitmap bitmap; 26 | private long spaceTime; 27 | private int index; 28 | private byte[] nv21Data; 29 | private byte[] rgbaData; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_yuv420_to_nv_21); 35 | iv_preview = findViewById(R.id.iv_preview); 36 | bz_camera2_view = findViewById(R.id.bz_camera2_view); 37 | bz_camera2_view.setPreviewTargetSize(480, 640); 38 | bz_camera2_view.setCheckCameraCapacity(false); 39 | bzyuvUtil = new BZYUVUtil(); 40 | bz_camera2_view.setOnStatusChangeListener(new BZCamera2View.OnStatusChangeListener() { 41 | @Override 42 | public void onPreviewSuccess(CameraDevice mCameraDevice, int width, int height) { 43 | 44 | } 45 | 46 | @Override 47 | public void onImageAvailable(Image image, int displayOrientation, float fps) { 48 | int height = image.getHeight(); 49 | int width = image.getWidth(); 50 | if (displayOrientation == 270 || displayOrientation == 90) { 51 | width = image.getHeight(); 52 | height = image.getWidth(); 53 | } 54 | long startTime = System.currentTimeMillis(); 55 | byte[] yuv420 = bzyuvUtil.preHandleYUV420(image, bz_camera2_view.getCurrentCameraLensFacing() == CameraCharacteristics.LENS_FACING_FRONT, displayOrientation); 56 | 57 | if (null == nv21Data) { 58 | nv21Data = new byte[width * height * 3 / 2]; 59 | } 60 | if (null == rgbaData) { 61 | rgbaData = new byte[width * height * 4]; 62 | } 63 | BZYUVUtil.yuvI420ToNV21(yuv420, nv21Data, width, height); 64 | // BZYUVUtil.yuvI420ToNV12(yuv420, nv21Data, width, height); 65 | 66 | BZYUVUtil.nv21ToRGBA(nv21Data,rgbaData,width,height,false,0); 67 | 68 | spaceTime += (System.currentTimeMillis() - startTime); 69 | index++; 70 | Log.d(TAG, "time cost=" + (spaceTime / index) + " bitmap.width=" + width + " height=" + height); 71 | if (null == bitmap) { 72 | bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 73 | } 74 | bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(rgbaData)); 75 | iv_preview.post(new Runnable() { 76 | @Override 77 | public void run() { 78 | iv_preview.setImageBitmap(bitmap); 79 | } 80 | }); 81 | } 82 | }); 83 | 84 | } 85 | 86 | @Override 87 | protected void onResume() { 88 | super.onResume(); 89 | bz_camera2_view.onResume(); 90 | } 91 | 92 | @Override 93 | protected void onPause() { 94 | super.onPause(); 95 | bz_camera2_view.onPause(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/com/luoye/bzyuvlib/ZoomYUVActivity.java: -------------------------------------------------------------------------------- 1 | package com.luoye.bzyuvlib; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.ImageFormat; 5 | import android.hardware.Camera; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.widget.ImageView; 9 | 10 | import androidx.appcompat.app.AppCompatActivity; 11 | 12 | import com.luoye.bzcamera.BZCameraView; 13 | import com.luoye.bzcamera.listener.OnCameraStateListener; 14 | 15 | import java.nio.ByteBuffer; 16 | 17 | public class ZoomYUVActivity extends AppCompatActivity { 18 | private static final String TAG = "bz_ZoomYUVActivity"; 19 | 20 | private BZCameraView bz_camera_view; 21 | private ImageView bz_image_view; 22 | private byte[] argbByteBuffer = null; 23 | private int index = 0; 24 | private Bitmap bitmap = null; 25 | private long totalTime = 0; 26 | private byte[] yuvBuffer = null; 27 | private byte[] zoomYuvBuffer = null; 28 | private int zoomWidth = 240; 29 | private int zoomHeight = 320; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_zoom_yuv); 35 | bz_camera_view = findViewById(R.id.bz_camera_view); 36 | bz_camera_view.setPreviewTargetSize(480, 640); 37 | bz_image_view = findViewById(R.id.bz_image_view); 38 | 39 | 40 | bz_camera_view.setPreviewFormat(ImageFormat.NV21); 41 | bz_camera_view.setNeedCallBackData(true); 42 | bz_camera_view.setOnCameraStateListener(new OnCameraStateListener() { 43 | @Override 44 | public void onPreviewSuccess(Camera camera, int width, int height) { 45 | 46 | } 47 | 48 | @Override 49 | public void onPreviewFail(String message) { 50 | 51 | } 52 | 53 | @Override 54 | public void onPreviewDataUpdate(byte[] data, int width, int height, int displayOrientation, int cameraId) { 55 | if (null == yuvBuffer) { 56 | yuvBuffer = new byte[width * height * 3 / 2]; 57 | } 58 | if (null == zoomYuvBuffer) { 59 | zoomYuvBuffer = new byte[zoomWidth * zoomHeight * 3 / 2]; 60 | } 61 | if (null == argbByteBuffer) { 62 | argbByteBuffer = new byte[zoomWidth * zoomHeight * 4]; 63 | } 64 | 65 | index++; 66 | long startTime = System.currentTimeMillis(); 67 | BZYUVUtil.preHandleNV21(data, yuvBuffer, width, height, cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT, displayOrientation); 68 | 69 | int tempWidth = width; 70 | int tempHeight = height; 71 | if (displayOrientation == 270 || displayOrientation == 90) { 72 | tempWidth = height; 73 | tempHeight = width; 74 | } 75 | BZYUVUtil.zoomYUV420(yuvBuffer, zoomYuvBuffer, tempWidth, tempHeight, zoomWidth, zoomHeight); 76 | 77 | 78 | BZYUVUtil.yuv420ToRGBA(zoomYuvBuffer, argbByteBuffer, zoomWidth, zoomHeight, false, 0); 79 | totalTime += (System.currentTimeMillis() - startTime); 80 | Log.d(TAG, "time cost=" + (totalTime / index)); 81 | if (null == bitmap) { 82 | bitmap = Bitmap.createBitmap(zoomWidth, zoomHeight, Bitmap.Config.ARGB_8888); 83 | } 84 | bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(argbByteBuffer)); 85 | bz_image_view.post(new Runnable() { 86 | @Override 87 | public void run() { 88 | bz_image_view.setImageBitmap(bitmap); 89 | } 90 | }); 91 | } 92 | 93 | @Override 94 | public void onCameraClose() { 95 | 96 | } 97 | }); 98 | } 99 | 100 | @Override 101 | protected void onResume() { 102 | super.onResume(); 103 | bz_camera_view.onResume(); 104 | } 105 | 106 | @Override 107 | protected void onPause() { 108 | super.onPause(); 109 | bz_camera_view.onPause(); 110 | } 111 | 112 | @Override 113 | protected void onDestroy() { 114 | super.onDestroy(); 115 | Log.d("onDestroy", "yuvFileOutputStream.close"); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/timg.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bookzhan/bzyuvlib/e208742089ffd942a215ddae227408a5b3e8be69/app/src/main/res/drawable/timg.jpeg -------------------------------------------------------------------------------- /app/src/main/res/drawable/timg_2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bookzhan/bzyuvlib/e208742089ffd942a215ddae227408a5b3e8be69/app/src/main/res/drawable/timg_2.jpeg -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_bitmap2_y_u_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 20 | 21 | 26 | 27 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_camera.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 19 | 20 | 25 | 26 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_camera1_y_u_v_crop.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 19 | 20 | 25 | 26 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_camera2.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 17 | 18 | 23 | 24 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_camera2_y_u_v_crop.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 17 | 18 | 23 | 24 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_grey_image_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 |