1 #define WIN32_LEAN_AND_MEAN
2 #define NOWINRES
3 #define NOSERVICE
4 #define NOMCX
5 #define NOIME
6 #include "windows.h"
7
8 #include <stdio.h>
9 #include <malloc.h>
10
11 #define TAG_SIZE(a) (((a)[0]&0x7F)*0x200000 + ((a)[1]&0x7F)*0x4000 + ((a)[2]&0x7F)*0x80 + ((a)[3]&0x7F))
12 #define FME_SIZE(a) ((a)[0]*0x1000000 + (a)[1]*0x10000 + (a)[2]*0x100 + (a)[3])
13
14 #pragma pack(1)
15
16 struct ID3V2Header
17 {
18 BYTE Header[3];
19 BYTE Version;
20 BYTE reVersion;
21 BYTE Flag;
22 BYTE Size[4];
23 };
24
25 struct ID3V2Frame
26 {
27 BYTE FrameID[4];
28 BYTE Size[4];
29 BYTE Flag[2];
30 };
31
32 #pragma pack()
33
34 BOOL WINAPI ExtractAlbum(const char *inputFile, const char *outputFile)
35 {
36 FILE *f = fopen(inputFile, "rb");
37
38 if (!f)
39 return FALSE;
40
41 BOOL success = FALSE;
42
43 ID3V2Header hdr;
44
45 if (fread(&hdr, sizeof(hdr), 1, f) != 1)
46 goto err;
47
48 if (memcmp(hdr.Header, "ID3", 3))
49 goto err;
50
51 while (!feof(f))
52 {
53 if (ftell(f) - sizeof(hdr) >= TAG_SIZE(hdr.Size))
54 break;
55
56 ID3V2Frame frame;
57
58 if (fread(&frame, sizeof(frame), 1, f) != 1)
59 break;
60
61 if (!memcmp(frame.FrameID, "APIC", 4))
62 {
63 size_t pos = ftell(f);
64
65 int ofs = fgetc(f) ? 7 : 2;
66
67 while (fgetc(f)) {}
68
69 fseek(f, ofs, SEEK_CUR);
70
71 size_t len = (pos + FME_SIZE(frame.Size)) - ftell(f);
72
73 void *buf = malloc(len);
74
75 if (fread(buf, len, 1, f) == 1)
76 {
77 FILE *fpic = fopen(outputFile, "wb");
78
79 if (fpic)
80 {
81 fwrite(buf, len, 1, fpic);
82 fclose(fpic);
83
84 success = TRUE;
85 }
86 }
87
88 free(buf);
89
90 continue;
91 }
92
93 fseek(f, FME_SIZE(frame.Size), SEEK_CUR);
94 }
95
96 err:
97 fclose(f);
98
99 return success;
100 }