I have a large PSB file (33600x19200px) and I need to write a script to export sections of this image as a series of images. What would the best approach be ?

Initially I thought about scripting slices and exporting, but Save for Web is diabled for this resolution.

Another option I thought was this:

  1. loop through each section I need to export
  2. make a selection
  3. copy pixels
  4. create a new document
  5. paste pixels
  6. save for the web with the format and name I need
  7. close the document without saving
  8. goto 1

Is this the best approach ? What are your suggestions ?


Here's my script with the steps above:

#target photoshop

var doc = app.activeDocument;
var sel = doc.selection;//main document selection
var rows = 70;
var cols = 40;
var cell  = 240;//size of a cell/display image/region of interest
var space=240; //space in between cells
var dname = doc.name.substr(0,doc.name.length-4);
var dir = doc.path.toString()+"/";
var dpi72 = 182.88036576073152146304292608585;
var options = new ExportOptionsSaveForWeb();
options.format = SaveDocumentType.JPEG;
options.quality = 75;

for(var y = 0; y < cols; y++){
        for(var x = 0 ; x < rows; x++){
            var xpos = (x * (cell+space))+((1-y%2) * space);//+ di-grid offset
             var ypos = (y * (cell+space));



             var nname = dname + "_"+((x+1)) + "_" + ((y+1));
             //$.writeln("["+x+"]["+y+"]" +nname +"\n"+sel.bounds);
             var small = app.documents.add(cell,cell,dpi72,dname,NewDocumentMode.RGB,DocumentFill.WHITE);

             app.activeDocument = small;

             small.exportDocument (new File(dir + "/" + nname + ".jpg"), ExportType.SAVEFORWEB, options);

             app.activeDocument = doc;
                 x = rows;
                 y = cols;

The script works, but it's a bit slow. Is my approach ok or is there a faster way to do this ?

  • First we need to know what the sections are. Regular grid of repeating sizes (aka tiling or paneling)? Hand selected areas? Let me know that and I can help you out.
    – TunaMaxx
    Jan 9, 2014 at 21:33
  • It's a diagonal grid actually (like a grid with space between rows and column but every other row is offset a bit and thus alternating) - I've worked out the arithmetic for creating the selection already Jan 9, 2014 at 22:29
  • Can you give me a sample image and sample grid? Also, how many are you doing? Is this a one off, or a repeat?
    – TunaMaxx
    Jan 9, 2014 at 22:52
  • Thanks! You can see quarter of the grid here. I'm only exporting the black squares as individual jpgs. This process will repeat with different content on the same layout/specs. Jan 10, 2014 at 1:18
  • OK, I get it. So is that an at size version of the art? 240px squares offset by 240px, then skip a 240px row, then repeat? We'll have to script that. give me a bit and I'll try and work something out.
    – TunaMaxx
    Jan 10, 2014 at 22:37

1 Answer 1


This should be a lot faster. Instead of copy and pasting into a new file hundreds of times, it does this:

  1. Makes the Background into a Layer.
  2. Reduces the Canvas size down to the cell size.
  3. Slides the Layer around 'under' the Canvas to the correct location.
  4. Does a "Save For Web" essentially the same as your script.
  5. Go to 3 and repeat, then stop when it runs out of pixels to nibble on.

It calculates the number of Cells per row, as well as the number of rows. No pre-configuration is needed!

There are some variables you can set at the beginning of the file should you ever need to.

NOTE: The script assumes that you start with a flattened file, and MAKE SURE YOU HAVE A BACKUP COPY of your artwork just in case anything goes wrong.

On my machine at work (absolutely nothing fancy or powerful, just a beater PC) it created the 350 tiles of your sample file in about 6 minutes. You can help the speed by hiding the Tools and Pallets (by pressing Tab) before running the script. Also, minimizing Photoshop while the script runs seems to help a bit too.

// Alter these as needed
var cellWidth         = 240; // The width, in px, of your image cell
var cellHeight        = 240; // The height, in px, of your image cell
var xOffset           = 240; // The space, in px, between each cell in a row
var yOffset           = 240; // The space, in px, between each row. Set to 0 for traditional checker board effect
var options           = new ExportOptionsSaveForWeb();
    options.format    = SaveDocumentType.JPEG;
    options.quality   = 75;

// Don't change these unless you know why you should! :)
var doc               = app.activeDocument;
var dname             = doc.name.substr(0,doc.name.length-4);
var dir               = doc.path.toString()+"/";
var rowShift          = true;
var imageWidth        = activeDocument.width.as('px');
var imageHeight       = activeDocument.height.as('px');

// Store the current rulerUnits for later. We're going to change
// it to pixels for now, and we want to change it back later.
var myRulerUnits = app.preferences.rulerUnits;

// Set rulerUnits to pixels
app.preferences.rulerUnits = Units.PIXELS;

// Find the "Background"
var layerRef = doc.artLayers.getByName("Background");

// Set our "Background" to be a Layer
layerRef.isBackgroundLayer = false;

// Reduce the Canvas size to our cell size
doc.resizeCanvas(cellWidth, cellHeight, AnchorPosition.TOPLEFT);

var totalOffset = 0;
var xMovement = 0;

// Do the magic
for (var y = 0; y < numberOfRows(); y++)
    totalOffset = 0;

    for (var x = 0; x < numberOfCells(); x++)
        if (x == 0)
            xMovement = (rowShift) ? xOffset : 0;
            xMovement = cellWidth + xOffset;

        totalOffset += xMovement;

        // Offset the layer into our Canvas "window"
        layerRef.applyOffset(-(xMovement), 0, OffsetUndefinedAreas.WRAPAROUND);


    // Offset the layer back to the left and down one row
    layerRef.applyOffset(totalOffset, -(cellHeight + yOffset), OffsetUndefinedAreas.WRAPAROUND);

    // Flip the rowShift. If it was true, make it false and vice versa.
    rowShift = !rowShift;

// Calculate number of cells per row. May change depending in rowShift, etc
function numberOfCells()
    var theWidth = imageWidth;

    if (rowShift == true)
        var theWidth = theWidth - xOffset; 
    return Math.floor((theWidth + xOffset) / (cellWidth + xOffset));

// Calculate number of rows
function numberOfRows()
    return Math.floor((imageHeight + yOffset) / (cellHeight + yOffset));

// Pad the cell x and y numbers for proper sorting
function pad(num, size)
    var s = "000000000" + num;
    return s.substr(s.length-size);

// Actually save, or really "Save For Web" the cell
function saveCell(x, y)
    var nname = dname + "_" + pad((x + 1), 3) + "_" + pad((y + 1), 3);

    doc.exportDocument (new File(dir + "/" + nname + ".jpg"), ExportType.SAVEFORWEB, options);

// Reset the ruler units
app.preferences.rulerUnits = myRulerUnits;
  • That's awesome! Thanks a lot! It is a lot faster :) I've tweaked a bit to do 2 more things: flatten layers, fetch layer[0] (instead of "Background"), and when storing unit preferences, I also store the history state, so I can restore the document to what it was before script manipulation. Jan 14, 2014 at 14:39
  • Great! Glad I could help. I figured sliding around the Layer under a smaller Canvas would be a bit quicker than Copy > New Doc > Paste > Etc was. Good ideas in your modifications. Without seeing the originals, I had no way of knowing what other things to tweak. I did another version that names the files a little differently with an incrementing number in the file name (like ctq_036_001_002.jpg), but I'm kind of OCD that way. Good luck and if you want to tweak it I'll be happy to help if you need it.
    – TunaMaxx
    Jan 14, 2014 at 17:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.