Capture screen to JPG

T

Tomer

Hi,
I've written an application that capture's the screen (alex feinman code) and creates a jpg file (using ARM_WriteRGBBytesIntoJpegFile function)

The result jpg looks OK except that it is 180 degrees turned+horizontally mirrored.
The question is why, and how can it be fixed.

Here's the code:

[DllImport("ARM_JpegLibThunk.dll", EntryPoint="WriteRGBBytesIntoJpegFile")]
private extern static bool ARM_WriteRGBBytesIntoJpegFile(string outFile, int width, int height, int quality, byte [] array);

public static bool Snapshot2(Control ctl, string FileName, bool overwrite)
{
IntPtr hDC;
if ( ctl != null )
{
ctl.Focus();
IntPtr hReal = GetFocus();
hDC = GetDC(hReal);
}
else
{
hDC = GetDC(IntPtr.Zero); //Full screen
}
IntPtr hMemDC = CreateCompatibleDC(hDC);
BITMAPINFOHEADER bi = new BITMAPINFOHEADER();
bi.biSize = (uint)Marshal.SizeOf(bi);
bi.biBitCount = 24; // Creating RGB bitmap. The following three members don't matter
//bi.biBitCount = 4; // for lower quality
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bi.biCompression = 0;
bi.biHeight = ctl != null? ctl.Height: Screen.PrimaryScreen.Bounds.Height;
bi.biWidth = ctl != null? ctl.Width: Screen.PrimaryScreen.Bounds.Width;
bi.biPlanes = 1;
int cb = (bi.biHeight * bi.biWidth * bi.biBitCount / 8); //8 is bits per byte
bi.biSizeImage = (uint)cb;
bi.biXPelsPerMeter = XPelsPerMeter;
bi.biYPelsPerMeter = YPelsPerMeter;
IntPtr pBits = IntPtr.Zero;
//Allocate memory for bitmap bits
IntPtr pBI = LocalAlloc(GPTR, bi.biSize);
// Not sure if this needed - simply trying to keep marshaller happy
Marshal.StructureToPtr(bi, pBI, false);
//This will return IntPtr to actual DIB bits in pBits
IntPtr hBmp = CreateDIBSection(hDC, pBI, 0, ref pBits, IntPtr.Zero, 0);
//Marshall back - now we have BITMAPINFOHEADER correctly filled in
// BITMAPINFOHEADER biNew = (BITMAPINFOHEADER)Marshal.PtrToStructure(pBI, typeof( BITMAPINFOHEADER ));
//Usual stuff
IntPtr hOldBitmap = SelectObject(hMemDC, hBmp);
//Grab bitmap
BitBlt(hMemDC, 0, 0, bi.biWidth, bi.biHeight, hDC, 0, 0, SRCCOPY);
// Allocate memory for a copy of bitmap bits
byte[] RealBits = new byte[cb];
// And grab bits from DIBSestion data
Marshal.Copy(pBits, RealBits, 0, cb);
bool res = ARM_WriteRGBBytesIntoJpegFile(FileName, bi.biWidth, bi.biHeight, 90, RealBits);
DeleteObject(SelectObject(hMemDC, hOldBitmap));
DeleteDC(hMemDC);
ReleaseDC(hDC);
return res;
}

Thanks, Tomer.
 
S

Sergey Bogdanov

The pixel data can be stored in reverse or forward order. Uncomment the
line which retrieves BITMAPINFOHEADER biNew. If biNew.biHeight is
negative then the data is stored in forward order; otherwise in reverse.

In your case the height value is positive thus just reverse pixels from
RealBits and pass into ARM_WriteRGBBytesIntoJpegFile.

HTH

--
Sergey Bogdanov [.NET CF MVP, MCSD]
http://www.sergeybogdanov.com

Hi,
I've written an application that capture's the screen (alex feinman
code) and creates a jpg file (using ARM_WriteRGBBytesIntoJpegFile function)

