import { NextResponse } from 'next/server' import { DeleteObjectCommand, GetObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3' import { v4 as uuidv4 } from 'uuid' import { Jimp } from 'jimp' const Bucket = process.env.AMPLIFY_BUCKET const s3 = new S3Client({ region: process.env.AWS_REGION, credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, }, }) const checkArea = (obj) => { const { width, height, left, top } = obj if (left < 0 || top < 0 || width > 1600 || height > 1000) { return false } return true } const cropImage = async (Key, width, height, left, top) => { try { // Get the image from S3 const { Body } = await s3.send( new GetObjectCommand({ Bucket, Key, }), ) const chunks = [] for await (const chunk of Body) { chunks.push(chunk) } const buffer = Buffer.concat(chunks) let image = await Jimp.read(buffer) image.autocrop({ tolerance: 0.0002, leaveBorder: 10 }) const resizedImage = await resizeImage(image).then((result) => { return result }) return await resizedImage.getBuffer('image/png') // Convert stream to buffer // const chunks = [] // for await (const chunk of Body) { // chunks.push(chunk) // } // const imageBuffer = Buffer.concat(chunks) // const image = await Jimp.read(Body) // if (!checkResult) { // processedImage = await image.toBuffer() // } //let processedImage // if (!checkResult) { // processedImage = await sharp(imageBuffer).toBuffer() // } else { // processedImage = await sharp(imageBuffer) // .extract({ // width: parseInt(width), // height: parseInt(height), // left: parseInt(left), // top: parseInt(top), // }) // .png() // .toBuffer() // } // return processedImage } catch (error) { console.error('Error processing image:', error) throw error } } //크롭된 이미지를 배경 크기에 맞게 리사이즈 const resizeImage = async (image) => { //엑셀 템플릿 너비 35.4cm, 높이 12.89cm const convertStandardWidth = Math.round((35.4 * 96) / 2.54) const convertStandardHeight = Math.round((12.89 * 96) / 2.54) // 이미지를 배경의 98%까지 확대 (훨씬 더 크게) const targetImageWidth = convertStandardWidth * 0.98 const targetImageHeight = convertStandardHeight * 0.98 const scaleX = targetImageWidth / image.bitmap.width const scaleY = targetImageHeight / image.bitmap.height let scale = Math.min(scaleX, scaleY) // 비율 유지하면서 최대한 크게 // scale 저장 (나중에 전체 확대에 사용) const originalScale = scale let finalWidth = Math.round(image.bitmap.width * scale) let finalHeight = Math.round(image.bitmap.height * scale) if (scale >= 0.6) { // 실제 리사이즈 실행 image.resize({ w: finalWidth, h: finalHeight }) } //배경 이미지를 생성 const mixedImage = new Jimp({ width: convertStandardWidth, height: convertStandardHeight, color: 0xffffffff }) //이미지를 중앙에 배치 const x = Math.floor((mixedImage.bitmap.width - image.bitmap.width) / 2) const y = Math.floor((mixedImage.bitmap.height - image.bitmap.height) / 2) //이미지를 배경 이미지에 합성 mixedImage.composite(image, x, y, { opacitySource: 1, // 원본 투명도 유지 opacityDest: 1, }) // scale이 0.8 이하인 경우 완성된 이미지를 전체적으로 확대 if (originalScale <= 0.8) { const enlargeRatio = 1.5 // 50% 확대 const newWidth = Math.round(mixedImage.bitmap.width * enlargeRatio) const newHeight = Math.round(mixedImage.bitmap.height * enlargeRatio) mixedImage.resize({ w: newWidth, h: newHeight }) } return mixedImage } export async function POST(req) { try { const formData = await req.formData() const file = formData.get('file') const objectNo = formData.get('objectNo') const planNo = formData.get('planNo') const type = formData.get('type') const width = formData.get('width') const height = formData.get('height') const left = formData.get('left') const top = formData.get('top') const OriginalKey = `Drawing/${uuidv4()}` /** * 원본 이미지를 우선 저장한다. * 이미지 이름이 겹지는 현상을 방지하기 위해 uuid 를 사용한다. */ await s3.send( new PutObjectCommand({ Bucket, Key: OriginalKey, Body: Buffer.from(await file.arrayBuffer()), ContentType: 'image/png', }), ) /** * 저장된 원본 이미지를 기준으로 크롭여부를 결정하여 크롭 이미지를 저장한다. */ const bufferImage = await cropImage(OriginalKey, width, height, left, top) /** * 크롭 이미지 이름을 결정한다. */ const Key = `Drawing/${process.env.S3_PROFILE}/${objectNo}_${planNo}_${type}.png` /** * 크롭이 완료된 이미지를 업로드한다. */ await s3.send( new PutObjectCommand({ Bucket, Key, Body: bufferImage, ContentType: 'image/png', }), ) /** * 크롭이미지 저장이 완료되면 원본 이미지를 삭제한다. */ await s3.send( new DeleteObjectCommand({ Bucket, Key: OriginalKey, }), ) const result = { filePath: `https://${process.env.AMPLIFY_BUCKET}.s3.${process.env.AWS_REGION}.amazonaws.com/${Key}`, fileName: Key, } return NextResponse.json(result) } catch (error) { console.error('Error in POST:', error) return NextResponse.json({ error: 'Failed to process and upload image' }, { status: 500 }) } }