← home

워드프레스 – Image EXIF orientation

모바일 기기로 촬영한 이미지를 워드프레스로 만든 웹사이트에 업로드했을 때, 이미지들이 엉뚱한 방향으로 뒤집히거나 회전되었던 적 있으신가요?

결론부터 말씀드리자면, 워드프레스가 서브사이즈 이미지를 생성하는 과정에서 원본 이미지 파일이 가지고 있던 EXIF를 누락하면서 발생되는 문제입니다. 사진에 관심이 있는 분들은 EXIF에 대해서 잘 아실텐데요, 이미지 파일에는 Camera, Credit, Aperture, Orientation 등 다양한 메타데이터들이 포함될 수 있습니다. 여기서 우리가 눈여겨 보아야할 것이 Orientation. 8가지 방향에 대한 값이 각각 숫자로 할당됩니다.

 

image-exif-orientation
* 2, 4, 5, 7은 플립된 상태.(셀카모드?)

 

모바일 기기로 사진촬영을 하면, 실제 데이터는 항상 같은 방향으로 기록되고, EXIF에 촬영 방향이 저장됩니다. 그리고 이미지 뷰어(웹브라우저, 탐색기 등)는 이 값을 체크하여 보정된 결과를 우리에게 보여주는 것입니다.(단, 기기/환경에 따라 다름)
따라서 워드프레스 처럼 자동으로 서브사이즈 이미지를 생성하는 경우, 그 전에 원본 파일의 Orientation을 미리 확인하여 방향을 교정해주어야 합니다.

안타깝게도 워드프레스가 현재 이런 이슈를 고려하고있지는 않지만, 이미지를 다루는데 있어서 유용한 많은 기능들을 제공하고 있기 때문에, 단 몇 줄의 코드만로 쉽게 구현할 수 있습니다.
아, 그 전에, PHP의 EXIF 익스텐션을 사용할 수 있는지 미리 체크해보세요. 사용할 수 없다면… 동작하지 않습니다.

우선, 파일 업로드 처리 함수인 wp_handle_upload를 찾아서, 어떤 액션 훅을 이용할 수 있는지 찾아봅니다.
wp-admin/includes/file.php에 함수가 정의되어 있는데요, 처리 결과를 반환하기 직전에 ‘wp_handle_upload’라는 훅이 걸려있는 것을 확인할 수 있습니다. 이 부분에서 EXIF Orientation을 확인하여 값이 1보다 큰 경우, flip 또는 rotate 되도록 훅을 걸어봅시다.

 

add_filter( 'wp_handle_upload', 'fix_image_orientation' );

function fix_image_orientation($upload){
	extract($upload);

	if( ! isset($file) || ! isset($type) || 0 !== strpos( $type, 'image/' ) )
		return $upload;

	$image = wp_get_image_editor($file);
	if ( is_wp_error( $image ) )
		return $upload;

	if ( ! function_exists('wp_read_image_metadata') )
		require_once(ABSPATH . 'wp-admin/includes/image.php');

	if ( ! $image_meta = wp_read_image_metadata($file) )
		return $upload;

	$orientation = 0;
	$degree = 0;
	$flip_horz = false;
	$flip_vert = false;
	$changed = false;

	if ( isset($image_meta['orientation']) ){
		$orientation = $image_meta['orientation'];

	}else{
		list( , , $sourceImageType ) = getimagesize( $file );
		if ( is_callable( 'exif_read_data' ) && in_array( $sourceImageType, apply_filters( 'wp_read_image_metadata_types', array( IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM ) ) ) ) {
			$exif = @exif_read_data( $file );
			if ( ! empty( $exif['Orientation'] ) )
				$orientation = $exif['Orientation'];
		}
	}

	switch ( $orientation ) {
		case 2:
			$flip_vert = true;
			break;

		case 3:
			$degree = 180;
			break;

		case 4:
			$flip_horz = true;
			break;

		case 5:
			$flip_vert = true;
			$degree = 90;
			break;

		case 6:
			$degree = -90;
			break;

		case 7:
			$flip_vert = true;
			$degree = -90;
			break;

		case 8:
			$degree = 90;
			break;
	}

	if( $flip_horz || $flip_vert )
		if( ! is_wp_error( $image->flip( $flip_horz, $flip_vert ) ) )
			$changed = true;

	if( $degree )
		if( ! is_wp_error( $image->rotate( $degree ) ) )
			$changed = true;

	if( $changed )
		$image->save( $file, $type );

	return $upload;
}

라인 6-7: 변수 체크, 마임타입 체크.
라인 9-11: GD 또는 Imagic PHP 모듈 인스턴스 생성.
라인 13-17: EXIF를 비롯한 메타데이터 가져오기.
라인 25-35: EXIF Orientation 값은 워드프레스 4.0부터 포함되었으므로 이전 버전을 고려하여 값을 가져옴.
라인 37-67: Orientation 값에 따라 회전 각도와 플립 방향을 정해줌.
라인 69-78: 회전, 플립, 저장

 

아래 이미지는 워드프레스의 미디어 라이브러리를 캡쳐한 것입니다.(테스트용 이미지는 여기에서 가져왔습니다.)

보정전 업로드 결과

image-exif-orientation-nofixed

 

보정후 업로드 결과

image-exif-orientation-fixed

← home