Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Tihs is a code that impliments the adaptive histogram equalization algorithm,called by a button in the c# main form, the image is about 1024*768 in size. The problem is this code is too slow ,I don't know where I should modify to improve the performance...Please give me some advice....thanks..
private void AHE_BMP_advanced(Int32 halfblocksize)
{
//adaptive histogram equalization
Size imgsz = sourceBMP.Size;
//compute total number of pixels
double totalNum = imgsz.Height * imgsz.Width;
//temp image for storation
Bitmap tempImg = new Bitmap(imgsz.Width, imgsz.Height);
//region statistics
double[,] prob = new double[256, 3];
Int32[,] mapping = new Int32[256, 3];
double[] probSum = new double[3];
for (int i = 0; i < imgsz.Height; i++)
{
for (int j = 0; j < imgsz.Width; j++)
{
//this.textBox2.Text = "i=" + i.ToString() + "j=" + j.ToString();
for (int u = 0; u < 256; u++) {
for (int v = 0; v < 3; v++) {
prob[u, v] = 0;
mapping[u, v] = 0;
}
}
//produce ahe for this pixel:
for (int u = i - halfblocksize; u <= i + halfblocksize; u++)
{
for (int v = j - halfblocksize; v <= j + halfblocksize; v++)
{
//uv->hi,wi;
int hi, wi;
hi = u;
wi = v;
//mirror:
if (hi < 0) hi = -hi;
else if (hi >= imgsz.Height)
hi = 2 * (imgsz.Height - 1) - hi;
if (wi < 0) wi = -wi;
else if (wi >= imgsz.Width)
wi = 2 * (imgsz.Width - 1) - wi;
//get hist
prob[sBmpdata[wi,hi,0], 0] += 1;
prob[sBmpdata[wi,hi,1], 1] += 1;
prob[sBmpdata[wi,hi,2], 2] += 1;
}
}
//get ahe value:
//probSum init:
probSum[0] = 0;
probSum[1] = 0;
probSum[2] = 0;
for (int k = 0; k < 256; k++)
{
this.textBox2.Text += "prob[" + k.ToString()+ ",0]=" +
prob[k,0].ToString()+"\r\n";
prob[k, 0] /= totalNum;
prob[k, 1] /= totalNum;
prob[k, 2] /= totalNum;
//Sum
probSum[0] += prob[k, 0];
probSum[1] += prob[k, 1];
probSum[2] += prob[k, 2];
if(i==40&&j==40)
//mapping(INT32)
mapping[k, 0] = Convert.ToInt32(255.0 * probSum[0]);
mapping[k, 1] = Convert.ToInt32(255.0 * probSum[1]);
mapping[k, 2] = Convert.ToInt32(255.0 * probSum[2]);
}
tempImg.SetPixel(j, i,
Color.FromArgb(mapping[sBmpdata[j,i,0], 0],
mapping[sBmpdata[j,i,1], 1], mapping[sBmpdata[j,i,2], 2]));
}
}
this.pictureBox1.Image = tempImg;
}
SetPixel
SetPixel is very slow. Look in to using LockBits. MSDN has good example.
String concatenation inside a loop
This line inside a loop is also inefficient as it creates 256 strings for each pixel, so 201 million strings allocated, that's got to be expensive!
for (int k = 0; k < 256; k++)
this.textBox2.Text += "prob[" + k.ToString()+ ",0]=" + prob[k,0].ToString()+"\r\n";
If it's debug, take it out, 201 million lines of debug text is not useful to you. It you need it you are better off writing to a file as otherwise it's going to take many GB's of ram to store the final string.
Using SetPixel is actually a fairly inefficient way of working with image data. If you want to scan across the whole image I'd suggest manipulating the image data directly using the BitmapData class.
// Create a new bitmap.
Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbValues = new byte[bytes];
// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
// Set every third value to 255. A 24bpp bitmap will look red.
for (int counter = 2; counter < rgbValues.Length; counter += 3)
rgbValues[counter] = 255;
// Copy the RGB values back to the bitmap
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
// Unlock the bits.
bmp.UnlockBits(bmpData);
// Draw the modified image.
e.Graphics.DrawImage(bmp, 0, 150);
Well, I think you should write
private void AHE_BMP_advanced(Int32 halfblocksize)
{
this.pictureBox1.Image = GetAHE_BMP_advanced(halfblocksize, sourceBMP.Size, sBmpdata);
}
where GetAHE_BMP_advanced is
private static Bitmap GetAHE_BMP_advanced(int halfblocksize, Size sourceBmpSize, int[,,] sourceBmpData)
{
const int m = 256;
const int n = 3;
//adaptive histogram equalization
Size imgsz = sourceBmpSize;
//compute total number of pixels
double totalNum = imgsz.Height * imgsz.Width;
var colors = new Color[sourceBmpSize.Width, sourceBmpSize.Height];
for (int i = 0; i < imgsz.Height; i++)
{
for (int j = 0; j < imgsz.Width; j++)
{
double[,] prob = new double[m, n];
int[,] mapping = new int[m, n];
//produce ahe for this pixel:
for (int u = i - halfblocksize; u <= i + halfblocksize; u++)
{
for (int v = j - halfblocksize; v <= j + halfblocksize; v++)
{
int hi = u;
int wi = v;
//mirror:
if (hi < 0) hi = -hi;
else if (hi >= imgsz.Height)
hi = 2 * (imgsz.Height - 1) - hi;
if (wi < 0) wi = -wi;
else if (wi >= imgsz.Width)
wi = 2 * (imgsz.Width - 1) - wi;
//get hist
prob[sourceBmpData[wi, hi, 0], 0] += 1;
prob[sourceBmpData[wi, hi, 1], 1] += 1;
prob[sourceBmpData[wi, hi, 2], 2] += 1;
}
}
double[] probSum = new double[n];
for (int k = 0; k < m; k++)
{
prob[k, 0] /= totalNum;
prob[k, 1] /= totalNum;
prob[k, 2] /= totalNum;
//Sum
probSum[0] += prob[k, 0];
probSum[1] += prob[k, 1];
probSum[2] += prob[k, 2];
if (i == 40 && j == 40) //mapping(INT32)
{
mapping[k, 0] = Convert.ToInt32(255.0 * probSum[0]);
mapping[k, 1] = Convert.ToInt32(255.0 * probSum[1]);
mapping[k, 2] = Convert.ToInt32(255.0 * probSum[2]);
}
}
colors[i, j] = Color.FromArgb(mapping[sourceBmpData[j, i, 0], 0],
mapping[sourceBmpData[j, i, 1], 1],
mapping[sourceBmpData[j, i, 2], 2]);
}
}
return BitmapHelper.CreateBitmap(colors);
}
where BitmapHelper is:
public static class BitmapHelper
{
public struct Pixel : IEquatable
{
// ReSharper disable UnassignedField.Compiler
public byte Blue;
public byte Green;
public byte Red;
public bool Equals(Pixel other)
{
return Red == other.Red && Green == other.Green && Blue == other.Blue;
}
}
public static Color[,] GetPixels(Bitmap two)
{
return ProcessBitmap(two, pixel => Color.FromArgb(pixel.Red, pixel.Green, pixel.Blue));
}
public static float[,] GetBrightness(Bitmap two)
{
return ProcessBitmap(two, pixel => Color.FromArgb(pixel.Red, pixel.Green, pixel.Blue).GetBrightness());
}
public static unsafe T[,] ProcessBitmap<T>(Bitmap bitmap, Func<Pixel, T> func)
{
var lockBits = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly,
bitmap.PixelFormat);
int padding = lockBits.Stride - (bitmap.Width * sizeof(Pixel));
int width = bitmap.Width;
int height = bitmap.Height;
var result = new T[height, width];
var ptr = (byte*)lockBits.Scan0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
var pixel = (Pixel*)ptr;
result[i, j] = func(*pixel);
ptr += sizeof(Pixel);
}
ptr += padding;
}
bitmap.UnlockBits(lockBits);
return result;
}
public static Bitmap CreateBitmap(Color[,] colors)
{
const int bytesPerPixel = 4, stride = 8;
int width = colors.GetLength(0);
int height = colors.GetLength(1);
byte[] bytes = new byte[width*height*bytesPerPixel];
int n = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
bytes[n++] = colors[i, j].R;
bytes[n++] = colors[i, j].G;
bytes[n++] = colors[i, j].B;
bytes[n++] = colors[i, j].A;
}
}
return CreateBitmap(bytes, width, height, stride, PixelFormat.Format32bppArgb);
}
public static Bitmap CreateBitmap(byte[] data, int width, int height, int stride, PixelFormat format)
{
var arrayHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
var bmp = new Bitmap(width, height, stride, format, arrayHandle.AddrOfPinnedObject());
arrayHandle.Free();
return bmp;
}
}
Related
I am trying to get the pixels a bit faster than one could when using .GetPixel() but I have found myself that it throws an exception with a 0,0 index with the right LockImageMode.
Exception
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
public async Task<IList<Color>> GetColorStream( )
{
(_Width, _Height, PixelFormat pixelFormat) = await GetDimensions(_Path);
List<Color> pixels = new();
if (pixelFormat is not PixelFormat.Format32bppRgb or not PixelFormat.Format24bppRgb or not PixelFormat.Format32bppRgb)
throw new InvalidOperationException("Cant operate with ess than 24bpps");
_Data = await GetBitmapData(_Width, _Height, pixelFormat, ImageLockMode.ReadWrite);
if(pixelFormat is PixelFormat.Format24bppRgb or PixelFormat.Format32bppRgb)
{
for (int i = 0; i < _Width; i++)
for (int j = 0; j < _Height; j++)
{
int stride = i * _Data.Stride / 3 + j;
(byte R, byte G, byte B, byte A) = (Marshal.ReadByte(_Data.Scan0, stride), Marshal.ReadByte(_Data.Scan0, stride + 1),
Marshal.ReadByte(_Data.Scan0, stride + 2), 0);
pixels.Add(new Color(R, G, B, A));
}
}
else if(pixelFormat == PixelFormat.Format32bppArgb )
{
for (int i = 0; i < _Width; i++)
for (int j = 0; j < _Height; j++)
{
int stride = i * _Data.Stride / 4 + j;
(byte R, byte G, byte B, byte A) = (Marshal.ReadByte(_Data.Scan0, stride), Marshal.ReadByte(_Data.Scan0, stride + 1),
Marshal.ReadByte(_Data.Scan0, stride + 2), Marshal.ReadByte(_Data.Scan0, stride + 3));
pixels.Add(new Color(R, G, B, A));
}
}
image.UnlockBits(_Data);
image = null;
return pixels;
}```
I have one pointer array of bytes with length(4325376) and i am trying to copy the values of first array to another one,
but the speed of copying is slow even with pointers: ~50ms.
The question is: How to increase the speed of copying?
I know there is a copy function to copy the entire array but i don't know if in my case it's possible to use it.
Here is my code:
var mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None);
byte[] rgbaValues = new byte[width * height * 4];
var curRowOffs = 0;
var stride = width * 4;
unsafe
{
byte* srcPtr = (byte *)mapSource.DataPointer;
Stopwatch sw = Stopwatch.StartNew();
fixed (byte* pDest = rgbaValues)
{
for (uint y = 0; y < height; y++)
{
var index2 = curRowOffs;
var index = y * mapSource.RowPitch;
for (uint x = 0; x < width; x++)
{
pDest[index2] = srcPtr[index + x * 4 + 0];
pDest[index2 + 1] = srcPtr[index + x * 4 + 1];
pDest[index2 + 2] = srcPtr[index + x * 4 + 2];
pDest[index2 + 3] = srcPtr[index + x * 4 + 3];
index2 += 4;
}
curRowOffs += stride;
}
}
sw.Stop();
Console.WriteLine("{0:N0} Milliseconds", sw.Elapsed.Milliseconds);
}
Udate:
The solution was to use Buffer.CopyMemory method, it gave me ~2ms, Awesome!
for (uint y = 0; y < height; y++)
{
System.Buffer.MemoryCopy(srcPtr, destPtr, width * 4, width * 4);
srcPtr = &srcPtr[mapSource.RowPitch];
destPtr = &destPtr[mapDest.Stride];
}
I'm writing a small steganography application in C# and was able to hide text in images. However the method I used was the GetPixel/SetPixel method which was a lot slower for larger images, which I noticed after trying to hide a mp3 file in the image. After some google searches, I found out about LockBits. While the speed did improve drastically, I discovered that I was unable to extract the encrypted data (the cipher text) which was hidden in the image.
I'm not sure if the issue is with how I insert the data or when extracting it. When attempting to extract the Base64 cipher text, it would be corrupted (random symbols and characters) and throw an exception about it not being a Base64String. I ended up changing the code by following what was on the documentation for LockBits, I'll paste it below.
Merging the cipher text
public static unsafe void MergeEncryptedData(string data, Bitmap bmp, string output) {
State s = State.HIDING;
int height = bmp.Height;
int width = bmp.Width;
var bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);
byte * scan0 = (byte * ) bitmapData.Scan0;
int bytesPerPixel = 4;
int dataIndex = 0;
byte dataValue = 0;
long colorUnitIndex = 0;
int zeros = 0;
byte R, G, B;
Parallel.For(0, height, (i, loopState) = > {
byte * currentLine = scan0 + (i * bitmapData.Stride);
for (int j = 0; j < (bitmapData.Width * bytesPerPixel); j += bytesPerPixel) {
R = currentLine[i + 2];
G = currentLine[i + 1];
B = currentLine[i];
for (int n = 0; n < 3; n++) {
if (colorUnitIndex % 8 == 0) {
if (zeros == 8) {
if ((colorUnitIndex - 1) % 3 < 2) {
currentLine[i + 2] = R;
currentLine[i + 1] = G;
currentLine[i] = B;
//bmp.SetPixel(j, i, Color.FromArgb(R, G, B));
}
loopState.Stop();
}
if (dataIndex >= data.Length) {
s = State.FILL_WITH_ZEROS;
} else {
dataValue = (byte) data[dataIndex++];
}
}
switch (colorUnitIndex % 3) {
case 0:
{
if (s == State.HIDING) {
B += (byte)(dataValue % 2);
dataValue /= 2;
}
}
break;
case 1:
{
if (s == State.HIDING) {
G += (byte)(dataValue % 2);
dataValue /= 2;
}
}
break;
case 2:
{
if (s == State.HIDING) {
R += (byte)(dataValue % 2);
dataValue /= 2;
}
currentLine[i + 2] = R;
currentLine[i + 1] = G;
currentLine[i] = B;
//bmp.SetPixel(j, i, Color.FromArgb(R, G, B));
}
break;
}
colorUnitIndex++;
if (s == State.FILL_WITH_ZEROS) {
zeros++;
}
}
}
});
bmp.UnlockBits(bitmapData);
bmp.Save(output, ImageFormat.Png);
}
Extracting the cipher text
public static unsafe string ExtractData(Bitmap bmp) {
int height = bmp.Height;
int width = bmp.Width;
var bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bmp.PixelFormat);
byte * scan0 = (byte * ) bitmapData.Scan0.ToPointer();
int bytesPerPixel = 4;
int colorUnitIndex = 0;
int charValue = 0;
string extractedText = String.Empty;
Parallel.For(0, height, (i, loopState) = > {
byte * currentLine = scan0 + (i * bitmapData.Stride);
for (int j = 0; j < (bitmapData.Width * bytesPerPixel); j += bytesPerPixel) {
for (int n = 0; n < 3; n++) { //this particular loop feels incorrect
switch (colorUnitIndex % 3) {
case 0:
{
charValue = charValue * 2 + currentLine[i] % 2;
}
break;
case 1:
{
charValue = charValue * 2 + currentLine[i + 1] % 2;
}
break;
case 2:
{
charValue = charValue * 2 + currentLine[i + 2] % 2;
}
break;
}
colorUnitIndex++;
if (colorUnitIndex % 8 == 0) {
charValue = reverseBits(charValue);
if (charValue == 0) {
loopState.Stop();
}
char c = (char) charValue;
extractedText += c.ToString();
}
}
}
});
bmp.UnlockBits(bitmapData);
return extractedText;
}
An example of what the extracted cipher text looks like when the error is thrown:
I$I$I$I$I$I$I$I$I$I$I$I$I$I䥉II!J$$.
It should be a Base-64 String
Just for reference, I'm using a LUT PNG image to hide the data, so I'm able see a slight difference in color when compared to the original. So I know the RGB values are indeed being changed.
You need to consider:
Stride - image data with may be different of image width. More info here.
Image number of color/data channels
8 bpp (1 channel)
24 bpp (3 channels RGB)
32 bpp (4 channels ARGB, where A means alpha, transparency)
You mention RGB PNG but you are using 4 channels in your code (ARGB), double check that.
Here is a sample method that WILL obtain the same data that using the slow Bitmap GetPixel, but really fast. Based on this sample you can fix your code, as:
How to calculate bits per pixel
How to use stride properly
How to read multiple channels
Code:
/// <summary>
/// Get pixel directly from unmanaged pixel data based on the Scan0 pointer.
/// </summary>
/// <param name="bmpData">BitmapData of the Bitmap to get the pixel</param>
/// <param name="p">Pixel position</param>
/// <returns>Pixel value</returns>
public static byte[] GetPixel(BitmapData bmpData, Point p)
{
if ((p.X > bmpData.Width - 1) || (p.Y > bmpData.Height - 1))
throw new ArgumentException("GetPixel Point p is outside image bounds!");
int bitsPerPixel = ((int)bmpData.PixelFormat >> 8) & 0xFF;
int channels = bitsPerPixel / 8;
byte[] data = new byte[channels];
int id = p.Y * bmpData.Stride + p.X * channels;
unsafe
{
byte* pData = (byte*)bmpData.Scan0;
for (int i = 0; i < data.Length; i++)
{
data[i] = pData[id + i];
}
}
return data;
}
Really I'm trying to apply 3X3 Median Filtering by C# and depending on my understanding the concepts of Median Filtering I wrote the following code but when I'm running it the Form hangs. I think have some problem in the last nested for loop but i don't know where is the error or the wrong in applying the Median concepts!
public static Bitmap MedianFiltering(Bitmap bm)
{
List<int> termsList = new List<int>();
Bitmap res, temp;
Color c;
int counter = 0;
//Convert to Grayscale
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
c = bm.GetPixel(i, j);
byte gray = (byte)(.333 * c.R + .333 * c.G + .333 * c.B);
bm.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
}
}
temp = bm;
//applying Median Filtering
for (int i = 0; i <= temp.Width - 3; i++)
for (int j = 0; j <= temp.Height - 3; j++)
{
for (int x = i; x <= i + 2; x++)
for (int y = j; y <= j + 2; y++)
{
c = temp.GetPixel(x, y);
termsList.Add(c.R);
counter++;
}
int[] terms = termsList.ToArray();
Array.Sort<int>(terms);
Array.Reverse(terms);
int color = terms[4];
temp.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color));
counter = 0;
}
res = temp;
return res;
}
Thanks.
You are not clearing the termsList after each pixel processing. This is causing the list to keep growing. Sorting and reversing the list will keep taking longer and longer times. This will also cause incorrect results since you only want to get the median of the 9 pixels related to the current pixel.
Simply clear the list like this:
...
int[] terms = termsList.ToArray();
termsList.Clear();
...
UPDATE:
I did more optimization for the code:
public static void MedianFiltering(Bitmap bm)
{
List<byte> termsList = new List<byte>();
byte[,] image = new byte[bm.Width,bm.Height];
//Convert to Grayscale
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
var c = bm.GetPixel(i, j);
byte gray = (byte)(.333 * c.R + .333 * c.G + .333 * c.B);
image[i, j] = gray;
}
}
//applying Median Filtering
for (int i = 0; i <= bm.Width - 3; i++)
for (int j = 0; j <= bm.Height - 3; j++)
{
for (int x = i; x <= i + 2; x++)
for (int y = j; y <= j + 2; y++)
{
termsList.Add(image[x, y]);
}
byte[] terms = termsList.ToArray();
termsList.Clear();
Array.Sort<byte>(terms);
Array.Reverse(terms);
byte color = terms[4];
bm.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color));
}
}
Please note that in your original method, you returned a Bitmap. I removed this.
Please note that temp = bm; does not create a copy of the Bitmap. It is just pointing the temp variable to the same object (that is pointed by bm). So in your original method, you returned the exact object that is passed in the method parameter. To use the new method pass the Bitmap and then the bitmap it self will be modified (this is also true for your method).
This enhanced performance 4 times on my machine.
What I did is mainly read the bitmap data into a byte array instead of using the Bitmap it self to read/write data multiple times.
If you need to further enhance the performance, take a look at this question.
I'm trying to output a new image after applying the adaptive median filter but it only works if the maximum window size is 3*3, but it should work for all odd window sizes, and it does so if the image is so small for example 10*10 pixels, but if the image is for example 440*445 pixels it only works if the max window size is 3*3 otherwise it says index outside bounds of the array, here is my code using counting sort to sort the pixels:
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace ImageFilters
{
public class Class2
{
public byte[,] median(byte[,] array, int width, int height, int msize)
{
byte[,] marr = new byte[height + 1, width + 1];
int size = 3;
for (int i = 0; i <height+1; i++)
{
marr[i, 0] = 255;
}
for (int j = 0; j < width+1; j++)
{
marr[0, j] = 255;
}
int n=0;
int z=0;
for (int k = 0; k < (height) * width; k++)
{
repeat:
byte[] farr = new byte[size * size];
int I=0;
for (int i = n; i < n+size; i++)
{
for (int j = z; j < z+size; j++)
{
if (j < width && i < height)
{
farr[I] = array[i, j];
I++;
}
else
{
farr[I] = 0;
I++;
}
}
}
int zxy = farr[(size*size)/2];
byte[] check = new byte[size * size];
check=counting(farr,size);
int median = 0;
int lennn;
lennn = check.Length;
int min = 99999;
int maxi = -1;
int a1, a2;
min = check.Min();
maxi = check.Max();
median = check[lennn / 2];
a1 = median - min;
a2 = maxi - median;
int b1, b2;
b1 = zxy - min;
b2 = maxi - zxy;
if (a1 > 0 && a2 > 0)
{
if (b1 > 0 && b2 > 0)
{
marr[n + 1, z + 1] = Convert.ToByte(zxy);
z++;
if (z + (size - 1) > (width + 1))
{
n++;
z = 0;
}
}
else
{
marr[n + 1, z + 1] = Convert.ToByte(median);
z++;
if (z + (size - 1) > (width + 1))
{
n++;
z = 0;
}
}
}
else
{
size = size + 2;
if (size <= msize)
goto repeat;
else
{
marr[n +1, z +1] = Convert.ToByte(median);
z++;
if (size > 3)
size = 3;
if (z + (size - 1) > (width + 1))
{
n++;
z = 0;
}
}
}
}
return marr;
}
public static byte[] counting(byte[] array1D, int siz)
{
int max = -10000000;
byte[] SortedArray = new byte[siz * siz];
max = array1D.Max();
byte[] Array2 = new byte[max + 1];
//for (int i = 0; i < Array2.Length; i++)
// Array2[i] = 0; // create new array ( Array2) with zeros in every index .
for (int i = 0; i < (siz*siz); i++)
{
Array2[array1D[i]] += 1; //take the element in the index(i) of(array1d) AS the index of (Array2)
// and increment the element in this index by 1 .
}
for (int i = 1; i <= max; i++)
{
Array2[i] += Array2[i - 1]; // Count every element in (array1d) and put it in (Array2).
}
for (int i = (siz*siz) - 1; i >= 0; i--)
{
SortedArray[Array2[array1D[i]] - 1] = array1D[i]; // transfer the element in index (i) of (array1d) to (SortedArray
Array2[array1D[i]]--;
}
return SortedArray;
}
}
}
Any help will be appreciated, thank you.