summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibGfx/JPGLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibGfx/JPGLoader.cpp')
-rw-r--r--Userland/Libraries/LibGfx/JPGLoader.cpp65
1 files changed, 34 insertions, 31 deletions
diff --git a/Userland/Libraries/LibGfx/JPGLoader.cpp b/Userland/Libraries/LibGfx/JPGLoader.cpp
index 1c2aefc209..e5591ad43d 100644
--- a/Userland/Libraries/LibGfx/JPGLoader.cpp
+++ b/Userland/Libraries/LibGfx/JPGLoader.cpp
@@ -122,7 +122,6 @@ struct MacroblockMeta {
};
struct ComponentSpec {
- u8 serial_id { 255 }; // In the interval [0, 3).
u8 id { 0 };
u8 hsample_factor { 1 }; // Horizontal sampling factor.
u8 vsample_factor { 1 }; // Vertical sampling factor.
@@ -187,7 +186,7 @@ struct JPGLoadingContext {
u8 hsample_factor { 0 };
u8 vsample_factor { 0 };
u8 component_count { 0 };
- HashMap<u8, ComponentSpec> components;
+ Vector<ComponentSpec, 3> components;
RefPtr<Gfx::Bitmap> bitmap;
u16 dc_reset_interval { 0 };
HashMap<u8, HuffmanTableSpec> dc_tables;
@@ -251,6 +250,18 @@ static Optional<u8> get_next_symbol(HuffmanStreamState& hstream, const HuffmanTa
return {};
}
+static inline i32* get_component(Macroblock& block, unsigned component)
+{
+ switch (component) {
+ case 0:
+ return block.y;
+ case 1:
+ return block.cb;
+ default:
+ return block.cr;
+ }
+}
+
/**
* Build the macroblocks possible by reading single (MCU) subsampled pair of CbCr.
* Depending on the sampling factors, we may not see triples of y, cb, cr in that
@@ -268,8 +279,8 @@ static Optional<u8> get_next_symbol(HuffmanStreamState& hstream, const HuffmanTa
*/
static bool build_macroblocks(JPGLoadingContext& context, Vector<Macroblock>& macroblocks, u32 hcursor, u32 vcursor)
{
- for (auto it = context.components.begin(); it != context.components.end(); ++it) {
- ComponentSpec& component = it->value;
+ for (unsigned component_i = 0; component_i < context.component_count; component_i++) {
+ auto& component = context.components[component_i];
if (component.dc_destination_id >= context.dc_tables.size())
return false;
@@ -306,8 +317,8 @@ static bool build_macroblocks(JPGLoadingContext& context, Vector<Macroblock>& ma
if (dc_length != 0 && dc_diff < (1 << (dc_length - 1)))
dc_diff -= (1 << dc_length) - 1;
- i32* select_component = component.serial_id == 0 ? block.y : (component.serial_id == 1 ? block.cb : block.cr);
- auto& previous_dc = context.previous_dc_values[component.serial_id];
+ auto select_component = get_component(block, component_i);
+ auto& previous_dc = context.previous_dc_values[component_i];
select_component[0] = previous_dc += dc_diff;
// Compute the AC coefficients.
@@ -502,21 +513,14 @@ static bool read_start_of_scan(InputMemoryStream& stream, JPGLoadingContext& con
}
for (int i = 0; i < component_count; i++) {
- ComponentSpec* component = nullptr;
u8 component_id = 0;
stream >> component_id;
if (stream.handle_any_error())
return false;
- auto it = context.components.find(component_id);
- if (it != context.components.end()) {
- component = &it->value;
- if (i != component->serial_id) {
- dbgln("JPEG decode failed (i != component->serial_id)");
- return false;
- }
- } else {
- dbgln_if(JPG_DEBUG, "{}: Unsupported component id: {}!", stream.offset(), component_id);
+ auto& component = context.components[i];
+ if (component.id != component_id) {
+ dbgln("JPEG decode failed (component.id != component_id)");
return false;
}
@@ -525,21 +529,21 @@ static bool read_start_of_scan(InputMemoryStream& stream, JPGLoadingContext& con
if (stream.handle_any_error())
return false;
- component->dc_destination_id = table_ids >> 4;
- component->ac_destination_id = table_ids & 0x0F;
+ component.dc_destination_id = table_ids >> 4;
+ component.ac_destination_id = table_ids & 0x0F;
if (context.dc_tables.size() != context.ac_tables.size()) {
dbgln_if(JPG_DEBUG, "{}: DC & AC table count mismatch!", stream.offset());
return false;
}
- if (!context.dc_tables.contains(component->dc_destination_id)) {
- dbgln_if(JPG_DEBUG, "DC table (id: {}) does not exist!", component->dc_destination_id);
+ if (!context.dc_tables.contains(component.dc_destination_id)) {
+ dbgln_if(JPG_DEBUG, "DC table (id: {}) does not exist!", component.dc_destination_id);
return false;
}
- if (!context.ac_tables.contains(component->ac_destination_id)) {
- dbgln_if(JPG_DEBUG, "AC table (id: {}) does not exist!", component->ac_destination_id);
+ if (!context.ac_tables.contains(component.ac_destination_id)) {
+ dbgln_if(JPG_DEBUG, "AC table (id: {}) does not exist!", component.ac_destination_id);
return false;
}
}
@@ -731,7 +735,6 @@ static bool read_start_of_frame(InputMemoryStream& stream, JPGLoadingContext& co
for (u8 i = 0; i < context.component_count; i++) {
ComponentSpec component;
- component.serial_id = i;
stream >> component.id;
if (stream.handle_any_error())
@@ -744,7 +747,7 @@ static bool read_start_of_frame(InputMemoryStream& stream, JPGLoadingContext& co
component.hsample_factor = subsample_factors >> 4;
component.vsample_factor = subsample_factors & 0x0F;
- if (component.serial_id == 0) {
+ if (i == 0) {
// By convention, downsampling is applied only on chroma components. So we should
// hope to see the maximum sampling factor in the luma component.
if (!validate_luma_and_modify_context(component, context)) {
@@ -772,7 +775,7 @@ static bool read_start_of_frame(InputMemoryStream& stream, JPGLoadingContext& co
return false;
}
- context.components.set(component.id, component);
+ context.components.append(move(component));
}
return true;
@@ -842,14 +845,14 @@ static void dequantize(JPGLoadingContext& context, Vector<Macroblock>& macrobloc
{
for (u32 vcursor = 0; vcursor < context.mblock_meta.vcount; vcursor += context.vsample_factor) {
for (u32 hcursor = 0; hcursor < context.mblock_meta.hcount; hcursor += context.hsample_factor) {
- for (auto it = context.components.begin(); it != context.components.end(); ++it) {
- auto& component = it->value;
+ for (u32 i = 0; i < context.component_count; i++) {
+ auto& component = context.components[i];
const u32* table = component.qtable_id == 0 ? context.luma_table : context.chroma_table;
for (u32 vfactor_i = 0; vfactor_i < component.vsample_factor; vfactor_i++) {
for (u32 hfactor_i = 0; hfactor_i < component.hsample_factor; hfactor_i++) {
u32 mb_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor);
Macroblock& block = macroblocks[mb_index];
- int* block_component = component.serial_id == 0 ? block.y : (component.serial_id == 1 ? block.cb : block.cr);
+ int* block_component = get_component(block, i);
for (u32 k = 0; k < 64; k++)
block_component[k] *= table[k];
}
@@ -878,13 +881,13 @@ static void inverse_dct(const JPGLoadingContext& context, Vector<Macroblock>& ma
for (u32 vcursor = 0; vcursor < context.mblock_meta.vcount; vcursor += context.vsample_factor) {
for (u32 hcursor = 0; hcursor < context.mblock_meta.hcount; hcursor += context.hsample_factor) {
- for (auto it = context.components.begin(); it != context.components.end(); ++it) {
- auto& component = it->value;
+ for (u32 component_i = 0; component_i < context.component_count; component_i++) {
+ auto& component = context.components[component_i];
for (u8 vfactor_i = 0; vfactor_i < component.vsample_factor; vfactor_i++) {
for (u8 hfactor_i = 0; hfactor_i < component.hsample_factor; hfactor_i++) {
u32 mb_index = (vcursor + vfactor_i) * context.mblock_meta.hpadded_count + (hfactor_i + hcursor);
Macroblock& block = macroblocks[mb_index];
- i32* block_component = component.serial_id == 0 ? block.y : (component.serial_id == 1 ? block.cb : block.cr);
+ i32* block_component = get_component(block, component_i);
for (u32 k = 0; k < 8; ++k) {
const float g0 = block_component[0 * 8 + k] * s0;
const float g1 = block_component[4 * 8 + k] * s4;