Page 1 of 2 12 Last
  • Jump to page:
    #1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    11
    Rep Power
    0

    How to use C based API for graphics ?


    I have this function in c++ and I want to use it in C:

    Code:
    void GetFrameData(Bitmap ^b)
    	{
    		auto bmpData = b->LockBits( System::Drawing::Rectangle(0,0,b->Width,b->Height), ImageLockMode::ReadWrite, PixelFormat::AV_PIX_FMT_RGB24);
    
        
        char* top = (char*)bmpData->Scan0.ToPointer();
    
        
        if (bmpData->Stride < 0) {
            top += bmpData->Stride * (1 - b->Height);
        }
    
        for( int y = 0; y < b->Height; ++y ) {
            RGBTRIPLE* row = (RGBTRIPLE*)(top + y * bmpData->Stride);
    
            
            for( int x = 0; x < b->Width; ++x ) {
               row[x].rgbtRed = 255;
        }
        
        b->UnlockBits( bmpData );
    	}
    	}
    In the end it's AV_PIX_FMT_RGB24 when it was on the c++ it was Format24bppRGB

    Now when it's on C I have an error on the -> symbol after the b

    The error is:


    Error 1 error C2664: 'System::Drawing::Imaging::BitmapData ^System::Drawing::Bitmap::LockBits(System::Drawing::Rectangle,System::Drawing::Imaging::ImageLockMod e,System::Drawing::Imaging::PixelFormat)' : cannot convert parameter 3 from 'AVPixelFormat' to 'System::Drawing::Imaging::PixelFormat'


    How can I fix it ?
  2. #2
  3. No Profile Picture
    I haz teh codez!
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Dec 2003
    Posts
    2,540
    Rep Power
    2337
    You may have a problem in that the code you've shown is not truly C++, but the abomination known as CLI C++, which is part of .NET. If it's even possible, I'm betting it would be a read pain in the butt to use it from C.
    I ♥ ManiacDan & requinix

    This is a sig, and not necessarily a comment on the OP:
    Please don't be a help vampire!
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    11
    Rep Power
    0

    Yes you right so what can i do ?


    How can I use lockbits in C ?
    Or it's not possible ?
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    First, disable smilies! Besides being completely useless, they cause C++ and .NET code to be misinterpreted as containing smilies and thus frak it all up. Just look at your message and you will see what I mean.

    You would have to go to the advanced editor to check the Disable smilies box, though I think that it shows up when you go back and edit your message.


    Second, that's not standard C++, but rather Visual C++.NET. What you are trying to do is to link the .NET libraries into a C program. Just trying to link a normal C++ library back into C would require a lot of rewriting (assuming that it would even do any good), so I cannot imagine what this would take.

    Why are you trying to convert this to C? Those libraries wouldn't be available outside of .NET. I'm not sure whether .NET would even support C. C++ supports almost any C code, and if it doesn't then a little bit of minor rewriting of the C would make it compatible with C++. So why try to switch from C++ to C?
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Originally Posted by chocolade
    How can I use lockbits in C ?
    Or it's not possible ?
    Lockbits is an operating-system/file-system thing. What OS/FS are you writing this for? If this is for .NET, then again the question is "why switch from C++ to C?"
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    11
    Rep Power
    0

    Let me clarify it


    I have visual studio 2012 pro
    And my project is in c++ I try to wrapp a C code.

    This function:

    Code:
    void GetFrameData(Bitmap ^b)
    	{
    		auto bmpData = b->LockBits( System::Drawing::Rectangle(0,0,b->Width,b->Height), ImageLockMode::ReadWrite, PixelFormat::Format24bppRgb);
    
        
        char* top = (char*)bmpData->Scan0.ToPointer();
    
        
        if (bmpData->Stride < 0) {
            top += bmpData->Stride * (1 - b->Height);
        }
    
        for( int y = 0; y < b->Height; ++y ) {
            RGBTRIPLE* row = (RGBTRIPLE*)(top + y * bmpData->Stride);
    
            
            for( int x = 0; x < b->Width; ++x ) {
               row[x].rgbtRed = 255;
        }
        
        b->UnlockBits( bmpData );
    	}
    	}
    Is in c++ the function get a bitmap from CSHARP
    Now I want to use the BMPDATA in this function to put it somehow in the Frame->data in the C file I have.

    This is the C code I added ot my c++ project I created a new file/item of C:

    Code:
    #include <stdlib.h>
    #include <string.h>
    #include <msclr\marshal.h>
    #include <vcclr.h>
    #include <cstdlib>
    #include <Windows.h>
    
    using namespace System;
    using namespace System::Drawing;
    using namespace System::Collections::Generic;
    using namespace System::Runtime::InteropServices;
    using namespace System::Drawing::Imaging;
    
    extern "C" {
    
    #include  "libavcodec\avcodec.h"
    #include "libavutil\mathematics.h"
    //#include "libavcodec\avcodec.h"
    
    
    AVCodec *codec;
    AVCodecContext *c= NULL;
    int i, ret, x, y, got_output;
    int total_frame_counter;
    FILE *f;
    AVFrame *frame;
    AVPacket pkt;
    int codec_id;
    uint8_t endcode[] = { 0, 0, 1, 0xb7 };
    int errn;
    
    void Encoder_init()
    {
    	avcodec_register_all();
        /* find the mpeg1 video encoder */
    
    	codec_id = CODEC_ID_MPEG1VIDEO;
    
        codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
        if (!codec) {
            fprintf(stderr, "Codec not found\n");
            exit(1);
        }
        c = avcodec_alloc_context3(codec);
        if (!c) {
            fprintf(stderr, "Could not allocate video codec context\n");
            exit(1);
        }
        /* put sample parameters */
        c->bit_rate = 400000;
        /* resolution must be a multiple of two */
        c->width = 352;
        c->height = 288;
        /* frames per second */
        
    	//c->time_base= (AVRational){1,25};
    	c->time_base.num=1;c->time_base.den=25;
    	
        c->gop_size = 10; /* emit one intra frame every ten frames */
        c->max_b_frames=1;
    	c->pix_fmt = AV_PIX_FMT_RGB24;//AV_PIX_FMT_YUV420P;
    	/*
        if(codec_id == AV_CODEC_ID_H264)
            av_opt_set(c->priv_data, "preset", "slow", 0);
    		*/
    }
    
    const char *Encoder_GetCodecName( int id )
    {
    	return avcodec_get_name( (AVCodecID)id );
    }
    
    void Encoder_start(char *filename)
    {
    	printf("Encode video file %s\n", filename);
    	/* open it */
        if (avcodec_open2(c, codec, NULL) < 0) {
            fprintf(stderr, "Could not open codec\n");
            exit(1);
        }
    //    f = fopen(filename, "wb");
    	errn = fopen_s(&f,filename, "wb");
    
        if (!f) {
            fprintf(stderr, "Could not open %s\n", filename);
            exit(1);
        }
    
    	
    	frame = avcodec_alloc_frame();
        if (!frame) {
            fprintf(stderr, "Could not allocate video frame\n");
            exit(1);
        }
    
    	frame->format = c->pix_fmt;
        frame->width  = c->width;
        frame->height = c->height;
        /* the image can be allocated by any means and av_image_alloc() is
         * just the most convenient way if av_malloc() is to be used */
    //    ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height,
      //                       c->pix_fmt, 32);
    
    	 frame->data[0] = (uint8_t*)av_malloc(1000000);
    	 frame->data[1] = (uint8_t*)av_malloc(1000000);
    	 frame->data[2] = (uint8_t*)av_malloc(1000000);
    	 frame->data[3] = (uint8_t*)av_malloc(1000000);
    	 frame->data[4] = (uint8_t*)av_malloc(1000000);
    	 frame->data[5] = (uint8_t*)av_malloc(1000000);
    	 frame->data[6] = (uint8_t*)av_malloc(1000000);
    	 frame->data[7] = (uint8_t*)av_malloc(1000000);
    
    	 if (frame->data[7]==0) {
        //if (ret < 0) {
            fprintf(stderr, "Could not allocate raw picture buffer\n");
            exit(1);
        }
    
    	 total_frame_counter=0;
    }
    I'm not sure yet how to do it but I need somehow to put in each frame->data the value/s from the bmpdata in the c++ function.

    Any ideas how can I do it ?
    My brother suggest me to move the function from the c++ to C but if not how else can I do it ?
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    11
    Rep Power
    0

    The reason i wanted to use lockbits


    Is that lockbits much faster then using getpixel
    But then again how do I make it in C and if not in C let's say I leave this function in my c++ how do I move put the values of bmpdata to the frame->data ?

    I saw that the frame pixel format in C have also RGB
    Which one I should use in the c++ and in the C ?

    In the C it's set now to :

    c->pix_fmt = AV_PIX_FMT_RGB24;

    It was: AV_PIX_FMT_YUV420P;
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    185
    Rep Power
    82
    Is that lockbits much faster then using getpixel
    Yea, it's a lot faster.

    One option is to use the GDI+ API..

    Code:
    #pragma comment(lib, "Gdi32.lib")
    #pragma comment(lib, "User32.lib")
    #pragma comment(lib, "gdiplus.lib")
    
    #include <windows.h>
    #include <gdiplus.h>
    #include <GdiPlusEnums.h>
    
    using namespace Gdiplus;
    
    int main(void)
    {
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR hgdiplusToken;
        Gdiplus::GdiplusStartup ( &hgdiplusToken, &gdiplusStartupInput, NULL );
    
        Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap ( L"yourfile.png" );
        int width = bitmap->GetWidth();
        int height = bitmap->GetHeight();
        Gdiplus::Rect rt ( 0, 0, width, height );
        unsigned char *image = new unsigned char[width*height*4];
        Gdiplus::BitmapData data;
        bitmap->LockBits ( &rt, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &data );
        memcpy ( image, data.Scan0, sizeof ( unsigned char ) * width * height * 4 );
        bitmap->UnlockBits ( &data );
        delete bitmap;
        bitmap = NULL;
        delete[] image;
        Gdiplus::GdiplusShutdown ( hgdiplusToken );
        return 0;
    }
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    11
    Rep Power
    0

    Good example how do i change the "yourfile.png" ?


    Or how do I make that this function will get a bitmap any bitmap ? I'm calling this function later through c++ so I need to make it get Bitmap. Or it's not logic and I should not call it outside the C file ?
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    185
    Rep Power
    82
    Originally Posted by chocolade
    Or how do I make that this function will get a bitmap any bitmap ? I'm calling this function later through c++ so I need to make it get Bitmap. Or it's not logic and I should not call it outside the C file ?
    I'm not sure I really understand your question. But anyway, you can change the yourfile.png file name in the above example to anything. For instance, you can change it to yournewbmfile.bmp. GDI+ supports a variety of graphic file formats from BMP, JPEG, GIF to TIFF etc.
  20. #11
  21. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    11
    Rep Power
    0

    What i mean is that


    You used L"yourfilenaem..."
    I saw that L is List

    So if I want instead "yourfile.png" to be global Bitmap so if I call this function somewhere else it will get any Bitmap and not the specific name in the ""

    I took you'r code and put it in a function inside the C file:

    Code:
    void GetFrameData()
    	{
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR hgdiplusToken;
        Gdiplus::GdiplusStartup ( &hgdiplusToken, &gdiplusStartupInput, NULL );
    
    	Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap ( L"hi" );
        int width = bitmap->GetWidth();
        int height = bitmap->GetHeight();
        Gdiplus::Rect rt ( 0, 0, width, height );
        unsigned char *image = new unsigned char[width*height*4];
        Gdiplus::BitmapData data;
        bitmap->LockBits ( &rt, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &data );
        memcpy ( image, data.Scan0, sizeof ( unsigned char ) * width * height * 4 );
        bitmap->UnlockBits ( &data );
        delete bitmap;
        bitmap = NULL;
        delete[] image;
        Gdiplus::GdiplusShutdown ( hgdiplusToken );
    
    	}
    So now I want instead putting some name to make a global Bitmap variable so I can call the function GetFrameData for example:

    GetFrameData("mynameis");
    And then the file name in the function will be "mynameis" and not the "yourfile.png" name.
  22. #12
  23. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2012
    Posts
    185
    Rep Power
    82
    Originally Posted by chocolade
    You used L"yourfilenaem..."
    I saw that L is List

    So if I want instead "yourfile.png" to be global Bitmap so if I call this function somewhere else it will get any Bitmap and not the specific name in the ""

    I took you'r code and put it in a function inside the C file:

    Code:
    void GetFrameData()
    	{
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR hgdiplusToken;
        Gdiplus::GdiplusStartup ( &hgdiplusToken, &gdiplusStartupInput, NULL );
    
    	Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap ( L"hi" );
        int width = bitmap->GetWidth();
        int height = bitmap->GetHeight();
        Gdiplus::Rect rt ( 0, 0, width, height );
        unsigned char *image = new unsigned char[width*height*4];
        Gdiplus::BitmapData data;
        bitmap->LockBits ( &rt, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &data );
        memcpy ( image, data.Scan0, sizeof ( unsigned char ) * width * height * 4 );
        bitmap->UnlockBits ( &data );
        delete bitmap;
        bitmap = NULL;
        delete[] image;
        Gdiplus::GdiplusShutdown ( hgdiplusToken );
    
    	}
    So now I want instead putting some name to make a global Bitmap variable so I can call the function GetFrameData for example:

    GetFrameData("mynameis");
    And then the file name in the function will be "mynameis" and not the "yourfile.png" name.
    The "L" that you see in the example code is the lazy person's way of implementing a Unicode file name. GDI+ uses (requires) Unicode in order to allow it to draw text in any language supported by the system. The "L" prefix denotes a wide character/string literal. It is a type wchar_t instead of char.

    If you want to call GetFrameData("mynameis"), you must either preface mynameis with the "L" or create a wide character string variable initialized to mynameis and pass it to GetFrameData.
  24. #13
  25. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    11
    Rep Power
    0

    So i tried to use the wchar_t but not working


    In C file code on top I did:

    Code:
    wchar_t *filename;
    Then inside the GetFrameData function I did:

    Code:
    Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap ( filename );
    Then i'm using a header file to pass the filename variable globaly:

    Code:
    wchar_t filename;
    Then in the header file on the c++ i'm doing:

    Code:
    void Push( Bitmap ^b )
    	{
    		filename = b;
                  }
    Ofcourse the filename is type wchar_t and the b is Bitmap so i'm getting an error I didn't except it to work so how can I fix it ?
  26. #14
  27. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    11
    Rep Power
    0

    Clarify:


    What I need is that in this c++ function:

    Code:
    void Push( Bitmap ^b )
    	{
    		Encoder_push_frame();
    	}
    I have global variable from the C file I called it:

    wchar_t filename;

    I want to get the bitmap file name and use it as filename.

    Or maybe i'm wrong since in C I have the function:

    Code:
    void GetFrameData()
    	{
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR hgdiplusToken;
        Gdiplus::GdiplusStartup ( &hgdiplusToken, &gdiplusStartupInput, NULL );
    
    	Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap ( filename );
        int width = bitmap->GetWidth();
        int height = bitmap->GetHeight();
        Gdiplus::Rect rt ( 0, 0, width, height );
        unsigned char *image = new unsigned char[width*height*4];
        Gdiplus::BitmapData data;
        bitmap->LockBits ( &rt, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &data );
        memcpy ( image, data.Scan0, sizeof ( unsigned char ) * width * height * 4 );
        bitmap->UnlockBits ( &data );
        delete bitmap;
        bitmap = NULL;
        delete[] image;
        Gdiplus::GdiplusShutdown ( hgdiplusToken );
    
    	}
    So what should I put as filename in this function ? Should it be a bitmap type or somehow to get the bitmap in c++ file name and put it in the wchar_t filename ?
  28. #15
  29. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    11
    Rep Power
    0

    Ok this is what i wanted to do almost:


    In c++

    Code:
    void Push( Bitmap ^b )
    	{
                  }
    Now in this Push function I want to put in the fname the variable fname the Bitmap ? What should I do ?
    I have a global variable I called it fname which is in C:
    The variable is type: WCHAR *fname

    The variable is in this C function:

    Code:
    void GetFrameData()
    	{
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR hgdiplusToken;
        Gdiplus::GdiplusStartup ( &hgdiplusToken, &gdiplusStartupInput, NULL );
    
    	Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap ( fname );
        int width = bitmap->GetWidth();
        int height = bitmap->GetHeight();
        Gdiplus::Rect rt ( 0, 0, width, height );
        unsigned char *image = new unsigned char[width*height*4];
        Gdiplus::BitmapData data;
        bitmap->LockBits ( &rt, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &data );
        memcpy ( image, data.Scan0, sizeof ( unsigned char ) * width * height * 4 );
        bitmap->UnlockBits ( &data );
        delete bitmap;
        bitmap = NULL;
        delete[] image;
        Gdiplus::GdiplusShutdown ( hgdiplusToken );
    
    	}
    But WCHAR *fname is not Bitmap so in the c++ in the Push function what should I do with the Bitmap and the fname ?

    Ican't understand.
Page 1 of 2 12 Last
  • Jump to page:

IMN logo majestic logo threadwatch logo seochat tools logo