Image Filter on ROI with Java2D - java-2d

i want apply some filters [image filter] on Region Of Interest that user selected.
i need API for getting pixels of this area [polygon or freehand also Rectangle] and apply
filter.any Suggestion for this work ?

Basically, what you need to do is:
Create a BufferedImage and link it with a Graphics object
Set clipping region
Draw to this Graphics object
Apply filter on the BufferedImage object
In pseudocode:
private BufferedImage bufferedImage = new BufferedImage()
private Graphics2D graphics = bufferedImage.createGraphics()
void paint(Graphics2D input) {
graphics.clip(selectionArea.getShape())
upperCanvas.paint(graphics)
BufferedImageOp op
bufferedImage = op.filter(bufferedImage, new BufferedImage())
input.drawImage(bufferedImage)
}
For applying filter, see java.awt.image
As you can see, this can be done in java2d, but the API is quite complicated. If you're interested I can suggest pulpcore as a replacement framework. It includes several predefine filters and a one-line-API for apply them. See demo. Also includes a Java2DSprite class for easy porting between pulpcore and java2d.

Related

How to rotate a specific text in a pdf which is already present in the pdf using itext or pdfbox?

I know we can insert text into pdf with rotation using itext. But I want to rotate the text which is already present in the pdf.
Before.pdf
After.pdf
First of all, in your question you only talk about how to rotate a specific text but in your example you additionally rotate a red rectangle. This answer focuses on rotating text. The process of guessing which graphics might be related to the text and, therefore, probably should be rotated along, is a topic in its own right.
You also mention you are looking for a solution using itext or pdfbox and used the tags itext, pdfbox, and itext7. For this answer I chose iText 7.
You did not explain what kind of text pieces you want to rotate but offered a representative example PDF. In that example I saw that the text to rotate was drawn using a single text showing instruction which is the only such instruction in the encompassing text object in the page content stream. To keep the code in the answer simple, therefore, I can assume the text to rotate is drawn in a consecutive sequence of text showing instructions in a text object in the page content stream framed by instructions that are not text showing ones. This is a generalization of your case.
Furthermore, you did not mention the center of rotation. Based on your example files I assume it to be approximately the start of the base line of the text to rotate.
A Simple Implementation
When editing PDF content streams it is helpful to know the current graphics state at each instruction, e.g. to properly recognize the text drawn by a text showing operation one needs to know the current font to map the character codes to Unicode characters. The text extraction framework in iText already contains code to follow the graphics state. Thus, in this answer a base PdfCanvasEditor class has been developed on top of the text extraction framework.
We can base a solution for the task at hand on that class after a small extension; that class originally sets the text extraction event listener to a dummy implementation but here we'll need a custom one. So we need to add an additional constructor that accepts such a custom event listener as parameter:
public PdfCanvasEditor(IEventListener listener)
{
super(listener);
}
(Additional PdfCanvasEditor constructor)
Based on this extended PdfCanvasEditor we can implement the task by inspecting the existing page content stream instruction by instruction. For a sequence of consecutive text showing instructions we retrieve the text matrix before and after the sequence, and if the text drawn by the sequence turns out to be the text to rotate, we insert an instruction before that sequence setting the initial text matrix to a rotated version of itself and another one after that sequence setting the text matrix back to what it was there originally.
Our implementation LimitedTextRotater accepts a Matrix representing the desired rotation and a Predicate matching the string to rotate.
public class LimitedTextRotater extends PdfCanvasEditor {
public LimitedTextRotater(Matrix rotation, Predicate<String> textMatcher) {
super(new TextRetrievingListener());
((TextRetrievingListener)getEventListener()).limitedTextRotater = this;
this.rotation = rotation;
this.textMatcher = textMatcher;
}
#Override
protected void write(PdfCanvasProcessor processor, PdfLiteral operator, List<PdfObject> operands) {
String operatorString = operator.toString();
if (TEXT_SHOWING_OPERATORS.contains(operatorString)) {
recentTextOperations.add(new ArrayList<>(operands));
} else {
if (!recentTextOperations.isEmpty()) {
boolean rotate = textMatcher.test(text.toString());
if (rotate)
writeSetTextMatrix(processor, rotation.multiply(initialTextMatrix));
for (List<PdfObject> recentOperation : recentTextOperations) {
super.write(processor, (PdfLiteral) recentOperation.get(recentOperation.size() - 1), recentOperation);
}
if (rotate)
writeSetTextMatrix(processor, finalTextMatrix);
recentTextOperations.clear();
text.setLength(0);
initialTextMatrix = null;
}
super.write(processor, operator, operands);
}
}
void writeSetTextMatrix(PdfCanvasProcessor processor, Matrix textMatrix) {
PdfLiteral operator = new PdfLiteral("Tm\n");
List<PdfObject> operands = new ArrayList<>();
operands.add(new PdfNumber(textMatrix.get(Matrix.I11)));
operands.add(new PdfNumber(textMatrix.get(Matrix.I12)));
operands.add(new PdfNumber(textMatrix.get(Matrix.I21)));
operands.add(new PdfNumber(textMatrix.get(Matrix.I22)));
operands.add(new PdfNumber(textMatrix.get(Matrix.I31)));
operands.add(new PdfNumber(textMatrix.get(Matrix.I32)));
operands.add(operator);
super.write(processor, operator, operands);
}
void eventOccurred(TextRenderInfo textRenderInfo) {
Matrix textMatrix = textRenderInfo.getTextMatrix();
if (initialTextMatrix == null)
initialTextMatrix = textMatrix;
finalTextMatrix = new Matrix(textRenderInfo.getUnscaledWidth(), 0).multiply(textMatrix);
text.append(textRenderInfo.getText());
}
static class TextRetrievingListener implements IEventListener {
#Override
public void eventOccurred(IEventData data, EventType type) {
if (data instanceof TextRenderInfo) {
limitedTextRotater.eventOccurred((TextRenderInfo) data);
}
}
#Override
public Set<EventType> getSupportedEvents() {
return null;
}
LimitedTextRotater limitedTextRotater;
}
final static List<String> TEXT_SHOWING_OPERATORS = Arrays.asList("Tj", "'", "\"", "TJ");
final Matrix rotation;
final Predicate<String> textMatcher;
final List<List<PdfObject>> recentTextOperations = new ArrayList<>();
final StringBuilder text = new StringBuilder();
Matrix initialTextMatrix = null;
Matrix finalTextMatrix = null;
}
(LimitedTextRotater)
You can apply it to a document like this:
try ( PdfReader pdfReader = new PdfReader(...);
PdfWriter pdfWriter = new PdfWriter(...);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter) )
{
PdfCanvasEditor editor = new LimitedTextRotater(new Matrix(0, -1, 1, 0, 0, 0), text -> true);
for (int i = 1; i <= pdfDocument.getNumberOfPages(); i++){
editor.editPage(pdfDocument, i);
}
}
(RotateText test testBeforeAkhilNagaSai)
The Predicate used here is text -> true which matches any text. In case of your example PDF that is ok as the text to rotate is the only text. In general you might want a more specific check, e.g. text -> text.equals("The text to be rotated"). In general try not to be too specific, though, as the extracted text might slightly deviate from expectations, e.g. by extra spaces.
The result:
As you can see the text is rotated. In contrast to your After.pdf, though, the red rectangle is not rotated. The reason is - as already mentioned at the start - that that rectangle in no way is part of the text.
Some Ideas
First of all, there are ports of the PdfCanvasEditor to iText 5 (the PdfContentStreamEditor in this answer) and PDFBox (the PdfContentStreamEditor in this answer). Thus, if you eventually prefer to switch to either of these PDF libraries, you can create equivalent implementations.
Then, if the assumption that the text to rotate is drawn in a consecutive sequence of text showing instructions in a text object in the page content stream framed by instructions that are not text showing ones does not hold for you, you can generalize the implementation here somewhat. Have a look at the SimpleTextRemover in this answer for inspiration which is based on the PdfContentStreamEditor for iText 5. Here also texts that start somewhere in one text showing instruction and end somewhere in another one are processed which requires some more detailed data keeping and splitting of existing text drawing instructions.
Also, if you want to rotate graphics along with the text that a human viewer might consider associated with it (like the red rectangle in your example file), you can try and extend the example accordingly, e.g. by also extracting the coordinates of the rotated text and in a second run trying to guess which graphics around those coordinates are related and rotating the graphics along. This is not trivial, though.
Finally note that the Matrix provided in the constructor is not limited to rotations, it can represent an arbitrary affine transformation. So instead of rotating text you can also move it or scale it or skew it, ...

