annotate foosdk/sdk/foobar2000/SDK/image.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 "foobar2000-sdk-pch.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2 #include "image.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include "album_art.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 namespace fb2k {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 bool imageSize_t::equals(imageSize_t const & v1, imageSize_t const & v2) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 return v1.width == v2.width && v1.height == v2.height;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 bool imageSize_t::greater(const fb2k::imageSize_t &v1, const fb2k::imageSize_t &v2) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 // v1 > v2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 if (v1.width > v2.width) return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 if (v1.width < v2.width) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 return v1.height > v2.height;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 bool imageSize_t::isValid() const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 return width > 0 && height > 0;
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 imageSize_t imageSize_t::fitIn( double longerEdge ) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 if (!isValid() || longerEdge <= 0) return empty();
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 if (height <= longerEdge && width <= longerEdge) return *this;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 imageSize_t rv = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 if (width > height) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 rv.width = longerEdge;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 rv.height = longerEdge * height / width;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 rv.height = longerEdge;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 rv.width = longerEdge * width / height;
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 return rv;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 imageSize_t imageSize_t::fitIn( imageSize_t size ) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 if (!isValid() || !size.isValid()) return empty();
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 if (width <= size.width && height <= size.height) return *this;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 imageSize_t rv = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 double ratio = size.width / size.height;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 double ourRatio = width / height;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 if (ratio < ourRatio) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 // fit width
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 rv.width = size.width;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 rv.height = height * (size.width / width);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 // fit height
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 rv.height = size.height;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 rv.width = width * (size.height / height);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 return rv;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 void imageSize_t::sanitize() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 if (width < 0) width = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 if (height < 0) height = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 width = pfc::rint32(width);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 height = pfc::rint32(height);
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 image::ptr image::resizeToFit( imageSize_t fitInSize ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 fitInSize.sanitize();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 imageSize_t ourSize = size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 imageSize_t resizeTo = ourSize.fitIn(fitInSize);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 if (resizeTo == ourSize || !resizeTo.isValid()) return this;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 return resize( resizeTo );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67
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 static imageSize_t imageSizeSafe(imageRef img) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 if (img.is_valid()) return img->size();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 else return imageSize_t::empty();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 imageRef imageCreator::loadImageNamed2( const char * imgName, arg_t & arg ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 auto ret = loadImageNamed( imgName, arg.inWantSize );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 arg.outRealSize = imageSizeSafe(ret);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 imageRef imageCreator::loadImageData2( const void * data, size_t size, stringRef sourceURL, arg_t & arg ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 auto ret = loadImageData(data, size, sourceURL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 arg.outRealSize = imageSizeSafe(ret);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 imageRef imageCreator::loadImageData2(memBlockRef block, stringRef sourceURL, arg_t & arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 auto ret = loadImageData(block, sourceURL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 arg.outRealSize = imageSizeSafe(ret);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 return ret;
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 imageRef imageCreator::loadImageFromFile2(const char * filePath, abort_callback & aborter, arg_t & arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 auto ret = loadImageFromFile(filePath, aborter);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 arg.outRealSize = imageSizeSafe(ret);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 imageRef imageCreator::loadImageFromFile3( fsItemFile::ptr fsFile, abort_callback & aborter, arg_t & arg ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 return loadImageFromFile2( fsFile->canonicalPath()->c_str(), aborter, arg);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 }
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 void imageLocation_t::setPath( const char * path_ ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 this->path = makeString(path_);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 void imageLocation_t::setPath(stringRef path_) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 this->path = path_;
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 bool imageLocation_t::setTrack2( trackRef track ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 return setTrack2( track, album_art_ids::cover_front );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 bool imageLocation_t::setTrack2( trackRef track, const GUID & albumArtID ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 if (track.is_empty()) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 setPath( pfc::format("trackimage://", pfc::print_guid(albumArtID), ",", track->get_path()));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 void imageLocation_t::setStock( const char * name ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 setPath( pfc::format( "stockimage://", name ) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 stringRef imageLocation_t::getStock( ) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 if (path.is_valid()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 if (matchProtocol( path->c_str(), "stockimage" ) ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 return makeString( strstr( path->c_str(), "://" ) + 3 );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 return nullptr;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 void imageLocation_t::setEmbedded( const char * path_, const GUID & albumArtID ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 setPath( PFC_string_formatter() << "embedded://" << pfc::print_guid(albumArtID) << "," << path_);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 bool imageLocation_t::equals(const fb2k::imageLocation_t &l1, const fb2k::imageLocation_t &l2) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 if ( l1.path.is_empty() && l2.path.is_empty() ) return true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 if ( l1.path.is_empty() || l2.path.is_empty() ) return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 return l1.path->equals( l2.path );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 bool imageLocation_t::operator==( imageLocation_t const & other) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 return equals(*this, other);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 bool imageLocation_t::operator!=( imageLocation_t const & other) const {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 return !equals(*this, other);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 imageRef imageLoader::loadStock( const char * name, arg_t const & arg, abort_callback & aborter ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 imageLocation_t loc; loc.setStock( name );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 return loadSynchronously(loc, arg, aborter);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 pfc::string_base & operator<<(pfc::string_base & p_fmt,const fb2k::imageSize_t & imgSize) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 auto iw = pfc::rint32(imgSize.width);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 auto ih = pfc::rint32(imgSize.height);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 if (iw == imgSize.width && ih == imgSize.height) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 return p_fmt << "(" << iw << "x" << ih << ")";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 return p_fmt << "(" << imgSize.width << "x" << imgSize.height << ")";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156