最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin0浏览0评论

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.

发布评论

评论列表(0)

  1. 暂无评论