• MTK Logo 逆向解析之 raw 转 bmp


    相关文章

    MTK Logo 逆向解析之 bin 转 rawx

    MTK Logo 逆向解析之 rawx 全解压

    终于来到最后一步啦,将 raw 转换为原始 bmp 文件,也就是我们在 alps\vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo

    文件夹中对应的原始文件,掌握了这个就可以提取设备中的开机logo文件解析

    话说在最后这个阶段卡了两星期吧,毕竟我的 c++ 很菜,都是边查边粘贴,总是卡在数据旋转那块,

    最终还是通过群友的 AI 大法搞定了,还提供了三种版本的转换方式。话不多说,先来看看源码

    1、分析源码

    源码路径

    vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo\tool\bmp_to_raw_dithering\

    main.cpp 运行入口 仅关注这个

    bmpdecoderhelper.cpp 标准 bmp 解析工具类,安装源码中默认也有

    bmpdecoderhelper.h 头文件

    Dither.c 没用到

    整体代码很简单,就是读取 bmp 文件大小,解析 bmp 数据,按照 ARGB8888 格式存储到 raw 文件中

    反解析只需要将流程逆过来就行

    #include <iostream>
    #include <fstream>
    #include <vector>
    
    #include "bmpdecoderhelper.h"
    
    using namespace std;
    using namespace image_codec;
    
    //g++ -m32  main.cpp bmpdecoderhelper.cpp -o bmp_to_raw
    // -------------------------------------------------------------------------------------
    
    class BmpToLogo : public BmpDecoderCallback
    {
    public:
        BmpToLogo() : BmpDecoderCallback(), m_width(0), m_height(0) {}
    
        bool DoBmpToLogo(const char *bmpFilename, const char *logoFilename, bool append)
        {
            // Open input BMP file
            ifstream bmpFile;
            bmpFile.open(bmpFilename, ios::in | ios::binary);
            if (!bmpFile.is_open()) {
                cout << "open " << bmpFilename << " failed!" << endl;
                return false;
            }
    
            // Open output LOGO file
            ofstream logoFile;
            ios_base::openmode outMode = (ofstream::out | ofstream::binary);
            if (append) outMode |= ofstream::app;
            logoFile.open(logoFilename, outMode);
            if (!logoFile.is_open()) {
                cout << "open " << logoFilename << " failed!" << endl;
                return false;
            }
    
            // Read in BMP file content
            int bmpFileSize = GetFileSize(bmpFile);
            m_bitstream.resize(bmpFileSize);
            bmpFile.read(&m_bitstream[0], m_bitstream.size());
    
            // Decode BMP file to destination buffer
            BmpDecoderHelper bmpDec;
            bmpDec.DecodeImage(&m_bitstream[0], m_bitstream.size(), INT_MAX, this);
    
            // ConvertToRGB565();
            // ConvertToRGB565Dither();
            // Convert RGB888 buffer to RGB565
            ConvertToARGB8888();
    
            // Write to LOGO file
            // logoFile.write(&m_rgb565Buffer[0], m_rgb565Buffer.size());
            logoFile.write(&m_argb8888Buffer[0], m_argb8888Buffer.size());
    
            // Close Files
            bmpFile.close();
            logoFile.close();
    
            return true;
        }
    
        virtual uint8* SetSize(int width, int height)
        {
            m_width  = (uint32)width;
            m_height = (uint32)height;
            m_rgb888Buffer.resize(width * height * 3);
            m_rgb565Buffer.resize(width * height * 2);
            m_argb8888Buffer.resize(width * height * 4);
    
            return (uint8 *) &m_argb8888Buffer[0];
        }
    
    private:
        int GetFileSize(ifstream& file)
        {
            ios::pos_type backup = file.tellg();
            file.seekg(0, std::ios::end);
            ios::pos_type size = file.tellg();
            file.seekg(backup, std::ios::beg);
            return (int)size;
        }
    
        void ConvertToRGB565()
        {
            uint8  *rgb888 = (uint8*)  &m_rgb888Buffer[0];
            uint16 *rgb565 = (uint16*) &m_rgb565Buffer[0];
            uint32 R, G, B;
    
            for(uint32 i = 0; i < m_width * m_height; ++ i) {
                R = rgb888[0]; G = rgb888[1]; B = rgb888[2];
                *rgb565 = ((R & 0xF8) << 8) | ((G & 0xFC) << 3) | ((B & 0xF8) >> 3);
                ++ rgb565;
                rgb888 += 3;
            }
        }
        
        void ConvertToARGB8888()
        {
            uint8  *rgb888   = (uint8*)  &m_rgb888Buffer[0];
            uint32 *argb8888 = (uint32*) &m_argb8888Buffer[0];
            uint32 R, G, B;
    
            for(uint32 i = 0; i < m_width * m_height; ++ i) {
                R = rgb888[0];
                G = rgb888[1]; 
                B = rgb888[2];
                *argb8888 = (0xFF << 24) | (R << 16) | (G << 8) | (B);
                ++argb8888;
                rgb888 += 3;
            }
        }
    
        #define CLIP_255(x) ((x)>255?255:(x))
    
        void ConvertToRGB565Dither(void) 
        {
            unsigned short DitherMatrix_3Bit_16[4] = {0x5140, 0x3726, 0x4051, 0x2637};
            unsigned int count = 0;
            unsigned int sr,sg,sb;
            unsigned int x, y;
            unsigned short dither_scan = 0;
            uint8  *src= (uint8*)  &m_rgb888Buffer[0];
            uint16 *dst= (uint16*) &m_rgb565Buffer[0];
    
            for(count = 0;count < m_width*m_height;count++)	
            {
                x = count % m_width;
                y = count / m_width;
                dither_scan = DitherMatrix_3Bit_16[(y) & 3];
    
                unsigned short dither = ((dither_scan >> (((x) & 3) << 2)) & 0xF);
                sr = ((CLIP_255(((*(src+0) + dither - (*(src+0) >> 5)))) >> (8 - 5)));
                sg = ((CLIP_255(((*(src+1) + (dither >> 1) - (*(src+1) >> 6)))) >> (8 - 6)));
                sb = ((CLIP_255(((*(src+2) + dither - (*(src+2) >> 5)))) >> (8 - 5)));
                printf("%3d,%3d,%3d|%3d,%3d,%3d|%3d,%3d,%3d|%d,%d|%d,%d\n",
                      (sr<<3)-*(src+0), (sg<<2)-*(src+1),(sb<<3)-*(src+2),
                       sr<<3,sg<<2,sb<<3,
                       *(src+0), *(src+1),*(src+2),
                       x,y,
                       dither_scan, dither);
                src += 3;
    
                *dst++ = ((uint16_t)((sr << (5 + 6)) | (sg << (5)) | (sb << 0)));
        	}
        }
    
    
    private:
        vector<char> m_bitstream;
        vector<char> m_rgb888Buffer;
        vector<char> m_argb8888Buffer;
        vector<char> m_rgb565Buffer;
        uint32 m_width, m_height;
    };
    
    // -------------------------------------------------------------------------------------
    
    int main(int argc, const char* argv[])
    {
        if (argc < 3) {
            cout << endl << "[Usage] bmp_to_logo logofile bmpfile1 [bmpfile2] ..." << endl << endl;
            cout << "Example: bmp_to_logo fhd.raw fhd_uboot.bmp fhd_kernel.bmp ..." << endl << endl;
            return -1;
        }
    
        const char *logo_filename = argv[1];
        const char *bmp_filename  = argv[2];
    
        BmpToLogo bmpToLogo;
        if (!bmpToLogo.DoBmpToLogo(bmp_filename, logo_filename, false)) {
            return -2;
        }
    
        for (int i = 3; i < argc; ++ i) {
            bmp_filename = argv[i];
            if (!bmpToLogo.DoBmpToLogo(bmp_filename, logo_filename, true)) {
                return -2;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181

    以下代码中宽、高值都需要替换为你自己的正确值,不然会转换不正常

    2、c++ 版本源码

    rawmain.cpp

    #include <iostream>  
    #include <fstream>  
    #include <vector>  
      
    using namespace std;  
      
    #pragma pack(push, 1)  
      
    typedef struct BITMAPFILEHEADER {  
        unsigned short bfType;  
        unsigned int bfSize;  
        unsigned short bfReserved1;  
        unsigned short bfReserved2;  
        unsigned int bfOffBits;  
    } BITMAPFILEHEADER;  
      
    typedef struct BITMAPINFOHEADER {  
        unsigned int biSize;  
        int biWidth;  
        int biHeight;  
        unsigned short biPlanes;  
        unsigned short biBitCount;  
        unsigned int biCompression;  
        unsigned int biSizeImage;  
        int biXPelsPerMeter;  
        int biYPelsPerMeter;  
        unsigned int biClrUsed;  
        unsigned int biClrImportant;  
    } BITMAPINFOHEADER;  
    
    typedef unsigned char  uint8_t;
    typedef unsigned short uint16_t;
    typedef unsigned int   uint32_t;
    
    typedef uint16_t uint16;
    typedef uint8_t uint8;
    typedef uint32_t uint32;
    
    vector<char> m_bitstream;
    vector<char> m_rgb888Buffer;
    uint32 m_width = 800;
    uint32 m_height = 1280;
    
    #pragma pack(pop)  
    
    int GetFileSize(ifstream& file)
    {
        ios::pos_type backup = file.tellg();
        file.seekg(0, std::ios::end);
        ios::pos_type size = file.tellg();
        file.seekg(backup, std::ios::beg);
        return (int)size;
    }
    
    
    /*void ConvertToARGB8888()
    {
        uint8  *rgb888   = (uint8*)  &m_rgb888Buffer[0];
        uint32 *argb8888 = (uint32*) &m_argb8888Buffer[0];
        uint32 R, G, B;
    
        for(uint32 i = 0; i < m_width * m_height; ++ i) {
            R = rgb888[0];
            G = rgb888[1]; 
            B = rgb888[2];
            *argb8888 = (0xFF << 24) | (R << 16) | (G << 8) | (B);
            ++argb8888;
            rgb888 += 3;
        }
    }*/
    
    void ConvertFromARGB8888() {  
        // uint32 *argb8888 = (uint32*) &m_argb8888Buffer[0];  
        uint32 *argb8888 = (uint32*) &m_bitstream[0];  
        uint8  *rgb888   = (uint8*)  &m_rgb888Buffer[0];  
        uint32 R, G, B, A;  
      
        //数据左右翻转了
        for(uint32 i = m_width * m_height - 1; i > 0; --i) {  
            // A = argb8888[i] >> 24;  
            R = (argb8888[i] >> 16);  
            G = (argb8888[i] >> 8);  
            B = argb8888[i];  
      
            rgb888[0] = B;  
            rgb888[1] = G;  
            rgb888[2] = R;  
            rgb888 += 3;
        }  
    
    }
    
    
    void ConvertFromARGB88882() {
        uint32 *argb8888 = (uint32*) &m_bitstream[0];  
        uint8  *rgb888   = (uint8*)  &m_rgb888Buffer[0];  
        uint32 R, G, B;  
        //bmp格式的位图区存储顺序是从下到上,从左到右
        for(int y = m_height - 1; y >= 0; --y) {  // 从最后一行开始,向上遍历
            for(uint32 x = 0; x < m_width; ++x) {  // 从每行的第一个像素开始,向右遍历
                uint32 i = y * m_width + x;
                R = (argb8888[i] >> 16) & 0xFF;  
                G = (argb8888[i] >> 8) & 0xFF;  
                B = argb8888[i] & 0xFF;  
                rgb888[0] = B;  
                rgb888[1] = G;  
                rgb888[2] = R;  
                rgb888 += 3;
            }
        }
    }
    
    int main(int argc, const char* argv[]) {  
    
        if (argc < 3) {
            cout << endl << "[Usage] raw_to_bmp rawfile bmpfile " << endl << endl;
            cout << "Example: raw_to_bmp logo.raw logo.bmp " << endl << endl;
            return -1;
        }
    
        const char *rawFilename  = argv[1];
        ifstream rawFile;
        rawFile.open(rawFilename, ios::in | ios::binary);
        if (!rawFile.is_open()) {
            cout << "open " << rawFilename << " failed!" << endl;
            return -1;
        }
    
        int rawFileSize = GetFileSize(rawFile);
        m_bitstream.resize(rawFileSize);
        rawFile.read(&m_bitstream[0], m_bitstream.size());
        
        m_rgb888Buffer.resize(m_width * m_height * 3);
        // m_argb8888Buffer.resize(width * height * 4);
    
        ConvertFromARGB88882();
    
        // 创建BMP文件头和信息头  
        BITMAPFILEHEADER fileHeader = {0x4D42, 54 + m_bitstream.size(), 0, 0, 54};  
        BITMAPINFOHEADER infoHeader = {40, m_width, m_height, 1, 24, 0, m_bitstream.size(), 0, 0, 0, 0};  
      
        // 创建BMP文件并写入头和数据  
        const char *bmpFilename  = argv[2];
    
        ofstream outputFile(bmpFilename, ios::binary);  
        if (!outputFile) {  
            cout << "open " << bmpFilename << " failed!" << endl; 
            return -1;  
        }  
        outputFile.write(reinterpret_cast<char*>(&fileHeader), sizeof(fileHeader));  
        outputFile.write(reinterpret_cast<char*>(&infoHeader), sizeof(infoHeader));  
        // outputFile.write(data.data(), data.size());  
        // outputFile.write(&m_bitstream[0], m_bitstream.size());  
        outputFile.write(&m_rgb888Buffer[0], m_rgb888Buffer.size());  
        outputFile.close();  
      
        return 0;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158

    2.1、编译指令

    g++ -m32 rawmain.cpp -o raw_to_bmp

    raw_to_bmp下载

    2.2、回转 bmp 文件

    使用方法

    [Usage] raw_to_bmp rawfile bmpfile

    Example: raw_to_bmp logo.raw logo.bmp

    3、python 版本源码

    raw_to_bmp.py

    # coding=UTF-8
    import struct
    
    #使用方法
    #python raw_to_bmp.py input.raw
    
    # 图像的宽度和高度
    WIDTH = 800
    HEIGHT = 1280
    
    # BMP文件头和信息头的大小
    FILE_HEADER_SIZE = 14
    INFO_HEADER_SIZE = 40
    
    def create_bmp_header(width, height):
        # 计算图像数据大小
        data_size = width * height * 3  # RGB888
    
        # 创建BMP文件头
        file_header = struct.pack('<2sIHHI', b'BM', FILE_HEADER_SIZE + INFO_HEADER_SIZE + data_size, 0, 0, FILE_HEADER_SIZE + INFO_HEADER_SIZE)
    
        # 创建BMP信息头
        info_header = struct.pack('
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    3.1、回转 bmp 文件

    使用方法

    python raw_to_bmp.py input.raw

    4、java 版本源码

    RawToBitMap.java

    /**
     * Created by cczheng on 2023/9/14.
     * 

    * https://www.cnblogs.com/chenrui7/p/4561020.html *

    * https://www.bilibili.com/read/cv15459784/ */ public class RawToBitMap { /** * 从流中读取数组 * * @param stream 输入流 * @return */ public static byte[] readByteArrayFormStream(InputStream stream) { try { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); int len = 0; byte[] tmp = new byte[1024]; while ((len = stream.read(tmp)) != -1) { outStream.write(tmp, 0, len); } byte[] data = outStream.toByteArray(); Log.d("bmp", "data length=" + data.length); return data; } catch (IOException e) { e.printStackTrace(); return new byte[0]; } } /** * 8位灰度转Bitmap *

    * 图像宽度必须能被4整除 * * @param data 裸数据 * @param width 图像宽度 * @param height 图像高度 * @return */ public static Bitmap convert8bit(byte[] data, int width, int height) { byte[] Bits = new byte[data.length * 4]; //RGBA 数组 int i; for (i = 0; i < data.length; i++) { // 原理:4个字节表示一个灰度,则RGB = 灰度值,最后一个Alpha = 0xff; Bits[i * 4] = Bits[i * 4 + 1] = Bits[i * 4 + 2] = data[i]; Bits[i * 4 + 3] = -1; //0xff } // Bitmap.Config.ARGB_8888 表示:图像模式为8位 Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); bmp.copyPixelsFromBuffer(ByteBuffer.wrap(Bits)); return bmp; } /** * 24位灰度转Bitmap *

    * 图像宽度必须能被4整除 * * @param data 裸数据 * @param width 图像宽度 * @param height 图像高度 * @return */ public static Bitmap convert24bit(byte[] data, int width, int height) { int i; /*void ConvertToARGB8888() { uint8 *rgb888 = (uint8*) &m_rgb888Buffer[0]; uint32 *argb8888 = (uint32*) &m_argb8888Buffer[0]; uint32 R, G, B; for(uint32 i = 0; i < m_width * m_height; ++ i) { R = rgb888[0]; G = rgb888[1]; B = rgb888[2]; *argb8888 = (0xFF << 24) | (R << 16) | (G << 8) | (B); ++argb8888; rgb888 += 3; } }*/ /*int[] iData = new int[data.length / 3]; //RGBA 数组// data.length / 3 表示 3位为一组 for (i = 0; i < data.length / 3; i++) {// 原理:24位是有彩色的,所以要复制3位,最后一位Alpha = 0xff; // iData[i] = (((int) data[i * 3]) << 16) + (((int) data[i * 3 + 1]) << 8) + data[i * 3 + 2] + 0xff000000; // iData[i] = (((int) data[i * 3]) >> 16) + (((int) data[i * 3 + 1]) >> 8) + data[i * 3 + 2] + 0xff000000; iData[i] = data[i * 3] | 0xff + (((int) data[i * 3 + 1] | 0xff) >> 8) + (((int) data[i * 3 + 2] | 0xff ) >> 16) +0xff; } Bitmap bmp = Bitmap.createBitmap(iData, width, height, Bitmap.Config.ARGB_8888);*/ byte[] Bits = new byte[data.length * 3]; byte A, R, G, B; for (i = 0; i < data.length / 3; i++) { R = data[i * 3]; G = data[i * 3 + 1]; B = data[i * 3 + 2]; // A = -1; //int color = (A & 0xff) << 24 | (B & 0xff) << 16 | (G & 0xff) << 8 | (R & 0xff); Bits[i * 3] = R; Bits[i * 3 + 1] = G; Bits[i * 3 + 2] = B; // Bits[i * 3 + 3] = A; } Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); bmp.copyPixelsFromBuffer(ByteBuffer.wrap(Bits)); return bmp; } private static byte[] parseRGBByte(byte argb8888) { byte[] rdata = new byte[4]; rdata[0] = (byte) ((argb8888 >> 24) & 0xFF); // 获取A通道的值 rdata[1] = (byte) ((argb8888 >> 16) & 0xFF); // 获取R通道的值 rdata[2] = (byte) ((argb8888 >> 8) & 0xFF); // 获取G通道的值 rdata[3] = (byte) ((argb8888) & 0xFF); // 获取B通道的值 return rdata; } /** * 8位灰度转Bitmap * * @param stream 输入流 * @param width 图像宽度 * @param height 图像高度 * @return */ public static Bitmap convert8bit(InputStream stream, int width, int height) { return convert8bit(readByteArrayFormStream(stream), width, height); } /** * 24位灰度转Bitmap * * @param stream 输入流 * @param width 图像宽度 * @param height 图像高度 * @return */ public static Bitmap convert24bit(InputStream stream, int width, int height) { Bitmap bitmap = convert24bit(readByteArrayFormStream(stream), width, height); saveBmp2Sdcard(bitmap); return bitmap; } private static void saveBmp2Sdcard(Bitmap bitmap) { File mSubFolder = new File( "/sdcard/DCIM/"); if (!mSubFolder.exists()) { mSubFolder.mkdir(); } String s = "test.png"; File f = new File(mSubFolder.getAbsolutePath(), s); FileOutputStream fos = null; try { fos = new FileOutputStream(f); bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); fos.flush(); fos.close(); } catch (Exception e) { e.printStackTrace(); } } }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171

    4.1、回转 bmp 文件

    使用方法

    try {
    Bitmap bitmap = RawToBitMap.convert24bit(getAssets().open(“input.raw”), 800, 1280);
    imageView.setImageBitmap(bitmap);
    } catch (IOException e) {
    e.printStackTrace();
    }

  • 相关阅读:
    web缓存器和CDN
    Chrome 浏览器经常卡死问题解决
    人体神经系统分类图解,人体神经系统分类图片
    MySQL8高级_读写分离和分库分表
    Mac 超好用的工具推荐
    可扩展标记语言-----XML
    ID-Aligner:通过奖励反馈学习提升身份保持文本到图像生成的性能
    17、Spring系列-SpringMVC-请求源码流程
    TCP优化一:TCP 三次握手的优化
    【专栏】核心篇07| Redis “jio”美的集群模式
  • 原文地址:https://blog.csdn.net/u012932409/article/details/133950056