Python에서 프레젠테이션 도형의 이미지 추출
개요
프레젠테이션의 이미지들은 여러 형태 유형으로 나타날 수 있습니다: 일반 사진 프레임, 도형에 적용된 사진 채우기, OLE 개체 미리보기 이미지, 비디오 또는 오디오 프레임 썸네일, 줌 이미지, 혹은 표, 차트 및 SmartArt 도형 안에 중첩된 이미지 등입니다. Aspose.Slides는 이러한 이미지들을 프레젠테이션 이미지 컬렉션에 저장하며, 이는 ImageCollection 및 PPImage 객체를 통해 노출됩니다.
프레젠테이션에 포함된 모든 이미지 리소스를 내보내기만 하면 된다면 presentation.images를 반복하면 됩니다. 이 문서는 다른 작업에 초점을 맞춥니다: 슬라이드에서 이미지가 사용된 위치를 찾기 위해 도형을 탐색하여 저장된 파일에 슬라이드 번호, 도형 위치 및 원본 유형(사진 프레임, 채우기 이미지, 미디어 미리보기, OLE 미리보기 또는 줌 이미지)과 같은 유용한 컨텍스트를 유지할 수 있도록 합니다.
Tip
binary_data 속성을 사용하면 원본 인코딩된 이미지 데이터와 파일 형식을 유지할 수 있습니다. PNG와 같은 특정 형식으로 출력을 정규화하려면 save와 함께 image 속성을 사용하십시오.
공유 헬퍼 메서드
아래 헬퍼 메서드는 예제를 간결하게 유지합니다. save_original_image는 원본 임베드된 바이트를 기록하고, MIME 유형에서 안전한 확장자를 선택하며, SHA-256 해시를 사용해 중복 이미지 바이너리를 건너뜁니다.
import hashlib
import re
from pathlib import Path
import aspose.slides as slides
import aspose.slides.charts as charts
import aspose.slides.smartart as smartart
def save_original_image(image, output_directory, file_name_base, saved_image_hashes):
image_data = bytes(image.binary_data)
image_hash = hashlib.sha256(image_data).hexdigest()
if image_hash in saved_image_hashes:
return False
saved_image_hashes.add(image_hash)
extension = get_extension_from_content_type(image.content_type)
file_name = f"{file_name_base}.{extension}"
output_path = Path(output_directory) / file_name
output_path.write_bytes(image_data)
return True
def save_image_as_png(image, output_directory, file_name_base):
file_name = f"{file_name_base}.png"
output_path = Path(output_directory) / file_name
image.image.save(str(output_path), slides.ImageFormat.PNG)
def get_picture_fill_image(fill_format):
if fill_format is None or fill_format.fill_type != slides.FillType.PICTURE:
return None
return fill_format.picture_fill_format.picture.image
def enumerate_shapes(shapes, prefix, include_grouped_shapes):
for shape_index, shape in enumerate(shapes, start=1):
shape_name_part = f"{prefix}_shape_{shape_index}"
yield shape, shape_name_part
if include_grouped_shapes and isinstance(shape, slides.GroupShape):
yield from enumerate_shapes(
shape.shapes,
shape_name_part,
include_grouped_shapes)
def get_extension_from_content_type(content_type):
if not content_type:
return "bin"
media_type = content_type.split(";")[0].strip().lower()
extensions = {
"image/jpeg": "jpg",
"image/png": "png",
"image/gif": "gif",
"image/bmp": "bmp",
"image/tiff": "tiff",
"image/x-emf": "emf",
"image/emf": "emf",
"image/x-wmf": "wmf",
"image/wmf": "wmf",
"image/svg+xml": "svg",
}
if media_type in extensions:
return extensions[media_type]
if media_type.startswith("image/"):
extension = media_type[len("image/"):]
return make_safe_file_name_part(extension)
return "bin"
def make_safe_file_name_part(value):
return re.sub(r'[<>:"/\\|?*]', "_", value)
그림 프레임에서 이미지 추출
독립 객체로 삽입된 그림에 이 접근 방식을 사용하십시오. [PictureFrame]은 그림을 picture_format.picture.image에 저장하며, 이는 [PPImage] 객체를 반환합니다.
input_path = "sample.pptx"
output_directory = Path.cwd() / "extracted-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=False):
if type(shape) is slides.PictureFrame:
image = shape.picture_format.picture.image
save_original_image(image, output_directory, name_part, saved_image_hashes)
그림으로 채워진 도형에서 이미지 추출
도형은 그림을 채우기로 사용할 수 있습니다. 먼저 도형의 채우기 유형을 확인하십시오: [FillType.PICTURE]가 아니면 해당 채우기에서 추출할 그림이 없습니다. 아래 예제는 [AutoShape] 객체를 처리하고, [PPImage]의 image 속성을 사용해 각 이미지를 PNG로 저장합니다.
input_path = "sample.pptx"
output_directory = Path.cwd() / "shape-fill-images"
output_directory.mkdir(parents=True, exist_ok=True)
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=False):
if isinstance(shape, slides.AutoShape):
image = get_picture_fill_image(shape.fill_format)
if image is not None:
save_image_as_png(image, output_directory, name_part)
OLE 개체 프레임에서 미리보기 이미지 추출
[OleObjectFrame]은 PowerPoint가 슬라이드에서 개체의 미리보기로 사용하는 대체 그림을 가질 수 있습니다. 이 이미지는 substitute_picture_format.picture.image를 통해 얻을 수 있습니다. 이 그림을 추출하면 임베드된 OLE 패키지 내용이 아니라 미리보기 이미지가 제공됩니다.
input_path = "sample.pptx"
output_directory = Path.cwd() / "ole-preview-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=False):
if isinstance(shape, slides.OleObjectFrame):
image = shape.substitute_picture_format.picture.image
if image is not None:
file_name_base = f"{name_part}_ole_preview"
save_original_image(image, output_directory, file_name_base, saved_image_hashes)
비디오 프레임에서 미리보기 이미지 추출
[VideoFrame]도 picture_format.picture.image에 미리보기 이미지를 저장할 수 있습니다. 이는 슬라이드에 표시되는 포스터 또는 썸네일이며, 비디오 스트림에서 디코딩된 프레임이 아닙니다.
input_path = "sample.pptx"
output_directory = Path.cwd() / "video-preview-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=False):
if isinstance(shape, slides.VideoFrame):
image = shape.picture_format.picture.image
if image is not None:
file_name_base = f"{name_part}_video_preview"
save_original_image(image, output_directory, file_name_base, saved_image_hashes)
오디오 프레임에서 미리보기 이미지 추출
[AudioFrame]은 picture_format.picture.image에 썸네일을 저장할 수 있습니다. 이는 슬라이드에 표시되는 오디오 개체의 이미지입니다.
input_path = "sample.pptx"
output_directory = Path.cwd() / "audio-preview-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=False):
if isinstance(shape, slides.AudioFrame):
image = shape.picture_format.picture.image
if image is not None:
file_name_base = f"{name_part}_audio_preview"
save_original_image(image, output_directory, file_name_base, saved_image_hashes)
줌 개체에서 이미지 추출
[ZoomFrame] 및 [SectionZoomFrame] 도형은 사용자 지정 이미지를 사용할 수 있습니다. 줌 프레임에서 zoom_image를 읽으십시오.
input_path = "sample.pptx"
output_directory = Path.cwd() / "zoom-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=False):
if isinstance(shape, slides.ZoomFrame) and shape.zoom_image is not None:
file_name_base = f"{name_part}_zoom"
save_original_image(shape.zoom_image, output_directory, file_name_base, saved_image_hashes)
continue
if isinstance(shape, slides.SectionZoomFrame) and shape.zoom_image is not None:
file_name_base = f"{name_part}_section_zoom"
save_original_image(shape.zoom_image, output_directory, file_name_base, saved_image_hashes)
continue
요약 줌 프레임에서 이미지 추출
[SummaryZoomFrame]도 도형입니다. 해당 섹션 항목들은 사용자 지정 이미지를 사용할 수 있으며, 각 요약 줌 섹션의 zoom_image 속성을 통해 노출됩니다.
input_path = "sample.pptx"
output_directory = Path.cwd() / "summary-zoom-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=False):
if isinstance(shape, slides.SummaryZoomFrame):
section_count = len(shape.summary_zoom_collection)
for section_index in range(section_count):
section = shape.summary_zoom_collection[section_index]
if section.zoom_image is not None:
display_index = section_index + 1
file_name_base = f"{name_part}_summary_zoom_{display_index}"
save_original_image(section.zoom_image, output_directory, file_name_base, saved_image_hashes)
표 도형에서 이미지 추출
[Table]은 도형입니다. 표에 있는 이미지는 일반적으로 표 셀의 그림 채우기로 저장됩니다.
input_path = "sample.pptx"
output_directory = Path.cwd() / "table-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=True):
if isinstance(shape, slides.Table):
row_count = len(shape.rows)
column_count = len(shape.columns)
for row_index in range(row_count):
for column_index in range(column_count):
cell = shape.rows[row_index][column_index]
image = get_picture_fill_image(cell.cell_format.fill_format)
if image is not None:
file_name_base = f"{name_part}_cell_{row_index + 1}_{column_index + 1}"
save_original_image(image, output_directory, file_name_base, saved_image_hashes)
차트 도형에서 이미지 추출
[Chart]은 도형입니다. 아래 예제는 차트 영역 그림 채우기에서 이미지를 추출합니다.
input_path = "sample.pptx"
output_directory = Path.cwd() / "chart-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=True):
if isinstance(shape, charts.Chart):
fill_format = shape.fill_format
image = get_picture_fill_image(fill_format)
if image is not None:
file_name_base = f"{name_part}_chart_area"
save_original_image(image, output_directory, file_name_base, saved_image_hashes)
SmartArt 도형에서 이미지 추출
[SmartArt] 객체는 도형입니다. SmartArt 레이아웃에 따라 이미지는 노드 글머리표 채우기 또는 노드 도형의 채우기 형식에 저장될 수 있습니다.
input_path = "sample.pptx"
output_directory = Path.cwd() / "smartart-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=True):
if isinstance(shape, smartart.SmartArt):
node_count = len(shape.all_nodes)
for node_index in range(node_count):
node = shape.all_nodes[node_index]
bullet_image = get_picture_fill_image(node.bullet_fill_format)
if bullet_image is not None:
file_name_base = f"{name_part}_smartart_node_{node_index + 1}_bullet"
save_original_image(bullet_image, output_directory, file_name_base, saved_image_hashes)
node_shape_count = len(node.shapes)
for node_shape_index in range(node_shape_count):
node_shape = node.shapes[node_shape_index]
image = get_picture_fill_image(node_shape.fill_format)
if image is not None:
file_name_base = f"{name_part}_smartart_node_{node_index + 1}_shape_{node_shape_index + 1}"
save_original_image(image, output_directory, file_name_base, saved_image_hashes)
그룹화된 도형 내부 이미지 포함
그룹화된 도형은 자체 도형 컬렉션을 포함합니다. 공유된 enumerate_shapes 헬퍼에는 include_grouped_shapes 옵션이 있습니다. [GroupShape] 객체 내부의 도형을 검사하려면 이를 True로 설정하십시오. 아래 예제는 그림 프레임, 그림으로 채워진 도형, OLE 개체 미리보기, 비디오 프레임 썸네일 및 오디오 프레임 썸네일에서 이미지를 추출합니다. 표, 차트, SmartArt 및 요약 줌 이미지도 포함하려면 이전 섹션의 특수 추출 로직을 재사용하면서 동일한 재귀 도형 순회를 유지하십시오.
input_path = "sample.pptx"
output_directory = Path.cwd() / "all-shape-images"
output_directory.mkdir(parents=True, exist_ok=True)
saved_image_hashes = set()
with slides.Presentation(input_path) as presentation:
for slide in presentation.slides:
slide_prefix = f"slide_{slide.slide_number}"
for shape, name_part in enumerate_shapes(
slide.shapes,
slide_prefix,
include_grouped_shapes=True):
if isinstance(shape, slides.OleObjectFrame):
image = shape.substitute_picture_format.picture.image
if image is not None:
file_name_base = f"{name_part}_ole_preview"
save_original_image(image, output_directory, file_name_base, saved_image_hashes)
continue
if isinstance(shape, slides.VideoFrame):
image = shape.picture_format.picture.image
if image is not None:
file_name_base = f"{name_part}_video_preview"
save_original_image(image, output_directory, file_name_base, saved_image_hashes)
continue
if isinstance(shape, slides.AudioFrame):
image = shape.picture_format.picture.image
if image is not None:
file_name_base = f"{name_part}_audio_preview"
save_original_image(image, output_directory, file_name_base, saved_image_hashes)
continue
if type(shape) is slides.PictureFrame:
image = shape.picture_format.picture.image
save_original_image(image, output_directory, name_part, saved_image_hashes)
continue
if isinstance(shape, slides.AutoShape):
image = get_picture_fill_image(shape.fill_format)
if image is not None:
save_original_image(image, output_directory, name_part, saved_image_hashes)
예외 상황 및 실용적인 주의사항
- 중복 이미지: 여러 도형이 동일한 이미지를 참조하거나 바이트가 동일한 별개의 이미지를 가질 수 있습니다. 고유 이미지당 하나의 출력 파일을 원한다면 파일을 쓰기 전에 [PPImage]의
binary_data속성을 해시하십시오. - 원본 데이터 vs. 변환된 출력: [PPImage]의
binary_data속성을 저장하면 임베드된 JPEG, PNG, GIF, SVG, EMF 또는 WMF 데이터가 보존됩니다.save를 통해image속성을 저장하면 일관된 출력 형식이 필요할 때 유용합니다. - 지원되지 않는 채우기 유형: 단색, 그라디언트, 패턴 및 무채움 도형은 그림 채우기를 포함하지 않습니다.
picture_fill_format을 읽기 전에 [FillType]을 확인하십시오. - 그룹화된 도형: 최상위 슬라이드 도형 컬렉션은 그룹을 평탄화하지 않습니다. 그룹화된 콘텐츠가 중요할 경우 [GroupShape.shapes]를 재귀적으로 검사하십시오.
- OLE 개체 미리보기: [OleObjectFrame]은
substitute_picture_format을 통해 미리보기 이미지를 제공할 수 있지만, 해당 이미지는 슬라이드 미리보기일 뿐이며 OLE 개체 내부에 임베드된 파일은 아닙니다. - 비디오 프레임 썸네일: [VideoFrame]은
picture_format을 통해 미리보기 이미지를 제공할 수 있지만, 그 이미지는 슬라이드에 표시되는 포스터일 뿐이며 비디오 스트림에서 추출된 것이 아닙니다. - 오디오 프레임 썸네일: [AudioFrame]은
picture_format을 통해 아이콘이나 썸네일을 제공할 수 있지만, 이는 임베드된 오디오 데이터가 아닙니다. - 줌 이미지: 슬라이드 줌, 섹션 줌 및 요약 줌 도형은
image를 통해 사용자 지정 [PPImage] 객체를 사용할 수 있습니다. - 중첩 도형 모델: 표, 차트 및 SmartArt 객체는 [Shape]을 구현하지만, 해당 이미지들은 종종 중첩된 표 셀, 차트 요소 또는 SmartArt 노드 서식 객체에 저장됩니다.
- 잘라내기 또는 변환된 그림: [PPImage]에 접근하면 저장된 이미지 리소스를 얻을 수 있지만, 도형에 적용된 자르기, 투명도, 색상 재조정, 회전 또는 기타 시각 효과는 렌더링되지 않습니다.
FAQ
이미지를 자르기, 효과, 도형 변환 없이 원본 그대로 추출할 수 있나요?
네. [PPImage] 객체에 접근하여 binary_data 속성을 디스크에 기록하십시오. 이렇게 하면 프레젠테이션에 저장된 원본 인코딩 이미지가 보존되며, 슬라이드에서 이미지가 렌더링되는 방식은 반영되지 않습니다.
추출한 모든 이미지를 PNG로 내보낼 수 있나요?
네. [PPImage]의 image 속성을 사용해 이미지 객체를 얻은 뒤, [ImageFormat.PNG]와 함께 save를 호출하십시오. 이는 출력이 변환되며 원본 파일 형식이나 벡터 데이터가 보존되지 않을 수 있습니다.
같은 이미지를 여러 번 저장하는 것을 방지하려면 어떻게 해야 하나요?
[PPImage]의 binary_data 속성 해시를 사용하고 해시를 집합에 보관하십시오. 새로운 이미지의 해시가 이미 존재한다면 해당 이미지를 건너뛰거나 기존 출력 파일에 대한 또 다른 참조를 기록하십시오.
왜 일부 도형에서는 이미지가 생성되지 않나요?
그림 프레임, 그림으로 채워진 도형, OLE 개체 프레임, 미디어 프레임, 줌 프레임, 표, 차트 및 SmartArt 객체는 이미지를 참조할 수 있습니다. 일부 도형 유형은 중첩된 서식 객체를 통해 이미지를 노출하므로 단순히 picture_format 또는 도형 fill_format을 확인하는 것만으로는 충분하지 않을 때가 있습니다.
비디오 프레임에 표시되는 썸네일을 추출할 수 있나요?
네. [VideoFrame]을 사용하고 picture_format.picture.image를 읽으십시오. 이는 비디오 프레임에 저장된 포스터 이미지를 추출하며, 비디오 파일에서 생성된 프레임이 아닙니다.
프레젠테이션 이미지 컬렉션의 특정 이미지가 어떤 도형에서 사용되는지 어떻게 알 수 있나요?
Aspose.Slides는 [PPImage]에서 도형으로의 역링크를 저장하지 않습니다. 탐색 중에 매핑을 구축하십시오: 이미지 참조를 찾을 때마다 슬라이드 번호, 도형 경로 및 이미지 해시 또는 컬렉션 항목을 기록하십시오.
OLE 개체 내부에 포함된 이미지(예: 첨부 문서)를 추출할 수 있나요?
[OleObjectFrame]의 substitute_picture_format 속성을 통해 OLE 개체의 슬라이드 미리보기를 추출할 수 있습니다. 그러나 해당 미리보기는 임베드된 문서 자체가 아닙니다. 임베드된 파일 내부의 이미지를 추출하려면 OLE 데이터를 추출한 뒤 해당 파일 유형에 맞는 도구로 검사하십시오.