Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TEST: PNG/Deflate compression option for sprites #2111

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ target_sources(common
util/path.cpp
util/path_ex.cpp
util/path.h
util/png.cpp
util/png.h
util/proxystream.cpp
util/proxystream.h
util/resourcecache.h
Expand Down
4 changes: 4 additions & 0 deletions Common/ac/spritefile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,8 @@ HError SpriteFile::LoadSprite(sprkey_t index, Common::Bitmap *&sprite)
break;
case kSprCompress_LZW: lzw_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get(), in_data_size);
break;
case kSprCompress_PNG: png_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get(), in_data_size);
break;
default: assert(!"Unsupported compression type!"); break;
}
// TODO: test that not more than data_size was read!
Expand Down Expand Up @@ -699,6 +701,8 @@ void SpriteFileWriter::WriteBitmap(Bitmap *image)
break;
case kSprCompress_LZW: lzw_compress(im_data.Buf, im_data.Size, im_data.BPP, &mems);
break;
case kSprCompress_PNG: png_compress(im_data.Buf, im_data.Size, im_data.BPP, &mems);
break;
default: assert(!"Unsupported compression type!"); break;
}
// mark to write as a plain byte array
Expand Down
3 changes: 2 additions & 1 deletion Common/ac/spritefile.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ enum SpriteCompression
{
kSprCompress_None = 0,
kSprCompress_RLE,
kSprCompress_LZW
kSprCompress_LZW,
kSprCompress_PNG
};

typedef int32_t sprkey_t;
Expand Down
23 changes: 18 additions & 5 deletions Common/util/compress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
// http://www.opensource.org/licenses/artistic-license-2.0.php
//
//=============================================================================
#ifdef _MANAGED
// ensure this doesn't get compiled to .NET IL
#pragma unmanaged
#endif

#include "util/compress.h"
#include <stdlib.h>
#include <stdio.h>
Expand All @@ -27,6 +22,7 @@
#if AGS_PLATFORM_ENDIAN_BIG
#include "util/bbop.h"
#endif
#include "util/png.h"

using namespace AGS::Common;

Expand Down Expand Up @@ -449,3 +445,20 @@ std::unique_ptr<Bitmap> load_lzw(Stream *in, int dst_bpp, RGB (*pal)[256])

return bmm;
}

//-----------------------------------------------------------------------------
// PNG
//-----------------------------------------------------------------------------

void png_compress(const uint8_t* data, size_t data_sz, int /*image_bpp*/, Stream* out)
{
MemoryStream mem_in(data, data_sz);
pngcompress(&mem_in, out);
}

