API Siêu dữ liệu
Sharp cung cấp các chức năng phong phú để thao tác siêu dữ liệu, có thể đọc, sửa đổi và ghi thông tin siêu dữ liệu của hình ảnh.
Đọc siêu dữ liệu
Cách sử dụng cơ bản
javascript
import sharp from 'sharp';
// Đọc siêu dữ liệu hình ảnh
const metadata = await sharp('input.jpg').metadata();
console.log(metadata);Cấu trúc đối tượng siêu dữ liệu
javascript
{
format: 'jpeg', // Định dạng hình ảnh
width: 1920, // Chiều rộng
height: 1080, // Chiều cao
space: 'srgb', // Không gian màu
channels: 3, // Số kênh
depth: 'uchar', // Độ sâu bit
density: 72, // Độ phân giải
hasProfile: false, // Có hồ sơ màu không
hasAlpha: false, // Có kênh trong suốt không
isOpaque: true, // Có mờ đục không
orientation: 1, // Hướng EXIF
exif: { ... }, // Dữ liệu EXIF
icc: { ... }, // Hồ sơ ICC
iptc: { ... }, // Dữ liệu IPTC
xmp: { ... }, // Dữ liệu XMP
tifftagPhotoshop: { ... } // Thẻ TIFF Photoshop
}Dữ liệu EXIF
Đọc EXIF
javascript
const metadata = await sharp('input.jpg').metadata();
if (metadata.exif) {
console.log('Dữ liệu EXIF:', metadata.exif);
// Phân tích dữ liệu EXIF
const exif = sharp.exif(metadata.exif);
console.log('Thời gian chụp:', exif.DateTime);
console.log('Model máy ảnh:', exif.Model);
console.log('ISO:', exif.ISOSpeedRatings);
}Ghi EXIF
javascript
// Tạo dữ liệu EXIF
const exif = sharp.exif({
IFD0: {
ImageDescription: 'Hình ảnh được xử lý bằng Sharp',
Copyright: '© 2024'
},
IFD1: {
Orientation: 1
},
EXIF: {
DateTimeOriginal: new Date().toISOString(),
UserComment: 'Được xử lý bằng Sharp'
}
});
// Ghi dữ liệu EXIF
await sharp('input.jpg')
.withMetadata({ exif })
.jpeg()
.toFile('output.jpg');Hồ sơ màu ICC
Đọc hồ sơ ICC
javascript
const metadata = await sharp('input.jpg').metadata();
if (metadata.icc) {
console.log('Hồ sơ ICC:', metadata.icc);
}Nhúng hồ sơ ICC
javascript
// Nhúng hồ sơ sRGB
await sharp('input.jpg')
.withMetadata({ icc: 'srgb' })
.jpeg()
.toFile('output.jpg');
// Nhúng hồ sơ ICC tùy chỉnh
const iccProfile = fs.readFileSync('custom.icc');
await sharp('input.jpg')
.withMetadata({ icc: iccProfile })
.jpeg()
.toFile('output.jpg');Dữ liệu IPTC
Đọc IPTC
javascript
const metadata = await sharp('input.jpg').metadata();
if (metadata.iptc) {
console.log('Dữ liệu IPTC:', metadata.iptc);
}Ghi IPTC
javascript
const iptc = {
'2:05': 'Object Name',
'2:15': 'Category',
'2:25': 'Keywords',
'2:55': 'Date Created',
'2:80': 'By-line',
'2:116': 'Copyright'
};
await sharp('input.jpg')
.withMetadata({ iptc })
.jpeg()
.toFile('output.jpg');Dữ liệu XMP
Đọc XMP
javascript
const metadata = await sharp('input.jpg').metadata();
if (metadata.xmp) {
console.log('Dữ liệu XMP:', metadata.xmp);
}Ghi XMP
javascript
const xmp = `
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title>Hình ảnh được xử lý bằng Sharp</dc:title>
<dc:creator>Sharp</dc:creator>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
`;
await sharp('input.jpg')
.withMetadata({ xmp })
.jpeg()
.toFile('output.jpg');Thông tin hướng
Đọc hướng
javascript
const metadata = await sharp('input.jpg').metadata();
console.log('Hướng hình ảnh:', metadata.orientation);Tự động xoay
javascript
// Tự động xoay theo hướng EXIF
await sharp('input.jpg')
.rotate() // Tự động xoay
.jpeg()
.toFile('output.jpg');Thông tin độ phân giải
Đọc độ phân giải
javascript
const metadata = await sharp('input.jpg').metadata();
console.log('Độ phân giải:', metadata.density);Thiết lập độ phân giải
javascript
await sharp('input.jpg')
.withMetadata({ density: 300 })
.jpeg()
.toFile('output.jpg');Giữ lại siêu dữ liệu
Giữ lại tất cả siêu dữ liệu
javascript
// Giữ lại tất cả siêu dữ liệu hiện có
await sharp('input.jpg')
.resize(800, 600)
.withMetadata()
.jpeg()
.toFile('output.jpg');Giữ lại có chọn lọc
javascript
// Chỉ giữ lại dữ liệu EXIF
await sharp('input.jpg')
.resize(800, 600)
.withMetadata({ exif: true })
.jpeg()
.toFile('output.jpg');
// Giữ lại EXIF và ICC
await sharp('input.jpg')
.resize(800, 600)
.withMetadata({ exif: true, icc: true })
.jpeg()
.toFile('output.jpg');Xóa siêu dữ liệu
Xóa tất cả siêu dữ liệu
javascript
// Xóa tất cả siêu dữ liệu
await sharp('input.jpg')
.resize(800, 600)
.jpeg()
.toFile('output.jpg');Xóa siêu dữ liệu cụ thể
javascript
// Xóa EXIF nhưng giữ lại phần còn lại
await sharp('input.jpg')
.resize(800, 600)
.withMetadata({ exif: false })
.jpeg()
.toFile('output.jpg');Xử lý hàng loạt siêu dữ liệu
Đọc hàng loạt
javascript
const fs = require('fs').promises;
async function batchReadMetadata(directory) {
const files = await fs.readdir(directory);
const results = [];
for (const file of files) {
if (file.match(/\.(jpg|jpeg|png|webp)$/i)) {
try {
const metadata = await sharp(`${directory}/${file}`).metadata();
results.push({ file, metadata });
} catch (error) {
console.error(`Đọc siêu dữ liệu ${file} thất bại:`, error.message);
}
}
}
return results;
}Ghi hàng loạt
javascript
async function batchWriteMetadata(directory, metadata) {
const files = await fs.readdir(directory);
for (const file of files) {
if (file.match(/\.(jpg|jpeg|png|webp)$/i)) {
try {
await sharp(`${directory}/${file}`)
.withMetadata(metadata)
.toFile(`${directory}/processed_${file}`);
} catch (error) {
console.error(`Xử lý ${file} thất bại:`, error.message);
}
}
}
}Xác thực siêu dữ liệu
Xác thực tính toàn vẹn siêu dữ liệu
javascript
async function validateMetadata(filePath) {
try {
const metadata = await sharp(filePath).metadata();
// Kiểm tra các thuộc tính cơ bản
if (!metadata.width || !metadata.height) {
throw new Error('Thiếu thông tin kích thước');
}
// Kiểm tra định dạng
if (!metadata.format) {
throw new Error('Thiếu thông tin định dạng');
}
// Kiểm tra số kênh
if (!metadata.channels) {
throw new Error('Thiếu thông tin kênh');
}
return {
valid: true,
metadata
};
} catch (error) {
return {
valid: false,
error: error.message
};
}
}Tối ưu hiệu suất
Chỉ đọc siêu dữ liệu cần thiết
javascript
// Chỉ đọc thông tin cơ bản, không phân tích EXIF
const metadata = await sharp('input.jpg')
.metadata({ pages: -1 });
// Chỉ đọc EXIF
const metadata = await sharp('input.jpg')
.metadata({ exif: true });Xử lý luồng
javascript
const fs = require('fs');
// Đọc siêu dữ liệu theo luồng
const stream = fs.createReadStream('input.jpg');
const metadata = await sharp(stream).metadata();Xử lý lỗi
javascript
try {
const metadata = await sharp('input.jpg').metadata();
console.log('Siêu dữ liệu:', metadata);
} catch (error) {
if (error.code === 'VipsForeignLoad') {
console.error('Định dạng hình ảnh không được hỗ trợ');
} else if (error.code === 'VipsForeignLoadLimit') {
console.error('Hình ảnh quá lớn');
} else {
console.error('Đọc siêu dữ liệu thất bại:', error.message);
}
}