Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#编组图像数据-复杂场景 我找到了一个用C++编写的库,用NTSC信号处理来过滤图像。你可以在这里看到:其目的是使图像看起来像是NES输出到电视上的图像_C#_Bitmap_Marshalling - Fatal编程技术网

C#编组图像数据-复杂场景 我找到了一个用C++编写的库,用NTSC信号处理来过滤图像。你可以在这里看到:其目的是使图像看起来像是NES输出到电视上的图像

C#编组图像数据-复杂场景 我找到了一个用C++编写的库,用NTSC信号处理来过滤图像。你可以在这里看到:其目的是使图像看起来像是NES输出到电视上的图像,c#,bitmap,marshalling,C#,Bitmap,Marshalling,我想用C#包装SNES版本的库(实际上,我会使用NES版本,但它只适用于NTSC调色板数据,而不适用于位图)。在玩了几个小时的代码后,我承认失败了,并向大家寻求帮助 这里是库中的一些C++代码。我已经添加了dllexports /* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown in parenthesis and should remain fairly stable in future ver

我想用C#包装SNES版本的库(实际上,我会使用NES版本,但它只适用于NTSC调色板数据,而不适用于位图)。在玩了几个小时的代码后,我承认失败了,并向大家寻求帮助

这里是库中的一些C++代码。我已经添加了dllexports

/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown
in parenthesis and should remain fairly stable in future versions. */
typedef struct snes_ntsc_setup_t
{
    /* Basic parameters */
    double hue;        /* -1 = -180 degrees     +1 = +180 degrees */
    double saturation; /* -1 = grayscale (0.0)  +1 = oversaturated colors (2.0) */
    double contrast;   /* -1 = dark (0.5)       +1 = light (1.5) */
    double brightness; /* -1 = dark (0.5)       +1 = light (1.5) */
    double sharpness;  /* edge contrast enhancement/blurring */

    /* Advanced parameters */
    double gamma;      /* -1 = dark (1.5)       +1 = light (0.5) */
    double resolution; /* image resolution */
    double artifacts;  /* artifacts caused by color changes */
    double fringing;   /* color artifacts caused by brightness changes */
    double bleed;      /* color bleed (color resolution reduction) */
    int merge_fields;  /* if 1, merges even and odd fields together to reduce flicker */
    float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */

    unsigned long const* bsnes_colortbl; /* undocumented; set to 0 */
} snes_ntsc_setup_t;

enum { snes_ntsc_entry_size = 128 };
enum { snes_ntsc_palette_size = 0x2000 };
typedef unsigned long snes_ntsc_rgb_t;
struct snes_ntsc_t {
    snes_ntsc_rgb_t table [snes_ntsc_palette_size] [snes_ntsc_entry_size];
};

/* Initializes and adjusts parameters. Can be called multiple times on the same
snes_ntsc_t object. Can pass NULL for either parameter. */
typedef struct snes_ntsc_t snes_ntsc_t;
__declspec(dllexport) void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup );

/* Filters one or more rows of pixels. Input pixel format is set by SNES_NTSC_IN_FORMAT
and output RGB depth is set by SNES_NTSC_OUT_DEPTH. Both default to 16-bit RGB.
In_row_width is the number of pixels to get to the next input row. Out_pitch
is the number of *bytes* to get to the next output row. */
__declspec(dllexport) void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input,
    long in_row_width, int burst_phase, int in_width, int in_height,
    void* rgb_out, long out_pitch );

这是C++演示代码的一个片段。它使用SDL

typedef struct image_t
{
    unsigned char const* byte_pixels;/* 8-bit pixels */
    unsigned short const* rgb_16;    /* 16-bit pixels */
    int width;
    int height;
    int row_width; /* number of pixels to get to next row (may be greater than width) */
} image_t;

image_t image;
int burst_phase = 0;
snes_ntsc_setup_t setup = snes_ntsc_composite;

snes_ntsc_t* ntsc = (snes_ntsc_t*) malloc( sizeof (snes_ntsc_t) );
if ( !ntsc )
    fatal_error( "Out of memory" );
snes_ntsc_init( ntsc, &setup );

load_bmp( &image, (argc > 1 ? argv [1] : "test.bmp"), 0 );
init_window( SNES_NTSC_OUT_WIDTH( image.width ), image.height * 2 );

// lock the SDL image surface elsewhere...
output_pitch = surface->pitch;
output_pixels = (unsigned char*) surface->pixels;

