为什么BitmapFactory.decodeByteArray返回Null?

时间:2015-05-19 09:06:44

标签: android image mp3 bitmapfactory id3

Bitmap.Factory不会将带有p​​ng图像数据的字节数组解码为位图。 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);
    }

我做错了吗?位图工厂始终返回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;
    ////////////////
}   

1 个答案:

答案 0 :(得分:1)

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

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

每个id3帧都有一个10字节的标头。第4至第8字节表示帧中数据的大小(不包括标题的大小)。在我用于测试的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;
                    }
                }
                /////////////////////////////////////////////////////