JPEG2000Loader.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * Copyright (c) 2024, Nico Weber <thakis@chromium.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/MemoryStream.h>
  7. #include <LibGfx/ImageFormats/ISOBMFF/JPEG2000Boxes.h>
  8. #include <LibGfx/ImageFormats/ISOBMFF/Reader.h>
  9. #include <LibGfx/ImageFormats/JPEG2000Loader.h>
  10. // Core coding system spec (.jp2 format): T-REC-T.800-201511-S!!PDF-E.pdf available here:
  11. // https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.800-201511-S!!PDF-E&type=items
  12. // Extensions (.jpx format): T-REC-T.801-202106-S!!PDF-E.pdf available here:
  13. // https://handle.itu.int/11.1002/1000/14666-en?locatt=format:pdf&auth
  14. // rfc3745 lists the MIME type. It only mentions the jp2_id_string as magic number.
  15. namespace Gfx {
  16. // A JPEG2000 image can be stored in a codestream with markers, similar to a JPEG image,
  17. // or in a JP2 file, which is a container format based on boxes similar to ISOBMFF.
  18. // This is the marker for the codestream version. We don't support this yet.
  19. // If we add support, add a second `"image/jp2"` line to MimeData.cpp for this magic number.
  20. // T.800 Annex A, Codestream syntax, A.2 Information in the marker segments and A.3 Construction of the codestream
  21. [[maybe_unused]] static constexpr u8 marker_id_string[] = { 0xFF, 0x4F, 0xFF, 0x51 };
  22. // This is the marker for the box version.
  23. // T.800 Annex I, JP2 file format syntax, I.5.1 JPEG 2000 Signature box
  24. static constexpr u8 jp2_id_string[] = { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A };
  25. // Table A.2 – List of markers and marker segments
  26. // "Delimiting markers and marker segments"
  27. #define J2K_SOC 0xFF4F // "Start of codestream"
  28. #define J2K_SOT 0xFF90 // "Start of tile-part"
  29. #define J2K_SOD 0xFF93 // "Start of data"
  30. #define J2K_EOC 0xFFD9 // "End of codestream"
  31. // "Fixed information marker segments"
  32. #define J2K_SIZ 0xFF51 // "Image and tile size"
  33. // "Functional marker segments"
  34. #define J2K_COD 0xFF52 // "Coding style default"
  35. #define J2K_COC 0xFF53 // "Coding style component"
  36. #define J2K_RGN 0xFF5E // "Region-of-interest"
  37. #define J2K_QCD 0xFF5C // "Quantization default"
  38. #define J2K_QCC 0xFF5D // "Quantization component"
  39. #define J2K_POC 0xFF5F // "Progression order change"
  40. // "Pointer marker segments"
  41. #define J2K_TLM 0xFF55 // "Tile-part lengths"
  42. #define J2K_PLM 0xFF57 // "Packet length, main header"
  43. #define J2K_PLT 0xFF58 // "Packet length, tile-part header"
  44. #define J2K_PPM 0xFF60 // "Packed packet headers, main header"
  45. #define J2K_PPT 0xFF61 // "Packed packet headers, tile-part header"
  46. // "In-bit-stream markers and marker segments"
  47. #define J2K_SOP 0xFF91 // "Start of packet"
  48. #define J2K_EPH 0xFF92 // "End of packet header"
  49. // "Informational marker segments"
  50. #define J2K_CRG 0xFF63 // "Component registration"
  51. #define J2K_COM 0xFF64 // "Comment"
  52. struct JPEG2000LoadingContext {
  53. enum class State {
  54. NotDecoded = 0,
  55. Error,
  56. };
  57. State state { State::NotDecoded };
  58. ReadonlyBytes codestream_data;
  59. size_t codestream_cursor { 0 };
  60. Optional<ReadonlyBytes> icc_data;
  61. IntSize size;
  62. ISOBMFF::BoxList boxes;
  63. };
  64. struct MarkerSegment {
  65. u16 marker;
  66. // OptionalNone for markers that don't have data.
  67. // For markers that do have data, this does not include the marker length data. (`data.size() + 2` is the value of the marker length field.)
  68. Optional<ReadonlyBytes> data;
  69. };
  70. static ErrorOr<u16> peek_marker(JPEG2000LoadingContext& context)
  71. {
  72. if (context.codestream_cursor + 2 > context.codestream_data.size())
  73. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Not enough data for marker");
  74. return *reinterpret_cast<AK::BigEndian<u16> const*>(context.codestream_data.data() + context.codestream_cursor);
  75. }
  76. static ErrorOr<MarkerSegment> read_marker_at_cursor(JPEG2000LoadingContext& context)
  77. {
  78. u16 marker = TRY(peek_marker(context));
  79. // "All markers with the marker code between 0xFF30 and 0xFF3F have no marker segment parameters. They shall be skipped by the decoder."
  80. // "The SOC, SOD and EOC are delimiting markers not marker segments, and have no explicit length information or other parameters."
  81. bool is_marker_segment = !(marker >= 0xFF30 && marker <= 0xFF3F) && marker != J2K_SOC && marker != J2K_SOD && marker != J2K_EOC;
  82. MarkerSegment marker_segment;
  83. marker_segment.marker = marker;
  84. if (is_marker_segment) {
  85. if (context.codestream_cursor + 4 > context.codestream_data.size())
  86. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Not enough data for marker segment length");
  87. u16 marker_length = *reinterpret_cast<AK::BigEndian<u16> const*>(context.codestream_data.data() + context.codestream_cursor + 2);
  88. if (marker_length < 2)
  89. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Marker segment length too small");
  90. if (context.codestream_cursor + 2 + marker_length > context.codestream_data.size())
  91. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Not enough data for marker segment data");
  92. marker_segment.data = ReadonlyBytes { context.codestream_data.data() + context.codestream_cursor + 4, marker_length - 2u };
  93. }
  94. context.codestream_cursor += 2;
  95. if (is_marker_segment)
  96. context.codestream_cursor += 2 + marker_segment.data->size();
  97. return marker_segment;
  98. }
  99. static ErrorOr<void> parse_codestream_main_header(JPEG2000LoadingContext& context)
  100. {
  101. // Figure A.3 – Construction of the main header
  102. // "Required as the first marker"
  103. auto marker = TRY(read_marker_at_cursor(context));
  104. if (marker.marker != J2K_SOC)
  105. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Expected SOC marker");
  106. // "Required as the second marker segment"
  107. marker = TRY(read_marker_at_cursor(context));
  108. if (marker.marker != J2K_SIZ)
  109. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Expected SIZ marker");
  110. // FIXME: Parse SIZ marker.
  111. while (true) {
  112. u16 marker = TRY(peek_marker(context));
  113. switch (marker) {
  114. case J2K_COD:
  115. case J2K_COC:
  116. case J2K_QCD:
  117. case J2K_QCC:
  118. case J2K_RGN:
  119. case J2K_POC:
  120. case J2K_PPM:
  121. case J2K_TLM:
  122. case J2K_PLM:
  123. case J2K_CRG:
  124. case J2K_COM: {
  125. // FIXME: These are valid main header markers. Parse contents.
  126. auto marker = TRY(read_marker_at_cursor(context));
  127. dbgln("JPEG2000ImageDecoderPlugin: marker {:#04x} not yet implemented", marker.marker);
  128. break;
  129. }
  130. case J2K_SOT:
  131. return {};
  132. default:
  133. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Unexpected marker in main header");
  134. }
  135. }
  136. }
  137. static ErrorOr<void> decode_jpeg2000_header(JPEG2000LoadingContext& context, ReadonlyBytes data)
  138. {
  139. if (!JPEG2000ImageDecoderPlugin::sniff(data))
  140. return Error::from_string_literal("JBIG2LoadingContext: Invalid JBIG2 header");
  141. auto reader = TRY(Gfx::ISOBMFF::Reader::create(TRY(try_make<FixedMemoryStream>(data))));
  142. context.boxes = TRY(reader.read_entire_file());
  143. // I.2.2 File organization
  144. // "A particular order of those boxes in the file is not generally implied. However, the JPEG 2000 Signature box
  145. // shall be the first box in a JP2 file, the File Type box shall immediately follow the JPEG 2000 Signature box
  146. // and the JP2 Header box shall fall before the Contiguous Codestream box."
  147. if (context.boxes.size() < 4)
  148. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Expected at least four boxes");
  149. // Required toplevel boxes: signature box, file type box, jp2 header box, contiguous codestream box.
  150. if (context.boxes[0]->box_type() != ISOBMFF::BoxType::JPEG2000SignatureBox)
  151. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Expected JPEG2000SignatureBox as first box");
  152. if (context.boxes[1]->box_type() != ISOBMFF::BoxType::FileTypeBox)
  153. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Expected FileTypeBox as second box");
  154. Optional<size_t> jp2_header_box_index;
  155. Optional<size_t> contiguous_codestream_box_index;
  156. for (size_t i = 2; i < context.boxes.size(); ++i) {
  157. if (context.boxes[i]->box_type() == ISOBMFF::BoxType::JPEG2000HeaderBox) {
  158. // "Within a JP2 file, there shall be one and only one JP2 Header box."
  159. if (jp2_header_box_index.has_value())
  160. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Multiple JP2 Header boxes");
  161. jp2_header_box_index = i;
  162. }
  163. if (context.boxes[i]->box_type() == ISOBMFF::BoxType::JPEG2000ContiguousCodestreamBox && !contiguous_codestream_box_index.has_value()) {
  164. // "a conforming reader shall ignore all codestreams after the first codestream found in the file.
  165. // Contiguous Codestream boxes may be found anywhere in the file except before the JP2 Header box."
  166. contiguous_codestream_box_index = i;
  167. if (!jp2_header_box_index.has_value() || contiguous_codestream_box_index.value() < jp2_header_box_index.value())
  168. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: JP2 Header box must come before Contiguous Codestream box");
  169. }
  170. }
  171. if (!jp2_header_box_index.has_value())
  172. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Expected JP2 Header box");
  173. if (!contiguous_codestream_box_index.has_value())
  174. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Expected Contiguous Codestream box");
  175. // FIXME: JPEG2000ContiguousCodestreamBox makes a copy of the codestream data. That's too heavy for header scanning.
  176. // Add a mode to ISOBMFF::Reader where it only stores offsets for the codestream data and the ICC profile.
  177. auto const& codestream_box = static_cast<ISOBMFF::JPEG2000ContiguousCodestreamBox const&>(*context.boxes[contiguous_codestream_box_index.value()]);
  178. context.codestream_data = codestream_box.codestream.bytes();
  179. // Required child boxes of the jp2 header box: image header box, color box.
  180. Optional<size_t> image_header_box_index;
  181. Optional<size_t> color_header_box_index;
  182. auto const& header_box = static_cast<ISOBMFF::JPEG2000HeaderBox const&>(*context.boxes[jp2_header_box_index.value()]);
  183. for (size_t i = 0; i < header_box.child_boxes().size(); ++i) {
  184. auto const& subbox = header_box.child_boxes()[i];
  185. if (subbox->box_type() == ISOBMFF::BoxType::JPEG2000ImageHeaderBox) {
  186. if (image_header_box_index.has_value())
  187. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Multiple Image Header boxes");
  188. image_header_box_index = i;
  189. }
  190. if (subbox->box_type() == ISOBMFF::BoxType::JPEG2000ColorSpecificationBox) {
  191. // T.800 says there should be just one 'colr' box, but T.801 allows several and says to pick the one with highest precedence.
  192. bool use_this_color_box;
  193. if (!color_header_box_index.has_value()) {
  194. use_this_color_box = true;
  195. } else {
  196. auto const& new_header_box = static_cast<ISOBMFF::JPEG2000ColorSpecificationBox const&>(*header_box.child_boxes()[i]);
  197. auto const& current_color_box = static_cast<ISOBMFF::JPEG2000ColorSpecificationBox const&>(*header_box.child_boxes()[color_header_box_index.value()]);
  198. use_this_color_box = new_header_box.precedence > current_color_box.precedence;
  199. }
  200. if (use_this_color_box)
  201. color_header_box_index = i;
  202. }
  203. }
  204. if (!image_header_box_index.has_value())
  205. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Expected Image Header box");
  206. if (!color_header_box_index.has_value())
  207. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Expected Color Specification box");
  208. auto const& image_header_box = static_cast<ISOBMFF::JPEG2000ImageHeaderBox const&>(*header_box.child_boxes()[image_header_box_index.value()]);
  209. context.size = { image_header_box.width, image_header_box.height };
  210. auto const& color_header_box = static_cast<ISOBMFF::JPEG2000ColorSpecificationBox const&>(*header_box.child_boxes()[color_header_box_index.value()]);
  211. if (color_header_box.method == 2 || color_header_box.method == 3)
  212. context.icc_data = color_header_box.icc_data.bytes();
  213. TRY(parse_codestream_main_header(context));
  214. return {};
  215. }
  216. bool JPEG2000ImageDecoderPlugin::sniff(ReadonlyBytes data)
  217. {
  218. return data.starts_with(jp2_id_string);
  219. }
  220. JPEG2000ImageDecoderPlugin::JPEG2000ImageDecoderPlugin()
  221. {
  222. m_context = make<JPEG2000LoadingContext>();
  223. }
  224. IntSize JPEG2000ImageDecoderPlugin::size()
  225. {
  226. return m_context->size;
  227. }
  228. ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> JPEG2000ImageDecoderPlugin::create(ReadonlyBytes data)
  229. {
  230. auto plugin = TRY(adopt_nonnull_own_or_enomem(new (nothrow) JPEG2000ImageDecoderPlugin()));
  231. TRY(decode_jpeg2000_header(*plugin->m_context, data));
  232. return plugin;
  233. }
  234. ErrorOr<ImageFrameDescriptor> JPEG2000ImageDecoderPlugin::frame(size_t index, Optional<IntSize>)
  235. {
  236. if (index != 0)
  237. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Invalid frame index");
  238. if (m_context->state == JPEG2000LoadingContext::State::Error)
  239. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Decoding failed");
  240. return Error::from_string_literal("JPEG2000ImageDecoderPlugin: Draw the rest of the owl");
  241. }
  242. ErrorOr<Optional<ReadonlyBytes>> JPEG2000ImageDecoderPlugin::icc_data()
  243. {
  244. return m_context->icc_data;
  245. }
  246. }