Home » Community » Forums » » Designing a Screen Shot System
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic

Page:   1 2 »»

 Last Thread Next Thread 
 Designing a Screen Shot System
Post Reply 
Damn good article, kudos for having the brainwave to write about something unusual and practical :D

 User Rating: 1027   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Wow, one of my favorite articles yet. I never thought of taking nine screenprints, shifting the perspective view around, and stiching them together to make a higher resolution image. That's quite clever!

The code makes perfect sense, but if I'm not mistaken, it looks like there isn't a demo included in the source to actually take these screenshots? I looked in the source for keys to press, but all I see are function calls to use. Excellent code btw!

I haven't tested it yet, but the update movie function has a note that says you need to figure out what it is crashing. Is this still the case? Or have you fixed that and forgot to remove the comment?

Excellent work!

~Graham

----
while (your_engine >= my_engine)
my_engine++;

 User Rating: 1328   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

hi nice article!

It would be nice to see some screens though, see your stuff "in action"

 User Rating: 1352   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Ah, found one part where you bound the functions to a key. Works quite nicely!

~Graham

----
while (your_engine >= my_engine)
my_engine++;

 User Rating: 1328   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Thanks everyone, glad you liked it.

gwihlidal:
On my system for some reason the video mode crashes after a little while. I have been to busy to look into it, but I will ASAP (Tonight) and try to get this fixed. If anyone else has this problem let me know. I just got off of work early so I'll have some time to work on this.

Agian, thanks and glad you liked it!

-UltimaX-
Ariel Productions

"You wished for a white christmas... Now go shovel your wishes!"

 User Rating: 1183   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hmm yes, I notice that the movie mode does indeed crash. It seems like a buffer overflow or something similar. It runs for about 10 seconds or so and crashes as it's running. If you close the window before it crashes, the avi is viewable and seemed to work ok.

EDIT: One possible improvement imo would be to render the hi res projections in an offscreen render buffer, so that the screen does not jitter when you take a screenshot. It works fine, and the hi res output is excellent, that's just one little thing if you want me to be picky

~Graham

----
while (your_engine >= my_engine)
my_engine++;

[edited by - gwihlidal on March 12, 2004 4:31:37 PM]

 User Rating: 1328   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Very nice article.

Cant add more than that really. Well written.

 User Rating: 1035   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Good news, I found the bug.
In the CaptureScreen(*) function add this and the video mode will work fine:
DeleteObject(BitmapHandle);

The last 4 lines should look like this:
//--Clear the handle to the device context

DeleteDC(CompatibleHDC);
//

DeleteObject(BitmapHandle);
//

//--Unlock the memory handle

GlobalUnlock(MemoryHandle);
//

//--Return the memory handle

return MemoryHandle;


If I find out how to update the source I will. (Does anyone know how?)

-UltimaX-
Ariel Productions
|Designing A Screen Shot System|

"You wished for a white christmas... Now go shovel your wishes!"

[edited by - UltimaX on March 12, 2004 12:17:28 AM]

 User Rating: 1183   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

By the way just FYI:
I was doing extensive error testing for the system and found it was failing on this line:
//--The BitmapHandle was failing

if(BitmapHandle == 0 || !SelectObject(CompatibleHDC, BitmapHandle))
{
	return NULL;
}


The BitmapHandle is created by this line:
HBITMAP BitmapHandle = CreateCompatibleBitmap(SourceHDC, GENGINE.GetWindowWidth(), GENGINE.GetWindowHeight());


So I went to MSDN to see why this could be failing after a certain amount of time. Reading MSDN it said this:
quote:

When you no longer need the bitmap, call the DeleteObject function to delete it.

Windows 95/98/Me: The created bitmap cannot exceed 16MB in size.



I have WindowsXP so I don't know if this would cause it or not, but I still needed to delete the object to free the resources. I found out that I wasn't releasing it though so deleting the handle did the trick.

I just wanted to explain what happend in case anyone ever has this problem.

-UltimaX-
Ariel Productions
|Designing A Screen Shot System|

"You wished for a white christmas... Now go shovel your wishes!"

 User Rating: 1183   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by UltimaX
If I find out how to update the source I will. (Does anyone know how?)
Normally, you'd just email me, but I've already updated it.



 User Rating: 2088   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

quote:
Original post by Myopic Rhino
quote:
Original post by UltimaX
If I find out how to update the source I will. (Does anyone know how?)
Normally, you'd just email me, but I've already updated it.




Cool, thanks a lot Myopic Rhino!

-UltimaX-
Ariel Productions
|Designing A Screen Shot System|

"You wished for a white christmas... Now go shovel your wishes!"

 User Rating: 1183   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

This is really cool, I have to re-implementthe screenshot functions in my engine and this is what I will be looking at. Thanks!

 User Rating: 871   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Good read, nice work

 User Rating: 1049   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hey, this is great. I've never seen the high resolution method described before. It really is something often overlooked! And I've been wondering how to go about the video saving, and your article covered that as well. Awesome!

Also, if you tend to copy around your screenshots a lot or move them to seperate directories, it is still possible to overwrite them, which is why in my screenshot system I put in the date instead of misc incrementing numbers.

