For windows phone app, when I am adjusting brightness by slider it works fine when I
move it to right. But when I go back to previous position, instead of image darkening, it goes brighter and brighter. Here is my code based on pixel manipulation.
private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
wrBmp = new WriteableBitmap(Image1, null);
for (int i = 0; i < wrBmp.Pixels.Count(); i++)
{
int pixel = wrBmp.Pixels[i];
int B = (int)(pixel & 0xFF); pixel >>= 8;
int G = (int)(pixel & 0xFF); pixel >>= 8;
int R = (int)(pixel & 0xFF); pixel >>= 8;
int A = (int)(pixel);
B += (int)slider1.Value; R += (int)slider1.Value; G += (int)slider1.Value;
if (R > 255) R = 255; if (G > 255) G = 255; if (B > 255) B = 255;
if (R < 0) R = 0; if (G < 0) G = 0; if (B < 0) B = 0;
wrBmp.Pixels[i] = B | (G << 8) | (R << 16) | (A << 24);
}
wrBmp.Invalidate();
Image1.Source = wrBmp;
}
What am I missing and is there any problem with slider value. I am working with small images as usual in mobiles. I have already tried copying original image to duplicate one. I think code is perfect, after a lot of research I found that the problem is due to slider value.Possible solution is assigning initial value to slider. I want some code help.
private double lastSlider3Vlaue;
private void slider3_ValueChanged(object sender,`RoutedPropertyChangedEventArgs e)
{
if (slider3 == null) return;
double[] contrastArray = { 1, 1.2, 1.3, 1.6, 1.7, 1.9, 2.1, 2.4, 2.6, 2.9 };
double CFactor = 0;
int nIndex = 0;
nIndex = (int)slider3.Value - (int)lastSlider3Vlaue;
if (nIndex < 0)
{
nIndex = (int)lastSlider3Vlaue - (int)slider3.Value;
this.lastSlider3Vlaue = slider3.Value;
CFactor = contrastArray[nIndex];
}
else
{
nIndex = (int)slider3.Value - (int)lastSlider3Vlaue;
this.lastSlider3Vlaue = slider3.Value;
CFactor = contrastArray[nIndex];
}
WriteableBitmap wbOriginal;
wbOriginal = new WriteableBitmap(Image1, null);
wrBmp = new WriteableBitmap(wbOriginal.PixelWidth, wbOriginal.PixelHeight);
wbOriginal.Pixels.CopyTo(wrBmp.Pixels, 0);
int h = wrBmp.PixelHeight;
int w = wrBmp.PixelWidth;
for (int i = 0; i < wrBmp.Pixels.Count(); i++)
{
int pixel = wrBmp.Pixels[i];
int B = (int)(pixel & 0xFF); pixel >>= 8;
int G = (int)(pixel & 0xFF); pixel >>= 8;
int R = (int)(pixel & 0xFF); pixel >>= 8;
int A = (int)(pixel);
R = (int)(((R - 128) * CFactor) + 128);
G = (int)(((G - 128) * CFactor) + 128);
B = (int)(((B - 128) * CFactor) + 128);
if (R > 255) R = 255; if (G > 255) G = 255; if (B > 255) B = 255;
if (R < 0) R = 0; if (G < 0) G = 0; if (B < 0) B = 0;
wrBmp.Pixels[i] = B | (G << 8) | (R << 16) | (A << 24);
}
wrBmp.Invalidate();
Image1.Source = wrBmp;
}
After debugging I found that the r g b values are decreasing continuosly when sliding forward,but when sliding backwards it is also decreasing where as it shoul increase.
please help iam working on this since past last three months.Besides this u also give me advice about how i can complete this whole image processing
Your algorithm is wrong. Each time the slider's value changes, you're adding that value to the picture's brightness. What makes your logic flawed is that the value returned by the slider will always be positive, and you're always adding the brightness to the same picture.
So, if the slider starts with a value of 10, I'll add 10 to the picture's brightness.
Then, I slide to 5. I'll add 5 to the previous picture's brightness (the one you already added 10 of brightness to).
Two ways to solve the issue:
Keep a copy of the original picture, and duplicate it every time your method is called. Then add the brightness to the copy (and not the original). That's the safest way.
Instead of adding the new absolute value of the slider, calculate the relative value (how much it changed since the last time the method was called:
private double lastSliderValue;
private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
var offset = slider1.Value - this.lastSliderValue;
this.lastSliderValue = slider1.Value;
// Insert your old algorithm here, but replace occurences of "slider1.Value" by "offset"
}
This second way can cause a few headaches though. Your algorithm is capping the RGB values to 255. In those cases, you are losing information and cannot revert back to the old state. For instance, take the extreme example of a slider value of 255. The algorithm sets all the pixels to 255, thus generating a white picture. Then you reduce the slider to 0, which should in theory restore the original picture. In this case, you'll subtract 255 to each pixel, but since every pixel's value is 255 you'll end up with a black picture.
Therefore, except if you find a clever way to solve the issue mentionned in the second solution, I'd recommand going with the first one.
Related
I have integer array and I need to convert it to byte array
but I need to take (only and just only) first 11 bit of each element of the هinteger array
and then convert it to a byte array
I tried this code
// ***********convert integer values to byte values
//***********to avoid the left zero padding on the byte array
// *********** first step : convert to binary string
// ***********second step : convert binary string to byte array
// *********** first step
string ByteString = Convert.ToString(IntArray[0], 2).PadLeft(11,'0');
for (int i = 1; i < IntArray.Length; i++)
ByteString = ByteString + Convert.ToString(IntArray[i], 2).PadLeft(11, '0');
// ***********second step
int numOfBytes = ByteString.Length / 8;
byte[] bytes = new byte[numOfBytes];
for (int i = 0; i < numOfBytes; ++i)
{
bytes[i] = Convert.ToByte(ByteString.Substring(8 * i, 8), 2);
}
But it takes too long time (if the file size large , the code takes more than 1 minute)
I need a very very fast code (very few milliseconds only )
can any one help me ?
Basically, you're going to be doing a lot of shifting and masking. The exact nature of that depends on the layout you want. If we assume that we pack little-endian from each int, appending on the left, so two 11-bit integers with positions:
abcdefghijk lmnopqrstuv
become the 8-bit chunks:
defghijk rstuvabc 00lmnopq
(i.e. take the lowest 8 bits of the first integer, which leaves 3 left over, so pack those into the low 3 bits of the next byte, then take the lowest 5 bits of the second integer, then finally the remaining 6 bits, padding with zero), then something like this should work:
using System;
using System.Linq;
static class Program
{
static string AsBinary(int val) => Convert.ToString(val, 2).PadLeft(11, '0');
static string AsBinary(byte val) => Convert.ToString(val, 2).PadLeft(8, '0');
static void Main()
{
int[] source = new int[1432];
var rand = new Random(123456);
for (int i = 0; i < source.Length; i++)
source[i] = rand.Next(0, 2047); // 11 bits
// Console.WriteLine(string.Join(" ", source.Take(5).Select(AsBinary)));
var raw = Encode(source);
// Console.WriteLine(string.Join(" ", raw.Take(6).Select(AsBinary)));
var clone = Decode(raw);
// now prove that it worked OK
if (source.Length != clone.Length)
{
Console.WriteLine($"Length: {source.Length} vs {clone.Length}");
}
else
{
int failCount = 0;
for (int i = 0; i < source.Length; i++)
{
if (source[i] != clone[i] && failCount++ == 0)
{
Console.WriteLine($"{i}: {source[i]} vs {clone[i]}");
}
}
Console.WriteLine($"Errors: {failCount}");
}
}
static byte[] Encode(int[] source)
{
long bits = source.Length * 11;
int len = (int)(bits / 8);
if ((bits % 8) != 0) len++;
byte[] arr = new byte[len];
int bitOffset = 0, index = 0;
for (int i = 0; i < source.Length; i++)
{
// note: this encodes little-endian
int val = source[i] & 2047;
int bitsLeft = 11;
if(bitOffset != 0)
{
val = val << bitOffset;
arr[index++] |= (byte)val;
bitsLeft -= (8 - bitOffset);
val >>= 8;
}
if(bitsLeft >= 8)
{
arr[index++] = (byte)val;
bitsLeft -= 8;
val >>= 8;
}
if(bitsLeft != 0)
{
arr[index] = (byte)val;
}
bitOffset = bitsLeft;
}
return arr;
}
private static int[] Decode(byte[] source)
{
int bits = source.Length * 8;
int len = (int)(bits / 11);
// note no need to worry about remaining chunks - no ambiguity since 11 > 8
int[] arr = new int[len];
int bitOffset = 0, index = 0;
for(int i = 0; i < source.Length; i++)
{
int val = source[i] << bitOffset;
int bitsLeftInVal = 11 - bitOffset;
if(bitsLeftInVal > 8)
{
arr[index] |= val;
bitOffset += 8;
}
else if(bitsLeftInVal == 8)
{
arr[index++] |= val;
bitOffset = 0;
}
else
{
arr[index++] |= (val & 2047);
if(index != arr.Length) arr[index] = val >> 11;
bitOffset = 8 - bitsLeftInVal;
}
}
return arr;
}
}
If you need a different layout you'll need to tweak it.
This encodes 512 MiB in just over a second on my machine.
Overview to the Encode method:
The first thing is does is pre-calculate the amount of space that is going to be required, and allocate the output buffer; since each input contributes 11 bits to the output, this is just some modulo math:
long bits = source.Length * 11;
int len = (int)(bits / 8);
if ((bits % 8) != 0) len++;
byte[] arr = new byte[len];
We know the output position won't match the input, and we know we're going to be starting each 11-bit chunk at different positions in bytes each time, so allocate variables for those, and loop over the input:
int bitOffset = 0, index = 0;
for (int i = 0; i < source.Length; i++)
{
...
}
return arr;
So: taking each input in turn (where the input is the value at position i), take the low 11 bits of the value - and observe that we have 11 bits (of this value) still to write:
int val = source[i] & 2047;
int bitsLeft = 11;
Now, if the current output value is partially written (i.e. bitOffset != 0), we should deal with that first. The amount of space left in the current output is 8 - bitOffset. Since we always have 11 input bits we don't need to worry about having more space than values to fill, so: left-shift our value by bitOffset (pads on the right with bitOffset zeros, as a binary operation), and "or" the lowest 8 bits of this with the output byte. Essentially this says "if bitOffset is 3, write the 5 low bits of val into the 5 high bits of the output buffer"; finally, fixup the values: increment our write position, record that we have fewer bits of the current value still to write, and use right-shift to discard the 8 low bits of val (which is made of bitOffset zeros and 8 - bitOffset "real" bits):
if(bitOffset != 0)
{
val = val << bitOffset;
arr[index++] |= (byte)val;
bitsLeft -= (8 - bitOffset);
val >>= 8;
}
The next question is: do we have (at least) an entire byte of data left? We might not, if bitOffset was 1 for example (so we'll have written 7 bits already, leaving just 4). If we do, we can just stamp that down and increment the write position - then once again track how many are left and throw away the low 8 bits:
if(bitsLeft >= 8)
{
arr[index++] = (byte)val;
bitsLeft -= 8;
val >>= 8;
}
And it is possible that we've still got some left-over; for example, if bitOffset was 7 we'll have written 1 bit in the first chunk, 8 bits in the second, leaving 2 more to write - or if bitOffset was 0 we won't have written anything in the first chunk, 8 in the second, leaving 3 left to write. So, stamp down whatever is left, but do not increment the write position - we've written to the low bits, but the next value might need to write to the high bits. Finally, update bitOffset to be however many low bits we wrote in the last step (which could be zero):
if(bitsLeft != 0)
{
arr[index] = (byte)val;
}
bitOffset = bitsLeft;
The Decode operation is the reverse of this logic - again, calculate the sizes and prepare the state:
int bits = source.Length * 8;
int len = (int)(bits / 11);
int[] arr = new int[len];
int bitOffset = 0, index = 0;
Now loop over the input:
for(int i = 0; i < source.Length; i++)
{
...
}
return arr;
Now, bitOffset is the start position that we want to write to in the current 11-bit value, so if we start at the start, it will be 0 on the first byte, then 8; 3 bits of the second byte join with the first 11-bit integer, so the 5 bits become part of the second - so bitOffset is 5 on the 3rd byte, etc. We can calculate the number of bits left in the current integer by subtracting from 11:
int val = source[i] << bitOffset;
int bitsLeftInVal = 11 - bitOffset;
Now we have 3 possible scenarios:
1) if we have more than 8 bits left in the current value, we can stamp down our input (as a bitwise "or") but do not increment the write position (as we have more to write for this value), and note that we're 8-bits further along:
if(bitsLeftInVal > 8)
{
arr[index] |= val;
bitOffset += 8;
}
2) if we have exactly 8 bits left in the current value, we can stamp down our input (as a bitwise "or") and increment the write position; the next loop can start at zero:
else if(bitsLeftInVal == 8)
{
arr[index++] |= val;
bitOffset = 0;
}
3) otherwise, we have less than 8 bits left in the current value; so we need to write the first bitsLeftInVal bits to the current output position (incrementing the output position), and whatever is left to the next output position. Since we already left-shifted by bitOffset, what this really means is simply: stamp down (as a bitwise "or") the low 11 bits (val & 2047) to the current position, and whatever is left (val >> 11) to the next if that wouldn't exceed our output buffer (padding zeros). Then calculate our new bitOffset:
else
{
arr[index++] |= (val & 2047);
if(index != arr.Length) arr[index] = val >> 11;
bitOffset = 8 - bitsLeftInVal;
}
And that's basically it. Lots of bitwise operations - shifts (<< / >>), masks (&) and combinations (|).
If you wanted to store the least significant 11 bits of an int into two bytes such that the least significant byte has bits 1-8 inclusive and the most significant byte has 9-11:
int toStore = 123456789;
byte msb = (byte) ((toStore >> 8) & 7); //or 0b111
byte lsb = (byte) (toStore & 255); //or 0b11111111
To check this, 123456789 in binary is:
0b111010110111100110100010101
MMMLLLLLLLL
The bits above L are lsb, and have a value of 21, above M are msb and have a value of 5
Doing the work is the shift operator >> where all the binary digits are slid to the right 8 places (8 of them disappear from the right hand side - they're gone, into oblivion):
0b111010110111100110100010101 >> 8 =
0b1110101101111001101
And the mask operator & (the mask operator works by only keeping bits where, in each position, they're 1 in the value and also 1 in the mask) :
0b111010110111100110100010101 &
0b000000000000000000011111111 (255) =
0b000000000000000000000010101
If you're processing an int array, just do this in a loop:
byte[] bs = new byte[ intarray.Length*2 ];
for(int x = 0, b=0; x < intarray.Length; x++){
int toStore = intarray[x];
bs[b++] = (byte) ((toStore >> 8) & 7);
bs[b++] = (byte) (toStore & 255);
}
How can I convert this matlab code to AForge.net+c# code?
cdf1 = cumsum(hist1) / numel(aa);
I found that there is Histogram.cumulative method is present in Accord.net.
But I dont know how to use.
Please teaching how to convert.
% Histogram Matching
%
clear
clc
close all
pkg load image
% 이미지 로딩
aa=imread('2.bmp');
ref=imread('ref2.png');
figure(1); imshow(aa); colormap(gray)
figure(2); imshow(ref); colormap(gray)
M = zeros(256,1,'uint8'); % Store mapping - Cast to uint8 to respect data type
hist1 = imhist(aa); % Compute histograms
hist2 = imhist(ref);
cdf1 = cumsum(hist1) / numel(aa); % Compute CDFs
cdf2 = cumsum(hist2) / numel(ref);
% Compute the mapping
for idx = 1 : 256
[~,ind] = min(abs(cdf1(idx) - cdf2));
M(idx) = ind-1;
end
% Now apply the mapping to get first image to make
% the image look like the distribution of the second image
out = M(double(aa)+1);
figure(3); imshow(out); colormap(gray)
Actually, I don't have a great knowledge of Accord.NET, but reading the documentation I think that ImageStatistics class is what you are looking for (reference here). The problem is that it cannot build a single histogram for the image and you have to do it by yourself. imhist in Matlab just merges the three channels and then counts the overall pixel occurrences so this is what you should do:
Bitmap image = new Bitmap(#"C:\Path\To\Image.bmp");
ImageStatistics statistics = new ImageStatistics(image);
Double imagePixels = (Double)statistics.PixelsCount;
Int32[] histR = statistics.Red.Values.ToArray();
Int32[] histG = statistics.Green.Values.ToArray();
Int32[] histB = statistics.Blue.Values.ToArray();
Int32[] histImage = new Int32[256];
for (Int32 i = 0; i < 256; ++i)
histImage[i] = histR[i] + histG[i] + histB[i];
Double cdf = new Double[256];
cdf[0] = (Double)histImage[0];
for (Int32 i = 1; i < 256; ++i)
cdf[i] = (Double)(cdf[i] + cdf[i - 1]);
for (Int32 i = 0; i < 256; ++i)
cdf[i] = cdf[i] / imagePixels;
In C#, an RGB value can be built from R, G and B channel values as follows:
public static int ChannelsToRGB(Int32 red, Int32 green, Int32 blue)
{
return ((red << 0) | (green << 8) | (blue << 16));
}
I'm trying to convert a RenderTargetBitmap to a byte array that will then get sent off to an external monochrome OLED screen. I know that for the bitmap to display correctly the bit/byte alignment should be LSB to MSB & Top to Bottom:
But I can't figure out how to get the RenderTargetBitmap's pixeldata in that format.
For the moment I've got:
RenderTargetBitmap renderTargetBitmap; //This is already set higher up
DataReader reader = DataReader.FromBuffer(await renderTargetBitmap.GetPixelsAsync());
// Placeholder for reading pixels
byte[] pixel = new byte[4]; // RGBA8
// Write out pixels
int index = 0;
byte[] array = new byte[renderTargetBitmap.PixelWidth*renderTargetBitmap.PixelHeight];
using (reader)
{
//THIS IS WHERE I THINK I'M SCREWING UP
for (int x = 0; x < rHeight; x++)
{
for (int y = 0; x < rWidth; y++)
{
reader.ReadBytes(pixel);
if (pixel[2] == 255)
array[index] = 0xff;
else
array[index] = 0x00;
index++;
}
}
}
sh1106.ShowBitmap(buffer); //Send off the byte array
I faced the same issue, this is what I did to get it working (It will convert the BGRA8 output to a 1BPP output that can then be used on a monochrome display, SSD1306 in my case)
At 1BPP output means that 8 pixels are stored in 1 byte. So you need to convert every 4 bytes into 1 bit.
public async Task Draw()
{
ActiveCanvas.UpdateLayout();
ActiveCanvas.Measure(ActiveCanvas.DesiredSize);
ActiveCanvas.Arrange(new Rect(new Point(0, 0), ActiveCanvas.DesiredSize));
// Create a render bitmap and push the surface to it
RenderTargetBitmap renderBitmap = new RenderTargetBitmap();
await renderBitmap.RenderAsync(ActiveCanvas, (int)ActiveCanvas.DesiredSize.Width, (int)ActiveCanvas.DesiredSize.Height);
DataReader bitmapStream = DataReader.FromBuffer(await renderBitmap.GetPixelsAsync());
if (_device != null)
{
byte[] pixelBuffer_1BPP = new byte[(int)(renderBitmap.PixelWidth * renderBitmap.PixelHeight) / 32];
pixelBuffer_1BPP.Initialize();
using (bitmapStream)
{
while (bitmapStream.UnconsumedBufferLength > 0)
{
uint index = (uint)(renderBitmap.PixelWidth * renderBitmap.PixelHeight * 4) - bitmapStream.UnconsumedBufferLength;
for (int bit = 0; bit < 8; bit++)
{
bitmapStream.ReadBytes(BGRA8);
byte value = (byte)(((BGRA8[0] & 0x80) | (BGRA8[1] & 0x80) | (BGRA8[2] & 0x80)) == 0x80 ? 1 : 0);
pixelBuffer_1BPP[index] |= (byte)(value << (7 - bit));
}
}
_device.DrawBitmap(0, 0, pixelBuffer_1BPP, (short)renderBitmap.PixelWidth, (short)renderBitmap.PixelHeight, Colors.White);
}
}
}
Is one of these decidedly faster?
var scan0 = (uint*)bitmapData.Scan0;
int length = pixels.Length;
for (int i = 0; i < length; i++)
{
uint j = scan0[i];
float a = (j >> 24) / 255f;
pixels[i] = new Vector(
(j >> 16 & 0xff) * a / 255,
(j >> 8 & 0xff) * a / 255,
(j & 0xff) * a / 255);
}
versus
var scan0 = (byte*)bitmapData.Scan0;
int length = pixels.Length * 4;
for (int i = 0; i < length; i += 4)
{
float a = scan0[i + 3] / 255f;
pixels[i / 4] = new Vector(
scan0[i + 2] * a / 255,
scan0[i + 1] * a / 255,
scan0[i] * a / 255);
}
In a 32 bit application, the second is about 2.5 times faster than the first. In a 64 bit application, the second is about 25% faster than the first.
Note that there is a bug in your second code. As you are adding four in each iteration, you will place the objects in every fourth item in the pixels array, and cause an IndexOutOfRangeException exception when it runs out of array.
Slightly faster (about 5%) than the second is to move the pointer for each pixel:
byte* scan0 = (byte*)bitmapData.Scan0;
for (int i = 0; i < pixels.Length; i++) {
float a = scan0[3] / 255f;
pixels[i] = new Vector(
scan0[2] * a / 255,
scan0[1] * a / 255,
scan0[0] * a / 255
);
scan0 += 4;
}
Note also that if you are reading data from a Bitmap image, it is not stored as a continuous array of pixel data. There may be padding between the scan lines, so the code can only read pixels from a single scan line, it can not safely read data from an entire image.
Edit:
Also, I just realised that you put the length of the array in a variable and used that in the loop. That will just make the code slower instead of faster, as the compiler can't optimise away the range check on the array accesses.
I think the bit shift "Your first solution" is faster. however you can test it by using Stopwatch. Start the stopwatch before the call the method, run the method multiple time, and then stop the watch and check its ElapcedMilliseconds. Like:
System.Diagnostics.Stopwatch watch = Stopwatch.StartNew();
//run your method that want to test its executable time multi time
for (int testIndex = 0; testIndex < 100; testIndex++)
{
TestWithShift();
}
watch.Stop();
Console.WriteLine("Test with shift time: {0}", watch.ElapcedMilliseconds);
And repeat the test for the other method. Hope that helps.
I've asked before about the opposite of Bitwise AND(&) and you told me its impossible to reverse.
Well,this is the situation: The server sends an image,which is encoded with the function I want to reverse,then it is encoded with zlib.
This is how I get the image from the server:
UInt32[] image = new UInt32[200 * 64];
int imgIndex = 0;
byte[] imgdata = new byte[compressed];
byte[] imgdataout = new byte[uncompressed];
Array.Copy(data, 17, imgdata, 0, compressed);
imgdataout = zlib.Decompress(imgdata);
for (int h = 0; h < height; h++)
{
for (int w = 0; w < width; w++)
{
imgIndex = (int)((height - 1 - h) * width + w);
image[imgIndex] = 0xFF000000;
if (((1 << (Int32)(0xFF & (w & 0x80000007))) & imgdataout[((h * width + w) >> 3)]) > 0)
{
image[imgIndex] = 0xFFFFFFFF;
}
}
}
Width,Height,Image decompressed and Image compressed length are always the same.
When this function is done I put image(UInt32[] array) in a Bitmap and I've got it.
Now I want to be the server and send that image.I have to do two things:
Reverse that function and then compress it with zlib.
How do I reverse that function so I can encode the picture?
for (int h = 0; h < height; h++)
{
for (int w = 0; w < width; w++)
{
imgIndex = (int)((height - 1 - h) * width + w);
image[imgIndex] = 0xFF000000;
if (((1 << (Int32)(0xFF & (w & 0x80000007))) & imgdataout[((h * width + w) >> 3)]) > 0)
{
image[imgIndex] = 0xFFFFFFFF;
}
}
}
EDIT:The format is 32bppRGB
The assumption that the & operator is always irreversible is incorrect.
Yes, in general if you have
c = a & b
and all you know is the value of c, then you cannot know what values a or b had before hand.
However it's very common for & to be used to extract certain bits from a longer value, where those bits were previously combined together with the | operator and where each 'bit field' is independent of every other. The fundamental difference with the generic & or | operators that makes this reversible is that the original bits were all zero beforehand, and the other bits in the word are left unchanged. i.e:
0xc0 | 0x03 = 0xc3 // combine two nybbles
0xc3 & 0xf0 = 0xc0 // extract the top nybble
0xc3 & 0x0f = 0x03 // extract the bottom nybble
In this case your current function appears to be extracting a 1 bit-per-pixel (monochrome image) and converting it to 32-bit RGBA.
You'll need something like:
int source_image[];
byte dest_image[];
for (int h = 0; h < height; ++h) {
for (int w = 0; w < width; ++w) {
int offset = (h * width) + w;
if (source_image[offset] == 0xffffffff) {
int mask = w % 8; // these two lines convert from one int-per-pixel
offset /= 8; // offset to one-bit-per-pixel
dest_image[offset] |= (1 << mask); // only changes _one_ bit
}
}
}
NB: assumes the image is a multiple of 8 pixels wide, that the dest_image array was previously all zeroes. I've used % and / in that inner test because it's easier to understand and the compiler should convert to mask / shift itself. Normally I'd do the masking and shifting myself.