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