Adding format filter

--HG--
branch : 1.x
extra : rebase_source : 85116c74542c45f39aa69ec6e66ce30b7684508d
This commit is contained in:
Sebastien Ros
2013-03-04 11:11:27 -08:00
parent e7910da0ad
commit 98b3f0553a
9 changed files with 176 additions and 292 deletions

View File

@@ -112,9 +112,7 @@
<Compile Include="Models\FilterRecord.cs" />
<Compile Include="Models\ImageProfilePart.cs" />
<Compile Include="Models\ImageProfilePartRecord.cs" />
<None Include="Providers\Filters\ConstrainFilter.cs" />
<None Include="Providers\Filters\CropFilter.cs" />
<None Include="Providers\Filters\ImageFormatFilter.cs" />
<Compile Include="Providers\Filters\FormatFilter.cs" />
<Compile Include="Providers\Filters\ResizeFilter.cs" />
<Compile Include="Services\IImageFilterProvider.cs" />
<Compile Include="Services\IImageProcessingFileNameProvider.cs" />

View File

@@ -1,97 +0,0 @@
using System;
using System.Web.Mvc;
using ImageResizer;
using Orchard.DisplayManagement;
using Orchard.Forms.Services;
using Orchard.Localization;
using Orchard.MediaProcessing.Descriptors.Filter;
using Orchard.MediaProcessing.Services;
namespace Orchard.MediaProcessing.Providers.Filters {
public class ConstrainFilter : IImageFilterProvider {
public ConstrainFilter() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeFilterContext describe) {
describe.For("Transform", T("Transform"), T("Transform"))
.Element("Constrain", T("Constrain"), T("Constrains the dimensions of an image either by with of by height"),
ApplyFilter,
DisplayFilter,
"ContrainImageFilter"
);
}
public void ApplyFilter(FilterContext context) {
var value = (int)context.State.Value;
var axis = (string)context.State.Axis;
var settings = new ResizeSettings {
Mode = FitMode.Max
};
switch (axis) {
case "width":
settings.Width = value;
break;
case "height":
settings.Height = value;
break;
}
context.Media = result;
}
public LocalizedString DisplayFilter(FilterContext context) {
var value = (int)context.State.Value;
var axis = (string)context.State.Axis;
return axis == "height"
? T("Constrain to {0}px high", value)
: T("Constrain to {0}px wide", value);
}
}
public class ConstrainFilterFilterForms : IFormProvider {
protected dynamic Shape { get; set; }
public Localizer T { get; set; }
public ConstrainFilterFilterForms(
IShapeFactory shapeFactory) {
Shape = shapeFactory;
T = NullLocalizer.Instance;
}
public void Describe(DescribeContext context) {
Func<IShapeFactory, object> form =
shape => {
var f = Shape.Form(
Id: "ContrainImageFilter",
_Axis: Shape.SelectList(
Id: "axis", Name: "Axis",
Title: T("Axis"),
Size: 1,
Multiple: false
),
_Height: Shape.Textbox(
Id: "value", Name: "Value",
Title: T("Value"),
Description: T("The value in pixel the selected axis should be constrained to. Mandatory."),
Classes: new[] {"text-small"})
);
f._Axis.Add(new SelectListItem { Value = "height", Text = T("Height").Text });
f._Axis.Add(new SelectListItem { Value = "width", Text = T("Width").Text });
return f;
};
context.Form("ContrainImageFilter", form);
}
}
}

View File

