annotate foosdk/sdk/foobar2000/helpers/album_art_helpers.cpp @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #include "StdAfx.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2 #include "album_art_helpers.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include <SDK/imageLoaderLite.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 #include <SDK/album_art_helpers.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 #include <libPPUI/gdiplus_helpers.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 using namespace Gdiplus;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 static GdiplusErrorHandler EH;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 static int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 UINT num = 0; // number of image encoders
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 UINT size = 0; // size of the image encoder array in bytes
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 ImageCodecInfo* pImageCodecInfo = NULL;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 GetImageEncodersSize(&num, &size);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 if (size == 0)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 return -1; // Failure
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 if (pImageCodecInfo == NULL)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 return -1; // Failure
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 GetImageEncoders(num, size, pImageCodecInfo);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 for (UINT j = 0; j < num; ++j)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 *pClsid = pImageCodecInfo[j].Clsid;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 free(pImageCodecInfo);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 return j; // Success
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 free(pImageCodecInfo);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 return -1; // Failure
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 static void SaveImage(Gdiplus::Bitmap* image, const TCHAR* out, const TCHAR* format, ULONG quality) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 CLSID encoderClsid;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 EncoderParameters encoderParameters;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 if (GetEncoderClsid(format, &encoderClsid) < 0) throw std::runtime_error("Encoder not found");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 if (_tcscmp(format, _T("image/jpeg")) == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 encoderParameters.Count = 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 encoderParameters.Parameter[0].Guid = EncoderQuality;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 encoderParameters.Parameter[0].NumberOfValues = 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 encoderParameters.Parameter[0].Value = &quality;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 EH << image->Save(out, &encoderClsid, &encoderParameters);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 EH << image->Save(out, &encoderClsid, NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 namespace album_art_helpers {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 bool isJPEG(album_art_data_ptr aa) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 if (aa->size() < 2) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 const uint8_t* p = (const uint8_t*)aa->data();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 return p[0] == 0xFF && p[1] == 0xD8;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 bool isPNG(album_art_data_ptr aa) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 if (aa->size() < 2) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 const uint8_t* p = (const uint8_t*)aa->data();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 return p[0] == 0x89 && p[1] == 0x50;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 bool isWebP(album_art_data_ptr aa) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 if (aa->size() < 12) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 const uint8_t* p = (const uint8_t*)aa->data();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 return memcmp(p, "RIFF", 4) == 0 && memcmp(p + 8, "WEBP", 4) == 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 album_art_data_ptr encodeJPEG(album_art_data_ptr aa, int quality1to100) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 GdiplusScope::Once();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 auto api = fb2k::imageLoaderLite::get();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 std::unique_ptr< Gdiplus::Image > img(api->load(aa));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 if (img->GetType() != Gdiplus::ImageTypeBitmap) throw std::runtime_error("Excepted a bitmap");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 pfc::string8 temp_path, temp_file;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 uGetTempPath(temp_path);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 uGetTempFileName(temp_path, "img", 0, temp_file);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 pfc::onLeaving scope([&] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 uDeleteFile(temp_file);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 });
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 SaveImage(static_cast<Gdiplus::Bitmap*>(img.get()), pfc::stringcvt::string_os_from_utf8(temp_file), L"image/jpeg", quality1to100);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 file::ptr f = fileOpenReadExisting(temp_file, fb2k::noAbort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 uint64_t s = f->get_size_ex(fb2k::noAbort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 if (s > 1024 * 1024 * 64) throw exception_io_data();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 auto obj = fb2k::service_new<album_art_data_impl>();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 obj->from_stream(f.get_ptr(), (size_t)s, fb2k::noAbort);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 return obj;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 }