diff --git a/core/modules/image/image.admin.inc b/core/modules/image/image.admin.inc
index 539e756..2c9d01c 100644
--- a/core/modules/image/image.admin.inc
+++ b/core/modules/image/image.admin.inc
@@ -449,6 +449,17 @@ function image_effect_scale_validate($element, &$form_state) {
 }
 
 /**
+ * Form element validation handler for a specified percent value.
+ */
+function image_effect_percent_validate($element, &$form_state) {
+  if ($element['#value'] !== '') {
+    if (!is_numeric($element['#value']) || $element['#value'] < 0 || $element['#value'] > 100) {
+      form_error($element, t('!name must be a number between 0 and 100.', array('!name' => $element['#title'])));
+    }
+  }
+}
+
+/**
  * Form structure for the image resize form.
  *
  * Note that this is not a complete form, it only contains the portion of the
@@ -588,6 +599,31 @@ function image_rotate_form($data) {
 }
 
 /**
+ * Form structure for the image quality effect form.
+ *
+ * Note that this is not a complete form, it only contains the portion of the
+ * form for configuring the quality options. Therefore it does not not need to
+ * include metadata about the effect, nor a submit button.
+ *
+ * @param $data
+ *   The current configuration for this quality effect.
+ */
+function image_quality_form($data) {
+  $form['quality'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Quality'),
+    '#default_value' => isset($data['quality']) ? $data['quality'] : 75,
+    '#field_suffix' => t('%'),
+    '#required' => TRUE,
+    '#element_validate' => array('image_effect_percent_validate'),
+    '#size' => 10,
+    '#maxlength' => 3,
+    '#description' => t('Define the image quality for JPEG manipulations. Ranges from 0 to 100. Higher values mean better image quality but bigger files.'),
+  );
+  return $form;
+}
+
+/**
  * Returns HTML for the page containing the list of image styles.
  *
  * @param $variables
@@ -846,3 +882,18 @@ function theme_image_rotate_summary($variables) {
   $data = $variables['data'];
   return ($data['random']) ? t('random between -@degrees&deg and @degrees&deg', array('@degrees' => str_replace('-', '', $data['degrees']))) : t('@degrees&deg', array('@degrees' => $data['degrees']));
 }
+
+/**
+ * Returns HTML for a summary of an image quality effect.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - data: The current configuration for this quality effect.
+ *
+ * @ingroup themeable
+ */
+function theme_image_quality_summary($variables) {
+  $data = $variables['data'];
+  return check_plain($data['percent']) . t('%');
+}
+
diff --git a/core/modules/image/image.effects.inc b/core/modules/image/image.effects.inc
index 35a6a74..6da38e1 100644
--- a/core/modules/image/image.effects.inc
+++ b/core/modules/image/image.effects.inc
@@ -56,6 +56,14 @@ function image_image_effect_info() {
       'form callback' => 'image_rotate_form',
       'summary theme' => 'image_rotate_summary',
     ),
+    'image_quality' => array(
+      'label' => t('Quality'),
+      'help' => t('Decreasing the quality will make image file sizes smaller.'),
+      'effect callback' => 'image_quality_effect',
+      'dimensions passthrough' => TRUE,
+      'form callback' => 'image_quality_form',
+      'summary theme' => 'image_quality_summary',
+    ),
   );
 
   return $effects;
@@ -312,3 +320,25 @@ function image_rotate_dimensions(array &$dimensions, array $data) {
     $dimensions['width'] = $dimensions['height'] = NULL;
   }
 }
+
+/**
+ * Image effect callback; Change the quality for a target image.
+ *
+ * @param $image
+ *   An image object returned by image_load().
+ * @param $data
+ *   An associative array containing the effect configuration values:
+ *   - quality: An integer representing the desired image quality in percent.
+ *
+ * @return
+ *   Always TRUE. The quality is set as a property on the $image, so the image
+ *   toolkit's save callback may apply it when the image is written to disk.
+ *
+ * @see image_save()
+ * @see image_gd_save()
+ */
+function image_quality_effect(&$image, $data) {
+  $image->quality = $data['quality'];
+  return TRUE;
+}
+
diff --git a/core/modules/system/image.gd.inc b/core/modules/system/image.gd.inc
index 39f86dc..c72e35d 100644
--- a/core/modules/system/image.gd.inc
+++ b/core/modules/system/image.gd.inc
@@ -268,8 +268,12 @@ function image_gd_save(stdClass $image, $destination) {
   if (!function_exists($function)) {
     return FALSE;
   }
+  // Apply the JPEG quality value if there is none yet.
+  if (!isset($image->quality)) {
+    $image->quality = variable_get('image_jpeg_quality', 75);
+  }
   if ($extension == 'jpeg') {
-    $success = $function($image->resource, $destination, variable_get('image_jpeg_quality', 75));
+    $success = $function($image->resource, $destination, $image->quality);
   }
   else {
     // Always save PNG images with full transparency.
