Skip to content

Commit

Permalink
Merge pull request #211 from Hoikas/mm_compress
Browse files Browse the repository at this point in the history
Allow using squish's high quality DXT compression.
  • Loading branch information
zrax authored Jun 5, 2021
2 parents 4290e61 + 2e6194b commit c7af40e
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 18 deletions.
17 changes: 12 additions & 5 deletions Python/PRP/Surface/pyMipmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,18 +282,20 @@ PY_METHOD_VA(Mipmap, DecompressImage,
return img;
}

PY_METHOD_VA(Mipmap, CompressImage,
"Params: level, data\n"
PY_METHOD_KWARGS(Mipmap, CompressImage,
"Params: level, data, quality\n"
"Compresses the specified mip level")
{
static char* kwlist[] = { _pycs("level"), _pycs("data"), _pycs("quality"), nullptr };
int level, dataSize;
char* data;
if (!PyArg_ParseTuple(args, "is#", &level, &data, &dataSize)) {
PyErr_SetString(PyExc_TypeError, "CompressImage expects an int and a binary string");
plMipmap::BlockQuality quality = plMipmap::kBlockQualityNormal;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "is#|i", kwlist, &level, &data, &dataSize, &quality)) {
PyErr_SetString(PyExc_TypeError, "CompressImage expects an int, a binary string, and an optional int");
return nullptr;
}
try {
self->fThis->CompressImage(level, data, dataSize);
self->fThis->CompressImage(level, data, dataSize, quality);
} catch (hsBadParamException& ex) {
PyErr_SetString(PyExc_RuntimeError, ex.what());
return nullptr;
Expand Down Expand Up @@ -366,6 +368,11 @@ PY_PLASMA_TYPE_INIT(Mipmap)
if (PyType_CheckAndReady(&pyMipmap_Type) < 0)
return nullptr;

// CompressImage quality
PY_TYPE_ADD_CONST(Mipmap, "kBlockQualityNormal", plMipmap::kBlockQualityNormal);
PY_TYPE_ADD_CONST(Mipmap, "kBlockQualityHigh", plMipmap::kBlockQualityHigh);
PY_TYPE_ADD_CONST(Mipmap, "kBlockQualityUltra", plMipmap::kBlockQualityUltra);

Py_INCREF(&pyMipmap_Type);
return (PyObject*)&pyMipmap_Type;
}
Expand Down
6 changes: 5 additions & 1 deletion Python/PyHSPlasma.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3898,6 +3898,10 @@ class plMessageWithCallbacks(plMessage):
def delCallback(self, idx: int) -> None: ...

class plMipmap(plBitmap):
kBlockQualityNormal: int = ...
kBlockQualityHigh: int = ...
kBlockQualityUltra: int = ...

height: int = ...
imageData: bytes = ...
numLevels: int = ...
Expand All @@ -3908,7 +3912,7 @@ class plMipmap(plBitmap):
@overload
def __init__(self, name: str = "") -> None: ...

def CompressImage(self, level: int, data: bytes) -> None: ...
def CompressImage(self, level: int, data: bytes, quality: int = kBlockQualityNormal) -> None: ...
def DecompressImage(self, level: int) -> bytes: ...
def extractAlphaData(self) -> bytes: ...
def extractColorData(self) -> bytes: ...
Expand Down
43 changes: 32 additions & 11 deletions core/PRP/Surface/plMipmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,24 +686,45 @@ void plMipmap::DecompressImage(size_t level, void* dest, size_t size)
}
}

void plMipmap::CompressImage(size_t level, void* src, size_t size)
void plMipmap::CompressImage(size_t level, void* src, size_t size, BlockQuality quality)
{
const LevelData& lvl = fLevelData[level];

if (fCompressionType == kDirectXCompression) {
unsigned char* imgPtr = fImageData + fLevelData[level].fOffset;
if (fDXInfo.fCompressionType == kDXT1) {
squish::CompressImage((squish::u8*)src, lvl.fWidth, lvl.fHeight,
imgPtr, squish::kDxt1 | squish::kColourRangeFit);
} else if (fDXInfo.fCompressionType == kDXT3) {
squish::CompressImage((squish::u8*)src, lvl.fWidth, lvl.fHeight,
imgPtr, squish::kDxt3 | squish::kColourRangeFit);
} else if (fDXInfo.fCompressionType == kDXT5) {
squish::CompressImage((squish::u8*)src, lvl.fWidth, lvl.fHeight,
imgPtr, squish::kDxt5 | squish::kColourRangeFit);
} else {

int squishFlags = 0;
switch (fDXInfo.fCompressionType) {
case kDXT1:
squishFlags |= squish::kDxt1;
break;
case kDXT3:
squishFlags |= squish::kDxt3;
break;
case kDXT5:
squishFlags |= squish::kDxt5;
break;
default:
throw hsBadParamException(__FILE__, __LINE__);
break;
}
switch (quality) {
case kBlockQualityNormal:
squishFlags |= squish::kColourRangeFit;
break;
case kBlockQualityHigh:
squishFlags |= squish::kColourClusterFit;
break;
case kBlockQualityUltra:
squishFlags |= squish::kColourIterativeClusterFit;
break;
default:
throw hsBadParamException(__FILE__, __LINE__);
break;
}

squish::CompressImage((squish::u8*)src, lvl.fWidth, lvl.fHeight,
imgPtr, squishFlags);
} else {
throw hsNotImplementedException(__FILE__, __LINE__, "Compression not currently supported for format.");
}
Expand Down
9 changes: 8 additions & 1 deletion core/PRP/Surface/plMipmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ class PLASMA_DLL plMipmap : public plBitmap
public:
enum { kColorDataRLE = 0x1, kAlphaDataRLE = 0x2 };

enum BlockQuality
{
kBlockQualityNormal,
kBlockQualityHigh,
kBlockQualityUltra,
};

protected:
struct PLASMA_DLL LevelData
{
Expand Down Expand Up @@ -103,7 +110,7 @@ class PLASMA_DLL plMipmap : public plBitmap

size_t GetUncompressedSize(size_t level) const;
void DecompressImage(size_t level, void* dest, size_t size);
void CompressImage(size_t level, void* src, size_t size);
void CompressImage(size_t level, void* src, size_t size, BlockQuality quality = kBlockQualityNormal);
};


Expand Down

0 comments on commit c7af40e

Please sign in to comment.