from PIL import Image import base64 from io import BytesIO def crop_and_encode_geographic_kma_image( image_path: str, type: str ) -> str: """ 지정된 PNG 이미지에서 특정 위경도 중심을 기준으로 주변 crop_radius_km 영역을 잘라내고 Base64 문자열로 인코딩합니다. :param image_path: 입력 PNG 파일 경로. :param image_bounds: 이미지 전체가 나타내는 영역의 (min_lon, min_lat, max_lon, max_lat) 좌표. (경도 최소, 위도 최소, 경도 최대, 위도 최대) :param center_point: 자르기 영역의 중심이 될 (lon, lat) 좌표. :param crop_radius_km: 중심에서 상하좌우로 자를 거리 (km). :return: 잘린 이미지의 PNG Base64 문자열. """ if type == 'wind': full_image_bounds = (78.0993797274984161,12.1585396012363489, 173.8566763130032484,61.1726557651764793) elif type == 'hydr': full_image_bounds = (101.57732, 12.21703, 155.62642, 57.32893) image_bounds = (121.8399658203125, 32.2400016784668, 131.679931640625, 42.79999923706055) TARGET_WIDTH = 50 TARGET_HEIGHT = 90 # 1. 이미지 로드 try: img = Image.open(image_path) except FileNotFoundError: return f"Error: File not found at {image_path}" except Exception as e: return f"Error opening image: {e}" width, height = img.size full_min_lon, full_min_lat, full_max_lon, full_max_lat = full_image_bounds full_deg_lat_span = full_max_lat - full_min_lat full_deg_lon_span = full_max_lon - full_min_lon min_lon, min_lat, max_lon, max_lat = image_bounds def lon_to_pixel_x(lon): return int(width * (lon - full_min_lon) / full_deg_lon_span) def lat_to_pixel_y(lat): # Y축은 위도에 반비례 (큰 위도가 작은 Y 픽셀) return int(height * (full_max_lat - lat) / full_deg_lat_span) # 자를 영역의 픽셀 좌표 계산 pixel_x_min = max(0, lon_to_pixel_x(min_lon)) pixel_y_min = max(0, lat_to_pixel_y(max_lat)) # 위도 최대가 y_min (상단) pixel_x_max = min(width, lon_to_pixel_x(max_lon)) pixel_y_max = min(height, lat_to_pixel_y(min_lat)) # 위도 최소가 y_max (하단) # PIL의 crop 함수는 (left, top, right, bottom) 순서의 픽셀 좌표를 사용 crop_box = (pixel_x_min, pixel_y_min, pixel_x_max, pixel_y_max) # 4. 이미지 자르기 if pixel_x_min >= pixel_x_max or pixel_y_min >= pixel_y_max: return "Error: Crop area is outside the image bounds or zero size." cropped_img = img.crop(crop_box) if cropped_img.size != (TARGET_WIDTH, TARGET_HEIGHT): cropped_img = cropped_img.resize( (TARGET_WIDTH, TARGET_HEIGHT), Image.LANCZOS ) # 5. Base64 문자열로 인코딩 buffer = BytesIO() cropped_img.save(buffer, format="PNG") base64_encoded_data = base64.b64encode(buffer.getvalue()).decode("utf-8") # Base64 문자열 앞에 MIME 타입 정보 추가 # base64_string = f"data:image/png;base64,{base64_encoded_data}" return base64_encoded_data