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