aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorsarbes <sarbes@kodi.tv>2024-09-17 22:21:51 +0200
committerGitHub <noreply@github.com>2024-09-17 22:21:51 +0200
commit51bef9501591cc8a753c91f97b8f554ad73049cb (patch)
tree29efb4ae2c5930b3c0536b46e2bdfe72abbd03f1 /tools
parentc782fe5150828dbb99f0ab75546f9db425a9f8e7 (diff)
Add single/dual channel texture support to XBT textures (#25714)
Add single/dual channel texture support to XBT textures
Diffstat (limited to 'tools')
-rw-r--r--tools/depends/native/TexturePacker/src/TexturePacker.cpp167
-rw-r--r--tools/depends/native/TexturePacker/src/decoder/IDecoder.h7
2 files changed, 141 insertions, 33 deletions
diff --git a/tools/depends/native/TexturePacker/src/TexturePacker.cpp b/tools/depends/native/TexturePacker/src/TexturePacker.cpp
index 5c8304c5cb..9d4f270b23 100644
--- a/tools/depends/native/TexturePacker/src/TexturePacker.cpp
+++ b/tools/depends/native/TexturePacker/src/TexturePacker.cpp
@@ -56,40 +56,30 @@
namespace
{
-const char *GetFormatString(unsigned int format)
+const char* GetFormatString(KD_TEX_FMT format)
{
switch (format)
{
- case XB_FMT_DXT1:
- return "DXT1 ";
- case XB_FMT_DXT3:
- return "DXT3 ";
- case XB_FMT_DXT5:
- return "DXT5 ";
- case XB_FMT_DXT5_YCoCg:
- return "YCoCg";
- case XB_FMT_A8R8G8B8:
- return "ARGB ";
- case XB_FMT_A8:
- return "A8 ";
- default:
- return "?????";
+ case KD_TEX_FMT_SDR_R8:
+ return "R8 ";
+ case KD_TEX_FMT_SDR_RG8:
+ return "RG8 ";
+ case KD_TEX_FMT_SDR_RGBA8:
+ return "RGBA8";
+ case KD_TEX_FMT_SDR_BGRA8:
+ return "BGRA8";
+ default:
+ return "?????";
}
}
-bool HasAlpha(unsigned char* argb, unsigned int width, unsigned int height)
-{
- unsigned char* p = argb + 3; // offset of alpha
- for (unsigned int i = 0; i < 4 * width * height; i += 4)
- {
- if (p[i] != 0xff)
- return true;
- }
- return false;
-}
-
void Usage()
{
+ puts("Texture Packer Version 3");
+ puts("");
+ puts("Tool to pack XBT 3 texture files, used in Kodi Piers (v22).");
+ puts("Accepts the following file formats as input: PNG (preferred), JPG and GIF.");
+ puts("");
puts("Usage:");
puts(" -help Show this screen.");
puts(" -input <dir> Input directory. Default: current dir");
@@ -122,6 +112,10 @@ private:
bool CheckDupe(MD5Context* ctx, unsigned int pos);
+ void ConvertToSingleChannel(RGBAImage& image, uint32_t channel);
+ void ConvertToDualChannel(RGBAImage& image);
+ void ReduceChannels(RGBAImage& image);
+
DecoderManager decoderManager;
std::map<std::string, unsigned int> m_hashes;
@@ -196,12 +190,13 @@ CXBTFFrame TexturePacker::CreateXBTFFrame(DecodedFrame& decodedFrame, CXBTFWrite
const unsigned int delay = decodedFrame.delay;
const unsigned int width = decodedFrame.rgbaImage.width;
const unsigned int height = decodedFrame.rgbaImage.height;
- const unsigned int size = width * height * 4;
- const XB_FMT format = XB_FMT_A8R8G8B8;
+ const uint32_t bpp = decodedFrame.rgbaImage.bbp;
+ const unsigned int size = width * height * (bpp / 8);
+ const uint32_t format = static_cast<uint32_t>(decodedFrame.rgbaImage.textureFormat) |
+ static_cast<uint32_t>(decodedFrame.rgbaImage.textureAlpha) |
+ static_cast<uint32_t>(decodedFrame.rgbaImage.textureSwizzle);
unsigned char* data = (unsigned char*)decodedFrame.rgbaImage.pixels.data();
- const bool hasAlpha = HasAlpha(data, width, height);
-
CXBTFFrame frame;
lzo_uint packedSize = size;
@@ -246,7 +241,7 @@ CXBTFFrame TexturePacker::CreateXBTFFrame(DecodedFrame& decodedFrame, CXBTFWrite
frame.SetUnpackedSize(size);
frame.SetWidth(width);
frame.SetHeight(height);
- frame.SetFormat(hasAlpha ? format : static_cast<XB_FMT>(format | XB_FMT_OPAQUE));
+ frame.SetFormat(format);
frame.SetDuration(delay);
return frame;
}
@@ -278,6 +273,111 @@ bool TexturePacker::CheckDupe(MD5Context* ctx,
return false;
}
+void TexturePacker::ConvertToSingleChannel(RGBAImage& image, uint32_t channel)
+{
+ uint32_t size = (image.width * image.height);
+ for (uint32_t i = 0; i < size; i++)
+ {
+ image.pixels[i] = image.pixels[i * 4 + channel];
+ }
+
+ image.textureFormat = KD_TEX_FMT_SDR_R8;
+
+ image.bbp = 8;
+ image.pitch = 1 * image.width;
+}
+
+void TexturePacker::ConvertToDualChannel(RGBAImage& image)
+{
+ uint32_t size = (image.width * image.height);
+ for (uint32_t i = 0; i < size; i++)
+ {
+ image.pixels[i * 2] = image.pixels[i * 4];
+ image.pixels[i * 2 + 1] = image.pixels[i * 4 + 3];
+ }
+ image.textureFormat = KD_TEX_FMT_SDR_RG8;
+ image.bbp = 16;
+ image.pitch = 2 * image.width;
+}
+
+void TexturePacker::ReduceChannels(RGBAImage& image)
+{
+ if (image.textureFormat != KD_TEX_FMT_SDR_BGRA8)
+ return;
+
+ uint32_t size = (image.width * image.height);
+ uint8_t red = image.pixels[0];
+ uint8_t green = image.pixels[1];
+ uint8_t blue = image.pixels[2];
+ uint8_t alpha = image.pixels[3];
+ bool uniformRed = true;
+ bool uniformGreen = true;
+ bool uniformBlue = true;
+ bool uniformAlpha = true;
+ bool isGrey = true;
+ bool isIntensity = true;
+
+ // Checks each pixel for various properties.
+ for (uint32_t i = 0; i < size; i++)
+ {
+ if (image.pixels[i * 4] != red)
+ uniformRed = false;
+ if (image.pixels[i * 4 + 1] != green)
+ uniformGreen = false;
+ if (image.pixels[i * 4 + 2] != blue)
+ uniformBlue = false;
+ if (image.pixels[i * 4 + 3] != alpha)
+ uniformAlpha = false;
+ if (image.pixels[i * 4] != image.pixels[i * 4 + 1] ||
+ image.pixels[i * 4] != image.pixels[i * 4 + 2])
+ isGrey = false;
+ if (image.pixels[i * 4] != image.pixels[i * 4 + 1] ||
+ image.pixels[i * 4] != image.pixels[i * 4 + 2] ||
+ image.pixels[i * 4] != image.pixels[i * 4 + 3])
+ isIntensity = false;
+ }
+
+ if (uniformAlpha && alpha != 0xff)
+ printf("WARNING: uniform alpha detected! Consider using diffusecolor!\n");
+
+ bool isWhite = red == 0xff && green == 0xff && blue == 0xff;
+ if (uniformRed && uniformGreen && uniformBlue && !isWhite)
+ printf("WARNING: uniform color detected! Consider using diffusecolor!\n");
+
+ if (isIntensity)
+ {
+ // this is an intensity (GL_INTENSITY) texture
+ ConvertToSingleChannel(image, 0);
+ image.textureSwizzle = KD_TEX_SWIZ_RRRR;
+ }
+ else if (uniformAlpha && alpha == 0xff)
+ {
+ // we have a opaque texture, L or RGBX
+ if (isGrey)
+ {
+ ConvertToSingleChannel(image, 1);
+ image.textureSwizzle = KD_TEX_SWIZ_RRR1;
+ }
+ image.textureAlpha = KD_TEX_ALPHA_OPAQUE;
+ }
+ else if (uniformRed && uniformGreen && uniformBlue && isWhite)
+ {
+ // an alpha only texture
+ ConvertToSingleChannel(image, 3);
+ image.textureSwizzle = KD_TEX_SWIZ_111R;
+ }
+ else if (isGrey)
+ {
+ // a LA texture
+ ConvertToDualChannel(image);
+ image.textureSwizzle = KD_TEX_SWIZ_RRRG;
+ }
+ else
+ {
+ // BGRA
+ }
+}
+
int TexturePacker::createBundle(const std::string& InputDir, const std::string& OutputFile)
{
CXBTFWriter writer(OutputFile);
@@ -312,6 +412,9 @@ int TexturePacker::createBundle(const std::string& InputDir, const std::string&
continue;
}
+ for (unsigned int j = 0; j < frames.frameList.size(); j++)
+ ReduceChannels(frames.frameList[j].rgbaImage);
+
printf("%s\n", output.c_str());
bool skip=false;
if (m_dupecheck)
@@ -342,7 +445,7 @@ int TexturePacker::createBundle(const std::string& InputDir, const std::string&
file.GetFrames().push_back(frame);
printf(" frame %4i (delay:%4i) %s%c (%d,%d @ %" PRIu64
" bytes)\n",
- j, frame.GetDuration(), GetFormatString(frame.GetFormat()),
+ j, frame.GetDuration(), GetFormatString(frame.GetKDFormat()),
frame.HasAlpha() ? ' ' : '*', frame.GetWidth(), frame.GetHeight(),
frame.GetUnpackedSize());
}
diff --git a/tools/depends/native/TexturePacker/src/decoder/IDecoder.h b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
index 5bc06f2f96..63b5dd8607 100644
--- a/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
+++ b/tools/depends/native/TexturePacker/src/decoder/IDecoder.h
@@ -20,6 +20,8 @@
#pragma once
+#include "guilib/TextureFormats.h"
+
#include <cstdint>
#include <string>
#include <vector>
@@ -52,8 +54,11 @@ public:
std::vector<uint8_t> pixels;
int width = 0; // width
int height = 0; // height
- int bbp = 0; // bits per pixel
+ int bbp = 32; // bits per pixel
int pitch = 0; // rowsize in bytes
+ KD_TEX_FMT textureFormat{KD_TEX_FMT_SDR_BGRA8};
+ KD_TEX_ALPHA textureAlpha{KD_TEX_ALPHA_STRAIGHT};
+ KD_TEX_SWIZ textureSwizzle{KD_TEX_SWIZ_RGBA};
};
class DecodedFrame