我怎样才能从.NET位图复制到av_image帧数据的所有像素?(How can i copy fr

2019-10-29 05:33发布

我只是在我的C ++项目中使用与位图锁位的例子创建了一个新功能:

void GetFrameData(Bitmap ^b)
    {

        typedef System::Drawing::Rectangle R;
        R rect = R(0,0,b->Width,b->Height);
        System::Drawing::Imaging::BitmapData^ bmpData = b->LockBits( rect, System::Drawing::Imaging::ImageLockMode::ReadWrite, b->PixelFormat );
        // Get the address of the first line.
        IntPtr ptr = bmpData->Scan0;

        // Declare an array to hold the bytes of the bitmap. 
        // This code is specific to a bitmap with 24 bits per pixels. 
       int bytes = Math::Abs(bmpData->Stride) * b->Height;
       array<Byte>^rgbValues = gcnew array<Byte>(bytes);

       // Copy the RGB values into the array.
      System::Runtime::InteropServices::Marshal::Copy( ptr, rgbValues, 0, bytes );

      // Set every third value to 255.   
     for ( int counter = 2; counter < rgbValues->Length; counter += 3 )
      rgbValues[ counter ] = 255;

     // Copy the RGB values back to the bitmap
    System::Runtime::InteropServices::Marshal::Copy( rgbValues, 0, ptr, bytes );

    // Unlock the bits.
    b->UnlockBits( bmpData );
    }

这个功能可以从CSHARP得到一个位图文件并不知我需要使用这个lockbits的像素从位图到这个功能复制:

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;
}



void Encoder_push_frame()
{
    /* encode 1 second of video */
   // for(i=0;i<25;i++) {
        av_init_packet(&pkt);
        pkt.data = NULL;    // packet data will be allocated by the encoder
        pkt.size = 0;
        fflush(stdout);
        /* prepare a dummy image */
        /* Y */
        for(y=0;y<c->height;y++) {
            for(x=0;x<c->width;x++) {
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }
        }
        /* Cb and Cr */
        for(y=0;y<c->height/2;y++) {
            for(x=0;x<c->width/2;x++) {
                frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
                frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
            }
        }
        frame->pts = total_frame_counter;

        total_frame_counter++;

        /* encode the image */
        ret = avcodec_encode_video2(c, &pkt, frame, &got_output);
        if (ret < 0) {
            fprintf(stderr, "Error encoding frame\n");
            exit(1);
        }
        if (got_output) {
            printf("Write frame %3d (size=%5d)\n", total_frame_counter, pkt.size);
            fwrite(pkt.data, 1, pkt.size, f);
            av_free_packet(&pkt);
        }
   // }

}

我不知道如何填写,并与什么av_malloc我将它设置为1000000测试每个地方。

而Encoder_push_frame功能应该得到的像素或者它与av_malloc的想法是填补push_frame功能将图像从位图像素的。

我尝试了很多方法,但它并没有在所有的工作。

编辑

我使用此代码:

void GetFrameData(Bitmap ^b)
    {
        auto bmpData = b->LockBits( System::Drawing::Rectangle(0,0,b->Width,b->Height), ImageLockMode::ReadWrite, PixelFormat::Format24bppRgb );

    // The beginning of the bitmap data in memory
    char* top = bmpData->Scan0.ToPointer();

    // find bitmap data for the top row (if bottom-up bitmap, this is at the end)
    if (bmpData->Stride < 0) {
        top += Stride * (1 - b->Height);
    }

    for( int y = 0; y < b->Height; ++y ) {
        RGBTRIPLE* row = (RGBTRIPLE*)(top + y * bmpData->Stride);

        // saturate red channel
        for( int x = 0; x < b->Width; ++x ) {
            row[x].rgbtBlue = 255;
            row[x].rgbtGreen = 255;
            row[x].rgbtRed = 255;
    }

    // Unlock the bits.
    b->UnlockBits( bmpData );
    }

在矩形我不得不将其更改为:系统::绘图::矩形如果不是的话,我对矩形一个错误,它与另一矩形的冲突。 但经过现在改口了我对bmpData在这条线的错误:

char* top = bmpData->Scan0.ToPointer();

智能感知:类型的值“无效*”不能用于初始化类型“的char *”的一个实体

第二个错误是在跨越:

top += Stride * (1 - b->Height);

错误:智能感知:标识符“步幅”是未定义的

我怎样才能解决这个错误。

和:

改变的for循环:

for( int x = 0; x < b->Width; ++x ) {
            row[x].rgbtBlue = 255;
            row[x].rgbtGreen = 255;
            row[x].rgbtRed = 255;

其原因我改变它是你没有行[X] .R = 255; 但R不存在/定义,因此我应该怎么在这对如何解决它呢? (我想我所做的是错的)。

Answer 1:

不要打扰从数据复制Scan0到一个新的数组。 位图数据不受到垃圾收集器被移动,和C ++是完全能够在适当位置与数据的工作,使用指针铸造。

就像是

#include <windows.h>
void GetFrameData(Bitmap ^b)
{
    using System::Drawing::Imaging::ImageLockMode;
    using System::Drawing::Imaging::PixelFormat;
    using System::Drawing::Rectangle;
    auto bmpData = b->LockBits( Rectangle(0,0,b->Width,b->Height), ImageLockMode::ReadWrite, PixelFormat::Format24bppRgb );

    // The beginning of the bitmap data in memory
    char* top = (char*)bmpData->Scan0.ToPointer();

    // find bitmap data for the top row (if bottom-up bitmap, this is at the end)
    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);

        // saturate red channel
        for( int x = 0; x < b->Width; ++x ) {
           row[x].rgbtRed = 255;
    }

    // Unlock the bits.
    b->UnlockBits( bmpData );
}

现在,当你在av_format图像填充您可以使用这些RGB值calulate Y / CR / Cb值。 (或者只是告诉av_format图像是RGB)



文章来源: How can i copy from a .NET Bitmap all pixels to av_image frame data?
标签: .net c++-cli