メタデータ API
Sharp は豊富なメタデータ操作機能を提供し、画像のメタデータ情報を読み取り、変更、書き込みできます。
メタデータの読み取り
基本的な使い方
javascript
import sharp from 'sharp';
// 画像メタデータを読み取る
const metadata = await sharp('input.jpg').metadata();
console.log(metadata);メタデータオブジェクトの構造
javascript
{
format: 'jpeg', // 画像形式
width: 1920, // 幅
height: 1080, // 高さ
space: 'srgb', // カラースペース
channels: 3, // チャンネル数
depth: 'uchar', // ビット深度
density: 72, // 解像度
hasProfile: false, // カラープロファイルの有無
hasAlpha: false, // 透明度チャンネルの有無
isOpaque: true, // 不透明かどうか
orientation: 1, // EXIF 方向
exif: { ... }, // EXIF データ
icc: { ... }, // ICC プロファイル
iptc: { ... }, // IPTC データ
xmp: { ... }, // XMP データ
tifftagPhotoshop: { ... } // Photoshop TIFF タグ
}EXIF データ
EXIF の読み取り
javascript
const metadata = await sharp('input.jpg').metadata();
if (metadata.exif) {
console.log('EXIF データ:', metadata.exif);
// EXIF データを解析
const exif = sharp.exif(metadata.exif);
console.log('撮影時刻:', exif.DateTime);
console.log('カメラモデル:', exif.Model);
console.log('ISO:', exif.ISOSpeedRatings);
}EXIF の書き込み
javascript
// EXIF データを作成
const exif = sharp.exif({
IFD0: {
ImageDescription: 'Sharp で処理された画像',
Copyright: '© 2024'
},
IFD1: {
Orientation: 1
},
EXIF: {
DateTimeOriginal: new Date().toISOString(),
UserComment: 'Sharp で処理'
}
});
// EXIF データを書き込む
await sharp('input.jpg')
.withMetadata({ exif })
.jpeg()
.toFile('output.jpg');ICC カラープロファイル
ICC プロファイルの読み取り
javascript
const metadata = await sharp('input.jpg').metadata();
if (metadata.icc) {
console.log('ICC プロファイル:', metadata.icc);
}ICC プロファイルの埋め込み
javascript
// sRGB プロファイルを埋め込む
await sharp('input.jpg')
.withMetadata({ icc: 'srgb' })
.jpeg()
.toFile('output.jpg');
// カスタム ICC プロファイルを埋め込む
const iccProfile = fs.readFileSync('custom.icc');
await sharp('input.jpg')
.withMetadata({ icc: iccProfile })
.jpeg()
.toFile('output.jpg');IPTC データ
IPTC の読み取り
javascript
const metadata = await sharp('input.jpg').metadata();
if (metadata.iptc) {
console.log('IPTC データ:', metadata.iptc);
}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');XMP データ
XMP の読み取り
javascript
const metadata = await sharp('input.jpg').metadata();
if (metadata.xmp) {
console.log('XMP データ:', metadata.xmp);
}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>Sharp で処理された画像</dc:title>
<dc:creator>Sharp</dc:creator>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
`;
await sharp('input.jpg')
.withMetadata({ xmp })
.jpeg()
.toFile('output.jpg');方向情報
方向の読み取り
javascript
const metadata = await sharp('input.jpg').metadata();
console.log('画像の方向:', metadata.orientation);自動回転
javascript
// EXIF 方向に基づいて自動回転
await sharp('input.jpg')
.rotate() // 自動回転
.jpeg()
.toFile('output.jpg');解像度情報
解像度の読み取り
javascript
const metadata = await sharp('input.jpg').metadata();
console.log('解像度:', metadata.density);解像度の設定
javascript
await sharp('input.jpg')
.withMetadata({ density: 300 })
.jpeg()
.toFile('output.jpg');メタデータの保持
すべてのメタデータを保持
javascript
// 既存のすべてのメタデータを保持
await sharp('input.jpg')
.resize(800, 600)
.withMetadata()
.jpeg()
.toFile('output.jpg');選択的な保持
javascript
// EXIF データのみを保持
await sharp('input.jpg')
.resize(800, 600)
.withMetadata({ exif: true })
.jpeg()
.toFile('output.jpg');
// EXIF と ICC を保持
await sharp('input.jpg')
.resize(800, 600)
.withMetadata({ exif: true, icc: true })
.jpeg()
.toFile('output.jpg');メタデータの削除
すべてのメタデータを削除
javascript
// すべてのメタデータを削除
await sharp('input.jpg')
.resize(800, 600)
.jpeg()
.toFile('output.jpg');特定のメタデータを削除
javascript
// EXIF を削除し、その他を保持
await sharp('input.jpg')
.resize(800, 600)
.withMetadata({ exif: false })
.jpeg()
.toFile('output.jpg');バッチ処理メタデータ
バッチ読み取り
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(`${file} のメタデータ読み取り失敗:`, error.message);
}
}
}
return results;
}バッチ書き込み
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(`${file} の処理失敗:`, error.message);
}
}
}
}メタデータの検証
メタデータの整合性を検証
javascript
async function validateMetadata(filePath) {
try {
const metadata = await sharp(filePath).metadata();
// 基本属性をチェック
if (!metadata.width || !metadata.height) {
throw new Error('サイズ情報が不足しています');
}
// 形式をチェック
if (!metadata.format) {
throw new Error('形式情報が不足しています');
}
// チャンネル数をチェック
if (!metadata.channels) {
throw new Error('チャンネル情報が不足しています');
}
return {
valid: true,
metadata
};
} catch (error) {
return {
valid: false,
error: error.message
};
}
}パフォーマンス最適化
必要なメタデータのみを読み取る
javascript
// 基本情報のみを読み取り、EXIF を解析しない
const metadata = await sharp('input.jpg')
.metadata({ pages: -1 });
// EXIF のみを読み取る
const metadata = await sharp('input.jpg')
.metadata({ exif: true });ストリーム処理
javascript
const fs = require('fs');
// ストリームでメタデータを読み取る
const stream = fs.createReadStream('input.jpg');
const metadata = await sharp(stream).metadata();エラー処理
javascript
try {
const metadata = await sharp('input.jpg').metadata();
console.log('メタデータ:', metadata);
} catch (error) {
if (error.code === 'VipsForeignLoad') {
console.error('サポートされていない画像形式');
} else if (error.code === 'VipsForeignLoadLimit') {
console.error('画像が大きすぎます');
} else {
console.error('メタデータ読み取り失敗:', error.message);
}
}