Converting iTextSharp.text.Image back to System.Drawing.Image - c#

I am trying to convert object of type iTextSharp.text.Image back to System.Drawing.Image.
Here is a chunk of code that is not working:
System.Drawing.Image img = System.Drawing.Image.FromStream(new MemoryStream(itextImg.RawData));
I could be going about this all wrong, but I won't know unless I consult the experts, and after two hours of fruitless searching online, I am finally posting it myself as a question.

I'm pretty sure that will work occasionally, but will fail in the general case... it depends on what compression filters the image is using.
I believe JPEG image streams are exactly what you'd see in a .jpeg file... but for most (all?) other compression types, the image information (height, width, bits per component, number of components, etc) is vital.
So it'll be possible, but Not Like That.
PS: There's at least one image format that iText cannot decompress, CITTFAXDecode (JBIG2, probably others). In those cases, you'll need some Other Software that will get the raw pixel data out so you can wrap it in a Drawing.Image.

Yes, I found the solution by rewriting BarcodeQRCode class of ITextSharp and GetImageMethod() as described below:
using System;
using System.Collections.Generic;
using System.Drawing;
using iTextSharp.text;
using iTextSharp.text.pdf.qrcode;
using iTextSharp.text.pdf.codec;
/*
Class rewritted to Convert ByteMatrix to BMP image by rewritting GetImage method
from ITextSharp
author: Luis Claudio Souza
*/
namespace iTextSharp.text.pdf{
/**
* A QRCode implementation based on the zxing code.
* #author Paulo Soares
* #since 5.0.2
*/
public class BarcodeQRCode {
ByteMatrix bm;
/**
* Creates the QR barcode. The barcode is always created with the smallest possible size and is then stretched
* to the width and height given. Set the width and height to 1 to get an unscaled barcode.
* #param content the text to be encoded
* #param width the barcode width
* #param height the barcode height
* #param hints modifiers to change the way the barcode is create. They can be EncodeHintType.ERROR_CORRECTION
* and EncodeHintType.CHARACTER_SET. For EncodeHintType.ERROR_CORRECTION the values can be ErrorCorrectionLevel.L, M, Q, H.
* For EncodeHintType.CHARACTER_SET the values are strings and can be Cp437, Shift_JIS and ISO-8859-1 to ISO-8859-16. The default value is
* ISO-8859-1.
* #throws WriterException
*/
public BarcodeQRCode(String content, int width, int height, IDictionary<EncodeHintType, Object> hints) {
QRCodeWriter qc = new QRCodeWriter();
bm = qc.Encode(content, width, height, hints);
}
private byte[] GetBitMatrix() {
int width = bm.GetWidth();
int height = bm.GetHeight();
int stride = (width + 7) / 8;
byte[] b = new byte[stride * height];
sbyte[][] mt = bm.GetArray();
for (int y = 0; y < height; ++y) {
sbyte[] line = mt[y];
for (int x = 0; x < width; ++x) {
if (line[x] != 0) {
int offset = stride * y + x / 8;
b[offset] |= (byte)(0x80 >> (x % 8));
}
}
}
return b;
}
/** Gets an <CODE>Image</CODE> with the barcode.
* #return the barcode <CODE>Image</CODE>
* #throws BadElementException on error
*/
public void GetImage()
{
sbyte[][] imgNew = bm.GetArray();
Bitmap bmp1 = new Bitmap(bm.GetWidth(), bm.GetHeight());
Graphics g1 = Graphics.FromImage(bmp1);
g1.Clear(Color.White);
for (int i = 0; i <= imgNew.Length - 1; i++)
{
for (int j = 0; j <= imgNew[i].Length - 1; j++)
{
if (imgNew[j][i] == 0)
{
g1.FillRectangle(Brushes.Black, i, j, 1, 1);
}
else
{
g1.FillRectangle(Brushes.White, i, j, 1, 1);
}
}
}
bmp1.Save("D:\\QREncode.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
After that, I used this code to call the method:
var hints = new Dictionary<EncodeHintType, object>();
hints.Add(EncodeHintType.ERROR_CORRECTION, iTextSharp.text.pdf.qrcode.ErrorCorrectionLevel.H);
BarcodeQRCode code = new BarcodeQRCode("98134979213479523874952873", 100, 100, hints);
code.GetImage();
In new GetImage method, you can choose what to do with the bmp class. In this case, it saves a JPEG image file but the method can either return a memorystream to be used by the caller.

Related

Converting 32bit TIFF to Bitmap

I have a 32bit .tif file which is displayed in the image below by first ImageJ, and secondly my program. As you can guess, the way ImageJ displays the picture is correct.
I am converting the file to a Bitmap like this:
private Bitmap TiffToBmp()
{
Bitmap bmp;
int width;
int height;
float[] scanline32Bit;
float[] buffer;
using (Tiff original = Tiff.Open(file, "r"))
{
width = original.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
height = original.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
byte[] scanline = new byte[original.ScanlineSize()];
scanline32Bit = new float[original.ScanlineSize() / 4];
buffer = new float[width * height];
for (int i = 0; i < height; i++) //loading the data into a buffer
{
original.ReadScanline(scanline, i);
Buffer.BlockCopy(scanline, 0, scanline32Bit, 0, scanline.Length);
for (int j = 0; j < width; j++)
{
buffer[i * width + j] = scanline32Bit[j];
}
}
}
bmp = new Bitmap(width, height);
BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);
byte[] bytes = new byte[data.Height * data.Stride];
for (int y = 0; y < data.Height; y++) //creating Bitmap from buffer
{
for (int x = 0; x < data.Stride; x += 4)
{
bytes[y * data.Stride + x] = (byte)buffer[(y * data.Stride + x) / 4];
bytes[y * data.Stride + x + 1] = (byte)buffer[(y * data.Stride + x) / 4];
bytes[y * data.Stride + x + 2] = (byte)buffer[(y * data.Stride + x) / 4];
bytes[y * data.Stride + x + 3] = 255;
}
}
Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);
bmp.UnlockBits(data);
return bmp;
}
Using a RGBA Bitmap might seem a bit naive but it's necessary in further steps of the program. Also worth mentioning: XnView displays the file similar to mine, just the negative (from white to black instead of black to white). When opening the file it notices me that it converts the image to RGB with 8bits per channel (the same thing I'm doing) and falsely claims the .tif is 16bit instead of 32bit.
Has someone an idea of what I am doing wrong?
It seems to me that the error comes purely from some kind of misuse of structs or wrongly converting between them (from float to byte and so on).
I am using BitMiracle.LibTiff.Classic from the the .NET version of original libtiff library
edit: after some research I found out that original.ReadScanline(scanline, i) returns seemingly weird values and converts them via Buffer.BlockCopy(...) to the stripes appearing in the image. For example the 4 bytes (read from scanline) of the pixel (x = 0, y = 0) are 0, 0, 200, 6, the corresponding 8bit pixel value (read from scanline32Bit) turns out to be 110. Of Pixel (x = width, y = 0) the 4 bytes are 0, 128, 111, 68 and the 8bit value displayed is 958 corresponding to 190. So now I think there's something wrong with one of those steps but I actually have no idea what's going on.
Assuming you don't mind using existing code, there is this: https://www.codeproject.com/Articles/8279/ImageConverter-Converts-images-to-a-specific-image
The author (not me, BTW) provides both the C# source and an executable. I used the executable to convert a TIF (created using paint.net) to a BMP, so I presume the source will be useful to you. I was able to open the author's solution using VS 2017 (VS upgraded both the solution and project to work in the current VS environment). The conversion is based on the System.Drawing.Imaging.ImageFormat class

Merging multiple Images

I'm trying to merge multiple Images into one image. Problem is that most libraries with such functionality are not available in a Windows 8.1 App. I'd prefer to not have to use external libraries such as WriteableBitmapEx
This is my current code which unfortunately doesn't work:
int count = 4;
int size = 150;
WriteableBitmap destination = new WriteableBitmap(300, 300);
BitmapFrame frame = await (await BitmapDecoder.CreateAsync(randomAccessStream)).GetFrameAsync(0);
PixelDataProvider pixelData = await frame.GetPixelDataAsync();
byte[] test = pixelData.DetachPixelData();
MemoryStream mem = new MemoryStream();
for (int row = 0; row < frame.PixelHeight; row++) {
for (int i = 0; i < count; i++)
{
mem.Write(test, row * (int)frame.PixelWidth * 4, (int)frame.PixelWidth * 4);
}
}
mem.Seek(0, SeekOrigin.Begin);
BitmapImage bmp = new BitmapImage();
bmp.SetSourceAsync(mem.AsRandomAccessStream());
If I set the bmp as the source of an Image UIElement nothing happens.
My Idea was to get the Pixeldata as a byte array and to write it line by line (pixel row of each image, so they'd be next to each other) to a memory stream which is then used as the source of the BitmapImage.
Solved
Thanks to Aditya and Romasz I could solve this.
The problem was that I had to encode the pixel data back to an image.
If anyone has the same Problem the following class merges the pixel data of multiple images and returns a BitmapImage:
public class ImageMerger
{
public static async Task<BitmapImage> MergeImages(int singleWidth, int singleHeight, params byte[][] pixelData)
{
int perRow = (int) Math.Ceiling(Math.Sqrt(pixelData.Length));
byte[] mergedImageBytes = new byte[singleHeight * singleWidth * perRow * perRow * 4];
for (int i = 0; i < pixelData.Length; i++ )
{
LoadPixelBytesAt(ref mergedImageBytes, pixelData[i], (i % perRow) * singleWidth, (i / perRow) * singleHeight, perRow * singleWidth, singleWidth, singleHeight);
}
InMemoryRandomAccessStream mem = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, mem);
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)(singleHeight * perRow), (uint)(singleWidth * perRow), 91, 91, mergedImageBytes);
await encoder.FlushAsync();
BitmapImage bmp = new BitmapImage();
bmp.SetSourceAsync(mem);
return bmp;
}
private static void LoadPixelBytesAt(ref byte[] dest, byte[] src, int destX, int destY, int destW, int srcW, int srcH)
{
for (int i = 0; i < srcH; i++)
{
for (int j = 0; j < srcW; j++)
{
if (src.Length < ((i * srcW + j + 1) * 4)) return;
for (int p = 0; p < 4; p++)
dest[((destY + i) * destW + destX + j) * 4 + p] = src[(i * srcW + j) * 4 + p];
}
}
}
}
This takes any number of images and puts them next to each other with around as many images from left to right as from top to bottom.
I.e. for 4 images it would return an image with them aligned like this:
1 2
3 4
Works for all of my images but one. There is one image that looks pretty weird after getting merged with others. Didn't figure out why yet.
This should do it :
byte[] PutOnCanvas(byte[] Canvas,byte[] Image,uint x,uint y,uint imageheight,uint imagewidth,uint CanvasWidth)
{
for (uint row = y; row < y+imageheight; row++)
for (uint col = x; col < x+imagewidth; col++)
for (int i = 0; i < 4; i++)
Canvas[(row * CanvasWidth + col) * 4 + i] = Image[((row-y) * imagewidth + (col - x)) * 4 + i];
return Canvas;
}
Now say I want to put two images (pixelbytes in Image1 and Image2) of 30x30 side by side and have a vertical margin of 10px in between them. I would call the function in the following way:
byte[] Canvas = new byte[30 * 70 * 4];
Canvas=PutOnCanvas(Canvas,Image1,0,0,30,30,70);
Canvas=PutOnCanvas(Canvas,Image2,40,0,30,30,70);
Then convert pixel bytes to BMP and you should be done!
Edit:
And this is the correct way to convert pixel bytes to image:
memStream.Size = 0;
var encoder = await BitmapEncoder.CreateAsync(Windows.Graphics.Imaging.BitmapEncoder.JpegEncoderId, memStream);
encoder.SetPixelData(
Windows.Graphics.Imaging.BitmapPixelFormat.Bgra8,
Windows.Graphics.Imaging.BitmapAlphaMode.Straight,
CanvasWidth, // pixel width
CanvasHeight, // pixel height
96, // horizontal DPI
96, // vertical DPI
PixelData);
try { await encoder.FlushAsync(); }
catch { }
memStream.Dispose();
Tried this method awhile ago and it worked for me.
http://www.codeproject.com/Articles/502249/Combineplusseveralplusimagesplustoplusformplusaplu
One option is to draw them in a Canvas like you normally would and then render that Canvas out. The only problem with this is that they must all be on the screen at the same time.
Unfortunately, that's about it as far as simple solutions without something like WriteableBitmapEx goes. Their BitmapContext class abstracts away a lot of the more complex math that goes on when changing an image's width. You can check out WinRTXamlToolkit's blit implementation here, but it has the limitation that the source and destination files must be the same width (due to the annoying math).
One option may be to try and up the size of the images without scaling, hopefully creating some whitespace in the proper spot, then layering them together using a facsimile of that blit implementation, but this seems like it will be a lot of trouble as well.
Your best bet, IMO, is to cut out the chunks of WriteableBitmapEx that you need, specifically their BitmapContext and the Blit Extensions that they provide, then create a blank image and overlay each image onto the destination image (as you are attempting to do now).
This is not legal advice.
WriteableBitmapEx is Microsoft License, which is very permissive, so you should be okay to do this.
Anyway, it'd likely be easier to just add the reference, but if it's necessary that you don't, you can still cut out the parts that you need (in this case) and use them 'a la carte'.

