업무용/springjava

바이너리 이미지 정방향으로 자바에서 돌리기

SEOKIHOUSE 2024. 7. 16. 15:04

 

 

요 녀석을.. 돌려버리자 갓 클소

package tests;

import java.awt.Color;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageInputStream;

import org.w3c.dom.NodeList;

import humetro.pm.haBscMttrMng.service.vo.HaBscMttrVo;

public class test {
	// 사용 예시
    public static void main(String[] args) {
    	HaBscMttrVo vo = new HaBscMttrVo();
        try {
            // 이미지 파일을 바이트 배열로 읽어오는 코드가 필요합니다.
            byte[] imageData = vo.getPhotoBt();// 이미지 바이트 배열을 여기에 넣으세요
            byte[] correctedImageData = correctOrientation(imageData);
            // 수정된 이미지를 저장하거나 사용하는 코드를 여기에 추가하세요
            // 예: ImageIO.write(correctedImage, "jpg", new File("corrected_image.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static byte[] correctOrientation(byte[] imageData) throws IOException {
		ByteArrayInputStream bis = new ByteArrayInputStream(imageData);
        ImageInputStream iis = ImageIO.createImageInputStream(bis);

        Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
        if (!readers.hasNext()) {
            return imageData; // 원본 이미지 데이터 반환
        }

        ImageReader reader = readers.next();
        String formatName = reader.getFormatName().toLowerCase();
        if (formatName.equals("jpeg") || formatName.equals("jpg") || formatName.equals("jpe") || formatName.equals("jfif")) {
            formatName = "jpg";
        }
        reader.setInput(iis, true);

        BufferedImage image = reader.read(0);

        IIOMetadata metadata = null;
        try {
            metadata = reader.getImageMetadata(0);
        } catch (IOException e) {
            //System.out.println("Failed to read metadata: " + e.getMessage());
            // 메타데이터를 읽을 수 없는 경우, 기본값 방향 출력
	        	metadata = null;
        }

        int orientation = (metadata != null) ? getExifOrientation(metadata) : 1;

        BufferedImage correctedImage;
        switch (orientation) {
            case 1: // 정상
                correctedImage = image;
                break;
            case 2: // 좌우 반전
                correctedImage = flip(image, false, true);
                break;
            case 3: // 180도 회전
                correctedImage = rotate(image, 180);
                break;
            case 4: // 상하 반전
                correctedImage = flip(image, true, false);
                break;
            case 5: // 90도 회전 후 좌우 반전
                BufferedImage rotated = rotate(image, 90);
                correctedImage = flip(rotated, false, true);
                break;
            case 6: // 90도 시계 방향 회전
                correctedImage = rotate(image, 90);
                break;
            case 7: // 270도 회전 후 좌우 반전
                rotated = rotate(image, 270);
                correctedImage = flip(rotated, false, true);
                break;
            case 8: // 270도 시계 방향 회전
                correctedImage = rotate(image, 270);
                break;
            default:
                correctedImage = image;
        }

        // BufferedImage를 byte 배열로 변환
        return bufferedImageToByteArray(correctedImage, formatName);
    }

    private static byte[] bufferedImageToByteArray(BufferedImage image, String formatName) throws IOException {
    	ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            // 이미지 형식이 지원되는지 확인
            if (!ImageIO.getImageWritersByFormatName(formatName).hasNext()) {
                throw new IllegalArgumentException("Unsupported image format: " + formatName);
            }

            // 알파 채널 처리
            BufferedImage convertedImg = image;
            if (image.getColorModel().hasAlpha()) {
                convertedImg = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
                convertedImg.createGraphics().drawImage(image, 0, 0, Color.WHITE, null);
            }

            // 이미지 쓰기
            ImageIO.write(convertedImg, formatName, baos);
        } catch (IOException e) {
        	throw new IOException("Error writing image: " + e.getMessage());
        }
        return baos.toByteArray();
    }

    private static int getExifOrientation(IIOMetadata metadata) {
    	int orientation = 1;
        String[] metadataFormats = metadata.getMetadataFormatNames();
        for (String format : metadataFormats) {
            IIOMetadataNode root = (IIOMetadataNode) metadata.getAsTree(format);
            NodeList nodes = root.getElementsByTagName("app1");

            if (nodes.getLength() > 0) {
                for (int i = 0; i < nodes.getLength(); i++) {
                    IIOMetadataNode node = (IIOMetadataNode) nodes.item(i);
                    if (node != null) {
                        try {
                            byte[] exif = (byte[]) node.getUserObject();
                            if (exif != null && exif.length > 20) {
                                // EXIF 헤더 확인
                                if (exif[0] == 'E' && exif[1] == 'x' && exif[2] == 'i' && exif[3] == 'f') {
                                    // EXIF 데이터에서 방향 정보 찾기
                                    for (int j = 0; j < exif.length - 1; j++) {
                                        if (exif[j] == 0x12 && exif[j+1] == 0x01) {
                                            orientation = exif[j + 8] & 0xFF;
                                            return orientation;
                                        }
                                    }
                                }
                            }
                        } catch (ClassCastException e) {
                        } catch (ArrayIndexOutOfBoundsException e) {
                        } catch (NullPointerException e) {
                        }
                    }
                }
            }
        }
        return orientation;
    }

    private static BufferedImage rotate(BufferedImage image, int degrees) {
    	double radians = Math.toRadians(degrees);
        int srcWidth = image.getWidth();
        int srcHeight = image.getHeight();

        int newWidth = srcWidth;
        int newHeight = srcHeight;
        if (degrees == 90 || degrees == 270) {
            newWidth = srcHeight;
            newHeight = srcWidth;
        }

        BufferedImage rotated = new BufferedImage(newWidth, newHeight, image.getType());
        AffineTransform at = AffineTransform.getRotateInstance(radians, newWidth / 2.0, newHeight / 2.0);

        if (degrees == 90) {
            at.translate((newWidth - srcWidth) / 2.0, (newHeight - srcHeight) / 2.0);
        } else if (degrees == 270) {
            at.translate(-(newWidth - srcWidth) / 2.0, -(newHeight - srcHeight) / 2.0);
        }

        AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
        op.filter(image, rotated);

        return rotated;
    }

    private static BufferedImage flip(BufferedImage image, boolean horizontal, boolean vertical) {
        int width = image.getWidth();
        int height = image.getHeight();

        BufferedImage flipped = new BufferedImage(width, height, image.getType());

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int newX = horizontal ? width - 1 - x : x;
                int newY = vertical ? height - 1 - y : y;
                flipped.setRGB(newX, newY, image.getRGB(x, y));
            }
        }

        return flipped;
    }

}