How to get access to pixels from an image in xamarin project? - c#

I want to get access to pixels colors from an image, but as far as I know Image cannot be used in that way. In my code there is an event Modify where I call a method MakeDarker, but I want to know how can I modify pixels there.
I tried to convert an Image to a bitmap or to byte array, but none of this works for me. Visual Studio doesn't even recognize Bitmap, when I'm typing it despite using Xamarin.Forms.Image.
public void Modify(object sender, EventArgs args)
{
ImageModify modify = new ImageModify();
picture = modify.MakeDarker(picture);
}
class ImageModify
{
public Image MakeDarker(Image image)
{
Image output = new Image();
for (int i = 0; i < image.Height; i++)
{
for (int j = 0; j < image.Width; j++)
{
}
}
return output;
}
}

Have you tried with the Color struct from the System.Drawing namespace (don't know if you can use it in Xamarin or if it's specific for Windows based projects) ?
I used it in my own C# projet to collect RGB values of a pixel and it worked well.

Related

Unity Texture2D loadImage exact values

Why with Unity when I load an external 1024x1024 RGBA32 .png (saved via either PaintXP or Gimp) with a blob of (64,64,64) pixels in the centre does the Debug.Log line at the bottom return incorrect values? - The closest I can get is with an uncompressed .png (from Gimp) with values like (65,66,65), but with a standard image they seem to come back as (56,56,56).
Texture2D tex = null;
byte[] fileData;
if (File.Exists(mapPath + "/map.png"))
{
fileData = File.ReadAllBytes(mapPath + "/map.png");
tex = new Texture2D(size, size, TextureFormat.RGBA32, false);
tex.anisoLevel = 0;
tex.Compress(false);
tex.filterMode = FilterMode.Point;
tex.LoadImage(fileData); // Auto-resize the texture dimensions
Color32[] pixelsRaw = tex.GetPixels32(0);
Color32[,] pixels = new Color32[size, size];
for (int j = 0; j < size - 1; j++)
{
for (int i = 0; i < size - 1; i++)
{
pixels[i, j] = pixelsRaw[(j * tex.height) + i];
}
}
Debug.Log(pixels[512, 512]);
}
This was all in an attempt to read a tile-based level from a .png image. But with the returned values being so inaccurate, I can't seem to find a way to make this possible. (I've done this loads of times with Java.awt/LWJGL and it works fine there, why not Unity?)
To clarify, this image is being loaded from outside the Unity project, so there is no way to manually set the compression/format settings via the editor.
There are a couple of problems: compression and gamma correction.
1. When you call Compress on your Texture2D it will compress your texture. The bool parameter only tells it to do a low quality or high quality compression. So just remove the line: tex.Compress(false);
2. The PNG has gamma information. Gimp has an option when you export to png to save gamma or not. So open your image in Gimp and export it with the "Save Gamma" option unchecked.
Alternatively I was able to get the same result by removing the gAMA and sRGB attributes from the png with TweakPNG.

WP8.1 RT - Changing pixel color

I've been working on some Windows Phone 8.1 RT app's lately which require quite alot of icons. For iOS and Android we can use White on Black icons and turn them into the right color(s) through code. But for WP8.1 it seems quite impossible to run it fast.
class ColoredImage
{
public static WriteableBitmap GetColoredImage(WriteableBitmap bitmap, Color color)
{
var result = bitmap;
for (int i = 0; i < (result.PixelWidth); i++)
{
for (int j = 0; j < result.PixelHeight; j++)
{
if (result.GetPixel(i, j) == Colors.Black)
{
result.SetPixel(i, j, Colors.Transparent);
}
else
{
result.SetPixel(i, j, color);
}
}
}
return result;
}
}
I got this class changing the colors of a WriteableBitmap but it takes about 15 seconds to change the colors of a 62x62 image. Is there anything I am doing wrong, and on what can I improve.
Thanks.
Your algo of reading an image finding pixel and changing their colors is a time consuming process. You have got two ways in which you can do it at a faster pace
1) Using Segoe MDL2 Assets You can use these pre installed font family which contains most of the basic images. Benefit is since these are vector images changing foreground would change the color instantly. Search for CharacterMap and then this font in your system and you will find all available fonts
2) If you are not able to find your particular image in charmap then you will have to create path images using blend which is similar to converting images to vector and then you can easily change color.

Kinect V2 Color Stream Byte Order

