reneschulte / writeablebitmapex Goto Github PK
View Code? Open in Web Editor NEWCollection of extension methods for the XAML WriteableBitmap
License: MIT License
Collection of extension methods for the XAML WriteableBitmap
License: MIT License
If you have an image with some picture on it and you FillRectangle on it with using a Color.FromArgb(...), the opacity of the color isn't used. It draws using zero opacity (solid color).
With WPF flavour of WriteableBitmapEx
if I do
wBitmap.Clear( Color.FromArgb(0x0, 0xFF, 0x0, 0xFF) );
on fresh created, empty, BGRA32 WritableBitmap,
I will end up with bitmap filled with 100% transparent black instead of magenta.
I would like to draw a polygon that border's color is not same as inside's color as below:
I think this it can be achieved by combining FillPolygon and DrawPolygon (create border).
However, DrawPolygon is not available in WriteableBitmapEx.
I tried to use DrawPolyline, but the result is not good, the polygon created by FillPolygon and DrawPolyline are not same.
Do you have any suggestion for me?
Thank you very much!
Im a bit of a newb to C# programming & i'm curious if its worth using WriteableBitmapEX as some videos suggest. However, I dont see it packaged for VScode, just Visual studio. Would anyone be able to package it? or is it just plug & play if I grab the correct Folder from the repo?
Hello.
DrawEllipse and DrawEllipseCentered draws a line when drawing a circle outside the image.
I think it is better not to draw out-of-range circles.
var wb = BitmapFactory.New(500, 500);
wb.DrawEllipseCentered(100, -200, 100, 100, Colors.Red); // out of image but line is drawn
wb.DrawEllipse(400, -100, 600, 100, Colors.Blue); // circle of edge
In public static void DrawLine(BitmapContext context, int pixelWidth, int pixelHeight, int x1, int y1, int x2, int y2, int color, Rect? clipRect = null) a System.AccessViolationException is thrown. It seems that there is an overflow in the index variable. Simply make the overflowing index a 64 bit integer.
Original Code
int index = x1s;
int indexBaseValue = y1 * pixelWidth;
// Walk the line!
var inc = (pixelWidth << PRECISION_SHIFT) + incx;
for (int y = y1; y <= y2; ++y)
{
pixels[indexBaseValue + (index >> PRECISION_SHIFT)] = color;
index += inc;
}
Fix
long index = x1s;
int indexBaseValue = y1 * pixelWidth;
// Walk the line!
var inc = (pixelWidth << PRECISION_SHIFT) + incx;
for (int y = y1; y <= y2; ++y)
{
pixels[indexBaseValue + (index >> PRECISION_SHIFT)] = color;
index += inc;
}
reproducing code:
var wb = BitmapFactory.New(1024, 1024);
wb.DrawLineDotted(-1, -1, 1, -1, 2, 2, Colors.Black);
Should I self-check that it is out of range?
GetBitmapContext()
The reason is that a new bitmapcontext instance is created in each extension method, and inside :
` public BitmapContext(WriteableBitmap writeableBitmap, ReadWriteMode mode)
{
_writeableBitmap = writeableBitmap;
_mode = mode;
_pixelWidth = _writeableBitmap.PixelWidth;`
.PixelWidth
raise the exception.
I have already the context, so these properties should not be called
I am successfully using your library in my UWP project.
I am using it specifically to draw a large amount of ink into a WriteableBitmap that I need to place as Source of an Image control.
I use DrawPolyline() to draw each single ink stroke, but apparently it is a little bit slow (for 900 strokes it takes 4 seconds...).
Is there a faster method?
Hi Rene,
is it possible to include a strong name for the .net-Assemblies?
I rely on strong names for the integrity of my application and that would enable me to use your library!
Thanks a lot!
In an attempt to use WriteableBitmapEx in a Windows Universal Store App written in C++, I attempted to install the nuget package but get the following message:
Could not install package 'WriteableBitmapEx 1.5.0'. You are trying to install this package into a project that targets 'native,Version=v0.0', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.
After wandering around in stack overflow, I found a link that describes how nuget supports C++ projects:
http://docs.nuget.org/consume/support-for-native-projects
Would it be possible to modify the nuget package so its compatible with C++ projects?
I have been banging my head on how to create a WriteableBitmap from a byte array. One part that is killing me is that I do not know how big the Bitmap is but that is a required constructor. So I have to create a bitmap just to get the higth and width. Then when I use FromByteArray, it just seems botched. It goes from 800k to 8000k with zero's filling in the array past 800. Utilmatly I am trying to crop an image. Any help would be much appreciated. Thanks!
` // Need to get original height and width
BitmapImage bitmap = new BitmapImage();
Task task = Task.Run(() => GetRandomStream(imageData));
task.Wait(10000);
InMemoryRandomAccessStream ms = task.Result;
bitmap.SetSource(ms);
// Create the WriteableBitmap
WriteableBitmap wb = new WriteableBitmap(bitmap.PixelHeight, bitmap.PixelWidth);
WriteableBitmap populatedImage = wb.FromByteArray(imageData);
WriteableBitmap cropped = populatedImage.Crop(crop_x, crop_y, width, height);
return cropped.ToByteArray();`
Was trying to Flip an RGB24 in a WPF app and got an access violation. Tracked it down to BitmapContext. It calculates _length using a width as BackBufferStride / SizeOfArgb. SizeOfArgb is a constant of 4.
Above the calculation for length is a commented out check for Pbgra32 that would throw an exception.
#if WPF
//// Check if it's the Pbgra32 pixel format
//if (writeableBitmap.Format != PixelFormats.Pbgra32)
//{
// throw new ArgumentException("The input WriteableBitmap needs to have the Pbgra32 pixel format. Use the BitmapFactory.ConvertToPbgra32Format method to automatically convert any input BitmapSource to the right format accepted by this class.", "writeableBitmap");
//}
double width = _writeableBitmap.BackBufferStride / WriteableBitmapExtensions.SizeOfArgb;
_length = (int)(width * _pixelHeight);
Hi
Following case:
var bmp = BitmapFactory.New(25, 25);
bmp.FillRectangle(0, 0, 24, 24, Color.FromArgb(255, 255, 0, 0));
I expect this to have the same result as:
bmp.Clear(Color.FromArgb(255, 255, 0, 0));
Because the x1,y1,x2 and y2 parameters encompass the entire bitmap.
However, FillRectangle does not fill the pixels on the right and bottom side of the given rectangle.
Even this does not fill the entire bitmap.
bmp.FillRectangle(0, 0, 26, 26, Color.FromArgb(255, 255, 0, 0));
This is caused because the x2 and y2 parameters are clamped to the width and height of the bitmap.
In my opinion this is not correct.
Either the code must be fixed so the right and bottom sides are inclusive instead of exclusive, or the documentation of the function must be altered to describe this behaviour.
As it is now it is never possible to fill the right side or the bottom side of the bitmap.
I'm pushing my luck here but... do you think you could implement some denoising algorithm ?
Preferably Non-local mean denoising ?
thx 💟
The Resize extension method throws an exception when trying to execute it.
In my software I'm trying to perform the resize on my WriteableBitmap like so:
_writeableBitmap.Resize((int)(imageData.Width * scale), (int)(imageData.Height * scale), WriteableBitmapExtensions.Interpolation.NearestNeighbor);
However it crashes in the public unsafe static int[] Resize(int* pixels, int widthSource, int heightSource, int width, int height, Interpolation interpolation)
method in the WriteableBitmapExtensions.cs.
It happens in the inner for loop where I added comment:
int srcIdx2 = 0;
for (int y2 = 0; y2 < height; y2++)
{
for (int x2 = 0; x2 < width; x2++)
{
float sx = (float)x2 * xs;
float num8 = (float)y2 * ys;
int x3 = (int)sx;
int y3 = (int)num8;
pd[srcIdx2++] = pixels[y3 * widthSource + x3]; // The exception is thrown from this line
}
}
The exception message is:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
I'm getting a System.AccessViolationException when I try to use the Blit extension method, but I don't know why.
I don't know what info would be required here, so I'll just give the meta on the images I'm trying to combine.
Dest:
DestRect:
Source:
SourceRect:
I want to draw a translucent decal onto an existing image with a transformation. When I call BlitRender
the library replaces all colour values in the destination image with the decal's, resulting in a square hole.
I'm having to fall back on GDI rendering to work around this.
Hello, I use WriteableBitmapEx for a my project and I need a vertical font printing.
I have updated a code and want to share updates with you. If you want you could integrate it to the trunk.
public static unsafe void DrawLetterVertical(this BitmapContext context, int x0, int y0, IntRect cliprect, Color fontColor, GrayScaleLetterGlyph glyph, Boolean topToBottom)
{
if (glyph.Items == null) return;
// Use refs for faster access (really important!) speeds up a lot!
int w = context.Width;
int h = context.Height;
var pixels = context.Pixels;
int fr = fontColor.R;
int fg = fontColor.G;
int fb = fontColor.B;
int xmin = cliprect.Left;
int ymin = cliprect.Top;
int xmax = cliprect.Right;
int ymax = cliprect.Bottom;
if (xmin < 0) xmin = 0;
if (ymin < 0) ymin = 0;
if (xmax >= w) xmax = w - 1;
if (ymax >= h) ymax = h - 1;
fixed (GrayScaleLetterGlyph.Item* items = glyph.Items)
{
int itemCount = glyph.Items.Length;
GrayScaleLetterGlyph.Item* currentItem = items;
for (int i = 0; i < itemCount; i++, currentItem++)
{
int x;
int y;
if (topToBottom)
{
x = x0 - currentItem->Y;
y = y0 + currentItem->X;
}
else
{
x = x0 + currentItem->Y;
y = y0 - currentItem->X;
}
int alpha = currentItem->Alpha;
if (x < xmin || y < ymin || x > xmax || y > ymax) continue;
int color = pixels[y * w + x];
int r = ((color >> 16) & 0xFF);
int g = ((color >> 8) & 0xFF);
int b = ((color) & 0xFF);
r = (((r << 12) + (fr - r) * alpha) >> 12) & 0xFF;
g = (((g << 12) + (fg - g) * alpha) >> 12) & 0xFF;
b = (((b << 12) + (fb - b) * alpha) >> 12) & 0xFF;
pixels[y * w + x] = (0xFF << 24) | (r << 16) | (g << 8) | (b);
}
}
}
public static int DrawStringVertical(this WriteableBitmap bmp, int x0, int y0, Color fontColor, PortableFontDesc typeface, string text, Boolean topToBottom)
{
IntRect cliprect = new IntRect(new IntPoint(0, 0), new IntSize(bmp.PixelWidth, bmp.PixelHeight));
var font = GetFont(typeface);
if (text == null) return 0;
int dx = 0;
int dy = 0;
int textwi = 0;
using (var context = bmp.GetBitmapContext())
{
int dyDirection = 1;
if (topToBottom == false)
{
dyDirection = -1;
}
foreach (char ch in text)
{
if (ch == '\n')
{
if (dy > textwi) textwi = dy;
dy = 0;
dx += font.TextHeight * dyDirection;
}
if (y0 + dy <= cliprect.Bottom)
{
var letter = font.GetGrayScaleLetter(ch);
if (letter == null) continue;
context.DrawLetterVertical(x0 + dx, y0 + dy, cliprect, fontColor, letter, topToBottom);
dy += letter.Width * dyDirection;
}
}
}
if (dx > textwi) textwi = dx;
return textwi;
}`
It would be great if we can have DrawArc
like methods.
Good catch. Should be fixed with next release.
Originally posted by @teichgraf in #29 (comment)
Unfortunately, DLL version is still 1.5.2 ... :-(
I tried to resize png files using both interpolations and because they have Indexed8 Format, the library throws the following exception:
System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
Just called:
return original.Resize(width, height, WriteableBitmapExtensions.Interpolation.NearestNeighbor);
If it is an jpg theres no problem because are Format Bgr32.
Might be a workaround can be copying the pixels from an image Indexed8 to a new one Bgr32:
using (resizable.GetBitmapContext())
{
using (original.GetBitmapContext())
{
resizable.Blit(rec, original, rec);
}
}
But I'm not an expert and because the original is Indexed8 and resizable is Bgr32 when I copy the colors the result is not the expected.
The FillRectangle with a color with alpha channel != 255 doesn't affect the filled rectangle, I will aspect to drawing a Rectangle with Alpha channel (low trasparency) but it draw always alpha like 255
The [Obsolete] attribute on obsolete extension method FromStream advises use of method "BitmpaContext.FromStream", which does not exist. The attribute should instead advise use of BitmapFactory.FromStream, which does exist.
Sorry for my question as it's not an issue...
But I'm looking for an easy way that allowing a user to add basic shapes (rectangle, ellipse, ...) on a WriteabkeBitmapEx that contains a photo.
Then the shape must be moved on the area, resizable and customizable (foreground color).
I have looked to samples but I didn't found a similar case...
hi
I just follow the link of drawString implementation, but it guide me to nowhere
can you pls fix it?
thx
I found the FillEllipseCentered
draw a extra line when drawing off the bitmap bounds.
There is my test code:
bitmap.FillEllipseCentered(100, -100, 10, 10, Colors.Red);
bitmap.FillEllipseCentered(-100, 100, 10, 10, Colors.Green);
bitmap.FillEllipseCentered(700, 100, 10, 10, Colors.Blue);
bitmap.FillEllipseCentered(100, 700, 10, 10, Colors.Purple);
Expected result should be a empty bitmap.
This problem occurs on the left\bottom\top edge.
My Version: 1.5.0.0
Try to create a bitmap with (10px width , 10px height)
now draw a rectangle and a line with same dimension (< than wBitmap.lenght)
The result is a different lenght of the rectangle and line, why ?
Code example:
wBitmap = ...(10,10)
wBitmap.FillRectangle(0, 0, 5, 10, System.Windows.Media.Colors.Aquamarine);
wBitmap.DrawLine(0, 0, 5, 10, System.Windows.Media.Colors.Blue);
The blue line is one pixel longer than rectangle!
Instead drawing a line and rectangle with full lenght of the bitmap (10px) is correct.
Code example:
wBitmap.FillRectangle(0, 0, 10, 10, System.Windows.Media.Colors.Aquamarine);
wBitmap.DrawLine(0, 0, 10, 10, System.Windows.Media.Colors.Blue);
There's a bug
Using VS 2015 I have created a C# Win 10 Windows Universal App
I installed the nugget package V 1.5.0
I copied the sample code from the main page and am getting some errors:
writeableBmp = BitmapFactory.New(1, 1).FromResource("Data/flower2.png");
FromResource does not exist
int[] pixels = writeableBmp.Pixels;
Pixels does not exist
WriteableBitmapExtensions.DrawLine(pixels, w, h, 1, 2, 30, 40, myIntColor);
DrawLine does not have a version which takes an int array
writeableBmp.DrawCurve(pts, 0.5, Colors.Yellow);
Had to cast 0.5 to (float)0.5 as compiler can't convert double to float automatically
So it's not possible to draw, for example, a rectangle with a border whose thickness is more than 1 pixel
Is there a way to draw text with this?
If I attempt to do anything in WriteableBitmapEx that attempts to get a read-only BitmapContext on a WriteableBitmap that has been frozen by the Freeze()
method (such as using the Blit()
method), an InvalidOperationException is thrown from WPF's System.Windows.Freezeable.WritePreamble()
, called in WriteableBitmap's TryLock()
method, called in WriteableBitmap's Lock()
method, which is called in WriteableBitmapEx here:
WriteableBitmapEx/Source/WriteableBitmapEx/BitmapContext.cs
Lines 129 to 131 in aad8373
I know that the concept of freezing a WriteableBitmap might not make much sense, but I am trying to use a frozen WriteableBitmap because of threading issues (if not frozen, I get an exception saying that the WriteableBitmap was being accessed on a different thread than it was originally created on), and I assumed that a read-only BitmapContext would let me use a frozen WriteableBitmap.
Maybe that new v.1.5.1 on Nuget delivers new DLL with old version number (1.5.0)?
I have writeablebitmap with width and height equal to 580, i need to draw a circle in it. So i will use bmp.FillEllipseCentered(290,290,290,290,color);
I need to zoom this circle by scaling factor 2, say the radius will be 290 *2 = 580, so that i will move the scroll bar and i will be able to see the curves of the circle by changing the center position. bmp.FillEllipseCentered(580-x,580-y,580,580,color);
When i zooming again i.e (bmp.FillEllipseCentered(1160-x,1160-y,1160,1160,color);), circle is not coming i was getting some lines at the end region. Is there any way to achieve this fill circle when it is outside of boundary.
Is there a UWP project available for WriteableBitmapEx?
None of the projects available under Source is a UWP project.
https://github.com/teichgraf/WriteableBitmapEx/tree/master/Source
This issue is different pattern from #46.
reproducing code:
var wb = BitmapFactory.New(500, 500);
wb.DrawLineDotted(0, 0, 100, 0, 1, 1, Colors.Red);
When i try to draw on bitmap in parallel, i got this exception:
The calling thread cannot access this object because a different thread owns it
Code:
Parallel.For(0, 100, i =>
{
WriteableBitmapExtensions.FillEllipseCentered(buffer, 0, 0, 100, 100, System.Windows.Media.Color.FromRgb(125, 125, 125));
});
Is it possible draw geometry elements in parallel like what i tried using WriteableBitmapEx?
I was not getting the results I expected when passing a rectangular (not square) pen in to DrawLinePenned(). When I looked at the implementation, I was surprised to see the pen's width was used as both the width and height of all the rectangles defined in this method. Shouldn't the rectangles' heights be the pen's height?
Hi.
DrawString implementation link is not working
It's awesome that WriteableBitmapEx is offered as a Nuget package. The latest version published on http://nuget.org/List/Packages/WriteableBitmapEx however is from March 2015.
It's possible to build and publish nuget packages automatically these days. Perhaps with the move to Github you'd want to explore than option?
For Improve performance when drawing multiple forms in same time you can getBitmapContext and use it for draw, there's a little bottleneck when the BitmapContext disposed this add automatically AddDirtyRect with full bitmap size.
The correct solution will be automatically adds AddDirtyRects for refresh only the changed bitmap portions.
A temporaney workaround is get the Context in ReadOnly mode and when you finish (before dispose) add manually the AddDirtyRect of the desiderated size.
Example:
```
using (BitmapContext ctx = wBitmap.GetBitmapContext(ReadWriteMode.ReadOnly))
{
ctx.WriteableBitmap.DrawLine((int)pPrec.X, (int)pPrec.Y, (int)pNext.X, (int)pNext.Y, colorPlot.ToArgb());
ctx.WriteableBitmap.AddDirtyRect(new Int32Rect((int)pPrec.X, 0, (int)pNext.X, (int)ctx.WriteableBitmap.Height));
} //when exit the lib call only Unlock() in ReadOnly mode;
I have a 3-d int array like:
int[ , , ] = new int[512,512,128];
which containing 128 images each has 512*512 pixels.
I used SetPixel(i) in a for-loop but the speed is too slow.
Is there any faster way to implement this?
Hi all,
This project is awesome, I have tried it in my product. But there is a minor issue that the layout is buggy when rendering in the maximized window (See the pictures below). I don't why it happened. Any ideas?
The normal state of the window, the rendering is quite good
After maximizing the window, the text is buggy. I have no idea!!
Any idea in this case? Thanks.
Hi all !
Nice nuget, very usefull !
I've been wondering for the "DrawTriangle" , "DrawQuad" etc.. functions.
Would it be possible to pass a boolean argument for "Fill" or "stroke" as in
Might seem like a specific question, yet i do really need it and see many applications for it (thus for other folks)
Thanks all.
Thanks for the excellent library!
When drawing concentric circles on a wide image using DrawEllipseCentered
the outer circles appear compressed/deformed.
using (writeableBitmap.GetBitmapContext())
{
var centreX = (int) (writeableBitmap.Width / 2D);
var centreY = (int) (writeableBitmap.Height / 2D);
for (int i = 1; i <= 100; i++)
{
var radius = i * 50;
writeableBitmap.DrawEllipseCentered(centreX, centreY, radius, radius, ConvertColor(Colors.Red));
}
}
The bitmap is passed to a WPF image control with Stretch="None"
.
Is there a way to compile a safe mode version for WPF (Similar to the SilverLight)?
So I'm trying to implement a function that modifies a bitmaps pixels. It was originally implemented using unsafe code/pointers and worked fine. We are now trying to convert it into a safe variation of the function. The piece that is snagging me currently is replacing:
var pixels = context.Pixels;
to
pixels = new int[context.Width * context.Height];
context.WriteableBitmap.CopyPixels(pixels, context.WriteableBitmap.BackBufferStride, 0);
For some reason, CopyPixels just hangs when it gets to that line. Im assuming there has to be some kind of infinite loop in there causing the issue, but not 100% sure. I noticed the api doc said that the bitmap is locked when in the BitmapContext and figured maybe it needed to be unlocked in order to work. I tried calling context.WriteableBitmap.Unlock();
first to see but get the message "Cannot perform this action on an unlocked bitmap", so maybe its not locked after all?
I can call CopyPixels successfully on the original WriteableBitmap just before going into the context so I know its not an issue of the bitmap not being good, and like I said before, the implementation works if just the original line of code with context.Pixels
is used, so I am at a loss for what could be the issue.
Any help or direction would be greatly appreciated!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.