Handdrawing image and saving it as an array? - c#

Question: What program / file format should I use?
I want to create an image (handdrawn pixel by pixel) and have it exported to text file formated as a pseudo-array of integers like this:
16 8
0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 9 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 10 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 11 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 12 0 0 256 0
I want every number to represent unique color (not actually matter what color as long as drawing program (the simpler, the better - MS Paint would do) itself can read it and I can distinguish it from others). Ultimately I want the ability to quickly draw an image with external program and use such exported data within my code. Can someone point me to the right direction?
I tried to export image to .c with GIMP, but the results:
/* GIMP RGB C-Source image dump (Bez nazwy.c) */
static const struct {
guint width;
guint height;
guint bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
guint8 pixel_data[64 * 64 * 2 + 1];
} gimp_image = {
64, 64, 2,
"\377\377\0\0\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"...
though close to the point, are not exactly what I expect.
And here I see other possible solution: draw simply bmp image and try to translate it to an array of ints in my actual code (C#). But I would like to avoid this unless there is some simple and quick way / handy library to do this.
Or maybe some of You know any online converter that can take .bmp and return an array of ints?

#include "ui_mainwindow.h"
#include <QString>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
void generate(Ui::MainWindow* ui)
{
if (ui->pic_label->pixmap() != 0)
{
int cap = 1024 * 4;
int ct = 32; //color tolerance
//int number_of_colors_third = 256 / color_tolerance;//=256/32=8
int *uncompressedcolortable = new int[256*256*256];
for (int k=0; k<256; k++){
for (int j=0; j<256; j++){
for (int i=0; i< 256; i++){
uncompressedcolortable[k*256*256+j*256+i] = k*1000000+j*1000+i;
}
}
}
int width = ui->pic_label->pixmap()->width();
int height = ui->pic_label->pixmap()->height();
// int tiles = width * height;
if ( (width > cap || height > cap) && !(ui->actionSurpass_sanity_check->isChecked())){
ui->label->setText("File is too big to generate map. Check menu option if you want to process it anyway.");
return;
}
QImage image = ui->pic_label->pixmap()->toImage();
ui->lcdRED->setPalette(Qt::red);
ui->lcdGREEN->setPalette(Qt::green);
ui->lcdBLUE->setPalette(Qt::blue);
ui->progressBar->setMaximum(height);
QColor pixel_color;
ofstream outfile ("C:/Users/Niewzruszony/Desktop/map.map");
outfile << width << " " << height << std::endl;
for (int j = 0; j < height; j++ )
{
outfile << std::endl;
for (int i = 0; i < width; i++)
{
pixel_color = image.pixelColor(i,j);
outfile << uncompressedcolortable[pixel_color.red()*256*256 + pixel_color.green()*256 + pixel_color.blue()];
if(i != width-1) outfile << "\t";
ui->lcdRED->display(QString::fromStdString(to_string( pixel_color.red())));
ui->lcdGREEN->display(QString::fromStdString(to_string( pixel_color.green())));
ui->lcdBLUE->display(QString::fromStdString(to_string( pixel_color.blue())));
}
ui->progressBar->setValue(j+1);
}
ui->lcdRED->setPalette(Qt::lightGray);
ui->lcdGREEN->setPalette(Qt::lightGray);
ui->lcdBLUE->setPalette(Qt::lightGray);
ui->lcdRED->display(QString::fromStdString("0"));
ui->lcdGREEN->display(QString::fromStdString("0"));
ui->lcdBLUE->display(QString::fromStdString("0"));
ui->label->setText("Generated RGB map.");
return;
}
ui->pic_label->setText("First please choose image to process!");
}
Done it wit Qt. Just thougth I will share the code.
Note I've done some quick cleanup while posting, to not to include unimportant stuff (at least not all).

Related

Explanation of Array[i, j] = rnd.Next(0, 100);

I have a code:
int[,] mas = new int[5, 5];
Random rnd = new Random();
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
mas[i, j] = rnd.Next(0, 100);
Console.Write(mas[i, j] + "\t");
}
Console.WriteLine();
but i can`t understand what mas[i, j] means. Like first our matrix is filled by default 0, but we inject i and j into our array and then i and j are filled by random numbers from 0 to 100? And what does"\t" mean?
It's just a coordinate to a position in a rectangular array (in your case a 5x5). This code will loop over ever row, and every column in each row, putting a random number in each
You start out with everything set to 0 when you make a new int[5,5]:
0 1 2 3 4
-+--------------
0| 0 0 0 0 0
1| 0 0 0 0 0
2| 0 0 0 0 0
3| 0 0 0 0 0
4| 0 0 0 0 0
And after the loops have finished running you end up with every array slot set to a random number:
0 1 2 3 4
-+--------------
0|22 75 43 97 45
1|11 4 97 28 33
2|84 92 51 89 32
3|32 54 63 91 60
4|71 2 39 74 1
i and j are not filled with random numbers; they are incremented by the loops so both will cycle through 0 to 5, i will do it once and j will do it 5 times:
i, j
0, 0
0, 1
0, 2
0, 3
0, 4
1, 0 <=j restarted from 0 when i went to 1
1, 1
...
4, 2
4, 3
4, 4
This is how each coordinate in the array is filled with a random number given by rnd.Next()
'\t' is a TAB character

Copying a smaller array into a larger one

I'm struggling to think of the most elegant/simple way of doing this. Perhaps I'm overthinking it a little.
Lets say I've got a 5x5 array of integers that looks like this:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
And another 2x2 array of integers that looks like this:
5 1
2 3
I want to pick a location in the 5x5 array, say [2][2], and place the values from the second array into the first, so it looks like this:
0 0 0 0 0
0 0 0 0 0
0 0 5 1 0
0 0 2 3 0
0 0 0 0 0
My initial thought was to use a for loop after determining the number of rows/columns in the array to be copied, but I can't seem to puzzle out a way in my head to do that this morning.
Any suggestions?
Edit:
Sorry, here's the way I'm doing it currently. Just wondering if there's a better way.
This is actually part of a unity thing I'm doing - "RoomDoors" is our smaller array, and "map" is the larger array it's being moved into. It's part of a random map generator that needs to know which "edges" of tiles in rooms have doors on them that can connect to other rooms. RoomDoors stores 4 booleans, one for each direction telling me if there's a door there.
roomDoors = previousRoom.GetComponent<RoomDataInterface> ().rooms; //2d array of room/door arrangement in new room
sizeCol = roomDoors.GetLength (0);
sizeRow = roomDoors.GetLength (1);
map [10, 10] = roomDoors [0, 0]; // top left of the room goes in the spot
for (int i = 0; i < sizeCol; i ++){
for (int j = 0; j < sizeRow; j ++) {
map [i + 10,j + 10] = roomDoors[i,j];
}
I think you can't do much better, just remove the unnecessary assignment:
roomDoors = previousRoom.GetComponent<RoomDataInterface> ().rooms;
sizeCol = roomDoors.GetLength (0);
sizeRow = roomDoors.GetLength (1);
for (int i = 0; i < sizeCol; i ++)
for (int j = 0; j < sizeRow; j ++)
map [i + 10, j + 10] = roomDoors[i, j];
The line
map [10, 10] = roomDoors [0, 0];
is redundant, as the same assignment will be performed by the first iteration of the loop. Removal of the line will result in a solution that is smaller and more efficient.

how to implementing gaussian elimination for binary equations

i have this system of equations1=x⊕y⊕z
1=x⊕y⊕w
0=x⊕w⊕z
1=w⊕y⊕zI'm trying to implement gaussian elimination to solve this system as described here , replacing division,subtraction and multiplication by XOR, but it gives my wrong answer..the correct answer is (x,y,z,w)=(0,1,0,0) what am i doing wrong ?
public static void ComputeCoefficents(byte[,] X, byte[] Y)
{
int I, J, K, K1, N;
N = Y.Length;
for (K = 0; K < N; K++)
{
K1 = K + 1;
for (I = K; I < N; I++)
{
if (X[I, K] != 0)
{
for (J = K1; J < N; J++)
{
X[I, J] /= X[I, K];
}
//Y[I] /= X[I, K];
Y[I] ^= X[I, K];
}
}
for (I = K1; I < N; I++)
{
if (X[I, K] != 0)
{
for (J = K1; J < N; J++)
{
X[I, J] ^= X[K, J];
}
Y[I] ^= Y[K];
}
}
}
for (I = N - 2; I >= 0; I--)
{
for (J = N - 1; J >= I + 1; J--)
{
//Y[I] -= AndOperation(X[I, J], Y[J]);
Y[I] ^= (byte)(X[I, J]* Y[J]);
}
}
}
I think you're trying to apply Gaussian elimination mod 2 for this.
In general you can do Gaussian elimination mod k, if your equations are of the form
a_1 * x + b_1 * y + c_1 * z = d_1
a_2 * x + b_2 * y + c_2 * z = d_2
a_3 * x + b_3 * y + c_3 * z = d_3
a_4 * x + b_4 * y + c_4 * z = d_4
And in Z2 * is and and + is xor, so you can use Gausian elimination to solve equations of the form
x (xor) y (xor) z = 1
x (xor) y (xor) w = 1
x (xor) z (xor) w = 0
y (xor) z (xor) w = 1
Lets do this equation using Gausian elimination by hand.
The corresponding augmented matrix is:
1 1 1 0 | 1
1 1 0 1 | 1
1 0 1 1 | 0
0 1 1 1 | 1
1 1 1 0 | 1
0 0 1 1 | 0 (R2 = R2 + R1)
0 1 0 1 | 1 (R3 = R3 + R1)
0 1 1 1 | 1
1 1 1 0 | 1
0 1 1 1 | 1 (R2 = R4)
0 1 0 1 | 1
0 0 1 1 | 0 (R4 = R2)
1 0 0 1 | 0 (R1 = R1 + R2)
0 1 1 1 | 1
0 0 1 0 | 0 (R3 = R3 + R2)
0 0 1 1 | 0
1 0 0 1 | 0
0 1 0 1 | 1 (R2 = R2 + R3)
0 0 1 0 | 0
0 0 0 1 | 0 (R4 = R4 + R3)
1 0 0 0 | 0 (R1 = R1 + R4)
0 1 0 0 | 1 (R2 = R2 + R4)
0 0 1 0 | 0
0 0 0 1 | 0
Giving your solution of (x,y,z,w) = (0,1,0,0).
But this requires row pivoting - which I can't see in your code.
There's also some multiplications and divisions floating around in your code that probably dont need to be there. I'd expect the code to look like this: (You'll need to fix the TODOs).
public static void ComputeCoefficents(byte[,] X, byte[] Y) {
int I, J, K, K1, N;
N = Y.Length;
for (K = 0; K < N; K++) {
//First ensure that we have a non-zero entry in X[K,K]
if( X[K,K] == 0 ) {
for(int i = 0; i<N ; ++i ) {
if(X[i,K] != 0 ) {
for( ... ) //TODO: A loop to swap the entries
//TODO swap entries in Y too
}
}
if( X[K,K] == 0 ) {
// TODO: Handle the case where we have a zero column
// - for now we just move on to the next column
// - This means we have no solutions or multiple
// solutions
continue
}
// Do full row elimination.
for( int I = 0; I<N; ++I)
{
if( I!=K ){ //Don't self eliminate
if( X[I,K] ) {
for( int J=K; J<N; ++J ) { X[I,J] = X[I,J] ^ X[K,J]; }
Y[J] = Y[J] ^ Y[K];
}
}
}
}
//Now assuming we didnt hit any zero columns Y should be our solution.
}

Closed path in the two-dimensional array

There is two-dimensional array of zeros and ones. Need algorithm (the implementation) that determines whether in this array closed path of ones, that surround the zeros
Example:
there EXISTS a closed path(center):
1 0 0 0 0
0 0 1 0 0
0 1 0 1 0
0 0 1 1 0
0 0 1 0 0
there is NO
0 0 0 0 1
0 1 0 1 0
0 0 1 0 0
0 0 1 0 1
0 1 0 1 0
You can look at Connected Components Labeling algorithms, e.g. in Wikipedia or google for them. These algorithms are used e.g. to separate foreground pixels from background pixels in a digital white/black image. To apply them to your specific problem, you can think of your matrix as a digital image where 0 means foreground and 1 means background (or vice versa according to your needs). The algorithm finds largest connected foreground regions (containing only 0) that are surrounded by the background (1's). So, if you found such a foreground region you know there is a cycle of 1's surrounding it. When the foreground region is at the boundary you can decide whether you consider it as surrounded or not.
It's homework so I'll just give a general sketch. Construct an undirected graph; each 1 is a node, adjacent 1s have an edge between them. Google for undirected graph cycle detection to find closed paths. Then you have to go back to the original matrix and make sure there's at least one 0 inside.
Another idea would be to flood-fill starting at each 0 bounded by 1s. If it doesn't reach an edge, it's surrounded.
Here is sample code i tried. test it through
Logic i tried is loop through all the rows except first and last row.
if you find 0 then check it neighbour to left,right,top and bottom if all the neighbours are 1 then closed.
private void Form1_Load(object sender, EventArgs e)
{
int[,] graph = new int[5, 5] {
{ 1, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 1, 0, 1, 0 },
{ 0, 0, 1, 1, 0 },
{ 0, 0, 1, 0, 0 }
};
int[,] graph1 = new int[5, 5] {
{ 0, 0, 0, 0, 1 },
{ 0, 1, 0, 1, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 1, 0, 1, 0 }
};
isClosed(graph1);
}
private bool isClosed(int[,] graph)
{
for (int i = 1; i < graph.GetUpperBound(0); i++)
{
for (int j = 1; j < graph.GetUpperBound(1); j++)
{
if (graph[i, j] == 0)
{
if (graph[i - 1, j] == 1 && graph[i + 1, j] == 1 && graph[i, j - 1] == 1 && graph[i, j + 1] == 1)
{
return true;
}
}
}
}
return false;
}

Rotate 2D Array by 45 degrees

How can I rotate a 2D rectangular array of integers that has odd number of rows by 45 degrees?
So something like
int[] myArray = new int[,]
{
{1, 0 ,1},
{0, 1 ,0},
{0, 0 ,0},
}
into
int[] rotatedArray = new int[,]
{
{0, 1 ,0},
{0, 1 ,1},
{0, 0 ,0},
}
for any dimension (3x3, 5x5, 7x7, etc.).
5x5
0 0 0 0 0
2 0 0 0 0
1 1 1 1 1
0 0 0 0 0
0 0 0 0 0
into
1 2 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
5x5
0 0 0 3 0
0 0 0 3 0
0 0 0 3 0
0 0 0 3 0
0 0 0 3 0
into
0 0 0 0 0
0 0 0 0 3
0 0 0 3 0
0 0 3 3 0
0 3 0 0 0
This is a code written by me and a friend that solves this:
public static class ArrayExtensions
{
public static Point RoundIndexToPoint(int index, int radius)
{
if (radius == 0)
return new Point(0, 0);
Point result = new Point(-radius, -radius);
while (index < 0) index += radius * 8;
index = index % (radius * 8);
int edgeLen = radius * 2;
if (index < edgeLen)
{
result.X += index;
}
else if ((index -= edgeLen) < edgeLen)
{
result.X = radius;
result.Y += index;
}
else if ((index -= edgeLen) < edgeLen)
{
result.X = radius - index;
result.Y = radius;
}
else if ((index -= edgeLen) < edgeLen)
{
result.Y = radius - index;
}
return result;
}
public static T[,] Rotate45<T>(this T[,] array)
{
int dim = Math.Max(array.GetLength(0), array.GetLength(0));
T[,] result = new T[dim, dim];
Point center = new Point((result.GetLength(0) - 1) / 2, (result.GetLength(1) - 1) / 2);
Point center2 = new Point((array.GetLength(0) - 1) / 2, (array.GetLength(1) - 1) / 2);
for (int r = 0; r <= (dim - 1) / 2; r++)
{
for (int i = 0; i <= r * 8; i++)
{
Point source = RoundIndexToPoint(i, r);
Point target = RoundIndexToPoint(i + r, r);
if (!(center2.X + source.X < 0 || center2.Y + source.Y < 0 || center2.X + source.X >= array.GetLength(0) || center2.Y + source.Y >= array.GetLength(1)))
result[center.X + target.X, center.Y + target.Y] = array[center2.X + source.X, center2.Y + source.Y];
}
}
return result;
}
}
You can try this library:
Math.NET Project for matrices operations... http://numerics.mathdotnet.com/
This code appears to be useful too:
http://www.drunkenhyena.com/cgi-bin/view_net_article.pl?chapter=2;article=28#Rotation
Don't forget the DirectX managed and unmanaged namespaces and classes. Lots
and lots of good stuff there to check.
For example:
Matrix..::.Rotate Method (Single, MatrixOrder)
I think we have these rules:
Imagine the matrix as a set of "frames or boxes without centers" within each other like "Russian dolls".
Elements at the center of a side (top/left/right/bottom) move towards the nearest corner clockwise.
Corners move towards the next center clockwise.
Elements that are not corners nor centers move to the next spot (clockwise) that is the same distance from a corner as they currently are.
I've started writing some code but I don't think it's trivial and I haven't had time to test.
You can see my solution for the matrix rotation in codesignal

Categories

Resources