9 Replies Latest reply on Feb 7, 2018 2:40 PM by i73

    Encoding Bitmaps and Byte Arrays Actionscript 3 help

    i73 Level 1

      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...

        • 1. Re: Encoding Bitmaps and Byte Arrays Actionscript 3 help
          JJMack Most Valuable Participant

          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

          • 2. Re: Encoding Bitmaps and Byte Arrays Actionscript 3 help
            i73 Level 1

            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).

            • 3. Re: Encoding Bitmaps and Byte Arrays Actionscript 3 help
              Kukurykus Adobe Community Professional

              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?

              • 4. Re: Encoding Bitmaps and Byte Arrays Actionscript 3 help
                JJMack Most Valuable Participant

                I'm retired I just hack at scripting Photoshop never had to learn JavaScript when I was working man.

                • 5. Re: Encoding Bitmaps and Byte Arrays Actionscript 3 help
                  i73 Level 1

                  "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, :/

                  • 6. Re: Encoding Bitmaps and Byte Arrays Actionscript 3 help
                    Kukurykus Adobe Community Professional

                    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...

                    • 7. Re: Encoding Bitmaps and Byte Arrays Actionscript 3 help
                      i73 Level 1

                      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.

                      • 8. Re: Encoding Bitmaps and Byte Arrays Actionscript 3 help
                        Tom Ruark Adobe Employee

                        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.

                        • 9. Re: Encoding Bitmaps and Byte Arrays Actionscript 3 help
                          i73 Level 1

                          @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, &currentRect, &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, &currentRect, &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);
                          }