nothnk
4/14/2012 - 7:33 AM

Returns the Base64 encoded version of an image. Has basic support for Drupal module ImageCache. Does not depend on Drupal.

Returns the Base64 encoded version of an image. Has basic support for Drupal module ImageCache. Does not depend on Drupal.

<?php
/**
 * @file
 *   Helper class for encoding images as Base64.
 *   Has support for the Drupal module ImageCache, just provide it with your
 *   preset name if you'd like the class to use that version of an image instead.
 *   Is by no means dependent on Drupal though. Just a nice feature.
 *   Feel free to use it as you like.
 *
 * @author Simon Ljungberg <simon@nimnim.se>
 */

/**
 * Error code definitions.
 * Defined outside the class to make them available to the user of the class.
 */
define('B64IMG_FILE_NOT_FOUND_ERROR', 1);
define('B64IMG_FILE_READ_ERROR', 2);
define('B64IMG_IMAGECACHE_PRESET_NOT_FOUND', 4);
define('B64IMG_IMAGECACHE_FAILED', 8);
define('B64IMG_IMAGECACHE_NOT_FOUND', 16);

class Base64Image {

  /**
   * The base64 encoded image string
   * @var string
   * @access private
   */
  private $base64;

  /**
   * Base64 encodes an image and returns the result.
   *
   * Useful when you need to save an image using a JavaScript client etc.
   *
   * @param string $imageFile
   *   Path to the image.
   * @param stirng $imageMIME
   *   Image MIME type.
   * @param string $imageCachePreset
   *   An image cache preset name, optional.
   * @return string $base64Image
   * @throws Exception
   *   Throws an exception if the file cannot be found.
   */
  public function __construct($imageFile, $imageMIME, $imageCachePreset = FALSE) {
    // Make sure the image exists
    if (!file_exists($imageFile)) {
      throw new Exception('File not found: ' . $imageFile, B64IMG_FILE_NOT_FOUND_ERROR);
    }

    // All strings begin with this sequence, that way they can be used
    // directly in an image tag.
    $this->base64 = 'data:' . $imageMIME . ';base64,' . "\r\n";

    // Add the encoded image
    $this->base64 .= ($imageCachePreset) ? $this->encodeImageCache($imageFile, $imageCachePreset) : $this->encodeImage($imageFile);
  }

  /**
   * Encodes an image.
   *
   * @access private
   * @param string $imageFile
   * @return string $encodedFile
   * @throws Exception
   *   Throws an exception is if a read error occur.
   */
  private function encodeImage($file) {
      $imgbinary = fread(fopen($file, 'r'), filesize($file));
      if (!$imgbinary) {
        throw new Exception('Could not read image: ' . $file, B64IMG_FILE_READ_ERROR);
      }
      return chunk_split(base64_encode($imgbinary), 64);
  }

  /**
   * Encode an ImageCache image.
   *
   * @access private
   * @param string $imageFile
   * @param string $imageCachePreset
   * @return string $encodedFile
   * @throws Exception
   *   Throws an exception is if a read error occur.
   */
  private function encodeImageCache($file, $preset) {
    // Make sure we have the module
    if (!function_exists('imagecache_build_derivative')) {
      throw new Exception('ImageCache module does not seem to be installed.', B64IMG_IMAGECACHE_NOT_FOUND);
    }

    // Validate the image preset
    $p = imagecache_preset_by_name($preset);
    if (empty($p)) {
      throw new Exception('No ImageCache preset with name ' . $preset . ' could be found', B64IMG_IMAGECACHE_PRESET_NOT_FOUND);
    }

    // Construct an imagecache path
    $imagepath = imagecache_create_path($preset, $file);

    // Seems like the first time this image is accessed, create it
    if (!file_exists($imageapth)) {
      $builtImage = imagecache_build_derivative($p['actions'], $file, $imagepath);
      if (!$builtImage) {
        throw new Exception('Failed to build ImageCache image.', B64IMG_IMAGECACHE_FAILED);
      }
    }

    // We should now have the image, encode it using our other method
    return $this->encodeImage($imagepath);
  }

  /**
   * Return the string representation of the image.
   */
  public function __toString() {
    return $this->base64;
  }
}