예제 #1
0
function ewww_image_optimizer_mimetype($path, $case)
{
    ewwwio_debug_message('<b>' . __FUNCTION__ . '()</b>');
    ewwwio_debug_message("testing mimetype: {$path}");
    if ($case === 'i' && preg_match('/^RIFF.+WEBPVP8/', file_get_contents($path, NULL, NULL, 0, 16))) {
        return 'image/webp';
    }
    if ($case === 'i' && strpos($path, 's3') === 0) {
        return ewww_image_optimizer_quick_mimetype($path);
    }
    if (function_exists('finfo_file') && defined('FILEINFO_MIME')) {
        // create a finfo resource
        $finfo = finfo_open(FILEINFO_MIME);
        // retrieve the mimetype
        $type = explode(';', finfo_file($finfo, $path));
        $type = $type[0];
        finfo_close($finfo);
        ewwwio_debug_message("finfo_file: {$type}");
    }
    // see if we can use the getimagesize function
    if (empty($type) && function_exists('getimagesize') && $case === 'i') {
        // run getimagesize on the file
        $type = getimagesize($path);
        // make sure we have results
        if (false !== $type) {
            // store the mime-type
            $type = $type['mime'];
        }
        ewwwio_debug_message("getimagesize: {$type}");
    }
    // see if we can use mime_content_type
    if (empty($type) && function_exists('mime_content_type')) {
        // retrieve and store the mime-type
        $type = mime_content_type($path);
        ewwwio_debug_message("mime_content_type: {$type}");
    }
    // if nothing else has worked, try the 'file' command
    if ((empty($type) || $type != 'application/x-executable') && $case === 'b') {
        // find the 'file' command
        if ($file = ewww_image_optimizer_find_nix_binary('file', 'f')) {
            // run 'file' on the file in question
            exec("{$file} {$path}", $filetype);
            ewwwio_debug_message("file command: {$filetype[0]}");
            // if we've found a proper binary
            if (strpos($filetype[0], 'ELF') && strpos($filetype[0], 'executable') || strpos($filetype[0], 'Mach-O universal binary')) {
                $type = 'application/x-executable';
            }
        }
    }
    // if we are dealing with a binary, and found an executable
    if ($case === 'b' && preg_match('/executable|octet-stream/', $type)) {
        ewwwio_memory(__FUNCTION__);
        return $type;
        // otherwise, if we are dealing with an image
    } elseif ($case == 'i') {
        ewwwio_memory(__FUNCTION__);
        return $type;
        // if all else fails, bail
    } else {
        ewwwio_debug_message('no mime functions or not a binary');
        ewwwio_memory(__FUNCTION__);
        return false;
    }
}
예제 #2
0
function ewww_image_optimizer_image_scan($dir)
{
    ewwwio_debug_message('<b>' . __FUNCTION__ . '()</b>');
    global $wpdb;
    $images = array();
    if (!is_dir($dir)) {
        return $images;
    }
    ewwwio_debug_message("scanning folder for images: {$dir}");
    $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD);
    $start = microtime(true);
    $query = "SELECT path,image_size FROM {$wpdb->ewwwio_images}";
    $already_optimized = $wpdb->get_results($query, ARRAY_A);
    $optimized_list = array();
    foreach ($already_optimized as $optimized) {
        $optimized_path = $optimized['path'];
        $optimized_list[$optimized_path] = $optimized['image_size'];
    }
    $file_counter = 0;
    if (ewww_image_optimizer_stl_check()) {
        set_time_limit(0);
    }
    foreach ($iterator as $file) {
        $file_counter++;
        $skip_optimized = false;
        if ($file->isFile()) {
            $path = $file->getPathname();
            if (preg_match('/(\\/|\\\\)\\./', $path) && apply_filters('ewww_image_optimizer_ignore_hidden_files', true)) {
                continue;
            }
            if (!ewww_image_optimizer_quick_mimetype($path)) {
                /*			$pathextension = strtolower( pathinfo( $path, PATHINFO_EXTENSION ) );
                			switch ( $pathextension ) {
                				case 'jpg':
                				case 'jpeg':
                				case 'jpe':
                				case 'png':
                				case 'gif':
                				case 'pdf':
                					break;
                				default:*/
                continue;
            }
            if (isset($optimized_list[$path])) {
                $image_size = $file->getSize();
                if ($optimized_list[$path] == $image_size) {
                    ewwwio_debug_message("match found for {$path}");
                    $skip_optimized = true;
                } else {
                    ewwwio_debug_message("mismatch found for {$path}, db says " . $optimized_list[$path] . " vs. current {$image_size}");
                }
            }
            if (empty($skip_optimized) || !empty($_REQUEST['ewww_force'])) {
                ewwwio_debug_message("queued {$path}");
                $images[] = utf8_encode($path);
            }
        }
        //		ewww_image_optimizer_debug_log();
    }
    $end = microtime(true) - $start;
    ewwwio_debug_message("query time for {$file_counter} files (seconds): {$end}");
    ewwwio_memory(__FUNCTION__);
    return $images;
}
예제 #3
0
function ewww_image_optimizer_count_optimized($gallery, $return_ids = false)
{
    ewwwio_debug_message('<b>' . __FUNCTION__ . '()</b>');
    global $wpdb;
    $full_count = 0;
    $unoptimized_full = 0;
    $unoptimized_re = 0;
    $resize_count = 0;
    $attachment_query = '';
    ewwwio_debug_message("scanning for {$gallery}");
    // retrieve the time when the optimizer starts
    $started = microtime(true);
    if (ewww_image_optimizer_stl_check()) {
        set_time_limit(0);
    }
    $max_query = apply_filters('ewww_image_optimizer_count_optimized_queries', 3000);
    $max_query = (int) $max_query;
    $attachment_query_count = 0;
    switch ($gallery) {
        case 'media':
            $ids = array();
            // see if we were given attachment IDs to work with via GET/POST
            if (!empty($_REQUEST['ids']) || get_option('ewww_image_optimizer_bulk_resume')) {
                ewwwio_debug_message('we have received attachment ids via $_REQUEST');
                // retrieve the attachment IDs that were pre-loaded in the database
                $attachment_ids = get_option('ewww_image_optimizer_bulk_attachments');
                if (!empty($attachment_ids)) {
                    $full_count = count($attachment_ids);
                    while ($attachment_ids && $attachment_query_count < $max_query) {
                        $attachment_query .= "'" . array_pop($attachment_ids) . "',";
                        $attachment_query_count++;
                    }
                    $attachment_query = 'AND metas.post_id IN (' . substr($attachment_query, 0, -1) . ')';
                }
            } else {
                $full_count = $wpdb->get_var("SELECT COUNT(ID) FROM {$wpdb->posts} WHERE (post_type = 'attachment' OR post_type = 'ims_image') AND (post_mime_type LIKE '%%image%%' OR post_mime_type LIKE '%%pdf%%')");
            }
            $offset = 0;
            // retrieve all the image attachment metadata from the database
            while ($attachments = $wpdb->get_results("SELECT metas.meta_value,post_id FROM {$wpdb->postmeta} metas INNER JOIN {$wpdb->posts} posts ON posts.ID = metas.post_id WHERE (posts.post_mime_type LIKE '%%image%%' OR posts.post_mime_type LIKE '%%pdf%%') AND metas.meta_key = '_wp_attachment_metadata' {$attachment_query} LIMIT {$offset},{$max_query}", ARRAY_N)) {
                ewwwio_debug_message("fetched " . count($attachments) . " attachments starting at {$offset}");
                $disabled_sizes = ewww_image_optimizer_get_option('ewww_image_optimizer_disable_resizes_opt');
                foreach ($attachments as $attachment) {
                    //					ewwwio_debug_message( 'checking attachment ' . $attachment[1] );
                    $meta = maybe_unserialize($attachment[0]);
                    if (empty($meta)) {
                        ewwwio_debug_message('empty meta');
                        continue;
                    }
                    $mime = '';
                    if (!empty($meta['file'])) {
                        $mime = ewww_image_optimizer_quick_mimetype($meta['file']);
                    } elseif (!empty($attachment[1])) {
                        $mime = get_post_mime_type($attachment[1]);
                        ewwwio_debug_message('checking mime via get_post...');
                    }
                    if ($mime == 'image/jpeg' && ewww_image_optimizer_get_option('ewww_image_optimizer_jpg_level') == 0) {
                        //						ewwwio_debug_message( 'optimization for this type disabled, skipping' );
                        continue;
                    }
                    if ($mime == 'image/png' && ewww_image_optimizer_get_option('ewww_image_optimizer_png_level') == 0) {
                        //						ewwwio_debug_message( 'optimization for this type disabled, skipping' );
                        continue;
                    }
                    if ($mime == 'image/gif' && ewww_image_optimizer_get_option('ewww_image_optimizer_gif_level') == 0) {
                        //						ewwwio_debug_message( 'optimization for this type disabled, skipping' );
                        continue;
                    }
                    if ($mime == 'application/pdf' && ewww_image_optimizer_get_option('ewww_image_optimizer_pdf_level') == 0) {
                        //						ewwwio_debug_message( 'optimization for this type disabled, skipping' );
                        continue;
                    }
                    if (empty($meta['ewww_image_optimizer'])) {
                        //						ewwwio_debug_message( 'no optimization status, counting as unoptimized full: ' . $attachment[1] );
                        //						ewwwio_debug_message( print_r( $meta, true ) );
                        $unoptimized_full++;
                        $ids[] = $attachment[1];
                    }
                    if (!empty($meta['ewww_image_optimizer']) && preg_match('/' . __('License exceeded', EWWW_IMAGE_OPTIMIZER_DOMAIN) . '/', $meta['ewww_image_optimizer'])) {
                        //						ewwwio_debug_message( 'optimization status license exceeded, counting as unoptimized full: ' . $attachment[1] );
                        //						ewwwio_debug_message( print_r( $meta, true ) );
                        $unoptimized_full++;
                        $ids[] = $attachment[1];
                    }
                    // resized versions, so we can continue
                    if (isset($meta['sizes']) && ewww_image_optimizer_iterable($meta['sizes'])) {
                        foreach ($meta['sizes'] as $size => $data) {
                            if (!empty($disabled_sizes[$size])) {
                                continue;
                            }
                            if (strpos($size, 'webp') === 0) {
                                continue;
                            }
                            $resize_count++;
                            if (empty($meta['sizes'][$size]['ewww_image_optimizer'])) {
                                $unoptimized_re++;
                            }
                        }
                    }
                }
                //		$full_count += count( $attachments );
                $offset += $max_query;
                if (!empty($attachment_ids)) {
                    $attachment_query = '';
                    $attachment_query_count = 0;
                    $offset = 0;
                    while ($attachment_ids && $attachment_query_count < $max_query) {
                        $attachment_query .= "'" . array_pop($attachment_ids) . "',";
                        $attachment_query_count++;
                    }
                    $attachment_query = 'AND metas.post_id IN (' . substr($attachment_query, 0, -1) . ')';
                }
            }
            break;
        case 'ngg':
            // see if we were given attachment IDs to work with via GET/POST
            if (!empty($_REQUEST['ewww_inline']) || get_option('ewww_image_optimizer_bulk_ngg_resume')) {
                // retrieve the attachment IDs that were pre-loaded in the database
                $attachment_ids = get_option('ewww_image_optimizer_bulk_ngg_attachments');
                while ($attachment_ids && $attachment_query_count < $max_query) {
                    $attachment_query .= "'" . array_pop($attachment_ids) . "',";
                    $attachment_query_count++;
                }
                $attachment_query = 'WHERE pid IN (' . substr($attachment_query, 0, -1) . ')';
            }
            // creating the 'registry' object for working with nextgen
            $registry = C_Component_Registry::get_instance();
            // creating a database storage object from the 'registry' object
            $storage = $registry->get_utility('I_Gallery_Storage');
            // get an array of sizes available for the $image
            $sizes = $storage->get_image_sizes();
            $offset = 0;
            while ($attachments = $wpdb->get_col("SELECT meta_data FROM {$wpdb->nggpictures} {$attachment_query} LIMIT {$offset}, {$max_query}")) {
                foreach ($attachments as $attachment) {
                    if (class_exists('Ngg_Serializable')) {
                        $serializer = new Ngg_Serializable();
                        $meta = $serializer->unserialize($attachment);
                    } else {
                        $meta = unserialize($attachment);
                    }
                    if (!is_array($meta)) {
                        continue;
                    }
                    if (empty($meta['ewww_image_optimizer'])) {
                        $unoptimized_full++;
                    }
                    if (ewww_image_optimizer_iterable($sizes)) {
                        foreach ($sizes as $size) {
                            if ($size !== 'full') {
                                $resize_count++;
                                if (empty($meta[$size]['ewww_image_optimizer'])) {
                                    $unoptimized_re++;
                                }
                            }
                        }
                    }
                }
                $full_count += count($attachments);
                $offset += $max_query;
                if (!empty($attachment_ids)) {
                    $attachment_query = '';
                    $attachment_query_count = 0;
                    $offset = 0;
                    while ($attachment_ids && $attachment_query_count < $max_query) {
                        $attachment_query .= "'" . array_pop($attachment_ids) . "',";
                        $attachment_query_count++;
                    }
                    $attachment_query = 'WHERE pid IN (' . substr($attachment_query, 0, -1) . ')';
                }
            }
            break;
        case 'flag':
            if (!empty($_REQUEST['doaction']) || get_option('ewww_image_optimizer_bulk_flag_resume')) {
                // retrieve the attachment IDs that were pre-loaded in the database
                $attachment_ids = get_option('ewww_image_optimizer_bulk_flag_attachments');
                while ($attachment_ids && $attachment_query_count < $max_query) {
                    $attachment_query .= "'" . array_pop($attachment_ids) . "',";
                    $attachment_query_count++;
                }
                $attachment_query = 'WHERE pid IN (' . substr($attachment_query, 0, -1) . ')';
            }
            $offset = 0;
            while ($attachments = $wpdb->get_col("SELECT meta_data FROM {$wpdb->flagpictures} {$attachment_query} LIMIT {$offset}, {$max_query}")) {
                foreach ($attachments as $attachment) {
                    $meta = unserialize($attachment);
                    if (!is_array($meta)) {
                        continue;
                    }
                    if (empty($meta['ewww_image_optimizer'])) {
                        $unoptimized_full++;
                    }
                    if (!empty($meta['webview'])) {
                        $resize_count++;
                        if (empty($meta['webview']['ewww_image_optimizer'])) {
                            $unoptimized_re++;
                        }
                    }
                    if (!empty($meta['thumbnail'])) {
                        $resize_count++;
                        if (empty($meta['thumbnail']['ewww_image_optimizer'])) {
                            $unoptimized_re++;
                        }
                    }
                }
                $full_count += count($attachments);
                $offset += $max_query;
                if (!empty($attachment_ids)) {
                    $attachment_query = '';
                    $attachment_query_count = 0;
                    $offset = 0;
                    while ($attachment_ids && $attachment_query_count < $max_query) {
                        $attachment_query .= "'" . array_pop($attachment_ids) . "',";
                        $attachment_query_count++;
                    }
                    $attachment_query = 'WHERE pid IN (' . substr($attachment_query, 0, -1) . ')';
                }
            }
            break;
    }
    if (empty($full_count) && !empty($attachment_ids)) {
        ewwwio_debug_message('query appears to have failed, just counting total images instead');
        $full_count = count($attachment_ids);
    }
    $elapsed = microtime(true) - $started;
    ewwwio_debug_message("counting images took {$elapsed} seconds");
    ewwwio_debug_message("found {$full_count} fullsize ({$unoptimized_full} unoptimized), and {$resize_count} resizes ({$unoptimized_re} unoptimized)");
    ewwwio_memory(__FUNCTION__);
    if ($return_ids) {
        return $ids;
    } else {
        return array($full_count, $unoptimized_full, $resize_count, $unoptimized_re);
    }
}
예제 #4
0
/**
 * Read the image paths from an attachment's meta data and process each image
 * with ewww_image_optimizer().
 *
 * This method also adds a `ewww_image_optimizer` meta key for use in the media library 
 * and may add a 'converted' and 'orig_file' key if conversion is enabled.
 *
 * Called after `wp_generate_attachment_metadata` is completed.
 */
function ewww_image_optimizer_resize_from_meta_data($meta, $ID = null, $log = true, $background_new = false)
{
    ewwwio_debug_message('<b>' . __FUNCTION__ . '()</b>');
    if (!is_array($meta) && empty($meta)) {
        $meta = array();
    } elseif (!is_array($meta)) {
        if (is_string($meta) && is_int($ID) && 'processing' == $meta) {
            ewwwio_debug_message("attempting to rebuild attachment meta for {$ID}");
            $new_meta = ewww_image_optimizer_rebuild_meta($ID);
            if (!is_array($new_meta)) {
                ewwwio_debug_message('attempt to rebuild attachment meta failed');
                return $meta;
            } else {
                $meta = $new_meta;
            }
        } else {
            ewwwio_debug_message('attachment meta is not a usable array');
            return $meta;
        }
    } elseif (is_array($meta) && !empty($meta[0]) && 'processing' == $meta[0]) {
        ewwwio_debug_message("attempting to rebuild attachment meta for {$ID}");
        $new_meta = ewww_image_optimizer_rebuild_meta($ID);
        if (!is_array($new_meta)) {
            ewwwio_debug_message('attempt to rebuild attachment meta failed');
            return $meta;
        } else {
            $meta = $new_meta;
        }
    }
    global $wpdb;
    global $ewww_defer;
    global $ewww_new_image;
    $gallery_type = 1;
    ewwwio_debug_message("attachment id: {$ID}");
    session_write_close();
    //if ( ! metadata_exists( 'post', $ID, '_wp_attachment_metadata' ) ) {
    if (!empty($ewww_new_image)) {
        ewwwio_debug_message('this is a newly uploaded image with no metadata yet');
        $new_image = true;
    } else {
        ewwwio_debug_message('this image already has metadata, so it is not new');
        $new_image = false;
    }
    list($file_path, $upload_path) = ewww_image_optimizer_attachment_path($meta, $ID);
    // if the attachment has been uploaded via the image store plugin
    if ('ims_image' == get_post_type($ID)) {
        $gallery_type = 6;
    }
    if (!$new_image && class_exists('Amazon_S3_And_CloudFront') && strpos($file_path, 's3') === 0) {
        ewww_image_optimizer_check_table_as3cf($meta, $ID, $file_path);
    }
    // if the local file is missing and we have valid metadata, see if we can fetch via CDN
    if (!is_file($file_path) || strpos($file_path, 's3') === 0) {
        $file_path = ewww_image_optimizer_remote_fetch($ID, $meta);
        if (!$file_path) {
            ewwwio_debug_message('could not retrieve path');
            $meta['ewww_image_optimizer'] = __('Could not find image', EWWW_IMAGE_OPTIMIZER_DOMAIN);
            return $meta;
        }
    }
    ewwwio_debug_message("retrieved file path: {$file_path}");
    $type = ewww_image_optimizer_mimetype($file_path, 'i');
    $supported_types = array('image/jpeg', 'image/png', 'image/gif', 'application/pdf');
    if (!in_array($type, $supported_types)) {
        ewwwio_debug_message("mimetype not supported: {$ID}");
        return $meta;
    }
    // see if this is a new image and Imsanity resized it (which means it could be already optimized)
    if (!empty($new_image) && function_exists('imsanity_get_max_width_height')) {
        list($maxW, $maxH) = imsanity_get_max_width_height(IMSANITY_SOURCE_LIBRARY);
        list($oldW, $oldH) = getimagesize($file_path);
        list($newW, $newH) = wp_constrain_dimensions($oldW, $oldH, $maxW, $maxH);
        $path_parts = pathinfo($file_path);
        $imsanity_path = trailingslashit($path_parts['dirname']) . $path_parts['filename'] . '-' . $newW . 'x' . $newH . '.' . $path_parts['extension'];
        ewwwio_debug_message("imsanity path: {$imsanity_path}");
        $image_size = ewww_image_optimizer_filesize($file_path);
        $already_optimized = ewww_image_optimizer_find_already_optimized($imsanity_path);
        if (is_array($already_optimized)) {
            ewwwio_debug_message("updating existing record, path: {$file_path}, size: " . $image_size);
            // store info on the current image for future reference
            $wpdb->update($wpdb->ewwwio_images, array('path' => $file_path), array('id' => $already_optimized['id']));
        }
    }
    // NOTE: if you use the ewww_image_optimizer_defer_resizing filter to defer the resize operation, only the "other" dimensions will apply
    // resize here unless the user chose to defer resizing, we have a new image OR resize existing is enabled, and imsanity isn't enabled with a max size
    if (!apply_filters('ewww_image_optimizer_defer_resizing', false) && (!empty($new_image) || ewww_image_optimizer_get_option('ewww_image_optimizer_resize_existing')) && !function_exists('imsanity_get_max_width_height')) {
        $new_dimensions = ewww_image_optimizer_resize_upload($file_path);
        if (is_array($new_dimensions)) {
            $meta['width'] = $new_dimensions[0];
            $meta['height'] = $new_dimensions[1];
        }
    }
    if ($ewww_defer && !ewww_image_optimizer_detect_wpsf_location_lock() && ewww_image_optimizer_get_option('ewww_image_optimizer_background_optimization')) {
        add_filter('http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX);
        global $ewwwio_media_background;
        if (!class_exists('WP_Background_Process')) {
            require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'background.php';
        }
        if (!is_object($ewwwio_media_background)) {
            $ewwwio_media_background = new EWWWIO_Media_Background_Process();
        }
        ewwwio_debug_message("backgrounding optimization for {$ID}");
        $ewwwio_media_background->push_to_queue(array('id' => $ID, 'new' => $new_image, 'type' => $type));
        $ewwwio_media_background->save()->dispatch();
        set_transient('ewwwio-background-in-progress-' . $ID, true, 24 * HOUR_IN_SECONDS);
        if ($log) {
            ewww_image_optimizer_debug_log();
        }
        return $meta;
    }
    if ($background_new) {
        $new_image = true;
    }
    // resize here if the user has used the filter to defer resizing, we have a new image OR resize existing is enabled, and imsanity isn't enabled with a max size
    if (apply_filters('ewww_image_optimizer_defer_resizing', false) && (!empty($new_image) || ewww_image_optimizer_get_option('ewww_image_optimizer_resize_existing')) && !function_exists('imsanity_get_max_width_height')) {
        $new_dimensions = ewww_image_optimizer_resize_upload($file_path);
        if (is_array($new_dimensions)) {
            $meta['width'] = $new_dimensions[0];
            $meta['height'] = $new_dimensions[1];
        }
    }
    // this gets a bit long, so here goes:
    // we run in parallel if we didn't detect breakage (test_parallel_opt), if the type isn't pdf (there's only one file to optimize anyway), and there are enough resizes to make it worthwhile (or if the API is enabled)
    if (ewww_image_optimizer_test_parallel_opt($ID) && $type != 'application/pdf' && isset($meta['sizes']) && (ewww_image_optimizer_get_option('ewww_image_optimizer_cloud_key') || count($meta['sizes']) > 5)) {
        //	if ( ewww_image_optimizer_test_parallel_opt( $ID ) && $type != 'application/pdf' ) {
        ewwwio_debug_message('running in parallel');
        $parallel_opt = true;
    } else {
        ewwwio_debug_message('running in sequence');
        $parallel_opt = false;
    }
    $parallel_sizes = array();
    if ($parallel_opt) {
        add_filter('http_headers_useragent', 'ewww_image_optimizer_cloud_useragent', PHP_INT_MAX);
        $parallel_sizes['full'] = $file_path;
        global $ewwwio_async_optimize_media;
        if (!class_exists('WP_Background_Process')) {
            require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'background.php';
        }
        if (!is_object($ewwwio_async_optimize_media)) {
            $ewwwio_async_optimize_media = new EWWWIO_Async_Request();
        }
    } else {
        list($file, $msg, $conv, $original) = ewww_image_optimizer($file_path, $gallery_type, false, $new_image, true);
        // update the optimization results in the metadata
        $meta['ewww_image_optimizer'] = $msg;
        if ($file === false) {
            return $meta;
        }
        $meta['file'] = str_replace($upload_path, '', $file);
        // if the file was converted
        if ($conv !== false) {
            // update the filename in the metadata
            $new_file = substr($meta['file'], 0, -3);
            // change extension
            $new_ext = substr($file, -3);
            $meta['file'] = $new_file . $new_ext;
            ewwwio_debug_message('image was converted');
            // if we don't already have the update attachment filter
            if (FALSE === has_filter('wp_update_attachment_metadata', 'ewww_image_optimizer_update_attachment')) {
                // add the update attachment filter
                add_filter('wp_update_attachment_metadata', 'ewww_image_optimizer_update_attachment', 10, 2);
            }
            // store the conversion status in the metadata
            $meta['converted'] = 1;
            // store the old filename in the database
            $meta['orig_file'] = $original;
        } else {
            remove_filter('wp_update_attachment_metadata', 'ewww_image_optimizer_update_attachment', 10);
        }
        ewww_image_optimizer_hidpi_optimize($file_path);
    }
    // resized versions, so we can continue
    if (isset($meta['sizes']) && ewww_image_optimizer_iterable($meta['sizes'])) {
        $disabled_sizes = ewww_image_optimizer_get_option('ewww_image_optimizer_disable_resizes_opt');
        ewwwio_debug_message('processing resizes');
        // meta sizes don't contain a path, so we calculate one
        if ($gallery_type === 6) {
            $base_ims_dir = trailingslashit(dirname($file_path)) . '_resized/';
        }
        $base_dir = trailingslashit(dirname($file_path));
        // process each resized version
        $processed = array();
        foreach ($meta['sizes'] as $size => $data) {
            ewwwio_debug_message("processing size: {$size}");
            if (strpos($size, 'webp') === 0) {
                continue;
            }
            if (!empty($disabled_sizes[$size])) {
                continue;
            }
            if (empty($data['file'])) {
                continue;
            }
            if ($gallery_type === 6) {
                $base_dir = dirname($file_path) . '/';
                $image_path = $base_dir . $data['file'];
                $ims_path = $base_ims_dir . $data['file'];
                if (file_exists($ims_path)) {
                    ewwwio_debug_message('ims resize already exists, wahoo');
                    ewwwio_debug_message("ims path: {$ims_path}");
                    $image_size = ewww_image_optimizer_filesize($ims_path);
                    $already_optimized = ewww_image_optimizer_find_already_optimized($image_path);
                    if (is_array($already_optimized)) {
                        ewwwio_debug_message("updating existing record, path: {$ims_path}, size: " . $image_size);
                        // store info on the current image for future reference
                        $wpdb->update($wpdb->ewwwio_images, array('path' => $ims_path), array('id' => $already_optimized['id']));
                    }
                    $base_dir = $base_ims_dir;
                }
            }
            // initialize $dup_size
            $dup_size = false;
            // check through all the sizes we've processed so far
            foreach ($processed as $proc => $scan) {
                // if a previous resize had identical dimensions
                if ($scan['height'] == $data['height'] && $scan['width'] == $data['width']) {
                    // found a duplicate resize
                    $dup_size = true;
                    // point this resize at the same image as the previous one
                    $meta['sizes'][$size]['file'] = $meta['sizes'][$proc]['file'];
                    // and tell the user we didn't do any further optimization
                    $meta['sizes'][$size]['ewww_image_optimizer'] = __('No savings', EWWW_IMAGE_OPTIMIZER_DOMAIN);
                }
            }
            // if this is a unique size
            if (!$dup_size) {
                $resize_path = $base_dir . $data['file'];
                // run the optimization and store the results
                if ($parallel_opt && file_exists($resize_path)) {
                    $parallel_sizes[$size] = $resize_path;
                } else {
                    list($optimized_file, $results, $resize_conv, $original) = ewww_image_optimizer($resize_path, $gallery_type, $conv, $new_image);
                    // if the resize was converted, store the result and the original filename in the metadata for later recovery
                    if ($resize_conv !== false) {
                        // if we don't already have the update attachment filter
                        if (FALSE === has_filter('wp_update_attachment_metadata', 'ewww_image_optimizer_update_attachment')) {
                            // add the update attachment filter
                            add_filter('wp_update_attachment_metadata', 'ewww_image_optimizer_update_attachment', 10, 2);
                        }
                        $meta['sizes'][$size]['mime-type'] = ewww_image_optimizer_quick_mimetype($optimized_file);
                        $meta['sizes'][$size]['converted'] = 1;
                        $meta['sizes'][$size]['orig_file'] = str_replace($base_dir, '', $original);
                        ewwwio_debug_message("original filename: {$original}");
                        $meta['sizes'][$size]['real_orig_file'] = str_replace($base_dir, '', $resize_path);
                        ewwwio_debug_message("resize path: {$resize_path}");
                    }
                    if ($optimized_file !== false) {
                        // update the filename
                        $meta['sizes'][$size]['file'] = str_replace($base_dir, '', $optimized_file);
                    }
                    // update the optimization results
                    $meta['sizes'][$size]['ewww_image_optimizer'] = $results;
                }
                // optimize retina images, if they exist
                if (function_exists('wr2x_get_retina') && ($retina_path = wr2x_get_retina($resize_path))) {
                    if ($parallel_opt && file_exists($retina_path)) {
                        $async_path = str_replace($upload_path, '', $retina_path);
                        $ewwwio_async_optimize_media->data(array('path' => $async_path, 'size' => '', 'ewww_force' => $force))->dispatch();
                    } elseif (file_exists($retina_path)) {
                        ewww_image_optimizer($retina_path);
                    }
                } elseif (!$parallel_opt) {
                    ewww_image_optimizer_hidpi_optimize($resize_path);
                }
            }
            // store info on the sizes we've processed, so we can check the list for duplicate sizes
            $processed[$size]['width'] = $data['width'];
            $processed[$size]['height'] = $data['height'];
        }
    }
    if (!empty($new_dimensions)) {
        $prev_string = " - " . __('Previously Optimized', EWWW_IMAGE_OPTIMIZER_DOMAIN);
        $meta['ewww_image_optimizer'] = preg_replace("/{$prev_string}/", '', $meta['ewww_image_optimizer']);
    }
    // process size from a custom theme
    if (isset($meta['image_meta']['resized_images']) && ewww_image_optimizer_iterable($meta['image_meta']['resized_images'])) {
        $imagemeta_resize_pathinfo = pathinfo($file_path);
        $imagemeta_resize_path = '';
        foreach ($meta['image_meta']['resized_images'] as $imagemeta_resize) {
            $imagemeta_resize_path = $imagemeta_resize_pathinfo['dirname'] . '/' . $imagemeta_resize_pathinfo['filename'] . '-' . $imagemeta_resize . '.' . $imagemeta_resize_pathinfo['extension'];
            if ($parallel_opt && file_exists($imagemeta_resize_path)) {
                $async_path = str_replace($upload_path, '', $imagemeta_resize_path);
                $ewwwio_async_optimize_media->data(array('path' => $async_path, 'size' => '', 'ewww_force' => $force))->dispatch();
            } else {
                ewww_image_optimizer($imagemeta_resize_path);
            }
        }
    }
    // and another custom theme
    if (isset($meta['custom_sizes']) && ewww_image_optimizer_iterable($meta['custom_sizes'])) {
        $custom_sizes_pathinfo = pathinfo($file_path);
        $custom_size_path = '';
        foreach ($meta['custom_sizes'] as $custom_size) {
            $custom_size_path = $custom_sizes_pathinfo['dirname'] . '/' . $custom_size['file'];
            if ($parallel_opt && file_exists($custom_size_path)) {
                $async_path = str_replace($upload_path, '', $custom_size_path);
                $ewwwio_async_optimize_media->data(array('path' => $async_path, 'size' => '', 'ewww_force' => $force))->dispatch();
            } else {
                ewww_image_optimizer($custom_size_path);
            }
        }
    }
    if ($parallel_opt && count($parallel_sizes) > 0) {
        $max_threads = (int) apply_filters('ewww_image_optimizer_max_parallel_threads', 5);
        $processing = true;
        $timer = (int) apply_filters('ewww_image_optimizer_background_timer_init', 1);
        $increment = (int) apply_filters('ewww_image_optimizer_background_timer_increment', 1);
        $timer_max = (int) apply_filters('ewww_image_optimizer_background_timer_max', 20);
        $processing_sizes = array();
        if (!empty($_REQUEST['ewww_force'])) {
            $force = true;
        } else {
            $force = false;
        }
        global $ewwwio_async_optimize_media;
        if (!class_exists('WP_Background_Process')) {
            require_once EWWW_IMAGE_OPTIMIZER_PLUGIN_PATH . 'background.php';
        }
        if (!is_object($ewwwio_async_optimize_media)) {
            $ewwwio_async_optimize_media = new EWWWIO_Async_Request();
        }
        while ($parallel_opt && count($parallel_sizes) > 0) {
            $threads = $max_threads;
            ewwwio_debug_message('sizes left to queue: ' . count($parallel_sizes));
            // phase 1, add $max_threads items to the queue and dispatch
            foreach ($parallel_sizes as $size => $filename) {
                if ($threads < 1) {
                    continue;
                }
                if (!file_exists($filename)) {
                    unset($parallel_sizes[$size]);
                    continue;
                }
                ewwwio_debug_message("queueing size {$size} - {$filename}");
                $processing_sizes[$size] = $filename;
                unset($parallel_sizes[$size]);
                touch($filename . '.processing');
                $async_path = str_replace($upload_path, '', $filename);
                ewwwio_debug_message("sending off {$async_path} in folder {$upload_path}");
                $ewwwio_async_optimize_media->data(array('ewwwio_path' => $async_path, 'ewwwio_size' => $size, 'ewww_force' => $force))->dispatch();
                $threads--;
                ewwwio_debug_message('sizes left to queue: ' . count($parallel_sizes));
                $processing = true;
            }
            // phase 2, we start checking to see what sizes are done, and populate the metadata with the results
            while ($parallel_opt && $processing) {
                $processing = false;
                foreach ($processing_sizes as $size => $filename) {
                    if (is_file($filename . '.processing')) {
                        ewwwio_debug_message("still processing {$size}");
                        $processing = true;
                        continue;
                    }
                    if ($size == 'full') {
                        $image = ewww_image_optimizer_find_already_optimized($filename);
                        $meta['ewww_image_optimizer'] = $image['results'];
                        unset($processing_sizes[$size]);
                        ewwwio_debug_message('got results for full size');
                    } else {
                        $image = ewww_image_optimizer_find_already_optimized($filename);
                        $meta['sizes'][$size]['ewww_image_optimizer'] = $image['results'];
                        unset($processing_sizes[$size]);
                        ewwwio_debug_message("got results for {$size} size");
                    }
                }
                if ($processing) {
                    ewwwio_debug_message("sleeping for {$timer} seconds");
                    sleep($timer);
                    $timer += $increment;
                    clearstatcache();
                }
                if ($timer > $timer_max) {
                    break;
                }
                if ($log) {
                    ewww_image_optimizer_debug_log();
                }
            }
            if ($timer > $timer_max) {
                foreach ($processing_sizes as $filename) {
                    if (is_file($filename . '.processing')) {
                        unlink($filename . '.processing');
                    }
                }
                $meta['processing'] = 1;
                if ($log) {
                    ewww_image_optimizer_debug_log();
                }
                return $meta;
            }
            if ($log) {
                ewww_image_optimizer_debug_log();
            }
        }
    }
    unset($meta['processing']);
    if (!empty($new_image)) {
        $meta = ewww_image_optimizer_update_attachment_metadata($meta, $ID);
    }
    global $ewww_attachment;
    $ewww_attachment['id'] = $ID;
    $ewww_attachment['meta'] = $meta;
    add_filter('w3tc_cdn_update_attachment_metadata', 'ewww_image_optimizer_w3tc_update_files');
    if (!preg_match('/' . __('Previously Optimized', EWWW_IMAGE_OPTIMIZER_DOMAIN) . '/', $meta['ewww_image_optimizer']) && class_exists('Amazon_S3_And_CloudFront')) {
        global $as3cf;
        if (method_exists($as3cf, 'wp_update_attachment_metadata')) {
            $as3cf->wp_update_attachment_metadata($meta, $ID);
        } elseif (method_exists($as3cf, 'wp_generate_attachment_metadata')) {
            $as3cf->wp_generate_attachment_metadata($meta, $ID);
        }
        ewwwio_debug_message('uploading to Amazon S3');
    }
    if (!preg_match('/' . __('Previously Optimized', EWWW_IMAGE_OPTIMIZER_DOMAIN) . '/', $meta['ewww_image_optimizer']) && class_exists('DreamSpeed_Services')) {
        global $dreamspeed;
        $dreamspeed->wp_generate_attachment_metadata($meta, $ID);
        ewwwio_debug_message('uploading to Dreamspeed');
    }
    if (class_exists('Cloudinary') && Cloudinary::config_get("api_secret") && ewww_image_optimizer_get_option('ewww_image_optimizer_enable_cloudinary') && !empty($new_image)) {
        try {
            $result = CloudinaryUploader::upload($file, array('use_filename' => true));
        } catch (Exception $e) {
            $error = $e->getMessage();
        }
        if (!empty($error)) {
            ewwwio_debug_message("Cloudinary error: {$error}");
        } else {
            ewwwio_debug_message('successfully uploaded to Cloudinary');
            // register the attachment in the database as a cloudinary attachment
            $old_url = wp_get_attachment_url($ID);
            wp_update_post(array('ID' => $ID, 'guid' => $result['url']));
            update_attached_file($ID, $result['url']);
            $meta['cloudinary'] = TRUE;
            $errors = array();
            // update the image location for the attachment
            CloudinaryPlugin::update_image_src_all($ID, $result, $old_url, $result['url'], TRUE, $errors);
            if (count($errors) > 0) {
                ewwwio_debug_message("Cannot migrate the following posts:");
                foreach ($errors as $error) {
                    ewwwio_debug_message($error);
                }
            }
        }
    }
    if ($log) {
        ewww_image_optimizer_debug_log();
    }
    ewwwio_memory(__FUNCTION__);
    // send back the updated metadata
    return $meta;
}