WebKit Bugzilla
Attachment 359745 Details for
Bug 186272
: [GTK][WPE] Support JPEG 2000 images
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
wcore-jp2.diff (text/plain), 29.30 KB, created by
Carlos Garcia Campos
on 2019-01-22 10:07:01 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Carlos Garcia Campos
Created:
2019-01-22 10:07:01 PST
Size:
29.30 KB
patch
obsolete
>diff --git a/ChangeLog b/ChangeLog >index 506fd3545b0..943bb7a6331 100644 >--- a/ChangeLog >+++ b/ChangeLog >@@ -1,3 +1,15 @@ >+2019-01-22 Carlos Garcia Campos <cgarcia@igalia.com> >+ >+ [GTK][WPE] Support JPEG 2000 images >+ https://bugs.webkit.org/show_bug.cgi?id=186272 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add USE_OPENJPEG build option. >+ >+ * Source/cmake/OptionsGTK.cmake: >+ * Source/cmake/OptionsWPE.cmake: >+ > 2019-01-18 Jer Noble <jer.noble@apple.com> > > SDK_VARIANT build destinations should be separate from non-SDK_VARIANT builds >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index e9f0c95c628..767627d3893 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,28 @@ >+2019-01-22 Carlos Garcia Campos <cgarcia@igalia.com> >+ >+ [GTK][WPE] Support JPEG 2000 images >+ https://bugs.webkit.org/show_bug.cgi?id=186272 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add JPEG2000ImageDecoder to support JPEG2000 images using OpenJPEG. For now only SRGB and SYCC color spaces are >+ supported. >+ >+ * platform/ImageDecoders.cmake: >+ * platform/MIMETypeRegistry.cpp: >+ (WebCore::MIMETypeRegistry::supportedImageMIMETypes): >+ * platform/image-decoders/ScalableImageDecoder.cpp: >+ (WebCore::ScalableImageDecoder::create): >+ * platform/image-decoders/jpeg2000/JPEG2000ImageDecoder.cpp: Added. >+ (WebCore::syccToRGB): >+ (WebCore::sycc444ToRGB): >+ (WebCore::sycc422ToRGB): >+ (WebCore::sycc420ToRGB): >+ (WebCore::JPEG2000ImageDecoder::JPEG2000ImageDecoder): >+ (WebCore::JPEG2000ImageDecoder::frameBufferAtIndex): >+ (WebCore::JPEG2000ImageDecoder::decode): >+ * platform/image-decoders/jpeg2000/JPEG2000ImageDecoder.h: Added. >+ > 2019-01-21 Carlos Garcia Campos <cgarcia@igalia.com> > > REGRESSION(r239915): about 130 test failures on WPE >diff --git a/Source/WebCore/platform/ImageDecoders.cmake b/Source/WebCore/platform/ImageDecoders.cmake >index 58d33051b37..292aa88cc88 100644 >--- a/Source/WebCore/platform/ImageDecoders.cmake >+++ b/Source/WebCore/platform/ImageDecoders.cmake >@@ -4,6 +4,7 @@ list(APPEND WebCore_INCLUDE_DIRECTORIES > "${WEBCORE_DIR}/platform/image-decoders/gif" > "${WEBCORE_DIR}/platform/image-decoders/ico" > "${WEBCORE_DIR}/platform/image-decoders/jpeg" >+ "${WEBCORE_DIR}/platform/image-decoders/jpeg2000" > "${WEBCORE_DIR}/platform/image-decoders/png" > "${WEBCORE_DIR}/platform/image-decoders/webp" > ) >@@ -22,6 +23,8 @@ list(APPEND WebCore_SOURCES > > platform/image-decoders/jpeg/JPEGImageDecoder.cpp > >+ platform/image-decoders/jpeg2000/JPEG2000ImageDecoder.cpp >+ > platform/image-decoders/png/PNGImageDecoder.cpp > > platform/image-decoders/webp/WEBPImageDecoder.cpp >@@ -36,6 +39,15 @@ list(APPEND WebCore_LIBRARIES > ${PNG_LIBRARIES} > ) > >+if (OpenJPEG_FOUND) >+ list(APPEND WebCore_SYSTEM_INCLUDE_DIRECTORIES >+ ${OPENJPEG_INCLUDE_DIRS} >+ ) >+ list(APPEND WebCore_LIBRARIES >+ ${OPENJPEG_LIBRARIES} >+ ) >+endif () >+ > if (WEBP_FOUND) > list(APPEND WebCore_SYSTEM_INCLUDE_DIRECTORIES > ${WEBP_INCLUDE_DIRS} >diff --git a/Source/WebCore/platform/MIMETypeRegistry.cpp b/Source/WebCore/platform/MIMETypeRegistry.cpp >index fdef56fa50c..f9eabb5fb90 100644 >--- a/Source/WebCore/platform/MIMETypeRegistry.cpp >+++ b/Source/WebCore/platform/MIMETypeRegistry.cpp >@@ -125,6 +125,10 @@ const HashSet<String, ASCIICaseInsensitiveHash>& MIMETypeRegistry::supportedImag > "image/vnd.microsoft.icon"_s, // ico > "image/x-icon"_s, // ico > "image/x-xbitmap"_s, // xbm >+#if USE(OPENJPEG) >+ "image/jp2"_s, >+ "image/jpeg2000"_s, >+#endif > #if USE(WEBP) > "image/webp"_s, > #endif >diff --git a/Source/WebCore/platform/image-decoders/ScalableImageDecoder.cpp b/Source/WebCore/platform/image-decoders/ScalableImageDecoder.cpp >index e24de4d1f8d..00810e57dab 100644 >--- a/Source/WebCore/platform/image-decoders/ScalableImageDecoder.cpp >+++ b/Source/WebCore/platform/image-decoders/ScalableImageDecoder.cpp >@@ -29,6 +29,9 @@ > #include "JPEGImageDecoder.h" > #include "PNGImageDecoder.h" > #include "SharedBuffer.h" >+#if USE(OPENJPEG) >+#include "JPEG2000ImageDecoder.h" >+#endif > #if USE(WEBP) > #include "WEBPImageDecoder.h" > #endif >@@ -73,6 +76,19 @@ bool matchesJPEGSignature(char* contents) > return !memcmp(contents, "\xFF\xD8\xFF", 3); > } > >+#if USE(OPENJPEG) >+bool matchesJP2Signature(char* contents) >+{ >+ return !memcmp(contents, "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A", 12) >+ || !memcmp(contents, "\x0D\x0A\x87\x0A", 4); >+} >+ >+bool matchesJ2KSignature(char* contents) >+{ >+ return !memcmp(contents, "\xFF\x4F\xFF\x51", 4); >+} >+#endif >+ > #if USE(WEBP) > bool matchesWebPSignature(char* contents) > { >@@ -117,6 +133,14 @@ RefPtr<ScalableImageDecoder> ScalableImageDecoder::create(SharedBuffer& data, Al > if (matchesJPEGSignature(contents)) > return JPEGImageDecoder::create(alphaOption, gammaAndColorProfileOption); > >+#if USE(OPENJPEG) >+ if (matchesJP2Signature(contents)) >+ return JPEG2000ImageDecoder::create(JPEG2000ImageDecoder::Format::JP2, alphaOption, gammaAndColorProfileOption); >+ >+ if (matchesJ2KSignature(contents)) >+ return JPEG2000ImageDecoder::create(JPEG2000ImageDecoder::Format::J2K, alphaOption, gammaAndColorProfileOption); >+#endif >+ > #if USE(WEBP) > if (matchesWebPSignature(contents)) > return WEBPImageDecoder::create(alphaOption, gammaAndColorProfileOption); >diff --git a/Source/WebCore/platform/image-decoders/jpeg2000/JPEG2000ImageDecoder.cpp b/Source/WebCore/platform/image-decoders/jpeg2000/JPEG2000ImageDecoder.cpp >new file mode 100644 >index 00000000000..e9dad965b9f >--- /dev/null >+++ b/Source/WebCore/platform/image-decoders/jpeg2000/JPEG2000ImageDecoder.cpp >@@ -0,0 +1,559 @@ >+/* >+ * Copyright (C) 2019 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "JPEG2000ImageDecoder.h" >+ >+#if USE(OPENJPEG) >+ >+#include <openjpeg.h> >+ >+namespace WebCore { >+ >+// SYCC to RGB conversion code from libopenjpeg (BSD), adapted to WebKit coding style. >+// -------------------------------------------------------- >+// Matrix for sYCC, Amendment 1 to IEC 61966-2-1 >+// >+// Y : 0.299 0.587 0.114 :R >+// Cb: -0.1687 -0.3312 0.5 :G >+// Cr: 0.5 -0.4187 -0.0812 :B >+// >+// Inverse: >+// >+// R: 1 -3.68213e-05 1.40199 :Y >+// G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1) >+// B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1) >+// >+// -----------------------------------------------------------*/ >+static void syccToRGB(int offset, int upb, int y, int cb, int cr, int* r, int* g, int* b) >+{ >+ cb -= offset; >+ cr -= offset; >+ >+ *r = std::max(0, std::min(upb, y + static_cast<int>(1.402 * static_cast<float>(cr)))); >+ *g = std::max(0, std::min(upb, y - static_cast<int>(0.344 * static_cast<float>(cb) + 0.714 * static_cast<float>(cr)))); >+ *b = std::max(0, std::min(upb, y + static_cast<int>(1.772 * static_cast<float>(cb)))); >+} >+ >+static void sycc444ToRGB(opj_image_t* img) >+{ >+ int upb = static_cast<int>(img->comps[0].prec); >+ int offset = 1 << (upb - 1); >+ upb = (1 << upb) - 1; >+ >+ size_t maxw = static_cast<size_t>(img->comps[0].w); >+ size_t maxh = static_cast<size_t>(img->comps[0].h); >+ size_t max = maxw * maxh; >+ >+ const int* y = img->comps[0].data; >+ const int* cb = img->comps[1].data; >+ const int* cr = img->comps[2].data; >+ >+ auto* d0 = static_cast<int*>(opj_image_data_alloc(sizeof(int) * max)); >+ auto* d1 = static_cast<int*>(opj_image_data_alloc(sizeof(int) * max)); >+ auto* d2 = static_cast<int*>(opj_image_data_alloc(sizeof(int) * max)); >+ auto* r = d0; >+ auto* g = d1; >+ auto* b = d2; >+ >+ if (!r || !g || !b) { >+ opj_image_data_free(r); >+ opj_image_data_free(g); >+ opj_image_data_free(b); >+ return; >+ } >+ >+ for (size_t i = 0; i < max; ++i) { >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ ++y; >+ ++cb; >+ ++cr; >+ ++r; >+ ++g; >+ ++b; >+ } >+ >+ opj_image_data_free(img->comps[0].data); >+ img->comps[0].data = d0; >+ opj_image_data_free(img->comps[1].data); >+ img->comps[1].data = d1; >+ opj_image_data_free(img->comps[2].data); >+ img->comps[2].data = d2; >+ img->color_space = OPJ_CLRSPC_SRGB; >+} >+ >+static void sycc422ToRGB(opj_image_t* img) >+{ >+ int upb = (int)img->comps[0].prec; >+ int offset = 1 << (upb - 1); >+ upb = (1 << upb) - 1; >+ >+ size_t maxw = static_cast<size_t>(img->comps[0].w); >+ size_t maxh = static_cast<size_t>(img->comps[0].h); >+ size_t max = maxw * maxh; >+ >+ const int* y = img->comps[0].data; >+ const int* cb = img->comps[1].data; >+ const int* cr = img->comps[2].data; >+ >+ auto* d0 = static_cast<int*>(opj_image_data_alloc(sizeof(int) * max)); >+ auto* d1 = static_cast<int*>(opj_image_data_alloc(sizeof(int) * max)); >+ auto* d2 = static_cast<int*>(opj_image_data_alloc(sizeof(int) * max)); >+ auto* r = d0; >+ auto* g = d1; >+ auto* b = d2; >+ >+ if (!r || !g || !b) { >+ opj_image_data_free(r); >+ opj_image_data_free(g); >+ opj_image_data_free(b); >+ return; >+ } >+ >+ // if img->x0 is odd, then first column shall use Cb/Cr = 0. >+ size_t offx = img->x0 & 1U; >+ size_t loopmaxw = maxw - offx; >+ >+ for (size_t i = 0; i < maxh; ++i) { >+ size_t j; >+ >+ if (offx > 0) { >+ syccToRGB(offset, upb, *y, 0, 0, r, g, b); >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ } >+ >+ for (j = 0; j < (loopmaxw & ~static_cast<size_t>(1U)); j += 2U) { >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ ++cb; >+ ++cr; >+ } >+ if (j < loopmaxw) { >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ ++cb; >+ ++cr; >+ } >+ } >+ >+ opj_image_data_free(img->comps[0].data); >+ img->comps[0].data = d0; >+ opj_image_data_free(img->comps[1].data); >+ img->comps[1].data = d1; >+ opj_image_data_free(img->comps[2].data); >+ img->comps[2].data = d2; >+ >+ img->comps[1].w = img->comps[2].w = img->comps[0].w; >+ img->comps[1].h = img->comps[2].h = img->comps[0].h; >+ img->comps[1].dx = img->comps[2].dx = img->comps[0].dx; >+ img->comps[1].dy = img->comps[2].dy = img->comps[0].dy; >+ img->color_space = OPJ_CLRSPC_SRGB; >+} >+ >+static void sycc420ToRGB(opj_image_t* img) >+{ >+ int upb = static_cast<int>(img->comps[0].prec); >+ int offset = 1 << (upb - 1); >+ upb = (1 << upb) - 1; >+ >+ size_t maxw = static_cast<size_t>(img->comps[0].w); >+ size_t maxh = static_cast<size_t>(img->comps[0].h); >+ size_t max = maxw * maxh; >+ >+ const int* y = img->comps[0].data; >+ const int* cb = img->comps[1].data; >+ const int* cr = img->comps[2].data; >+ >+ auto* d0 = static_cast<int*>(opj_image_data_alloc(sizeof(int) * max)); >+ auto* d1 = static_cast<int*>(opj_image_data_alloc(sizeof(int) * max)); >+ auto* d2 = static_cast<int*>(opj_image_data_alloc(sizeof(int) * max)); >+ auto* r = d0; >+ auto* g = d1; >+ auto* b = d2; >+ >+ if (!r || !g || !b) { >+ opj_image_data_free(r); >+ opj_image_data_free(g); >+ opj_image_data_free(b); >+ return; >+ } >+ >+ // if img->x0 is odd, then first column shall use Cb/Cr = 0. >+ size_t offx = img->x0 & 1U; >+ size_t loopmaxw = maxw - offx; >+ // if img->y0 is odd, then first line shall use Cb/Cr = 0. >+ size_t offy = img->y0 & 1U; >+ size_t loopmaxh = maxh - offy; >+ >+ if (offy > 0) { >+ size_t j; >+ for (j = 0; j < maxw; ++j) { >+ syccToRGB(offset, upb, *y, 0, 0, r, g, b); >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ } >+ } >+ >+ size_t i; >+ for (i = 0; i < (loopmaxh & ~static_cast<size_t>(1U)); i += 2U) { >+ const int* ny = y + maxw; >+ int* nr = r + maxw; >+ int* ng = g + maxw; >+ int* nb = b + maxw; >+ >+ if (offx > 0) { >+ syccToRGB(offset, upb, *y, 0, 0, r, g, b); >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ syccToRGB(offset, upb, *ny, *cb, *cr, nr, ng, nb); >+ ++ny; >+ ++nr; >+ ++ng; >+ ++nb; >+ } >+ >+ size_t j; >+ for (j = 0; j < (loopmaxw & ~static_cast<size_t>(1U)); j += 2U) { >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ >+ syccToRGB(offset, upb, *ny, *cb, *cr, nr, ng, nb); >+ ++ny; >+ ++nr; >+ ++ng; >+ ++nb; >+ syccToRGB(offset, upb, *ny, *cb, *cr, nr, ng, nb); >+ ++ny; >+ ++nr; >+ ++ng; >+ ++nb; >+ ++cb; >+ ++cr; >+ } >+ if (j < loopmaxw) { >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ >+ syccToRGB(offset, upb, *ny, *cb, *cr, nr, ng, nb); >+ ++ny; >+ ++nr; >+ ++ng; >+ ++nb; >+ ++cb; >+ ++cr; >+ } >+ y += maxw; >+ r += maxw; >+ g += maxw; >+ b += maxw; >+ } >+ if (i < loopmaxh) { >+ size_t j; >+ for (j = 0; j < (maxw & ~static_cast<size_t>(1U)); j += 2U) { >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ >+ ++y; >+ ++r; >+ ++g; >+ ++b; >+ ++cb; >+ ++cr; >+ } >+ if (j < maxw) >+ syccToRGB(offset, upb, *y, *cb, *cr, r, g, b); >+ } >+ >+ opj_image_data_free(img->comps[0].data); >+ img->comps[0].data = d0; >+ opj_image_data_free(img->comps[1].data); >+ img->comps[1].data = d1; >+ opj_image_data_free(img->comps[2].data); >+ img->comps[2].data = d2; >+ >+ img->comps[1].w = img->comps[2].w = img->comps[0].w; >+ img->comps[1].h = img->comps[2].h = img->comps[0].h; >+ img->comps[1].dx = img->comps[2].dx = img->comps[0].dx; >+ img->comps[1].dy = img->comps[2].dy = img->comps[0].dy; >+ img->color_space = OPJ_CLRSPC_SRGB; >+} >+ >+JPEG2000ImageDecoder::JPEG2000ImageDecoder(Format format, AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption) >+ : ScalableImageDecoder(alphaOption, gammaAndColorProfileOption) >+ , m_format(format) >+{ >+} >+ >+ScalableImageDecoderFrame* JPEG2000ImageDecoder::frameBufferAtIndex(size_t index) >+{ >+ if (index) >+ return nullptr; >+ >+ if (m_frameBufferCache.isEmpty()) >+ m_frameBufferCache.grow(1); >+ >+ auto& frame = m_frameBufferCache[0]; >+ if (!frame.isComplete()) >+ decode(false, isAllDataReceived()); >+ return &frame; >+} >+ >+void JPEG2000ImageDecoder::decode(bool onlySize, bool allDataReceived) >+{ >+ if (failed()) >+ return; >+ >+ std::unique_ptr<opj_codec_t, void(*)(opj_codec_t*)> decoder(opj_create_decompress(m_format == Format::JP2 ? OPJ_CODEC_JP2 : OPJ_CODEC_J2K), opj_destroy_codec); >+ if (!decoder) { >+ setFailed(); >+ return; >+ } >+ >+ opj_dparameters_t parameters; >+ opj_set_default_decoder_parameters(¶meters); >+ if (!opj_setup_decoder(decoder.get(), ¶meters)) { >+ setFailed(); >+ return; >+ } >+ >+ std::unique_ptr<opj_stream_t, void(*)(opj_stream_t*)> stream(opj_stream_default_create(OPJ_TRUE), opj_stream_destroy); >+ if (!stream) { >+ setFailed(); >+ return; >+ } >+ >+ struct Reader { >+ SharedBuffer& data; >+ size_t offset; >+ } reader = { *m_data, 0 }; >+ >+ opj_stream_set_user_data(stream.get(), &reader, nullptr); >+ opj_stream_set_user_data_length(stream.get(), m_data->size()); >+ opj_stream_set_read_function(stream.get(), [](void* buffer, OPJ_SIZE_T bytes, void* userData) -> OPJ_SIZE_T { >+ auto& reader = *static_cast<Reader*>(userData); >+ if (reader.offset == reader.data.size()) >+ return -1; >+ >+ OPJ_SIZE_T length = reader.offset + bytes > reader.data.size() ? reader.data.size() - reader.offset : bytes; >+ memcpy(buffer, reader.data.data(), length); >+ reader.offset += length; >+ >+ return length; >+ }); >+ opj_stream_set_skip_function(stream.get(), [](OPJ_OFF_T bytes, void* userData) -> OPJ_OFF_T { >+ auto& reader = *static_cast<Reader*>(userData); >+ >+ OPJ_OFF_T skip = reader.offset + bytes > reader.data.size() ? reader.data.size() - reader.offset : bytes; >+ reader.offset += skip; >+ >+ return skip; >+ }); >+ opj_stream_set_seek_function(stream.get(), [](OPJ_OFF_T bytes, void* userData) -> OPJ_BOOL { >+ auto& reader = *static_cast<Reader*>(userData); >+ >+ if (static_cast<unsigned>(bytes) > reader.data.size()) >+ return OPJ_FALSE; >+ >+ reader.offset = bytes; >+ >+ return OPJ_TRUE; >+ }); >+ >+ opj_image_t* imagePtr = nullptr; >+ if (!opj_read_header(stream.get(), decoder.get(), &imagePtr)) { >+ if (allDataReceived) >+ setFailed(); >+ opj_image_destroy(imagePtr); >+ return; >+ } >+ >+ std::unique_ptr<opj_image_t, void(*)(opj_image_t*)> image(imagePtr, opj_image_destroy); >+ setSize({ static_cast<int>(image->x1 - image->x0), static_cast<int>(image->y1 - image->y0) }); >+ if (onlySize) >+ return; >+ >+ if (!opj_decode(decoder.get(), stream.get(), image.get())) { >+ if (allDataReceived) >+ setFailed(); >+ return; >+ } >+ >+ if (image->color_space == OPJ_CLRSPC_UNSPECIFIED) { >+ if (image->numcomps == 3 && image->comps[0].dx == image->comps[0].dy && image->comps[1].dx != 1) >+ image->color_space = OPJ_CLRSPC_SYCC; >+ else if (image->numcomps <= 2) >+ image->color_space = OPJ_CLRSPC_GRAY; >+ } >+ >+ if (image->color_space == OPJ_CLRSPC_SYCC) { >+ if (image->numcomps < 3) >+ image->color_space = OPJ_CLRSPC_GRAY; >+ else if ((image->comps[0].dx == 1) >+ && (image->comps[1].dx == 2) >+ && (image->comps[2].dx == 2) >+ && (image->comps[0].dy == 1) >+ && (image->comps[1].dy == 2) >+ && (image->comps[2].dy == 2)) { >+ // Horizontal and vertical sub-sample. >+ sycc420ToRGB(image.get()); >+ } else if ((image->comps[0].dx == 1) >+ && (image->comps[1].dx == 2) >+ && (image->comps[2].dx == 2) >+ && (image->comps[0].dy == 1) >+ && (image->comps[1].dy == 1) >+ && (image->comps[2].dy == 1)) { >+ // Horizontal sub-sample only. >+ sycc422ToRGB(image.get()); >+ } else if ((image->comps[0].dx == 1) >+ && (image->comps[1].dx == 1) >+ && (image->comps[2].dx == 1) >+ && (image->comps[0].dy == 1) >+ && (image->comps[1].dy == 1) >+ && (image->comps[2].dy == 1)) { >+ // No sub-sample. >+ sycc444ToRGB(image.get()); >+ } >+ } >+ >+ if (image->color_space != OPJ_CLRSPC_SRGB) { >+ // Unsupported format. >+ setFailed(); >+ return; >+ } >+ >+ auto& buffer = m_frameBufferCache[0]; >+ if (!buffer.initialize(scaledSize(), m_premultiplyAlpha)) { >+ setFailed(); >+ return; >+ } >+ >+ buffer.setDecodingStatus(DecodingStatus::Partial); >+ buffer.setHasAlpha(false); >+ >+ int adjust[4] = { 0, 0, 0, 0 }; >+ for (OPJ_UINT32 component = 0; component < image->numcomps; ++component) { >+ if (!image->comps[component].data) { >+ setFailed(); >+ break; >+ } >+ >+ if (image->comps[component].prec > 8) >+ adjust[component] = image->comps[component].prec - 8; >+ } >+ >+ bool subsampling = image->comps[0].dx != 1 || image->comps[0].dy != 1 || image->comps[1].dx != 1 || image->comps[1].dy != 1 || image->comps[2].dx != 1 || image->comps[2].dy != 1; >+ unsigned char nonTrivialAlphaMask = 0; >+ const IntRect& frameRect = buffer.backingStore()->frameRect(); >+ for (int y = 0; y < frameRect.height(); ++y) { >+ for (int x = 0; x < frameRect.width(); ++x) { >+ int r, g, b, a; >+ >+ int offset; >+ if (subsampling) { >+ int subX = frameRect.width() / image->comps[0].w; >+ int subY = frameRect.height() / image->comps[0].h; >+ offset = (y / subY) * image->comps[0].w + (x / subX); >+ } else >+ offset = y * frameRect.width() + x; >+ >+ r = image->comps[0].data[offset]; >+ r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); >+ if (subsampling) { >+ int subX = frameRect.width() / image->comps[1].w; >+ int subY = frameRect.height() / image->comps[1].h; >+ offset = (y / subY) * image->comps[1].w + (x / subX); >+ } >+ g = image->comps[1].data[offset]; >+ g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); >+ if (subsampling) { >+ int subX = frameRect.width() / image->comps[2].w; >+ int subY = frameRect.height() / image->comps[2].h; >+ offset = (y / subY) * image->comps[2].w + (x / subX); >+ } >+ b = image->comps[2].data[offset]; >+ b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); >+ >+ if (image->numcomps > 3) { >+ if (subsampling) { >+ int subX = frameRect.width() / image->comps[3].w; >+ int subY = frameRect.height() / image->comps[3].h; >+ offset = (y / subY) * image->comps[3].w + (x / subX); >+ } >+ a = image->comps[3].data[offset]; >+ a += (image->comps[3].sgnd ? 1 << (image->comps[3].prec - 1) : 0); >+ } >+ >+ int adjustedRed = (r >> adjust[0]) + ((r >> (adjust[0] - 1)) % 2); >+ int adjustedGreen = (g >> adjust[1]) + ((g >> (adjust[1] - 1)) % 2); >+ int adjustedBlue = (b >> adjust[2]) + ((b >> (adjust[2] - 1)) % 2); >+ int adjustedAlpha = image->numcomps > 3 ? (a >> adjust[3]) + ((a >> (adjust[3] - 1)) % 2) : 0xFF; >+ buffer.backingStore()->setPixel(x, y, adjustedRed, adjustedGreen, adjustedBlue, adjustedAlpha); >+ nonTrivialAlphaMask |= (255 - adjustedAlpha); >+ } >+ } >+ >+ buffer.setDecodingStatus(DecodingStatus::Complete); >+ if (nonTrivialAlphaMask && !buffer.hasAlpha()) >+ buffer.setHasAlpha(true); >+} >+ >+} // namespace WebCore >+ >+#endif // USE(OPENJPEG) >diff --git a/Source/WebCore/platform/image-decoders/jpeg2000/JPEG2000ImageDecoder.h b/Source/WebCore/platform/image-decoders/jpeg2000/JPEG2000ImageDecoder.h >new file mode 100644 >index 00000000000..c159ccba338 >--- /dev/null >+++ b/Source/WebCore/platform/image-decoders/jpeg2000/JPEG2000ImageDecoder.h >@@ -0,0 +1,59 @@ >+/* >+ * Copyright (C) 2019 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "ScalableImageDecoder.h" >+ >+#if USE(OPENJPEG) >+ >+namespace WebCore { >+ >+class JPEG2000ImageDecoder final : public ScalableImageDecoder { >+public: >+ enum class Format { JP2, J2K }; >+ static Ref<ScalableImageDecoder> create(Format format, AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption) >+ { >+ return adoptRef(*new JPEG2000ImageDecoder(format, alphaOption, gammaAndColorProfileOption)); >+ } >+ >+ virtual ~JPEG2000ImageDecoder() = default; >+ >+ // ScalableImageDecoder >+ String filenameExtension() const override { return m_format == Format::JP2 ? "jp2"_s : "j2k"_s; } >+ ScalableImageDecoderFrame* frameBufferAtIndex(size_t index) override; >+ >+private: >+ JPEG2000ImageDecoder(Format, AlphaOption, GammaAndColorProfileOption); >+ >+ void decode(bool onlySize, bool allDataReceived); >+ void tryDecodeSize(bool allDataReceived) override { decode(true, allDataReceived); } >+ >+ Format m_format; >+}; >+ >+} // namespace WebCore >+ >+#endif // USE(OPENJPEG) >diff --git a/Source/cmake/OptionsGTK.cmake b/Source/cmake/OptionsGTK.cmake >index 5e5529e3f56..bc6868edfa6 100644 >--- a/Source/cmake/OptionsGTK.cmake >+++ b/Source/cmake/OptionsGTK.cmake >@@ -83,6 +83,7 @@ WEBKIT_OPTION_DEFINE(ENABLE_WAYLAND_TARGET "Whether to enable support for the Wa > WEBKIT_OPTION_DEFINE(USE_LIBNOTIFY "Whether to enable the default web notification implementation." PUBLIC ON) > WEBKIT_OPTION_DEFINE(USE_LIBHYPHEN "Whether to enable the default automatic hyphenation implementation." PUBLIC ON) > WEBKIT_OPTION_DEFINE(USE_LIBSECRET "Whether to enable the persistent credential storage using libsecret." PUBLIC ON) >+WEBKIT_OPTION_DEFINE(USE_OPENJPEG "Whether to enable support for JPEG2000 images." PUBLIC ON) > WEBKIT_OPTION_DEFINE(USE_WOFF2 "Whether to enable support for WOFF2 Web Fonts." PUBLIC ON) > > # Private options specific to the GTK+ port. Changing these options is >@@ -389,6 +390,16 @@ if (USE_LIBHYPHEN) > endif () > endif () > >+if (USE_OPENJPEG) >+ find_package(OpenJPEG) >+ if (NOT OpenJPEG_FOUND) >+ message(FATAL_ERROR "libopenjpeg is needed for USE_OPENJPEG.") >+ endif () >+ if ("${OPENJPEG_MAJOR_VERSION}.${OPENJPEG_MINOR_VERSION}.${OPENJPEG_BUILD_VERSION}" VERSION_LESS "2.1.0") >+ message(FATAL_ERROR "libopenjpeg 2.1.0 is required for USE_OPENJPEG.") >+ endif () >+endif () >+ > if (USE_WOFF2) > find_package(WOFF2Dec 1.0.2) > if (NOT WOFF2DEC_FOUND) >diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake >index 5f311b83c5a..924291e7a90 100644 >--- a/Source/cmake/OptionsWPE.cmake >+++ b/Source/cmake/OptionsWPE.cmake >@@ -44,6 +44,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FE > # there is a strong reason we should support changing the value of the option, > # and the option is not relevant to any other WebKit ports. > WEBKIT_OPTION_DEFINE(ENABLE_GTKDOC "Whether or not to use generate gtkdoc." PUBLIC OFF) >+WEBKIT_OPTION_DEFINE(USE_OPENJPEG "Whether to enable support for JPEG2000 images." PUBLIC ON) > WEBKIT_OPTION_DEFINE(USE_WOFF2 "Whether to enable support for WOFF2 Web Fonts." PUBLIC ON) > WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC OFF) > >@@ -86,6 +87,16 @@ find_package(WebP REQUIRED) > find_package(WPE REQUIRED) > find_package(ZLIB REQUIRED) > >+if (USE_OPENJPEG) >+ find_package(OpenJPEG) >+ if (NOT OpenJPEG_FOUND) >+ message(FATAL_ERROR "libopenjpeg is needed for USE_OPENJPEG.") >+ endif () >+ if ("${OPENJPEG_MAJOR_VERSION}.${OPENJPEG_MINOR_VERSION}.${OPENJPEG_BUILD_VERSION}" VERSION_LESS "2.1.0") >+ message(FATAL_ERROR "libopenjpeg 2.1.0 is required for USE_OPENJPEG.") >+ endif () >+endif () >+ > if (USE_WOFF2) > find_package(WOFF2Dec 1.0.2) > if (NOT WOFF2DEC_FOUND)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186272
:
359745
|
359870
|
359873
|
359881