I want to Send Arabic text as Bitmap to a POS printer since I could not print Arabic words directly to the printer. I used below code to convert a text to Bitmap :
Convert_ValueToImage("كيكه", "Simplified Arabic Fixed", 12)
public static Bitmap Convert_ValueToImage(string ValueText, string Fontname, int Fontsize)
{
//creating bitmap image
Bitmap ValueBitmap = new Bitmap(1, 1);
//FromImage method creates a new Graphics from the specified Image.
Graphics Graphics = Graphics.FromImage(ValueBitmap);
// Create the Font object for the image text drawing.
Font Font = new Font(Fontname, Fontsize);
// Instantiating object of Bitmap image again with the correct size for the text and font.
SizeF stringSize = Graphics.MeasureString(ValueText, Font);
ValueBitmap = new Bitmap(ValueBitmap, (int)stringSize.Width, (int)stringSize.Height);
Graphics = Graphics.FromImage(ValueBitmap);
//Draw Specified text with specified format
Graphics.DrawString(ValueText, Font, Brushes.Black, 0, 0);
Font.Dispose();
Graphics.Flush();
Graphics.Dispose();
return ValueBitmap; //return Bitmap Image
}
and when I assign it to pictureBox it works.
Now I want to send it to the printer. I used below method to convert the bitmap image to string with adding the image mode to the string:
public string GetArabic(Bitmap ArabicText)
{
string logo = "";
BitmapData data = GetArabicBitmapData(ArabicText);
BitArray dots = data.Dots;
byte[] width = BitConverter.GetBytes(data.Width);
int offset = 0;
MemoryStream stream = new MemoryStream();
BinaryWriter bw = new BinaryWriter(stream);
bw.Write((char)0x1B);
bw.Write('#');
bw.Write((char)0x1B);
bw.Write('3');
bw.Write((byte)24);
while (offset < data.Height)
{
bw.Write((char)0x1B);
bw.Write('*'); // bit-image mode
bw.Write((byte)33); // 24-dot double-density
bw.Write(width[0]); // width low byte
bw.Write(width[1]); // width high byte
for (int x = 0; x < data.Width; ++x)
{
for (int k = 0; k < 3; ++k)
{
byte slice = 0;
for (int b = 0; b < 8; ++b)
{
int y = (((offset / 8) + k) * 8) + b;
// Calculate the location of the pixel we want in the bit array.
// It'll be at (y * width) + x.
int i = (y * data.Width) + x;
// If the image is shorter than 24 dots, pad with zero.
bool v = false;
if (i < dots.Length)
{
v = dots[i];
}
slice |= (byte)((v ? 1 : 0) << (7 - b));
}
bw.Write(slice);
}
}
offset += 24;
bw.Write((char)0x0A);
}
// Restore the line spacing to the default of 30 dots.
bw.Write((char)0x1B);
bw.Write('3');
bw.Write((byte)30);
bw.Flush();
byte[] bytes = stream.ToArray();
return logo + Encoding.Default.GetString(bytes);
}
public BitmapData GetArabicBitmapData(Bitmap bmpFileName)
{
using (var bitmap = bmpFileName )
{
var threshold = 127;
var index = 0;
double multiplier = 570; // this depends on your printer model. for Beiyang you should use 1000
double scale = (double)(multiplier / (double)bitmap.Width);
int xheight = (int)(bitmap.Height * scale);
int xwidth = (int)(bitmap.Width * scale);
var dimensions = xwidth * xheight;
var dots = new BitArray(dimensions);
for (var y = 0; y < xheight; y++)
{
for (var x = 0; x < xwidth; x++)
{
var _x = (int)(x / scale);
var _y = (int)(y / scale);
var color = bitmap.GetPixel(_x, _y);
var luminance = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
dots[index] = (luminance < threshold);
index++;
}
}
return new BitmapData()
{
Dots = dots,
Height = (int)(bitmap.Height * scale),
Width = (int)(bitmap.Width * scale)
};
}
}
this code print a black Rectangle. what would help me is if I could print the text with white background and the size is small as the text size.
Related
I have created a program to draw square grids on a selected image. It works fine for images that has small resolution, but it doesn't work properly on large images.
The all grid lines are not visible seem when the image is saved as file.
The image I am testing has resolution 3600x4320 and can be shown in the link.
How can I fix this problem?
My code:
Image drawGrid(int n, string imgPath)
{
Image img = Image.FromFile(imgPath);
Graphics grp = Graphics.FromImage(img);
grp.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
float m = img.Width * 1f / n;
for (int i = 1; i < n; i++)
{
var x = new PointF(i * m, 0);
var y = new PointF(i * m, img.Height);
grp.DrawLine(Pens.Red, x, y);
}
for (int i = 1; i <= (int)(this.Height / m); i++)
{
var x = new PointF(0, i * m);
var y = new PointF(img.Width, i * m);
grp.DrawLine(new Pen(Color.Red, 5f), x, y);
}
return img;
}
void BtnExportClick(object sender, EventArgs e)
{
if(saveFileDialog1.ShowDialog() == DialogResult.OK)
{
int n = (int)numericUpDown1.Value;
drawGrid(n, txtImagePath.Text).Save(saveFileDialog1.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
MessageBox.Show("Done");
}
}
The result image is below (resolution reduced to upload)
The grid lines not shown correctly.
The major problem is in this line:
for (int i = 1; i <= (int)(this.Height / m); i++)
▶ this.Height is clearly not what you wanted to write, let's replace it with the Image.Height
▶ grp.DrawLine(Pens.Red, x, y); and grp.DrawLine(new Pen(Color.Red, 5f), x, y); will draw lines of different size (1 and 5 pixels). In the sample code, the two methods accept Color and float arguments that define the Pen color and size.
▶ grp.SmoothingMode: we don't want any smoothing mode here, not needed to draw straight lines and it will add anti-alias which will be clearly visible, especially when saving the Image in JPEG format (it will anti-alias - sort of, it actually mangles the colors - these lines by itself).
▶ You're not disposing of any of the Graphics object you create. This is quite important with both frequent graphics operations and when working with large Bitmaps.
The Pen and Graphics objects needs to be disposed.
Since it's not exactly clear if you want to generate a grid that has the same number of lines in both dimensions - hence, a grid with Cells in which the Width is not equal to the Height, most probably - or a grid with squared Cells (this is what the sample Image seems to show, not the code), I posted two method that draw both grid types:
First method, same number of lines in both width and height:
var gridSizeX = (float)image.Width / lines;
var gridSizeY = (float)image.Height / lines;
private Image DrawGridLines(int lines, string imgPath, Color penColor, float penSize)
{
var image = Image.FromStream(new MemoryStream(File.ReadAllBytes(imgPath)), true);
using (var g = Graphics.FromImage(image)) {
g.PixelOffsetMode = PixelOffsetMode.Half;
var gridSizeX = (float)image.Width / lines;
var gridSizeY = (float)image.Height / lines;
for (int i = 1; i < lines; i++) {
var pointX1 = new PointF(0, i * gridSizeY);
var pointX2 = new PointF(image.Width, i * gridSizeY);
var pointY1 = new PointF(i * gridSizeX, 0);
var pointY2 = new PointF(i * gridSizeX, image.Height);
using (var pen = new Pen(penColor, penSize)) {
g.DrawLine(pen, pointX1, pointX2);
g.DrawLine(pen, pointY1, pointY2);
}
}
return image;
}
}
Second method, drawing a squared grid. The integer value, gridSection, is used to define a grid Cell based on the minimum dimension of the Bitmap.
This dimension is then used to determine how many lines to draw in the other dimension.
The grid size is calculated on the minimum dimension:
var gridSize = (float)Math.Min(image.Width, image.Height) / gridSection;
And the Cell are determined as a consequence:
var gridStepMin = Math.Min(image.Width, image.Height) / gridSize;
var gridStepMax = Math.Max(image.Width, image.Height) / gridSize;
private Image DrawSquaredGrid(int gridSection, string imgPath, Color penColor, float penSize)
{
var image = Image.FromStream(new MemoryStream(File.ReadAllBytes(imgPath)), true);
using (var g = Graphics.FromImage(image)) {
g.PixelOffsetMode = PixelOffsetMode.Half;
var gridSize = (float)Math.Min(image.Width, image.Height) / gridSection;
var gridStepMin = Math.Min(image.Width, image.Height) / gridSize;
var gridStepMax = Math.Max(image.Width, image.Height) / gridSize;
for (int i = 1; i < gridStepMin; i++) {
var pointY1 = new PointF(i * gridSize, 0);
var pointY2 = new PointF(i * gridSize, image.Height);
using (var pen = new Pen(penColor, penSize)) {
g.DrawLine(pen, pointY1, pointY2);
}
}
for (int i = 1; i < gridStepMax; i++) {
var pointX1 = new PointF(0, i * gridSize);
var pointX2 = new PointF(image.Width, i * gridSize);
using (var pen = new Pen(penColor, penSize)) {
g.DrawLine(pen, pointX1, pointX2);
}
}
return image;
}
}
The SaveFileDialog is refactored to allow multiple Image formats. and to call one of the drawing methods based on a selection (in the sample code, a CheckBox (chkSquared) is used select one of the Grid types).
You can add more formats, the ImageFormatFromFileName() methods selects the ImageFormat type based on the SaveFileDialog.FielName extension.
private void BtnExportClick(object sender, EventArgs e)
{
string imagePath = [Some Path];
using (var sfd = new SaveFileDialog()) {
sfd.Filter = "PNG Image (*.png)|*.png|TIFF Image (*.tif)|*.tif|JPEG Image (*.jpg)|*.jpg";
sfd.RestoreDirectory = true;
sfd.AddExtension = true;
if (sfd.ShowDialog() == DialogResult.OK) {
Image image = null;
if (chkSquared.Checked) {
image = DrawSquaredGrid((int)numericUpDown1.Value, imagePath, Color.Red, 5.0f);
}
else {
image = DrawGridLines((int)numericUpDown1.Value, imagePath, Color.Red, 5.0f);
}
image.Save(sfd.FileName, ImageFormatFromFileName(sfd.FileName));
MessageBox.Show("Done");
image.Dispose();
}
}
}
private ImageFormat ImageFormatFromFileName(string fileName)
{
string fileType = Path.GetExtension(fileName).Remove(0, 1);
if (fileType.Equals("tif")) fileType = "tiff";
if (fileType.Equals("jpg")) fileType = "jpeg";
return (ImageFormat)new ImageFormatConverter().ConvertFromString(fileType);
}
I am trying to get color from specific area in an Image.
Assume that , this is image , and I want to get color inside image.(the result should be red of the above image) This color may be different position in image. Because I don't know exact position of color where it starting, so I can't get exact result.
Until now, I cropped image giving manually position of x and y, and then cropped image and I got average color of cropped image. But I know , this is not exact color.
What I tried :
private RgbDto GetRGBvalueCroppedImage(Image croppedImage)
{
var avgRgb = new RgbDto();
var bm = new Bitmap(croppedImage);
BitmapData srcData = bm.LockBits(
new Rectangle(0, 0, bm.Width, bm.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
int stride = srcData.Stride;
IntPtr Scan0 = srcData.Scan0;
long[] totals = new long[] { 0, 0, 0 };
int width = bm.Width;
int height = bm.Height;
unsafe
{
byte* p = (byte*)(void*)Scan0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
for (int color = 0; color < 3; color++)
{
int idx = (y * stride) + x * 4 + color;
totals[color] += p[idx];
}
}
}
}
avgRgb.avgB = (int)totals[0] / (width * height);
avgRgb.avgG = (int)totals[1] / (width * height);
avgRgb.avgR = (int)totals[2] / (width * height);
return avgRgb;
}
How can I get exact position to crop? May be I can convert image to byte array, then I can find different color and take position of it and then crop. But I have no clue how do this.
You can use something this extension method to get dominant color in a region of an image in case they are not all the same
public static Color GetDominantColor(this Bitmap bitmap, int startX, int startY, int width, int height) {
var maxWidth = bitmap.Width;
var maxHeight = bitmap.Height;
//TODO: validate the region being requested
//Used for tally
int r = 0;
int g = 0;
int b = 0;
int totalPixels = 0;
for (int x = startX; x < (startX + width); x++) {
for (int y = startY; y < (startY + height); y++) {
Color c = bitmap.GetPixel(x, y);
r += Convert.ToInt32(c.R);
g += Convert.ToInt32(c.G);
b += Convert.ToInt32(c.B);
totalPixels++;
}
}
r /= totalPixels;
g /= totalPixels;
b /= totalPixels;
Color color = Color.FromArgb(255, (byte)r, (byte)g, (byte)b);
return color;
}
You can then use it like
Color pixelColor = myBitmap.GetDominantColor(xPixel, yPixel, 5, 5);
there is room for improvement, like using a Point and Size, or even a Rectangle
public static Color GetDominantColor(this Bitmap bitmap, Rectangle area) {
return bitmap.GetDominantColor(area.X, area.Y, area.Width, area.Height);
}
and following this link:
https://www.c-sharpcorner.com/UploadFile/0f68f2/color-detecting-in-an-image-in-C-Sharp/
If you want to get the image colors, you don't need to do any cropping at all. Just loop on image pixels and find the two different colors. (Assuming that you already know the image will have exactly 2 colors, as you said in comments). I've written a small function that will do that. However, I didn't test it in an IDE, so expect some small mistakes:
private static Color[] GetColors(Image image)
{
var bmp = new Bitmap(image);
var colors = new Color[2];
colors[0] = bmp.GetPixel(0, 0);
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
Color c = bmp.GetPixel(i, j);
if (c == colors[0]) continue;
colors[1] = c;
return colors;
}
}
return colors;
}
The following routine is to sharpen an 8 bit indexed grayscale only.
This code seems to have no effect on the input image. That is, what is going in, the same is coming out.
If I increase the value of strength the image seems to be getting darker, but, never filtered.
What could be possibly going wrong?
I am using the following kernel,
double[,] _numericalKernel = new double[,]
{ { -1, -1, -1, },
{ -1, 9, -1, },
{ -1, -1, -1, }, };
The following is my source code for sharpening,
public static Bitmap NonfftSharpen(Bitmap image, double[,] mask, double strength)
{
Bitmap bitmap = (Bitmap)image.Clone();
if (bitmap != null)
{
int width = bitmap.Width;
int height = bitmap.Height;
if (mask.GetLength(0) != mask.GetLength(1))
{
throw new Exception("_numericalKernel dimensions must be same");
}
// Create sharpening filter.
int filterSize = mask.GetLength(0);
double[,] filter = (double[,])mask.Clone();
int channels = sizeof(byte);
double bias = 1.0 - strength;
double factor = strength / 16.0;
int halfOfFilerSize = filterSize / 2;
byte[,] result = new byte[bitmap.Width, bitmap.Height];
// Lock image bits for read/write.
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite,
PixelFormat.Format8bppIndexed);
// Declare an array to hold the bytes of the bitmap.
int memorySize = bitmapData.Stride * height;
byte[] memory = new byte[memorySize];
// Copy the RGB values into the local array.
Marshal.Copy(bitmapData.Scan0, memory, 0, memorySize);
int rgb;
// Fill the color array with the new sharpened color values.
for (int y = halfOfFilerSize; y < height - halfOfFilerSize; y++)
{
for (int x = halfOfFilerSize; x < width - halfOfFilerSize; x++)
{
for (int filterY = 0; filterY < filterSize; filterY++)
{
double grayShade = 0.0;
for (int filterX = 0; filterX < filterSize; filterX++)
{
int imageX = (x - halfOfFilerSize + filterX + width) % width;
int imageY = (y - halfOfFilerSize + filterY + height) % height;
rgb = imageY * bitmapData.Stride + channels * imageX;
grayShade += memory[rgb + 0] * filter[filterX, filterY];
}
rgb = y * bitmapData.Stride + channels * x;
int b = Math.Min(Math.Max((int)(factor * grayShade + (bias * memory[rgb + 0])), 0), 255);
result[x, y] = (byte)b;
}
}
}
// Update the image with the sharpened pixels.
for (int x = halfOfFilerSize; x < width - halfOfFilerSize; x++)
{
for (int y = halfOfFilerSize; y < height - halfOfFilerSize; y++)
{
rgb = y * bitmapData.Stride + channels * x;
memory[rgb + 0] = result[x, y];
}
}
// Copy the RGB values back to the bitmap.
Marshal.Copy(memory, 0, bitmapData.Scan0, memorySize);
// Release image bits.
bitmap.UnlockBits(bitmapData);
return bitmap;
}
else
{
throw new Exception("input image can't be null");
}
}
I've changed your function a bit to make it work.
Take care that the strength parameter has no effect in my function. You can play with the bias and factor values to get different results in brightness and so on.
public static Bitmap NonfftSharpen(Bitmap image, double[,] mask, double strength)
{
Bitmap bitmap = (Bitmap)image.Clone();
if (bitmap != null)
{
int width = bitmap.Width;
int height = bitmap.Height;
if (mask.GetLength(0) != mask.GetLength(1))
{
throw new Exception("_numericalKernel dimensions must be same");
}
// Create sharpening filter.
int filterSize = mask.GetLength(0);
double[,] filter = (double[,])mask.Clone();
int channels = sizeof(byte);
double bias = 0.0; // 1.0 - strength;
double factor = 1.0; // strength / 16.0;
byte[,] result = new byte[bitmap.Width, bitmap.Height];
// Lock image bits for read/write.
BitmapData bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite,
System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
// Declare an array to hold the bytes of the bitmap.
int memorySize = bitmapData.Stride * height;
byte[] memory = new byte[memorySize];
// Copy the RGB values into the local array.
Marshal.Copy(bitmapData.Scan0, memory, 0, memorySize);
int pixel;
// Fill the color array with the new sharpened color values.
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
double grayShade = 0.0;
for (int filterY = 0; filterY < filterSize; filterY++)
{
for (int filterX = 0; filterX < filterSize; filterX++)
{
int imageX = (x - filterSize / 2 + filterX + width) % width;
int imageY = (y - filterSize / 2 + filterY + height) % height;
pixel = imageY * bitmapData.Stride + channels * imageX;
grayShade += memory[pixel] * filter[filterX, filterY];
}
int newPixel = Math.Min(Math.Max((int)(factor * grayShade + bias), 0), 255);
result[x, y] = (byte)newPixel;
}
}
}
// Update the image with the sharpened pixels.
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
pixel = y * bitmapData.Stride + channels * x;
memory[pixel] = result[x, y];
}
}
// Copy the values back to the bitmap.
Marshal.Copy(memory, 0, bitmapData.Scan0, memorySize);
// Release image bits.
bitmap.UnlockBits(bitmapData);
return bitmap;
}
else
{
throw new Exception("input image can't be null");
}
}
I hope this gets you going :)
Regards
I want to know the error in the following code.I want to draw the values of array that contains wave file samples.in the form i put panel and inside it picturebox.
private void button1_Click(object sender, EventArgs e)
{
string ss = "test.wav";
double[] xxwav = prepare(ss);
int xmin = 300; int ymin = 250; int xmax = 1024; int ymax = 450;
int xpmin = 0; int xpmax = xxwav.Length; int ypmin = 32767; int ypmax = -32768;
double a = (double)((xmax - xmin)) /(double) (xpmax - xpmin);
double b = (double)(xpmin - (a * xmin));
double c = (double)((ymax - ymin) /(double) (ypmax - ypmin));
double d = (double)(ypmin - (c * ymin));
double xp1,yp1,xp2,yp2;
Pen redPen = new Pen(Color.Red, 1);
Bitmap bmp = new Bitmap(40000, 500);
Graphics g = Graphics.FromImage(bmp);
PointF p1;
PointF p2;
for (int i = 1; i < xxwav.Length; i++)
{
xp1 = a * (i-1) + b;
yp1 = c * xxwav[i-1] + d;
xp2=a * i + b;
yp2=c * xxwav[i] + d;
p1 =new PointF ((float)xp1,(float)yp1);
p2 =new PointF ((float)xp2,(float)yp2);
g.DrawLine(redPen, p1, p2);
}
pictureBox1.Image = bmp;
MessageBox.Show("complete");
}
public static Double[] prepare(String wavePath)
{
Double[] data;
byte[] wave;
byte[] sR = new byte[4];
System.IO.FileStream WaveFile = System.IO.File.OpenRead(wavePath);
wave = new byte[WaveFile.Length];
data = new Double[(wave.Length - 44) / 4];//shifting the headers out of the PCM data;
WaveFile.Read(wave, 0, Convert.ToInt32(WaveFile.Length));//read the wave file into the wave variable
/***********Converting and PCM accounting***************/
for (int i = 0; i < data.Length; i++)
{
data[i] = BitConverter.ToInt16(wave, i * 2) / 32768.0;
}
//65536.0.0=2^n, n=bits per sample;
return data;
}
Your code worked for me only after I fiddled with your transformations and scaling parameters.
I have replaced your code with the scaling and transformation methods available in the System.Drawing namespace. This did gave me a view of one of my wav files. You only have to replace the private void button1_Click(object sender, EventArgs e) implementation.
var xxwav = prepare(wavFile);
// determine max and min
var max = (from v in xxwav
select v).Max();
var min = (from v in xxwav
select v).Min();
// what is our Y-axis scale
var mid = (max - min);
Pen redPen = new Pen(Color.Red, 1);
Bitmap bmp = new Bitmap(this.pictureBox1.Size.Width, this.pictureBox1.Size.Height);
Graphics g = Graphics.FromImage(bmp);
// x / y position (y-axis to the middle)
g.TranslateTransform(
0
, this.pictureBox1.Size.Height / 2);
// scaling according to picturebox size
g.ScaleTransform(
(float)this.pictureBox1.Size.Width / (float)xxwav.Length
, (float)this.pictureBox1.Size.Height / ((float)mid));
//first point
var prev = new PointF(0, (float)xxwav[0]);
// iterate over next points
for (int i = 1; i < xxwav.Length; i++)
{
var next = new PointF((float) i , (float) xxwav[i] );
g.DrawLine(redPen, prev, next);
prev = next;
}
pictureBox1.Image = bmp;
The C# software I'm involved with writing has a component that involves the reading of barcodes from scanned documents. The PDFs themselves are opened using PDFSharp.
Unfortunately we're encountering an issue with the process when it involves Flate Decoding of PDFs. Basically, all we get is a bunch of fuzz, which means there is no barcode to check and the document is not recognised.
Our code (which we shamelessly "borrowed" from another Stack Overflow case!) is as follows:
private FileInfo ExportAsPngImage(PdfDictionary image, string sourceFileName, ref int count)
{
//This code basically comes from http://forum.pdfsharp.net/viewtopic.php?f=2&t=2338#p6755
//and http://stackoverflow.com/questions/10024908/how-to-extract-flatedecoded-images-from-pdf-with-pdfsharp
string tempFile = string.Format("{0}_Image{1}.png", sourceFileName, count);
int width = image.Elements.GetInteger(PdfImage.Keys.Width);
int height = image.Elements.GetInteger(PdfImage.Keys.Height);
int bitsPerComponent = image.Elements.GetInteger(PdfImage.Keys.BitsPerComponent);
var pixelFormat = new PixelFormat();
switch (bitsPerComponent)
{
case 1:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format1bppIndexed;
break;
case 8:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed;
break;
case 24:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
break;
default:
throw new Exception("Unknown pixel format " + bitsPerComponent);
}
var fd = new FlateDecode();
byte[] decodedBytes = fd.Decode(image.Stream.Value);
byte[] resultBytes = null;
int newWidth = width;
int alignment = 4;
if (newWidth % alignment != 0)
//Image data in BMP files always starts at a DWORD boundary, in PDF it starts at a BYTE boundary.
//Most images have a width that is a multiple of 4, so there is no problem with them.
//You must copy the image data line by line and start each line at the DWORD boundary.
{
while (newWidth % alignment != 0)
{
newWidth++;
}
var copy_dword_boundary = new byte[height, newWidth];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < newWidth; x++)
{
if (x <= width && (x + (y * width) < decodedBytes.Length))
// while not at end of line, take orignal array
copy_dword_boundary[y, x] = decodedBytes[x + (y * width)];
else //fill new array with ending 0
copy_dword_boundary[y, x] = 0;
}
}
resultBytes = new byte[newWidth * height];
int counter = 0;
for (int x = 0; x < copy_dword_boundary.GetLength(0); x++)
{
for (int y = 0; y < copy_dword_boundary.GetLength(1); y++)
{ //put 2dim array back in 1dim array
resultBytes[counter] = copy_dword_boundary[x, y];
counter++;
}
}
}
else
{
resultBytes = new byte[decodedBytes.Length];
decodedBytes.CopyTo(resultBytes, 0);
}
//Create a new bitmap and shove the bytes into it
var bitmap = new Bitmap(newWidth, height, pixelFormat);
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat);
int length = (int)Math.Ceiling(width * bitsPerComponent / 8.0);
for (int i = 0; i < height; i++)
{
int offset = i * length;
int scanOffset = i * bitmapData.Stride;
Marshal.Copy(resultBytes, offset, new IntPtr(bitmapData.Scan0.ToInt32() + scanOffset), length);
}
bitmap.UnlockBits(bitmapData);
//Now save the bitmap to memory
using (var fs = new FileStream(String.Format(tempFile, count++), FileMode.Create, FileAccess.Write))
{
bitmap.Save(fs, ImageFormat.Png);
}
return new FileInfo(tempFile);
}
Unfortunately, all we get out of it is this http://i.stack.imgur.com/FwatQ.png
Any ideas on where we're going wrong, or suggestions for things we might try would be greatly appreciated.
Cheers
Thanks for the suggestions guys. One of the other developers managed to crack it - it was (as Jongware suggested) a JPEG, but it was actually zipped as well! Once unzipped it could be processed and recognised as normal.