The result jpg looks OK except that it is 180 degrees
turned+horizontally mirrored.
The question is why, and how can it be fixed.

Here's the code:

[DllImport("ARM_JpegLibThunk.dll", EntryPoint="WriteRGBBytesIntoJpegFile")]
private extern static bool ARM_WriteRGBBytesIntoJpegFile(string outFile,
int width, int height, int quality, byte [] array);

public static bool Snapshot2(Control ctl, string FileName, bool overwrite)
{
IntPtr hDC;
if ( ctl != null )
{
ctl.Focus();
IntPtr hReal = GetFocus();
hDC = GetDC(hReal);
}
else
{
hDC = GetDC(IntPtr.Zero); //Full screen
}
IntPtr hMemDC = CreateCompatibleDC(hDC);
BITMAPINFOHEADER bi = new BITMAPINFOHEADER();
bi.biSize = (uint)Marshal.SizeOf(bi);
bi.biBitCount = 24; // Creating RGB bitmap. The following three members
don't matter
//bi.biBitCount = 4; // for lower quality
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bi.biCompression = 0;
bi.biHeight = ctl != null? ctl.Height: Screen.PrimaryScreen.Bounds.Height;
bi.biWidth = ctl != null? ctl.Width: Screen.PrimaryScreen.Bounds.Width;
bi.biPlanes = 1;
int cb = (bi.biHeight * bi.biWidth * bi.biBitCount / 8); //8 is bits per
byte
bi.biSizeImage = (uint)cb;
bi.biXPelsPerMeter = XPelsPerMeter;
bi.biYPelsPerMeter = YPelsPerMeter;
IntPtr pBits = IntPtr.Zero;
//Allocate memory for bitmap bits
IntPtr pBI = LocalAlloc(GPTR, bi.biSize);
// Not sure if this needed - simply trying to keep marshaller happy
Marshal.StructureToPtr(bi, pBI, false);
//This will return IntPtr to actual DIB bits in pBits
IntPtr hBmp = CreateDIBSection(hDC, pBI, 0, ref pBits, IntPtr.Zero, 0);
//Marshall back - now we have BITMAPINFOHEADER correctly filled in
// BITMAPINFOHEADER biNew =
(BITMAPINFOHEADER)Marshal.PtrToStructure(pBI, typeof( BITMAPINFOHEADER ));
//Usual stuff
IntPtr hOldBitmap = SelectObject(hMemDC, hBmp);
//Grab bitmap
BitBlt(hMemDC, 0, 0, bi.biWidth, bi.biHeight, hDC, 0, 0, SRCCOPY);
// Allocate memory for a copy of bitmap bits
byte[] RealBits = new byte[cb];
// And grab bits from DIBSestion data
Marshal.Copy(pBits, RealBits, 0, cb);
_*bool*__* res = ARM_WriteRGBBytesIntoJpegFile(FileName, bi.biWidth,
bi.biHeight, 90, RealBits);*_
DeleteObject(SelectObject(hMemDC, hOldBitmap));
DeleteDC(hMemDC);
ReleaseDC(hDC);
return res;
}

Thanks, Tomer.
 
G

Guest

Tomer said:
Hi,
I've written an application that capture's the screen (alex feinman code) and creates a jpg file (using ARM_WriteRGBBytesIntoJpegFile function)

The result jpg looks OK except that it is 180 degrees turned+horizontally mirrored.
The question is why, and how can it be fixed.

To capture your screen easily I found free software that does the job.
Description found on the website
(http://www.nakka.com/soft/ptools/index_eng.html):
rCE ver 0.0.6 (2001/11/27)

Remote operation of the WindowsCE connected by ActiveSync is carried out. The > keyboard and the mouse can operate it.

With a simple ALT + Print Screen you have your jpg on the clipboard.
 
E

Earl

There are tons of Alt+PrtScn programs out there, but that's a different
animal than having your code programatically capture the screen during
operation.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top