Rotate raw pixel data of an image 180 degrees

I'm trying to rotate raw pixel data from a DICOM file by 180 degrees (or flipped). I've successfully flipped the image correctly, however, upon writing the pixel data back to the file (in this case it's a DICOM file) and displaying it. The final output of the image is not correct.
Below is the sample a sample of the image I'm trying to flip 180 /mirror.
Here's the code I'm using to perform the flipping:
string file = #"adicomfile.dcm";
DicomFile df = new DicomFile();
df.Load(file);
// Get the amount of bits per pixel from the DICOM header.
int bitsPerPixel = df.DataSet[DicomTags.BitsAllocated].GetInt32(0, 0);
// Get the raw pixel data from the DICOM file.
byte[] bytes = df.DataSet[DicomTags.PixelData].Values as byte[];
// Get the width and height of the image.
int width = df.DataSet[DicomTags.Columns].GetInt32(0, 0);
int height = df.DataSet[DicomTags.Rows].GetInt32(0, 0);
byte[] original = bytes;
byte[] mirroredPixels = new byte[width * height * (bitsPerPixel / 8)];
width *= (bitsPerPixel / 8);
// The mirroring / image flipping.
for (int i = 0; i < original.Length; i++)
{
int mod = i % width;
int x = ((width - mod - 1) + i) - mod;
mirroredPixels[i] = original[x];
}
df.DataSet[DicomTags.PixelData].Values = mirroredPixels;
df.Save(#"flippedicom.dcm", DicomWriteOptions.Default);
And here's my output (incorrect). The white and distortion is not the desired output.
I'm using ClearCanvas DICOM library, however this shouldn't matter as I'm only trying to manipulate the raw pixel data contained within the file itself.
The desired output would preferably look like the original, but flipped 180 / mirrored.
Some assistance would be greatly appreciated. I've tried my best searching SO, but to no avail.
It took a while, but I ended up solving my problem by using a method from a Java library. You can see the class here.
string file = #"adicomfile.dcm";
DicomFile df = new DicomFile();
df.Load(file);
// Get the amount of bits per pixel from the DICOM header.
int bitsPerPixel = df.DataSet[DicomTags.BitsAllocated].GetInt32(0, 0);
// Get the raw pixel data from the DICOM file.
byte[] bytes = df.DataSet[DicomTags.PixelData].Values as byte[];
// Get the width and height of the image.
int width = df.DataSet[DicomTags.Columns].GetInt32(0, 0);
int height = df.DataSet[DicomTags.Rows].GetInt32(0, 0);
byte[] newBytes = new byte[height * width * (bitsPerPixel / 8)];
int stride = bitsPerPixel / 8;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width * stride; x++)
{
newBytes[((height - y - 1) * (width * stride)) + x] = bytes[(y * (width * stride)) + x];
}
}
// Set patient orientation.
df.DataSet[DicomTags.PatientOrientation].Values = #"A\L";
// The pixel data of the DICOM file to the flipped/mirrored data.
df.DataSet[DicomTags.PixelData].Values = mirroredPixels;
// Save the DICOM file.
df.Save(#"flippedicom.dcm", DicomWriteOptions.Default);
The output was correct and I was able to continue other modifications to the raw pixel data.
Thank you all for the pointers.

How to render audio waveform?

Is there any audio/programming-related stack-exchange site?
I'm trying to make a wave form in WinForms
What algorithm should I use?
For example, if I have 200 samples per pixel (vertical line), should I draw the lowest and the highest sample from that portion of 200 samples? Or should I draw average of low and high samples? Maybe both in different colors?
This will help you to generate waveform from audio file using nAudio in C#...
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string strPath = Server.MapPath("audio/060.mp3");
string SongID = "2";
byte[] bytes = File.ReadAllBytes(strPath);
WriteToFile(SongID,strPath, bytes);
Response.Redirect("Main.aspx");
}
private void WriteToFile(string SongID, string strPath, byte[] Buffer)
{
try
{
int samplesPerPixel = 128;
long startPosition = 0;
//FileStream newFile = new FileStream(GeneralUtils.Get_SongFilePath() + "/" + strPath, FileMode.Create);
float[] data = FloatArrayFromByteArray(Buffer);
Bitmap bmp = new Bitmap(1170, 200);
int BORDER_WIDTH = 5;
int width = bmp.Width - (2 * BORDER_WIDTH);
int height = bmp.Height - (2 * BORDER_WIDTH);
NAudio.Wave.Mp3FileReader reader = new NAudio.Wave.Mp3FileReader(strPath, wf => new NAudio.FileFormats.Mp3.DmoMp3FrameDecompressor(wf));
NAudio.Wave.WaveChannel32 channelStream = new NAudio.Wave.WaveChannel32(reader);
int bytesPerSample = (reader.WaveFormat.BitsPerSample / 8) * channelStream.WaveFormat.Channels;
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.White);
Pen pen1 = new Pen(Color.Gray);
int size = data.Length;
string hexValue1 = "#009adf";
Color colour1 = System.Drawing.ColorTranslator.FromHtml(hexValue1);
pen1.Color = colour1;
Stream wavestream = new NAudio.Wave.Mp3FileReader(strPath, wf => new NAudio.FileFormats.Mp3.DmoMp3FrameDecompressor(wf));
wavestream.Position = 0;
int bytesRead1;
byte[] waveData1 = new byte[samplesPerPixel * bytesPerSample];
wavestream.Position = startPosition + (width * bytesPerSample * samplesPerPixel);
for (float x = 0; x < width; x++)
{
short low = 0;
short high = 0;
bytesRead1 = wavestream.Read(waveData1, 0, samplesPerPixel * bytesPerSample);
if (bytesRead1 == 0)
break;
for (int n = 0; n < bytesRead1; n += 2)
{
short sample = BitConverter.ToInt16(waveData1, n);
if (sample < low) low = sample;
if (sample > high) high = sample;
}
float lowPercent = ((((float)low) - short.MinValue) / ushort.MaxValue);
float highPercent = ((((float)high) - short.MinValue) / ushort.MaxValue);
float lowValue = height * lowPercent;
float highValue = height * highPercent;
g.DrawLine(pen1, x, lowValue, x, highValue);
}
}
string filename = Server.MapPath("image/060.png");
bmp.Save(filename);
bmp.Dispose();
}
catch (Exception e)
{
}
}
public float[] FloatArrayFromStream(System.IO.MemoryStream stream)
{
return FloatArrayFromByteArray(stream.GetBuffer());
}
public float[] FloatArrayFromByteArray(byte[] input)
{
float[] output = new float[input.Length / 4];
for (int i = 0; i < output.Length; i++)
{
output[i] = BitConverter.ToSingle(input, i * 4);
}
return output;
}
}
Try dsp.stackexchange.com
At 200 samples per pixel, there are several approaches you can try. Whatever you do, it often works best to draw each vertical line both above and below 0, ie. treat positive and negative sample values seperately. Probably the easiest is to just calculate an RMS. At such a low resolution peak values will probably give you a misleading representation of the waveform.
You can use AudioControl from code project.
and see this one: Generating various audio waveforms in C#
these projects may be useful for you if implement your code originally:
High-Speed-Feature-Rich-and-Easy-To-Use-Graphs
and this
Incase anyone runs into this:
You can treat the samples per pixel as your zoom level, at higher levels (zoomed out more) you will probably want to subsample that for performance reasons.
You will most likely want a fixed width that fits on the screen to draw on and use virtual scrolling (so you don't potentially have a draw area of several million pixels).
You can calculate the value for each pixel by iterating over the audio data with: skip (scroll position * samples per pixel) + (pixel * samples per pixel) take samples per pixel.
This allows for performant infinite zoom and scroll as you only read and draw the minimum amount to fill the view.
The scroll width is calculated with audio data length / samples per pixel.
Audio samples are generally shown in one of two ways, the peak value of the sample range or the rms value. The rms value is calculated by summing the squares of all values in the sample range, divide the sum by sample length, the rms value if the squareroot of this (rms will be a bit higher than average and is a good measure of perceived loudness)
You can increase performance in multiple ways such as increasing sub sampling (causes loss of detail), throttling the scroll and making the draw requests cancelable incase new scroll fires before previous is rendered.
just to document it, if you want to make the audio file fill the width of the output image
samplesPerPixel = (reader.Length / bytesPerSample) / width ;

Converting an array of Pixels to an image in C#

I have an array of int pixels in my C# program and I want to convert it into an image. The problem is I am converting Java source code for a program into equivalent C# code. In java the line reads which displays the array of int pixels into image:
Image output = createImage(new MemoryImageSource(width, height, orig, 0, width));
can someone tell me the C# equivalent?
Here orig is the array of int pixels. I searched the Bitmap class and there is a method called SetPixel but the problem is it takes a x,y coordinate number. But what I have in my code is an array of int pixels. Another weird thing is my orig array has negative number and they are way far away from 255. In Java this is the same case (meaning both the array in C# and Java have equivalent value) and the values is working fine in Java.
But I can't get that line translated into C#. Please help.
Using WPF, you can create a bitmap (image) directly from your array. You can then encode this image or display it or play with it:
int width = 200;
int height = 200;
//
// Here is the pixel format of your data, set it to the proper value for your data
//
PixelFormat pf = PixelFormats.Bgr32;
int rawStride = (width * pf.BitsPerPixel + 7) / 8;
//
// Here is your raw data
//
int[] rawImage = new int[rawStride * height / 4];
//
// Create the BitmapSource
//
BitmapSource bitmap = BitmapSource.Create(
width, height,
96, 96, pf, null,
rawImage, rawStride);
You can use Bitmap.LockBits to obtain the bitmap data that you can then manipulate directly, rather than via SetPixel. (How to use LockBits)
I like the WPF option already presented, but here it is using LockBits and Bitmap:
// get the raw image data
int width, height;
int[] data = GetData(out width, out height);
// create a bitmap and manipulate it
Bitmap bmp = new Bitmap(width,height, PixelFormat.Format32bppArgb);
BitmapData bits = bmp.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, bmp.PixelFormat);
unsafe
{
for (int y = 0; y < height; y++)
{
int* row = (int*)((byte*)bits.Scan0 + (y * bits.Stride));
for (int x = 0; x < width; x++)
{
row[x] = data[y * width + x];
}
}
}
bmp.UnlockBits(bits);
With (as test data):
public static int[] GetData(out int width, out int height)
{
// diagonal gradient over a rectangle
width = 127;
height = 128;
int[] data = new int[width * height];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int val = x + y;
data[y * width + x] = 0xFF << 24 | (val << 16) | (val << 8) | val;
}
}
return data;
}
Well, I'm assuming each int is the composite ARGB value? If there isn't an easy option, then LockBits might be worth looking at - it'll be a lot quicker than SetPixel, but is more complex. You'll also have to make sure you know how the int is composed (ARGB? RGBA?). I'll try to see if there is a more obvious option...
MemoryImageSource's constructor's 3rd argument is an array of ints composed of argb values in that order
The example in that page creates such an array by;
pix[index++] = (255 << 24) | (red << 16) | blue;
You need to decompose that integer array to a byte array (shift operator would be useful), but it should be in bgr order, for LockBits method to work.
I would recommend using LockBits but a slower SetPixel based algorithm might look something like
// width - how many int's per row
// array - array of integers
Bitmap createImage(int width, int[] array)
{
int height = array.Length / width;
Bitmap bmp = new Bitmap(width, height);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < array.Length; x += width)
{
bmp.SetPixel(x, y, Color.FromArgb(array[i]));
}
}
return bmp;
}

Categories