I'm working on an application which will stream the color, depth, and IR video data from the Kinect V2 sensor. Right now I'm just putting together the color video part of the app. I've read through some tutorials and actually got some video data coming into my app - the problem seems to be that the byte order seems to be in the wrong order which gives me an oddly discolored image (see below).
So, let me explain how I got here. In my code, I first open the sensor and also instantiate a new multi source frame reader. After I've created the reader, I create an event handler called Reader_MultiSourceFrameArrived:
void Reader_MultiSourceFrameArrived(object sender, MultiSourceFrameArrivedEventArgs e)
{
if (proccessing || gotframe) return;
// Get a reference to the multi-frame
var reference = e.FrameReference.AcquireFrame();
// Open color frame
using (ColorFrame frame = reference.ColorFrameReference.AcquireFrame())
{
if (frame != null)
{
proccessing = true;
var description = frame.ColorFrameSource.FrameDescription;
bw2 = description.Width / 2;
bh2 = description.Height / 2;
bpp = (int)description.BytesPerPixel;
if (imgBuffer == null)
{
imgBuffer = new byte[description.BytesPerPixel * description.Width * description.Height];
}
frame.CopyRawFrameDataToArray(imgBuffer);
gotframe = true;
proccessing = false;
}
}
}
Now, every time a frame is received (and not processing) it should copy the frame data into an array called imgBuffer. When my application is ready I then call this routine to convert the array into a Windows Bitmap that I can display on my screen.
if (gotframe)
{
if (theBitmap.Rx != bw2 || theBitmap.Ry != bh2) theBitmap.SetSize(bw2, bh2);
int kk = 0;
for (int j = 0; j < bh2; ++j)
{
for (int i = 0; i < bw2; ++i)
{
kk = (j * bw2 * 2 + i) * 2 * bpp;
theBitmap.pixels[i, bh2 - j - 1].B = imgBuffer[kk];
theBitmap.pixels[i, bh2 - j - 1].G = imgBuffer[kk + 1];
theBitmap.pixels[i, bh2 - j - 1].R = imgBuffer[kk + 2];
theBitmap.pixels[i, bh2 - j - 1].A = 255;
}
}
theBitmap.needupdate = true;
gotframe = false;
}
}
So, after this runs theBitmap now contains the image information needed to draw the image on the screen... however, as seen in the image above - it looks quite strange. The most obvious change is to simply change the order of the pixel B,G,R values when they get assigned to the bitmap in the double for loop (which I tried)... however, this simply results in other strange color images and none provide an accurate color image. Any thoughts where I might be going wrong?
Is this Bgra?
The normal "RGB" in Kinect v2 for C# is BGRA.
Using the Kinect SDK 2.0, you don't need all of those "for" cycles.
The function used to allocate the pixels in the bitmap is this one:
colorFrame.CopyConvertedFrameDataToIntPtr(
this.colorBitmap.BackBuffer,
(uint)(colorFrameDescription.Width * colorFrameDescription.Height * 4),
ColorImageFormat.Bgra);
1) Get the Frame From the kinect, using Reader_ColorFrameArrived (go see ColorSamples - WPF);
2) Create the colorFrameDescription from the ColorFrameSource using Bgra format;
3) Create the bitmap to display;
If you have any problems, please say. But if you follow the sample it's actually pretty clean there how to do it.
I was stuck on this problem forever. Problem is, that all almost all examples you find, are WPF examples. But for Windows Forms its a different story.
frame.CopyRawFrameDataToArray(imgBuffer);
gets you the rawdata whitch is
ColorImageFormat.Yuy2
By converting it to RGB you should be able to fix your color problem. The transformation from YUY2 to RGB is very expensive, you might want to use a Parallel foreach loop to maintain your framerate

Adding Multiple Pictureboxes in C# for the same image source

In my application I have over 60 pictureboxes with the same image source added to a panel.
Code Example
class MainForm : Form{
private Image image = (Image)Resources.myImage;
public MainForm(){
InitializeComponent();
initAddImages();
}
private void initAddImages(){
for (int i = 0; i < 10; i++)
for (int j = 0; j < 8; j++){
PictureBox p = new PictureBox();
p.Image = image;
p.SizeMode = PictureBoxSizeMode.Zoom;
//"ImagePanel" is a TableLayoutPanel
imagePanel.Controls.Add(p, i, j);
}
}
private void changeImage(){
image = (Image)Resources.anotherImage;
}
}
Problems / Questions:
The pictureboxes rendering are kinda slow. (I already have a small image resolution). Since the application is re-sizable, the images need to be resized everytime I resize the form. My guess the reason behind this slowness in rendering is caused because the images size needs to be calculated for ever single picturebox. Is there way to resize the image once and force all pictureboxes to use this resized image ?
Is it possible to pass the image object reference to all pictureboxes objects so when I change the image resource reference (by calling for example "changeImage"), all pictureboxes will be rendered with the new image "anotherImage"?
Thanks in Advance ...

Drawing using a bitmap on PictureBox in C#

my first question here. And I'm sure it's an easy one, but I can't find a solution anywhere, I've read lots and just can't comprehend how to what i need to do:
I have a *.gif file, that I want to store in System.Drawing.Bitmap, so that I have access to GetPixel() method
I want to have my drawing on some control (currently trying out PictureBox)
So far what I've got:
I create a template, Bitmap from file - and that works (map_t in code)
I create a bitmap that will actually be drawn (map)
I can set my PictureBox image to a bitmap
I can't change this bitmap. Or I can, but the result doesn't show
I thought I'd have to create Graphic from that bitmap, then change it. I have no idea what i'm missing.
Here's the code: MapCanvas is PictureBox on a form, everything is in MouseMove, because I was trying to make some circles around the pointer - didn't work so I ended up with this code, which doesn't work either. I have read every question I could find, nothing helps... Here's the code:
namespace Projekt_innowacje
{
public partial class MapForm : Form
{
Bitmap map_t;
Bitmap map;
public MapForm()
{
InitializeComponent();
map_t = new Bitmap("map.gif", true);
map = new Bitmap(map_t.Width, map_t.Height);
MapCanvas.Image = map;
}
private void MapCanvas_MouseMove(object sender, MouseEventArgs e)
{
Graphics canvas = Graphics.FromImage(map);
for (int i = 0; i <= map.Width; i++)
for (int j = 0; j <= map.Height; j++)
if (map.GetPixel(i, j) == Color.Red)
canvas.DrawLine(new Pen(Color.Blue), i, j, i + 1, j + 1);
// map.SetPixel(i, j, map.GetPixel(i, j)); // also doesn't work
//MapCanvas.Refresh();
MapCanvas.Invalidate();
canvas.Dispose();
}
}
}
The code you are showing will never modify the canvas/map image unless you are making some other changes to the map image that you're not sharing. In your loop you test map.GetPixel, however map is created as a blank image in the constructor, so none of its pixels will ever be Color.Red. Did you intend to test against your template instead?
Also, you may want to have a look at this question which talks about comparing colors. It suggests that for basic color comparisons to use the .ToArgb() method on the color structure since the == and Equals do more than just compare the color value.

Categories

Resources