[Windows] Fix driver version detection of AMD RDNA+ GPU on Windows 10
[xbmc.git] / xbmc / addons / ImageDecoder.cpp
blob48c3042b44ac4242e9a163dc4d5c3cda51a288fd
1 /*
2 * Copyright (C) 2013 Arne Morten Kvarving
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 * See LICENSES/README.md for more information.
6 */
8 #include "ImageDecoder.h"
10 #include "guilib/TextureFormats.h"
11 #include "pictures/PictureInfoTag.h"
12 #include "utils/StringUtils.h"
14 using namespace ADDON;
15 using namespace KODI::ADDONS;
17 namespace
20 constexpr std::array<std::tuple<unsigned int, ADDON_IMG_FMT, size_t>, 4> KodiToAddonFormat = {
21 {{XB_FMT_A8R8G8B8, ADDON_IMG_FMT_A8R8G8B8, sizeof(uint8_t) * 4},
22 {XB_FMT_A8, ADDON_IMG_FMT_A8, sizeof(uint8_t) * 1},
23 {XB_FMT_RGBA8, ADDON_IMG_FMT_RGBA8, sizeof(uint8_t) * 4},
24 {XB_FMT_RGB8, ADDON_IMG_FMT_RGB8, sizeof(uint8_t) * 3}}};
26 } /* namespace */
28 CImageDecoder::CImageDecoder(const AddonInfoPtr& addonInfo, const std::string& mimetype)
29 : IAddonInstanceHandler(ADDON_INSTANCE_IMAGEDECODER, addonInfo), m_mimetype(mimetype)
31 // Create all interface parts independent to make API changes easier if
32 // something is added
33 m_ifc.imagedecoder = new AddonInstance_ImageDecoder;
34 m_ifc.imagedecoder->toAddon = new KodiToAddonFuncTable_ImageDecoder();
35 m_ifc.imagedecoder->toKodi = new AddonToKodiFuncTable_ImageDecoder();
37 if (CreateInstance() != ADDON_STATUS_OK)
38 return;
40 m_created = true;
43 CImageDecoder::~CImageDecoder()
45 DestroyInstance();
47 delete m_ifc.imagedecoder->toKodi;
48 delete m_ifc.imagedecoder->toAddon;
49 delete m_ifc.imagedecoder;
52 bool CImageDecoder::SupportsFile(const std::string& filename)
54 // Create in case not available, possible as this done by IAddonSupportCheck
55 if (!m_created || !m_ifc.imagedecoder->toAddon->supports_file)
56 return false;
58 return m_ifc.imagedecoder->toAddon->supports_file(m_ifc.hdl, filename.c_str());
61 bool CImageDecoder::LoadInfoTag(const std::string& fileName, CPictureInfoTag* tag)
63 if (!m_created || !m_ifc.imagedecoder->toAddon->read_tag || !tag)
64 return false;
66 KODI_ADDON_IMAGEDECODER_INFO_TAG ifcTag = {};
67 bool ret = m_ifc.imagedecoder->toAddon->read_tag(m_ifc.hdl, fileName.c_str(), &ifcTag);
68 if (ret)
70 /*!
71 * List of values currently not used on addon interface.
73 * struct ExifInfo:
74 * - int Process{};
75 * - float CCDWidth{};
76 * - int Whitebalance{};
77 * - int CommentsCharset{};
78 * - int XPCommentsCharset{};
79 * - std::string Comments;
80 * - std::string FileComment;
81 * - std::string XPComment;
82 * - unsigned ThumbnailOffset{};
83 * - unsigned ThumbnailSize{};
84 * - unsigned LargestExifOffset{};
85 * - char ThumbnailAtEnd{};
86 * - int ThumbnailSizeOffset{};
87 * - std::vector<int> DateTimeOffsets;
89 * struct IPTCInfo:
90 * - std::string RecordVersion;
91 * - std::string SupplementalCategories;
92 * - std::string Keywords;
93 * - std::string Caption;
94 * - std::string Headline;
95 * - std::string SpecialInstructions;
96 * - std::string Category;
97 * - std::string Byline;
98 * - std::string BylineTitle;
99 * - std::string Credit;
100 * - std::string Source;
101 * - std::string ObjectName;
102 * - std::string City;
103 * - std::string State;
104 * - std::string Country;
105 * - std::string TransmissionReference;
106 * - std::string Date;
107 * - std::string Urgency;
108 * - std::string ReferenceService;
109 * - std::string CountryCode;
110 * - std::string SubLocation;
111 * - std::string ImageType;
113 * @todo Rework @ref CPictureInfoTag to not limit on fixed structures ExifInfo & IPTCInfo.
116 tag->m_exifInfo.Width = ifcTag.width;
117 tag->m_exifInfo.Height = ifcTag.height;
118 tag->m_exifInfo.Distance = ifcTag.distance;
119 tag->m_exifInfo.Orientation = ifcTag.orientation;
120 tag->m_exifInfo.IsColor = ifcTag.color == ADDON_IMG_COLOR_COLORED ? 1 : 0;
121 tag->m_exifInfo.ApertureFNumber = ifcTag.aperture_f_number;
122 tag->m_exifInfo.FlashUsed = ifcTag.flash_used ? 1 : 0;
123 tag->m_exifInfo.LightSource = ifcTag.light_source;
124 tag->m_exifInfo.FocalLength = ifcTag.focal_length;
125 tag->m_exifInfo.FocalLength35mmEquiv = ifcTag.focal_length_in_35mm_format;
126 tag->m_exifInfo.MeteringMode = ifcTag.metering_mode;
127 tag->m_exifInfo.DigitalZoomRatio = ifcTag.digital_zoom_ratio;
128 tag->m_exifInfo.ExposureTime = ifcTag.exposure_time;
129 tag->m_exifInfo.ExposureBias = ifcTag.exposure_bias;
130 tag->m_exifInfo.ExposureProgram = ifcTag.exposure_program;
131 tag->m_exifInfo.ExposureMode = ifcTag.exposure_mode;
132 tag->m_exifInfo.ISOequivalent = static_cast<int>(ifcTag.iso_speed);
133 CDateTime dt;
134 dt.SetFromUTCDateTime(ifcTag.time_created);
135 tag->m_iptcInfo.TimeCreated = dt.GetAsLocalizedDateTime();
136 tag->m_dateTimeTaken = dt;
137 tag->m_exifInfo.GpsInfoPresent = ifcTag.gps_info_present;
138 if (tag->m_exifInfo.GpsInfoPresent)
140 tag->m_exifInfo.GpsLat =
141 StringUtils::Format("{}{:.0f}°{:.0f}'{:.2f}\"", ifcTag.latitude_ref, ifcTag.latitude[0],
142 ifcTag.latitude[1], ifcTag.latitude[2]);
143 tag->m_exifInfo.GpsLong =
144 StringUtils::Format("{}{:.0f}°{:.0f}'{:.2f}\"", ifcTag.longitude_ref, ifcTag.longitude[0],
145 ifcTag.longitude[1], ifcTag.longitude[2]);
146 tag->m_exifInfo.GpsAlt =
147 StringUtils::Format("{}{:.2f} m", ifcTag.altitude_ref ? '-' : '+', ifcTag.altitude);
150 if (ifcTag.camera_manufacturer)
152 tag->m_exifInfo.CameraMake = ifcTag.camera_manufacturer;
153 free(ifcTag.camera_manufacturer);
155 if (ifcTag.camera_model)
157 tag->m_exifInfo.CameraModel = ifcTag.camera_model;
158 free(ifcTag.camera_model);
160 if (ifcTag.author)
162 tag->m_iptcInfo.Author = ifcTag.author;
163 free(ifcTag.author);
165 if (ifcTag.description)
167 tag->m_exifInfo.Description = ifcTag.description;
168 free(ifcTag.description);
170 if (ifcTag.copyright)
172 tag->m_iptcInfo.CopyrightNotice = ifcTag.copyright;
173 free(ifcTag.copyright);
177 return ret;
180 bool CImageDecoder::LoadImageFromMemory(unsigned char* buffer,
181 unsigned int bufSize,
182 unsigned int width,
183 unsigned int height)
185 if (!m_created || !m_ifc.imagedecoder->toAddon->load_image_from_memory)
186 return false;
188 m_width = width;
189 m_height = height;
190 return m_ifc.imagedecoder->toAddon->load_image_from_memory(m_ifc.hdl, m_mimetype.c_str(), buffer,
191 bufSize, &m_width, &m_height);
194 bool CImageDecoder::Decode(unsigned char* const pixels,
195 unsigned int width,
196 unsigned int height,
197 unsigned int pitch,
198 unsigned int format)
200 if (!m_created || !m_ifc.imagedecoder->toAddon->decode)
201 return false;
203 const auto it = std::find_if(KodiToAddonFormat.begin(), KodiToAddonFormat.end(),
204 [format](auto& p) { return std::get<0>(p) == format; });
205 if (it == KodiToAddonFormat.end())
206 return false;
208 const ADDON_IMG_FMT addonFmt = std::get<1>(*it);
209 const size_t size = width * height * std::get<2>(*it);
210 const bool result =
211 m_ifc.imagedecoder->toAddon->decode(m_ifc.hdl, pixels, size, width, height, pitch, addonFmt);
212 m_width = width;
213 m_height = height;
215 return result;