为什么 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;
}
}
/////////////////////////////////////////////////////
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;
}
}
/////////////////////////////////////////////////////