Get Contents Of Image Class From AutomationElement

I am walking controls in a third party app that contains images. The automation element returns the class name Image, Any ideas on how I can get the contents of that Image as a bitmap object, or even bytes?
Although this question is old, I wanted to add an answer as I came across this problem as well.
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Automation;
namespace AutomationElementExtension
{
public static class AutomationElementExtension
{
public static Bitmap ToBitmap(this AutomationElement automationElement)
{
var boundingRectangle = automationElement.Current.BoundingRectangle;
var bitmap = new Bitmap(Convert.ToInt32(boundingRectangle.Width), Convert.ToInt32(boundingRectangle.Height), PixelFormat.Format32bppArgb);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.CopyFromScreen(Convert.ToInt32(boundingRectangle.X), Convert.ToInt32(boundingRectangle.Y), Point.Empty.X, Point.Empty.Y, bitmap.Size);
}
return bitmap;
}
}
}
You can then get the image as a bitmap by calling it as
var bitmap = myAutomationElement.ToBitmap();
This discussion can be useful: Capturing an image behind a rectangle .
Just use BoundingRectangle property of the AutomationElement to make a snapshot.

How to customize the labels of an Infragistics Ultrachart?

I am trying to customize the series labels of the X axis of a linear ultrachart using vb.net.
I looked into the documentation from Infragistics and found that I could use this code:
UltraChart.Axis.Y.Labels.SeriesLabels.FormatString = "<Item_Label>"
A description of the types of labels available can be seen here.
However, I'm not getting the result I expected. I get "Row#1" and I want to get only the "1".
I've tried the approach used in the first reply of this post in Infragistics forums, which consists of using an hashtable with the customized labels. The code used there is the following (in C#):
Hashtable labelHash = new Hashtable();
labelHash.Add("CUSTOM", new MyLabelRenderer());
ultraChart1.LabelHash = labelHash;
xAxis.Labels.ItemFormatString = "<CUSTOM>";
public class MyLabelRenderer : IRenderLabel
{
public string ToString(Hashtable context)
{
string label = (string)context["ITEM_LABEL"];
int row = (int)context["DATA_ROW"];
int col = (int)context["DATA_COLUMN"];
//use row, col, current label's text or other info inside the context to get the axis label.
//the string returned here will replace the current label.
return label;
}
}
This approach didn't work either.
I am using Infragistics NetAdvantage 2011.1.
Anyone has any idea how to customize these labels in order to obtain the number after "Row#"?
There are different approaches to solve this task. One possible solution could be if you are using FillSceneGraph event. By this way you could get your TEXT primitives and modify it. For example:
private void ultraChart1_FillSceneGraph(object sender, Infragistics.UltraChart.Shared.Events.FillSceneGraphEventArgs e)
{
foreach (Primitive pr in e.SceneGraph)
{
if (pr is Text &&((Text)pr).labelStyle.Orientation == TextOrientation.VerticalLeftFacing )
{
pr.PE.Fill = Color.Red;
((Text)pr).SetTextString("My custom labels");
}
}
}
OK. I`ll try to explain more deeply about FormatString property.
When you are using this property, you could determinate which information to be shown (for example: Items values or Data Values or Series Values). Of course there are option to use your custom FormatString.
For example:
axisX2.Labels.ItemFormat=AxisItemLabelFormat.Custom;
axisX2.Labels.ItemFormatString ="";
In this case we have labels which represent Date on your X axis, so if you are using these two properties, you are able to determinate the Date format (for example dd/MM/yyyy or MM/ddd/yy). In your scenario you have string values on your X axis. If you are not able to modify these strings values at lower level (for example in your database, through TableAdapters SQL query, DataSet, i.e. before to set your DataSource to our UltraChart), then you could use FillSceneGraph event and modify your Text primitives. More details about this event you could find at http://help.infragistics.com/Help/NetAdvantage/WinForms/2013.1/CLR4.0/html/Chart_Modify_Scene_Graph_Using_FillSceneGraph_Event.html If you need a sample or additional assistance, please do not hesitate to create a new forum thread in our web site - http://www.infragistics.com/community/forums/
I`ll be glad to help you.