Like this
year, month, day, hour, min, second, so it sorts it in the directory correctly as well.
screen_yyyymmdd_hrmn_sc

so today, right now would be
screen_20040313_0611_37

Anyway, that's just something I found to be very very useful in numbering screenshots. And you do not even have to check if the screenshot exists already or not, unless you take screenshots very fast (you could also add miliseconds if you needed)...It's also useful if you take screenshots of various versions of the program, so in the future you can see the date and time the screenshot was taking without relying on the 'Date Modified' data.

Great article, UltimaX!!! I'm glad someone wrote about something so simple, yet so useful!

- Aeroum

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

aftermath, Taharez:
Thanks, I'm glad you liked the article

quote:
Original post by Aeroum
Hey, this is great. I've never seen the high resolution method described before. It really is something often overlooked! And I've been wondering how to go about the video saving, and your article covered that as well. Awesome!

Also, if you tend to copy around your screenshots a lot or move them to seperate directories, it is still possible to overwrite them, which is why in my screenshot system I put in the date instead of misc incrementing numbers.

Like this
year, month, day, hour, min, second, so it sorts it in the directory correctly as well.
screen_yyyymmdd_hrmn_sc

so today, right now would be
screen_20040313_0611_37

Anyway, that's just something I found to be very very useful in numbering screenshots. And you do not even have to check if the screenshot exists already or not, unless you take screenshots very fast (you could also add miliseconds if you needed)...It's also useful if you take screenshots of various versions of the program, so in the future you can see the date and time the screenshot was taking without relying on the 'Date Modified' data.

Great article, UltimaX!!! I'm glad someone wrote about something so simple, yet so useful!

- Aeroum


That's a real good idea, I might update the file manager in the next update. I have never had a screen shot be overwritten yet and the manager should be able to find out which one was moved.

For instance, if you have _001, _002, and _003 and you move _002 it will know and create a new one with _002.
Also, I'm glad you liked the article and found it useful, thanks.

-UltimaX-
Ariel Productions
|Designing A Screen Shot System|

"You wished for a white christmas... Now go shovel your wishes!"

 User Rating: 1183   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Oh yeah, I looked at the code and I see the file manager determines if a file exist and increments if the name is taken. But let me give you an example...

Before I would keep my debug and my release versions in seperate directories, and as I was testing I took screen shots with both. Then I wanted to put screenshots from both into the same directory, with Windows explorer, and there were like 60 files with the same name. So all I could do to keep them both in the same directory would be to first manually rename each one, 1 by 1.

You could use a batch file renamer, but putting a timestamp on the filename itself worked a lot better. With date/time on each file name, I can move screenshots from multiple directories into other directories and they all fall smoothly into place, sorted by filename and therefore by date/time.

This probably will never come up, but if it does, putting date/time could be helpful, especially if there are 100s of screens.

It's a great article and I'm not suggesting that anything be changed. Just something anyone may want to keep in mind.

- Aeroum

 User Rating: 1015   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Aeroum
Oh yeah, I looked at the code and I see the file manager determines if a file exist and increments if the name is taken. But let me give you an example...

Before I would keep my debug and my release versions in seperate directories, and as I was testing I took screen shots with both. Then I wanted to put screenshots from both into the same directory, with Windows explorer, and there were like 60 files with the same name. So all I could do to keep them both in the same directory would be to first manually rename each one, 1 by 1.

You could use a batch file renamer, but putting a timestamp on the filename itself worked a lot better. With date/time on each file name, I can move screenshots from multiple directories into other directories and they all fall smoothly into place, sorted by filename and therefore by date/time.

This probably will never come up, but if it does, putting date/time could be helpful, especially if there are 100s of screens.

It's a great article and I'm not suggesting that anything be changed. Just something anyone may want to keep in mind.

- Aeroum


Yeah that is a good example. I'll add the time stamp to it after the index.
_000_HHMMSS.ext

That should do the trick. Thanks for the suggestion.

-UltimaX-
Ariel Productions
|Designing A Screen Shot System|

"You wished for a white christmas... Now go shovel your wishes!"

 User Rating: 1183   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

The new method is finished. I'll email Myopic Rhino the new updated source and ask him to update the zip.

-UltimaX-
Ariel Productions
|Designing A Screen Shot System|

"You wished for a white christmas... Now go shovel your wishes!"

 User Rating: 1183   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

That was a great article, that system sure beats my current method of hitting print screen

 User Rating: 992   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by SarsDP
That was a great article, that system sure beats my current method of hitting print screen




-UltimaX-
Ariel Productions
|Designing A Screen Shot System|

"You wished for a white christmas... Now go shovel your wishes!"

 User Rating: 1183   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Nice job!

Some constructive criticism:
- When the demo is executed in a folder that doesn't contain the watermark image, it pops an error message saying that, and then crashes. It should fail and quit.

- Debug build crashes complaining about an invalid heap pointer. This is the code that's causing the problem:
//--Validate the memory data

        if(MemoryData)
        {
                //--Free the memory data

                free(MemoryData);
                MemoryData = NULL;
        }

        //--Free the Watermark handle

        GlobalFreePtr(MemoryData);

