diff --git a/remote_stream_wrapper.image.inc b/remote_stream_wrapper.image.inc
index 6f1b84e..bdc1eb1 100644
--- a/remote_stream_wrapper.image.inc
+++ b/remote_stream_wrapper.image.inc
@@ -2,21 +2,25 @@
 
 /**
  * Copy of image_style_deliver() for use with remote images.
+ *
+ * @see remote_stream_wrapper_image_style_path()
  */
-function remote_stream_wrapper_image_style_deliver($style, $scheme) {
-  $args = func_get_args();
-  array_shift($args);
-  array_shift($args);
-  $target = implode('/', $args);
+function remote_stream_wrapper_image_style_deliver($style, $scheme, $host, $filename) {
+  list($hash, $extension) = explode('.', $filename, 2);
 
-  $image_uri = $scheme . '://' . $target;
-  $derivative_uri = remote_stream_wrapper_image_style_path($style['name'], $image_uri);
+  // Only process remote URLs for which remote_stream_wrapper_image_style_path()
+  // (e.g., via theme('image_style')) has been invoked. Otherwise, the website
+  // is open to any user processing any remote URL.
+  $image_uri = db_select('remote_stream_wrapper_url', 'rswu')->fields('rswu', array('url'))->condition('id', $hash)->execute()->fetchField();
+  if (!isset($image_uri)) {
+    return MENU_NOT_FOUND;
+  }
 
-  // Prevent only the remote files that exist in {file_managed} from having
-  // image style derivatives generated. Otherwise this could open up the site
-  // to allowing any remote file to be processed.
-  if (!remote_stream_wrapper_file_load_by_uri($image_uri)) {
-    return MENU_ACCESS_DENIED;
+  // Ensure the derivative URI requested matches the one returned by
+  // remote_stream_wrapper_image_style_path().
+  $derivative_uri = file_default_scheme() . '://styles/' . $style['name'] . '/' . $scheme . '/' . $host . '/' . $filename;
+  if ($derivative_uri !== remote_stream_wrapper_image_style_path($style['name'], $image_uri)) {
+    return MENU_NOT_FOUND;
   }
 
   // Don't start generating the image if the derivative already exists or if
diff --git a/remote_stream_wrapper.install b/remote_stream_wrapper.install
new file mode 100644
index 0000000..b4d47ca
--- /dev/null
+++ b/remote_stream_wrapper.install
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @file
+ * Install, update and uninstall functions for the Remote Stream Wrapper module.
+ *
+ * @ingroup remote_stream_wrapper
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function remote_stream_wrapper_schema() {
+  $schema['remote_stream_wrapper_url'] = _remote_stream_wrapper_url_schema_7000();
+  return $schema;
+}
+
+/**
+ * Add the {remote_stream_wrapper_url} table to track information about remote URLs.
+ */
+function remote_stream_wrapper_update_7000() {
+  db_create_table('remote_stream_wrapper_url', _remote_stream_wrapper_url_schema_7000());
+}
+
+/**
+ * Schema for the {remote_stream_wrapper_url} table as of remote_stream_wrapper_update_7000().
+ */
+function _remote_stream_wrapper_url_schema_7000() {
+  return array(
+    'description' => 'The base table for information about remote URLs.',
+    'fields' => array(
+      'id' => array(
+        'description' => 'Primary key; the sha256 hash of the URL.',
+        'type' => 'varchar',
+        'length' => 64,
+        'not null' => TRUE,
+      ),
+      'url' => array(
+        'description' => 'The URL.',
+        'type' => 'text',
+        'not null' => TRUE,
+      ),
+    ),
+    'primary key' => array('id'),
+  );
+}
diff --git a/remote_stream_wrapper.module b/remote_stream_wrapper.module
index cba1d97..5ce5c28 100644
--- a/remote_stream_wrapper.module
+++ b/remote_stream_wrapper.module
@@ -96,18 +96,21 @@ function file_is_scheme_remote($scheme) {
 }
 
 /**
+ * Implements hook_process_image_style().
+ */
+function remote_stream_wrapper_process_image_style(&$variables) {
+  $variables['source_path'] = $variables['path'];
+}
+
+/**
  * Implements hook_preprocess_image().
  */
 function remote_stream_wrapper_preprocess_image(&$variables) {
-  static $regex;
-
-  if (!empty($variables['style_name'])) {
-    if (!isset($regex)) {
-      $wrappers = file_get_remote_stream_wrappers();
-      $schemes = implode('|', array_keys($wrappers));
-      $regex = "#^($schemes)://styles/#";
+  if (!empty($variables['style_name']) && !empty($variables['source_path'])) {
+    $uri = $variables['source_path'];
+    if (file_is_scheme_remote(file_uri_scheme($uri))) {
+      $variables['path'] = remote_stream_wrapper_image_style_path($variables['style_name'], $uri);
     }
-    $variables['path'] = preg_replace($regex, file_default_scheme() . '://styles/', $variables['path'], 1);
   }
 }
 
@@ -119,9 +122,47 @@ function remote_stream_wrapper_preprocess_image(&$variables) {
  * which will fail image_style_deliver().
  */
 function remote_stream_wrapper_image_style_path($style_name, $uri) {
-  // Force the image style to be returned with the default file scheme, but
-  // with the file's original scheme in the path.
-  return file_default_scheme() . '://styles/' . $style_name . '/' . file_uri_scheme($uri) . '/' . file_uri_target($uri);
+  $scheme = file_uri_scheme($uri);
+  $host = parse_url($uri, PHP_URL_HOST);
+
+  // Retrieve the canonical extension of the file. If it's not an image, then
+  // generating an image style is unlikely to work, so return the source URL.
+  $extension = remote_stream_wrapper_image_style_extension($uri);
+  if (!isset($extension)) {
+    return $uri;
+  }
+
+  // The remote URL might have a query string or other characters that we don't
+  // want in the generated derivative filename, so use a hash for the derivative
+  // name.
+  $hash = hash('sha256', $uri);
+
+  // Add this URL to the database, so that
+  // remote_stream_wrapper_image_style_deliver() knows that this is an allowed
+  // file to fetch and process, and can recover the source URL from the hash.
+  db_merge('remote_stream_wrapper_url')
+    ->key(array('id' => $hash))
+    ->fields(array('url' => $uri))
+    ->execute();
+
+  // Place the derivative in the default file scheme.
+  return file_default_scheme() . '://styles/' . $style_name . '/' . $scheme . '/' . $host . '/' . $hash . '.' . $extension;
+}
+
+/**
+ * Returns the canonical extension for the mimetype of the URI, if it's an image.
+ */
+function remote_stream_wrapper_image_style_extension($uri) {
+  $mimetype = file_get_mimetype($uri);
+  if (strpos($mimetype, 'image/') === 0) {
+    include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
+    $mapping = file_mimetype_mapping();
+    $mimetypes = array_flip($mapping['mimetypes']);
+    $extensions = array_flip($mapping['extensions']);
+    if (isset($mimetypes[$mimetype]) && isset($extensions[$mimetypes[$mimetype]])) {
+      return $extensions[$mimetypes[$mimetype]];
+    }
+  }
 }
 
 /**