Pragmatically convert PDF images to 8 bit

I have a set of PDFs in normal RGB colour. They would benefit from conversion to 8 bit to reduce file sizes. Are there any APIs or tools that would allow me to do this whilst retaining non-raster elements in the PDF?
This is a fun one. Atalasoft dotImage with the PDF Rasterizer and dotPdf can do this (disclaimer: I work for Atalasoft and wrote most of the PDF tools). I'd start off first by finding candidate pages:
List<int> GetCandidatePages(Stream pdf, string password)
{
List<int> retVal = new List<int>();
using (PageCollection pages = new PageCollection(pdf, password)) {
for (int i=0; i < pages.Count; i++) {
if (pages[i].SingleImageOnly())
retVal.Add(i);
}
}
pdf.Seek(0, SeekOrigin.Begin); // restore file pointer
return retVal;
}
Next, I'd rasterize only those pages, turning them into 8-bit images, but to keep things efficient, I'd use an ImageSource which manages memory well:
public class SelectPageImageSource : RandomAccessImageSource {
private List<int> _pages;
private Stream _stm;
public SelectPageImageSource(Stream stm, List<int> pages)
{
_stm = stm;
_pages = pages;
}
protected override ImageSourceNode LowLevelAcquire(int index)
{
PdfDecoder decoder = new PdfDecoder();
_stm.Seek(0, SeekOrigin.Begin);
AtalaImage image = PdfDecoder.Read(_stm, _pages[index], null);
// change to 8 bit
if (image.PixelFormat != PixelFormat.Pixel8bppIndexed) {
AtalaImage changed = image.GetChangedPixelFormat(PixelFormat.Pixel8bppIndexed);
image.Dispose();
image = changed;
}
return new FileReloader(image, new PngEncoder());
}
protected override int LowLevelTotalImages() { return _pages.Count; }
}
Next you need to create a new PDF from this:
public void Make8BitImagePdf(Stream pdf, Stream outPdf, List<int> pages)
{
PdfEncoder encoder = new PdfEncoder();
SelectPageImageSource source = new SelectPageImageSource(pdf, pages);
encoder.Save(outPdf, source, null);
}
Next you need to replace the original pages with the new ones:
public void ReplaceOriginalPages(Stream pdf, Stream image8Bit, Stream outPdf, List<int> pages)
{
PdfDocument docOrig = new PdfDocument(pdf);
PdfDocument doc8Bit = new PdfDocument(image8Bit);
for (int i=0; i < pages.Count; i++) {
docOrig.Pages[pages[i]] = doc8Bit[i];
}
docOrig.Save(outPdf); // this is your final
}
This will do what you want, more or less. The less-than ideal bit of this is that the image pages have been rasterized, which is probably not what you want. The nice thing is that just by rasterizing, generating output is easy, but it might not be at the resolution of the original image. This can be done, but it is significantly more work in that you need to extract the image from SingleImageOnly pages and then change their pixel format. The problem with this is that SingleImageOnly does NOT imply that the image fits the entire page, nor does it imply that the image is placed in any particular location. In addition to the PixelFormat change (actually, before the change), you would want to apply the matrix that is used to place the image on the page to the image itself, and use PdfEncoder with an appropriate set of margins and the original page size to get the image where it should be. This is all cut-and dried, but it is a substantial amount of code.
There is another approach that might also work using our PDF generation API. It involves opening the document and swapping out the image resources for the document with 8-bit ones. This is also doable, but is not entirely trivial. You would do something like this:
public void ReplaceImageResources(Stream pdf, Stream outPdf, List<int> pages)
{
PdfGeneratedDocument doc = new PdfGeneratedDocument(pdf);
doc.Resources.Images.Compressors.Insert(0, new AtalaImageCompressor());
foreach (int page in pages) {
// GetSinglePageImage uses PageCollection, as above, to
// pull a single image from the page (no need to use the matrix)
// then converts it to 8 bpp indexed and returns it or null if it
// is already 8 bpp indexed (or 4bpp or 1bpp).
using (AtalaImage image = GetSinglePageImage(pdf, page)) {
if (image == null) continue;
foreach (string resName in doc.Pages[page].ImportedImages) {
doc.Resources.Images.Remove(resName);
doc.Resources.Images.Add(resName, image);
break;
}
}
}
doc.Save(outPdf);
}
As I said, this is tricky - the PDF generation suite was made for making new PDFs from whole cloth or adding new pages to an existing PDF (in the future, we want to add full editing). But PDF manages all of its images as resources within the document and we have the ability to replace those resources entirely. So to make life easier, we add an ImageCompressor to the Image resource collection that handles AtalaImage objects and remove the existing image resources and replace them with the new ones.
Now I'm going to do something that you probably won't see any vendor do when talking about their own products - I'm going to be critical of it on a number of levels. First, it isn't super cheap. Sorry. You might get sticker shock when you look at the price, but the price includes technical support from a staff that is honestly second to none.
You can probably do a lot of this with iTextPdf Sharp or the Bit Miracle's Docotic PDF library or Tall Components PDF libraries. The latter two also cost money. Bit Miracle's engineers have proven to be pretty helpful and you're likely to see them here (HI!). Maybe they can help you out too. iTextPdfSharp is problematic in that you really need to understand the PDF spec to do the right thing or you're likely to output garbage PDF - I've done this experiment with my own library side-by-side with iTextPdfSharp and found a number of pain points for common tasks that require an in-depth knowledge of the PDF spec to fix. I tried to make decisions in my high-level tools such that you didn't need to know the PDF spec nor did you need to worry about creating bad PDF.
I don't particularly like the fact that there are several apparently different tools in our code base that do similar things. PageCollection is part of our PDF rasterizer for historical reasons. PdfDocument is made strictly for manipulating pages and tries to be lightweight and stingy with memory. PdfGeneratedDocument is made for manipulating/creating page content. PdfDecoder is for generating raster images from existing PDF. PdfEncoder is for generating image-only PDF from images. It can be daunting to have all these apparently overlapping niche tools, but there is a logic to them and their relationship to each other.

