为什么 BitmapFactory.decodeByteArray 返回 Null?

Why is BitmapFactory.decodeByteArray returning Null?

Bitmap.Factory 不会将带有 png 图像数据的字节数组解码为位图。 png 数据是从 mp3 的 id3 标签中收集的。

     byte[] imageBytes = getImageFrameData("APIC", imageType, _id3TagByteArray);
    //!convert frame data bytes to image
    if(imageBytes != null) {
        image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
    }

我做错了吗?位图工厂总是 returns null.

getImageFrameData

     private byte[] getImageFrameData(String frameID, byte imageType, byte[] ID3tag){
    /////////////////
     /*
    variable position is initialized to 10 in order to skip ID3 header
    (this must be improved in order to account for potential extended id3 header)
     */
    //!check for extended id3 header (to be implemented)
    final int FRAME_ID_LENGTH = 4;
    final int DATA_LENGTH = 4;
    final int FLAG_LENGTH = 2;
    final int HEADER_LENGTH = FRAME_ID_LENGTH + DATA_LENGTH + FLAG_LENGTH;
    final int TEXT_ENC_LENGTH = 1;
    final int PICT_TYPE_LENGTH = 1;
    List<Byte> fMimeType = new ArrayList<Byte>();


    int position = 10;
    int fInfoPos = position;
    byte[]frame = null;

    while(true){//!loop for seeking frames

        //!Get Frame Id of current frame in loop
        byte[] fID = getBytesInRange(ID3tag, fInfoPos, FRAME_ID_LENGTH);//^search start skips ten bytes

        //!Get Size of Frame Data
        byte[] fSize = getBytesInRange(ID3tag, fInfoPos+=fID.length, DATA_LENGTH);
        int frameDataSize = decodeSynchsafe(fSize);

        //!Get Frame Header Flags (to be implemented)
        byte[] fFlags = getBytesInRange(ID3tag, fInfoPos+=fSize.length, FLAG_LENGTH);

        try {
            if (frameID.equals(new String(fID, "UTF-8"))) {
                //!process image frame
                //!!get additional information data from image frame
                //!!!get text encoding
                byte[] fTextEnc = getBytesInRange(ID3tag, fInfoPos+=fFlags.length, TEXT_ENC_LENGTH);

                //!!!get MIME type
                for(int i = fInfoPos+=fTextEnc.length; i < ID3tag.length - 1; i++){
                    if(ID3tag[i] != 0){
                        fMimeType.add(ID3tag[i]);
                    }else{
                        fInfoPos += fMimeType.size() + 1;
                        break;
                    }
                }
                ////////////////
                byte[]mimeTypeData = new byte[fMimeType.size()];
                for(int i = 0; i < mimeTypeData.length; i++){
                    mimeTypeData[i] = fMimeType.get(i);
                }
                String mime = new String(mimeTypeData);
                ///////////////

                //!!!get image type
                byte[] imgType = getBytesInRange(ID3tag, fInfoPos, PICT_TYPE_LENGTH);

                //!!!get Description
                List<Byte>fDescList = new ArrayList<>();
                for(int i = fInfoPos+=imgType.length; i < ID3tag.length - 1; i++){
                    if(ID3tag[i] != 0){
                        fDescList.add(ID3tag[i]);
                    }else{
                        fInfoPos += fDescList.size() + 1;//+1
                        break;
                    }
                }

                //?if picture type is that of query

                if(imgType[0] == imageType ){
                    //!get image Frame
                    imageFrame = getBytesInRange(ID3tag, position, frameDataSize + 10);
                }

                //!Get Data from Image Frame
                int start = fInfoPos - position;/////////HERE
                //int end = (frameDataSize) - (fInfoPos - position);
                int end = (HEADER_LENGTH + frameDataSize) - start;
                byte[] image = getBytesInRange(imageFrame, start, end);
                String stop = "stop";
                return image;
            }else{
                //!skip to next frame
                position += frameDataSize + HEADER_LENGTH;
                fInfoPos = position;
            }
        }catch(Exception ex){

        }

        /*
        The frame header flags could have important information
         which can determine how the frame is to be processed.
         */
        /////////////////
        //No Frame Exists for the current tag
        // (The id3 tag has been scanned and the tag of query doesn't exist
        //!break
        if(frameDataSize == 0){
            break;
        }
        /////////////////
    }
    return null;
    ////////////////
}   

问题已解决。对于那些可能希望创建一个程序来处理 mp3 id3tag 信息的人来说,解决方案很重要。

问题是 image-data 字节数组中的图像数据不完整。 id3 图像帧中存储的 id3 帧大小数据不正确是原因。

每个 id3 帧都有一个 header 10 字节。第 4-8 个字节表示帧中数据的大小(不包括 header 的大小)。在我用于测试的 mp3 中,图像帧的解码大小很简单。当实际数据大小为 85867 时,它给出的帧数据字节大小为 26350。

通过在 id3tag 字节数组中搜索 PNG 文件结尾标记,问题已解决。从标记开始的 8 个字节是文件的结尾。要获得 png 文件的大小,将在找到文件标记的 png 结尾之前在 id3 字节数组中搜索的字节数减去图像帧数据开始之前的字节数,然后加上 8。 我知道这听起来很复杂,但我认为这可能会对某人有所帮助。 此外,id3 标签可以包含两种图像 mime 类型,PNG 和 JPG。必须修改以前的解决方案以也处理 JPG。

                ///////////// Calculate size of PNG file /////////////
                int[]chunk_id_IEND = {73,69,78,68};
                int pngSize = 0;
                int counter = 0;
                for(int i = 0; i < _id3TagByteArray.length; i++){
                    if(_id3TagByteArray[i] == chunk_id_IEND[0]){
                        for(int j = 0; j < 4; j++ ){
                            if(_id3TagByteArray[i + j] == chunk_id_IEND[j]){
                                ++counter;
                            }else{
                                break;
                            }
                        }
                    }
                    if(counter == 4){
                        pngSize = (i - fInfoPos) + 8;
                        break;
                    }else{
                        counter = 0;
                    }
                }
                /////////////////////////////////////////////////////