/** * Redirect (mean read from file and output) to CSS-file of current map. * Almost generate header-values. * * @param array $map_cfg map-config array * * @return bool is redirect done */ public static function redirect($map_cfg) { $filename = self::get_valid_css_source($map_cfg, isset($map_cfg['attach'])); if ($filename === false) { return false; } //--------------------------------------------------------------------- $cache_timeout = qpimg_config::get_option('cache_time_expire'); $headers = array(); $headers['Expires'] = gmdate('D, d M Y H:i:s \\G\\M\\T', time() + $cache_timeout); $headers['Last-Modified'] = gmdate('D, d M Y H:i:s \\G\\M\\T', filemtime($filename)); $headers['ETag'] = "\"qpimg-{$map_cfg['id']}-{$map_cfg['hash']}\""; //--------------------------------------------------------------------- $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : false; $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false; if ($if_none_match && $if_none_match == $headers['ETag']) { $headers[':Response-Code'] = 304; $filename = false; } elseif ($if_modified_since && $if_modified_since == $headers['Last-Modified']) { $headers[':Response-Code'] = 304; $filename = false; } else { $headers['Content-Type'] = 'text/css'; $headers['Cache-Control'] = "max-age={$cache_timeout}, public, must-revalidate"; } qpimg_utils::send_headers($headers); if ($filename !== false) { @readfile($filename); } return true; }
/** * Generate css & sprite (image) for single map * * @param array $map_cfg map-config array * * @return bool status */ public static function pack($map_cfg) { //--------------------------------------------------------------------- // PreCheck incoming data if (is_array($map_cfg['objects']) === false) { $map_cfg['objects'] = array(); } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (isset($map_cfg['verbose_check']) === false) { $map_cfg['verbose_check'] = false; } $map_cfg['verbose_check'] = (bool) $map_cfg['verbose_check']; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $map_cfg['save_format'] = strtolower($map_cfg['save_format']); if (in_array($map_cfg['save_format'], array('png', 'gif', 'jpg')) === false) { $map_cfg['save_format'] = 'png'; } //--------------------------------------------------------------------- self::prepare_media_items($map_cfg); if ($map_cfg['objects:dataURI_files_count'] == 0) { // if no dataURI media-items -> then no need proecee MODE_DATAURI_REJECT $process_modes = array(self::MODE_STANDARD); } else { $process_modes = array(self::MODE_STANDARD, self::MODE_DATAURI_REJECT); } foreach ($process_modes as $mode) { switch ($mode) { case self::MODE_STANDARD: $css_filename = qpimg_cache::gen_filename($map_cfg, 'css', qpimg::CSS_FILE_KEY_DEFAULT); $sprite_filename = qpimg_cache::gen_filename($map_cfg, $map_cfg['save_format'], qpimg::SPRITE_FILE_KEY_DEFAULT); $sprite_url = qpimg_cache::gen_filename($map_cfg, $map_cfg['save_format'], qpimg::SPRITE_FILE_KEY_DEFAULT, true); break; case self::MODE_DATAURI_REJECT: $css_filename = qpimg_cache::gen_filename($map_cfg, 'css', qpimg::CSS_FILE_KEY_DATAURI_REJECT); $sprite_filename = qpimg_cache::gen_filename($map_cfg, $map_cfg['save_format'], qpimg::SPRITE_FILE_KEY_DATAURI_REJECT); $sprite_url = qpimg_cache::gen_filename($map_cfg, $map_cfg['save_format'], qpimg::SPRITE_FILE_KEY_DATAURI_REJECT, true); break; } //--------------------------------------------------------------------- // Set positions of each media-item-element for sprite switch ($map_cfg['orientation']) { case 'static': default: $set_position_funcname = 'set_position_static'; $css_bg_repeat_style = 'no-repeat'; break; case 'repeat_x': $set_position_funcname = 'set_position_repeat_x'; $css_bg_repeat_style = 'repeat-x'; break; case 'repeat_y': $set_position_funcname = 'set_position_repeat_y'; $css_bg_repeat_style = 'repeat-y'; break; } list($pos_media_items, $img_width, $img_height) = self::$set_position_funcname($map_cfg, $mode); //--------------------------------------------------------------------- // Save CSS data (by mode) $css_data = array(); if (count($pos_media_items) > 0) { $css_data[':main_sprite']['background-image'] = "url('{$sprite_url}')"; $css_data[':main_sprite']['background-repeat'] = $css_bg_repeat_style; $css_data[':main_sprite'][':css-selector'] = array(); } // Generate crash rules foreach ($map_cfg['objects:items'] as $media_id => $media_item) { if ($media_item->is_crashed() === false) { continue; } $item_css_data = array(); $item_css_data['background-image'] = 'none !important'; $item_css_data['background-color'] = '#800000'; $css_data[qpimg::get_obj_css_selector($map_cfg['id'], $media_id, $map_cfg)] = $item_css_data; } // Generate items data foreach ($pos_media_items as $media_id => $media_item) { $item_css_data = array(); $item_css_data['background-position'] = -($media_item->get('left') + $media_item->get('space-left')) . "px " . -($media_item->get('top') + $media_item->get('space-top')) . "px"; self::prepare_item_css($item_css_data, $media_item); $css_data[':main_sprite'][':css-selector'] = array_merge($css_data[':main_sprite'][':css-selector'], $item_css_data[':css-selector']); $css_data[qpimg::get_obj_css_selector($map_cfg['id'], $media_id, $map_cfg)] = $item_css_data; } unset($item_css_data); // Generate data:URI content (for MODE_STANDARD) if ($mode == self::MODE_STANDARD) { if (is_array($map_cfg['objects:items']) === true) { foreach ($map_cfg['objects:items'] as $media_id => $media_item) { if ($media_item->is_crashed() === true) { continue; } if ($media_item->get('data:URI') === false) { continue; } $item_css_data = array(); self::prepare_item_css($item_css_data, $media_item); switch ($media_item->get('imagetype')) { case IMAGETYPE_GIF: $mimetype = 'image/gif'; break; case IMAGETYPE_JPEG: $mimetype = 'image/jpeg'; break; case IMAGETYPE_PNG: $mimetype = 'image/png'; break; } $item_css_data['background-image'] = "url(" . "data:{$mimetype};" . "base64," . base64_encode(@file_get_contents($media_item->get('source'))) . ")"; $css_data[qpimg::get_obj_css_selector($map_cfg['id'], $media_id, $map_cfg)] = $item_css_data; } } } $css_hf = @fopen($css_filename, 'w'); if (is_resource($css_hf) === false) { self::drop_temporary_media(); return false; } ksort($css_data); foreach ($css_data as $css_selector => $item_css_data) { if ($css_selector == ':main_sprite') { $css_selector = qpimg::get_map_css_selector($map_cfg['id'], $map_cfg); } fwrite($css_hf, ".{$css_selector}"); if (is_array($item_css_data[':css-selector']) === true) { foreach ($item_css_data[':css-selector'] as $sub_css_selector) { $sub_css_selector = trim($sub_css_selector); if ($sub_css_selector == '') { continue; } fwrite($css_hf, ", {$sub_css_selector}"); } } fwrite($css_hf, " { "); foreach ($item_css_data as $css_attr_key => $css_attr_value) { if ($css_attr_key[0] == ':') { continue; } fwrite($css_hf, "{$css_attr_key}: {$css_attr_value}; "); } fwrite($css_hf, "}\n"); } fclose($css_hf); //--------------------------------------------------------------------- // Make SPRITE (image) if (count($pos_media_items) > 0) { $sprite_img = @imagecreatetruecolor($img_width, $img_height); if (is_resource($sprite_img) === false) { self::drop_temporary_media(); return false; } imagealphablending($sprite_img, false); imagesavealpha($sprite_img, true); if (isset($map_cfg['bgcolor']) === true && $map_cfg['bgcolor']) { list($color_r, $color_g, $color_b) = qpimg_utils::color2rgb($map_cfg['bgcolor']); imagefill($sprite_img, 0, 0, imagecolorallocate($sprite_img, $color_r, $color_g, $color_b)); unset($color_r, $color_g, $color_b); } else { imagefill($sprite_img, 0, 0, imagecolorallocatealpha($sprite_img, 0, 0, 0, 127)); } //--------------------------------------------------------------------- if (isset($map_cfg['transparent_color']) === true) { list($color_r, $color_g, $color_b) = qpimg_utils::color2rgb($map_cfg['transparent_color']); imagecolortransparent($sprite_img, imagecolorallocate($sprite_img, $color_r, $color_g, $color_b)); unset($color_r, $color_g, $color_b); } //--------------------------------------------------------------------- // Copy images in sprite & save css attributes for each element foreach ($pos_media_items as $media_id => $media_item) { $safe_image_source = self::parse_media_source($media_item->get('source'), $map_cfg['id']); if ($safe_image_source === false) { continue; } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - switch ($media_item->get('imagetype')) { case IMAGETYPE_GIF: $tmp_img = @imagecreatefromgif($safe_image_source); break; case IMAGETYPE_JPEG: $tmp_img = @imagecreatefromjpeg($safe_image_source); break; case IMAGETYPE_PNG: $tmp_img = @imagecreatefrompng($safe_image_source); break; } if (is_resource($tmp_img) === false) { continue; } $src_x = 0; $src_y = 0; $src_w = $media_item->get('etalon-width'); $src_h = $media_item->get('etalon-height'); $dst_x = $media_item->get('left') + $media_item->get('space-left'); $dst_y = $media_item->get('top') + $media_item->get('space-top'); $dst_w = $media_item->get('scale-width'); $dst_h = $media_item->get('scale-height'); if ($media_item->get('bgcolor') !== false) { list($color_r, $color_g, $color_b) = qpimg_utils::color2rgb($media_item->get('bgcolor')); imagefilledrectangle($sprite_img, $media_item->get('left'), $media_item->get('top'), $media_item->get('left') + $media_item->get('full-width') - 1, $media_item->get('top') + $media_item->get('full-height') - 1, imagecolorallocate($sprite_img, $color_r, $color_g, $color_b)); unset($color_r, $color_g, $color_b); } if ($src_w == $dst_w && $src_h == $dst_h) { imagecopy($sprite_img, $tmp_img, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h); } else { if ($media_item->get('scale-method') == 'resize') { imagecopyresized($sprite_img, $tmp_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); } elseif ($media_item->get('scale-method') == 'resample') { imagecopyresampled($sprite_img, $tmp_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h); } elseif ($media_item->get('scale-method') == 'mosaic') { $mosaic_y = $dst_y; $mosaic_h = $dst_h; do { $mosaic_x = $dst_x; $mosaic_w = $dst_w; do { imagecopy($sprite_img, $tmp_img, $mosaic_x, $mosaic_y, 0, 0, min($mosaic_w, $src_w), min($mosaic_h, $src_h)); $mosaic_x += $src_w; $mosaic_w -= $src_w; } while ($mosaic_w > 0); $mosaic_y += $src_h; $mosaic_h -= $src_h; } while ($mosaic_h > 0); unset($mosaic_x, $mosaic_y, $mosaic_w, $mosaic_h); } else { qpimg_logger::write("QPIMG_WARNING: Undefined scale-method: " . $media_item->get('scale-method'), __FILE__, __LINE__); continue; } } unset($src_x, $src_y, $src_w, $src_h); unset($dst_x, $dst_y, $dst_w, $dst_h); imagedestroy($tmp_img); } //--------------------------------------------------------------------- // Save image-data switch ($map_cfg['save_format']) { case 'png': if (isset($map_cfg['save_quality']) === false) { $map_cfg['save_quality'] = 9; } $save_result = @imagepng($sprite_img, $sprite_filename, min(max($map_cfg['save_quality'], 0), 9)); break; case 'gif': $save_result = @imagegif($sprite_img, $sprite_filename); break; case 'jpg': if (isset($map_cfg['save_quality']) === false) { $map_cfg['save_quality'] = 95; } $save_result = @imagejpeg($sprite_img, $sprite_filename, min(max($map_cfg['save_quality'], 0), 100)); break; } if ($save_result === false) { qpimg_logger::write("QPIMG_ERROR: Failed on save result sprite '{$sprite_filename}'", __FILE__, __LINE__); } imagedestroy($sprite_img); } } //--------------------------------------------------------------------- // Save crc-hash [if set verbose_check mode] if ($map_cfg['verbose_check'] === true) { @file_put_contents(qpimg_cache::gen_filename($map_cfg, 'crc'), $map_cfg['hash'] . ':' . qpimg_cache::get_media_hash($map_cfg)); } self::drop_temporary_media(); return true; }