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:
- loop through each section I need to export
- make a selection
- copy pixels
- create a new document
- paste pixels
- save for the web with the format and name I need
- close the document without saving
- 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);
//*
var small = app.documents.add(cell,cell,dpi72,dname,NewDocumentMode.RGB,DocumentFill.WHITE);
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;
alert(err);
}
}
}
The script works, but it's a bit slow. Is my approach ok or is there a faster way to do this ?
Answer
This should be a lot faster. Instead of copy and pasting into a new file hundreds of times, it does this:
- Makes the Background into a Layer.
- Reduces the Canvas size down to the cell size.
- Slides the Layer around 'under' the Canvas to the correct location.
- Does a "Save For Web" essentially the same as your script.
- 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
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;
No comments:
Post a Comment