mirror of https://github.com/SixLabors/ImageSharp
14 changed files with 988 additions and 134 deletions
@ -0,0 +1,66 @@ |
|||||
|
// -----------------------------------------------------------------------
|
||||
|
// <copyright file="CachedImage.cs" company="James South">
|
||||
|
// Copyright (c) James South.
|
||||
|
// Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
|
// </copyright>
|
||||
|
// -----------------------------------------------------------------------
|
||||
|
|
||||
|
namespace ImageProcessor.Web.Caching |
||||
|
{ |
||||
|
#region Using
|
||||
|
using System; |
||||
|
#endregion
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Describes a cached image
|
||||
|
/// </summary>
|
||||
|
public class CachedImage |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="CachedImage"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="value">
|
||||
|
/// The value of the cached item.
|
||||
|
/// </param>
|
||||
|
/// <param name="lastWriteTimeUtc">
|
||||
|
/// The last write time of the cached item.
|
||||
|
/// </param>
|
||||
|
public CachedImage(string value, DateTime lastWriteTimeUtc) |
||||
|
{ |
||||
|
this.Value = value; |
||||
|
this.LastWriteTimeUtc = lastWriteTimeUtc; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value date time delimiter.
|
||||
|
/// </summary>
|
||||
|
public static string ValueLastWriteTimeDelimiter |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return "|*|"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the value of the cached item
|
||||
|
/// </summary>
|
||||
|
public string Value { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the last write time of the cached item
|
||||
|
/// </summary>
|
||||
|
public DateTime LastWriteTimeUtc { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The value and last write time as a string.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="string"/>.
|
||||
|
/// </returns>
|
||||
|
public string ValueAndLastWriteTimeUtcToString() |
||||
|
{ |
||||
|
return string.Format("{0}{1}{2}", this.Value, ValueLastWriteTimeDelimiter, this.LastWriteTimeUtc); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,321 @@ |
|||||
|
// -----------------------------------------------------------------------
|
||||
|
// <copyright file="LockedDictionary.cs" company="James South">
|
||||
|
// Copyright (c) James South.
|
||||
|
// Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
|
// </copyright>
|
||||
|
// -----------------------------------------------------------------------
|
||||
|
|
||||
|
namespace ImageProcessor.Web.Caching |
||||
|
{ |
||||
|
#region Using
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
#endregion
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Represents a collection of keys and values that are thread safe.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TKey">
|
||||
|
/// The type of the keys in the dictionary.
|
||||
|
/// </typeparam>
|
||||
|
/// <typeparam name="TVal">
|
||||
|
/// The type of the values in the dictionary.
|
||||
|
/// </typeparam>
|
||||
|
public class LockedDictionary<TKey, TVal> : IDictionary<TKey, TVal> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The _inner.
|
||||
|
/// </summary>
|
||||
|
private readonly Dictionary<TKey, TVal> innerDictionary = new Dictionary<TKey, TVal>(); |
||||
|
|
||||
|
#region Constructors
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="LockedDictionary{TKey,TVal}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="val">
|
||||
|
/// The value to initialize the LockedDictionary with.
|
||||
|
/// </param>
|
||||
|
public LockedDictionary(IDictionary<TKey, TVal> val = null) |
||||
|
{ |
||||
|
if (val != null) |
||||
|
{ |
||||
|
this.innerDictionary = val.ToDictionary(x => x.Key, x => x.Value); |
||||
|
} |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region Properties
|
||||
|
/// <summary>
|
||||
|
/// Gets a collection containing the keys in the <see cref="LockedDictionary{TKey,TVal}"/>.
|
||||
|
/// </summary>
|
||||
|
public ICollection<TKey> Keys |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
return this.innerDictionary.Keys.ToArray(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a collection containing the values in the <see cref="LockedDictionary{TKey,TVal}"/>.
|
||||
|
/// </summary>
|
||||
|
public ICollection<TVal> Values |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
return this.innerDictionary.Values.ToArray(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the number of key/value pairs contained in the <see cref="LockedDictionary{TKey,TVal}"/>.
|
||||
|
/// </summary>
|
||||
|
public int Count |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
return this.innerDictionary.Count; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets a value indicating whether the <see cref="LockedDictionary{TKey,TVal}"/> is read only.
|
||||
|
/// </summary>
|
||||
|
public bool IsReadOnly |
||||
|
{ |
||||
|
get { return false; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the value associated with the specified key.
|
||||
|
/// </summary>
|
||||
|
/// <param name="key">
|
||||
|
/// The key of the value to get or set.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// TThe value associated with the specified key. If the specified key is not found,
|
||||
|
/// a get operation throws a <see cref="T:System.Collections.Generic.KeyNotFoundException"/> ,
|
||||
|
/// and a set operation creates a new element with the specified key.
|
||||
|
/// </returns>
|
||||
|
public TVal this[TKey key] |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
return this.innerDictionary[key]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
set |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
this.innerDictionary[key] = value; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region Methods
|
||||
|
/// <summary>
|
||||
|
/// Adds the specified key and value to the dictionary.
|
||||
|
/// </summary>
|
||||
|
/// <param name="key">
|
||||
|
/// The key of the element to add.
|
||||
|
/// </param>
|
||||
|
/// <param name="value">
|
||||
|
/// The value of the element to add. The value can be null for reference types.
|
||||
|
/// </param>
|
||||
|
public void Add(TKey key, TVal value) |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
this.innerDictionary.Add(key, value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Determines whether the LockedDictionary contains the specified key.
|
||||
|
/// </summary>
|
||||
|
/// <param name="key">
|
||||
|
/// The key to locate in the LockedDictionary.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// true if the LockedDictionary contains the key; otherwise, false.
|
||||
|
/// </returns>
|
||||
|
public bool ContainsKey(TKey key) |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
return this.innerDictionary.ContainsKey(key); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Removes the value with the specified key from the <see cref="LockedDictionary{TKey,TVal}"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="key">
|
||||
|
/// The key of the element to remove.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// true if the element is successfully found and removed; otherwise, false.
|
||||
|
/// This method returns false if key is not found in the <see cref="LockedDictionary{TKey,TVal}"/>.
|
||||
|
/// </returns>
|
||||
|
public bool Remove(TKey key) |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
return this.innerDictionary.Remove(key); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value associated with the specified key.
|
||||
|
/// </summary>
|
||||
|
/// <param name="key">
|
||||
|
/// The key of the value to get.
|
||||
|
/// </param>
|
||||
|
/// <param name="value">
|
||||
|
/// When this method returns, contains the value associated with the specified key, if the key is found;
|
||||
|
/// otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// true if the <see cref="LockedDictionary{TKey,TVal}"/> contains an element with
|
||||
|
/// the specified key; otherwise, false.
|
||||
|
/// </returns>
|
||||
|
public bool TryGetValue(TKey key, out TVal value) |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
return this.innerDictionary.TryGetValue(key, out value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds the specified key and value to the dictionary.
|
||||
|
/// </summary>
|
||||
|
/// <param name="item">
|
||||
|
/// The <see cref="System.Collections.Generic.KeyValuePair{TKey, TVal}"/> representing
|
||||
|
/// the item to add.
|
||||
|
/// </param>
|
||||
|
public void Add(KeyValuePair<TKey, TVal> item) |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
this.innerDictionary.Add(item.Key, item.Value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Removes all keys and values from the <see cref="LockedDictionary{TKey,TVal}"/>.
|
||||
|
/// </summary>
|
||||
|
public void Clear() |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
this.innerDictionary.Clear(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Determines whether the <see cref="LockedDictionary{TKey,TVal}"/> contains the specified key.
|
||||
|
/// </summary>
|
||||
|
/// <param name="item">
|
||||
|
/// The <see cref="System.Collections.Generic.KeyValuePair{TKey, TVal}"/> representing
|
||||
|
/// the item to locate.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// true if the <see cref="LockedDictionary{TKey,TVal}"/> contains an element
|
||||
|
/// with the specified key; otherwise, false.
|
||||
|
/// </returns>
|
||||
|
public bool Contains(KeyValuePair<TKey, TVal> item) |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
var inner = this.innerDictionary as IDictionary<TKey, TVal>; |
||||
|
return inner.Contains(item); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Copies the elements of an <see cref="LockedDictionary{TKey,TVal}"/> to a one-dimensional
|
||||
|
/// <see cref="T:System.Array"/> starting at a particular <see cref="T:System.Array"/> index.
|
||||
|
/// </summary>
|
||||
|
/// <param name="array">
|
||||
|
/// The one-dimensional <see cref="T:System.Array"/> that is the destination of the elements copied
|
||||
|
/// from <see cref="LockedDictionary{TKey,TVal}"/>.KeyCollection.
|
||||
|
/// The <see cref="T:System.Array"/> must have zero-based indexing.
|
||||
|
/// </param>
|
||||
|
/// <param name="arrayIndex">
|
||||
|
/// The zero-based index in array at which copying begins.
|
||||
|
/// </param>
|
||||
|
public void CopyTo(KeyValuePair<TKey, TVal>[] array, int arrayIndex) |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
var inner = this.innerDictionary as IDictionary<TKey, TVal>; |
||||
|
inner.CopyTo(array, arrayIndex); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Removes the item with the specified <see cref="System.Collections.Generic.KeyValuePair{TKey, TVal}"/>
|
||||
|
/// from the <see cref="LockedDictionary{TKey,TVal}"/>
|
||||
|
/// </summary>
|
||||
|
/// <param name="item">
|
||||
|
/// The <see cref="System.Collections.Generic.KeyValuePair{TKey, TVal}"/>representing the item to remove.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// This method returns false if item is not found in the <see cref="LockedDictionary{TKey,TVal}"/>.
|
||||
|
/// </returns>
|
||||
|
public bool Remove(KeyValuePair<TKey, TVal> item) |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
var inner = this.innerDictionary as IDictionary<TKey, TVal>; |
||||
|
return inner.Remove(item); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns an enumerator that iterates through the <see cref="LockedDictionary{TKey,TVal}"/>.KeyCollection.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// A <see cref="System.Collections.Generic.Dictionary{TKey,TValue}.KeyCollection.Enumerator"/>
|
||||
|
/// for the <see cref="System.Collections.Generic.Dictionary{TKey,TValue}.KeyCollection"/>.
|
||||
|
/// </returns>
|
||||
|
public IEnumerator<KeyValuePair<TKey, TVal>> GetEnumerator() |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
return this.innerDictionary.ToList().GetEnumerator(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns an enumerator that iterates through the <see cref="LockedDictionary{TKey,TVal}"/>.KeyCollection.
|
||||
|
/// </summary>
|
||||
|
/// <returns>
|
||||
|
/// A <see cref="System.Collections.Generic.Dictionary{TKey,TValue}.Enumerator"/>
|
||||
|
/// for the <see cref="System.Collections.Generic.Dictionary{TKey,TValue}"/>.
|
||||
|
/// </returns>
|
||||
|
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() |
||||
|
{ |
||||
|
lock (this.innerDictionary) |
||||
|
{ |
||||
|
return this.innerDictionary.ToArray().GetEnumerator(); |
||||
|
} |
||||
|
} |
||||
|
#endregion
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,193 @@ |
|||||
|
// -----------------------------------------------------------------------
|
||||
|
// <copyright file="PersistantDictionary.cs" company="James South">
|
||||
|
// Copyright (c) James South.
|
||||
|
// Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
|
// </copyright>
|
||||
|
// -----------------------------------------------------------------------
|
||||
|
|
||||
|
namespace ImageProcessor.Web.Caching |
||||
|
{ |
||||
|
#region Using
|
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Web.Hosting; |
||||
|
using ImageProcessor.Web.Config; |
||||
|
#endregion
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Represents a collection of keys and values whose operations are concurrent.
|
||||
|
/// </summary>
|
||||
|
public class PersistantDictionary : LockedDictionary<string, CachedImage> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A new instance Initializes a new instance of the <see cref="T:ImageProcessor.Web.Caching.PersistantDictionary"/> class.
|
||||
|
/// initialized lazily.
|
||||
|
/// </summary>
|
||||
|
private static readonly Lazy<PersistantDictionary> Lazy = |
||||
|
new Lazy<PersistantDictionary>(() => new PersistantDictionary()); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The default path for cached folders on the server.
|
||||
|
/// </summary>
|
||||
|
private static readonly string CachePath = ImageProcessorConfig.Instance.VirtualCachePath; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The object to lock against.
|
||||
|
/// </summary>
|
||||
|
private static readonly object SyncRoot = new object(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The cached index location.
|
||||
|
/// </summary>
|
||||
|
private readonly string cachedIndexFile = Path.Combine(HostingEnvironment.MapPath(CachePath), "imagecache.bin"); |
||||
|
|
||||
|
#region Constructors
|
||||
|
/// <summary>
|
||||
|
/// Prevents a default instance of the <see cref="T:ImageProcessor.Web.Caching.PersistantDictionary"/> class
|
||||
|
/// from being created.
|
||||
|
/// </summary>
|
||||
|
private PersistantDictionary() |
||||
|
{ |
||||
|
this.LoadCache(); |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the current instance of the <see cref="T:ImageProcessor.Web.Caching.PersistantDictionary"/> class.
|
||||
|
/// </summary>
|
||||
|
public static PersistantDictionary Instance |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
return Lazy.Value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#region Public
|
||||
|
/// <summary>
|
||||
|
/// Tries to remove the value associated with the specified key.
|
||||
|
/// </summary>
|
||||
|
/// <param name="key">
|
||||
|
/// The key of the item to remove.
|
||||
|
/// </param>
|
||||
|
/// <param name="value">
|
||||
|
/// The value to assign the returned value to.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// true if the <see cref="PersistantDictionary"/> removes an element with
|
||||
|
/// the specified key; otherwise, false.
|
||||
|
/// </returns>
|
||||
|
public bool TryRemove(string key, out CachedImage value) |
||||
|
{ |
||||
|
// No CachedImage to remove.
|
||||
|
if (!this.ContainsKey(key)) |
||||
|
{ |
||||
|
value = default(CachedImage); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// Remove the CachedImage.
|
||||
|
lock (SyncRoot) |
||||
|
{ |
||||
|
value = this[key]; |
||||
|
this.Remove(key); |
||||
|
|
||||
|
this.SaveCache(); |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds the specified key and value to the dictionary or returns the value if it exists.
|
||||
|
/// </summary>
|
||||
|
/// <param name="key">
|
||||
|
/// The key.
|
||||
|
/// </param>
|
||||
|
/// <param name="factory">
|
||||
|
/// The delegate method that returns the value.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The value of the item to add or get.
|
||||
|
/// </returns>
|
||||
|
public CachedImage GetOrAdd(string key, Func<string, CachedImage> factory) |
||||
|
{ |
||||
|
// Get the CachedImage.
|
||||
|
if (this.ContainsKey(key)) |
||||
|
{ |
||||
|
return this[key]; |
||||
|
} |
||||
|
|
||||
|
lock (SyncRoot) |
||||
|
{ |
||||
|
// Add the CachedImage.
|
||||
|
CachedImage ret = factory(key); |
||||
|
this[key] = ret; |
||||
|
|
||||
|
this.SaveCache(); |
||||
|
|
||||
|
return ret; |
||||
|
} |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Saves the in memory cache to the file-system.
|
||||
|
/// </summary>
|
||||
|
private void SaveCache() |
||||
|
{ |
||||
|
using (FileStream fileStream = File.Create(this.cachedIndexFile)) |
||||
|
{ |
||||
|
using (BinaryWriter binaryWriter = new BinaryWriter(fileStream)) |
||||
|
{ |
||||
|
// Put the count.
|
||||
|
binaryWriter.Write(this.Count); |
||||
|
|
||||
|
// Put the values.
|
||||
|
foreach (var pair in this) |
||||
|
{ |
||||
|
binaryWriter.Write(pair.Key); |
||||
|
binaryWriter.Write(pair.Value.ValueAndLastWriteTimeUtcToString()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Loads the cache file to populate the in memory cache.
|
||||
|
/// </summary>
|
||||
|
private void LoadCache() |
||||
|
{ |
||||
|
lock (SyncRoot) |
||||
|
{ |
||||
|
if (File.Exists(this.cachedIndexFile)) |
||||
|
{ |
||||
|
using (FileStream fileStream = File.OpenRead(this.cachedIndexFile)) |
||||
|
{ |
||||
|
using (BinaryReader binaryReader = new BinaryReader(fileStream)) |
||||
|
{ |
||||
|
// Get the count.
|
||||
|
int count = binaryReader.ReadInt32(); |
||||
|
|
||||
|
// Read in all pairs.
|
||||
|
for (int i = 0; i < count; i++) |
||||
|
{ |
||||
|
// Read the key/value strings
|
||||
|
string key = binaryReader.ReadString(); |
||||
|
string value = binaryReader.ReadString(); |
||||
|
|
||||
|
// Create a CachedImage
|
||||
|
string[] valueAndLastWriteTime = value.Split(new[] { CachedImage.ValueLastWriteTimeDelimiter }, StringSplitOptions.None); |
||||
|
DateTime lastWriteTime = DateTime.Parse(valueAndLastWriteTime[1]); |
||||
|
CachedImage cachedImage = new CachedImage(valueAndLastWriteTime[0], lastWriteTime); |
||||
|
|
||||
|
// Assign the value
|
||||
|
this[key] = cachedImage; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
8150b46ab27c62ba51aaba551eef3f1a30f08de9 |
||||
@ -0,0 +1 @@ |
|||||
|
6ad3b846d4697584ff601ac481b14a4d3bbb5736 |
||||
@ -0,0 +1 @@ |
|||||
|
a2c796fbb7de948230a22982ab74892891dd5198 |
||||
@ -1,94 +1,367 @@ |
|||||
@{ |
@{ |
||||
ViewBag.Title = "Home Page"; |
ViewBag.Title = "Home Page"; |
||||
} |
} |
||||
<section> |
<article> |
||||
<div class="container"> |
<h1 class="container">Jpg</h1> |
||||
<div class="clmn2"> |
<section> |
||||
<h2>Resized</h2> |
<div class="container"> |
||||
<img src="/images/Penguins.jpg?width=300" /> |
<div class="clmn2"> |
||||
</div> |
<h2>Resized</h2> |
||||
<div class="clmn2"> |
<img src="/images/Penguins.jpg?width=300" /> |
||||
<h2>Cropped </h2> |
</div> |
||||
<img src="/images/Penguins.jpg?crop=0-0-300-225" /> |
<div class="clmn2"> |
||||
</div> |
<h2>Cropped </h2> |
||||
</div> |
<img src="/images/Penguins.jpg?crop=0-0-300-225" /> |
||||
</section> |
</div> |
||||
<section> |
</div> |
||||
<div class="container"> |
</section> |
||||
<h2>Filter</h2> |
<section> |
||||
<ul class="no-bullets clearfix"> |
<div class="container"> |
||||
<li> |
<h2>Filter</h2> |
||||
<h3>blackwhite</h3> |
<ul class="no-bullets clearfix"> |
||||
<img src="/images/Penguins.jpg?width=300&filter=blackwhite" /> |
<li> |
||||
</li> |
<h3>blackwhite</h3> |
||||
<li> |
<img src="/images/Penguins.jpg?width=300&filter=blackwhite" /> |
||||
<h3>comic</h3> |
</li> |
||||
<img src="/images/Penguins.jpg?width=300&filter=comic" /> |
<li> |
||||
</li> |
<h3>comic</h3> |
||||
<li> |
<img src="/images/Penguins.jpg?width=300&filter=comic" /> |
||||
<h3>lomograph</h3> |
</li> |
||||
<img src="/images/Penguins.jpg?width=300&filter=lomograph" /> |
<li> |
||||
</li> |
<h3>lomograph</h3> |
||||
<li> |
<img src="/images/Penguins.jpg?width=300&filter=lomograph" /> |
||||
<h3>greyscale</h3> |
</li> |
||||
<img src="/images/Penguins.jpg?width=300&filter=greyscale" /> |
<li> |
||||
</li> |
<h3>greyscale</h3> |
||||
<li> |
<img src="/images/Penguins.jpg?width=300&filter=greyscale" /> |
||||
<h3>polaroid</h3> |
</li> |
||||
<img src="/images/Penguins.jpg?width=300&filter=polaroid" /> |
<li> |
||||
</li> |
<h3>polaroid</h3> |
||||
<li> |
<img src="/images/Penguins.jpg?width=300&filter=polaroid" /> |
||||
<h3>sepia</h3> |
</li> |
||||
<img src="/images/Penguins.jpg?width=300&filter=sepia" /> |
<li> |
||||
</li> |
<h3>sepia</h3> |
||||
<li> |
<img src="/images/Penguins.jpg?width=300&filter=sepia" /> |
||||
<h3>gotham</h3> |
</li> |
||||
<img src="/images/Penguins.jpg?width=300&filter=gotham" /> |
<li> |
||||
</li> |
<h3>gotham</h3> |
||||
<li> |
<img src="/images/Penguins.jpg?width=300&filter=gotham" /> |
||||
<h3>hisatch</h3> |
</li> |
||||
<img src="/images/Penguins.jpg?width=300&filter=hisatch" /> |
<li> |
||||
</li> |
<h3>hisatch</h3> |
||||
<li> |
<img src="/images/Penguins.jpg?width=300&filter=hisatch" /> |
||||
<h3>losatch</h3> |
</li> |
||||
<img src="/images/Penguins.jpg?width=300&filter=losatch" /> |
<li> |
||||
</li> |
<h3>losatch</h3> |
||||
</ul> |
<img src="/images/Penguins.jpg?width=300&filter=losatch" /> |
||||
</div> |
</li> |
||||
</section> |
</ul> |
||||
<section> |
</div> |
||||
<div class="container"> |
</section> |
||||
<div class="clmn2"> |
<section> |
||||
<h2>Watermark</h2> |
<div class="container"> |
||||
<img src="/images/Penguins.jpg?width=300&watermark=text-test|color-fff|size-48|style-italic|opacity-100|position-100-100|shadow-true|font-arial" /> |
<div class="clmn2"> |
||||
</div> |
<h2>Watermark</h2> |
||||
<div class="clmn2"> |
<img src="/images/Penguins.jpg?width=300&watermark=text-test|color-fff|size-48|style-italic|opacity-100|position-100-100|shadow-true|font-arial" /> |
||||
<h2>Format</h2> |
</div> |
||||
<img src="/images/Penguins.jpg?width=300&format=gif" /> |
<div class="clmn2"> |
||||
</div> |
<h2>Format</h2> |
||||
</div> |
<img src="/images/Penguins.jpg?width=300&format=gif" /> |
||||
</section> |
</div> |
||||
<section> |
</div> |
||||
<div class="container"> |
</section> |
||||
<div class="clmn2"> |
<section> |
||||
<h2>Rotate</h2> |
<div class="container"> |
||||
<img src="/images/Penguins.jpg?width=300&rotate=angle-54|bgcolor-fff" /> |
<div class="clmn2"> |
||||
</div> |
<h2>Rotate</h2> |
||||
<div class="clmn2"> |
<img src="/images/Penguins.jpg?width=300&rotate=angle-54|bgcolor-fff" /> |
||||
<h2>Quality</h2> |
</div> |
||||
<img src="/images/Penguins.jpg?width=300&quality=5" /> |
<div class="clmn2"> |
||||
</div> |
<h2>Quality</h2> |
||||
</div> |
<img src="/images/Penguins.jpg?width=300&quality=5" /> |
||||
</section> |
</div> |
||||
<section> |
</div> |
||||
<div class="container"> |
</section> |
||||
<div class="clmn2"> |
<section> |
||||
<h2>Alpha</h2> |
<div class="container"> |
||||
<img src="/images/Penguins.jpg?width=300&format=png&alpha=50" /> |
<div class="clmn2"> |
||||
</div> |
<h2>Alpha</h2> |
||||
<div class="clmn2"> |
<img src="/images/Penguins.jpg?width=300&format=png&alpha=50" /> |
||||
<h2>Remote</h2> |
</div> |
||||
<img src="/remote.axd?http://images.mymovies.net/images/film/cin/500x377/fid11707.jpg?width=300" /> |
<div class="clmn2"> |
||||
</div> |
<h2>Remote</h2> |
||||
</div> |
<img src="/remote.axd?http://images.mymovies.net/images/film/cin/500x377/fid11707.jpg?width=300" /> |
||||
</section> |
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
</article> |
||||
|
<article> |
||||
|
<h1 class="container">Gif</h1> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Resized</h2> |
||||
|
<img src="/images/Penguins.gif?width=300" /> |
||||
|
</div> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Cropped </h2> |
||||
|
<img src="/images/Penguins.gif?crop=0-0-300-225" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<h2>Filter</h2> |
||||
|
<ul class="no-bullets clearfix"> |
||||
|
<li> |
||||
|
<h3>blackwhite</h3> |
||||
|
<img src="/images/Penguins.gif?width=300&filter=blackwhite" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>comic</h3> |
||||
|
<img src="/images/Penguins.gif?width=300&filter=comic" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>lomograph</h3> |
||||
|
<img src="/images/Penguins.gif?width=300&filter=lomograph" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>greyscale</h3> |
||||
|
<img src="/images/Penguins.gif?width=300&filter=greyscale" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>polaroid</h3> |
||||
|
<img src="/images/Penguins.gif?width=300&filter=polaroid" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>sepia</h3> |
||||
|
<img src="/images/Penguins.gif?width=300&filter=sepia" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>gotham</h3> |
||||
|
<img src="/images/Penguins.gif?width=300&filter=gotham" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>hisatch</h3> |
||||
|
<img src="/images/Penguins.gif?width=300&filter=hisatch" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>losatch</h3> |
||||
|
<img src="/images/Penguins.gif?width=300&filter=losatch" /> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Watermark</h2> |
||||
|
<img src="/images/Penguins.gif?width=300&watermark=text-test|color-fff|size-48|style-italic|opacity-100|position-100-100|shadow-true|font-arial" /> |
||||
|
</div> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Format</h2> |
||||
|
<img src="/images/Penguins.gif?width=300&format=png" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Rotate</h2> |
||||
|
<img src="/images/Penguins.gif?width=300&rotate=angle-54|bgcolor-fff" /> |
||||
|
</div> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Quality</h2> |
||||
|
<img src="/images/Penguins.gif?width=300&quality=5" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Alpha</h2> |
||||
|
<img src="/images/Penguins.gif?width=300&alpha=50" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
</article> |
||||
|
<article> |
||||
|
<h1 class="container">Png</h1> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Resized</h2> |
||||
|
<img src="/images/Penguins.png?width=300" /> |
||||
|
</div> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Cropped </h2> |
||||
|
<img src="/images/Penguins.png?crop=0-0-300-225" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<h2>Filter</h2> |
||||
|
<ul class="no-bullets clearfix"> |
||||
|
<li> |
||||
|
<h3>blackwhite</h3> |
||||
|
<img src="/images/Penguins.png?width=300&filter=blackwhite" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>comic</h3> |
||||
|
<img src="/images/Penguins.png?width=300&filter=comic" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>lomograph</h3> |
||||
|
<img src="/images/Penguins.png?width=300&filter=lomograph" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>greyscale</h3> |
||||
|
<img src="/images/Penguins.png?width=300&filter=greyscale" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>polaroid</h3> |
||||
|
<img src="/images/Penguins.png?width=300&filter=polaroid" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>sepia</h3> |
||||
|
<img src="/images/Penguins.png?width=300&filter=sepia" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>gotham</h3> |
||||
|
<img src="/images/Penguins.png?width=300&filter=gotham" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>hisatch</h3> |
||||
|
<img src="/images/Penguins.png?width=300&filter=hisatch" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>losatch</h3> |
||||
|
<img src="/images/Penguins.png?width=300&filter=losatch" /> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Watermark</h2> |
||||
|
<img src="/images/Penguins.png?width=300&watermark=text-test|color-fff|size-48|style-italic|opacity-100|position-100-100|shadow-true|font-arial" /> |
||||
|
</div> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Format</h2> |
||||
|
<img src="/images/Penguins.png?width=300&format=bmp" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Rotate</h2> |
||||
|
<img src="/images/Penguins.png?width=300&rotate=angle-54|bgcolor-fff" /> |
||||
|
</div> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Quality</h2> |
||||
|
<img src="/images/Penguins.png?width=300&quality=5" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Alpha</h2> |
||||
|
<img src="/images/Penguins.png?width=300&alpha=50" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
</article> |
||||
|
<article> |
||||
|
<h1 class="container">Bmp</h1> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Resized</h2> |
||||
|
<img src="/images/Penguins.bmp?width=300" /> |
||||
|
</div> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Cropped </h2> |
||||
|
<img src="/images/Penguins.bmp?crop=0-0-300-225" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<h2>Filter</h2> |
||||
|
<ul class="no-bullets clearfix"> |
||||
|
<li> |
||||
|
<h3>blackwhite</h3> |
||||
|
<img src="/images/Penguins.bmp?width=300&filter=blackwhite" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>comic</h3> |
||||
|
<img src="/images/Penguins.bmp?width=300&filter=comic" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>lomograph</h3> |
||||
|
<img src="/images/Penguins.bmp?width=300&filter=lomograph" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>greyscale</h3> |
||||
|
<img src="/images/Penguins.bmp?width=300&filter=greyscale" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>polaroid</h3> |
||||
|
<img src="/images/Penguins.bmp?width=300&filter=polaroid" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>sepia</h3> |
||||
|
<img src="/images/Penguins.bmp?width=300&filter=sepia" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>gotham</h3> |
||||
|
<img src="/images/Penguins.bmp?width=300&filter=gotham" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>hisatch</h3> |
||||
|
<img src="/images/Penguins.bmp?width=300&filter=hisatch" /> |
||||
|
</li> |
||||
|
<li> |
||||
|
<h3>losatch</h3> |
||||
|
<img src="/images/Penguins.bmp?width=300&filter=losatch" /> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Watermark</h2> |
||||
|
<img src="/images/Penguins.bmp?width=300&watermark=text-test|color-fff|size-48|style-italic|opacity-100|position-100-100|shadow-true|font-arial" /> |
||||
|
</div> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Format</h2> |
||||
|
<img src="/images/Penguins.bmp?width=300&format=jpg" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Rotate</h2> |
||||
|
<img src="/images/Penguins.bmp?width=300&rotate=angle-54|bgcolor-fff" /> |
||||
|
</div> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Quality</h2> |
||||
|
<img src="/images/Penguins.bmp?width=300&quality=5" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section> |
||||
|
<div class="container"> |
||||
|
<div class="clmn2"> |
||||
|
<h2>Alpha</h2> |
||||
|
<img src="/images/Penguins.bmp?width=300&alpha=50" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
</article> |
||||
|
|||||
Loading…
Reference in new issue