Upscreen: A Screenshot Utility using the Min.us API
It’s been a long time since I posted something, again. Well actually I was hospitalized for 6 days, from December 18 to 24. I nearly spent Christmas the hospital. And after the hospital days, I worked on 2 projects, one is paid, and the other one is this.
The Story
Min.us is a great image hosting website. And when the time they sent me their API (I asked; their API wasn’t public yet that time) I came up with an idea, and yes basically the idea is to upload the screenshot taken in a computer to the min.us image hosting. When I finished the first (paid) project, I switched to this one. And I started with finding a way to execute code when the user pressed the PrintScreen key. I thought of using Windows Hooks but later on, I found out about RegisterHotKey and used it instead. But there’s a little problem, when I registered PrintScreen as a hotkey. Just like:
RegisterHotKey(NULL, 1, NULL, 0x2C);
The normal function of the key is disabled. This is bad, and I probably really need to use a keyboard hook instead. But no, instead I changed the hotkey and set it to Win + PrintScreen.
RegisterHotKey(NULL, 1, MOD_WIN | MOD_NOREPEAT, 0x2C);
So yes, it’s working great now. Though the PrintScreen key must be pressed first to load the image to the clipboard. So if you’re going to upload a screenshot, Press PrintScreen, then Win + PrintScreen. The good thing caused by this is, you can choose what to upload, and just place it in your clipboard. Say you need to upload an image from the internet, copy it, and then press Win + PrintScreen. Sweet.
Next, I need to get the data from the clipboard, and that was easy using GetClipboardData. Then, I need to save the bitmap file from the clipboard. I had some trouble finding a way to do this, so I used a function named CreateBMPFile and CreateBitmapInfoStruct. Success, now originally I was planning to use the BMP image and upload it right away. Then I just realized, the BMP file generated was uncompressed. So I think I need to use PNG instead (No not JPG, never). For this conversion I did some research. I ended up on using the ATL image header, and the CImage class. Well basically, converting an image is just 3 lines:
void Upscreen::ConvertToPNG(LPTSTR &sourceName, LPTSTR &destName) {
CImage img;
img.Load(sourceName);
img.Save(destName);
}
Now that I have my PNG image, its time to upload it. By this time, Min.us have their API published and you can view it here. I only used two methods, CreateGallery and UploadItem. And I created a C++ class for the API:
class Minus {
public:
std::string editorId, id, readerId;
Minus();
virtual ~Minus();
void CreateGallery();
void UploadItem(std::string&);
private:
std::string key;
};
It’s incomplete, because the other two methods wasn’t included. So basically we need to get the editor_id, reader_id, and key from the first method then use these variables on the second method. To get these variables, an HTTP GET request must be accomplished. I do not want to use too much external libraries, so I just used Winsock2. I didn’t have too much trouble performing this, and the only issue I had was separating the HTTP headers from the response body. And later on, I found out its very easy:
response = response.substr(response.find("\r\n\r\n"));
The API’s response content type is JSON. I found it hard finding a good JSON parser in C++. And I ended using JSON Spirit . The downside is, this uses Boost Headers, so both must be downloaded.
I got the variables I need, now to the HTTP POST request. This is the bloodiest part of the program. I had trouble reading the the PNG file, and used ReadFile instead. Then, I didn’t know std::string is not suitable for storing binary data. So after switching many data types, I finally decided to use just a char * pointer to hold the data. And to pass the data, I put the POST headers and the data to a std::vector variable. All went well, but I’m a having 404 error in the POST request, and the data is incomplete. I just figured out the example URL in the Min.us API documentation is wrong. The trailing slash after UploadItem is causing the 404 error, and removing it fixed the problem. The other one was caused by the Content-Length parameter. I used WireShark and LiveHTTPHeaders to trace the packets and again, some bloody debugging. Later on, I found out the number I’ve been passing exceeded by one. After this part, all went so easy. The only thing I have to deal with is validation. Whenever the clipboard has data other than an image, it crashes. So I just placed an if condition to check if the PNG data exist. Because no PNG data will be saved if there’s no valid bitmap file present.
After uploading, I used the editor_id variable and attached it to the min.us URL. And made the program open it at the default browser using ShellExecute.
Header Files
The header files I used in this project are:
#include <WinSock2.h> #include <windows.h> #include <atlimage.h> #include <string> #include <json_spirit\json_spirit_reader_template.h>
Source Code
The source code is released under the GNU GPL v3. Get it here.
Year Ends
So this became my last post for 2010. Very timely, isn’t it? Anyway, Happy New Year!


