美文网首页
Android 保存yuyv数据y(灰度值)为bitmap原始图

Android 保存yuyv数据y(灰度值)为bitmap原始图

作者: 怪咖小青年_56e8 | 来源:发表于2023-04-18 16:35 被阅读0次
  public void saveImage(byte[] yuv, int[] rgb , int width, int height) {
 int y = 0;

        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int dex = (i * width + j)*2;
                y = 0xff & yuv[dex];
                rgb[i*width + j] = 0xff000000| y << 16 | y << 8 | y;
                yuv_y[i*width + j] = yuv[dex];//一帧原始数据的y(灰度值)提取
            }
        }

   File appDir = new File(Environment.getExternalStorageDirectory(), "wy/"+getDate()+"/"+tv_scene.getText());
        if (!appDir.exists()) {
            appDir.mkdirs();
        }
 if (!TextUtils.isEmpty(text1)&&!TextUtils.isEmpty(text2)&&!TextUtils.isEmpty(text3)&&!TextUtils.isEmpty(text4)&&!TextUtils.isEmpty(text5)&&!TextUtils.isEmpty(text6)&&!TextUtils.isEmpty(text7)) {
            fileName = System.currentTimeMillis()+"_"+ tv_scene.getText()+"_"+textLh(text1)+"_"+textLh(text2)+"_"+textLh(text3)+"_"+textLh(text4)+"_"+textLh(text5)+"_"+textLh(text6)+"_"+text7+ ".bmp";

        }else {
            fileName = str = System.currentTimeMillis() +"_"+tv_scene.getText()+"_"+"7005"+"_"+"0301"+"_"+"0420"+"_"+"7005"+"_"+"0301"+"_"+"0420"+"_"+"00"+ ".bmp";

        }
        int len = yuv_y.length;
        int offset = 0;
        //原始数据 bitmap图片存储格式是从左下写到右上 ,此循环将数据颠倒存储,正好为bitmap需要的数据
        for (int i = len - 1; i >= (width - 1); i -= width) {
            // 对于bmp图,DIB文件格式最后一行为第一行,每行按从左到右顺序
            int end = i, start = i - width + 1;
            for (int j = start; j <= end; j++) {
                yuv_b[offset] = yuv_y[j];
                offset ++;
            }
        }
        //将一张640*960的图片分成 两张 640*480 的图片
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int dex = (i * width + j);
                if (i*width + j < width*height/2){
                    yuv_l[i*width + j] = yuv_b[dex];
                }else {
                    yuv_r[(i*width + j)-(width*height/2)] = yuv_b[dex];
                }


            }
        }
        //640*480的图片数据 顺时针旋转90度 为 480*640的图片
        int y_90 = 0;
        for (int j = 640-1; j >= 0; j--) {
            for (int i = 0; i < 480; i++) {

                int index = (i * 640 + j );
                int dex = (y_90 * 480 + i);

                    yuv_l_90[y_90] = yuv_l[index];

                    yuv_r_90[(y_90)] = yuv_r[index];

                y_90 ++ ;
            }

        }
        //旋转之后的两张480*640 数据拼起来 为960*640的图片数据
        for (int i = 0; i < 640; i++) {
            System.arraycopy(yuv_l_90,i*480, yuv_y, i*960, 480);
            System.arraycopy(yuv_r_90,i*480, yuv_y, i*960+480, 480);
        }


        try {
            AndroidBmpUtil bmpUtil = new AndroidBmpUtil();
//            bmpUtil.save(this,yuv_y,Cmd.width,Cmd.height, fileName,appDir);
//            bmpUtil.save(this,yuv_l_90,480,640, "_l"+fileName,appDir);
//            bmpUtil.save(this,yuv_r_90,480,640, "_r"+fileName,appDir);
//            System.arraycopy(yuv_l_90,0, yuv_y, 0, yuv_l_90.length);
//            System.arraycopy(yuv_r_90,0, yuv_y, yuv_l_90.length-1, yuv_r_90.length);

            bmpUtil.save(this,yuv_y,960,640, fileName,appDir);
            showShortMsg(fileName+"");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

这个工具类是直接保存bitmap 原始图片,占内存比较大

这个是24位bitmap图片工具类
package com.example.wyhfviewer.utils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.widget.Toast;

/**
 * Android Bitmap Object to .bmp image (Windows BMP v3 24bit) file util class
 *
 * ref : http://en.wikipedia.org/wiki/BMP_file_format
 *
 * @author ultrakain ( ultrasonic@gmail.com )
 * @since 2012-09-27
 *
 */
public class AndroidBmpUtil {

    private static final int BMP_WIDTH_OF_TIMES = 4;
    private static final int BYTE_PER_PIXEL = 3;

    /**
     * Android Bitmap Object to Window's v3 24bit Bmp Format File
     * @param orgBitmap
     * @param filePath
     * @return file saved result
     */
    public static boolean save(Bitmap orgBitmap, String filePath, File appDir) throws Exception {
        long start = System.currentTimeMillis();
        if(orgBitmap == null){
            return false;
        }

        if(filePath == null){
            return false;
        }

        boolean isSaveSuccess = true;

        //image size
        int width = orgBitmap.getWidth();
        int height = orgBitmap.getHeight();

        //image dummy data size
        //reason : the amount of bytes per image row must be a multiple of 4 (requirements of bmp format)
        byte[] dummyBytesPerRow = null;
        boolean hasDummy = false;
        int rowWidthInBytes = BYTE_PER_PIXEL * width; //source image width * number of bytes to encode one pixel.
        if(rowWidthInBytes%BMP_WIDTH_OF_TIMES>0){
            hasDummy=true;
            //the number of dummy bytes we need to add on each row
            dummyBytesPerRow = new byte[(BMP_WIDTH_OF_TIMES-(rowWidthInBytes%BMP_WIDTH_OF_TIMES))];


            //just fill an array with the dummy bytes we need to append at the end of each row


            for(int i = 0; i < dummyBytesPerRow.length; i++){
                dummyBytesPerRow[i] = (byte)0xFF;
            }
        }

        //an array to receive the pixels from the source image
        int[] pixels = new int[width * height];

        //the number of bytes used in the file to store raw image data (excluding file headers)
        int imageSize = (rowWidthInBytes+(hasDummy?dummyBytesPerRow.length:0)) * height;
        //file headers size
        int imageDataOffset = 0x36;

        //final size of the file
        int fileSize = imageSize + imageDataOffset;

        //Android Bitmap Image Data
        orgBitmap.getPixels(pixels, 0, width, 0, 0, width, height);

        //ByteArrayOutputStream baos = new ByteArrayOutputStream(fileSize);
        ByteBuffer buffer = ByteBuffer.allocate(fileSize);

        /**
         * BITMAP FILE HEADER Write Start
         **/
        buffer.put((byte)0x42);
        buffer.put((byte)0x4D);

        //size
        buffer.put(writeInt(fileSize));

        //reserved
        buffer.put(writeShort((short)0));
        buffer.put(writeShort((short)0));

        //image data start offset
        buffer.put(writeInt(imageDataOffset));

        /** BITMAP FILE HEADER Write End */

        //*******************************************

        /** BITMAP INFO HEADER Write Start */
        //size
        buffer.put(writeInt(0x28));

        //width, height
        //if we add 3 dummy bytes per row : it means we add a pixel (and the image width is modified.
        buffer.put(writeInt(width+(hasDummy?(dummyBytesPerRow.length==3?1:0):0)));
        buffer.put(writeInt(height));

        //planes
        buffer.put(writeShort((short)1));

        //bit count
        buffer.put(writeShort((short)24));

        //bit compression
        buffer.put(writeInt(0));

        //image data size
        buffer.put(writeInt(imageSize));

        //horizontal resolution in pixels per meter
        buffer.put(writeInt(0));

        //vertical resolution in pixels per meter (unreliable)
        buffer.put(writeInt(0));

        buffer.put(writeInt(0));

        buffer.put(writeInt(0));

        /** BITMAP INFO HEADER Write End */

        int row = height;
        int col = width;
        int startPosition = (row - 1) * col;
        int endPosition = row * col;
        while( row > 0 ){
            for(int i = startPosition; i < endPosition; i++ ){
                buffer.put((byte)(pixels[i] & 0x000000FF));


                buffer.put((byte)((pixels[i] & 0x0000FF00) >> 8));
                buffer.put((byte)((pixels[i] & 0x00FF0000) >> 16));
            }
            if(hasDummy){
                buffer.put(dummyBytesPerRow);
            }
            row--;
            endPosition = startPosition;
            startPosition = startPosition - col;
        }
        File file = new File(appDir, filePath);
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(buffer.array());
        fos.close();
        Log.v("AndroidBmpUtil" ,System.currentTimeMillis()-start+" ms");

        return isSaveSuccess;
    }

    /**
     * Write integer to little-endian
     * @param value
     * @return
     * @throws IOException
     */
    private static byte[] writeInt(int value) throws IOException {
        byte[] b = new byte[4];

        b[0] = (byte)(value & 0x000000FF);
        b[1] = (byte)((value & 0x0000FF00) >> 8);
        b[2] = (byte)((value & 0x00FF0000) >> 16);
        b[3] = (byte)((value & 0xFF000000) >> 24);

        return b;
    }

    /**
     * Write short to little-endian byte array
     * @param value
     * @return
     * @throws IOException
     */
    private static byte[] writeShort(short value) throws IOException {
        byte[] b = new byte[2];

        b[0] = (byte)(value & 0x00FF);
        b[1] = (byte)((value & 0xFF00) >> 8);

        return b;
    }
}

使用工具类

AndroidBmpUtil bmpUtil = new AndroidBmpUtil();
 boolean isSaveResult = bmpUtil.save(bmp, fileName,appDir);
public void saveImage(Bitmap bmp) {

        File appDir = new File(Environment.getExternalStorageDirectory(), "wy");
        if (!appDir.exists()) {
            appDir.mkdir();
        }
        if (!TextUtils.isEmpty(text1)&&!TextUtils.isEmpty(text2)&&!TextUtils.isEmpty(text3)&&!TextUtils.isEmpty(text4)&&!TextUtils.isEmpty(text5)&&!TextUtils.isEmpty(text6)&&!TextUtils.isEmpty(text7)) {
            fileName = tv_scene.getText()+"_"+textLh(text1)+"_"+textLh(text2)+"_"+textLh(text3)+"_"+textLh(text4)+"_"+textLh(text5)+"_"+textLh(text6)+"_"+text7+"_"+System.currentTimeMillis() + ".bmp";

        }else {
            fileName = str = tv_scene.getText()+"_"+"7005"+"_"+"0301"+"_"+"0420"+"_"+"7005"+"_"+"0301"+"_"+"0420"+"_"+"00"+"_"+System.currentTimeMillis() + ".bmp";

        }



        try {
//使用工具类,保存原始bitmap
            AndroidBmpUtil bmpUtil = new AndroidBmpUtil();
            boolean isSaveResult = bmpUtil.save(bmp, fileName,appDir);
            showShortMsg(fileName+"");

//使用Android 原生保存,有压缩
//            FileOutputStream fos = new FileOutputStream(file);
//            bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
////            fos.flush();
////            fos.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
//        return file.getAbsolutePath();
    }

下面是8位

public class AndroidBmpUtil {

    private static final int BMP_WIDTH_OF_TIMES = 4;
    private static final int BYTE_PER_PIXEL = 1;

    /**
     * Android Bitmap Object to Window's v3 8bit Bmp Format File
     * @param
     * @param filePath
     * @return file saved result
     */
    public boolean save(Context context, byte[] yuv_y, int width, int height, String filePath, File appDir) throws Exception {
        long start = System.currentTimeMillis();
        if(yuv_y == null){
            return false;
        }

        if(filePath == null){
            return false;
        }

        boolean isSaveSuccess = true;


        //image dummy data size
        //reason : the amount of bytes per image row must be a multiple of 4 (requirements of bmp format)
        byte[] dummyBytesPerRow = null;
        boolean hasDummy = false;
        int rowWidthInBytes = BYTE_PER_PIXEL * width; //source image width * number of bytes to encode one pixel.
        if(rowWidthInBytes%BMP_WIDTH_OF_TIMES>0){
            hasDummy=true;
            //the number of dummy bytes we need to add on each row
            dummyBytesPerRow = new byte[(BMP_WIDTH_OF_TIMES-(rowWidthInBytes%BMP_WIDTH_OF_TIMES))];


            //just fill an array with the dummy bytes we need to append at the end of each row


            for(int i = 0; i < dummyBytesPerRow.length; i++){
                dummyBytesPerRow[i] = (byte)0xFF;
            }
        }

        //an array to receive the pixels from the source image
        int[] pixels = new int[width * height];

        //the number of bytes used in the file to store raw image data (excluding file headers)
        int imageSize = /*(rowWidthInBytes+(hasDummy?dummyBytesPerRow.length:0))*/width * height;
        //file headers size
        int imageDataOffset = 0x36;

        //final size of the file
        int fileSize = imageSize + imageDataOffset + 1024;


        //ByteArrayOutputStream baos = new ByteArrayOutputStream(fileSize);
        ByteBuffer buffer = ByteBuffer.allocate(fileSize);
        byte[] mBMPImageInfo = addBMPImageInfosHeaderTable(width, height);
        /**
         * BITMAP FILE HEADER Write Start
         **/
        buffer.put((byte)0x42);
        buffer.put((byte)0x4D);

        //size
        buffer.put(writeInt(fileSize));

        //reserved
        buffer.put(writeShort((short)0));
        buffer.put(writeShort((short)0));

        //image data start offset
        buffer.put(writeInt(imageDataOffset+1024));

        /** BITMAP FILE HEADER Write End */

        //*******************************************

        /** BITMAP INFO HEADER Write Start */
        //size
        buffer.put(writeInt(0x28));

        //width, height
        //if we add 3 dummy bytes per row : it means we add a pixel (and the image width is modified.
        buffer.put(writeInt(width/*+(hasDummy?(dummyBytesPerRow.length==3?1:0):0)*/));
        buffer.put(writeInt(height));

        //planes
        buffer.put(writeShort((short)1));

        //bit count
        buffer.put(writeShort((short)8));

        //bit compression
        buffer.put(writeInt(0));

        //image data size
        buffer.put(writeInt(imageSize));

        //horizontal resolution in pixels per meter
        buffer.put(writeInt(0));

        //vertical resolution in pixels per meter (unreliable)
        buffer.put(writeInt(0));

        buffer.put(writeInt(0));

        buffer.put(writeInt(0));

        /** BITMAP INFO HEADER Write End */
        for(int i = 0; i < mBMPImageInfo.length; i++ ) {
            buffer.put((byte)(mBMPImageInfo[i] & 0x000000FF));
        }
        int row = height;
        int col = width;
        int startPosition = (row - 1) * col;
        int endPosition = row * col;
          //bmp格式存储从左下往右上写,我这里没有颠倒写入,可自行调试
            for(int i = 0; i < width*height; i++ ){
                buffer.put((byte)(yuv_y[i] & 0x000000FF));
            }
//        }



        Toast.makeText(context,buffer.array().length+"",Toast.LENGTH_SHORT).show();
        File file = new File(appDir, filePath);
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(buffer.array());
        fos.close();
        Log.v("AndroidBmpUtil" ,System.currentTimeMillis()-start+" ms");

        return isSaveSuccess;
    }
    /**
     * 生成颜色表的示例程序(8位灰阶)如下(Java)
颜色表因位数不同而异,24位及以上可以忽略颜色表,8位图的颜色表要包含28 = 256种颜色,每种颜色由BGRA(蓝、绿、红、保留)四个元素组成,即256 * 4 = 1024,需占用1024个字节(byte)。因此,8位图的颜色表有256组颜色,每组颜色格式如下(C/C++):
BYTE rgbBlue;     //该颜色的蓝色分量
BYTE rgbGreen;    //该颜色的绿色分量
BYTE rgbRed;      //该颜色的红色分量
BYTE rgbReserved; //保留值,有人说是透明度,不过没见过bmp图能透明的,未追究
     * */
    private byte[] addBMPImageInfosHeaderTable(int w, int h) {
        byte[] buffer = new byte[256 * 4];

        //生成颜色表
        for (int iiii = 0; iiii < 256; iiii++) {
            buffer[0 + 4 * iiii] = (byte) iiii;   //Blue
            buffer[1 + 4 * iiii] = (byte) iiii;   //Green
            buffer[2 + 4 * iiii] = (byte) iiii;   //Red
            buffer[3 + 4 * iiii] = (byte) 0xFF;   //保留值
        }

        return buffer;
    }
    /**
     * Write integer to little-endian
     * @param value
     * @return
     * @throws IOException
     */
    private static byte[] writeInt(int value) throws IOException {
        byte[] b = new byte[4];

        b[0] = (byte)(value & 0x000000FF);
        b[1] = (byte)((value & 0x0000FF00) >> 8);
        b[2] = (byte)((value & 0x00FF0000) >> 16);
        b[3] = (byte)((value & 0xFF000000) >> 24);

        return b;
    }

    /**
     * Write short to little-endian byte array
     * @param value
     * @return
     * @throws IOException
     */
    private static byte[] writeShort(short value) throws IOException {
        byte[] b = new byte[2];

        b[0] = (byte)(value & 0x00FF);
        b[1] = (byte)((value & 0xFF00) >> 8);

        return b;
    }
}

颜色表 https://blog.csdn.net/ichen86/article/details/50534197
8位bmp (头)54+1024(颜色表)+w*h(长乘宽数据)

相关文章

  • 02总结--011--OpenGL 纹理基础1——像素与纹理

    (一)原始图像数据 位图(bitmap):经常用在饱含灰度或全彩色数据的图像中。 像素图(pixmap):由像素组...

  • 数字图像基础知识整理

    1、单像素操作 s = T(z);z为原始图像灰度值,s为处理后输出灰度值,T为变换函数。 2、领域操作 ,其中(...

  • Android bitmap 保存透明图片背景变黑色

    Android 保存bitmap时,调用mybitmap.compress(Bitmap.CompressForm...

  • matplotlib灰度图可视化处理

    这里我们利用matplotlib可视化一张图片的灰度图。纵横坐标为图片的像素点位置(x, y),此像素点的灰度值z...

  • numpy

    灰度图保存为三通道 数据类型转换问题

  • BitMap

    含义 BitMap是一种二进制位的数据结构,假设BitMap为8位,值为00000000,可以单独设置每一位的值为...

  • 基于Python的条件函数(Con)批量处理

    需求 在输入条件栅格数据值小于0 的原始值将在输出中保存为 0,输出中保留在输入条件栅格数据值大于 0 的原始值。 代码

  • 基础 - 话术

    灰度图灰度图 RGB 三个值相同的图片,灰度的方法有=R、=G、=B、平均、加权平均等。 [灰度化] (https...

  • Opencv之图像二值化

    二值化是图像分割的一种方法。在二值化图象的时候把大于某个临界灰度值的像素灰度设为灰度极大值,把小于这个值的像素灰度...

  • 2018-07-17

    android 关于破损图片判断,处理 判断bitmap是否为null即可 Bitmap bitmap = Bit...

网友评论

      本文标题:Android 保存yuyv数据y(灰度值)为bitmap原始图

      本文链接:https://www.haomeiwen.com/subject/nwahjdtx.html