[Closed] Max scene icon
How do we get the saved scene icon that is associated with a Max file? Not the standard Max file Icon but the image of the viewport that was saved.
Hey Paul
they are stored in
C:\Program Files\Autodesk\3ds Max 2013\CachedThumbnails
But the location to the screengrab bitmap is also saved in one of the config xml files. I’m not at my machine right now, I think I have a function somewhere to get this.
Thanks Pete, I don’t think that is going to work for me. The whole DotNet rabbit whole isn’t much better how ever, nasty mess.
don’t know if this is any help, this c++ code will get you to the data
def_visible_primitive(getMaxSceneIcon, "getMaxSceneIcon");
Value* getMaxSceneIcon_cf(Value** arg_list, int count)
{
check_arg_count(getMaxSceneIcon, 1, count);
TSTR maxfile = arg_list[0]->to_filename();
IStorage* pStorage = NULL;
IPropertySetStorage* pPropertySetStorage = NULL;
HRESULT res = MAXScript_interface11->OpenMAXStorageFile(WStr(maxfile), &pStorage);
if(res != S_OK)
return &undefined;
// Get the Storage interface
if(S_OK != pStorage->QueryInterface(IID_IPropertySetStorage, (void**)&pPropertySetStorage))
{
pStorage->Release();
return &undefined;
}
// Get the SummaryInfo property set interface
IPropertyStorage* pSummaryInfoStorage;
int imgsize;
if(S_OK == pPropertySetStorage->Open(FMTID_SummaryInformation, STGM_READ|STGM_SHARE_EXCLUSIVE, &pSummaryInfoStorage))
{
PROPSPEC PropSpec[1];
PROPVARIANT PropVar[1];
PropSpec[0].ulKind = PRSPEC_PROPID;
PropSpec[0].propid = PIDSI_THUMBNAIL;
HRESULT hr = pSummaryInfoStorage->ReadMultiple(1, PropSpec, PropVar);
if(S_OK == hr)
{
if(PropVar[0].vt == VT_CF)
{
imgsize = PropVar[0].pclipdata->cbSize;
BYTE* imgdata = PropVar[0].pclipdata->pClipData + 0x62;
}
}
FreePropVariantArray(1, PropVar);
pSummaryInfoStorage->Release();
}
pStorage->Release();
return Integer::intern(imgsize);
}
unsure on the format of the thumbnail header, tried copying as is to the clipboard photoshop complained about unexpected eof.
Here is the messy c# version of Klvnk’s code:
http://forums.cgsociety.org/showthread.php?f=98&t=1121870&page=1&pp=15
this will copy the thumbnail onto the clipboard as a DIB
def_visible_primitive(setMaxSceneIconToClipboard, "setMaxSceneIconToClipboard");
struct thumbheader
{
WORD bytesperpixel;
WORD reserved1;
WORD mm;
WORD xExt;
WORD yExt;
WORD reserved2;
};
Value* setMaxSceneIconToClipboard_cf(Value** arg_list, int count)
{
check_arg_count(setMaxSceneIconToClipboard, 1, count);
TSTR maxfile = arg_list[0]->to_filename();
IStorage* pStorage = NULL;
IPropertySetStorage* pPropertySetStorage = NULL;
HRESULT hres;
// open the max file
hres = MAXScript_interface11->OpenMAXStorageFile(WStr(maxfile), &pStorage);
if(hres != S_OK)
return &false_value;
// Get the Storage interface
if(pStorage->QueryInterface(IID_IPropertySetStorage, (void**)&pPropertySetStorage) != S_OK)
{
pStorage->Release();
return &false_value;
}
// Get the SummaryInfo property set interface
IPropertyStorage* pSummaryInfoStorage;
if(pPropertySetStorage->Open(FMTID_SummaryInformation, STGM_READ|STGM_SHARE_EXCLUSIVE, &pSummaryInfoStorage) == S_OK)
{
PROPSPEC PropSpec[1];
PROPVARIANT PropVar[1];
PropSpec[0].ulKind = PRSPEC_PROPID;
PropSpec[0].propid = PIDSI_THUMBNAIL;
hres = pSummaryInfoStorage->ReadMultiple(1, PropSpec, PropVar);
if(hres == S_OK && PropVar[0].vt == VT_CF)
{
thumbheader* th = (thumbheader*)PropVar[0].pclipdata->pClipData;
int imgdatasize = th->yExt * th->xExt * th->bytesperpixel;
HGLOBAL clipHandle = GlobalAlloc(GMEM_MOVEABLE, imgdatasize + sizeof(BITMAPINFOHEADER));
if(clipHandle && OpenClipboard(MAXScript_interface->GetMAXHWnd()))
{
EmptyClipboard();
BYTE* clipPtr = (BYTE*)GlobalLock(clipHandle);
BITMAPINFOHEADER bmh;
ZeroMemory(&bmh, sizeof(BITMAPINFOHEADER));
bmh.biBitCount = th->bytesperpixel * 8;
bmh.biPlanes = 1;
bmh.biHeight = th->yExt;
bmh.biWidth = th->xExt;
bmh.biSize = sizeof(BITMAPINFOHEADER);
bmh.biSizeImage = imgdatasize;
memcpy(clipPtr, &bmh, sizeof(BITMAPINFOHEADER));
clipPtr += sizeof(BITMAPINFOHEADER);
BYTE* imgdata = PropVar[0].pclipdata->pClipData + 0x62;
memcpy(clipPtr, imgdata, imgdatasize);
GlobalUnlock(clipHandle);
SetClipboardData(CF_DIB, clipHandle);
}
else
hres = S_FALSE;
}
FreePropVariantArray(1, PropVar);
pSummaryInfoStorage->Release();
}
pStorage->Release();
CloseClipboard();
return hres == S_OK ? &true_value : &false_value;
}
then you can get it into a max bitmap with the following
setMaxSceneIconToClipboard <myfile>;
bm = getclipboardBitmap();
display bm;
this will return a max bitmap directly…
def_visible_primitive(MaxSceneIconToMaxBitmap, "MaxSceneIconToMaxBitmap");
Value* MaxSceneIconToMaxBitmap_cf(Value** arg_list, int count)
{
check_arg_count(MaxSceneIconToMaxBitmap, 1, count);
TSTR maxfile = arg_list[0]->to_filename();
IStorage* pStorage = NULL;
IPropertySetStorage* pPropertySetStorage = NULL;
HRESULT hres;
// open the max file
hres = MAXScript_interface11->OpenMAXStorageFile(WStr(maxfile), &pStorage);
if(hres != S_OK)
return &false_value;
// Get the Storage interface
if(pStorage->QueryInterface(IID_IPropertySetStorage, (void**)&pPropertySetStorage) != S_OK)
{
pStorage->Release();
return &false_value;
}
BYTE* dib;
IPropertyStorage* pSummaryInfoStorage;
if(pPropertySetStorage->Open(FMTID_SummaryInformation, STGM_READ|STGM_SHARE_EXCLUSIVE, &pSummaryInfoStorage) == S_OK)
{
PROPSPEC PropSpec[1];
PROPVARIANT PropVar[1];
PropSpec[0].ulKind = PRSPEC_PROPID;
PropSpec[0].propid = PIDSI_THUMBNAIL;
hres = pSummaryInfoStorage->ReadMultiple(1, PropSpec, PropVar);
if(hres == S_OK && PropVar[0].vt == VT_CF)
{
thumbheader* th = (thumbheader*)PropVar[0].pclipdata->pClipData;
int imgdatasize = th->yExt * th->xExt * th->bytesperpixel;
// build a dib from the thumbnail
dib = (BYTE*)MAX_malloc(imgdatasize + sizeof(BITMAPINFOHEADER));
if(dib)
{
BYTE* tempdib = dib;
BITMAPINFOHEADER bmh;
ZeroMemory(&bmh, sizeof(BITMAPINFOHEADER));
bmh.biBitCount = th->bytesperpixel * 8;
bmh.biPlanes = 1;
bmh.biHeight = th->yExt;
bmh.biWidth = th->xExt;
bmh.biSize = sizeof(BITMAPINFOHEADER);
bmh.biSizeImage = imgdatasize;
memcpy(tempdib, &bmh, sizeof(BITMAPINFOHEADER));
tempdib += sizeof(BITMAPINFOHEADER);
BYTE* imgdata = PropVar[0].pclipdata->pClipData + 0x62;
memcpy(tempdib, imgdata, imgdatasize);
}
else
hres = S_FALSE;
}
FreePropVariantArray(1, PropVar);
pSummaryInfoStorage->Release();
}
pStorage->Release();
if(hres == S_OK)
{
Bitmap *map = TheManager->Create((PBITMAPINFO)dib); // create a bitmap from the dib
if(dib)
MAX_free(dib);
if(!map)
return &undefined;
one_typed_value_local(MAXBitMap* mbm);
vl.mbm = new MAXBitMap();
vl.mbm->bi.CopyImageInfo(&map->Storage()->bi);
vl.mbm->bi.SetFirstFrame(0);
vl.mbm->bi.SetLastFrame(0);
vl.mbm->bi.SetName("");
vl.mbm->bi.SetDevice("");
if (vl.mbm->bi.Type() > BMM_TRUE_64)
vl.mbm->bi.SetType(BMM_TRUE_64);
vl.mbm->bm = map;
return_value(vl.mbm);
}
return &undefined;
}
shortens quite nicely to this
def_visible_primitive(MaxSceneIconToMaxBitmap, "MaxSceneIconToMaxBitmap");
Value* MaxSceneIconToMaxBitmap_cf(Value** arg_list, int count)
{
check_arg_count(MaxSceneIconToMaxBitmap, 1, count);
TSTR maxfile = arg_list[0]->to_filename();
IStorage* pStorage = NULL;
IPropertySetStorage* pPropertySetStorage = NULL;
HRESULT hres;
// open the max file
hres = MAXScript_interface11->OpenMAXStorageFile(WStr(maxfile), &pStorage);
if(hres != S_OK)
return &undefined;
// Get the Storage interface
if(pStorage->QueryInterface(IID_IPropertySetStorage, (void**)&pPropertySetStorage) != S_OK)
{
pStorage->Release();
return &undefined;
}
Bitmap* bm = NULL;
IPropertyStorage* pSummaryInfoStorage;
if(pPropertySetStorage->Open(FMTID_SummaryInformation, STGM_READ|STGM_SHARE_EXCLUSIVE, &pSummaryInfoStorage) == S_OK)
{
PROPSPEC PropSpec[1];
PROPVARIANT PropVar[1];
PropSpec[0].ulKind = PRSPEC_PROPID;
PropSpec[0].propid = PIDSI_THUMBNAIL;
hres = pSummaryInfoStorage->ReadMultiple(1, PropSpec, PropVar);
if(hres == S_OK && PropVar[0].vt == VT_CF)
bm = TheManager->Create((PBITMAPINFO)(PropVar[0].pclipdata->pClipData + 0x3a));
FreePropVariantArray(1, PropVar);
pSummaryInfoStorage->Release();
}
pStorage->Release();
if(bm)
{
one_typed_value_local(MAXBitMap* mbm);
vl.mbm = new MAXBitMap();
vl.mbm->bi.CopyImageInfo(&bm->Storage()->bi);
vl.mbm->bi.SetFirstFrame(0);
vl.mbm->bi.SetLastFrame(0);
vl.mbm->bi.SetName("");
vl.mbm->bi.SetDevice("");
if (vl.mbm->bi.Type() > BMM_TRUE_64)
vl.mbm->bi.SetType(BMM_TRUE_64);
vl.mbm->bm = bm;
return_value(vl.mbm);
}
return &undefined;
}
edit: a more memory safe version
Thanks for the help, I was trying to avoid getting out of Max script but that just isn’t going to happen.