0

I'm writing my own ID3v2 tag reader, but I seem to be having an issue with the APIC tag. Whenever it reads it, it'll say it's 2,038,335 bytes big when it's really 511,281 bytes big. I have no idea as to why and I have a feeling it's something to do with this line:

int size = ( data[ i ] << 24 ) | ( data[ ++i ] << 16 ) | ( data[ ++i ] << 8 ) | ( data[ ++i ] << 0 ) - 1;

But this line works for every other tag I've tested against. It could also be that I'm missing something in the ID3v2 tag standard or something entirely else. Here is the piece of code that is meant to store the image for later:

List<byte> temp = new List<byte>();

            for( int i = 1; i < frame.Length; i++ ) {
                if(frame[i] == 0x00 ) {
                    break;
                } else {
                    temp.Add( frame[ i ] );
                }
            }

            string strVer = Encoding.Default.GetString( temp.ToArray() );

            if ( strVer.StartsWith( "image/" ) ) {
                List<byte> image = new List<byte>();

                for(int i = temp.Count + 1 + frame[ temp.Count + 2 ]; i < frame.Length; i++ ) {
                    image.Add( frame[ i ] );
                }

                tagInfo[ tag ] = image.ToArray();
            }

            tagInfo[ tag ] = frame;

The file I'm using for testing is "Resistence by Aero Chord" with a 2000x2000 pixel image.

Here's a script that produces the same size:

using System;
using System.IO;
using System.Text;
using System.Threading;

class Program {
    static void Main( string[] args ) {
        int tagSize = 0;

        byte[] fileData = byte[] fileData = { 0x41, 0x50, 0x49, 0x43, 0x00, 0x1f, 0x1a, 0x3f };

        for ( int i = 0; i < fileData.Length - 3; i++ ) {
            string tag = Encoding.Default.GetString( new byte[] { fileData[ i ], fileData[ i + 1 ], fileData[ i + 2 ], fileData[ i + 3 ] } );

            if ( tag.Equals( "APIC" ) ) {
                i += 4;

                tagSize = ( fileData[ i ] << 24 ) | ( fileData[ ++i ] << 16 ) | ( fileData[ ++i ] << 8 ) | ( fileData[ ++i ] << 0 ) - 1;
                break;
            }
        }

        Console.Write( $"Tag stated size: {tagSize} bytes." );

        Thread.Sleep( 60000 );
    }
}

Expected: 511,281 bytes

Result: 2,038,334 bytes

Uses the image that was embedded into the file and the APIC tag from the file.

Kyu Vulpes
  • 79
  • 11
  • Welcome to Stack Overflow. Please read the [tour] and [ask]; your question should contain all code and input necessary to reproduce your problem, i.e. a [mcve]. – CodeCaster Dec 19 '17 at 08:37
  • @CodeCaster Is my edit better? I'm new to asking on this site and I'm not that good with human interaction. – Kyu Vulpes Dec 19 '17 at 08:48
  • Yeah that's better, but if you believe the problem to be in that line, then please show a [mcve] (start a new project in Visual Studio or on ideoneor dotnetfiddle) that reproduces the issue, including input, expected output and actual output. – CodeCaster Dec 19 '17 at 08:50
  • @CodeCaster I've added the Minimal, Complete, and Verifiable to the best of what I understand. Is this helpful? – Kyu Vulpes Dec 19 '17 at 09:17
  • Almost there. If you believe the APIC tag to be the problem, then save the relevant byte values of `fileData` and construct an array in memory, so we don't have to download any files. – CodeCaster Dec 19 '17 at 09:19
  • @CodeCaster I've made that section built right into the script and removed the image file. I'm guessing it's completed for the MCV now? – Kyu Vulpes Dec 19 '17 at 09:25

1 Answers1

0

From the standard:

The ID3 tag size is encoded with four bytes where the first bit (bit 7) is set to zero in every byte, making a total of 28 bits. The zeroed bits are ignored, so a 257 bytes long tag is represented as $00 00 02 01

Your byte values are eight bits in size, but you need the seven last bits, dropping the first bit which'll always have a zero value.

So:

tagSize = (tagSize[i] << 21) | (tagSize[++i] << 14) | (tagSize[++i] << 7) | (tagSize[++i] << 0);

This will yield a size of 511295 for an input of 0x00, 0x1f, 0x1a, 0x3f.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • Wow, thanks, where ever you found that seems to explain it better than this site: http://id3.org/id3v2.4.0-structure – Kyu Vulpes Dec 19 '17 at 09:46
  • Yeah I found that site as well, but their headline _"The Audience is informed"_ isn't really made true by that document. – CodeCaster Dec 19 '17 at 09:47
  • It doesn't seem to like my main dll, however, I did put in a little hack in order for it to work properly. All I did was check to see if the tag was the APIC tag if so subtract 11, otherwise subtract 1. – Kyu Vulpes Dec 19 '17 at 10:28