From 08fa25a7377b13cc13a24c0322a6c5d544fc78ab Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Thu, 9 Feb 2012 23:47:22 -0800 Subject: [PATCH 1/6] Fix a potential crash in pyVaultImageNode. Fixes a crash which can occur when attempting to fetch an unsupported image type. --- Sources/Plasma/FeatureLib/pfPython/pyVaultImageNode.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyVaultImageNode.cpp b/Sources/Plasma/FeatureLib/pfPython/pyVaultImageNode.cpp index f4c7368c..71d83e02 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyVaultImageNode.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyVaultImageNode.cpp @@ -171,6 +171,8 @@ PyObject* pyVaultImageNode::Image_GetImage( void ) else fMipmapKey->RefObject(); } + else + PYTHON_RETURN_NONE; } return pyImage::New(fMipmap); From cb697523f9de18403abe517e23c417004dbf4d07 Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Thu, 9 Feb 2012 23:50:55 -0800 Subject: [PATCH 2/6] Add PNG support to the VaultImageNode functions. --- Sources/Plasma/PubUtilLib/plVault/Pch.h | 1 + .../PubUtilLib/plVault/plVaultNodeAccess.cpp | 51 ++++++++++++------- .../PubUtilLib/plVault/plVaultNodeAccess.h | 4 +- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/Sources/Plasma/PubUtilLib/plVault/Pch.h b/Sources/Plasma/PubUtilLib/plVault/Pch.h index 80663e1f..9b751c76 100644 --- a/Sources/Plasma/PubUtilLib/plVault/Pch.h +++ b/Sources/Plasma/PubUtilLib/plVault/Pch.h @@ -74,6 +74,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pnDispatch/plDispatch.h" #include "plDniCoordinateInfo.h" #include "plGImage/plMipmap.h" +#include "plGImage/plPNG.h" #include "plJPEG/plJPEG.h" #include "plMessage/plVaultNotifyMsg.h" #include "plNetClientComm/plNetClientComm.h" diff --git a/Sources/Plasma/PubUtilLib/plVault/plVaultNodeAccess.cpp b/Sources/Plasma/PubUtilLib/plVault/plVaultNodeAccess.cpp index 754b6288..47d520aa 100644 --- a/Sources/Plasma/PubUtilLib/plVault/plVaultNodeAccess.cpp +++ b/Sources/Plasma/PubUtilLib/plVault/plVaultNodeAccess.cpp @@ -633,18 +633,30 @@ void VaultImageNode::SetImageData (const uint8_t buffer[], unsigned bytes) { //============================================================================ #ifdef CLIENT -void VaultImageNode::StuffImage (plMipmap * src) { +void VaultImageNode::StuffImage (plMipmap * src, int dstType) { hsRAMStream ramStream; - plJPEG::Instance().SetWriteQuality(30/*percent*/); - if (plJPEG::Instance().WriteToStream(&ramStream, src)) { + hsBool compressSuccess = false; + + switch (dstType) { + case kJPEG: + plJPEG::Instance().SetWriteQuality(70/*percent*/); + compressSuccess = plJPEG::Instance().WriteToStream(&ramStream, src); + break; + case kPNG: + compressSuccess = plPNG::Instance().WriteToStream(&ramStream, src); + break; + default: + break; + } + + if (compressSuccess) { unsigned bytes = ramStream.GetEOF(); uint8_t * buffer = (uint8_t *)malloc(bytes); ramStream.CopyToMem(buffer); IVaultNodeSetBlob(kImageData, base, &imgData, &imgDataLen, buffer, bytes); - SetImageType(kJPEG); + SetImageType(dstType); free(buffer); - } - else { + } else { IVaultNodeSetBlob(kImageData, base, &imgData, &imgDataLen, nil, 0); SetImageType(kNone); } @@ -654,22 +666,25 @@ void VaultImageNode::StuffImage (plMipmap * src) { //============================================================================ #ifdef CLIENT bool VaultImageNode::ExtractImage (plMipmap ** dst) { - + hsRAMStream ramStream; + ramStream.Write(imgDataLen, imgData); + ramStream.Rewind(); + switch (imgType) { + case kJPEG: + (*dst) = plJPEG::Instance().ReadFromStream(&ramStream); + break; + + case kPNG: + (*dst) = plPNG::Instance().ReadFromStream(&ramStream); + break; + case kNone: + default: (*dst) = nil; - return false; - - case kJPEG: { - hsRAMStream ramStream; - ramStream.Write(imgDataLen, imgData); - ramStream.Rewind(); - (*dst) = plJPEG::Instance().ReadFromStream(&ramStream); - } - return ((*dst) != nil); - - DEFAULT_FATAL(imgType); + break; } + return ((*dst) != nil); } #endif diff --git a/Sources/Plasma/PubUtilLib/plVault/plVaultNodeAccess.h b/Sources/Plasma/PubUtilLib/plVault/plVaultNodeAccess.h index 83acd6c3..a15ecccd 100644 --- a/Sources/Plasma/PubUtilLib/plVault/plVaultNodeAccess.h +++ b/Sources/Plasma/PubUtilLib/plVault/plVaultNodeAccess.h @@ -290,7 +290,7 @@ struct VaultAgeLinkNode : NetVaultNodeAccess { //============================================================================ struct VaultImageNode : NetVaultNodeAccess { - enum ImageTypes { kNone=0, kJPEG=1 }; + enum ImageTypes { kNone=0, kJPEG=1, kPNG=2 }; static const uint64_t kImageType = NetVaultNode::kInt32_1; static const uint64_t kImageTitle = NetVaultNode::kString64_1; @@ -310,7 +310,7 @@ struct VaultImageNode : NetVaultNodeAccess { void SetImageData (const uint8_t buffer[], unsigned bytes); #ifdef CLIENT - void StuffImage (class plMipmap * src); + void StuffImage (class plMipmap * src, int dstType=kJPEG); bool ExtractImage (class plMipmap ** dst); #endif }; From 3b22256085ecfcb19e1e4a59cdc766f65e713a35 Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Fri, 10 Feb 2012 00:12:52 -0800 Subject: [PATCH 3/6] Add python function glue to allow loading PNG images from disk. --- .../Plasma/FeatureLib/pfPython/pyImage.cpp | 45 +++++++++++++++++++ Sources/Plasma/FeatureLib/pfPython/pyImage.h | 1 + .../FeatureLib/pfPython/pyImageGlue.cpp | 38 +++++++++++++++- 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp index 3a7c3bd6..70edf630 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp @@ -230,4 +230,49 @@ PyObject* pyImage::LoadJPEGFromDisk(const wchar_t* filename, uint16_t width, uin PYTHON_RETURN_NONE; } +PyObject* pyImage::LoadPNGFromDisk(const wchar_t* filename, uint16_t width, uint16_t height) +{ + plMipmap* theMipmap = plPNG::Instance().ReadFromFile(filename); + if (theMipmap) + { + if (width > 0 && height > 0) + { + if (!theMipmap->ResizeNicely(width, height, plMipmap::kDefaultFilter)) + { + delete theMipmap; + PYTHON_RETURN_NONE; + } + } + + // let's create a nice name for this thing based on the filename + std::string name = "PtImageFromDisk_"; + const wchar_t* i = filename; + int charsChecked = 0; + + while (*i != '\\' && *i != '\0' && charsChecked < 1024) + { + i++; + charsChecked++; + } + + if (*i == '\0') + { + i = filename; + } + else + { + i++; + } + + char* cName = hsWStringToString(i); + name = name + cName; + + hsgResMgr::ResMgr()->NewKey(name.c_str(), theMipmap, plLocation::kGlobalFixedLoc); + + return pyImage::New( theMipmap ); + } + else + PYTHON_RETURN_NONE; +} + #endif diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImage.h b/Sources/Plasma/FeatureLib/pfPython/pyImage.h index 86e9337f..95c2a810 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImage.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyImage.h @@ -168,6 +168,7 @@ public: void SaveAsJPEG(const wchar_t* fileName, uint8_t quality = 75); void SaveAsPNG(const wchar_t* fileName); static PyObject* LoadJPEGFromDisk(const wchar_t* filename, uint16_t width, uint16_t height); // returns pyImage + static PyObject* LoadPNGFromDisk(const wchar_t* filename, uint16_t width, uint16_t height); // returns pyImage #endif }; diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp index bf0c1c01..dbd3f178 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp @@ -306,7 +306,43 @@ PYTHON_GLOBAL_METHOD_DEFINITION(PtLoadJPEGFromDisk, args, "Params: filename,widt } else { - PyErr_SetString(PyExc_TypeError, "saveAsJPEG expects a string and a unsigned 8-bit int"); + PyErr_SetString(PyExc_TypeError, "PtLoadJPEGFromDisk expects a string and two unsigned shorts"); + PYTHON_RETURN_ERROR; + } +} + +PYTHON_GLOBAL_METHOD_DEFINITION(PtLoadPNGFromDisk, args, "Params: filename,width,height\nThe image will be resized to fit the width and height arguments. Set to 0 if resizing is not desired.\nReturns a pyImage of the specified file.") +{ + PyObject* filenameObj; + unsigned short width, height; + if (!PyArg_ParseTuple(args, "Ohh", &filenameObj, &width, &height)) + { + PyErr_SetString(PyExc_TypeError, "PtLoadPNGFromDisk expects a string and two unsigned shorts"); + PYTHON_RETURN_ERROR; + } + + if (PyUnicode_Check(filenameObj)) + { + int strLen = PyUnicode_GetSize(filenameObj); + wchar_t* text = new wchar_t[strLen + 1]; + PyUnicode_AsWideChar((PyUnicodeObject*)filenameObj, text, strLen); + text[strLen] = L'\0'; + PyObject* ret = pyImage::LoadPNGFromDisk(text, width, height); + delete [] text; + return ret; + } + else if (PyString_Check(filenameObj)) + { + // we'll allow this, just in case something goes weird + char* text = PyString_AsString(filenameObj); + wchar_t* wText = hsStringToWString(text); + PyObject* ret = pyImage::LoadPNGFromDisk(wText, width, height); + delete [] wText; + return ret; + } + else + { + PyErr_SetString(PyExc_TypeError, "PtLoadPNGFromDisk expects a string and two unsigned shorts"); PYTHON_RETURN_ERROR; } } From 036a1d38fc0868becdecaa883021f947911715c0 Mon Sep 17 00:00:00 2001 From: Joseph Davies Date: Fri, 10 Feb 2012 13:53:04 -0800 Subject: [PATCH 4/6] Clean up python binding for image-loading functions. --- .../Plasma/FeatureLib/pfPython/pyImage.cpp | 46 +++---------------- .../FeatureLib/pfPython/pyImageGlue.cpp | 38 ++++----------- 2 files changed, 15 insertions(+), 69 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp index 70edf630..bd815f4f 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp @@ -201,26 +201,9 @@ PyObject* pyImage::LoadJPEGFromDisk(const wchar_t* filename, uint16_t width, uin // let's create a nice name for this thing based on the filename std::string name = "PtImageFromDisk_"; - const wchar_t* i = filename; - int charsChecked = 0; - - while (*i != '\\' && *i != '\0' && charsChecked < 1024) - { - i++; - charsChecked++; - } - - if (*i == '\0') - { - i = filename; - } - else - { - i++; - } - - char* cName = hsWStringToString(i); - name = name + cName; + char* filetext = hsWStringToString(filename); + name = name + filetext; + delete[] filetext; hsgResMgr::ResMgr()->NewKey(name.c_str(), theMipmap, plLocation::kGlobalFixedLoc); @@ -246,26 +229,9 @@ PyObject* pyImage::LoadPNGFromDisk(const wchar_t* filename, uint16_t width, uint // let's create a nice name for this thing based on the filename std::string name = "PtImageFromDisk_"; - const wchar_t* i = filename; - int charsChecked = 0; - - while (*i != '\\' && *i != '\0' && charsChecked < 1024) - { - i++; - charsChecked++; - } - - if (*i == '\0') - { - i = filename; - } - else - { - i++; - } - - char* cName = hsWStringToString(i); - name = name + cName; + char* filetext = hsWStringToString(filename); + name = name + filetext; + delete[] filetext; hsgResMgr::ResMgr()->NewKey(name.c_str(), theMipmap, plLocation::kGlobalFixedLoc); diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp index dbd3f178..7670b48c 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyImageGlue.cpp @@ -285,23 +285,13 @@ PYTHON_GLOBAL_METHOD_DEFINITION(PtLoadJPEGFromDisk, args, "Params: filename,widt PYTHON_RETURN_ERROR; } - if (PyUnicode_Check(filenameObj)) - { - int strLen = PyUnicode_GetSize(filenameObj); - wchar_t* text = new wchar_t[strLen + 1]; - PyUnicode_AsWideChar((PyUnicodeObject*)filenameObj, text, strLen); - text[strLen] = L'\0'; - PyObject* ret = pyImage::LoadJPEGFromDisk(text, width, height); - delete [] text; - return ret; - } - else if (PyString_Check(filenameObj)) + if (PyString_CheckEx(filenameObj)) { - // we'll allow this, just in case something goes weird - char* text = PyString_AsString(filenameObj); + char* text = PyString_AsStringEx(filenameObj); wchar_t* wText = hsStringToWString(text); PyObject* ret = pyImage::LoadJPEGFromDisk(wText, width, height); - delete [] wText; + delete[] wText; + delete[] text; return ret; } else @@ -320,24 +310,13 @@ PYTHON_GLOBAL_METHOD_DEFINITION(PtLoadPNGFromDisk, args, "Params: filename,width PyErr_SetString(PyExc_TypeError, "PtLoadPNGFromDisk expects a string and two unsigned shorts"); PYTHON_RETURN_ERROR; } - - if (PyUnicode_Check(filenameObj)) + if (PyString_CheckEx(filenameObj)) { - int strLen = PyUnicode_GetSize(filenameObj); - wchar_t* text = new wchar_t[strLen + 1]; - PyUnicode_AsWideChar((PyUnicodeObject*)filenameObj, text, strLen); - text[strLen] = L'\0'; - PyObject* ret = pyImage::LoadPNGFromDisk(text, width, height); - delete [] text; - return ret; - } - else if (PyString_Check(filenameObj)) - { - // we'll allow this, just in case something goes weird - char* text = PyString_AsString(filenameObj); + char* text = PyString_AsStringEx(filenameObj); wchar_t* wText = hsStringToWString(text); PyObject* ret = pyImage::LoadPNGFromDisk(wText, width, height); - delete [] wText; + delete[] wText; + delete[] text; return ret; } else @@ -352,5 +331,6 @@ void pyImage::AddPlasmaMethods(std::vector &methods) { #ifndef BUILDING_PYPLASMA PYTHON_GLOBAL_METHOD(methods, PtLoadJPEGFromDisk); + PYTHON_GLOBAL_METHOD(methods, PtLoadPNGFromDisk); #endif } \ No newline at end of file From c9b4c0a92d4f715f8350f9859ceb8026d1917cd5 Mon Sep 17 00:00:00 2001 From: NadnerbD Date: Sun, 12 Feb 2012 01:58:37 -0500 Subject: [PATCH 5/6] NewKey can take a plString, so no need to convert to const char* --- Sources/Plasma/FeatureLib/pfPython/pyImage.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp index 9d23bc0d..caf8c83d 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp @@ -200,12 +200,9 @@ PyObject* pyImage::LoadJPEGFromDisk(const wchar_t* filename, uint16_t width, uin } // let's create a nice name for this thing based on the filename - plString name = _TEMP_CONVERT_FROM_LITERAL("PtImageFromDisk_"); - char* filetext = hsWStringToString(filename); - name = name + filetext; - delete[] filetext; + plString name = plString::Format("PtImageFromDisk_%s", hsWStringToString(filename)); - hsgResMgr::ResMgr()->NewKey(name.c_str(), theMipmap, plLocation::kGlobalFixedLoc); + hsgResMgr::ResMgr()->NewKey(name, theMipmap, plLocation::kGlobalFixedLoc); return pyImage::New( theMipmap ); } @@ -227,7 +224,8 @@ PyObject* pyImage::LoadPNGFromDisk(const wchar_t* filename, uint16_t width, uint } } - name += plString::FromWchar(i); + // let's create a nice name for this thing based on the filename + plString name = plString::Format("PtImageFromDisk_%s", hsWStringToString(filename)); hsgResMgr::ResMgr()->NewKey(name, theMipmap, plLocation::kGlobalFixedLoc); From 3e15b5d31841cc29b7dbe788cf7f025704de831b Mon Sep 17 00:00:00 2001 From: NadnerbD Date: Sun, 12 Feb 2012 21:45:48 -0500 Subject: [PATCH 6/6] Fixed memory leak, plString is nice --- Sources/Plasma/FeatureLib/pfPython/pyImage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp index caf8c83d..7e019a88 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyImage.cpp @@ -200,7 +200,7 @@ PyObject* pyImage::LoadJPEGFromDisk(const wchar_t* filename, uint16_t width, uin } // let's create a nice name for this thing based on the filename - plString name = plString::Format("PtImageFromDisk_%s", hsWStringToString(filename)); + plString name = plString::Format("PtImageFromDisk_%S", filename); hsgResMgr::ResMgr()->NewKey(name, theMipmap, plLocation::kGlobalFixedLoc); @@ -225,7 +225,7 @@ PyObject* pyImage::LoadPNGFromDisk(const wchar_t* filename, uint16_t width, uint } // let's create a nice name for this thing based on the filename - plString name = plString::Format("PtImageFromDisk_%s", hsWStringToString(filename)); + plString name = plString::Format("PtImageFromDisk_%S", filename); hsgResMgr::ResMgr()->NewKey(name, theMipmap, plLocation::kGlobalFixedLoc);