Make WordPress Core

Ticket #33772: add-iptc-keywords-to-attachment-metadata.php

File add-iptc-keywords-to-attachment-metadata.php, 6.2 KB (added by SteveHoneyNZ, 9 years ago)
Line 
1<?php
2/**
3 * Get extended image metadata, exif or iptc as available.
4 *
5 * Retrieves the EXIF metadata aperture, credit, camera, caption, copyright, iso
6 * created_timestamp, focal_length, shutter_speed, and title.
7 *
8 * The IPTC metadata that is retrieved is APP13, credit, byline, created date
9 * and time, caption, copyright, and title. Also includes FNumber, Model,
10 * DateTimeDigitized, FocalLength, ISOSpeedRatings, and ExposureTime.
11 *
12 * @todo Try other exif libraries if available.
13 * @since 2.5.0
14 *
15 * @param string $file
16 * @return bool|array False on failure. Image metadata array on success.
17 */
18function wp_read_image_metadata( $file ) {
19        if ( ! file_exists( $file ) )
20                return false;
21
22        list( , , $sourceImageType ) = getimagesize( $file );
23
24        /*
25         * EXIF contains a bunch of data we'll probably never need formatted in ways
26         * that are difficult to use. We'll normalize it and just extract the fields
27         * that are likely to be useful. Fractions and numbers are converted to
28         * floats, dates to unix timestamps, and everything else to strings.
29         */
30        $meta = array(
31                'aperture' => 0,
32                'credit' => '',
33                'camera' => '',
34                'caption' => '',
35                'created_timestamp' => 0,
36                'copyright' => '',
37                'focal_length' => 0,
38                'iso' => 0,
39                'shutter_speed' => 0,
40                'title' => '',
41                'orientation' => 0,
42        );
43
44        /*
45         * Read IPTC first, since it might contain data not available in exif such
46         * as caption, description etc.
47         */
48        if ( is_callable( 'iptcparse' ) ) {
49                getimagesize( $file, $info );
50
51                if ( ! empty( $info['APP13'] ) ) {
52                        $iptc = iptcparse( $info['APP13'] );
53                       
54                        apply_filters( 'wp_parse_image_iptc', $meta, $iptc, $file, $sourceImageType );
55
56                        // Headline, "A brief synopsis of the caption."
57                        if ( ! empty( $iptc['2#105'][0] ) ) {
58                                $meta['title'] = trim( $iptc['2#105'][0] );
59                        /*
60                         * Title, "Many use the Title field to store the filename of the image,
61                         * though the field may be used in many ways."
62                         */
63                        } elseif ( ! empty( $iptc['2#005'][0] ) ) {
64                                $meta['title'] = trim( $iptc['2#005'][0] );
65                        }
66
67                        if ( ! empty( $iptc['2#120'][0] ) ) { // description / legacy caption
68                                $caption = trim( $iptc['2#120'][0] );
69
70                                mbstring_binary_safe_encoding();
71                                $caption_length = strlen( $caption );
72                                reset_mbstring_encoding();
73
74                                if ( empty( $meta['title'] ) && $caption_length < 80 ) {
75                                        // Assume the title is stored in 2:120 if it's short.
76                                        $meta['title'] = $caption;
77                                }
78
79                                $meta['caption'] = $caption;
80                        }
81
82                        if ( ! empty( $iptc['2#110'][0] ) ) // credit
83                                $meta['credit'] = trim( $iptc['2#110'][0] );
84                        elseif ( ! empty( $iptc['2#080'][0] ) ) // creator / legacy byline
85                                $meta['credit'] = trim( $iptc['2#080'][0] );
86
87                        if ( ! empty( $iptc['2#055'][0] ) && ! empty( $iptc['2#060'][0] ) ) // created date and time
88                                $meta['created_timestamp'] = strtotime( $iptc['2#055'][0] . ' ' . $iptc['2#060'][0] );
89
90                        if ( ! empty( $iptc['2#116'][0] ) ) // copyright
91                                $meta['copyright'] = trim( $iptc['2#116'][0] );
92                               
93                        if ( ! empty( $iptc['2#025'][0] ) ) // keywords array
94                                $meta['keywords'] = array_values( $iptc['2#025'] );
95                 }
96        }
97
98        /**
99         * Filter the image types to check for exif data.
100         *
101         * @since 2.5.0
102         *
103         * @param array $image_types Image types to check for exif data.
104         */
105        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 ) ) ) ) {
106                $exif = @exif_read_data( $file );
107
108                if ( ! empty( $exif['ImageDescription'] ) ) {
109                        mbstring_binary_safe_encoding();
110                        $description_length = strlen( $exif['ImageDescription'] );
111                        reset_mbstring_encoding();
112
113                        if ( empty( $meta['title'] ) && $description_length < 80 ) {
114                                // Assume the title is stored in ImageDescription
115                                $meta['title'] = trim( $exif['ImageDescription'] );
116                        }
117
118                        if ( empty( $meta['caption'] ) && ! empty( $exif['COMPUTED']['UserComment'] ) ) {
119                                $meta['caption'] = trim( $exif['COMPUTED']['UserComment'] );
120                        }
121
122                        if ( empty( $meta['caption'] ) ) {
123                                $meta['caption'] = trim( $exif['ImageDescription'] );
124                        }
125                } elseif ( empty( $meta['caption'] ) && ! empty( $exif['Comments'] ) ) {
126                        $meta['caption'] = trim( $exif['Comments'] );
127                }
128
129                if ( empty( $meta['credit'] ) ) {
130                        if ( ! empty( $exif['Artist'] ) ) {
131                                $meta['credit'] = trim( $exif['Artist'] );
132                        } elseif ( ! empty($exif['Author'] ) ) {
133                                $meta['credit'] = trim( $exif['Author'] );
134                        }
135                }
136
137                if ( empty( $meta['copyright'] ) && ! empty( $exif['Copyright'] ) ) {
138                        $meta['copyright'] = trim( $exif['Copyright'] );
139                }
140                if ( ! empty( $exif['FNumber'] ) ) {
141                        $meta['aperture'] = round( wp_exif_frac2dec( $exif['FNumber'] ), 2 );
142                }
143                if ( ! empty( $exif['Model'] ) ) {
144                        $meta['camera'] = trim( $exif['Model'] );
145                }
146                if ( empty( $meta['created_timestamp'] ) && ! empty( $exif['DateTimeDigitized'] ) ) {
147                        $meta['created_timestamp'] = wp_exif_date2ts( $exif['DateTimeDigitized'] );
148                }
149                if ( ! empty( $exif['FocalLength'] ) ) {
150                        $meta['focal_length'] = (string) wp_exif_frac2dec( $exif['FocalLength'] );
151                }
152                if ( ! empty( $exif['ISOSpeedRatings'] ) ) {
153                        $meta['iso'] = is_array( $exif['ISOSpeedRatings'] ) ? reset( $exif['ISOSpeedRatings'] ) : $exif['ISOSpeedRatings'];
154                        $meta['iso'] = trim( $meta['iso'] );
155                }
156                if ( ! empty( $exif['ExposureTime'] ) ) {
157                        $meta['shutter_speed'] = (string) wp_exif_frac2dec( $exif['ExposureTime'] );
158                }
159                if ( ! empty( $exif['Orientation'] ) ) {
160                        $meta['orientation'] = $exif['Orientation'];
161                }
162        }
163
164        foreach ( array( 'title', 'caption', 'credit', 'copyright', 'camera', 'iso' ) as $key ) {
165                if ( $meta[ $key ] && ! seems_utf8( $meta[ $key ] ) ) {
166                        $meta[ $key ] = utf8_encode( $meta[ $key ] );
167                }
168        }
169
170        foreach ( $meta as &$value ) {
171                if ( is_string( $value ) ) {
172                        $value = wp_kses_post( $value );
173                }
174        }
175
176        /**
177         * Filter the array of meta data read from an image's exif data.
178         *
179         * @since 2.5.0
180         *
181         * @param array  $meta            Image meta data.
182         * @param string $file            Path to image file.
183         * @param int    $sourceImageType Type of image.
184         */
185        return apply_filters( 'wp_read_image_metadata', $meta, $iptc, $file, $sourceImageType );
186
187}