mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Adding format filter
--HG-- branch : 1.x extra : rebase_source : 85116c74542c45f39aa69ec6e66ce30b7684508d
This commit is contained in:
@@ -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" />
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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>
|
||||
|
Reference in New Issue
Block a user