Results 1 to 8 of 8

Thread: takeScreen shot

  1. #1
    Join Date
    Sep 2010
    Posts
    5,762
    Mentioned
    136 Post(s)
    Quoted
    2739 Post(s)

    Default takeScreen shot

    I was bored and messing around with simba last night, and I wrote up a little take screenshot function..


    Simba Code:
    procedure takeScreenshot(x1, y1, x2, y2:integer);
    var
      i, k, c:integer;
    begin
      setLength(tpa, (x2 - x1) * (y2 - y1));
      setLength(colors, length(tpa));
      for i := x1 to x2 - 1 do
        for k := y1 to y2 - 1 do
        begin
          tpa[c] := point(i, k);
          Colors[c] := getColor(i, k);
          c := c + 1;
        end;
    end;

    full
    Simba Code:
    var
      tpa:tpointarray;
      colors:tintegerarray;



    procedure showScreenShot(x1, y1, x2, y2:integer);
    var
      tpa2:tpointarray;
      bmp, i:integer;
    begin
      setLength(tpa2, length(tpa));
      for i := 0 to high(tpa) do
        tpa2[i] := point(tpa[i].x - x1, tpa[i].y - y1);
      bmp := createBitmap(x2 - x1, y2 - y1);
      fastsetpixels(bmp, tpa2, colors);
      DisplayDebugImgWindow(x2 - x1 + 1, y2 - y1 + 1);
      DrawBitmapDebugImg(Bmp);
      freebitmap(bmp);
    end;

    procedure takeScreenshot(x1, y1, x2, y2:integer);
    var
      i, k, c:integer;
    begin
      setLength(tpa, (x2 - x1) * (y2 - y1));
      setLength(colors, length(tpa));
      for i := x1 to x2 - 1 do
        for k := y1 to y2 - 1 do
        begin
          tpa[c] := point(i, k);
          Colors[c] := getColor(i, k);
          c := c + 1;
        end;
      showScreenShot(x1, y1, x2, y2);
    end;

    var
      t:integer;

    begin
      t := getsystemTime;
      takeScreenshot(2, 2, 843, 857);
      writeln('Took ' , GetsystemTime - t, ' ms');
    end.


    It's pretty darn slow, (4000 ms for my like 1900X1700 screen or something) I didn't really do it for speed or any purpose, I just wanted to make the function on my own without the help of anything (sort of)



    But I was wondering, how could I replicate this in c++? How would I actually capture the window and then display the image?

    my c++ code so far:

    c++ Code:
    #include <iostream>
    #include<windows.h>

    using namespace std;



    void takeScreenshot(int x1, int y1, int x2, int y2)
    {
          std::cout << "Hello World!";
    }
    int main()
    {
        takeScreenshot(0, 0, 5, 5)
        return 0;
    }

    lol

  2. #2
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    C++ Code:
    #include <windows.h>
    #include <iostream>
    #include <fstream>
    #include <chrono>
    #include <ctime>

    typedef struct
    {
        HBITMAP hBmp;
        int Width, Height;
        unsigned int* Pixels;
        unsigned short BitsPerPixel;
    } BmpData;

    bool ScreenShot(BmpData &Data, HDC DC)
    {
        bool Result = false;
        memset(&Data, 0, sizeof(Data));
        HDC hdcMem = CreateCompatibleDC(DC);
        Data.Width = GetDeviceCaps(DC, HORZRES);
        Data.Height = GetDeviceCaps(DC, VERTRES);

        unsigned char* Pixels = NULL;
        unsigned short BitsPerPixel = 32;
        BITMAPINFO Info = {{sizeof(BITMAPINFOHEADER), Data.Width, -Data.Height, 1, BitsPerPixel, BI_RGB, 0, 0, 0, 0, 0}};

        Data.hBmp = CreateDIBSection(DC, &Info, DIB_RGB_COLORS, reinterpret_cast<void**>(&Pixels), NULL, 0);
        if(Data.hBmp)
        {
            HBITMAP hOld = reinterpret_cast<HBITMAP>(SelectObject(hdcMem, Data.hBmp));
            BitBlt(hdcMem, 0, 0, Data.Width, Data.Height, DC, 0, 0, SRCCOPY);
            SelectObject(hdcMem, hOld);
            Data.Height *= -1;
            Data.BitsPerPixel = BitsPerPixel;
            Data.Pixels = reinterpret_cast<unsigned int*>(Pixels);
            Result = true;
        }

        DeleteDC(hdcMem);
        return Result;
    }

    /*Portable way to save a bitmap =)*/
    void SaveBitmap(const char* FilePath, const BmpData &Data)
    {
        std::fstream hFile(FilePath, std::ios::out | std::ios::binary);
        if (!hFile.is_open())
        {
            printf("%s", "Error. Cannot Create Bitmap.");
            return;
        }

        unsigned int Trash = 0;
        unsigned short Planes = 1;
        unsigned int biSize = 40;
        unsigned short Type = 0x4D42;
        unsigned int compression = 0;
        unsigned int PixelsOffsetBits = 54;
        int Width = Data.Width;
        int Height = -Data.Height;
        unsigned short BitsPerPixel = Data.BitsPerPixel;
        unsigned int size = ((Width * BitsPerPixel + 31) / 32) * 4 * Height;
        unsigned int bfSize = 54 + size;
        Height *= -1;

        hFile.write(reinterpret_cast<char*>(&Type), sizeof(Type));
        hFile.write(reinterpret_cast<char*>(&bfSize), sizeof(bfSize));
        hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
        hFile.write(reinterpret_cast<char*>(&PixelsOffsetBits), sizeof(PixelsOffsetBits));
        hFile.write(reinterpret_cast<char*>(&biSize), sizeof(biSize));
        hFile.write(reinterpret_cast<char*>(&Width), sizeof(Width));
        hFile.write(reinterpret_cast<char*>(&Height), sizeof(Height));
        hFile.write(reinterpret_cast<char*>(&Planes), sizeof(Planes));
        hFile.write(reinterpret_cast<char*>(&BitsPerPixel), sizeof(BitsPerPixel));
        hFile.write(reinterpret_cast<char*>(&compression), sizeof(compression));
        hFile.write(reinterpret_cast<char*>(&size), sizeof(size));
        hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
        hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
        hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
        hFile.write(reinterpret_cast<char*>(&Trash), sizeof(unsigned int));
        hFile.write(reinterpret_cast<char*>(Data.Pixels), size);
        hFile.close();
    }

    std::chrono::time_point<std::chrono::high_resolution_clock> SystemTime()
    {
        return std::chrono::high_resolution_clock::now();
    }

    float FloatTimeDuration(std::chrono::time_point<std::chrono::high_resolution_clock> Time)
    {
        return std::chrono::duration<float>(SystemTime() - Time).count() * 1000.0f;
    }

    unsigned int TimeDuration(std::chrono::time_point<std::chrono::high_resolution_clock> Time)
    {
        return std::chrono::duration_cast<std::chrono::milliseconds>(SystemTime() - Time).count();
    }

    int main()
    {
        HWND MyWindow = nullptr;  //Handle to the window that you want to screenshot..

        BmpData data;
        HDC Screen = GetDC(MyWindow); //Get a DC..

        auto Time = SystemTime();
        ScreenShot(data, Screen);
        std::cout<<"It took: "<<FloatTimeDuration(Time)<<"ms to take a screenshot!\n";

        SaveBitmap("C:/Users/Brandon/desktop/Foo.bmp", data);
        DeleteDC(Screen);
        DeleteObject(data.hBmp);
    }
    Last edited by Brandon; 01-18-2014 at 10:24 PM.
    I am Ggzz..
    Hackintosher

  3. #3
    Join Date
    Sep 2010
    Posts
    5,762
    Mentioned
    136 Post(s)
    Quoted
    2739 Post(s)

    Default

    @Brandon; C:\Users\\Desktop\Takescreenshot\main.cpp|86|error : 'nullptr' was not declared in this scope|


    hmm am I supposed to input a windowname?

  4. #4
    Join Date
    Aug 2007
    Location
    Colorado
    Posts
    7,421
    Mentioned
    268 Post(s)
    Quoted
    1442 Post(s)

    Default

    I'm guessing Warpie can help speed this up.

    Current projects:
    [ AeroGuardians (GotR minigame), Motherlode Miner, Blast furnace ]

    "I won't fall in your gravity. Open your eyes,
    you're the Earth and I'm the sky..."


  5. #5
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by Officer Barbrady View Post
    @Brandon; C:\Users\\Desktop\Takescreenshot\main.cpp|86|error : 'nullptr' was not declared in this scope|


    hmm am I supposed to input a windowname?

    You need to enable C++11 to use nullptr.

    http://i.imgur.com/d0V3BFk.png


    Secondly.. You're supposed to replace the nullptr with GetDesktopWindow(); or whatever the handle to the window is that you want to screenshot.

    Finally, to optimise your Simba code:

    Simba Code:
    var
      t:integer;

    begin
      t := getsystemTime;
      FreeBitmap(BitmapFromClient(2, 2, 843, 857)); //Takes a screenshot and deletes it.
      writeln('Took ' , GetsystemTime - t, ' ms');
    end.
    Last edited by Brandon; 01-18-2014 at 10:29 PM.
    I am Ggzz..
    Hackintosher

  6. #6
    Join Date
    Nov 2011
    Location
    England
    Posts
    3,072
    Mentioned
    296 Post(s)
    Quoted
    1094 Post(s)

    Default

    Uh, Are you aware there is SaveScreenshot in Simba?

    Also yikes, I couldn't think of a way to make it slower...!

  7. #7
    Join Date
    Jan 2012
    Posts
    1,596
    Mentioned
    78 Post(s)
    Quoted
    826 Post(s)

    Default

    Quote Originally Posted by Olly View Post
    Uh, Are you aware there is SaveScreenshot in Simba?

    Also yikes, I couldn't think of a way to make it slower...!
    Oh i could. make it save each color in rgb in 3 separate arrays!

  8. #8
    Join Date
    Feb 2012
    Location
    Norway
    Posts
    995
    Mentioned
    145 Post(s)
    Quoted
    596 Post(s)

    Default

    Quote Originally Posted by Turpinator View Post
    Oh i could. make it save each color in rgb in 3 separate arrays!
    Why would you do that? Also, you have TMufasaBitmap.GetData() which returns an record array (R,G,B,A), no need for separate arrays...
    The color-int you get normally can easly "be bitshifted" (which is very fast) so you can get the R,G,B values that way.

    I would avoid doing anything related to a lot of iterations within a (slow) interpreted language like PS, even Lape would be quite a bit to slow.


    Fastest way to grab a screenshot in Simba is (as far as I remember):
    > BitmapFromClient(x1, y1, x2, y2)
    To get the whole screen you would need to set the client as the mainscreen (pretty sure you can do that within the function).

    If you want the data separated (like in the first post) you can do something like:
    Code:
    procedure UglyScreenShotThingyCrap(x1,y1,x2,y2: Integer;
                                       var TPA:TPointArray; var Colors:TIntegerArray);
    var
      im: Integer;
    begin
      im := BitmapFromClient(0,0,x2,y2); 
      TPA := TPAFromBox(IntToBox(x1,y1,x2,y2));
      Colors := FastGetPixels(im,TPA);
      FreeBitmap(im);
    end;
    
    var
      T: Integer;
      TPA:TPointArray;
      Colors:TIntegerArray;
    begin
      t := GetTimeRunning;
      UglyScreenShotThingyCrap(0,0,850,850, TPA, Colors);
      writeln('Took ', GetTimeRunning - t, ' ms');
    end.

    If you just want direct array access to the data I would prefer a matrix.. And thanks to Olly we have BitmapToMatrix in Simba:
    Code:
    ...
    var
      im: Integer;
      Matrix: T2DIntegerArray;
    begin
      im := BitmapFromClient(0,0,800,600); //Screenshot.
      Matrix := BitmapToMatrix(im);
    
      WriteLn(Matrix[300][300]);  //Index with Matrix[y][x]
    end;
    !No priv. messages please

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •