2 * Copyright (C) 2013 Arne Morten Kvarving
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 * See LICENSES/README.md for more information.
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
;
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}}};
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
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
)
43 CImageDecoder::~CImageDecoder()
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
)
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
)
66 KODI_ADDON_IMAGEDECODER_INFO_TAG ifcTag
= {};
67 bool ret
= m_ifc
.imagedecoder
->toAddon
->read_tag(m_ifc
.hdl
, fileName
.c_str(), &ifcTag
);
71 * List of values currently not used on addon interface.
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;
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
);
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
);
162 tag
->m_iptcInfo
.Author
= 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
);
180 bool CImageDecoder::LoadImageFromMemory(unsigned char* buffer
,
181 unsigned int bufSize
,
185 if (!m_created
|| !m_ifc
.imagedecoder
->toAddon
->load_image_from_memory
)
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
,
200 if (!m_created
|| !m_ifc
.imagedecoder
->toAddon
->decode
)
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())
208 const ADDON_IMG_FMT addonFmt
= std::get
<1>(*it
);
209 const size_t size
= width
* height
* std::get
<2>(*it
);
211 m_ifc
.imagedecoder
->toAddon
->decode(m_ifc
.hdl
, pixels
, size
, width
, height
, pitch
, addonFmt
);