@@ -1,89 +0,0 @@
using System;
using System.Drawing;
using Orchard.DisplayManagement;
using Orchard.Forms.Services;
using Orchard.Localization;
using Orchard.MediaProcessing.Descriptors.Filter;
using Orchard.MediaProcessing.Services;
namespace Orchard.MediaProcessing.Providers.Filters {
public class CropFilter : IImageFilterProvider {
public CropFilter() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeFilterContext describe) {
describe.For("Transform", T("Transform"), T("Transform"))
.Element("Crop", T("Crop"), T("Crops to a fixed height and width"),
ApplyFilter,
DisplayFilter,
"CropFilter"
);
}
public void ApplyFilter(FilterContext context) {
var newHeight = int.Parse(context.State.Height);
newHeight = newHeight > 0 ? newHeight : context.Media.Height;
var heightFactor = (float) context.Media.Height/newHeight;
var newWidth = int.Parse(context.State.Width);
newWidth = newWidth > 0 ? newWidth : context.Media.Width;
var widthFactor = context.Media.Width/newWidth;
if (widthFactor != heightFactor) {
if (widthFactor > heightFactor) {
newHeight = Convert.ToInt32(context.Media.Height/widthFactor);
}
else {
newWidth = Convert.ToInt32(context.Media.Width/heightFactor);
}
}
var newImage = new Bitmap(newWidth, newHeight);
using (var graphics = Graphics.FromImage(newImage)) {
graphics.DrawImage(context.Media, 0, 0, new Rectangle(0, 0, newWidth, newHeight), GraphicsUnit.Pixel);
}
context.Media = newImage;
}
public LocalizedString DisplayFilter(FilterContext context) {
return T("Crop to {0}px high x {1}px wide", context.State.Height, context.State.Width);
}
}
public class CropFilterForms : IFormProvider {
protected dynamic Shape { get; set; }
public Localizer T { get; set; }
public CropFilterForms(
IShapeFactory shapeFactory) {
Shape = shapeFactory;
T = NullLocalizer.Instance;
}
public void Describe(DescribeContext context) {
Func<IShapeFactory, object> form =
shape => {
var f = Shape.Form(
Id: "ImageCropFilter",
_Height: Shape.Textbox(
Id: "height", Name: "Height",
Title: T("Height"),
Description: T("The height in pixels, 0 to allow any value."),
Classes: new[] {"text-small"}),
_Width: Shape.Textbox(
Id: "width", Name: "Width",
Title: T("Width"),
Description: T("The width in pixels, 0 to allow any value."),
Classes: new[] {"text-small"}));
return f;
};
context.Form("CropFilter", form);
}
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.IO;
using System.Web.Mvc;
using ImageResizer;
using Orchard.DisplayManagement;
using Orchard.Forms.Services;
using Orchard.Localization;
using Orchard.MediaProcessing.Descriptors.Filter;
using Orchard.MediaProcessing.Services;
namespace Orchard.MediaProcessing.Providers.Filters {
public class FormatFilter : IImageFilterProvider {
public FormatFilter() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeFilterContext describe) {
describe.For("Transform", T("Transform"), T("Transform"))
.Element("Format", T("Format"), T("Change the format of the image."),
ApplyFilter,
DisplayFilter,
"FormatFilter"
);
}
public void ApplyFilter(FilterContext context) {
string format = context.State.Format;
int quality = context.State.Quality;
var settings = new ResizeSettings {
Quality = quality,
Format = format
};
var result = new MemoryStream();
if (context.Media.CanSeek) {
context.Media.Seek(0, SeekOrigin.Begin);
}
ImageBuilder.Current.Build(context.Media, result, settings);
context.FilePath = Path.ChangeExtension(context.FilePath, format);
context.Media = result;
}
public LocalizedString DisplayFilter(FilterContext context) {
return T("Format the image to {0}", (string)context.State.Format);
}
}
public class FormatFilterForms : IFormProvider {
protected dynamic Shape { get; set; }
public Localizer T { get; set; }
public FormatFilterForms(
IShapeFactory shapeFactory) {
Shape = shapeFactory;
T = NullLocalizer.Instance;
}
public void Describe(DescribeContext context) {
Func<IShapeFactory, object> form =
shape => {
var f = Shape.Form(
Id: "FormatFilter",
_Format: Shape.SelectList(
Id: "format", Name: "Format",
Title: T("Format"),
Description: T("The target format of the image."),
Size: 1,
Multiple: false),
_Quality: Shape.Textbox(
Id: "quality", Name: "Quality",
Title: T("Quality"),
Value: 90,
Description: T("JPeg compression quality, from 0 to 100."),
Classes: new[] { "text-small" })
);
f._Format.Add(new SelectListItem { Value = "jpg", Text = T("Jpeg").Text });
f._Format.Add(new SelectListItem { Value = "gif", Text = T("Gif").Text });
f._Format.Add(new SelectListItem { Value = "png", Text = T("Png").Text });
return f;
};
context.Form("FormatFilter", form);
}
}
}

View File

