aboutsummaryrefslogtreecommitdiff
path: root/libtiled/compression.cpp
diff options
context:
space:
mode:
authorSamu Laaksonen <laaksonen.sj@gmail.com>2012-09-25 20:00:41 +0300
committerSamu Laaksonen <laaksonen.sj@gmail.com>2012-09-25 20:00:41 +0300
commit685fe05def77b039221edf06c74af74915d536c5 (patch)
tree9c1a14b8f68bc0f801bdec3edc447d04fdbf7a4c /libtiled/compression.cpp
parent29eabac0670574efd384182c065f53d08c42a483 (diff)
downloadprism-685fe05def77b039221edf06c74af74915d536c5.tar.gz
prism-685fe05def77b039221edf06c74af74915d536c5.zip
Initial code commit
Added some stuff for project base - tiled sources - few Qt based classes for gfx
Diffstat (limited to 'libtiled/compression.cpp')
-rw-r--r--libtiled/compression.cpp162
1 files changed, 162 insertions, 0 deletions
diff --git a/libtiled/compression.cpp b/libtiled/compression.cpp
new file mode 100644
index 0000000..3cf6f46
--- /dev/null
+++ b/libtiled/compression.cpp
@@ -0,0 +1,162 @@
+/*
+ * compression.cpp
+ * Copyright 2008, Thorbjørn Lindeijer <thorbjorn@lindeijer.nl>
+ *
+ * This file is part of libtiled.
+ *
+ * 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 THE CONTRIBUTORS ``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 THE 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 "compression.h"
+
+#include <zlib.h>
+#include <QByteArray>
+#include <QDebug>
+
+using namespace Tiled;
+
+// TODO: Improve error reporting by showing these errors in the user interface
+static void logZlibError(int error)
+{
+ switch (error)
+ {
+ case Z_MEM_ERROR:
+ qDebug() << "Out of memory while (de)compressing data!";
+ break;
+ case Z_VERSION_ERROR:
+ qDebug() << "Incompatible zlib version!";
+ break;
+ case Z_NEED_DICT:
+ case Z_DATA_ERROR:
+ qDebug() << "Incorrect zlib compressed data!";
+ break;
+ default:
+ qDebug() << "Unknown error while (de)compressing data!";
+ }
+}
+
+QByteArray Tiled::decompress(const QByteArray &data, int expectedSize)
+{
+ QByteArray out;
+ out.resize(expectedSize);
+ z_stream strm;
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.next_in = (Bytef *) data.data();
+ strm.avail_in = data.length();
+ strm.next_out = (Bytef *) out.data();
+ strm.avail_out = out.size();
+
+ int ret = inflateInit2(&strm, 15 + 32);
+
+ if (ret != Z_OK) {
+ logZlibError(ret);
+ return QByteArray();
+ }
+
+ do {
+ ret = inflate(&strm, Z_SYNC_FLUSH);
+
+ switch (ret) {
+ case Z_NEED_DICT:
+ case Z_STREAM_ERROR:
+ ret = Z_DATA_ERROR;
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ inflateEnd(&strm);
+ logZlibError(ret);
+ return QByteArray();
+ }
+
+ if (ret != Z_STREAM_END) {
+ int oldSize = out.size();
+ out.resize(out.size() * 2);
+
+ strm.next_out = (Bytef *)(out.data() + oldSize);
+ strm.avail_out = oldSize;
+ }
+ }
+ while (ret != Z_STREAM_END);
+
+ if (strm.avail_in != 0) {
+ logZlibError(Z_DATA_ERROR);
+ return QByteArray();
+ }
+
+ const int outLength = out.size() - strm.avail_out;
+ inflateEnd(&strm);
+
+ out.resize(outLength);
+ return out;
+}
+
+QByteArray Tiled::compress(const QByteArray &data, CompressionMethod method)
+{
+ QByteArray out;
+ out.resize(1024);
+ int err;
+ z_stream strm;
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.next_in = (Bytef *) data.data();
+ strm.avail_in = data.length();
+ strm.next_out = (Bytef *) out.data();
+ strm.avail_out = out.size();
+
+ const int windowBits = (method == Gzip) ? 15 + 16 : 15;
+
+ err = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowBits,
+ 8, Z_DEFAULT_STRATEGY);
+ if (err != Z_OK) {
+ logZlibError(err);
+ return QByteArray();
+ }
+
+ do {
+ err = deflate(&strm, Z_FINISH);
+ Q_ASSERT(err != Z_STREAM_ERROR);
+
+ if (err == Z_OK) {
+ // More output space needed
+ int oldSize = out.size();
+ out.resize(out.size() * 2);
+
+ strm.next_out = (Bytef *)(out.data() + oldSize);
+ strm.avail_out = oldSize;
+ }
+ } while (err == Z_OK);
+
+ if (err != Z_STREAM_END) {
+ logZlibError(err);
+ deflateEnd(&strm);
+ return QByteArray();
+ }
+
+ const int outLength = out.size() - strm.avail_out;
+ deflateEnd(&strm);
+
+ out.resize(outLength);
+ return out;
+}