diff --git a/includes/mapProviderGoogle.php b/includes/mapProviderGoogle.php
index 84024b9..e23d231 100644
--- a/includes/mapProviderGoogle.php
+++ b/includes/mapProviderGoogle.php
@@ -3,55 +3,308 @@
 class mapProviderGoogle extends mapProviderBase {
   public $api_uri = 'http://maps.google.com/maps/api/staticmap?';
 
-  public function build_params(&$items, &$settings) {    
+  /**
+   * Build the query string for the static map url.
+   *
+   * @param $items
+   *   An array of the marker locations.
+   * @param $settings
+   *   An array of field display settings.
+   *
+   * @return
+   *   The query string.
+   */
+  public function build_params(&$items, &$settings) {
+    $preset_data = $this->_preset_form_defaults($settings['preset']);
+    
     $parameters = array(
-      'size' => $settings['preset']['mapsize'],
-      'maptype' => $settings['preset']['maptype'],
-      'markers' => implode('|', $items),
+      'size' => $preset_data['mapsize'],
+      'maptype' => $preset_data['maptype'],
+      'format' => $preset_data['format'],
+      'scale' => $preset_data['scale'],
+      'markers' => $this->generate_marker_query($items, $preset_data),
       'sensor' => 'false',
+      'zoom' => $preset_data['zoom'],
     );
-    
+
+    // Add the google premier ID if it has been set.
     $premier_id = variable_get('staticmap_google_premier', '');
     if ($premier_id) {
       $parameters['client'] = $premier_id;
     }
 
-    return $parameters;
+    // Generate the query string.
+    $query_string =  http_build_query($parameters);
+
+    // Add map styles if they have been set.
+    // These have to be done like this because multiple styles use a duplicate
+    // 'style' params and if we send an array to http_build_query() we get a
+    // single array parameter, which won't work.
+    if ($styles = $this->parse_styles($preset_data['style'])) {
+      foreach ($styles as $style) {
+        $query_string .= '&style=' . urlencode($style);
+      }
+    }
+
+    return $query_string;
   }
-  
+
   public function preset_form_alter(&$form, &$form_state, $preset_data) {
+    return $this->_preset_form_elements($preset_data);
+  }
+  
+  private function _preset_form_defaults($preset_data = array()) {
+    return
+      $preset_data +
+      array(
+        'maptype' => '',
+        'zoom' => 'auto',
+        'marker_type' => 'normal',
+        'marker_size' => 'normal',
+        'marker_color' => 'red',
+        'marker_color_custom' => '',
+        'marker_icon_path' => '',
+        'marker_icon_shadow' => TRUE,
+        'style' => '',
+        'scale' => '1',
+        'format' => 'png',
+      );
+  }
+  
+  private function _preset_form_elements($preset_data) {
     $elements = array();
-    
+    $preset_data = $this->_preset_form_defaults($preset_data);
+
     $elements['maptype'] = array(
       '#type' => 'select',
       '#title' => t('Map Type'),
-      '#default_value' => (!empty($preset_data['maptype'])) ? $preset_data['maptype'] : '',
-      '#options' => $this->_maptypes(),
+      '#default_value' => $preset_data['maptype'],
+      '#options' => array(
+        'roadmap' => t('Roadmap'),
+        'satellite' => t('Satellite'),
+        'hybrid' => t('Hybrid'),
+        'terrain' => t('Terrain'),
+      ),
     );
     
+    $options = array('auto' => t('Auto')) + range(0, 21);
+    $elements['zoom'] = array(
+      '#type' => 'select',
+      '#title' => t('Zoom level'),
+      '#default_value' => $preset_data['zoom'],
+      '#options' => $options,
+      '#description' => t('Select to zoom level for your maps. Auto means the zoom level will be automatically calculated to fit any markers displaying on the map. Note that available zoom levels depend on location.'),
+    );
+
+    $elements['markers'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Markers'),
+    );
+    $elements['markers']['marker_type'] = array(
+      '#type' => 'select',
+      '#title' => t('Marker type'),
+      '#default_value' => $preset_data['marker_type'],
+      '#options' => array(
+        'normal' => t('Normal'),
+        'custom' => t('Custom'),
+      ),
+      '#description' => t('Choose whether to use normal google markers, or your own custom images.'),
+    );
+
+    $elements['markers']['marker_size'] = array(
+      '#type' => 'select',
+      '#title' => t('Marker size'),
+      '#default_value' => $preset_data['marker_size'],
+      '#options' => array(
+        'tiny' => t('Tiny'),
+        'small' => t('Small'),
+        'mid' => t('Mid'),
+        'normal' => t('Normal'),
+      ),
+      '#states' => array(
+        // Only show the setting when the normal marker type is selected.
+        'visible' => array(
+          ':input[name="marker_type"]' => array('value' => 'normal'),
+        ),
+      ),
+    );
+    $elements['markers']['marker_color'] = array(
+      '#type' => 'select',
+      '#title' => t('Marker color'),
+      '#default_value' => $preset_data['marker_color'],
+      '#options' => array(
+        'black' => t('Black'),
+        'brown' => t('Brown'),
+        'green' => t('Green'),
+        'purple' => t('Purple'),
+        'yellow' => t('Yellow'),
+        'blue' => t('Blue'),
+        'gray' => t('Gray'),
+        'orange' => t('Orange'),
+        'red' => t('Red'),
+        'white' => t('White'),
+        'custom' => t('Custom'),
+      ),
+      '#description' => t("Select the color for the markers, or choose Custom to specify a color that isn't listed. The default is red."),
+      '#states' => array(
+        // Only show the setting when the normal marker type is selected.
+        'visible' => array(
+          ':input[name="marker_type"]' => array('value' => 'normal'),
+        ),
+      ),
+    );
+    $elements['markers']['marker_color_custom'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Custom color'),
+      '#default_value' => $preset_data['marker_color_custom'],
+      '#description' => t('If you have selected "Custom" as the marker color, the color specified here will be used for the marker color.') . '<br />' .
+                        t('The color must be a hex value without the preceeding hash. For example FF0000 for red.'),
+      '#states' => array(
+        // Only show the setting when the normal marker type and custom marker
+        // color options are selected.
+        'visible' => array(
+          ':input[name="marker_type"]' => array('value' => 'normal'),
+          ':input[name="marker_color"]' => array('value' => 'custom'),
+        ),
+      ),
+    );
+
+    $elements['markers']['marker_icon_path'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Custom marker icon path'),
+      '#default_value' => $preset_data['marker_icon_path'],
+      '#description' => t("The URL of the image to use as the marker's custom icon (including the http:// part). Images may be in PNG, JPEG or GIF formats, though PNG is recommended. Icons are limited to sizes of 4096 pixels (64x64 for square images).") . '<br />' .
+                        t("Custom icons that have a shadow enabled (the default) will have their 'anchor point' set as the bottom center of the provided icon image, from which the shadow is cast. Icons without a shadow are instead assumed to be icons centered on their specified locations, so their anchor points are set as the center of the image."),
+      '#states' => array(
+        // Only show the setting when the custom marker type is selected.
+        'visible' => array(
+          ':input[name="marker_type"]' => array('value' => 'custom'),
+        ),
+      ),
+    );
+    $elements['markers']['marker_icon_shadow'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Custom marker icon shadow'),
+      '#default_value' => $preset_data['marker_icon_shadow'],
+      '#description' => t("Indicates that the Static Maps service should construct an appropriate shadow for the custom marker image. This shadow is based on the image's visible region and its opacity/transparency. Default is on."),
+      '#states' => array(
+        // Only show the setting when the custom marker type is selected.
+        'visible' => array(
+          ':input[name="marker_type"]' => array('value' => 'custom'),
+        ),
+      ),
+    );
+
+    $elements['style'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Map Styles'),
+      '#default_value' => $preset_data['style'],
+      '#description' => t('Enter custom style parameters, one per line.') . '<br />' .
+                        t('For example, %style will change the color of all highway roads (geometry only, not labels) to be pink.', array('%style' => 'feature:road.highway|element:geometry|lightness:35|hue:0xff00ee|saturation:29')) . '<br />' .
+                        t('For more information see the <a href="@url">documentation</a>', array('@url' => url('http://code.google.com/apis/maps/documentation/staticmaps/#StyledMaps'))) . '<br />' .
+                        t('There is a map style wizard that allows easy creation of map styles <a href="@url">here</a>', array('@url' => url('http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html'))) . '<br />' .
+                        t('Styles have no affect on the satellite map type and limited affect on the hybrid map type.'),
+    );
+
+    $elements['scale'] = array(
+      '#type' => 'select',
+      '#title' => t('Scale'),
+      '#default_value' => $preset_data['scale'],
+      '#options' => array(
+        1 => t('1'),
+        2 => t('2'),
+        4 => t('4'),
+      ),
+      '#description' => t("Affects the number of pixels that are returned. scale = 2 returns twice as many pixels as scale = 1 while retaining the same coverage area and level of detail (i.e. the contents of the map don't change). This is useful when developing for high-resolution displays, or when generating a map for printing. The default value is 1. 4 is only available to Maps API for Business customers."),
+    );
+
+    $elements['format'] = array(
+      '#type' => 'select',
+      '#title' => t('Format'),
+      '#default_value' => $preset_data['format'],
+      '#options' => array(
+        'png' => t('8-bit PNG format'),
+        'png32' => t('32-bit PNG format'),
+        'gif' => t('GIF format'),
+        'jpg' => t('JPEG compression format'),
+        'jpg-baseline' => t('non-progressive (baseline) JPEG compression format'),
+      ),
+      '#description' => t("Select the image format of the static map. The default is 8-bit PNG."),
+    );
+
     return $elements;
   }
   
   public function field_formatter_settings_summary($field, $instance, $view_mode, $preset_data) {
-    $maptypes = $this->_maptypes();
+    $preset_data = $this->_preset_form_defaults($preset_data);
+    $preset_form = $this->_preset_form_elements($preset_data);
+    
+    $options = $preset_form['maptype']['#options'];
+    $maptype = in_array($preset_data['maptype'], array_keys($options)) ? $options[$preset_data['maptype']] : '';
+    
+    $options = $preset_form['zoom']['#options'];
+    $zoom = in_array($preset_data['zoom'], array_keys($options)) ? $options[$preset_data['zoom']] : '';
+    
+    $options = $preset_form['format']['#options'];
+    $format = in_array($preset_data['format'], array_keys($options)) ? $options[$preset_data['format']] : '';
     
     return t(
-      'Map Style: @maptype',
+      'Map Style: %maptype<br>Zoom Level: %zoom<br>Format: %format',
       array(
-        '@maptype' => !empty($maptypes[$preset_data['maptype']]) ? $maptypes[$preset_data['maptype']] : '',
+        '%maptype' => $maptype,
+        '%zoom' => $zoom,
+        '%format' => $format,
       )
     );
   }
 
-
   
-  private function _maptypes() {
-    return
-      array(
-        'roadmap' => t('Roadmap'),
-        'satellite' => t('Satellite'),
-        'hybrid' => t('Hybrid'),
-        'terrain' => t('Terrain'),
-      );
+  /**
+   * Parse the styles string into useable query parameters.
+   *
+   * @param $style_string
+   *   A new line delimited string of styles to apply to the map.
+   *
+   * @return
+   *   A string of styles for the styles parameter.
+   */
+  private function parse_styles($style_string = '') {
+    return preg_split('/$\R?^/m', $style_string);
+  }
+
+  /**
+   * Generate the query string for the markers parameter.
+   *
+   * @param $items
+   *   An array of the marker locations.
+   * @param $preset
+   *   The static map preset being used.
+   *
+   * @return
+   *   A query string for the markers parameter.
+   */
+  private function generate_marker_query($items, $preset) {
+    $markers = '';
+    if ($preset['marker_type'] == 'normal') {
+      if ($preset['marker_size'] != 'normal') {
+        $markers .= 'size:' . $preset['marker_size'] . '|';
+      }
+      if ($preset['marker_color'] == 'custom') {
+        if (!empty($preset['marker_color_custom'])) {
+          $markers .= 'color:0x' . $preset['marker_color_custom'] . '|';
+        }
+      }
+      else {
+        $markers .= 'color:' . $preset['marker_color'] . '|';
+      }
+    }
+    else if (!empty($preset['marker_icon_path'])) {
+      $markers .= 'icon:' . $preset['marker_icon_path'] . '|';
+      if (!$preset['marker_icon_shadow']) {
+        $markers .= 'shadow:false|';
+      }
+    }
+    $markers .= implode('|', $items);
+    return $markers;
   }
 }
\ No newline at end of file
diff --git a/includes/mapProviderOpenStreetMap.php b/includes/mapProviderOpenStreetMap.php
index 988a147..b2b998d 100644
--- a/includes/mapProviderOpenStreetMap.php
+++ b/includes/mapProviderOpenStreetMap.php
@@ -3,6 +3,17 @@
 class mapProviderOpenStreetMap extends mapProviderBase {
   public $api_uri = 'http://ojw.dev.openstreetmap.org/StaticMap/?';
 
+  /**
+   * Build the query string for the static map url.
+   *
+   * @param $items
+   *   An array of the marker locations.
+   * @param $settings
+   *   An array of field display settings.
+   *
+   * @return
+   *   The query string.
+   */
   public function build_params(&$items, &$settings) {    
     $parameters = array(
       'show' => 1,
@@ -23,7 +34,8 @@ class mapProviderOpenStreetMap extends mapProviderBase {
       }
     }
 
-    return $parameters;
+    // Generate the query string.
+    return http_build_query($parameters);
   }
   
   public function preset_form_alter(&$form, &$form_state, $preset_data) {
diff --git a/staticmap.module b/staticmap.module
index d422b28..24311ff 100644
--- a/staticmap.module
+++ b/staticmap.module
@@ -161,9 +161,12 @@ function staticmap_field_formatter_view($entity_type, $entity, $field, $instance
       if ($provider) {
         $geodata = $field_processor->provide_geodata($items, $settings);
         $parameters = $provider->build_params($geodata, $settings);
+        if (is_array($parameters)) {
+          $parameters = http_build_query($parameters);
+        }
 
         $element[0] = array(
-          '#markup' => theme('staticmap_map', array('path' => $provider->api_uri . http_build_query($parameters))),
+          '#markup' => theme('staticmap_map', array('path' => $provider->api_uri . $parameters)),
         );
       }
       else {
@@ -230,11 +233,11 @@ function staticmap_field_formatter_settings_summary($field, $instance, $view_mod
   }
   
   return t(
-    'Map preset: @preset<br>Map Size: @map_size<br>@provider_summary',
+    'Map preset: %preset<br>Map Size: %map_size<br>!provider_summary',
     array(
-      '@preset' => $preset->title,
-      '@map_size' => $preset_data['mapsize'],
-      '@provider_summary' => $provider_summary
+      '%preset' => $preset->title,
+      '%map_size' => $preset_data['mapsize'],
+      '!provider_summary' => $provider_summary
     )
   );
 }