SharpDX: Enabling BlendState

I'm trying to get the "SharpDX.Direct3D11.DeviceContext.OutputMerger.Blendstate" to work. Without this, i have nice scene (Polygones with textures on it, for a Spaceshooter). I've done OpenGL Graphics in the past three years, so i thought it might be as simple as in OpenGL - just enable Blending and set the right Dst/Src Modes. But if i set a new BlendStateDescription, all Output is Black, even if "RenderTarget[x].IsBlendEnabled" is set to "false".
I searched for a tutorial or something, and find one - but it uses effects. So my question is simple - do i have to use technique's and effects in SharpDX? No other way left for simple blending?
This is what i've done:
mBackBuffer = Texture2D.FromSwapChain<Texture2D>(mSwapChain, 0);
mRenderView = new RenderTargetView(mDevice, mBackBuffer);
mContext.OutputMerger.SetTargets(mDepthStencilView, mRenderView);
mContext.OutputMerger.SetBlendState(new BlendState(mDevice, new BlendStateDescription()), new SharpDX.Color4(1.0f), -1);
mContext.OutputMerger.BlendState.Description.RenderTarget[0].IsBlendEnabled = true;
mContext.OutputMerger.BlendState.Description.RenderTarget[0].SourceBlend = BlendOption.SourceAlpha;
mContext.OutputMerger.BlendState.Description.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha;
mContext.OutputMerger.BlendState.Description.RenderTarget[0].BlendOperation = BlendOperation.Add;
mContext.OutputMerger.BlendState.Description.RenderTarget[0].SourceAlphaBlend = BlendOption.One;
mContext.OutputMerger.BlendState.Description.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero;
mContext.OutputMerger.BlendState.Description.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add;
mContext.OutputMerger.BlendState.Description.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All;
And, even if just simply do:
mContext.OutputMerger.SetBlendState(new BlendState(mDevice, new BlendStateDescription()), new SharpDX.Color4(1.0f), -1);
mContext.OutputMerger.BlendState.Description.RenderTarget[0].IsBlendEnabled = false;
ouput is all black.. maybe i just have to change something in the pixel shaders?
All resource in Direct3D11 are immutable, so when you are creating the new Blendstate(mDevice, new BlendStateDescription()), you cannot change the description later.
The normal workflow is:
var blendDescription = new BlendDescription();
blendDescription.RenderTarget[0].IsBlendEnabled = .. // set all values
[...]
var blendState = new BlendState(device, blendDescription);
context.OutputMerger.SetBlendState(blendState, ...);
Also resource objects need to be stored somewhere and disposed when you are completely done with them (most of the time for blendstates, at the end of your application), otherwise you will get memory leaks.
I advice you to look more closely at some Direct3D11 C++ samples when you are not sure about the API usage. Also, I recommend you to read a book like "Introduction to 3D Game Programming with DirectX 11" by Frank.D.Luna which is perfect to begin and learn the Direct3D11 API.