Node.js Native Addon for LibRaw - Process RAW image files with JavaScript
npm install librawspeed一个使用 LibRaw 库处理 RAW 图像文件的高性能 Node.js 原生插件。



![Build Status]()

- ✅ 100+ RAW 格式 - Canon、Nikon、Sony、Adobe DNG 等
- ✅ 全面的元数据 - EXIF 数据、相机设置、尺寸、镜头信息
- ✅ 高级色彩信息 - 色彩矩阵、白平衡、校准数据
- ✅ 图像处理管道 - 完整的 dcraw 兼容处理链
- ✅ 缩略图提取 - 高质量嵌入式缩略图提取
- ✅ RAW 转 JPEG 转换 - 🆕 高性能 JPEG 导出与优化
- ✅ 批量处理 - 🆕 使用智能设置处理数百个文件
- ✅ AI 驱动设置 - 🆕 基于图像分析的自动质量优化
- ✅ 内存操作 - 完全在内存中处理图像
- ✅ 多种输出格式 - PPM、TIFF、JPEG 与高级压缩选项
- ✅ 缓冲区创建 API - 🆕 直接在内存中创建图像缓冲区(JPEG、PNG、WebP、AVIF、TIFF、PPM、缩略图)
- ✅ 基于流的处理 - 🆕 返回数据流而不是写入文件
- ✅ 缓冲区支持 - 从内存缓冲区加载 RAW 数据
- ✅ 配置控制 - 伽马、亮度、色彩空间设置
- ✅ 高性能 - 原生 C++ 处理与 JavaScript 便利性
- ✅ 内存高效 - 适当的资源管理和清理
- ✅ 基于 Promise 的 API - 现代 async/await 支持
- ✅ 跨平台 - Windows、macOS、Linux 支持(已测试 Windows)
- ✅ 1000+ 相机支持 - LibRaw 的广泛相机数据库
- ✅ 全面测试 - 使用真实 RAW 文件 100% 测试覆盖
- ✅ 生产就绪 - 经过多种相机格式实战测试
LibRaw 支持 100+ RAW 格式,包括:
| 制造商 | 格式 |
| -------------------- | ---------------------- |
| 佳能 | .CR2, .CR3, .CRW |
| 尼康 | .NEF, .NRW |
| 索尼 | .ARW, .SRF, .SR2 |
| Adobe | .DNG |
| 富士 | .RAF |
| 奥林巴斯 | .ORF |
| 松下 | .RW2 |
| 宾得 | .PEF |
| 徕卡 | .DNG, .RWL |
| 还有更多... | _总共 100+ 格式_ |
``bash`
npm install librawspeed
版本 1.0.18 现已在 npmjs.com 上可用!🎉
- Node.js 14.0.0 或更高版本
- Python 2.7 或 3.x(用于 node-gyp)
- C++ 编译器:
- Windows: Visual Studio Build Tools 或 Visual Studio Community
- macOS: Xcode Command Line Tools 或 Xcode
- Linux: build-essential 包
💡 提示:node-gyp 会自动处理构建工具,无需手动安装 make 等工具
安装前可以检查环境是否满足要求:
`bash`
npm run check:env
如果安装失败,请尝试:
`bash清理并重新安装
npm run clean
npm run rebuild
常见问题:
1. Python 未找到
`bash
npm config set python python3
`2. 编译器未找到
`bash
# Windows
npm install --global windows-build-tools
# macOS
xcode-select --install
# Linux
sudo apt-get install build-essential
`$3
安装后,验证包是否正常工作:
`bash
node -e "const LibRaw = require('librawspeed'); console.log('LibRaw version:', LibRaw.getVersion());"
`预期输出:
LibRaw version: 0.21.4-Release先决条件(从源码构建)
- Node.js 14.0.0 或更高版本
- Python 3.x(用于 node-gyp)
- Visual Studio Build Tools(Windows)
- Xcode Command Line Tools(macOS)
- build-essential(Linux)
$3
此项目支持多平台交叉编译。有关详细工具链要求和设置说明,请参阅交叉编译指南。
支持的平台:
- ✅ Windows x64
- ✅ macOS x64(Intel)
- ✅ macOS ARM64(Apple Silicon)
- ✅ Linux x64
- ✅ Linux ARM64
快速设置:
`bash
安装所有交叉编译工具链
brew install mingw-w64 aarch64-apple-darwin24-gcc-15 musl-cross构建所有平台
npm run cross-compile:all
`快速开始
`javascript
const LibRaw = require("librawspeed");async function processRAW() {
// 🆕 检查文件是否为 LibRaw 支持的 RAW 格式
const checkResult = LibRaw.isRawFile('photo.cr2');
if (!checkResult.isRawFile) {
console.log('不是支持的 RAW 文件:', checkResult.message);
return;
}
const processor = new LibRaw();
try {
// 加载 RAW 文件
await processor.loadFile("photo.cr2");
// 🆕 新功能:缓冲区创建 API - 直接在内存中创建图像
// 首先处理 RAW 数据
await processor.processImage();
// 创建 JPEG 缓冲区而不写入文件
const jpegBuffer = await processor.createJPEGBuffer({
quality: 85,
width: 1920,
progressive: true,
});
console.log(
JPEG 缓冲区已创建:${jpegBuffer.buffer.length} 字节); // 并行创建多种格式
const [pngResult, webpResult, thumbResult] = await Promise.all([
processor.createPNGBuffer({ width: 1200, compressionLevel: 6 }),
processor.createWebPBuffer({ quality: 80, width: 1200 }),
processor.createThumbnailJPEGBuffer({ maxSize: 300 }),
]);
// 直接使用缓冲区(例如,通过 HTTP 发送、存储到数据库等)
// 无需临时文件!
console.log(
PNG:${pngResult.buffer.length} 字节);
console.log(WebP:${webpResult.buffer.length} 字节);
console.log(缩略图:${thumbResult.buffer.length} 字节); // 🆕 新功能:高性能 JPEG 转换(传统方法仍然可用)
// 使用高级选项将 RAW 转换为 JPEG
const jpegResult = await processor.convertToJPEG("output.jpg", {
quality: 85, // JPEG 质量(1-100)
width: 1920, // 调整到 1920px 宽度
progressive: true, // 用于网络的渐进式 JPEG
mozjpeg: true, // 使用 MozJPEG 获得更好的压缩
chromaSubsampling: "4:2:0", // 优化文件大小
});
console.log(
JPEG 已保存:${jpegResult.metadata.fileSize.compressed / 1024}KB
);
console.log(
压缩率:${jpegResult.metadata.fileSize.compressionRatio}x
);
console.log(处理时间:${jpegResult.metadata.processing.timeMs}ms); // 🆕 AI 驱动的优化设置
const analysis = await processor.getOptimalJPEGSettings({ usage: "web" });
console.log(
推荐质量:${analysis.recommended.quality});
console.log(图像类别:${analysis.imageAnalysis.category}); // 应用优化设置
await processor.convertToJPEG("optimized.jpg", analysis.recommended);
// 提取全面的元数据
const [metadata, advanced, lens, color] = await Promise.all([
processor.getMetadata(),
processor.getAdvancedMetadata(),
processor.getLensInfo(),
processor.getColorInfo(),
]);
console.log("相机:", metadata.make, metadata.model);
console.log("镜头:", lens.lensName || "未知");
console.log(
"设置:",
ISO ${metadata.iso}, f/${metadata.aperture}, ${metadata.focalLength}mm
);
console.log(
"色彩:",
${color.colors} 通道,黑电平 ${color.blackLevel}
); // 传统处理管道(仍然可用)
await processor.setOutputParams({
bright: 1.1, // 亮度调整
gamma: [2.2, 4.5], // 伽马曲线
output_bps: 16, // 16 位输出
no_auto_bright: false, // 启用自动亮度
});
// 处理图像
await processor.raw2Image();
await processor.processImage();
// 在内存中创建处理后的图像
const imageData = await processor.createMemoryImage();
console.log(
已处理:${imageData.width}x${imageData.height},${imageData.dataSize} 字节
); // 导出到文件
await processor.writeTIFF("output.tiff");
await processor.writeThumbnail("thumbnail.jpg");
// 提取高质量缩略图
const thumbnailData = await processor.createMemoryThumbnail();
console.log(
缩略图:${thumbnailData.width}x${thumbnailData.height}); // 始终清理资源
await processor.close();
} catch (error) {
console.error("错误:", error.message);
}
}
processRAW();
`完整的 API 覆盖
此包装器提供全面的 LibRaw 功能,包含 50+ 方法,分为 8 个类别:
$3
- 文件加载(
loadFile、loadBuffer)
- 处理管道(raw2Image、processImage、subtractBlack)
- 资源管理(close、freeImage)$3
- 基本元数据(
getMetadata、getImageSize、getFileInfo)
- 高级元数据(getAdvancedMetadata、getLensInfo、getColorInfo)
- 相机矩阵(getCameraColorMatrix、getRGBCameraMatrix)$3
- 内存操作(
createMemoryImage、createMemoryThumbnail)
- 格式转换(getMemImageFormat、copyMemImage)
- 处理控制(adjustMaximum、adjustSizesInfoOnly)$3
- 输出格式(
writePPM、writeTIFF、writeThumbnail)
- 格式验证和质量控制$3
- 参数控制(
setOutputParams、getOutputParams)
- 处理设置和色彩空间管理$3
- 格式检测(
isFloatingPoint、isFujiRotated、isSRAW)
- 相机特定功能(isNikonSRAW、isCoolscanNEF)$3
- 色彩分析(
getColorAt、convertFloatToInt)
- 白平衡和色彩矩阵操作$3
- 库信息(
getVersion、getCapabilities)
- 相机数据库(getCameraList、getCameraCount)所有方法都经过全面测试,可用于生产环境!
🆕 缓冲区创建 API(新功能)
$3
直接在内存中创建图像缓冲区,无需写入文件。非常适合 Web 应用程序、API 和流式工作流程。
#### 可用的缓冲区方法
`javascript
const processor = new LibRaw();
await processor.loadFile("photo.cr2");
await processor.processImage();// 创建不同格式的缓冲区
const jpegBuffer = await processor.createJPEGBuffer(options);
const pngBuffer = await processor.createPNGBuffer(options);
const webpBuffer = await processor.createWebPBuffer(options);
const avifBuffer = await processor.createAVIFBuffer(options);
const tiffBuffer = await processor.createTIFFBuffer(options);
const ppmBuffer = await processor.createPPMBuffer();
// 无需完整处理即可提取缩略图缓冲区
const processor2 = new LibRaw();
await processor2.loadFile("photo.cr2");
const thumbBuffer = await processor2.createThumbnailJPEGBuffer(options);
`#### 缓冲区创建选项
##### JPEG 缓冲区选项
`javascript
{
quality: 85, // 1-100(默认:85)
width: 1200, // 目标宽度
height: 800, // 目标高度
progressive: true, // 渐进式 JPEG
fastMode: false, // 速度与质量权衡
effort: 4 // 编码努力程度 1-8
}
`##### PNG 缓冲区选项
`javascript
{
width: 1200, // 目标宽度
height: 800, // 目标高度
compressionLevel: 6, // 0-9(默认:6)
fastMode: false // 速度与大小权衡
}
`##### WebP 缓冲区选项
`javascript
{
quality: 80, // 1-100(默认:80)
width: 1200, // 目标宽度
height: 800, // 目标高度
lossless: false, // 无损模式
effort: 4, // 编码努力程度 0-6
fastMode: false // 速度优化
}
`##### AVIF 缓冲区选项
`javascript
{
quality: 50, // 1-100(默认:50)
width: 1200, // 目标宽度
height: 800, // 目标高度
lossless: false, // 无损模式
effort: 4 // 编码努力程度 0-9
}
`##### TIFF 缓冲区选项
`javascript
{
width: 1200, // 目标宽度
height: 800, // 目标高度
compression: 'lzw', // 'none', 'lzw', 'zip'
predictor: 'horizontal' // 压缩预测器
}
`##### 缩略图缓冲区选项
`javascript
{
maxSize: 300, // 最大尺寸
quality: 85, // JPEG 质量 1-100
fastMode: false // 速度优化
}
`#### 使用示例
##### Web API 响应
`javascript
app.get("/api/photo/:id/thumbnail", async (req, res) => {
const processor = new LibRaw();
try {
await processor.loadFile(photos/${req.params.id}.cr2); const result = await processor.createThumbnailJPEGBuffer({
maxSize: 300,
quality: 85,
});
res.set({
"Content-Type": "image/jpeg",
"Content-Length": result.buffer.length,
"Cache-Control": "public, max-age=86400",
});
res.send(result.buffer);
} finally {
await processor.close();
}
});
`##### 多格式生成
`javascript
async function generateFormats(rawFile, outputDir) {
const processor = new LibRaw();
await processor.loadFile(rawFile);
await processor.processImage(); // 并行生成所有格式
const [jpeg, png, webp, avif] = await Promise.all([
processor.createJPEGBuffer({ quality: 85, width: 1920 }),
processor.createPNGBuffer({ width: 1200, compressionLevel: 6 }),
processor.createWebPBuffer({ quality: 80, width: 1920 }),
processor.createAVIFBuffer({ quality: 50, width: 1200 }),
]);
// 根据需要保存或处理缓冲区
fs.writeFileSync(
${outputDir}/image.jpg, jpeg.buffer);
fs.writeFileSync(${outputDir}/image.png, png.buffer);
fs.writeFileSync(${outputDir}/image.webp, webp.buffer);
fs.writeFileSync(${outputDir}/image.avif, avif.buffer); await processor.close();
}
`##### 流式上传
`javascript
async function uploadToCloud(rawFile) {
const processor = new LibRaw();
await processor.loadFile(rawFile);
await processor.processImage(); const webpResult = await processor.createWebPBuffer({
quality: 80,
width: 1600,
});
// 直接将缓冲区上传到云存储
const uploadResult = await cloudStorage.upload(webpResult.buffer, {
contentType: "image/webp",
fileName: "processed-image.webp",
});
await processor.close();
return uploadResult;
}
`#### 缓冲区结果结构
所有缓冲区创建方法都返回一致的结果结构:
`javascript
{
success: true,
buffer: Buffer, // 创建的图像缓冲区
metadata: {
format: "JPEG", // 输出格式
outputDimensions: { // 最终图像尺寸
width: 1920,
height: 1280
},
fileSize: {
original: 50331648, // 原始处理图像大小
compressed: 245760, // 缓冲区大小
compressionRatio: "204.8" // 压缩比
},
processing: {
timeMs: "45.23", // 处理时间
throughputMBps: "15.4" // 处理吞吐量
},
options: { // 应用的选项
quality: 85,
width: 1920,
// ... 其他选项
}
}
}
`#### 性能特征
| 格式 | 典型大小(1920px) | 创建时间 | 压缩比 |
| ---------- | --------------------- | ------------- | ----------------- |
| JPEG | 80-400KB | 200-500ms | 50-200x |
| PNG | 1-4MB | 400-800ms | 12-50x |
| WebP | 50-300KB | 100-300ms | 60-300x |
| AVIF | 30-150KB | 300-800ms | 100-500x |
| TIFF (LZW) | 2-8MB | 100-200ms | 6-25x |
| PPM | 11-45MB | 50-100ms | 1x(未压缩) |
| 缩略图 | 5-50KB | 50-150ms | 200-1000x |
🆕 JPEG 转换(增强功能)
$3
将 RAW 文件转换为优化的 JPEG 格式,具有高级压缩选项和智能设置分析。
#### 基本 JPEG 转换
`javascript
const processor = new LibRaw();
await processor.loadFile("photo.cr2");// 使用默认设置的基本转换
const result = await processor.convertToJPEG("output.jpg");
// 使用自定义选项的高质量转换
const result = await processor.convertToJPEG("high-quality.jpg", {
quality: 95, // JPEG 质量(1-100)
chromaSubsampling: "4:2:2", // 更好的色度用于打印
trellisQuantisation: true, // 高级压缩
optimizeCoding: true, // 霍夫曼优化
});
console.log(
文件大小:${result.metadata.fileSize.compressed / 1024}KB);
console.log(压缩率:${result.metadata.fileSize.compressionRatio}x);
console.log(处理时间:${result.metadata.processing.timeMs}ms);
`#### 网络优化的调整大小转换
`javascript
// 为网络使用转换和调整大小
const webResult = await processor.convertToJPEG("web-optimized.jpg", {
quality: 80, // 网络使用的良好质量
width: 1920, // 调整到 1920px 宽度(保持宽高比)
progressive: true, // 渐进式加载
mozjpeg: true, // 卓越的压缩算法
optimizeScans: true, // 优化以更快加载
});// 创建缩略图
const thumbResult = await processor.convertToJPEG("thumbnail.jpg", {
quality: 85,
width: 400,
height: 300,
chromaSubsampling: "4:2:2", // 小图像的更好质量
});
`#### AI 驱动的优化设置
`javascript
// 分析图像并获取推荐设置
const analysis = await processor.getOptimalJPEGSettings({ usage: "web" });console.log("推荐设置:", analysis.recommended);
console.log("图像分析:", analysis.imageAnalysis);
// 应用推荐设置
const optimizedResult = await processor.convertToJPEG(
"optimized.jpg",
analysis.recommended
);
`#### 批量转换
`javascript
// 使用优化设置转换多个 RAW 文件
const inputFiles = ["photo1.cr2", "photo2.nef", "photo3.arw"];
const outputDir = "./jpeg-output";const batchResult = await processor.batchConvertToJPEG(inputFiles, outputDir, {
quality: 80,
width: 1920,
progressive: true,
mozjpeg: true,
});
console.log(
已处理:${batchResult.summary.processed}/${batchResult.summary.total}
);
console.log(
成功率:${(
);
console.log(
节省空间:${(
);
`$3
| 选项 | 类型 | 默认值 | 描述 |
| --------------------- | ------- | ------- | ---------------------------------------------------- |
|
quality | number | 85 | JPEG 质量(1-100,越高质量越好) |
| width | number | - | 目标宽度(像素,保持宽高比) |
| height | number | - | 目标高度(像素,保持宽高比) |
| progressive | boolean | false | 启用渐进式 JPEG 用于网络优化 |
| mozjpeg | boolean | true | 使用 MozJPEG 编码器获得卓越压缩 |
| chromaSubsampling | string | '4:2:0' | 色度子采样('4:4:4', '4:2:2'\*, '4:2:0') |
| trellisQuantisation | boolean | false | 高级压缩技术 |
| optimizeScans | boolean | false | 优化扫描顺序用于渐进式加载 |
| optimizeCoding | boolean | true | 优化霍夫曼编码表 |
| colorSpace | string | 'srgb' | 输出色彩空间('srgb', 'rec2020', 'p3', 'cmyk') |\*注意:由于 Sharp 库限制,'4:2:2' 色度子采样自动映射到 '4:4:4'。
$3
- 处理速度:在现代硬件上 70-140 MB/s
- 压缩比:典型压缩 2-10x(因内容而异)
- 内存效率:大文件的流式处理
- 质量保持:Q85+ 设置下视觉无损
$3
#### 网络优化
`javascript
{
quality: 80,
width: 1920,
progressive: true,
mozjpeg: true,
chromaSubsampling: '4:2:0',
optimizeScans: true
}
`#### 打印质量
`javascript
{
quality: 95,
chromaSubsampling: '4:2:2',
trellisQuantisation: true,
optimizeCoding: true,
mozjpeg: true
}
`#### 归档/最大质量
`javascript
{
quality: 98,
chromaSubsampling: '4:4:4',
trellisQuantisation: true,
optimizeCoding: true
}
`#### 缩略图生成
`javascript
{
quality: 85,
width: 800,
chromaSubsampling: '4:2:2',
mozjpeg: true
}
`$3
#### 单个文件转换
`bash
node examples/jpeg-conversion-example.js photo.cr2
`#### 批量转换
`bash
网络优化的批量转换
node scripts/batch-jpeg-conversion.js ./raw-photos ./web-gallery 1打印质量转换
node scripts/batch-jpeg-conversion.js ./raw-photos ./print-gallery 2归档质量转换
node scripts/batch-jpeg-conversion.js ./raw-photos ./archive-gallery 3
`#### NPM 脚本
`bash
运行 JPEG 转换测试
npm run test:jpeg-conversion使用 CLI 界面批量转换
npm run convert:jpeg [output-dir] [preset]
```API 参考
$3
####
new LibRaw()创建一个新的 LibRaw 处理器实例。
####
loadFile(filename)从文件系统加载 RAW 文件。
- filename
{string} - RAW 文件路径
- 返回 {Promise - 成功状态####
loadBuffer(buffer)从内存缓冲区加载 RAW 数据。
- buffer
{Buffer} - 包含 RAW 数据的缓冲区
- 返回 {Promise - 成功状态####
close()关闭处理器并释放所有资源。
- 返回
{Promise - 成功状态$3
####
getMetadata()从加载的 RAW 文件中提取基本元数据。
- 返回
{Promise