npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

eufymake-empf

v2.0.0

Published

Browser-first TypeScript generator and parser for encrypted eufyMake Studio EMPF projects

Readme

eufymake-empf

浏览器优先、与 Node.js 无关的 TypeScript EMPF 库,用于生成和解析 eufyMake Studio 4.x 离线工程。

生成格式为:

eufyMake TLV header + AES-256-GCM(nonce + ZIP + auth tag)

核心库支持普通彩色图、白墨/彩墨/光油层数、自定义灰度深度图和 Texture Layer。格式已经通过 macOS eufyMake Studio 4.0.4 实机打开和自动重存测试。

架构

src/       浏览器库,只使用 Web 标准 API
cli/       Node.js 命令行入口和文件系统适配
scripts/   构建期浏览器兼容检查
test/      格式回归测试

src/ 中没有 node: 导入、Bufferprocess、文件系统或 sharp。二进制 API 使用 Uint8ArrayArrayBufferBlob,加密使用 Web Crypto。

安装

npm install eufymake-empf

浏览器使用

坐标原点是打印平面左上角;位置和尺寸均使用毫米。

彩图和深度图以 3 cm 宽度等比居中

下面的例子把彩色图片和对应深度图放到迷你板(335 × 90 mm)上。彩色图片的打印宽度固定为 3 cm,即 30 mm;打印高度根据原图宽高比自动计算,图片整体位于画板正中央。

深度图必须和彩图具有相同的像素宽高。深度图可以是浏览器能够解码的图片格式,imageToPng() 会将其转换为 Studio 所需的 PNG。

import {
  EmpfGenerator,
  InkModeEnum,
  PRINT_BEDS,
  PrintBedEnum,
  imageToPng,
  readImageMetadata,
} from "eufymake-empf";

const colorFile = colorInput.files![0];
const depthFile = depthInput.files![0];

// 读取彩图的原始像素尺寸,用它计算打印高度。
const colorBytes = new Uint8Array(await colorFile.arrayBuffer());
const { width: pixelWidth, height: pixelHeight } = readImageMetadata(colorBytes);

// 库的尺寸单位是 mm:3 cm = 30 mm。
const imageWidthMm = 30;
const imageHeightMm = imageWidthMm * (pixelHeight / pixelWidth);

const bed = PRINT_BEDS[PrintBedEnum.miniFlatbed];

if (imageWidthMm > bed.widthMm || imageHeightMm > bed.heightMm) {
  throw new Error("等比缩放后的图片无法放入迷你板");
}

// addImage() 接收图片左上角坐标;用两侧剩余空间的一半实现居中。
const xMm = (bed.widthMm - imageWidthMm) / 2;
const yMm = (bed.heightMm - imageHeightMm) / 2;

// Studio 的自定义深度图必须使用 PNG。
const depthPng = await imageToPng(depthFile);

const generator = new EmpfGenerator({
  printBed: PrintBedEnum.miniFlatbed,
  projectName: "3 cm centered texture",
});

await generator.addImage(
  colorBytes,
  xMm,
  yMm,
  imageWidthMm,
  imageHeightMm,
  {
    inkMode: InkModeEnum.cmyk,
    cmykLayers: 1,
    whiteLayers: 3,
    texture: {
      depthMap: depthPng,
      thickness: 5,
      gamma: 7,
      invert: false,
    },
  },
);

const empfBlob = await generator.toBlob();
const downloadUrl = URL.createObjectURL(empfBlob);
const anchor = document.createElement("a");
anchor.href = downloadUrl;
anchor.download = "centered-texture.empf";
anchor.click();
URL.revokeObjectURL(downloadUrl);

例如原图是 1200 × 800 px,打印高度会是:

30 × (800 / 1200) = 20 mm

最终图片范围为 x = 152.5 ~ 182.5 mmy = 35 ~ 55 mm,正好位于 335 × 90 mm 迷你板的中心。图片打印尺寸只取决于传给 addImage() 的毫米尺寸,与图片 DPI 元数据无关。

如果不需要缩略图,可以不传 thumbnail;工程中会写入一个透明占位 PNG。

内存 API

const bytes: Uint8Array = await generator.toUint8Array();
const project = await parseEmpf(bytes);
const zipBytes: Uint8Array = await decryptEmpf(bytes);

// File 和 Blob 也可以直接解析。
const uploadedProject = await parseEmpf(fileInput.files![0]);

因为 Web Crypto 是异步 API,encryptEmpf()decryptEmpf() 也都是异步函数。

Node CLI

CLI 是 cli/ 下的独立 workspace 包,拥有自己的 package.json 和 Node 依赖,不会进入浏览器库的安装内容或依赖图。Node CLI 需要 Node.js 20 或更高版本。

node cli/dist/empf.js generate \
  --image color.png \
  --depth-map depth.png \
  --output texture.empf \
  --bed mini \
  --x 122.5 --y 0 --width 90 --height 90 \
  --white-layers 3 --cmyk-layers 1 \
  --thickness 5 --gamma 7

node cli/dist/empf.js inspect texture.empf
node cli/dist/empf.js decrypt texture.empf --output texture.zip

本地开发:

pnpm install
pnpm check
pnpm test
pnpm build
node cli/dist/empf.js inspect test.empf

pnpm check 会同时执行:

  • 纯浏览器库 TypeScript 检查,且不加载 Node 类型;
  • CLI 的独立 Node 类型检查;
  • src/ Node API 静态扫描;
  • platform: browser 的完整打包测试。

已确认的 4.0.4 兼容要点

  • 文件头长度为 88 字节,TLV 字段记录格式版本、密钥版本、offlineapplication/zip 和内部文件名。
  • AES-GCM 使用 12 字节随机 nonce 和 16 字节认证标签。
  • ZIP 使用 STORE,包含项目信息、Fabric 5.3.0 画布、缩略图和字体映射。
  • 画布单位为 50 DPI,即 50 / 25.4 单位/mm。
  • 自定义 Texture 对象内嵌 src 彩图与 grayscale 深度图,并设置纹理、厚度、Gamma 和墨层字段。

实机验收中,Studio 4.0.4 成功解密生成文件、创建工程缩略图、载入 Texture 对象,并自动重存为新的加密 EMPF。重存文件保留了彩图、深度图、pattern 纹理、厚度、墨层、位置和缩放;Studio 自身在该次重存时省略了 gamma 字段,生成器仍按原生 test.empf 结构写入该字段。

这里使用的是 Studio 离线工程所需的内置离线密钥。云端文件可能使用不同的用户密钥,不属于这个库的目标范围。