javascript - Generating EPS Files with Clipping Paths that Photoshop Correctly Recognizes as Vector Paths - Stack Overflow

I'm working on a web application (Vue.js) that removes backgrounds from images. An important compo

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:

  1. Various PostScript structures for defining clipping paths
  2. Registering the path with different notations (/DefaultClippingPath, /_clippingpath, etc.)
  3. Accurately converting SVG path instructions (M, L, C, Z) to PostScript path instructions (moveto, lineto, curveto, closepath)
  4. 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:

  1. The paths are correctly converted from SVG to PostScript format.
  2. The EPS files can be opened in Photoshop without errors.
  3. 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.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745049180a4608279.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信