Capture screen to JPG

  • Thread starter Thread starter Tomer
  • Start date Start date
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.
 
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.
 
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.
 
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.
 
Back
Top