void png_decompress(uint8_t* data, size_t data_sz, int /*image_bpp*/, Stream* in, size_t in_sz)
{
std::vector<uint8_t> in_buf(in_sz);
in->Read(in_buf.data(), in_sz);
pngexpand(in_buf.data(), in_sz, data, data_sz);
}
5 changes: 5 additions & 0 deletions Common/util/compress.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,9 @@ void save_lzw(Common::Stream *out, const Common::Bitmap *bmpp, const RGB (*pal)[
// Loads bitmap decompressing
std::unique_ptr<Common::Bitmap> load_lzw(Common::Stream *in, int dst_bpp, RGB (*pal)[256] = nullptr);

// PNG compression
void png_compress(const uint8_t* data, size_t data_sz, int image_bpp, Common::Stream* out);
void png_decompress(uint8_t* data, size_t data_sz, int image_bpp, Common::Stream* in, size_t in_sz);


#endif // __AC_COMPRESS_H
5 changes: 0 additions & 5 deletions Common/util/lzw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@

using namespace AGS::Common;

#ifdef _MANAGED
// ensure this doesn't get compiled to .NET IL
#pragma unmanaged
#endif

int insert(int, int);
void _delete(int);

Expand Down
6 changes: 2 additions & 4 deletions Common/util/lzw.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@
#define __AGS_CN_UTIL__LZW_H

#include "core/types.h"
#include "util/stream.h"

namespace AGS { namespace Common { class Stream; } }
using namespace AGS; // FIXME later

bool lzwcompress(Common::Stream *lzw_in, Common::Stream *out);
bool lzwcompress(AGS::Common::Stream *lzw_in, AGS::Common::Stream *out);
// Expands lzw-compressed data from src to dst.
// the dst buffer should be large enough, or the uncompression will not be complete.
bool lzwexpand(const uint8_t *src, size_t src_sz, uint8_t *dst, size_t dst_sz);
Expand Down
104 changes: 104 additions & 0 deletions Common/util/png.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//=============================================================================
//
// Adventure Game Studio (AGS)
//
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
// The full list of copyright holders can be found in the Copyright.txt
// file, which is part of this source code distribution.
//
// The AGS source code is provided under the Artistic License 2.0.
// A copy of this license can be found in the file License.txt and at
// http://www.opensource.org/licenses/artistic-license-2.0.php
//
//=============================================================================
//
// PNG compression.
//
//=============================================================================
#include "util/png.h"
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include "util/bbop.h"
#include "util/stream.h"

using namespace AGS::Common;

bool pngcompress(Stream* input, Stream* output) {
z_stream stream;
memset(&stream, 0, sizeof(stream));

int ret = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK) {
std::cerr << "Error initializing compression" << std::endl;
return false;
}

stream.data_type = Z_BINARY;

char inbuf[1024];
char outbuf[1024];

stream.avail_in = input->Read(inbuf, sizeof(inbuf));
while (stream.avail_in > 0) {
stream.next_in = (Bytef*)inbuf;
int flush = input->EOS() ? Z_FINISH : Z_NO_FLUSH;

do {
stream.next_out = (Bytef*)outbuf;
stream.avail_out = sizeof(outbuf);
ret = deflate(&stream, flush);
assert(ret != Z_STREAM_ERROR);
int have = sizeof(outbuf) - stream.avail_out;
output->Write(outbuf, have);
} while (stream.avail_out == 0);

stream.avail_in = input->Read(inbuf, sizeof(inbuf));
}

(void)deflateEnd(&stream);

return true;
}

bool pngexpand(const uint8_t* src, size_t src_sz, uint8_t* dst, size_t dst_sz) {
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.avail_in = 0;
stream.next_in = Z_NULL;

int ret = inflateInit(&stream);
if (ret != Z_OK) {
std::cerr << "Error initializing decompression" << std::endl;
return false;
}

stream.next_in = (Bytef*)src;
stream.avail_in = src_sz;
stream.next_out = dst;
stream.avail_out = dst_sz;

do {
ret = inflate(&stream, Z_FINISH);
switch (ret) {
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
case Z_BUF_ERROR:
std::cerr << "Error decompressing data" << std::endl;
(void)inflateEnd(&stream);
return false;
default:
stream.next_out = dst + (dst_sz - stream.avail_out);
break;
}
} while (stream.avail_out > 0);

(void)inflateEnd(&stream);

return true;
}
29 changes: 29 additions & 0 deletions Common/util/png.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//=============================================================================
//
// Adventure Game Studio (AGS)
//
// Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
// The full list of copyright holders can be found in the Copyright.txt
// file, which is part of this source code distribution.
//
// The AGS source code is provided under the Artistic License 2.0.
// A copy of this license can be found in the file License.txt and at
// http://www.opensource.org/licenses/artistic-license-2.0.php
//
//=============================================================================
//
// PNG (un)compression functions.
//
//=============================================================================
#ifndef __AGS_CN_UTIL__PNG_H
#define __AGS_CN_UTIL__PNG_H

#include "core/types.h"
#include "util/stream.h"

bool pngcompress(AGS::Common::Stream* input, AGS::Common::Stream* output);
// Expands lzw-compressed data from src to dst.
// the dst buffer should be large enough, or the uncompression will not be complete.
bool pngexpand(const uint8_t* src, size_t src_sz, uint8_t* dst, size_t dst_sz);

#endif // __AGS_CN_UTIL__PNG_H
3 changes: 2 additions & 1 deletion Editor/AGS.Types/Enums/SpriteCompression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum SpriteCompression
{
None,
RLE,
LZW
LZW,
PNG, // this means DEFLATE
}
}
1 change: 1 addition & 0 deletions Engine/Makefile-defs.linux
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ CXXFLAGS := -std=c++11 -Werror=delete-non-virtual-dtor $(CXXFLAGS)
LIBS += $(FT_LDFLAGS)
LIBS += $(shell pkg-config --libs ogg)
LIBS += $(shell pkg-config --libs theora)
LIBS += $(shell pkg-config --libs zlib)

ifeq ($(USE_TREMOR), 1)
LIBS += -lvorbisidec
Expand Down
14 changes: 14 additions & 0 deletions Solutions/Common.Lib/Common.Lib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -128,39 +128,51 @@
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_MD|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_MD|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_MD|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_MD|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_XP|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_XP|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_XP|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_XP|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\zlib.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
Expand Down Expand Up @@ -608,6 +620,7 @@
<ClCompile Include="..\..\Common\util\multifilelib.cpp" />
<ClCompile Include="..\..\Common\util\path.cpp" />
<ClCompile Include="..\..\Common\util\path_ex.cpp" />
<ClCompile Include="..\..\Common\util\png.cpp" />
<ClCompile Include="..\..\Common\util\proxystream.cpp" />
<ClCompile Include="..\..\Common\util\stdio_compat.c" />
<ClCompile Include="..\..\Common\util\stream.cpp" />
Expand Down Expand Up @@ -769,6 +782,7 @@
<ClInclude Include="..\..\Common\util\memory_compat.h" />
<ClInclude Include="..\..\Common\util\multifilelib.h" />
<ClInclude Include="..\..\Common\util\path.h" />
<ClInclude Include="..\..\Common\util\png.h" />
<ClInclude Include="..\..\Common\util\proxystream.h" />
<ClInclude Include="..\..\Common\util\resourcecache.h" />
<ClInclude Include="..\..\Common\util\scaling.h" />
Expand Down
6 changes: 6 additions & 0 deletions Solutions/Common.Lib/Common.Lib.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,9 @@
<ClCompile Include="..\..\Common\script\cc_common.cpp">
<Filter>Source Files\script</Filter>
</ClCompile>
<ClCompile Include="..\..\Common\util\png.cpp">
<Filter>Source Files\util</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Common\ac\audiocliptype.h">
Expand Down Expand Up @@ -829,5 +832,8 @@
<ClInclude Include="..\..\Common\util\resourcecache.h">
<Filter>Header Files\util</Filter>
</ClInclude>
<ClInclude Include="..\..\Common\util\png.h">
<Filter>Header Files\util</Filter>
</ClInclude>
</ItemGroup>
</Project>
20 changes: 20 additions & 0 deletions Solutions/zlib.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(ZLIB_INCLUDE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(ZLIB_LIB);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Lib>
<AdditionalLibraryDirectories>$(ZLIB_LIB);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Lib>
</ItemDefinitionGroup>
<ItemGroup />
</Project>