| File: | dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp |
| Warning: | line 113, column 17 Opened stream never closed. Potential resource leak |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* ============================================================ | |||
| 2 | * | |||
| 3 | * This file is a part of digiKam project | |||
| 4 | * https://www.digikam.org | |||
| 5 | * | |||
| 6 | * Date : 2006-06-14 | |||
| 7 | * Description : A JPEG-2000 IO file for DImg framework- load operations | |||
| 8 | * | |||
| 9 | * SPDX-FileCopyrightText: 2006-2025 by Gilles Caulier <caulier dot gilles at gmail dot com> | |||
| 10 | * | |||
| 11 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
| 12 | * | |||
| 13 | * ============================================================ */ | |||
| 14 | ||||
| 15 | #include "dimgjpeg2000loader_p.h" | |||
| 16 | ||||
| 17 | namespace DigikamJPEG2000DImgPlugin | |||
| 18 | { | |||
| 19 | ||||
| 20 | bool DImgJPEG2000Loader::load(const QString& filePath, DImgLoaderObserver* const observer) | |||
| 21 | { | |||
| 22 | readMetadata(filePath); | |||
| 23 | ||||
| 24 | #ifdef Q_OS_WIN | |||
| 25 | ||||
| 26 | FILE* const file = _wfopen((const wchar_t*)filePath.utf16(), L"rb"); | |||
| 27 | ||||
| 28 | #else | |||
| 29 | ||||
| 30 | FILE* const file = fopen(filePath.toUtf8().constData(), "rb"); | |||
| ||||
| 31 | ||||
| 32 | #endif | |||
| 33 | ||||
| 34 | if (!file
| |||
| 35 | { | |||
| 36 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 36, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category .name()).warning() << "Unable to open JPEG2000 file"; | |||
| 37 | loadingFailed(); | |||
| 38 | ||||
| 39 | return false; | |||
| 40 | } | |||
| 41 | ||||
| 42 | imageSetAttribute(QLatin1String("format"), QLatin1String("JP2")); | |||
| 43 | ||||
| 44 | #if defined JAS_VERSION_MAJOR4 && JAS_VERSION_MAJOR4 >= 3 | |||
| 45 | ||||
| 46 | // NOTE: nothing to do. | |||
| 47 | ||||
| 48 | #else | |||
| 49 | ||||
| 50 | QScopedPointer<DMetadata> metadata(new DMetadata(filePath)); | |||
| 51 | QSize size = metadata->getItemDimensions(); | |||
| 52 | QString decoderOptions = QLatin1String("max_samples=100000000"); | |||
| 53 | ||||
| 54 | if (size.isValid()) | |||
| 55 | { | |||
| 56 | imageWidth() = size.width(); | |||
| 57 | imageHeight() = size.height(); | |||
| 58 | decoderOptions = QString::fromLatin1("max_samples=%1").arg(size.width() * size.height() * 4); | |||
| 59 | qCDebug(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 59, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category .name()).debug() << "JP2 image size:" << size; | |||
| 60 | } | |||
| 61 | ||||
| 62 | if (!(m_loadFlags & LoadImageData) && !(m_loadFlags & LoadICCData)) | |||
| 63 | { | |||
| 64 | // libjasper will load the full image in memory already when calling jas_image_decode. | |||
| 65 | // This is bad when scanning. See bugs 215458 and 195583. | |||
| 66 | // Exiv2 is used to extract this info. | |||
| 67 | ||||
| 68 | fclose(file); | |||
| 69 | ||||
| 70 | return true; | |||
| 71 | } | |||
| 72 | ||||
| 73 | #endif | |||
| 74 | ||||
| 75 | // ------------------------------------------------------------------- | |||
| 76 | // Initialize JPEG 2000 API. | |||
| 77 | ||||
| 78 | long i = 0; | |||
| 79 | long x = 0; | |||
| 80 | long y = 0; | |||
| 81 | int components[4] = { 0 }; | |||
| 82 | unsigned int maximum_component_depth = 0; | |||
| 83 | unsigned int scale[4] = { 0 }; | |||
| 84 | unsigned int x_step[4] = { 0 }; | |||
| 85 | unsigned int y_step[4] = { 0 }; | |||
| 86 | unsigned long number_components = 0; | |||
| 87 | jas_image_t* jp2_image = nullptr; | |||
| 88 | jas_stream_t* jp2_stream = nullptr; | |||
| 89 | jas_matrix_t* pixels[4] = { nullptr }; | |||
| 90 | ||||
| 91 | if (initJasper() != 0) | |||
| 92 | { | |||
| 93 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 93, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category .name()).warning() << "Unable to init JPEG2000 decoder"; | |||
| 94 | loadingFailed(); | |||
| 95 | fclose(file); | |||
| 96 | ||||
| 97 | return false; | |||
| 98 | } | |||
| 99 | ||||
| 100 | jp2_stream = jas_stream_freopen(filePath.toUtf8().constData(), "rb", file); | |||
| 101 | ||||
| 102 | if (jp2_stream == nullptr) | |||
| 103 | { | |||
| 104 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 104, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Unable to open JPEG2000 stream"; | |||
| 105 | fclose(file); | |||
| 106 | ||||
| 107 | cleanupJasper(); | |||
| 108 | loadingFailed(); | |||
| 109 | ||||
| 110 | return false; | |||
| 111 | } | |||
| 112 | ||||
| 113 | int fmt = jas_image_strtofmt(QByteArray("jp2").data()); | |||
| ||||
| 114 | ||||
| 115 | #if defined JAS_VERSION_MAJOR4 && JAS_VERSION_MAJOR4 >= 3 | |||
| 116 | ||||
| 117 | jp2_image = jas_image_decode(jp2_stream, fmt, nullptr); | |||
| 118 | ||||
| 119 | #else | |||
| 120 | ||||
| 121 | // See bug 447240 and UPSTREAM https://github.com/jasper-software/jasper/issues/315#issuecomment-1007872809 | |||
| 122 | ||||
| 123 | qCDebug(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 123, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).debug() << "jas_image_decode decoder options string:" << decoderOptions; | |||
| 124 | ||||
| 125 | jp2_image = jas_image_decode(jp2_stream, fmt, decoderOptions.toLatin1().data()); | |||
| 126 | ||||
| 127 | #endif | |||
| 128 | ||||
| 129 | if (jp2_image == nullptr) | |||
| 130 | { | |||
| 131 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 131, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Unable to decode JPEG2000 image"; | |||
| 132 | jas_stream_close(jp2_stream); | |||
| 133 | ||||
| 134 | cleanupJasper(); | |||
| 135 | loadingFailed(); | |||
| 136 | ||||
| 137 | return false; | |||
| 138 | } | |||
| 139 | ||||
| 140 | jas_stream_close(jp2_stream); | |||
| 141 | ||||
| 142 | // some pseudo-progress | |||
| 143 | ||||
| 144 | if (observer) | |||
| 145 | { | |||
| 146 | observer->progressInfo(0.1F); | |||
| 147 | } | |||
| 148 | ||||
| 149 | // ------------------------------------------------------------------- | |||
| 150 | // Check color space. | |||
| 151 | ||||
| 152 | int colorModel = DImg::COLORMODELUNKNOWN; | |||
| 153 | ||||
| 154 | switch (jas_clrspc_fam(jas_image_clrspc(jp2_image))((((jp2_image)->clrspc_)) >> 8)) | |||
| 155 | { | |||
| 156 | case JAS_CLRSPC_FAM_RGB4: | |||
| 157 | { | |||
| 158 | components[0] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_RGB_R0); | |||
| 159 | components[1] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_RGB_G1); | |||
| 160 | components[2] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_RGB_B2); | |||
| 161 | ||||
| 162 | if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0)) | |||
| 163 | { | |||
| 164 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 164, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Error parsing JPEG2000 image : Missing Image Channel"; | |||
| 165 | jas_image_destroy(jp2_image); | |||
| 166 | ||||
| 167 | cleanupJasper(); | |||
| 168 | loadingFailed(); | |||
| 169 | ||||
| 170 | return false; | |||
| 171 | } | |||
| 172 | ||||
| 173 | number_components = 3; | |||
| 174 | components[3] = jas_image_getcmptbytype(jp2_image, 3); | |||
| 175 | ||||
| 176 | if (components[3] > 0) | |||
| 177 | { | |||
| 178 | m_hasAlpha = true; | |||
| 179 | ++number_components; | |||
| 180 | } | |||
| 181 | ||||
| 182 | colorModel = DImg::RGB; | |||
| 183 | ||||
| 184 | break; | |||
| 185 | } | |||
| 186 | ||||
| 187 | case JAS_CLRSPC_FAM_GRAY3: | |||
| 188 | { | |||
| 189 | components[0] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_GRAY_Y0); | |||
| 190 | ||||
| 191 | // cppcheck-suppress knownConditionTrueFalse | |||
| 192 | if (components[0] < 0) | |||
| 193 | { | |||
| 194 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 194, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Error parsing JP2000 image : Missing Image Channel"; | |||
| 195 | jas_image_destroy(jp2_image); | |||
| 196 | ||||
| 197 | cleanupJasper(); | |||
| 198 | loadingFailed(); | |||
| 199 | ||||
| 200 | return false; | |||
| 201 | } | |||
| 202 | ||||
| 203 | number_components = 1; | |||
| 204 | colorModel = DImg::GRAYSCALE; | |||
| 205 | ||||
| 206 | break; | |||
| 207 | } | |||
| 208 | ||||
| 209 | case JAS_CLRSPC_FAM_YCBCR5: | |||
| 210 | { | |||
| 211 | components[0] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_YCBCR_Y0); | |||
| 212 | components[1] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_YCBCR_CB1); | |||
| 213 | components[2] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_YCBCR_CR2); | |||
| 214 | ||||
| 215 | // cppcheck-suppress knownConditionTrueFalse | |||
| 216 | if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0)) | |||
| 217 | { | |||
| 218 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 218, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Error parsing JP2000 image : Missing Image Channel"; | |||
| 219 | jas_image_destroy(jp2_image); | |||
| 220 | ||||
| 221 | cleanupJasper(); | |||
| 222 | loadingFailed(); | |||
| 223 | ||||
| 224 | return false; | |||
| 225 | } | |||
| 226 | ||||
| 227 | number_components = 3; | |||
| 228 | components[3] = jas_image_getcmptbytype(jp2_image, JAS_IMAGE_CT_UNKNOWN0x10000); | |||
| 229 | ||||
| 230 | if (components[3] > 0) | |||
| 231 | { | |||
| 232 | m_hasAlpha = true; | |||
| 233 | ++number_components; | |||
| 234 | } | |||
| 235 | ||||
| 236 | // FIXME: image->colorspace = YCbCrColorspace; | |||
| 237 | ||||
| 238 | colorModel = DImg::YCBCR; | |||
| 239 | ||||
| 240 | break; | |||
| 241 | } | |||
| 242 | ||||
| 243 | default: | |||
| 244 | { | |||
| 245 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 245, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Error parsing JP2000 image : Colorspace Model Is Not Supported"; | |||
| 246 | jas_image_destroy(jp2_image); | |||
| 247 | ||||
| 248 | cleanupJasper(); | |||
| 249 | loadingFailed(); | |||
| 250 | ||||
| 251 | return false; | |||
| 252 | } | |||
| 253 | } | |||
| 254 | ||||
| 255 | // ------------------------------------------------------------------- | |||
| 256 | // Check image geometry. | |||
| 257 | ||||
| 258 | imageWidth() = jas_image_width(jp2_image)((jp2_image)->brx_ - (jp2_image)->tlx_); | |||
| 259 | imageHeight() = jas_image_height(jp2_image)((jp2_image)->bry_ - (jp2_image)->tly_); | |||
| 260 | ||||
| 261 | for (i = 0 ; i < (long)number_components ; ++i) | |||
| 262 | { | |||
| 263 | if ( | |||
| 264 | ( | |||
| 265 | ((jas_image_cmptwidth(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->width_)* | |||
| 266 | jas_image_cmpthstep(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->hstep_)) != (long)imageWidth()) | |||
| 267 | ) || | |||
| 268 | ( | |||
| 269 | ((jas_image_cmptheight(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->height_)* | |||
| 270 | jas_image_cmptvstep(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->vstep_)) != (long)imageHeight()) | |||
| 271 | ) || | |||
| 272 | (jas_image_cmpttlx(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->tlx_) != 0) || | |||
| 273 | (jas_image_cmpttly(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->tly_) != 0) || | |||
| 274 | (jas_image_cmptsgnd(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->sgnd_) != false) | |||
| 275 | ) | |||
| 276 | { | |||
| 277 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 277, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Error parsing JPEG2000 image : Irregular Channel Geometry Not Supported"; | |||
| 278 | jas_image_destroy(jp2_image); | |||
| 279 | ||||
| 280 | cleanupJasper(); | |||
| 281 | loadingFailed(); | |||
| 282 | ||||
| 283 | return false; | |||
| 284 | } | |||
| 285 | ||||
| 286 | x_step[i] = jas_image_cmpthstep(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->hstep_); | |||
| 287 | y_step[i] = jas_image_cmptvstep(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->vstep_); | |||
| 288 | } | |||
| 289 | ||||
| 290 | // ------------------------------------------------------------------- | |||
| 291 | // Get image format. | |||
| 292 | ||||
| 293 | maximum_component_depth = 0; | |||
| 294 | ||||
| 295 | for (i = 0 ; i < (long)number_components ; ++i) | |||
| 296 | { | |||
| 297 | maximum_component_depth = qMax((long)jas_image_cmptprec(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->prec_), | |||
| 298 | (long)maximum_component_depth); | |||
| 299 | ||||
| 300 | pixels[i] = jas_matrix_create(1, ((unsigned int)imageWidth()) / x_step[i]); | |||
| 301 | ||||
| 302 | if (!pixels[i]) | |||
| 303 | { | |||
| 304 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 304, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Error decoding JPEG2000 image data : Memory Allocation Failed"; | |||
| 305 | jas_image_destroy(jp2_image); | |||
| 306 | ||||
| 307 | cleanupJasper(); | |||
| 308 | loadingFailed(); | |||
| 309 | ||||
| 310 | return false; | |||
| 311 | } | |||
| 312 | } | |||
| 313 | ||||
| 314 | #if defined JAS_VERSION_MAJOR4 && JAS_VERSION_MAJOR4 >= 3 | |||
| 315 | ||||
| 316 | if (!(m_loadFlags & LoadImageData) && !(m_loadFlags & LoadICCData)) | |||
| 317 | { | |||
| 318 | imageSetAttribute(QLatin1String("originalColorModel"), colorModel); | |||
| 319 | imageSetAttribute(QLatin1String("originalBitDepth"), maximum_component_depth); | |||
| 320 | imageSetAttribute(QLatin1String("originalSize"), QSize(imageWidth(), imageHeight())); | |||
| 321 | ||||
| 322 | jas_image_destroy(jp2_image); | |||
| 323 | cleanupJasper(); | |||
| 324 | ||||
| 325 | return true; | |||
| 326 | } | |||
| 327 | ||||
| 328 | #endif | |||
| 329 | ||||
| 330 | if (maximum_component_depth > 8) | |||
| 331 | { | |||
| 332 | m_sixteenBit = true; | |||
| 333 | } | |||
| 334 | ||||
| 335 | for (i = 0 ; i < (long)number_components ; ++i) | |||
| 336 | { | |||
| 337 | scale[i] = 1; | |||
| 338 | int prec = jas_image_cmptprec(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->prec_); | |||
| 339 | ||||
| 340 | if (m_sixteenBit && (prec < 16)) | |||
| 341 | { | |||
| 342 | scale[i] = (1 << (16 - jas_image_cmptprec(jp2_image, components[i])((jp2_image)->cmpts_[components[i]]->prec_))); | |||
| 343 | } | |||
| 344 | } | |||
| 345 | ||||
| 346 | // ------------------------------------------------------------------- | |||
| 347 | // Get image data. | |||
| 348 | ||||
| 349 | QScopedArrayPointer<uchar> data; | |||
| 350 | ||||
| 351 | if (m_loadFlags & LoadImageData) | |||
| 352 | { | |||
| 353 | if (m_sixteenBit) // 16 bits image. | |||
| 354 | { | |||
| 355 | data.reset(new_failureTolerant(imageWidth(), imageHeight(), 8)); | |||
| 356 | } | |||
| 357 | else | |||
| 358 | { | |||
| 359 | data.reset(new_failureTolerant(imageWidth(), imageHeight(), 4)); | |||
| 360 | } | |||
| 361 | ||||
| 362 | if (!data) | |||
| 363 | { | |||
| 364 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 364, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Error decoding JPEG2000 image data : Memory Allocation Failed"; | |||
| 365 | jas_image_destroy(jp2_image); | |||
| 366 | ||||
| 367 | for (i = 0 ; i < (long)number_components ; ++i) | |||
| 368 | { | |||
| 369 | jas_matrix_destroy(pixels[i]); | |||
| 370 | } | |||
| 371 | ||||
| 372 | cleanupJasper(); | |||
| 373 | loadingFailed(); | |||
| 374 | ||||
| 375 | return false; | |||
| 376 | } | |||
| 377 | ||||
| 378 | uint checkPoint = 0; | |||
| 379 | uchar* dst = data.data(); | |||
| 380 | unsigned short* dst16 = reinterpret_cast<unsigned short*>(data.data()); | |||
| 381 | ||||
| 382 | for (y = 0 ; y < (long)imageHeight() ; ++y) | |||
| 383 | { | |||
| 384 | for (i = 0 ; i < (long)number_components ; ++i) | |||
| 385 | { | |||
| 386 | int ret = jas_image_readcmpt(jp2_image, (short)components[i], 0, | |||
| 387 | ((unsigned int) y) / y_step[i], | |||
| 388 | ((unsigned int) imageWidth()) / x_step[i], | |||
| 389 | 1, pixels[i]); | |||
| 390 | ||||
| 391 | if (ret != 0) | |||
| 392 | { | |||
| 393 | qCWarning(DIGIKAM_DIMG_LOG_JP2K)for (QLoggingCategoryMacroHolder<QtWarningMsg> qt_category ((DIGIKAM_DIMG_LOG_JP2K)()); qt_category; qt_category.control = false) QMessageLogger(static_cast<const char *>("/home/gilles/devel/8.x/core/dplugins/dimg/jpeg2000/dimgjpeg2000loader_load.cpp" ), 393, static_cast<const char *>(__PRETTY_FUNCTION__), qt_category.name()).warning() << "Error decoding JPEG2000 image data"; | |||
| 394 | jas_image_destroy(jp2_image); | |||
| 395 | ||||
| 396 | for (i = 0 ; i < (long)number_components ; ++i) | |||
| 397 | { | |||
| 398 | jas_matrix_destroy(pixels[i]); | |||
| 399 | } | |||
| 400 | ||||
| 401 | cleanupJasper(); | |||
| 402 | loadingFailed(); | |||
| 403 | ||||
| 404 | return false; | |||
| 405 | } | |||
| 406 | } | |||
| 407 | ||||
| 408 | switch (number_components) | |||
| 409 | { | |||
| 410 | case 1: // Grayscale. | |||
| 411 | { | |||
| 412 | if (!m_sixteenBit) // 8 bits image. | |||
| 413 | { | |||
| 414 | for (x = 0 ; x < (long)imageWidth() ; ++x) | |||
| 415 | { | |||
| 416 | dst[0] = (uchar)(scale[0] * jas_matrix_getv(pixels[0], x / x_step[0])); | |||
| 417 | dst[1] = dst[0]; | |||
| 418 | dst[2] = dst[0]; | |||
| 419 | dst[3] = 0xFF; | |||
| 420 | ||||
| 421 | dst += 4; | |||
| 422 | } | |||
| 423 | } | |||
| 424 | else // 16 bits image. | |||
| 425 | { | |||
| 426 | for (x = 0 ; x < (long)imageWidth() ; ++x) | |||
| 427 | { | |||
| 428 | dst16[0] = (unsigned short)(scale[0] * jas_matrix_getv(pixels[0], x / x_step[0])); | |||
| 429 | dst16[1] = dst16[0]; | |||
| 430 | dst16[2] = dst16[0]; | |||
| 431 | dst16[3] = 0xFFFF; | |||
| 432 | ||||
| 433 | dst16 += 4; | |||
| 434 | } | |||
| 435 | } | |||
| 436 | ||||
| 437 | break; | |||
| 438 | } | |||
| 439 | ||||
| 440 | case 3: // RGB. | |||
| 441 | { | |||
| 442 | if (!m_sixteenBit) // 8 bits image. | |||
| 443 | { | |||
| 444 | for (x = 0 ; x < (long)imageWidth() ; ++x) | |||
| 445 | { | |||
| 446 | // Blue | |||
| 447 | dst[0] = (uchar)(scale[2] * jas_matrix_getv(pixels[2], x / x_step[2])); | |||
| 448 | // Green | |||
| 449 | dst[1] = (uchar)(scale[1] * jas_matrix_getv(pixels[1], x / x_step[1])); | |||
| 450 | // Red | |||
| 451 | dst[2] = (uchar)(scale[0] * jas_matrix_getv(pixels[0], x / x_step[0])); | |||
| 452 | // Alpha | |||
| 453 | dst[3] = 0xFF; | |||
| 454 | ||||
| 455 | dst += 4; | |||
| 456 | } | |||
| 457 | } | |||
| 458 | else // 16 bits image. | |||
| 459 | { | |||
| 460 | for (x = 0 ; x < (long)imageWidth() ; ++x) | |||
| 461 | { | |||
| 462 | // Blue | |||
| 463 | dst16[0] = (unsigned short)(scale[2] * jas_matrix_getv(pixels[2], x / x_step[2])); | |||
| 464 | // Green | |||
| 465 | dst16[1] = (unsigned short)(scale[1] * jas_matrix_getv(pixels[1], x / x_step[1])); | |||
| 466 | // Red | |||
| 467 | dst16[2] = (unsigned short)(scale[0] * jas_matrix_getv(pixels[0], x / x_step[0])); | |||
| 468 | // Alpha | |||
| 469 | dst16[3] = 0xFFFF; | |||
| 470 | ||||
| 471 | dst16 += 4; | |||
| 472 | } | |||
| 473 | } | |||
| 474 | ||||
| 475 | break; | |||
| 476 | } | |||
| 477 | ||||
| 478 | case 4: // RGBA. | |||
| 479 | { | |||
| 480 | if (!m_sixteenBit) // 8 bits image. | |||
| 481 | { | |||
| 482 | for (x = 0 ; x < (long)imageWidth() ; ++x) | |||
| 483 | { | |||
| 484 | // Blue | |||
| 485 | dst[0] = (uchar)(scale[2] * jas_matrix_getv(pixels[2], x / x_step[2])); | |||
| 486 | // Green | |||
| 487 | dst[1] = (uchar)(scale[1] * jas_matrix_getv(pixels[1], x / x_step[1])); | |||
| 488 | // Red | |||
| 489 | dst[2] = (uchar)(scale[0] * jas_matrix_getv(pixels[0], x / x_step[0])); | |||
| 490 | // Alpha | |||
| 491 | dst[3] = (uchar)(scale[3] * jas_matrix_getv(pixels[3], x / x_step[3])); | |||
| 492 | ||||
| 493 | dst += 4; | |||
| 494 | } | |||
| 495 | } | |||
| 496 | else // 16 bits image. | |||
| 497 | { | |||
| 498 | for (x = 0 ; x < (long)imageWidth() ; ++x) | |||
| 499 | { | |||
| 500 | // Blue | |||
| 501 | dst16[0] = (unsigned short)(scale[2] * jas_matrix_getv(pixels[2], x / x_step[2])); | |||
| 502 | // Green | |||
| 503 | dst16[1] = (unsigned short)(scale[1] * jas_matrix_getv(pixels[1], x / x_step[1])); | |||
| 504 | // Red | |||
| 505 | dst16[2] = (unsigned short)(scale[0] * jas_matrix_getv(pixels[0], x / x_step[0])); | |||
| 506 | // Alpha | |||
| 507 | dst16[3] = (unsigned short)(scale[3] * jas_matrix_getv(pixels[3], x / x_step[3])); | |||
| 508 | ||||
| 509 | dst16 += 4; | |||
| 510 | } | |||
| 511 | } | |||
| 512 | ||||
| 513 | break; | |||
| 514 | } | |||
| 515 | } | |||
| 516 | ||||
| 517 | // Use 0-10% and 90-100% for pseudo-progress | |||
| 518 | ||||
| 519 | if (observer && (y >= (long)checkPoint)) | |||
| 520 | { | |||
| 521 | checkPoint += granularity(observer, y, 0.8F); | |||
| 522 | ||||
| 523 | if (!observer->continueQuery()) | |||
| 524 | { | |||
| 525 | jas_image_destroy(jp2_image); | |||
| 526 | ||||
| 527 | for (i = 0 ; i < (long)number_components ; ++i) | |||
| 528 | { | |||
| 529 | jas_matrix_destroy(pixels[i]); | |||
| 530 | } | |||
| 531 | ||||
| 532 | cleanupJasper(); | |||
| 533 | loadingFailed(); | |||
| 534 | ||||
| 535 | return false; | |||
| 536 | } | |||
| 537 | ||||
| 538 | observer->progressInfo(0.1F + (0.8F * (((float)y) / ((float)imageHeight())))); | |||
| 539 | } | |||
| 540 | } | |||
| 541 | } | |||
| 542 | ||||
| 543 | // ------------------------------------------------------------------- | |||
| 544 | // Get ICC color profile. | |||
| 545 | ||||
| 546 | if (m_loadFlags & LoadICCData) | |||
| 547 | { | |||
| 548 | jas_iccprof_t* icc_profile = nullptr; | |||
| 549 | jas_stream_t* icc_stream = nullptr; | |||
| 550 | jas_cmprof_t* cm_profile = nullptr; | |||
| 551 | ||||
| 552 | // To prevent cppcheck warnings. | |||
| 553 | ||||
| 554 | (void)icc_profile; | |||
| 555 | (void)icc_stream; | |||
| 556 | (void)cm_profile; | |||
| 557 | ||||
| 558 | cm_profile = jas_image_cmprof(jp2_image)((jp2_image)->cmprof_); | |||
| 559 | ||||
| 560 | if (cm_profile != nullptr) | |||
| 561 | { | |||
| 562 | icc_profile = jas_iccprof_createfromcmprof(cm_profile); | |||
| 563 | } | |||
| 564 | ||||
| 565 | if (icc_profile != nullptr) | |||
| 566 | { | |||
| 567 | icc_stream = jas_stream_memopen(nullptr, 0); | |||
| 568 | ||||
| 569 | if (icc_stream != nullptr) | |||
| 570 | { | |||
| 571 | if (jas_iccprof_save(icc_profile, icc_stream) == 0) | |||
| 572 | { | |||
| 573 | if (jas_stream_flush(icc_stream) == 0) | |||
| 574 | { | |||
| 575 | jas_stream_memobj_t* const blob = reinterpret_cast<jas_stream_memobj_t*>(icc_stream->obj_); | |||
| 576 | QByteArray profile_rawdata; | |||
| 577 | profile_rawdata.resize(blob->len_); | |||
| 578 | memcpy(profile_rawdata.data(), blob->buf_, blob->len_); | |||
| 579 | imageSetIccProfile(IccProfile(profile_rawdata)); | |||
| 580 | jas_stream_close(icc_stream); | |||
| 581 | } | |||
| 582 | } | |||
| 583 | } | |||
| 584 | } | |||
| 585 | else | |||
| 586 | { | |||
| 587 | // If ICC profile is null, check Exif metadata. | |||
| 588 | ||||
| 589 | checkExifWorkingColorSpace(); | |||
| 590 | } | |||
| 591 | } | |||
| 592 | ||||
| 593 | if (observer) | |||
| 594 | { | |||
| 595 | observer->progressInfo(1.0F); | |||
| 596 | } | |||
| 597 | ||||
| 598 | imageData() = data.take(); | |||
| 599 | imageSetAttribute(QLatin1String("originalColorModel"), colorModel); | |||
| 600 | imageSetAttribute(QLatin1String("originalBitDepth"), maximum_component_depth); | |||
| 601 | imageSetAttribute(QLatin1String("originalSize"), QSize(imageWidth(), imageHeight())); | |||
| 602 | ||||
| 603 | jas_image_destroy(jp2_image); | |||
| 604 | ||||
| 605 | for (i = 0 ; i < (long)number_components ; ++i) | |||
| 606 | { | |||
| 607 | jas_matrix_destroy(pixels[i]); | |||
| 608 | } | |||
| 609 | ||||
| 610 | cleanupJasper(); | |||
| 611 | ||||
| 612 | return true; | |||
| 613 | } | |||
| 614 | ||||
| 615 | } // namespace DigikamJPEG2000DImgPlugin |