I'm working on a web application (Vue.js) that removes backgrounds from images. An important component is exporting EPS files with clipping paths that are correctly recognized in Adobe Photoshop.
The Problem:
Despite multiple implementations, the path in the EPS file is not recognized as a vector path in Photoshop. The file opens correctly, but the path only appears as pixels in a regular layer, not as a vector path in the Paths panel.
What I Want to Achieve:
When the EPS file is opened in Photoshop, the path should appear in the Paths panel (Window > Paths) as an editable vector path, not as pixels in a layer.
What I've Tried:
- Various PostScript structures for defining clipping paths
- Registering the path with different notations (/DefaultClippingPath, /_clippingpath, etc.)
- Accurately converting SVG path instructions (M, L, C, Z) to PostScript path instructions (moveto, lineto, curveto, closepath)
- Different methods for naming and defining the path
Relevant Code:
const createEPSWithPath = async (imageBase64, pathString) => {
return new Promise((resolve) => {
const img = new Image();
img.onload = () => {
const imgWidth = img.width;
const imgHeight = img.height;
// Process SVG path accurately
let postScriptPath = '';
try {
// Clean pathstring
const cleanPathString = pathString.trim().replace(/\s+/g, ' ');
if (cleanPathString.includes('M')) {
// Parse each instruction separately for better control
let svgCommands = cleanPathString.match(/[MLCZmlcz][^MLCZmlcz]*/g) || [];
svgCommands.forEach(cmd => {
const command = cmd[0]; // First letter is the command
const args = cmd.substring(1).trim(); // Rest are the arguments
switch(command) {
case 'M':
// MoveTo: x y moveto
const movePoints = args.split(/[,\s]+/);
if (movePoints.length >= 2) {
const x = parseFloat(movePoints[0]).toFixed(3);
const y = parseFloat(movePoints[1]).toFixed(3);
postScriptPath += `${x} ${y} moveto\n`;
}
break;
case 'L':
// LineTo: x y lineto
const linePoints = args.split(/[,\s]+/);
if (linePoints.length >= 2) {
const x = parseFloat(linePoints[0]).toFixed(3);
const y = parseFloat(linePoints[1]).toFixed(3);
postScriptPath += `${x} ${y} lineto\n`;
}
break;
case 'C':
// CurveTo: x1 y1 x2 y2 x3 y3 curveto
const curvePoints = args.split(/[,\s]+/);
if (curvePoints.length >= 6) {
const x1 = parseFloat(curvePoints[0]).toFixed(3);
const y1 = parseFloat(curvePoints[1]).toFixed(3);
const x2 = parseFloat(curvePoints[2]).toFixed(3);
const y2 = parseFloat(curvePoints[3]).toFixed(3);
const x3 = parseFloat(curvePoints[4]).toFixed(3);
const y3 = parseFloat(curvePoints[5]).toFixed(3);
postScriptPath += `${x1} ${y1} ${x2} ${y2} ${x3} ${y3} curveto\n`;
}
break;
case 'Z':
case 'z':
// ClosePath: closepath
postScriptPath += `closepath\n`;
break;
}
});
}
} catch(e) {
console.error('Error converting path:', e);
// Fallback path
postScriptPath = '0 0 moveto\n0 100 lineto\n100 100 lineto\n100 0 lineto\nclosepath\n';
}
// EPS structure
let epsContent = `%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 ${Math.ceil(imgWidth)} ${Math.ceil(imgHeight)}
%%Creator: Background Remover
%%Title: Image with Path
%%Pages: 1
%%EndComments
% Define clipping path
/CustomPath {
newpath
${postScriptPath}
} def
% Register path as Photoshop clipping path
/CustomClippingPath {
CustomPath
} def
/DefaultClippingPath {
CustomPath
} def
% Make path visible (blue line)
1 setlinewidth
0 0 1 setrgbcolor
CustomPath
stroke
% Draw border (black line)
0.5 setlinewidth
0 0 0 setrgbcolor
newpath
0 0 moveto
${imgWidth} 0 lineto
${imgWidth} ${imgHeight} lineto
0 ${imgHeight} lineto
closepath
stroke
%%EOF`;
// Create JPEG version for preview
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = imgWidth;
canvas.height = imgHeight;
ctx.drawImage(img, 0, 0);
const jpegDataUrl = canvas.toDataURL('image/jpeg', 1.0);
const jpegData = jpegDataUrl.split(',')[1];
resolve({
eps: epsContent,
jpeg: jpegData
});
};
img.src = imageBase64;
});
};
What I Already Know:
- The paths are correctly converted from SVG to PostScript format.
- The EPS files can be opened in Photoshop without errors.
- The paths are visible as blue lines in the file, but only as pixels, not as vector paths.
Question:
What is the correct EPS file structure and PostScript code to create a vector clipping path that Photoshop recognizes? I'm looking for a correct example of the PostScript code that Photoshop needs to display the paths in the Paths panel and not just as pixels.