From 84f388f2944e7b0485e43b2a2ce9c0e30ff2a880 Mon Sep 17 00:00:00 2001 From: yizhi <946185759@qq.com> Date: Mon, 17 Mar 2025 11:51:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=87=AA=E5=8A=A8=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++- package.json | 2 +- src/cv/addon.ts | 9 ++++-- src/cv/common.ts | 3 +- src/cv/download.ts | 77 ++++++++++++++++++++++++++++++++++++++++++++ src/cv/index.ts | 1 + src/test.ts | 1 + thirdpart/install.js | 3 -- 8 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 src/cv/download.ts diff --git a/README.md b/README.md index 656f700..2488779 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ 简单的OpenCV封装 -## 编译源码 +## 编译源码(可选) 1. 依赖 1. python3 1. cmake @@ -31,6 +31,9 @@ import cv from '@yizhi/opencv'; //配置addon路径 cv.config("ADDON_PATH", "/path/to/cv.node"); +//下载addon(可选) +// 如果配置了ADDON_PATH,则下载addon到ADDON_PATH,否则下载到build/cv.node +await cv.downloadAddon(); //正常使用 const im = cv.imread("/path/to/input"); diff --git a/package.json b/package.json index 59a9ca5..e18a00f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yizhi/cv", - "version": "1.0.0", + "version": "1.0.1", "main": "dist/index.js", "types": "typing/index.d.ts", "scripts": { diff --git a/src/cv/addon.ts b/src/cv/addon.ts index 178e2df..3a2fe4e 100644 --- a/src/cv/addon.ts +++ b/src/cv/addon.ts @@ -1,18 +1,21 @@ +import path from "path"; import { LINE_8, MARKER_CROSS } from "./consts"; export const config = { - ADDON_PATH: "../../build/cv.node", + ADDON_PATH: path.join(__dirname, "../../build/cv.node"), DEFAULT_LINE_TYPE: LINE_8, DEFAULT_THICKNESS: 1, DEFAULT_MARKER: MARKER_CROSS, }; +export type AddonConfig = typeof config; + export function getAddon() { return require(config.ADDON_PATH); } -export function getConfig(name: N): typeof config[N] { return config[name]; } -export function setConfig(name: N, value: typeof config[N]) { config[name] = value; } +export function getConfig(name: N): AddonConfig[N] { return config[name]; } +export function setConfig(name: N, value: AddonConfig[N]) { config[name] = value; } export function CVMat() { return getAddon().Mat; } diff --git a/src/cv/common.ts b/src/cv/common.ts index 44caade..848180e 100644 --- a/src/cv/common.ts +++ b/src/cv/common.ts @@ -1,11 +1,10 @@ -import { getAddon, getConfig } from "./addon"; +export { getConfig as C } from "./addon"; import { Mat } from "./mat"; export type TypedArray = Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | BigUint64Array | BigInt64Array | Float32Array | Float64Array export function FromCV(mat: any): Mat { return new (Mat as any)(mat); } export function M(mat: Mat) { return (mat as any).__mat__; } -export function C(name: Parameters[0]) { return getConfig(name); } export function resolveArgs>(args: any[], checker: boolean | (() => boolean)): R { if (typeof checker === "function") checker = checker(); diff --git a/src/cv/download.ts b/src/cv/download.ts new file mode 100644 index 0000000..a022914 --- /dev/null +++ b/src/cv/download.ts @@ -0,0 +1,77 @@ +import os from "os"; +import fs from "fs"; +import path from "path"; +import { C } from "./common"; + +const URLS = { + GITHUB: `https://github.com/kangkang520/node-addons/releases/download/cv{{version}}/cv_{{platform}}_{{arch}}.node`, + URNAS: `http://git.urnas.cn:5200/yizhi-js-lib/opencv/releases/download/{{version}}/cv_{{platform}}_{{arch}}.node`, +} + +function getURL(template: string) { + const version = require("../../package.json").version; + let platform = ""; + let arch = ""; + switch (os.platform()) { + case "win32": + platform = "windows"; + break; + case "linux": + platform = "linux"; + break; + default: + throw new Error(`Unsupported platform: ${os.platform()}, Please compile the addon yourself.`); + } + switch (os.arch()) { + case "x64": + arch = "x64"; + break; + default: + throw new Error(`Unsupported architecture: ${os.arch()}, Please compile the addon yourself.`); + } + + return template.replaceAll("{{version}}", version).replaceAll("{{platform}}", platform).replaceAll("{{arch}}", arch); +} + +async function getStream() { + for (const [name, url] of Object.entries(URLS)) { + try { + return await fetch(getURL(url)).then(res => { + if (res.status != 200) throw new Error("Failed to download addon."); + return res.blob().then(b => b.stream()); + }) + } catch (e) { } + } + throw new Error("Failed to download addon."); +} + +export async function downloadAddon(savename?: string) { + const defaultAddon = path.resolve(process.cwd(), C("ADDON_PATH")); + const saveName = savename ? path.resolve(path.dirname(defaultAddon), savename) : defaultAddon; + if (fs.existsSync(saveName)) return saveName; + + await fs.promises.mkdir(path.dirname(saveName), { recursive: true }); + + const stream = await getStream(); + const cacheFile = await new Promise((resolve, reject) => { + const cacheFile = path.join(os.tmpdir(), Date.now() + ".cv.node"); + let fsStream!: ReturnType; + stream.pipeTo(new WritableStream({ + start(controller) { + fsStream = fs.createWriteStream(cacheFile); + }, + async write(chunk, controller) { + await new Promise((resolve, reject) => fsStream.write(chunk, err => err ? reject(err) : resolve())); + }, + close() { + fsStream.end(); + resolve(cacheFile); + }, + abort() { } + })).catch(reject); + }); + + await fs.promises.cp(cacheFile, saveName); + await fs.promises.rm(cacheFile); + return saveName; +} diff --git a/src/cv/index.ts b/src/cv/index.ts index 102451b..65ce3d9 100644 --- a/src/cv/index.ts +++ b/src/cv/index.ts @@ -1,4 +1,5 @@ export { setConfig as config } from "./addon"; +export { downloadAddon } from "./download"; export * from "./mat"; export * from "./consts"; export * from "./proc"; diff --git a/src/test.ts b/src/test.ts index 814932d..91595b7 100644 --- a/src/test.ts +++ b/src/test.ts @@ -2,6 +2,7 @@ import cv from "."; async function test() { + await cv.downloadAddon(); const fs = await import("fs"); // const buffer = fs.readFileSync("data/im1.jpeg") const res = await cv.imread("test_data/im1.jpeg"); diff --git a/thirdpart/install.js b/thirdpart/install.js index 89569c3..b580c38 100644 --- a/thirdpart/install.js +++ b/thirdpart/install.js @@ -105,9 +105,6 @@ async function downloadFromURL(name, url, resolver) { if (!checkFile(saveName)) { console.log(`开始下载${name}, 地址:${url}`); - await fetch(url).then(res => { - console.log(res.status) - }) const result = spawnSync("curl", ["-o", saveName + ".cache", "-L", url, "-s", "-w", "%{http_code}"], { ...spawnOption, stdio: "pipe" }); assert(result.status == 0 && result.stdout.toString() == "200", `下载${name}失败`); fs.renameSync(saveName + ".cache", saveName);