@@ -1,92 +0,0 @@
using System;
using System.Drawing.Imaging;
using System.IO;
using System.Web.Mvc;
using Orchard.DisplayManagement;
using Orchard.Forms.Services;
using Orchard.Localization;
using Orchard.MediaProcessing.Descriptors.Filter;
using Orchard.MediaProcessing.Services;
namespace Orchard.MediaProcessing.Providers.Filters {
public class ImageFormatFilter : IImageFilterProvider {
public ImageFormatFilter() {
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(DescribeFilterContext describe) {
describe.For("Transform", T("Transform"), T("Transform"))
.Element("ImageFormat", T("ImageFormat"), T("Changes the image file format"),
ApplyFilter,
DisplayFilter,
"ImageFormatFilter"
);
}
public void ApplyFilter(FilterContext context) {
context.Format = ImageFormatConverter.ToImageFormat((ImageFormats)Enum.Parse(typeof (ImageFormats), (string)context.State.ImageFormat));
context.FilePath = Path.ChangeExtension(context.FilePath, context.Format.ToString().ToLower());
}
public LocalizedString DisplayFilter(FilterContext context) {
return T("Convert to {0}", context.State.ImageFormat.ToString());
}
}
public class ImageFormatFilterForms : IFormProvider {
protected dynamic Shape { get; set; }
public Localizer T { get; set; }
public ImageFormatFilterForms(
IShapeFactory shapeFactory) {
Shape = shapeFactory;
T = NullLocalizer.Instance;
}
public void Describe(DescribeContext context) {
Func<IShapeFactory, object> form =
shape => {
var f = Shape.Form(
Id: "ImageFormatFilter",
_ImageFormat: Shape.SelectList(
Id: "imageformat",
Name: "ImageFormat"
));
foreach (var item in Enum.GetValues(typeof (ImageFormats))) {
var name = Enum.GetName(typeof (ImageFormats), item);
f._ImageFormat.Add(new SelectListItem {Value = item.ToString(), Text = name});
}
return f;
};
context.Form("ImageFormatFilter", form);
}
}
public enum ImageFormats {
Bmp,
Gif,
Jpeg,
Png
}
public class ImageFormatConverter {
public static ImageFormat ToImageFormat(ImageFormats format) {
switch (format) {
case ImageFormats.Bmp:
return ImageFormat.Bmp;
case ImageFormats.Gif:
return ImageFormat.Gif;
case ImageFormats.Jpeg:
return ImageFormat.Jpeg;
case ImageFormats.Png:
return ImageFormat.Png;
}
return ImageFormat.Jpeg;
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Web.Mvc;
using ImageResizer;
using Orchard.DisplayManagement;
using Orchard.Forms.Services;
@@ -29,6 +29,9 @@ namespace Orchard.MediaProcessing.Providers.Filters {
public void ApplyFilter(FilterContext context) {
int witdh = context.State.Width;
int height = context.State.Height;
string mode = context.State.Mode;
string alignment = context.State.Alignment;
string padcolor = context.State.PadColor;
var settings = new ResizeSettings {
Mode = FitMode.Max,
@@ -36,13 +39,45 @@ namespace Orchard.MediaProcessing.Providers.Filters {
Width = witdh
};
switch (mode) {
case "max": settings.Mode = FitMode.Max; break;
case "pad": settings.Mode = FitMode.Pad; break;
case "crop": settings.Mode = FitMode.Crop; break;
case "stretch": settings.Mode = FitMode.Stretch; break;
}
switch (alignment) {
case "topleft": settings.Anchor = ContentAlignment.TopLeft; break;
case "topcenter": settings.Anchor = ContentAlignment.TopCenter; break;
case "topright": settings.Anchor = ContentAlignment.TopRight; break;
case "middleleft": settings.Anchor = ContentAlignment.MiddleLeft; break;
case "middlecenter": settings.Anchor = ContentAlignment.MiddleCenter; break;
case "middleright": settings.Anchor = ContentAlignment.MiddleRight; break;
case "bottomleft": settings.Anchor = ContentAlignment.BottomLeft; break;
case "bottomcenter": settings.Anchor = ContentAlignment.BottomCenter; break;
case "bottomright": settings.Anchor = ContentAlignment.BottomRight; break;
}
if (!String.IsNullOrWhiteSpace(padcolor)) {
if (padcolor.StartsWith("#")) {
ColorTranslator.FromHtml(padcolor);
}
else {
settings.PaddingColor = Color.FromName(padcolor);
}
}
var result = new MemoryStream();
if (context.Media.CanSeek) {
context.Media.Seek(0, SeekOrigin.Begin);
}
ImageBuilder.Current.Build(context.Media, result, settings);
context.Media = result;
}
public LocalizedString DisplayFilter(FilterContext context) {
return T("Resize to {0}px high x {1}px wide", context.State.Height, context.State.Width);
return T((string)context.State.Mode + " to {0}px high x {1}px wide", context.State.Height, context.State.Width);
}
}
@@ -64,14 +99,50 @@ namespace Orchard.MediaProcessing.Providers.Filters {
_Width: Shape.Textbox(
Id: "width", Name: "Width",
Title: T("Width"),
Description: T("The width in pixels, 0 to allow any value."),
Value: 0,
Description: T("The width in pixels."),
Classes: new[] {"text-small"}),
_Height: Shape.Textbox(
Id: "height", Name: "Height",
Title: T("Height"),
Description: T("The height in pixels, 0 to allow any value."),
Value: 0,
Description: T("The height in pixels."),
Classes: new[] {"text-small"}),
_Mode: Shape.SelectList(
Id: "mode", Name: "Mode",
Title: T("Mode"),
Description: T("How the image should be resized.<br/>Max: adjusts to the max given width or left, keeping image ratio.<br/>Pad: adds a padding so that the target image is exactly of width and height.<br/>Crop: removes part of the image to fit with given height and width.<br/>Stretch: stretches the image to fit within height and width."),
Size: 1,
Multiple: false),
_Alignment: Shape.SelectList(
Id: "alignment", Name: "Alignment",
Title: T("Alignment"),
Description: T("Select the alignment for Crop and Pad modes."),
Size: 1,
Multiple: false),
_PadColor: Shape.Textbox(
Id: "padcolor", Name: "PadColor",
Title: T("Pad Color"),
Value: "#ffffff",
Description: T("The background color to use to pad the image. Named color or hex value."),
Classes: new[] {"text-small"})
);
);
f._Mode.Add(new SelectListItem { Value = "max", Text = T("Max").Text });
f._Mode.Add(new SelectListItem { Value = "pad", Text = T("Pad").Text });
f._Mode.Add(new SelectListItem { Value = "crop", Text = T("Crop").Text });
f._Mode.Add(new SelectListItem { Value = "stretch", Text = T("Stretch").Text });
f._Alignment.Add(new SelectListItem { Value = "topleft", Text = T("Top Left").Text });
f._Alignment.Add(new SelectListItem { Value = "topcenter", Text = T("Top Center").Text });
f._Alignment.Add(new SelectListItem { Value = "topright", Text = T("Top Right").Text });
f._Alignment.Add(new SelectListItem { Value = "middleleft", Text = T("Middle Left").Text });
f._Alignment.Add(new SelectListItem { Value = "middlecenter", Text = T("Middle Center").Text });
f._Alignment.Add(new SelectListItem { Value = "middleright", Text = T("Middle Right").Text });
f._Alignment.Add(new SelectListItem { Value = "bottomleft", Text = T("Bottom Left").Text });
f._Alignment.Add(new SelectListItem { Value = "bottomcenter", Text = T("Bottom Center").Text });
f._Alignment.Add(new SelectListItem { Value = "bottomright", Text = T("Bottom Right").Text });
return f;
};

View File

@@ -1,8 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Orchard.Caching;
using Orchard.Data;
using Orchard.MediaProcessing.Models;
namespace Orchard.MediaProcessing.Services {

View File

@@ -35,7 +35,8 @@ namespace Orchard.MediaProcessing.Shapes {
[Shape]
public void ImageUrl(dynamic Display, TextWriter Output, string Profile, string Path) {
var filePath = _fileNameProvider.Value.GetFileName(Profile, Path);
if (string.IsNullOrEmpty(filePath) || _storageProvider.Value.GetFile(filePath) == null) {
// todo: regenerate the file if the profile is newer, by getting IStorageFile.
if (string.IsNullOrEmpty(filePath) || !_storageProvider.Value.FileExists(filePath)) {
try {
var profilePart = _profileService.Value.GetImageProfileByName(Profile);
if (profilePart == null)
@@ -58,10 +59,12 @@ namespace Orchard.MediaProcessing.Shapes {
var newFile = _storageProvider.Value.OpenOrCreate(filterContext.FilePath);
using (var imageStream = newFile.OpenWrite()) {
using (var sw = new BinaryWriter(imageStream)) {
filterContext.Media.Seek(0, SeekOrigin.Begin);
if (filterContext.Media.CanSeek) {
filterContext.Media.Seek(0, SeekOrigin.Begin);
}
using (var sr = new BinaryReader(filterContext.Media)) {
int count;
var buffer = new byte[1024];
var buffer = new byte[8192];
while ((count = sr.Read(buffer, 0, buffer.Length)) != 0) {
sw.Write(buffer, 0, count);
}

View File

@@ -70,7 +70,7 @@ namespace Orchard.FileSystems.Media {
/// <param name="path">The relative path within the storage provider.</param>
/// <returns>True if the file exists; False otherwise.</returns>
public bool FileExists(string path) {
return new FileInfo(MapStorage(path)).Exists;
return File.Exists(MapStorage(path));
}
/// <summary>