|
All good suggestion. Thank you guys!
I was hoping to avoid LockBits, since this technique presupposes that the developer understands the in-memory representation of each PixelFormat. I didn't have that knowledge, and didn't want to learn it unless absolutely necessary. But it turns out that Bitmap.SetPixel() performs a lock and unlock every time a bit is set, which is hugely inefficient. So it appeared I had no choice...
So I bit the bullet, hopped on Google and found everything I needed to know at Bob Powell's site: http://www.bobpowell.net/lockingbits.htm[^]. Here is the resulting code:
public static void FileToImage(string path, int imageHeight, int imageWidth)
{
byte[] data;
using (FileStream fs = File.OpenRead(path))
{
data = new byte[fs.Length];
ReadWholeArray(fs, data);
}
Bitmap bmp = new Bitmap(imageWidth, imageHeight, PixelFormat.Format1bppIndexed);
Rectangle bounds = new Rectangle(Point.Empty, bmp.Size);
BitmapData bmpData = bmp.LockBits(bounds, ImageLockMode.WriteOnly, bmp.PixelFormat);
int iBitList = 0;
unsafe
{
Byte* bmpDataPointer = (Byte*)bmpData.Scan0.ToPointer();
for (int y = 0; y < imageHeight; y++)
{
for (int x = 0; x < imageWidth; x++)
{
int iBitmap = y * bmpData.Stride + (x >> 3);
byte mask = (byte)(0x80 >> (x & 0x7));
if (0x0 == data[iBitList])
{
}
else
{
bmpDataPointer[iBitmap] |= mask;
}
iBitList++;
}
}
}
bmp.UnlockBits(bmpData);
bmp.Save(path + ".bmp");
}
When the BitmapData object is constructed, it automatically sets all pixels to 0 (black), so setting just the white pixels is perfectly valid.
That being said, this technique is so fast that it actually make no difference at all. Processing three 1025x1025 pixel images took 93 ms either way. Incidentally, this is over 400 times faster than Bitmap.SetPixel(). Wow!
Just remember - this uses pointers and unsafe code. Select 'Allow unsafe code' in the project properties (Build tab).
|
|
|
|
|
Glad you got it working.
However, as I said earlier, I think most of your code is unnecessary as there is at least one Bitmap constructor that takes raw data as is, provided it conforms to one of the supported pixel formats; chances are good it does.
|
|
|
|
|
I knew there was something I forgot to mention. Thanks for the reminder Luc.
I assumed that the data format does not conform to any bitmap standards for two reasons:
1) I made up the format of the raw data, and it's just a string of bits. No encoding or anything.
2) I tried using the standard Bitmap constructors, and they garbled the data pretty badly.
|
|
|
|
|
for 1-bit-per-pixel data, there is only so much you can choose. IMO chances are great your intuitive choices are what PixelFormat.Format1bppIndexed also does. The biggest uncertainty would be the ordering of the 8 pixels that constitute a byte. there is 50% chance there.
|
|
|
|
|
what the meaning of this code
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace DESERT_Server_v2
{
class Win32Stuff
{
#region Class Variables
public const int SM_CXSCREEN = 0;
public const int SM_CYSCREEN = 1;
public const Int32 CURSOR_SHOWING = 0x00000001;
[StructLayout(LayoutKind.Sequential)]
public struct ICONINFO
{
public bool fIcon;
public Int32 xHotspot;
public Int32 yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public Int32 x;
public Int32 y;
}
[StructLayout(LayoutKind.Sequential)]
public struct CURSORINFO
{
public Int32 cbSize;
public Int32 flags;
public IntPtr hCursor;
public POINT ptScreenPos; }
#endregion
#region Class Functions
[DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", EntryPoint = "GetDC")]
public static extern IntPtr GetDC(IntPtr ptr);
[DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
public static extern int GetSystemMetrics(int abc);
[DllImport("user32.dll", EntryPoint = "GetWindowDC")]
public static extern IntPtr GetWindowDC(Int32 ptr);
[DllImport("user32.dll", EntryPoint = "ReleaseDC")]
public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
[DllImport("user32.dll", EntryPoint = "GetCursorInfo")]
public static extern bool GetCursorInfo(out CURSORINFO pci);
[DllImport("user32.dll", EntryPoint = "CopyIcon")]
public static extern IntPtr CopyIcon(IntPtr hIcon);
[DllImport("user32.dll", EntryPoint = "GetIconInfo")]
public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);
#endregion
}
}
|
|
|
|
|
It's a wrapper class that links to API calls.
"WPF has many lovers. It's a veritable porn star!" - Josh Smith As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.
My blog | My articles | MoXAML PowerToys | Onyx
|
|
|
|
|
Hello everyone,
I encountered the following problem :
I want to make a C like interpreter and I've found some good materials but only in C. So I have a (modest but) functional interpreter written in C and I would like to improve it in C#.
I don't know how to make a .dll from that C code and if I could maybe I could invoke it from C#, or I could rewrite the whole program in C# but in .NET I don't have
<#include setjmp.h> which is used in the C interpreter.
So if anyone knows how to make a .dll or something I could invoke from C# or if it is any alternative to
#include <setjmp.h> in .NET please let me know!
Thanks in advance,
Tamash
|
|
|
|
|
You can make a dll in C# by making a Class Library project.
To call the C code from C#, you will need to research P/Invoke. You will need to replicate all the function signatures, structures and constants in the C header file in C#
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier.
Please take your VB.NET out of our nice case sensitive forum.(Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Hi,
if you really want to go the trouble, study P/Invoke. I have a little article[^] that might help.
However, I wouldn't do such things in C nowadays, C# is much easier. You do not really need setjmp, there are several ways to avoid it, e.g. restructuring your set of methods; what you also could do is use a specialized exception. Partial example:
try {
} catch(SetjmpLikeException exc) {
} catch(Exception exc) {
}
...
throw new SetjmpLikeException();
...
public class SetjmpLikeException : Exception {
}
|
|
|
|
|
I wrote a program for Windows XP that does not function in Windows 7. Is there a way I can build the program in Visual Studio so that it will require Windows XP to install?
|
|
|
|
|
The first thing to do would be understand why it doesn't work on Windows 7, you shouldn't be creating an app that is dependent on an older OS.
You can check for the OS version at startup but the logical thing would to would be prevent it from installing in the first place via the setup.
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
Mark Nischalke wrote: the logical thing would to would be prevent it from installing in the first place via the setup.
I agree. This is what my question pertains to.
|
|
|
|
|
Then it depends on what tool you are using to create the installation package. You can create a custom action to validate the OS level.
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
It is a Visual Studio project, and so far I have been using Video Studio to create the installers. Is this possible to do with Visual Studio?
|
|
|
|
|
Yes. There are plenty of examples for creating custom actions with Visual Studio
I know the language. I've read a book. - _Madmatt
|
|
|
|
|
Fix the program; what problem does it have?
|
|
|
|
|
Come on, when a program depends on some third party components, that's pretty normal. And nothing you can change!
|
|
|
|
|
Then make a note in the documentation to that effect and let the buyer beware.
|
|
|
|
|
please,
what is the equivalent of FileSystem.GetFIleinfo() in C#
thanks
|
|
|
|
|
Take a look here[^] and you will see how MSDN shows the differences between the various .NET languages.
It's time for a new signature.
|
|
|
|
|
Um. Difficult...
FileInfo fi = new FileInfo(@"C:\myFileName");
Real men don't use instructions. They are only the manufacturers opinion on how to put the thing together.
|
|
|
|
|
Good morning.
I have created an Excel add-in to display a Import tab with several buttons designed to run VBA macros.
I only want this tab to display on the one workbook and not every instance of Excel. I am trying to test for the specific spreadsheet name, but the If statement keeps defaulting to the else condition. I have the following:
public RibbonCustom()
{
InitializeComponent();
this.tabImport.Visible = true;
if (Globals.ThisAddIn.Application.ThisWorkbook.FullName.ToString() == "ImportFile.xlsm") { this.tabImport.Visible = true; }
else { this.tabImport.Visible = false; }
}
The MessageBox.Show doesn't work.
Any suggestions? WHEELS
|
|
|
|
|
string theName = Globals.ThisAddIn.Application.ThisWorkbook.FullName.ToString();
if (theName == "ImportFile.xlsm")
{
this.tabImport.Visible = true;
}
else
{
this.tabImport.Visible = false;
}
Put a breakpoint on the declaration of theName , and run the code. Somehow, those two strings aren't the same.
I are Troll
|
|
|
|
|
Hi Eddy. I found one issue. I was using >FullName instead of .Name, but unfortunately it didn't fix the issue. Trying to figure out a way that I can see the contents of the code (variable).
|
|
|
|
|
Wheels012 wrote: Trying to figure out a way that I can see the contents of the code (variable).
That would be debugging[^]?
I are Troll
|
|
|
|