-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3d7a6b3
Showing
14 changed files
with
10,943 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
#include <cstdint> | ||
#include <cstdio> | ||
#include <vector> | ||
#include <fstream> | ||
#include <span> | ||
|
||
#include "common.h" | ||
#include "compress.h" | ||
#include "stb_image.h" | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
printf("998pack - PNG -> Microsoft 998 image format packer - © 2023 Alula\n\n"); | ||
|
||
if (argc == 1) | ||
{ | ||
printf("The output file(s) will be named <input without extension>.998\n\n"); | ||
|
||
printf("Usage: %s <file1> <file2> ... <fileN>\n", argv[0]); | ||
return 0; | ||
} | ||
|
||
printf("Processing %d files...\n", argc - 1); | ||
|
||
for (int i = 1; i < argc; i++) | ||
{ | ||
std::string input = argv[i]; | ||
std::string output = strip_ext(input) + ".998"; | ||
|
||
printf("Packing: %s -> %s\n", input.c_str(), output.c_str()); | ||
|
||
stbi_set_flip_vertically_on_load(true); | ||
int width, height, bpp; | ||
uint8_t *data = stbi_load(input.c_str(), &width, &height, &bpp, 4); | ||
|
||
if (!data) | ||
{ | ||
printf("Error: Failed to load image '%s': %s\n", input.c_str(), stbi_failure_reason()); | ||
return 1; | ||
} | ||
|
||
if (width > 0xffff || height > 0xffff) | ||
{ | ||
printf("Error: Image '%s' is too large: %dx%d\n", input.c_str(), width, height); | ||
return 1; | ||
} | ||
|
||
bool hasAlpha = false; | ||
for (int i = 0; i < width * height; i++) | ||
{ | ||
if (data[i * 4 + 3] != 0xFF) | ||
{ | ||
hasAlpha = true; | ||
break; | ||
} | ||
} | ||
|
||
File998 image; | ||
image.width = width; | ||
image.height = height; | ||
image.bpp = hasAlpha ? 32 : 24; | ||
|
||
auto stride = (image.width * (image.bpp >> 3) + 3) & 0xFFFFFFFC; | ||
|
||
size_t decompressedSize = image.height * stride; | ||
image.data.resize(decompressedSize, 0); | ||
|
||
for (int y = 0; y < image.height; y++) | ||
{ | ||
for (int x = 0; x < image.width; x++) | ||
{ | ||
int srcIdx = (y * image.width + x) * 4; | ||
int dstIdx = (y * stride + x * (image.bpp >> 3)); | ||
|
||
image.data[dstIdx + 0] = data[srcIdx + 2]; | ||
image.data[dstIdx + 1] = data[srcIdx + 1]; | ||
image.data[dstIdx + 2] = data[srcIdx + 0]; | ||
|
||
if (hasAlpha) | ||
image.data[dstIdx + 3] = data[srcIdx + 3]; | ||
} | ||
} | ||
|
||
stbi_image_free(data); | ||
|
||
auto compressed = MsoCompressLZW(image.data); | ||
|
||
std::ofstream out(output, std::ios::binary); | ||
auto write = [&]<typename T>(T &value) { | ||
out.write(reinterpret_cast<char *>(&value), sizeof(T)); | ||
}; | ||
|
||
write(image.width); | ||
write(image.height); | ||
write(image.bpp); | ||
out.write(reinterpret_cast<char *>(compressed.data()), compressed.size()); | ||
out.flush(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> | ||
<assemblyIdentity type="win32" name="998pack" version="6.0.0.0"/> | ||
<application> | ||
<windowsSettings> | ||
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage> | ||
</windowsSettings> | ||
</application> | ||
</assembly> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#include <cstdint> | ||
#include <cstdio> | ||
#include <vector> | ||
#include <fstream> | ||
#include <span> | ||
#include <ranges> | ||
#include <array> | ||
|
||
#include "common.h" | ||
#include "compress.h" | ||
#include "stb_image_write.h" | ||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
printf("998unpack - Microsoft 998 -> PNG image format unpacker - © 2023 Alula\n\n"); | ||
|
||
if (argc == 1) | ||
{ | ||
printf("The output file(s) will be named <input without extension>.png\n\n"); | ||
|
||
printf("Usage: %s <file1> <file2> ... <fileN>\n", argv[0]); | ||
return 0; | ||
} | ||
|
||
printf("Processing %d files...\n", argc - 1); | ||
|
||
for (int i = 1; i < argc; i++) | ||
{ | ||
std::string input = argv[i]; | ||
std::string output = strip_ext(input) + ".png"; | ||
|
||
printf("Unpacking: %s -> %s\n", input.c_str(), output.c_str()); | ||
|
||
std::ifstream file(input, std::ios::binary); | ||
|
||
File998 image{}; | ||
|
||
auto read = [&]<typename T>(T &value) | ||
{ | ||
file.read(reinterpret_cast<char *>(&value), sizeof(T)); | ||
}; | ||
|
||
bool compressed = true; | ||
|
||
read(image.width); | ||
read(image.height); | ||
read(image.bpp); | ||
|
||
std::array<uint32_t, 256> palette; | ||
|
||
// idfk what this format is and I don't want to bother | ||
// if (image.bpp == 0) | ||
// { | ||
// uint8_t unknown; | ||
// read(unknown); | ||
// image.bpp = 8; | ||
// } | ||
// else | ||
if (image.bpp == 1) | ||
{ | ||
image.bpp = 8; | ||
uint8_t entry_count; | ||
read(entry_count); | ||
|
||
for (int i = 0; i < entry_count; i++) | ||
{ | ||
uint32_t color = 0; | ||
read(color); | ||
|
||
if ((color & 0xff000000) == 0) | ||
color |= 0xff000000; | ||
|
||
uint32_t oc = color; | ||
color &= 0xff00ff00; | ||
color |= ((oc >> 16) & 0xff); | ||
color |= ((oc << 16) & 0xff0000); | ||
|
||
palette[i] = color; | ||
} | ||
} | ||
else if (image.bpp != 24 && image.bpp != 32) | ||
{ | ||
printf("Error: Invalid color depth, unsupported or not a 998 file?\n"); | ||
return 1; | ||
} | ||
|
||
auto stride = (image.width * (image.bpp >> 3) + 3) & 0xFFFFFFFC; | ||
|
||
size_t decompressedSize = image.height * stride; | ||
image.data.resize(decompressedSize, 0); | ||
|
||
std::vector<uint8_t> compressedData; | ||
auto pos = file.tellg(); | ||
file.seekg(0, std::ios::end); | ||
auto end = file.tellg(); | ||
file.seekg(pos); | ||
|
||
compressedData.resize(end - pos); | ||
file.read(reinterpret_cast<char *>(compressedData.data()), compressedData.size()); | ||
|
||
if (compressed) | ||
{ | ||
MsoUncompressLZW(compressedData, image.data); | ||
} | ||
else | ||
{ | ||
image.data = std::move(compressedData); | ||
image.data.resize(decompressedSize); | ||
} | ||
|
||
stbi_flip_vertically_on_write(1); | ||
|
||
if (image.bpp == 8) | ||
{ | ||
std::vector<uint8_t> pixels = std::move(image.data); | ||
image.bpp = 32; | ||
|
||
stride = (image.width * (image.bpp >> 3) + 3) & 0xFFFFFFFC; | ||
decompressedSize = image.height * stride; | ||
|
||
image.data.resize(decompressedSize); | ||
|
||
uint32_t *data = reinterpret_cast<uint32_t *>(image.data.data()); | ||
|
||
for (uint32_t i = 0; i < static_cast<uint32_t>(image.width) * static_cast<uint32_t>(image.height); i++) | ||
{ | ||
data[i] = palette[pixels[i]]; | ||
} | ||
} | ||
else | ||
{ | ||
// swap RGB -> BGR | ||
for (uint32_t y = 0; y < image.height; y++) | ||
{ | ||
for (uint32_t x = 0; x < image.width; x++) | ||
{ | ||
size_t offset = y * stride + x * (image.bpp / 8); | ||
std::swap(image.data[offset + 0], image.data[offset + 2]); | ||
} | ||
} | ||
} | ||
|
||
stbi_write_png(output.c_str(), image.width, image.height, image.bpp / 8, image.data.data(), stride); | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> | ||
<assemblyIdentity type="win32" name="998pack" version="6.0.0.0"/> | ||
<application> | ||
<windowsSettings> | ||
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage> | ||
</windowsSettings> | ||
</application> | ||
</assembly> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
project(988unpack LANGUAGES CXX) | ||
|
||
cmake_minimum_required(VERSION 3.18) | ||
|
||
set(CMAKE_CXX_STANDARD 20) | ||
set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
|
||
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>") | ||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>") | ||
|
||
add_library(common STATIC stb_image.cpp compress.cpp) | ||
|
||
add_executable(998pack 998pack.cpp) | ||
add_executable(998unpack 998unpack.cpp) | ||
target_link_libraries(998pack common) | ||
target_link_libraries(998unpack common) | ||
|
||
if(MSVC) | ||
ADD_CUSTOM_COMMAND( | ||
TARGET 998pack | ||
POST_BUILD | ||
DEPENDS | ||
COMMAND mt.exe -manifest "${CMAKE_SOURCE_DIR}/998pack.manifest.xml" -inputresource:"$<TARGET_FILE:998pack>"\;\#1 -updateresource:"$<TARGET_FILE:998pack>"\;\#1 | ||
) | ||
ENDIF(MSVC) | ||
|
||
if(MSVC) | ||
ADD_CUSTOM_COMMAND( | ||
TARGET 998pack | ||
POST_BUILD | ||
DEPENDS | ||
COMMAND mt.exe -manifest "${CMAKE_SOURCE_DIR}/998unpack.manifest.xml" -inputresource:"$<TARGET_FILE:998unpack>"\;\#1 -updateresource:"$<TARGET_FILE:998unpack>"\;\#1 | ||
) | ||
ENDIF(MSVC) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Copyright 2023 Alula | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# 998tools | ||
|
||
Toolkit for manipulating Microsoft 998 image format files, used in Microsoft Office and UIRibbon.dll. | ||
|
||
## Usage | ||
|
||
### 998pack | ||
|
||
``` | ||
The output file(s) will be named <input without extension>.998 | ||
Usage: 998pack <file1> <file2> ... <fileN> | ||
``` | ||
|
||
### 998unpack | ||
|
||
``` | ||
The output file(s) will be named <input without extension>.png | ||
Usage: 998unpack <file1> <file2> ... <fileN> | ||
``` |
Oops, something went wrong.