diff --git a/imageapi_optimize.module b/imageapi_optimize.module
index eee1349..b19673b 100644
--- a/imageapi_optimize.module
+++ b/imageapi_optimize.module
@@ -138,6 +138,9 @@ function image_imageapi_optimize_settings() {
     if (isset($service['url'])) {
       $form['imageapi_optimize_service']['imageapi_optimize_service']['#options'][$name] = l($service['title'], $service['url']);
     }
+    if (isset($service['description'])) {
+      $form['imageapi_optimize_service']['imageapi_optimize_service']['#options'][$name] .= $service['description'];
+    }
 
     // Build service form if required.
     if (isset($service['callbacks']['form'])) {
diff --git a/services/tinypng.inc b/services/tinypng.inc
new file mode 100644
index 0000000..ba9d03b
--- /dev/null
+++ b/services/tinypng.inc
@@ -0,0 +1,143 @@
+<?php
+/**
+ * @file
+ * TinyPNG service integration.
+ * Registration is required for using this service.
+ * @see details at https://tinypng.com/developers
+ */
+
+/**
+ * Implements imageapi_optimize_TYPE_NAME_info().
+ */
+function imageapi_optimize_services_tinypng_info() {
+  return array(
+    'title' => t('TinyPNG.com'),
+    'description' => t('- Registration is required for using this service. Obtain your free API key <a href="@tinyPNG-registration">here</a>.', array('@tinyPNG-registration' => 'https://tinypng.com/developers')),
+    'url' => 'http://tinypng.com',
+    'weight' => 10,
+  );
+}
+
+/**
+ * TinyPNG ImageAPI Optimize form callback.
+ */
+function imageapi_optimize_services_tinypng_form($info) {
+  $form = array();
+
+  $settings = variable_get('imageapi_optimize_tinypng', array(
+    'api_key' => '',
+    'debug_mode_tinypng' => FALSE,
+  ));
+
+  $form['imageapi_optimize_tinypng'] = array(
+    '#type' => 'container',
+    '#tree' => TRUE,
+  );
+
+  $form['imageapi_optimize_tinypng']['intro'] = array(
+    '#markup' => '<p>TinyPNG uses smart lossy compression techniques to reduce the file size of your PNG files. By selectively decreasing the number of colors in the image, fewer bytes are required to store the data. The effect is nearly invisible but it makes a very large difference in file size!</p><p>TinyPNG compression ONLY APPLIES TO PNG files. If your image is uploaded in other format, TinyPNG will not process the image and the default Image Toolkit processing will apply.</p><p>If you want to process existing PNG files, remove their image styles with the command <pre>drush image-flush --all</pre> and they will be recreated using TinyPNG the 1st time they are called.</p><p>Free licenses has a limit of conversions per user and per month. Please note that each time an image is uploaded to your Drupal site, an automatic request to TinyPNG is performed for EACH ONE of the Image Styles EFFECTIVELY USED for the image. This is the desired behavior, but it may quickly drain your monthly quota if many images are uploaded and many Image Styles are used.</p>'
+  );
+
+  $form['imageapi_optimize_tinypng']['api_key'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Enter your API key'),
+    '#default_value' => $settings['api_key'],
+    '#size' => 33,
+    '#maxlength' => 32,
+    '#required' => FALSE,
+    '#element_validate' => array('imageapi_optimize_tinypng_validate_api_key')
+  );
+
+  $form['imageapi_optimize_tinypng']['debug_mode_tinypng'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('<b>Enable debug mode</b>: show statistics (size reduction) from successful requests.'),
+    '#default_value' => $settings['debug_mode_tinypng']
+  );
+
+  return $form;
+}
+
+/**
+ * Validation callback for tinyPNG API key.
+ * Just check that the key entered has 32-char length.
+ */
+function imageapi_optimize_tinypng_validate_api_key($element, &$form_state, $form) {
+
+  if (($form_state['values']['image_toolkit'] == 'imageapi_optimize') &&
+      ($form_state['values']['imageapi_optimize_service'] == 'tinypng') &&
+      (strlen($element['#value']) != 32)) {
+    form_set_error($element['#parents'][0], t('TinyPNG API key must have 32-char length.'));
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
+/**
+ * TinyPNG ImageAPI Optimize service callback.
+ */
+function imageapi_optimize_services_tinypng($image, $dst) {
+
+  // Gracefully delegate to Image Toolkit if format is not PNG
+  if ($image->info['mime_type'] != 'image/png') {
+    return FALSE;
+  }
+
+  // Check if you have curl loaded
+  if (!function_exists('curl_init')) {
+    drupal_set_message(t('ImageAPI Optimize TinyPNG service requires PHP curl library. Please check that php_curl extension is enabled', 'warning', FALSE));
+  }
+
+  // Check if json is available
+  if (!function_exists('json_decode')) {
+    drupal_set_message(t('ImageAPI Optimize TinyPNG service requires PHP json support', 'warning', FALSE));
+  }
+
+  // Prepare the request
+  $filepath = drupal_realpath($dst);
+  $url = 'https://api.tinypng.com/shrink';
+  $settings = variable_get('imageapi_optimize_tinypng');
+
+  $request = curl_init();
+  curl_setopt_array($request, array(
+    CURLOPT_URL => 'https://api.tinypng.com/shrink',
+    CURLOPT_USERPWD => "api:" . $settings['api_key'],
+    CURLOPT_POSTFIELDS => file_get_contents($filepath),
+    CURLOPT_BINARYTRANSFER => TRUE,
+    CURLOPT_RETURNTRANSFER => TRUE,
+    CURLOPT_HEADER => TRUE,
+    /* Uncomment below if you have trouble validating our SSL certificate.
+       Download cacert.pem from: http://curl.haxx.se/ca/cacert.pem */
+    // CURLOPT_CAINFO => __DIR__ . "/cacert.pem",
+    CURLOPT_SSL_VERIFYPEER => TRUE
+  ));
+
+  // Make the request
+  $response = curl_exec($request);
+  $json = json_decode($response, TRUE);
+
+  if (curl_getinfo($request, CURLINFO_HTTP_CODE) === 201) {
+    /* Compression was successful, retrieve output */
+    $result = drupal_http_request($json['output']['url']);
+    if (!isset($result->error)) {
+      if (!file_unmanaged_save_data($result->data, $dst, FILE_EXISTS_REPLACE)) {
+        drupal_set_message(t('Processed image received from TinyPNG.com could not be saved to disk on @dir. Please review the directory permissions'), array('@dir' => $filepath), 'warning');
+        curl_close($request);
+        return FALSE;
+      }
+
+      if ($settings['debug_mode_tinypng']) {
+        drupal_set_message(t('Sucessful request to TinyPNG.com for @file', array('@file' => $dst)), 'status');
+        drupal_set_message(t('Initial file size = @input bytes.<br>Final file size = @output bytes.<br>Compression ratio = @ratio.', array('@input' => $json['input']['size'], '@output' => $json['output']['size'], '@ratio' => $json['output']['ratio'])), 'status');
+      }
+      // Everything went OK
+      curl_close($request);
+      return TRUE;
+    }
+  }
+
+  // Something went wrong :(
+  drupal_set_message(t('TinyPNG.com could not process your rquest for @file. Error code = @error - @msg', array('@file' => $filepath, '@error' => $json['error'], '@msg' => $json['message'])), 'warning');
+  curl_close($request);
+  return FALSE;
+}