Copy link to clipboard
Copied
I've been trying to write a CPP plugin that will access a layers bitmap but I don't have a low level API to do this (Stupid Action descriptor garbage) so I figured I am just going to pass data from Actionscript or JS I'm following a Actionscript 3 post here: Encoding Bitmaps and Byte Arrays
Can someone give me the quick rundown on what I need to do to get this AS working? I've never used AS in PS... Or in general...
Copy link to clipboard
Copied
Isn't ActionScript use in what was flash and is now renamed Adobe Animate CC. Photoshop Scripting plug-in does support JavaScript but I believe base on a very old version of Javascript.
ActionScript Adobe Animate CC - Home
Copy link to clipboard
Copied
Thank you JJMack, do you know off the top of your head if there is the same libraries I can use in JS as the ones found in there? I need to access a layers bitmap (byte array).
Copy link to clipboard
Copied
I'm retired I just hack at scripting Photoshop never had to learn JavaScript when I was working man.
Copy link to clipboard
Copied
Do you still search for method to read layers bitmap from a document not saved to disk? Or just other faster, but from a file?
Copy link to clipboard
Copied
"Do you still search for method to read layers bitmap from a document not saved to disk? Or just other faster, but from a file?"
Every example I see in C++ uses fread() to read a PSD from a file.
I would prefer it to be in the actual memory of the canvas, 😕
Copy link to clipboard
Copied
Is that really big problem to make quick save of flattened layer, read binary and delete it from disk. I would like to have it in memory too, but saving process of single layer won't affect extra time to delay working of script. Reading binary takes time...
Copy link to clipboard
Copied
So there are actually two problems writing to disk:
1. The current system with the Action Descriptors is just plain silly, it's adding time to create a new doc and copy and paste a layer to it and save it, adding time to the writing to disk and reading the file on read. So a larger document will take some time to export.
2. I'm streaming data to my service, so having to save it then just pass it a file directory of the saved file (what I already wrote) is useless, might as well write an importer at that point.
I've found a way to read a PSD with 'fread' but I'm still in the same position I was with writing to disk.
Copy link to clipboard
Copied
If you want the pixel values you need a filter plug-in or export plug-in helper for your automation workflow. See the AutomationFilter + Hidden example in the SDK.
Copy link to clipboard
Copied
@Tom, and this will return theSo byte array without saving any files to disk?
So this is looking good, Question about the read(), ,is the com a layer?
//-------------------------------------------------------------------------------
//
// HiddenData::Write
//
// Given a readChannelDesc and a percent write to all the pixels.
// If the percent is -1 then write a random number to all the pixels.
//
//-------------------------------------------------------------------------------
void HiddenData::Write(void)
{
// find out which channel we are writing to
// this was already read in from the scripting parameters
ReadChannelDesc * readChannelDesc = NULL;
if (channelName.empty())
readChannelDesc = FindChannelDesc(channelType);
else
readChannelDesc = FindChannelDesc(channelName);
if (readChannelDesc == NULL)
{
error = filterBadParameters;
throw(this);
}
// check some things to see if we should continue
if (readChannelDesc->tileSize.v == 0)
{
error = filterBadParameters;
throw(this);
}
if (readChannelDesc->tileSize.h == 0)
{
error = filterBadParameters;
throw(this);
}
Boolean canWrite = false;
if (readChannelDesc->writePort == NULL)
{
error = filterBadParameters;
throw(this);
}
int32 bigError = sPSChannelProcs->CanWrite(readChannelDesc->writePort, &canWrite);
if (bigError != 0 || !canWrite)
{
error = filterBadParameters;
throw(this);
}
// set up for tiling the document
int32 docHeight = readChannelDesc->bounds.bottom - readChannelDesc->bounds.top;
int32 docWidth = readChannelDesc->bounds.right - readChannelDesc->bounds.left;
int32 tileHeight = readChannelDesc->tileSize.v;
int32 tileWidth = readChannelDesc->tileSize.h;
uint32 tilesVert = (tileHeight - 1 + docHeight) / tileHeight;
uint32 tilesHoriz = (tileWidth - 1 + docWidth) / tileWidth;
uint32 channelSize = tileHeight * tileWidth * readChannelDesc->depth / 8;
// get a buffer that we can read and write into
Ptr pixelData = sPSBuffer->New(NULL, channelSize);
if (pixelData == NULL)
{
error = filterBadParameters;
throw(this);
}
// set up the PixelMemoryDesc for the channel ports suite
PixelMemoryDesc pixelMemoryDesc;
pixelMemoryDesc.data = pixelData;
pixelMemoryDesc.colBits = readChannelDesc->depth;
pixelMemoryDesc.bitOffset = 0;
pixelMemoryDesc.depth = readChannelDesc->depth;
VRect currentRect;
int32 progressTotal = tilesVert * tilesHoriz;
int32 progressDone = 0;
// process each tile in order
for (uint32 vertTile = 0; vertTile < tilesVert && error == 0; vertTile++)
{
for (uint32 horizTile = 0; horizTile < tilesHoriz && error == 0; horizTile++)
{
currentRect.top = vertTile * tileHeight;
currentRect.left = horizTile * tileWidth;
currentRect.bottom = currentRect.top + tileHeight;
currentRect.right = currentRect.left + tileWidth;
// don't go past the document bounds
if (currentRect.bottom > docHeight)
currentRect.bottom = docHeight;
if (currentRect.right > docWidth)
currentRect.right = docWidth;
pixelMemoryDesc.rowBits = (currentRect.right - currentRect.left) *
readChannelDesc->depth;
// read
int32 bigError = sPSChannelProcs->ReadPixelsFromLevel(
readChannelDesc->port, 0, ¤tRect, &pixelMemoryDesc);
if (bigError)
{
error = filterBadParameters;
throw(this);
}
// muck with
if (percent == kRandomPercent)
{
srand((unsigned int)(time(NULL)));
Ptr pixel = pixelData;
uint16 * bigPixel = reinterpret_cast<uint16 *>(pixelData);
float * fPixel = reinterpret_cast<float *>(pixelData);
for(uint32 a = 0; a < channelSize; a++, pixel++, bigPixel++, fPixel++)
if (pixelMemoryDesc.depth == 32)
{
*fPixel = static_cast<float>( (float)rand() / (float)RAND_MAX );
a += 3; // 3 because we get one in the loop for free
}
else if (pixelMemoryDesc.depth == 16)
{
*bigPixel = static_cast<uint16>( rand() % 32768 );
a++; // big pixels are half the channelSize
}
else
{
*pixel = static_cast<uint8>( rand() % 255 );
}
}
else
{
if (pixelMemoryDesc.depth == 32)
{
float * fPixel = reinterpret_cast<float *>(pixelData);
for(uint32 a = 0; a < channelSize; a += 4, fPixel++)
*fPixel = static_cast<float>( (float)percent / (float)100 );
}
else if (pixelMemoryDesc.depth == 16)
{
uint16 * bigPixel = reinterpret_cast<uint16 *>(pixelData);
for(uint32 a = 0; a < channelSize; a += 2, bigPixel++)
*bigPixel = static_cast<uint16>(percent * 32768 / 100);
}
else
memset(pixelData, percent * 255 / 100, channelSize);
}
// write
bigError = sPSChannelProcs->WritePixelsToBaseLevel(
readChannelDesc->writePort, ¤tRect, &pixelMemoryDesc);
if (bigError)
{
error = filterBadParameters;
throw(this);
}
gFilterRecord->progressProc(++progressDone, progressTotal);
// see if the user is impatient or didn't mean to do that
if (gFilterRecord->abortProc())
{
error = userCanceledErr;
throw(this);
}
}
}
sPSBuffer->Dispose(&pixelData);
}