Repository: zy445566/node-digital-watermarking
Branch: master
Commit: 302d71d773d7
Files: 10
Total size: 10.9 MB
Directory structure:
gitextract_5caq41ia/
├── .github/
│ └── workflows/
│ └── npmpublish.yml
├── .gitignore
├── LICENSE
├── README.md
├── index.d.ts
├── index.js
├── lib.js
├── opencv.js
├── package.json
└── test/
└── test.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/npmpublish.yml
================================================
name: Node.js Package
on:
push:
branches:
- master
jobs:
build-node-8:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 8
- run: npm ci
- run: npm test
build-node-10:
needs: build-node-8
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 10
- run: npm ci
- run: npm test
build-node-12:
needs: build-node-10
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- run: npm ci
- run: npm test
publish-npm:
needs: build-node-12
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: 12
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# my
.vscode
build
*.heapsnapshot
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2017 ZhangYuan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# node-digital-watermarking
[A digital watermark is a kind of marker covertly embedded in a noise-tolerant signal such as an audio, video or image data. It is typically used to identify ownership of the copyright of such signal. "Watermarking" is the process of hiding digital information in a carrier signal; the hidden information should, but does not need to, contain a relation to the carrier signal. Digital watermarks may be used to verify the authenticity or integrity of the carrier signal or to show the identity of its owners. It is prominently used for tracing copyright infringements and for banknote authentication.](https://en.wikipedia.org/wiki/Digital_watermarking)
<br />
[数字水印(Digital Watermarking)技术是将一些标识信息(即数字水印)直接嵌入数字载体当中(包括多媒体、文档、软件等)或是间接表示(修改特定区域的结构),且不影响原载体的使用价值,也不容易被探知和再次修改。但可以被生产方识别和辨认。通过这些隐藏在载体中的信息,可以达到确认内容创建者、购买者、传送隐秘信息或者判断载体是否被篡改等目的。数字水印是保护信息安全、实现防伪溯源、版权保护的有效办法,是信息隐藏技术研究领域的重要分支和研究方向。](https://baike.baidu.com/item/%E6%95%B0%E5%AD%97%E6%B0%B4%E5%8D%B0/722667)
# package install
```
npm install digital-watermarking
```
This package is only used for the Node.js, if you are using Web, use [web-digital-watermarking](https://github.com/zy445566/web-digital-watermarking).
# Sample Use
```js
const dw = require('digital-watermarking');
//EnCode Image add digital watermarking
let srcFileName = "srcImg.png";
let watermarkText = "github.com/zy445566";
let fontSize = 1.1;
let enCodeFileName = "enCode.png";
async function run() {
await dw.transformImageWithText(srcFileName,watermarkText,fontSize,enCodeFileName);
//DeCode Image get digital watermarking
let deCodeFileName = "deCode.png";
await dw.getTextFormImage(enCodeFileName,deCodeFileName);
}
run()
```
# Result
## enCode.png

## deCode.png

================================================
FILE: index.d.ts
================================================
import Jimp from "jimp/*";
declare class DigitalWatermarking {
static transformImageWithText(
srcFileName:string,watermarkText:string,
fontSize:number,enCodeFileName:string
):Promise<Jimp>;
static transformImageBufferWithText(srcBuffer:Buffer,watermarkText:string,fontSize:number):Promise<Jimp>;
static getTextFormImage(enCodeFileName:string,deCodeFileName:string):Promise<Jimp>;
static getTextFormImageBuffer(enCodeBuffer:Buffer):Promise<Jimp>;
}
export function transformImageWithText(
srcFileName:string,watermarkText:string,
fontSize:number,enCodeFileName:string
):Promise<Jimp>;
export function transformImageBufferWithText(srcBuffer:Buffer,watermarkText:string,fontSize:number):Promise<Jimp>;
export function getTextFormImage(enCodeFileName:string,deCodeFileName:string):Promise<Jimp>;
export function getTextFormImageBuffer(enCodeBuffer:Buffer):Promise<Jimp>;
================================================
FILE: index.js
================================================
const lib = require('./lib.js');
const path = require('path');
const fs = require('fs');
class DigitalWatermarking{
static getConfig() {
return lib.getConfig()
}
static setConfig({opencvJsPath}) {
return lib.setConfig({opencvJsPath})
}
static getAbsoluteFilePath(filePath)
{
return path.isAbsolute(filePath)?filePath:path.join(process.cwd(),filePath);
}
static existsFilePath(filePath)
{
if(!fs.existsSync(filePath)){throw new Error(`not file in ${filePath}`);}
}
static isBuffer(fileBuf)
{
if((!(fileBuf instanceof Buffer))) {
throw new Error(`input not Buffer`);
}
}
static async transformImageWithText(srcFileName,watermarkText,fontSize,enCodeFileName)
{
const srcFilePath = DigitalWatermarking.getAbsoluteFilePath(srcFileName);
DigitalWatermarking.existsFilePath(srcFilePath);
return await lib.transformImageWithText(
srcFilePath,
watermarkText,fontSize,
DigitalWatermarking.getAbsoluteFilePath(enCodeFileName)
);
}
static async transformImageBufferWithText(srcBuffer,watermarkText,fontSize)
{
DigitalWatermarking.isBuffer(srcBuffer);
return await lib.transformImageWithText(
srcBuffer,
watermarkText,fontSize,
);
}
static async getTextFormImage(enCodeFileName,deCodeFileName)
{
const enCodeFilePath = DigitalWatermarking.getAbsoluteFilePath(enCodeFileName);
DigitalWatermarking.existsFilePath(enCodeFilePath);
return await lib.getTextFormImage(
enCodeFileName,
DigitalWatermarking.getAbsoluteFilePath(deCodeFileName)
);
}
static async getTextFormImageBuffer(enCodeBuffer) {
DigitalWatermarking.isBuffer(enCodeBuffer);
return await lib.getTextFormImage(
enCodeBuffer
);
}
}
module.exports = DigitalWatermarking;
================================================
FILE: lib.js
================================================
const Jimp = require('jimp');
const requireVm = require('require-vm');
let libConfig={
opencvJsPath:''
};
function getConfig() {
return libConfig
}
function setConfig(configData) {
libConfig = configData
}
function isReadyFunc () {
return new Promise((reslove,reject)=>{
const context = {
module:{exports:{}},
Module:{
onRuntimeInitialized() {
context.cv = context.module.exports();
const cv = context.cv;
cv.idft = function(src, dst, flags, nonzero_rows ) {
cv.dft( src, dst, flags | cv.DFT_INVERSE, nonzero_rows );
}
return reslove(context);
},
onAbort() {
return reject(new Error('loading opencv error'))
}
},
print:console.log
}
requireVm(libConfig.opencvJsPath || './opencv.js',context,{},{},true)
})
}
function shiftDFT(cv, mag) {
let rect = new cv.Rect(0, 0, mag.cols & (-2), mag.rows & (-2));
mag.roi(rect);
let cx = mag.cols / 2;
let cy = mag.rows / 2;
let q0 = mag.roi(new cv.Rect(0, 0, cx, cy));
let q1 = mag.roi(new cv.Rect(cx, 0, cx, cy));
let q2 = mag.roi(new cv.Rect(0, cy, cx, cy));
let q3 = mag.roi(new cv.Rect(cx, cy, cx, cy));
let tmp = new cv.Mat();
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
tmp.delete()
q0.delete()
q1.delete()
q2.delete()
q3.delete()
}
function getBlueChannel(cv, image)
{
let nextImg = image;
let channel = new cv.MatVector();
cv.split(nextImg, channel);
return channel.get(0);
}
function getDftMat(cv, padded)
{
let planes = new cv.MatVector();
planes.push_back(padded);
let matZ = new cv.Mat.zeros(padded.size(), cv.CV_32F)
planes.push_back(matZ);
let comImg = new cv.Mat();
cv.merge(planes,comImg);
cv.dft(comImg, comImg);
matZ.delete();
return comImg;
}
function addTextByMat(cv, comImg,watermarkText,point,fontSize)
{
cv.putText(comImg, watermarkText, point, cv.FONT_HERSHEY_DUPLEX, fontSize, cv.Scalar.all(0),2);
cv.flip(comImg, comImg, -1);
cv.putText(comImg, watermarkText, point, cv.FONT_HERSHEY_DUPLEX, fontSize, cv.Scalar.all(0),2);
cv.flip(comImg, comImg, -1);
}
function transFormMatWithText(cv, srcImg, watermarkText,fontSize) {
let padded = getBlueChannel(cv, srcImg);
padded.convertTo(padded, cv.CV_32F);
let comImg = getDftMat(cv, padded);
// add text
let center = new cv.Point(padded.cols/2, padded.rows/2);
addTextByMat(cv, comImg,watermarkText,center,fontSize);
let outer = new cv.Point (45, 45);
addTextByMat(cv, comImg,watermarkText,outer,fontSize);
//back image
let invDFT = new cv.Mat();
cv.idft(comImg, invDFT, cv.DFT_SCALE | cv.DFT_REAL_OUTPUT, 0);
let restoredImage = new cv.Mat();
invDFT.convertTo(restoredImage, cv.CV_8U);
let backPlanes = new cv.MatVector();
cv.split(srcImg, backPlanes);
// backPlanes.erase(backPlanes.get(0));
// backPlanes.insert(backPlanes.get(0), restoredImage);
backPlanes.set(0,restoredImage)
let backImage = new cv.Mat();
cv.merge(backPlanes,backImage);
padded.delete();
comImg.delete();
invDFT.delete();
restoredImage.delete()
return backImage;
}
function getTextFormMat(cv, backImage) {
let padded= getBlueChannel(cv, backImage);
padded.convertTo(padded, cv.CV_32F);
let comImg = getDftMat(cv, padded);
let backPlanes = new cv.MatVector();
// split the comples image in two backPlanes
cv.split(comImg, backPlanes);
let mag = new cv.Mat();
// compute the magnitude
cv.magnitude(backPlanes.get(0), backPlanes.get(1), mag);
// move to a logarithmic scale
let matOne = cv.Mat.ones(mag.size(), cv.CV_32F)
cv.add(matOne, mag, mag);
cv.log(mag, mag);
shiftDFT(cv, mag);
mag.convertTo(mag, cv.CV_8UC1);
cv.normalize(mag, mag, 0, 255, cv.NORM_MINMAX, cv.CV_8UC1);
padded.delete();
comImg.delete();
matOne.delete();
return mag;
}
function matToBuffer(cv, mat){
if(!(mat instanceof cv.Mat)){
throw new Error("Please input the valid new cv.Mat instance.");
}
var img=new cv.Mat();
var depth=mat.type()%8;
var scale=depth<=cv.CV_8S?1:depth<=cv.CV_32S?1/256:255;
var shift=depth===cv.CV_8S||depth===cv.CV_16S?128:0;
mat.convertTo(img,cv.CV_8U,scale,shift);
switch(img.type()){
case cv.CV_8UC1:cv.cvtColor(img,img,cv.COLOR_GRAY2RGBA);break;
case cv.CV_8UC3:cv.cvtColor(img,img,cv.COLOR_RGB2RGBA);break;
case cv.CV_8UC4:break;
default:throw new Error("Bad number of channels (Source image must have 1, 3 or 4 channels)");
}
var imgData=Buffer.from(img.data);
img.delete()
return imgData
}
async function transformImageWithText(srcFileName,watermarkText,fontSize,enCodeFileName='') {
const context = await isReadyFunc ()
const cv = context.cv;
if((typeof srcFileName)!='string' && (!(srcFileName instanceof Buffer))) {
throw new Error('fileName must be string or Buffer')
}
if((typeof watermarkText)!='string') {
throw new Error('waterMarkText must be string')
}
if((typeof fontSize)!='number') {
throw new Error('fontSize must be number')
}
if((typeof enCodeFileName)!='string') {
throw new Error('outFileName must be string')
}
let jimpSrc = await Jimp.read(srcFileName);
let srcImg = new cv.matFromImageData(jimpSrc.bitmap);
if (srcImg.empty()){throw new Error("read image failed");}
let comImg = transFormMatWithText(cv, srcImg, watermarkText, fontSize);
const imgRes = new Jimp({
width: comImg.cols,
height: comImg.rows,
data: matToBuffer(cv, comImg)
});
srcImg.delete();
comImg.delete();
if(enCodeFileName) {
return await imgRes.writeAsync(enCodeFileName);
} else {
return imgRes
}
}
async function getTextFormImage(enCodeFileName,deCodeFileName='') {
const context = await isReadyFunc ()
const cv = context.cv;
if((typeof enCodeFileName)!='string' && (!(enCodeFileName instanceof Buffer))) {
throw new Error('fileName must be string or Buffer')
}
if((typeof deCodeFileName)!='string') {
throw new Error('backFileName must be string')
}
let jimpSrc = await Jimp.read(enCodeFileName);
let comImg = new cv.matFromImageData(jimpSrc.bitmap);
let backImage = getTextFormMat(cv, comImg);
const imgRes = await new Jimp({
width: backImage.cols,
height: backImage.rows,
data: matToBuffer(cv, backImage)
})
comImg.delete();
backImage.delete();
if(deCodeFileName) {
return await imgRes.writeAsync(deCodeFileName);
} else {
return imgRes
}
}
module.exports.transformImageWithText = transformImageWithText;
module.exports.getTextFormImage = getTextFormImage;
module.exports.getConfig = getConfig;
module.exports.setConfig = setConfig;
================================================
FILE: opencv.js
================================================
[File too large to display: 10.9 MB]
================================================
FILE: package.json
================================================
{
"name": "digital-watermarking",
"version": "1.1.15",
"description": "A digital watermark is a kind of marker covertly embedded in a noise-tolerant signal such as an audio, video or image data. It is typically used to identify ownership of the copyright of such signal. \"Watermarking\" is the process of hiding digital information in a carrier signal; the hidden information should, but does not need to, contain a relation to the carrier signal. Digital watermarks may be used to verify the authenticity or integrity of the carrier signal or to show the identity of its owners. It is prominently used for tracing copyright infringements and for banknote authentication.",
"main": "index.js",
"scripts": {
"test": "node ./test/test.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/zy445566/node-digital-watermarking.git"
},
"keywords": [
"digital",
"watermark",
"embedded",
"hidden"
],
"author": "zy445566",
"license": "MIT",
"gypfile": true,
"bugs": {
"url": "https://github.com/zy445566/node-digital-watermarking/issues"
},
"homepage": "https://github.com/zy445566/node-digital-watermarking#readme",
"dependencies": {
"@types/node": "^14.0.12",
"jimp": "^0.12.1",
"require-vm": "^1.0.8"
}
}
================================================
FILE: test/test.js
================================================
const dw = require('../index');
const path = require('path');
const fs = require('fs');
const Jimp = require('jimp');
function getAbsolutePath(fileName) {
return path.join(__dirname,fileName)
}
//EnCode Image add digital watermarking
let srcFileName = getAbsolutePath("srcImg.png");
let watermarkText = "github.com/zy445566";
let fontSize = 1.1;
let enCodeFileName = getAbsolutePath("enCode.png");
async function run() {
dw.setConfig({opencvJsPath:path.join(__dirname,'../opencv.js')})
await dw.transformImageWithText(srcFileName,watermarkText,fontSize,enCodeFileName);
//DeCode Image get digital watermarking
let deCodeFileName = getAbsolutePath("deCode.png");
await dw.getTextFormImage(enCodeFileName,deCodeFileName);
// let startTime = new Date().getTime();
// for(let i=0;i<1000;i++) {
const enCodeFileRes = await dw.transformImageBufferWithText(fs.readFileSync(srcFileName),watermarkText,fontSize);
const deCodeFileRes = await dw.getTextFormImageBuffer(fs.readFileSync(enCodeFileName));
// console.log(enCodeFileRes instanceof Jimp,deCodeFileRes instanceof Jimp, i)
// }
// console.log('runTime',new Date().getTime()-startTime);
}
run()
gitextract_5caq41ia/
├── .github/
│ └── workflows/
│ └── npmpublish.yml
├── .gitignore
├── LICENSE
├── README.md
├── index.d.ts
├── index.js
├── lib.js
├── opencv.js
├── package.json
└── test/
└── test.js
SYMBOL INDEX (25 symbols across 4 files)
FILE: index.d.ts
class DigitalWatermarking (line 3) | class DigitalWatermarking {
FILE: index.js
class DigitalWatermarking (line 4) | class DigitalWatermarking{
method getConfig (line 5) | static getConfig() {
method setConfig (line 9) | static setConfig({opencvJsPath}) {
method getAbsoluteFilePath (line 13) | static getAbsoluteFilePath(filePath)
method existsFilePath (line 18) | static existsFilePath(filePath)
method isBuffer (line 22) | static isBuffer(fileBuf)
method transformImageWithText (line 29) | static async transformImageWithText(srcFileName,watermarkText,fontSize...
method transformImageBufferWithText (line 40) | static async transformImageBufferWithText(srcBuffer,watermarkText,font...
method getTextFormImage (line 49) | static async getTextFormImage(enCodeFileName,deCodeFileName)
method getTextFormImageBuffer (line 58) | static async getTextFormImageBuffer(enCodeBuffer) {
FILE: lib.js
function getConfig (line 8) | function getConfig() {
function setConfig (line 11) | function setConfig(configData) {
function isReadyFunc (line 15) | function isReadyFunc () {
function shiftDFT (line 38) | function shiftDFT(cv, mag) {
function getBlueChannel (line 66) | function getBlueChannel(cv, image)
function getDftMat (line 74) | function getDftMat(cv, padded)
function addTextByMat (line 87) | function addTextByMat(cv, comImg,watermarkText,point,fontSize)
function transFormMatWithText (line 95) | function transFormMatWithText(cv, srcImg, watermarkText,fontSize) {
function getTextFormMat (line 124) | function getTextFormMat(cv, backImage) {
function matToBuffer (line 148) | function matToBuffer(cv, mat){
function transformImageWithText (line 168) | async function transformImageWithText(srcFileName,watermarkText,fontSize...
function getTextFormImage (line 201) | async function getTextFormImage(enCodeFileName,deCodeFileName='') {
FILE: test/test.js
function getAbsolutePath (line 5) | function getAbsolutePath(fileName) {
function run (line 13) | async function run() {
Condensed preview — 10 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (19K chars).
[
{
"path": ".github/workflows/npmpublish.yml",
"chars": 1149,
"preview": "name: Node.js Package\r\n\r\non:\r\n push:\r\n branches:\r\n - master\r\n\r\njobs:\r\n build-node-8:\r\n runs-on: ubuntu-late"
},
{
"path": ".gitignore",
"chars": 919,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directo"
},
{
"path": "LICENSE",
"chars": 1066,
"preview": "MIT License\n\nCopyright (c) 2017 ZhangYuan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
},
{
"path": "README.md",
"chars": 1990,
"preview": "# node-digital-watermarking\r\n[A digital watermark is a kind of marker covertly embedded in a noise-tolerant signal such "
},
{
"path": "index.d.ts",
"chars": 914,
"preview": "import Jimp from \"jimp/*\";\n\ndeclare class DigitalWatermarking {\n static transformImageWithText(\n srcFileName:s"
},
{
"path": "index.js",
"chars": 1985,
"preview": "const lib = require('./lib.js');\nconst path = require('path');\nconst fs = require('fs');\nclass DigitalWatermarking{\n "
},
{
"path": "lib.js",
"chars": 7020,
"preview": "const Jimp = require('jimp');\nconst requireVm = require('require-vm');\n\nlet libConfig={\n opencvJsPath:''\n};\n\nfunction g"
},
{
"path": "package.json",
"chars": 1326,
"preview": "{\r\n \"name\": \"digital-watermarking\",\r\n \"version\": \"1.1.15\",\r\n \"description\": \"A digital watermark is a kind of marker "
},
{
"path": "test/test.js",
"chars": 1212,
"preview": "const dw = require('../index');\nconst path = require('path');\nconst fs = require('fs');\nconst Jimp = require('jimp');\nfu"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the zy445566/node-digital-watermarking GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 10 files (10.9 MB), approximately 4.9k tokens, and a symbol index with 25 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.