日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

html中获取modelandview中的json数据_从Bitmap中获取YUV数据的两种方式

發布時間:2025/3/12 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 html中获取modelandview中的json数据_从Bitmap中获取YUV数据的两种方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

從Bitmap中我們能獲取到的是RGB顏色分量,當需要獲取YUV數據的時候,則需要先提取R,G,B分量的值,然后將RGB轉化為YUV(根據具體的YUV的排列格式做相應的Y,U,V分量的排列)

所以這篇文章的真正題目叫“從Bitmap中獲取RGB數據的兩種方式”,下面我們以從Bitmap中獲取NV21數據為例進行說明

從Bitmap中獲取RGB數據,Android?SDK提供了兩種方式供我們使用

第一種是getPixels接口:

public void getPixels(@ColorInt int[] pixels, int offset, int stride, int x, int y, int width, int height)

Bitmap中的像素數據將copy到pixels數組中,數組中每一個pixel都是按ARGB四個分量8位排列壓縮而成的一個int值

第二種是copyPixelsToBuffer接口:

public void copyPixelsToBuffer(Buffer dst)

Bitmap中的像素數據將copy到buffer中,buffer中每一個pixel都是按RGBA四個分量的順序進行排列的

兩種接口返回的顏色通道順序不同,在取值的時候需要特別注意

拿到R,G,B分量的值后,就可以轉化為Y,U,V分量了,轉化算法:

y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;v = ((112 * r - 94 * g -18 * b + 128) >> 8) + 128;

使用getPixels接口從Bitmap中獲取NV21數據的完整代碼

public static byte[] fetchNV21(@NonNull Bitmap bitmap) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); int size = w * h; int[] pixels = new int[size]; bitmap.getPixels(pixels, 0, w, 0, 0, w, h);????????byte[]?nv21?=?new?byte[size?*?3?/?2];????????????????// Make w and h are all even.????????w &= ~1; h &= ~1; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) {????????????????int?yIndex?=?i?*?w?+?j;????????????????????????????????int?argb?=?pixels[yIndex];????????????????int?a?=?(argb?>>?24)?&?0xff;? // unused int r = (argb >> 16) & 0xff; int g = (argb >> 8) & 0xff; int b = argb & 0xff; int y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16; y = clamp(y, 16, 255); nv21[yIndex] = (byte)y; if (i % 2 == 0 && j % 2 == 0) { int u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128; int v = ((112 * r - 94 * g -18 * b + 128) >> 8) + 128; u = clamp(u, 0, 255); v = clamp(v, 0, 255); nv21[size + i / 2 * w + j] = (byte) v; nv21[size + i / 2 * w + j + 1] = (byte) u; } } } return nv21; }

拿到nv21數據后,我們怎么驗證數據是正常的呢?

可以通過YuvImage接口轉成jpeg,然后再將jpeg轉化為Bitmap,使用ImageView顯示出來看下是否和原圖一致就可以驗證了

//?create?test?bitmap?and fetch nv21 dataBitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.header);int w = bitmap.getWidth();int?h?=?bitmap.getHeight();byte[] nv21 = Util.fetchNV21(bitmap);bitmap.recycle();// nv21 -> jpeg -> bitmapYuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, w, h, null);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();yuvImage.compressToJpeg(new Rect(0, 0, w, h), 100, outputStream);byte[] array = outputStream.toByteArray();Bitmap tmp = BitmapFactory.decodeByteArray(array, 0, array.length);//?showimageView.setImageBitmap(tmp);

在YuvImage的compressToJpeg接口的源碼中,有個調整壓縮rect的步驟

進入到adjustRectangle方法,可以發現壓縮區域的寬高被調整為偶數了

為什么w,h必須要保證為偶數呢?這個是因為當w,h都不為偶數的時候,在計算到最后的V,U的索引時候算出來會和NV21的數組長度一致,這樣就會導致ArrayIndexOutOfBoundsException了

使用copyPixelsToBuffer接口從Bitmap中獲取NV21數據的完整代碼

public static byte[] fetchNV21(@NonNull Bitmap bitmap) { ByteBuffer byteBuffer = ByteBuffer .allocateDirect(bitmap.getByteCount()) .order(ByteOrder.nativeOrder()); bitmap.copyPixelsToBuffer(byteBuffer); byte[] array = byteBuffer.array(); int w = bitmap.getWidth(); int h = bitmap.getHeight(); int area = w * h; int count = array.length / 4; if (count > area) { count = area; } int nv21Size = area * 3 / 2; byte[] nv21 = new byte[nv21Size]; for (int i = 0; i < count; i++) { int row = i / w; int col = i - col * w; int vIndex = area + (row >> 1) * w + (col & ~1); int uIndex = area + (row >> 1) * w + (col & ~1) + 1; // case: w or h not even if (vIndex >= nv21Size) { break; }????????????// RGBA int r = ((int)array[i * 4]) & 0xff; int g = ((int)array[i * 4 + 1]) & 0xff; int b = ((int)array[i * 4 + 2]) & 0xff; int a = ((int)array[i * 4 + 3]) & 0xff; // unused int y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16; int u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128; int v = ((112 * r - 94 * g -18 * b + 128) >> 8) + 128; y = clamp(y, 16, 255); u = clamp(u, 0, 255); v = clamp(v, 0, 255); nv21[i] = (byte)y; nv21[vIndex] = (byte)v; nv21[uIndex] = (byte)u; } return nv21; }

通過buffer拷貝的數據,有時候是會多那么一兩個pixel。比如我測試的一張圖片,Bitmap寬高為1200,獲取到的byte數組長度為5760007,就多了7個字節,2個像素

fetchBitmapToNv21:?w?=?1200,?h?=?1200,?array.length?=?5760007,?w * h?=?1440000

從Bitmap中拿到RGB數據,再轉化為YUV數據后,根據Y,U,V分量排列的不同可以任意組合為自己所需要的YUV格式~

推薦閱讀:

音視頻面試基礎題

OpenGL 之 GPUImage 源碼分析

OpenGL ES 實現實時音頻的可視化

Shader 優化 | OpenGL 繪制網格效果

覺得不錯,點個在看唄~

總結

以上是生活随笔為你收集整理的html中获取modelandview中的json数据_从Bitmap中获取YUV数据的两种方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。