burst_phase = 0;

snes_ntsc_blit( ntsc, image.rgb_16, image.row_width, burst_phase,
    image.width, image.height, output_pixels, output_pitch );
SNES\u NTSC\u OUT\u WIDTH是一个宏,如果输入256,则返回441

此外,该库(默认情况下)构建为在6-5-6模式下,每像素16位输入和输出

使用来自docs、defines和typedefs的所有这些数据,下面是我对一些C#的尝试:

所以,问题是在
snes\u ntsc\u blit
行上,我得到了一个AccessViolationException。这个毫无帮助的错误基本上是一个segfault,但我不知道我犯了几十个可能的错误中的哪一个:

  • 我的
    snes\u ntsc\t
    表是否分配错误?也许我应该找警察来
  • 我的图像大小(602x448)可能有误吗?如果我把它做得太大,我还会得到这个错误吗?或者这是一种可能的保护措施,可以将它作为一个错误消除吗
  • 我的结构声明正确吗?我不知道是否有更多的东西需要编组,是否有错误的类型,或者其他一些东西需要输出参数
  • 我的blit参数正确吗?我真的不知道,但它似乎符合人们的要求
  • 我是否需要以某种方式封送位图数据?如果是,请解释
  • 我很抱歉提出这么大的问题,但编组是我C#职业生涯的祸根。我讨厌它。请帮忙

    编辑 我加入了断点,并且能够进入C代码。我的init调用参数现在正常了,但是对于
    blit
    ,我的输入参数都搞乱了。在VS中(在C端)将鼠标移到它上面,显示一个地址和一些unicode垃圾。我不知道这是否合适。该错误发生在内部for循环的SNES_NTSC_RGB_OUT行中,但不是在第一次通过时。所述宏进行一系列运算,然后分配给第二个参数。下面是blit函数的代码:

    void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width,
        int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
    {
        int chunk_count = (in_width - 1) / snes_ntsc_in_chunk;
        for ( ; in_height; --in_height )
        {
            SNES_NTSC_IN_T const* line_in = input;
            SNES_NTSC_BEGIN_ROW( ntsc, burst_phase,
                snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in ) );
            snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out;
            int n;
            ++line_in;
    
            for ( n = chunk_count; n; --n )
            {
                /* order of input and output pixels must not be altered */
                SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) );
                SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
                SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
    
                SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) );
                SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
                SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
    
                SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) );
                SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
                SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
                SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
    
                line_in  += 3;
                line_out += 7;
            }
    
            /* finish final pixels */
            SNES_NTSC_COLOR_IN( 0, snes_ntsc_black );
            SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
            SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
    
            SNES_NTSC_COLOR_IN( 1, snes_ntsc_black );
            SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
            SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
    
            SNES_NTSC_COLOR_IN( 2, snes_ntsc_black );
            SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
            SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
            SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
    
            burst_phase = (burst_phase + 1) % snes_ntsc_burst_count;
            input += in_row_width;
            rgb_out = (char*) rgb_out + out_pitch;
        }
    }
    

    也许我的rgb_out参数仍然没有正确编组,即使我的[out]在上面?或者我计算错了一些尺寸?再次为大量的代码表示歉意。

    在C中,
    无符号长
    是一个32位无符号整数——它对应于C#中的
    uint
    ,而不是
    ulong
    ,它是一个64位无符号整数。因为这个结构是按值传递的,所以您可能向函数传递了太多的数据,并用图像数据来替换其余的参数。更改C#绑定中的
    snes\u ntsc\t
    定义,以包含
    uint[]
    ,然后查看发生了什么


    (您在其他一些地方也犯了同样的错误。您可能会查看
    long
    类型的所有定义,并仔细检查C类型。C
    long
    将是32位的,对应于C的
    int
    ,而C
    long
    将是64位的,对应于C的
    long

    我认为你的问题可以追溯到你打电话给snes\U ntsc\U init。我通过在C++(32位)和C客户端中使用代码编写一个非托管DLL来模拟它。在DLL中,函数snes_ntsc_init和snes_ntsc_blit什么都不做——我只是在它们上面放了一个断点,看看封送的参数有什么值

    这是我在snes_ntsc_init中发现的:

    第二个参数“setup”是一个struct*。因此,您必须在C#端将其作为“ref setup”传递

    我在C#结构定义中的每个结构成员上放置了MarshalAs属性,以确保大小正确。我的DLL是32位的,但你的可能是64位的。这就是我在C#中定义结构的方式:

    解码器_矩阵是浮点*,而不是浮点。(要么是打字错误,要么就是代码盲……很容易犯这种错误。)此外,由于它是指针,你必须使用不安全的代码来初始化它,或者类似的东西。在我的测试中,我只是将其设置为IntPtr.Zero

    这就是我从C#调用函数的方式:

    在调试器的DLL中,我可以看到“setup”参数包含这些值。这意味着它被正确地编组。不一定独立于体系结构,因为其中可能还有一些隐含的大小假设,但至少这是一个开始

    我认为现在回答你的其他问题还为时过早。我建议您像我一样构建一个存根DLL,至少让所有参数都正确编组。然后你就可以担心语义了


    祝你好运!谢谢你提出了一个有趣的问题:-)

    谢谢你的更正,但它还是坏了。可能有很多问题,谢谢!在您这样说之前,我实际上没有在非托管代码中设置断点。我的头看起来很好,但另一边我的布利特情人看起来很邋遢。请参阅编辑。我修复了它-我的编组很好,只是我的参数不好。但是,我的版本和C演示程序并排进行,帮助我解决了这个问题。谢谢
    void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width,
        int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
    {
        int chunk_count = (in_width - 1) / snes_ntsc_in_chunk;
        for ( ; in_height; --in_height )
        {
            SNES_NTSC_IN_T const* line_in = input;
            SNES_NTSC_BEGIN_ROW( ntsc, burst_phase,
                snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in ) );
            snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out;
            int n;
            ++line_in;
    
            for ( n = chunk_count; n; --n )
            {
                /* order of input and output pixels must not be altered */
                SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) );
                SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
                SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
    
                SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) );
                SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
                SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
    
                SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) );
                SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
                SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
                SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
    
                line_in  += 3;
                line_out += 7;
            }
    
            /* finish final pixels */
            SNES_NTSC_COLOR_IN( 0, snes_ntsc_black );
            SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
            SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
    
            SNES_NTSC_COLOR_IN( 1, snes_ntsc_black );
            SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
            SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
    
            SNES_NTSC_COLOR_IN( 2, snes_ntsc_black );
            SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
            SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
            SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
    
            burst_phase = (burst_phase + 1) % snes_ntsc_burst_count;
            input += in_row_width;
            rgb_out = (char*) rgb_out + out_pitch;
        }
    }
    
    [DllImport("snes_server.dll")]
    internal static extern
    void snes_ntsc_init(snes_ntsc_t t, ref snes_ntsc_setup_t setup);
    
    [StructLayout(LayoutKind.Sequential)]
    internal struct snes_ntsc_setup_t
    {
        [MarshalAs(UnmanagedType.R8)] public double hue;
        [MarshalAs(UnmanagedType.R8)] public double saturation;
        [MarshalAs(UnmanagedType.R8)] public double contrast;
        [MarshalAs(UnmanagedType.R8)] public double brightness;
        [MarshalAs(UnmanagedType.R8)] public double sharpness;
    
        [MarshalAs(UnmanagedType.R8)] public double gamma;
        [MarshalAs(UnmanagedType.R8)] public double resolution;
        [MarshalAs(UnmanagedType.R8)] public double artifacts;
        [MarshalAs(UnmanagedType.R8)] public double fringing;
        [MarshalAs(UnmanagedType.R8)] public double bleed;
        [MarshalAs(UnmanagedType.I4)] public int merge_fields;
        [MarshalAs(UnmanagedType.SysInt)] public IntPtr decoder_matrix;
    
        [MarshalAs(UnmanagedType.SysInt)] public IntPtr bsnes_colortbl;
    }
    
    snes_ntsc_setup_t setup = new snes_ntsc_setup_t();
    setup.merge_fields = 1;
    setup.hue = 0.1;
    setup.saturation = 0.2;
    setup.contrast = 0.3;
    setup.brightness = 0.4;
    setup.sharpness = 0.5;
    setup.gamma = 0.6;
    setup.artifacts = 0.7;
    setup.fringing = 0.8;
    setup.bleed = 0.9;
    setup.merge_fields = 10;
    setup.decoder_matrix = IntPtr.Zero;
    setup.bsnes_colortbl = IntPtr.Zero;
    snes_ntsc_init(t, ref setup);