summaryrefslogtreecommitdiff
path: root/indra/llkdu/llblockdecoder.cpp
diff options
context:
space:
mode:
authorMerov Linden <merov@lindenlab.com>2010-11-11 09:33:29 -0800
committerMerov Linden <merov@lindenlab.com>2010-11-11 09:33:29 -0800
commit94f44437d7e7ccb54f227e35523fa8a4e027d7d2 (patch)
treedd899aa6e98b2c10b22fa0db58cfca866a0322de /indra/llkdu/llblockdecoder.cpp
parentee8df375449e97476408417ec6dea0d6a8853d73 (diff)
parent0e07758b540374aa421d2938ce5ed13e2b9eefe4 (diff)
STORM-151 : merge kdu static linking, add indra/llkdu implementation. Doesn't build yet.
Diffstat (limited to 'indra/llkdu/llblockdecoder.cpp')
-rw-r--r--indra/llkdu/llblockdecoder.cpp273
1 files changed, 273 insertions, 0 deletions
diff --git a/indra/llkdu/llblockdecoder.cpp b/indra/llkdu/llblockdecoder.cpp
new file mode 100644
index 0000000000..b4ddb2fba2
--- /dev/null
+++ b/indra/llkdu/llblockdecoder.cpp
@@ -0,0 +1,273 @@
+ /**
+ * @file llblockdecoder.cpp
+ * @brief Image block decompression
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llblockdecoder.h"
+
+// KDU core header files
+#include "kdu/kdu_elementary.h"
+#include "kdu/kdu_messaging.h"
+#include "kdu/kdu_params.h"
+#include "kdu/kdu_compressed.h"
+#include "kdu/kdu_sample_processing.h"
+
+// KDU utility functions.
+#include "kde_flow_control.h"
+
+#include "llkdumem.h"
+
+#include "llblockdata.h"
+#include "llerror.h"
+
+
+BOOL LLBlockDecoder::decodeU32(LLBlockDataU32 &block_data, U8 *source_data, const U32 source_size) const
+{
+ U32 width, height;
+
+ llassert(source_data);
+
+ LLKDUMemSource source(source_data, source_size);
+
+ source.reset();
+
+ kdu_codestream codestream;
+
+ codestream.create(&source);
+ codestream.set_fast();
+
+ kdu_dims dims;
+ codestream.get_dims(0,dims);
+ llassert(codestream.get_num_components() == 1);
+
+ width = dims.size.x;
+ height = dims.size.y;
+
+ // Assumes U32 data.
+ U8 *output = block_data.getData();
+
+ kdu_dims tile_indices;
+ codestream.get_valid_tiles(tile_indices);
+
+ kdu_coords tpos;
+ tpos.x = 0;
+ tpos.y = 0;
+
+ // Now we are ready to walk through the tiles processing them one-by-one.
+ while (tpos.y < tile_indices.size.y)
+ {
+ while (tpos.x < tile_indices.size.x)
+ {
+ kdu_tile tile = codestream.open_tile(tpos+tile_indices.pos);
+
+ kdu_resolution res = tile.access_component(0).access_resolution();
+ kdu_dims tile_dims;
+ res.get_dims(tile_dims);
+ kdu_coords offset = tile_dims.pos - dims.pos;
+ int row_gap = block_data.getRowStride(); // inter-row separation
+ kdu_byte *buf = output + offset.y*row_gap + offset.x*4;
+
+ kdu_tile_comp tile_comp = tile.access_component(0);
+ bool reversible = tile_comp.get_reversible();
+ U32 precision = tile_comp.get_bit_depth();
+ U32 precision_scale = 1 << precision;
+ llassert(precision >= 8); // Else would have used 16 bit representation
+
+ kdu_resolution comp_res = tile_comp.access_resolution(); // Get top resolution
+ kdu_dims comp_dims;
+ comp_res.get_dims(comp_dims);
+
+ bool use_shorts = (tile_comp.get_bit_depth(true) <= 16);
+
+ kdu_line_buf line;
+ kdu_sample_allocator allocator;
+ kdu_pull_ifc engine;
+
+ line.pre_create(&allocator, comp_dims.size.x, reversible, use_shorts);
+ if (res.which() == 0) // No DWT levels used
+ {
+ engine = kdu_decoder(res.access_subband(LL_BAND), &allocator, use_shorts);
+ }
+ else
+ {
+ engine = kdu_synthesis(res, &allocator, use_shorts);
+ }
+ allocator.finalize(); // Actually creates buffering resources
+
+ line.create(); // Grabs resources from the allocator.
+
+ // Do the actual processing
+ while (tile_dims.size.y--)
+ {
+ engine.pull(line, true);
+ int width = line.get_width();
+
+ llassert(line.get_buf32());
+ llassert(!line.is_absolute());
+ // Decompressed samples have a 32-bit representation (integer or float)
+ kdu_sample32 *sp = line.get_buf32();
+ // Transferring normalized floating point data.
+ U32 *dest_u32 = (U32 *)buf;
+ for (; width > 0; width--, sp++, dest_u32++)
+ {
+ if (sp->fval < -0.5f)
+ {
+ *dest_u32 = 0;
+ }
+ else
+ {
+ *dest_u32 = (U32)((sp->fval + 0.5f)*precision_scale);
+ }
+ }
+ buf += row_gap;
+ }
+ engine.destroy();
+ tile.close();
+ tpos.x++;
+ }
+ tpos.y++;
+ tpos.x = 0;
+ }
+ codestream.destroy();
+
+ return TRUE;
+}
+
+BOOL LLBlockDecoder::decodeF32(LLBlockDataF32 &block_data, U8 *source_data, const U32 source_size, const F32 min, const F32 max) const
+{
+ U32 width, height;
+ F32 range, range_inv, float_offset;
+ bool use_shorts = false;
+
+ range = max - min;
+ range_inv = 1.f / range;
+ float_offset = 0.5f*(max + min);
+
+ llassert(source_data);
+
+ LLKDUMemSource source(source_data, source_size);
+
+ source.reset();
+
+ kdu_codestream codestream;
+
+ codestream.create(&source);
+ codestream.set_fast();
+
+ kdu_dims dims;
+ codestream.get_dims(0,dims);
+ llassert(codestream.get_num_components() == 1);
+
+ width = dims.size.x;
+ height = dims.size.y;
+
+ // Assumes F32 data.
+ U8 *output = block_data.getData();
+
+ kdu_dims tile_indices;
+ codestream.get_valid_tiles(tile_indices);
+
+ kdu_coords tpos;
+ tpos.x = 0;
+ tpos.y = 0;
+
+ // Now we are ready to walk through the tiles processing them one-by-one.
+ while (tpos.y < tile_indices.size.y)
+ {
+ while (tpos.x < tile_indices.size.x)
+ {
+ kdu_tile tile = codestream.open_tile(tpos+tile_indices.pos);
+
+ kdu_resolution res = tile.access_component(0).access_resolution();
+ kdu_dims tile_dims;
+ res.get_dims(tile_dims);
+ kdu_coords offset = tile_dims.pos - dims.pos;
+ int row_gap = block_data.getRowStride(); // inter-row separation
+ kdu_byte *buf = output + offset.y*row_gap + offset.x*4;
+
+ kdu_tile_comp tile_comp = tile.access_component(0);
+ bool reversible = tile_comp.get_reversible();
+
+ kdu_resolution comp_res = tile_comp.access_resolution(); // Get top resolution
+ kdu_dims comp_dims;
+ comp_res.get_dims(comp_dims);
+
+ kdu_line_buf line;
+ kdu_sample_allocator allocator;
+ kdu_pull_ifc engine;
+
+ line.pre_create(&allocator, comp_dims.size.x, reversible, use_shorts);
+ if (res.which() == 0) // No DWT levels used
+ {
+ engine = kdu_decoder(res.access_subband(LL_BAND), &allocator, use_shorts);
+ }
+ else
+ {
+ engine = kdu_synthesis(res, &allocator, use_shorts);
+ }
+ allocator.finalize(); // Actually creates buffering resources
+
+ line.create(); // Grabs resources from the allocator.
+
+ // Do the actual processing
+ while (tile_dims.size.y--)
+ {
+ engine.pull(line, true);
+ int width = line.get_width();
+
+ llassert(line.get_buf32());
+ llassert(!line.is_absolute());
+ // Decompressed samples have a 32-bit representation (integer or float)
+ kdu_sample32 *sp = line.get_buf32();
+ // Transferring normalized floating point data.
+ F32 *dest_f32 = (F32 *)buf;
+ for (; width > 0; width--, sp++, dest_f32++)
+ {
+ if (sp->fval < -0.5f)
+ {
+ *dest_f32 = min;
+ }
+ else if (sp->fval > 0.5f)
+ {
+ *dest_f32 = max;
+ }
+ else
+ {
+ *dest_f32 = (sp->fval) * range + float_offset;
+ }
+ }
+ buf += row_gap;
+ }
+ engine.destroy();
+ tile.close();
+ tpos.x++;
+ }
+ tpos.y++;
+ tpos.x = 0;
+ }
+ codestream.destroy();
+ return TRUE;
+}