# Advice on batch exporting sections of an image

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.

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 ?

Update:

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

try{

sel.select([[xpos,ypos],[xpos+cell,ypos],[xpos+cell,ypos+cell],[xpos,ypos+cell]],SelectionType.REPLACE,0,false);
sel.copy(true);

var nname = dname + "_"+((x+1)) + "_" + ((y+1));
//\$.writeln("["+x+"]["+y+"]" +nname +"\n"+sel.bounds);
//*

app.activeDocument = small;

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

app.activeDocument = doc;
//*/
}catch(err){
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 '14 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 – George Profenza Jan 9 '14 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 '14 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. – George Profenza Jan 10 '14 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 '14 at 22:37

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;
}
else
{
xMovement = cellWidth + xOffset;
}

totalOffset += xMovement;

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

saveCell(x,y);
};

// 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
{
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. – George Profenza Jan 14 '14 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 '14 at 17:26