The complaint (assertion failure) is fired from inside free. Basically, it says that the pointer supplied (MemoryData) doesn't belong to this heap. MemoryData should be freed by GlobalFreePtr, obviously. What the code does is free() MemoryData (which is causing the error), and then it always passes a NULL pointer to GlobalFreePtr.

- Using the GDI is most probably the source of the huge slow-downs. Try locking the back-buffer and mem-copying it instead, every frame. In one of my previous demos (light-scattered sky+terrain), locking the whole back-buffer reduced the frame rate from ~330 to ~150, which isn't that bad.(frame-time changed from ~0.00303 to ~0.00667).

- Supporting D3D and GL using 2 code-paths with if-else blocks is very tedious. You'd better create an "abstract" renderer (an interface) and then implement it with D3D and GL concrete classes. Or better, drop support for one of them (It consumes loads of time, and if you don't have a very good reason to justify it, just drop one of them).

- I think it'd be better to rename source-code zip packages included with articles to something more reasonable. I mean, "source.zip" causes a lot of ambiguity, unless I explicitly rename it when saving it (something I never ever did).
Making it "screenshot-system-source.zip" would be much better.

Muhammad Haggag
Bitwise account: MHaggag -

 User Rating: 1823   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

quote:
Original post by Coder
Nice job!

Some constructive criticism:
- When the demo is executed in a folder that doesn't contain the watermark image, it pops an error message saying that, and then crashes. It should fail and quit.

- Debug build crashes complaining about an invalid heap pointer. This is the code that's causing the problem:
//--Validate the memory data

        if(MemoryData)
        {
                //--Free the memory data

                free(MemoryData);
                MemoryData = NULL;
        }

        //--Free the Watermark handle

        GlobalFreePtr(MemoryData);

The complaint (assertion failure) is fired from inside free. Basically, it says that the pointer supplied (MemoryData) doesn't belong to this heap. MemoryData should be freed by GlobalFreePtr, obviously. What the code does is free() MemoryData (which is causing the error), and then it always passes a NULL pointer to GlobalFreePtr.

- Using the GDI is most probably the source of the huge slow-downs. Try locking the back-buffer and mem-copying it instead, every frame. In one of my previous demos (light-scattered sky+terrain), locking the whole back-buffer reduced the frame rate from ~330 to ~150, which isn't that bad.(frame-time changed from ~0.00303 to ~0.00667).

- Supporting D3D and GL using 2 code-paths with if-else blocks is very tedious. You'd better create an "abstract" renderer (an interface) and then implement it with D3D and GL concrete classes. Or better, drop support for one of them (It consumes loads of time, and if you don't have a very good reason to justify it, just drop one of them).

- I think it'd be better to rename source-code zip packages included with articles to something more reasonable. I mean, "source.zip" causes a lot of ambiguity, unless I explicitly rename it when saving it (something I never ever did).
Making it "screenshot-system-source.zip" would be much better.

Muhammad Haggag
Bitwise account: MHaggag -


Wow, thanks Coder.
I'll work on the watermark and heap pointer problems ASAP.

I was thinking about using some kind of back buffer (GDI, OpenGL, DirectX, ...) to help for speed and to avoid the flickering and the high resolution projection view switching. I should work on this since I have to optimize the code, cleanup, etc. anyway.

The reason I have Direct3D and OpenGL in there is to show that just about any API can be used easily. Also, if someone decides to use this system they can drop whatever API they're not using. This would save them time setting it up.

About the zip... When I uploaded the zip file to GameDev it was named "ScreenShotSystem.zip" which means GameDev renamed it. I have no clue why, but there had to some kind of reason?

Agian, thank you so much for the valuable input.

-UltimaX-
Ariel Productions
|Designing A Screen Shot System|

"You wished for a white christmas... Now go shovel your wishes!"

 User Rating: 1183   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Hi!

Nice article. I thought about the high res screenshot system with the 9 sub images and I don't want to belive that's the only way it works! I am not a total crack regarding rendering context/device context but I guess a solution would be to create an new device context 3 times as big as the device context of the window and connect the rendering context with that new device context. Now you render the scene again and save this device context in a bmp as done with the low res screenshot.

I searched the device context definition for something like size etc. but found nothing. perhaps I am wrong and it has nothing to do with the DC but somewhere OpenGL for example must get the dimensions.

Hope someone knows more and has some ideas!
-Constantin

 User Rating: 1054   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Well, I read only the introduction right now and I have a notice to the video recording: I think that very effective solution would be to record not the video itself, but the gameplay as some kind of demo or record (you know - not the picture data themselves, but the movement info of objects and so). And then, after the game is recorded at full FPS, run special rendering pass, which would render that demo frame-by-frame using various codecs and stuff, no matter how long it would last.
I'm aware of the fact that this would require the demo recording support, but when you are writting some kind of 3D FPS, demo recording is a good feature to have and demo rendering is just a matter of few changes.
I hope I'm the first to notice this; I only read the previous discussion very briefly (you know - not enough time).

 User Rating: 1022   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link
Page:   1 2 »»
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: