출력 형식 API
Sharp는 다양한 이미지 출력 형식을 지원하며, 각 형식에는 특정 옵션과 용도가 있습니다.
JPEG 형식
기본 사용법
javascript
import sharp from 'sharp';
sharp('input.png')
.jpeg()
.toFile('output.jpg');JPEG 옵션
javascript
sharp('input.png')
.jpeg({
quality: 80, // 품질 (1-100)
progressive: false, // 프로그레시브 JPEG
chromaSubsampling: '4:4:4', // 색상 서브샘플링
mozjpeg: false, // mozjpeg 인코더 사용
trellisQuantisation: false, // 트렐리스 양자화
overshootDeringing: false, // 오버슈트 디링잉
optimiseScans: false, // 스캔 최적화
quantisationTable: 0 // 양자화 테이블
})
.toFile('output.jpg');품질 설정
javascript
// 고품질
sharp('input.png').jpeg({ quality: 95 })
// 중간 품질
sharp('input.png').jpeg({ quality: 80 })
// 저품질 (작은 파일)
sharp('input.png').jpeg({ quality: 50 })PNG 형식
기본 사용법
javascript
sharp('input.jpg')
.png()
.toFile('output.png');PNG 옵션
javascript
sharp('input.jpg')
.png({
progressive: false, // 프로그레시브 PNG
compressionLevel: 6, // 압축 레벨 (0-9)
adaptiveFiltering: false, // 적응형 필터링
palette: false, // 팔레트 모드
quality: 100, // 품질 (팔레트 모드에만 사용)
colours: 256, // 색상 수 (팔레트 모드에만 사용)
dither: 0.5, // 디더링 (0-1)
force: false // PNG 출력 강제
})
.toFile('output.png');투명도 처리
javascript
// 투명도 유지
sharp('input.png')
.png()
.toFile('output.png');
// 흰색 배경 추가
sharp('input.png')
.flatten({ background: { r: 255, g: 255, b: 255 } })
.png()
.toFile('output.png');WebP 형식
기본 사용법
javascript
sharp('input.jpg')
.webp()
.toFile('output.webp');WebP 옵션
javascript
sharp('input.jpg')
.webp({
quality: 80, // 품질 (1-100)
alphaQuality: 100, // 투명도 품질 (1-100)
lossless: false, // 무손실 압축
nearLossless: false, // 거의 무손실 압축
smartSubsample: false, // 스마트 서브샘플링
reductionEffort: 4, // 압축 노력 (0-6)
mixed: false, // 혼합 모드
force: false // WebP 출력 강제
})
.toFile('output.webp');무손실 WebP
javascript
// 무손실 압축
sharp('input.png')
.webp({ lossless: true })
.toFile('output.webp');
// 거의 무손실 압축
sharp('input.png')
.webp({ nearLossless: true, quality: 60 })
.toFile('output.webp');AVIF 형식
기본 사용법
javascript
sharp('input.jpg')
.avif()
.toFile('output.avif');AVIF 옵션
javascript
sharp('input.jpg')
.avif({
quality: 80, // 품질 (1-100)
lossless: false, // 무손실 압축
effort: 4, // 압축 노력 (0-6)
chromaSubsampling: '4:4:4', // 색상 서브샘플링
force: false // AVIF 출력 강제
})
.toFile('output.avif');TIFF 형식
기본 사용법
javascript
sharp('input.jpg')
.tiff()
.toFile('output.tiff');TIFF 옵션
javascript
sharp('input.jpg')
.tiff({
quality: 80, // 품질 (1-100)
compression: 'jpeg', // 압축 방식
pyramid: false, // 피라미드 모드
tile: false, // 타일 모드
tileSize: 256, // 타일 크기
xres: 1, // X 해상도
yres: 1, // Y 해상도
resolutionUnit: 'inch', // 해상도 단위
force: false // TIFF 출력 강제
})
.toFile('output.tiff');압축 옵션
javascript
// JPEG 압축
sharp('input.jpg').tiff({ compression: 'jpeg' })
// LZW 압축
sharp('input.jpg').tiff({ compression: 'lzw' })
// 압축 없음
sharp('input.jpg').tiff({ compression: 'none' })
// Deflate 압축
sharp('input.jpg').tiff({ compression: 'deflate' })원시 형식 (raw)
원시 픽셀 데이터 출력
javascript
// RGB 원시 데이터 출력
const rawData = await sharp('input.jpg')
.raw()
.toBuffer();
// RGBA 원시 데이터 출력
const rawData = await sharp('input.jpg')
.ensureAlpha()
.raw()
.toBuffer();다중 형식 출력
여러 형식 동시 출력
javascript
const image = sharp('input.jpg').resize(800, 600);
// 여러 형식 출력
await Promise.all([
image.clone().jpeg({ quality: 80 }).toFile('output.jpg'),
image.clone().png().toFile('output.png'),
image.clone().webp({ quality: 80 }).toFile('output.webp'),
image.clone().avif({ quality: 80 }).toFile('output.avif')
]);반응형 이미지
javascript
async function generateResponsiveImages(inputPath) {
const sizes = [320, 640, 1280, 1920];
const formats = ['jpeg', 'webp', 'avif'];
const promises = [];
for (const size of sizes) {
for (const format of formats) {
const image = sharp(inputPath).resize(size);
switch (format) {
case 'jpeg':
promises.push(
image.clone().jpeg({ quality: 80 })
.toFile(`output-${size}.jpg`)
);
break;
case 'webp':
promises.push(
image.clone().webp({ quality: 80 })
.toFile(`output-${size}.webp`)
);
break;
case 'avif':
promises.push(
image.clone().avif({ quality: 80 })
.toFile(`output-${size}.avif`)
);
break;
}
}
}
await Promise.all(promises);
}형식 감지
파일 확장자에 따라 형식 자동 선택
javascript
function getOutputFormat(filename) {
const ext = filename.split('.').pop().toLowerCase();
switch (ext) {
case 'jpg':
case 'jpeg':
return 'jpeg';
case 'png':
return 'png';
case 'webp':
return 'webp';
case 'avif':
return 'avif';
case 'tiff':
case 'tif':
return 'tiff';
default:
return 'jpeg';
}
}
async function convertImage(inputPath, outputPath) {
const format = getOutputFormat(outputPath);
const image = sharp(inputPath);
switch (format) {
case 'jpeg':
await image.jpeg({ quality: 80 }).toFile(outputPath);
break;
case 'png':
await image.png().toFile(outputPath);
break;
case 'webp':
await image.webp({ quality: 80 }).toFile(outputPath);
break;
case 'avif':
await image.avif({ quality: 80 }).toFile(outputPath);
break;
case 'tiff':
await image.tiff({ compression: 'jpeg' }).toFile(outputPath);
break;
}
}성능 최적화
스트림 출력
javascript
const fs = require('fs');
// 스트림 처리
fs.createReadStream('input.jpg')
.pipe(sharp().jpeg({ quality: 80 }))
.pipe(fs.createWriteStream('output.jpg'));메모리 최적화
javascript
// 파일 대신 Buffer 사용
const buffer = await sharp('input.jpg')
.jpeg({ quality: 80 })
.toBuffer();
// 응답에 직접 출력
app.get('/image', async (req, res) => {
const buffer = await sharp('input.jpg')
.resize(300, 200)
.jpeg({ quality: 80 })
.toBuffer();
res.set('Content-Type', 'image/jpeg');
res.send(buffer);
});