Signature image extracted by itextsharp is crashed - itext

I extracted some stamped signature images(png file) from pdf.
like this
Lots of them are normal but few images are crashed.
I can guess some reasons: the image is encrypted? confused? when signing.
I'm new to itext, any idea will be appreciated.

The reason is that the image you see is created by drawing that mostly red image
with a soft mask derived from another image
I.e. where the soft mask is white, the red from the image is drawn completely opaquely; where the mask is black it is drawn completely transparently, invisibly; and where the mask is some gray in-between, the red is drawn somewhat transparently.
The ImageRenderListener you use in your previous answer is from this older answer and only extracts the base image, not the mask.
You can improve it like this to also extract the soft masks directly associated with the respective base image:
public class ExtImageRenderListener : IRenderListener
{
public List<System.Drawing.Image> Images = new List<System.Drawing.Image>();
public List<System.Drawing.Image> Masks = new List<System.Drawing.Image>();
public void BeginTextBlock()
{ }
public void EndTextBlock()
{ }
public void RenderText(TextRenderInfo renderInfo)
{ }
public void RenderImage(ImageRenderInfo renderInfo)
{
PdfImageObject imageObject = renderInfo.GetImage();
if (imageObject == null)
{
Console.WriteLine("Image {0} could not be read.", renderInfo.GetRef().Number);
}
else
{
Images.Add(imageObject.GetDrawingImage());
PRStream maskStream = (PRStream) imageObject.GetDictionary().GetAsStream(PdfName.SMASK);
if (maskStream != null)
{
PdfImageObject maskImageObject = new PdfImageObject(maskStream);
Masks.Add(maskImageObject.GetDrawingImage());
}
else
{
Masks.Add(null);
}
}
}
}
Now you can process both the image and the mask:
String source = #"stampForDebug.pdf";
String signatureFieldName = "Signature12";
using (PdfReader sourceReader = new PdfReader(source))
{
PdfStream xObject = (PdfStream)PdfReader.GetPdfObjectRelease(sourceReader.AcroFields.GetNormalAppearance(signatureFieldName));
PdfDictionary resources = xObject.GetAsDict(PdfName.RESOURCES);
ExtImageRenderListener strategy = new ExtImageRenderListener();
PdfContentStreamProcessor processor = new PdfContentStreamProcessor(strategy);
processor.ProcessContent(ContentByteUtils.GetContentBytesFromContentObject(xObject), resources);
System.Drawing.Image drawingImage = strategy.Images.First();
System.Drawing.Image drawingMask = strategy.Masks.First();
if (drawingImage != null)
{
drawingImage.Save(#"Signature12Image.png");
}
if (drawingMask != null)
{
drawingMask.Save(#"Signature12Mask.png");
}
}

Related

html2pdf - get page content inside IEventHandler implementation

I need to have two different headers in my pdf generated using html2pdf from iText.
Currently I'm 'printing' the headers by using a implemetation of IEventHandler. Like this:
public virtual void HandleEvent(Event #event)
{
PdfDocumentEvent docEvent = (PdfDocumentEvent)#event;
PdfDocument pdf = docEvent.GetDocument();
PdfPage page = docEvent.GetPage();
int pageNumber = pdf.GetPageNumber(page);
Rectangle pageSize = page.GetPageSize();
// Creates drawing canvas
PdfCanvas pdfCanvas = new PdfCanvas(page);
Canvas canvas = new Canvas(pdfCanvas, pageSize);
try
{
if (typeof(Paragraph) == element.GetType()) // This is an IElement object
{
Paragraph p = (Paragraph)element;
if (p.GetChildren().Count > 0)
{
p.SetWidth(pageSize.GetWidth() - iLeftMargin - iRightMargin).SetMarginLeft(iLeftMargin);
canvas.Add(p);
}
}
canvas.Close();
pdfCanvas.Release();
}
catch (System.Exception)
{
}
}
Now I need to check if the current page has a specific text (or anything) so I can change the text inside my element object and then print a different header.
It would be really nice if the TagWorker get processed alogside IEventHandler, but it is sequential, and I can't know when i need to change the text in my header.

How can i store or read a animation clip data in runtime?

I'm working on a small program that can modify the animation at run time(Such as when you run faster the animation not only play faster but also with larger movement). So i need to get the existing animation, change its value, then send it back.
I found it is interesting that i can set a new curve to the animation, but i can't get access to what i already have. So I either write a file to store my animation curve (as text file for example), or i find someway to read the animation on start up.
I tried to use
AnimationUtility.GetCurveBindings(AnimationCurve);
It worked in my testing, but in some page it says this is a "Editor code", that if i build the project into a standalone program it will not work anymore. Is that true? If so, is there any way to get the curve at run time?
Thanks to the clearify from Benjamin Zach and suggestion from TehMightyPotato
I'd like to keep the idea about modifying the animation at runtime. Because it could adapt to more situations imo.
My idea for now is to write a piece of editor code that can read from the curve in Editor and output all necesseary information about the curve (keyframes) into a text file. Then read that file at runtime and create new curve to overwrite the existing one. I will leave this question open for a few days and check it to see if anyone has a better idea about it.
As said already AnimationUtility belongs to the UnityEditor namespace. This entire namespace is completely stripped of in a build and nothing in it will be available in the final app but only within the Unity Editor.
Store AnimationCurves to file
In order to store all needed information to a file you could have a script for once serializing your specific animation curve(s) in the editor before building using e.g. BinaryFormatter.Serialize. Then later on runtime you can use BinaryFormatter.Deserialize for returning the info list again.
If you wanted it more editable you could as well use e.g. JSON or XML of course
UPDATE: In general Stop using BinaryFormatter!
In the newest Unity versions the Newtonsoft Json.NET package comes already preinstalled so simply rather use JSON
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Unity.Plastic.Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
public class AnimationCurveManager : MonoBehaviour
{
[Serializable]
public sealed class ClipInfo
{
public int ClipInstanceID;
public List<CurveInfo> CurveInfos = new List<CurveInfo>();
// default constructor is sometimes required for (de)serialization
public ClipInfo() { }
public ClipInfo(Object clip, List<CurveInfo> curveInfos)
{
ClipInstanceID = clip.GetInstanceID();
CurveInfos = curveInfos;
}
}
[Serializable]
public sealed class CurveInfo
{
public string PathKey;
public List<KeyFrameInfo> Keys = new List<KeyFrameInfo>();
public WrapMode PreWrapMode;
public WrapMode PostWrapMode;
// default constructor is sometimes required for (de)serialization
public CurveInfo() { }
public CurveInfo(string pathKey, AnimationCurve curve)
{
PathKey = pathKey;
foreach (var keyframe in curve.keys)
{
Keys.Add(new KeyFrameInfo(keyframe));
}
PreWrapMode = curve.preWrapMode;
PostWrapMode = curve.postWrapMode;
}
}
[Serializable]
public sealed class KeyFrameInfo
{
public float Value;
public float InTangent;
public float InWeight;
public float OutTangent;
public float OutWeight;
public float Time;
public WeightedMode WeightedMode;
// default constructor is sometimes required for (de)serialization
public KeyFrameInfo() { }
public KeyFrameInfo(Keyframe keyframe)
{
Value = keyframe.value;
InTangent = keyframe.inTangent;
InWeight = keyframe.inWeight;
OutTangent = keyframe.outTangent;
OutWeight = keyframe.outWeight;
Time = keyframe.time;
WeightedMode = keyframe.weightedMode;
}
}
// I know ... singleton .. but what choices do we have? ;)
private static AnimationCurveManager _instance;
public static AnimationCurveManager Instance
{
get
{
// lazy initialization/instantiation
if (_instance) return _instance;
_instance = FindObjectOfType<AnimationCurveManager>();
if (_instance) return _instance;
_instance = new GameObject("AnimationCurveManager").AddComponent<AnimationCurveManager>();
return _instance;
}
}
// Clips to manage e.g. reference these via the Inspector
public List<AnimationClip> clips = new List<AnimationClip>();
// every animation curve belongs to a specific clip and
// a specific property of a specific component on a specific object
// for making this easier lets simply use a combined string as key
private string CurveKey(string pathToObject, Type type, string propertyName)
{
return $"{pathToObject}:{type.FullName}:{propertyName}";
}
public List<ClipInfo> ClipCurves = new List<ClipInfo>();
private string filePath = Path.Combine(Application.streamingAssetsPath, "AnimationCurves.dat");
private void Awake()
{
if (_instance && _instance != this)
{
Debug.LogWarning("Multiple Instances of AnimationCurveManager! Will ignore this one!", this);
return;
}
_instance = this;
DontDestroyOnLoad(gameObject);
// load infos on runtime
LoadClipCurves();
}
#if UNITY_EDITOR
// Call this from the ContextMenu (or later via editor script)
[ContextMenu("Save Animation Curves")]
private void SaveAnimationCurves()
{
ClipCurves.Clear();
foreach (var clip in clips)
{
var curveInfos = new List<CurveInfo>();
ClipCurves.Add(new ClipInfo(clip, curveInfos));
foreach (var binding in AnimationUtility.GetCurveBindings(clip))
{
var key = CurveKey(binding.path, binding.type, binding.propertyName);
var curve = AnimationUtility.GetEditorCurve(clip, binding);
curveInfos.Add(new CurveInfo(key, curve));
}
}
// create the StreamingAssets folder if it does not exist
try
{
if (!Directory.Exists(Application.streamingAssetsPath))
{
Directory.CreateDirectory(Application.streamingAssetsPath);
}
}
catch (IOException ex)
{
Debug.LogError(ex.Message);
}
// create a new file e.g. AnimationCurves.dat in the StreamingAssets folder
var json = JsonConvert.SerializeObject(ClipCurves);
File.WriteAllText(filePath, json);
AssetDatabase.Refresh();
}
#endif
private void LoadClipCurves()
{
if (!File.Exists(filePath))
{
Debug.LogErrorFormat(this, "File \"{0}\" not found!", filePath);
return;
}
var fileStream = new FileStream(filePath, FileMode.Open);
var json = File.ReadAllText(filePath);
ClipCurves = JsonConvert.DeserializeObject<List<ClipInfo>>(json);
}
// now for getting a specific clip's curves
public AnimationCurve GetCurve(AnimationClip clip, string pathToObject, Type type, string propertyName)
{
// either not loaded yet or error -> try again
if (ClipCurves == null || ClipCurves.Count == 0) LoadClipCurves();
// still null? -> error
if (ClipCurves == null || ClipCurves.Count == 0)
{
Debug.LogError("Apparantly no clipCurves loaded!");
return null;
}
var clipInfo = ClipCurves.FirstOrDefault(ci => ci.ClipInstanceID == clip.GetInstanceID());
// does this clip exist in the dictionary?
if (clipInfo == null)
{
Debug.LogErrorFormat(this, "The clip \"{0}\" was not found in clipCurves!", clip.name);
return null;
}
var key = CurveKey(pathToObject, type, propertyName);
var curveInfo = clipInfo.CurveInfos.FirstOrDefault(c => string.Equals(c.PathKey, key));
// does the curve key exist for the clip?
if (curveInfo == null)
{
Debug.LogErrorFormat(this, "The key \"{0}\" was not found for clip \"{1}\"", key, clip.name);
return null;
}
var keyframes = new Keyframe[curveInfo.Keys.Count];
for (var i = 0; i < curveInfo.Keys.Count; i++)
{
var keyframe = curveInfo.Keys[i];
keyframes[i] = new Keyframe(keyframe.Time, keyframe.Value, keyframe.InTangent, keyframe.OutTangent, keyframe.InWeight, keyframe.OutWeight)
{
weightedMode = keyframe.WeightedMode
};
}
var curve = new AnimationCurve(keyframes)
{
postWrapMode = curveInfo.PostWrapMode,
preWrapMode = curveInfo.PreWrapMode
};
// otherwise finally return the AnimationCurve
return curve;
}
}
Then you can do something like e.e.
AnimationCurve originalCurve = AnimationCurvesManager.Instance.GetCurve(
clip,
"some/relative/GameObject",
typeof<SomeComponnet>,
"somePropertyName"
);
the second parameter pathToObject is an empty string if the property/component is attached to the root object itself. Otherwise it is given in the hierachy path as usual for Unity like e.g. "ChildName/FurtherChildName".
Now you can change the values and assign a new curve on runtime.
Assigning new curve on runtime
On runtime you can use animator.runtimeanimatorController in order to retrieve a RuntimeAnimatorController reference.
It has a property animationClips which returns all AnimationClips assigned to this controller.
You could then use e.g. Linq FirstOrDefault in order to find a specific AnimationClip by name and finally use AnimationClip.SetCurve to assign a new animation curve to a certain component and property.
E.g. something like
// you need those of course
string clipName;
AnimationCurve originalCurve = AnimationCurvesManager.Instance.GetCurve(
clip,
"some/relative/GameObject",
typeof<SomeComponnet>,
"somePropertyName"
);
// TODO
AnimationCurve newCurve = SomeMagic(originalCurve);
// get the animator reference
var animator = animatorObject.GetComponent<Animator>();
// get the runtime Animation controller
var controller = animator.runtimeAnimatorController;
// get all clips
var clips = controller.animationClips;
// find the specific clip by name
// alternatively you could also get this as before using a field and
// reference the according script via the Inspector
var someClip = clips.FirstOrDefault(clip => string.Equals(clipName, clip.name));
// was found?
if(!someClip)
{
Debug.LogWarningFormat(this, "There is no clip called {0}!", clipName);
return;
}
// assign a new curve
someClip.SetCurve("relative/path/to/some/GameObject", typeof(SomeComponnet), "somePropertyName", newCurve);
Note: Typed on smartphone so no warranty! But I hope the idea gets clear...
Also checkout the example in AnimationClip.SetCurve → You might want to use the Animation component instead of an Animator in your specific use case.

Powershell - How to print rendered HTML to a network printer? [duplicate]

I would like to create a function in C# that takes a specific webpage and coverts it to a JPG image from within ASP.NET. I don't want to do this via a third party or thumbnail service as I need the full image. I assume I would need to somehow leverage the webbrowser control from within ASP.NET but I just can't see where to get started. Does anyone have examples?
Ok, this was rather easy when I combined several different solutions:
These solutions gave me a thread-safe way to use the WebBrowser from ASP.NET:
http://www.beansoftware.com/ASP.NET-Tutorials/Get-Web-Site-Thumbnail-Image.aspx
http://www.eggheadcafe.com/tutorials/aspnet/b7cce396-e2b3-42d7-9571-cdc4eb38f3c1/build-a-selfcaching-asp.aspx
This solution gave me a way to convert BMP to JPG:
Bmp to jpg/png in C#
I simply adapted the code and put the following into a .cs:
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using System.Windows.Forms;
public class WebsiteToImage
{
private Bitmap m_Bitmap;
private string m_Url;
private string m_FileName = string.Empty;
public WebsiteToImage(string url)
{
// Without file
m_Url = url;
}
public WebsiteToImage(string url, string fileName)
{
// With file
m_Url = url;
m_FileName = fileName;
}
public Bitmap Generate()
{
// Thread
var m_thread = new Thread(_Generate);
m_thread.SetApartmentState(ApartmentState.STA);
m_thread.Start();
m_thread.Join();
return m_Bitmap;
}
private void _Generate()
{
var browser = new WebBrowser { ScrollBarsEnabled = false };
browser.Navigate(m_Url);
browser.DocumentCompleted += WebBrowser_DocumentCompleted;
while (browser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
browser.Dispose();
}
private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// Capture
var browser = (WebBrowser)sender;
browser.ClientSize = new Size(browser.Document.Body.ScrollRectangle.Width, browser.Document.Body.ScrollRectangle.Bottom);
browser.ScrollBarsEnabled = false;
m_Bitmap = new Bitmap(browser.Document.Body.ScrollRectangle.Width, browser.Document.Body.ScrollRectangle.Bottom);
browser.BringToFront();
browser.DrawToBitmap(m_Bitmap, browser.Bounds);
// Save as file?
if (m_FileName.Length > 0)
{
// Save
m_Bitmap.SaveJPG100(m_FileName);
}
}
}
public static class BitmapExtensions
{
public static void SaveJPG100(this Bitmap bmp, string filename)
{
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
bmp.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParameters);
}
public static void SaveJPG100(this Bitmap bmp, Stream stream)
{
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
bmp.Save(stream, GetEncoder(ImageFormat.Jpeg), encoderParameters);
}
public static ImageCodecInfo GetEncoder(ImageFormat format)
{
var codecs = ImageCodecInfo.GetImageDecoders();
foreach (var codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
// Return
return null;
}
}
And can call it as follows:
WebsiteToImage websiteToImage = new WebsiteToImage( "http://www.cnn.com", #"C:\Some Folder\Test.jpg");
websiteToImage.Generate();
It works with both a file and a stream. Make sure you add a reference to System.Windows.Forms to your ASP.NET project. I hope this helps.
UPDATE: I've updated the code to include the ability to capture the full page and not require any special settings to capture only a part of it.
Good solution by Mr Cat Man Do.
I've needed to add a row to suppress some errors that came up in some webpages
(with the help of an awesome colleague of mine)
private void _Generate()
{
var browser = new WebBrowser { ScrollBarsEnabled = false };
browser.ScriptErrorsSuppressed = true; // <--
browser.Navigate(m_Url);
browser.DocumentCompleted += WebBrowser_DocumentCompleted;
}
...
Thanks Mr Do
Here is my implementation using extension methods and task factory instead thread:
/// <summary>
/// Convert url to bitmap byte array
/// </summary>
/// <param name="url">Url to browse</param>
/// <param name="width">width of page (if page contains frame, you need to pass this params)</param>
/// <param name="height">heigth of page (if page contains frame, you need to pass this params)</param>
/// <param name="htmlToManipulate">function to manipulate dom</param>
/// <param name="timeout">in milliseconds, how long can you wait for page response?</param>
/// <returns>bitmap byte[]</returns>
/// <example>
/// byte[] img = new Uri("http://www.uol.com.br").ToImage();
/// </example>
public static byte[] ToImage(this Uri url, int? width = null, int? height = null, Action<HtmlDocument> htmlToManipulate = null, int timeout = -1)
{
byte[] toReturn = null;
Task tsk = Task.Factory.StartNew(() =>
{
WebBrowser browser = new WebBrowser() { ScrollBarsEnabled = false };
browser.Navigate(url);
browser.DocumentCompleted += (s, e) =>
{
var browserSender = (WebBrowser)s;
if (browserSender.ReadyState == WebBrowserReadyState.Complete)
{
if (htmlToManipulate != null) htmlToManipulate(browserSender.Document);
browserSender.ClientSize = new Size(width ?? browser.Document.Body.ScrollRectangle.Width, height ?? browser.Document.Body.ScrollRectangle.Bottom);
browserSender.ScrollBarsEnabled = false;
browserSender.BringToFront();
using (Bitmap bmp = new Bitmap(browserSender.Document.Body.ScrollRectangle.Width, browserSender.Document.Body.ScrollRectangle.Bottom))
{
browserSender.DrawToBitmap(bmp, browserSender.Bounds);
toReturn = (byte[])new ImageConverter().ConvertTo(bmp, typeof(byte[]));
}
}
};
while (browser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
browser.Dispose();
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
tsk.Wait(timeout);
return toReturn;
}
There is a good article by Peter Bromberg on this subject here. His solution seems to do what you need...
The solution is perfect, just needs a fixation in the line which sets the WIDTH of the image. For pages with a LARGE HEIGHT, it does not set the WIDTH appropriately:
//browser.ClientSize = new Size(browser.Document.Body.ScrollRectangle.Width, browser.Document.Body.ScrollRectangle.Bottom);
browser.ClientSize = new Size(1000, browser.Document.Body.ScrollRectangle.Bottom);
And for adding a reference to System.Windows.Forms, you should do it in .NET-tab of ADD REFERENCE instead of COM -tab.
You could use WatiN to open a new browser, then capture the screen and crop it appropriately.

Eclipse RCP console

I have integrated a console to my rcp application but I would like to display some important informations in red colour rather than in blue but I don't know how to do it(can I add some if conditions?)this the class for my console view .please help me to solve my problem.
public DebugConsole()
{
super("stdio/stderr", null);
outMessageStream = newMessageStream();
outMessageStream.setColor(Display.getCurrent().getSystemColor(
SWT.COLOR_BLUE));
errMessageStream = newMessageStream();
errMessageStream.setColor(Display.getCurrent().getSystemColor(
SWT.COLOR_RED));
System.setOut(new PrintStream(outMessageStream));
System.setErr(new PrintStream(errMessageStream));
}
Suggest the below.
From your code if newMessageStream() method returns valid MessageConsoleStream then all System.out.print messages will be displayed in BLUE colour and System.err.print messages will be displayed in RED colour
Use ConsolePatternListener to display matching messages in
different colour on console.
Change stream colour before you use System.out.print or System.err.print statements.
In the last two lines of you code make PrintSteam instances as class public fields(or private with getter and setters) and get these streams and set colour. Remember to reset the colour back after you used System.out.print or System.err.print statement.
public class DebugConsole {
private PrintStream outStream;
private PrintStream errStream;
public DebugConsole() {
super("stdio/stderr", null);
outMessageStream = newMessageStream();
outMessageStream.setColor(Display.getCurrent().getSystemColor(SWT.COLOR_BLUE));
errMessageStream = newMessageStream();
errMessageStream.setColor(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
outStream = new PrintStream(outMessageStream);
errStream = new PrintStream(errMessageStream);
System.setOut(outStream);
System.setErr(errStream);
}
public PrintStream getOutStream() {
return outStream;
}
public void setOutStream(PrintStream outStream) {
this.outStream = outStream;
}
public PrintStream getErrStream() {
return errStream;
}
public void setErrStream(PrintStream errStream) {
this.errStream = errStream;
}
}
Test class:
public class TestConsole {
public static void main(String[] args) {
DebugConsole console = new DebugConsole();
MessageConsoleStream errStream = (MessageConsoleStream)console.getErrStream();
Color oldColor = errStream.getColor();
errStream.setColor(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GREEN));
//All the below message will be displayed in green color
System.err.println("This is in green color");
System.err.println("This is in green color");
//Reset color back
errStream.setColor(oldColor);
//Do the same for output stream
}
}
Or Use Grep console Plugin See
here

CQ5 image resizing from DAM

I am looking to resize image from the DAM, my image path is stored in pathfield which direclty links to DAM asset.
Where image is "/content/dam/....jpg";
I have access to DAM path, I need to get this image resized and displayed using selector.
I tried the code using the foundation image component, it didn't work for me.
Resource rsc = resourceResolver.getResource(image);
Image img3 = new Image(rsc);
img3.setSrc(img3.getPath());
img3.setSelector(".myselector");
img3.setFileReference(image);
img3.draw(out);
If you want to use a selector you will need to create a servlet for it that extends the AbstractImageServlet. You would start out with something like this:
#Component
#Service
#Properties({
#Property(name="sling.servlet.resourceTypes", value="sling/servlet/default"),
#Property(name="sling.servlet.selectors", value="resize"),
#Property(name="sling.servlet.extensions", value={"jpg", "png", "gif"}),
#Property(name="sling.servlet.methods", value="GET")
})
public class ImageResizeServlet extends AbstractImageServlet {
//... code.
}
sling.servlet.selectors would be the selector name you would want to set. For example:
//in the servlet
#Property(name="sling.servlet.selectors", value="resize")
//in the jsp
image.setSelector("resize");
Within your class, you would want to override the writeLayer method. Something like this:
#Override
protected void writeLayer(SlingHttpServletRequest req,
SlingHttpServletResponse resp,
AbstractImageServlet.ImageContext c, Layer layer)
throws IOException, RepositoryException {
// set new width and height
int width = 100;
int height = 100;
Image image = new Image(c.resource);
if (!image.hasContent() || width == 0) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// get style and set constraints
image.loadStyleData(c.style);
// get pure layer
layer = image.getLayer(true, true, true);
Layer newLayer = ImageHelper.resize(layer, new Dimension(width, 0), null, null);
if (newLayer != null) {
layer = newLayer;
}
String mimeType = image.getMimeType();
if (ImageHelper.getExtensionFromType(mimeType) == null) {
// get default mime type
mimeType = "image/png";
}
resp.setContentType(mimeType);
layer.write(mimeType, mimeType.equals("image/gif") ? 255 : 1.0, resp.getOutputStream());
resp.flushBuffer();
}
In our custom solution we handled everything in the writeLayer method and not the createLayer method. So we overwrote createLayer.
#Override
protected Layer createLayer(AbstractImageServlet.ImageContext c)
throws RepositoryException, IOException {
// don't create the layer yet. handle everything later
return null;
}
We also overwrote createImageResource
/**
* {#inheritDoc}
*
* Override default ImageResource creation to support assets
*/
#Override
protected ImageResource createImageResource(Resource resource) {
return new Image(resource);
}
Hope that helps.