C ++ memcpy и счастливое нарушение доступа - PullRequest
2 голосов
/ 27 июля 2011

По какой-то причине я не могу понять, что получаю нарушение прав доступа.

memcpy_s (buffer, bytes_per_line * height, image, bytes_per_line * height);

Это целая функция:

int Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)   
{   
    // this function is used to flip bottom-up .BMP images   

    UCHAR *buffer; // used to perform the image processing   
    int index;     // looping index   

    // allocate the temporary buffer   
    if (!(buffer = (UCHAR *) malloc (bytes_per_line * height)))   
        return(0);   

    // copy image to work area   
    //memcpy(buffer, image, bytes_per_line * height);   
    memcpy_s (buffer, bytes_per_line * height, image, bytes_per_line * height);

    // flip vertically   
    for (index = 0; index < height; index++)   
        memcpy(&image[((height - 1) - index) * bytes_per_line], &buffer[index * bytes_per_line], bytes_per_line);   

    // release the memory   
    free(buffer);   

    // return success   
    return(1);   

} // end Flip_Bitmap   

Весь код: http://pastebin.com/udRqgCfU

Для запуска вам понадобится 24-битное растровое изображение в вашем исходном каталоге. Это часть большего кода, я пытаюсь заставить функцию Load_Bitmap_File работать ... Итак, есть идеи?

Ответы [ 3 ]

5 голосов
/ 27 июля 2011

Вы получаете нарушение прав доступа, потому что многие графические программы неправильно устанавливают biSizeImage .Используемое изображение, вероятно, имеет biSizeImage, установленное в 0, поэтому вы не выделяете память для данных изображения (в действительности вы, вероятно, выделяете 4-16 байт, поскольку большинство реализаций malloc вернетне NULL значение, даже если запрошенный размер выделения равен 0).Поэтому, когда вы копируете данные, вы читаете за концом этого массива, что приводит к нарушению прав доступа.

Игнорируйте параметр biSizeImage и вычисляйте размер изображения самостоятельно.Помните, что размер каждой строки сканирования должен быть кратным 4 байтам, поэтому вам нужно округлить:

// Pseudocode
#define ROUNDUP(value, power_of_2) (((value) + (power_of_2) - 1) & (~((power_of_2) - 1)))
bytes_per_line = ROUNDUP(width * bits_per_pixel/8, 4)
image_size = bytes_per_line * height;

Затем просто используйте один и тот же размер изображения для чтения в данных изображения и для переворачиванияэто.

3 голосов
/ 27 июля 2011

Как отмечалось в комментариях, данные изображения не обязательно имеют ширину * высоту * bytes_per_pixel

Доступ к памяти обычно быстрее на 32-битных границах, а при работе с изображениями скорость обычно имеет значение.Из-за этого строки изображения часто сдвигаются, чтобы начать на 4-байтовой (32-битной) границе

Если пиксели изображения 32-битные (т.е. RGBA), это не проблема, но если у вас есть 3 байта на пиксель (24 бита), затем для определенной ширины изображения, где число столбцов * 3 не кратно 4, тогда дополнительные пустые байты будут вставлены в edn каждой строки.

Формат изображения, вероятно, имеетширина шага или значение размера, чтобы сказать вам это.

2 голосов
/ 27 июля 2011

Вы выделяете bitmap->bitmapinfoheader.biSizeImage для image, но приступаете к копированию bitmap->bitmapinfoheader.biWidth * (bitmap->bitmapinfoheader.biBitCount / 8) * bitmap->bitmapinfoheader.biHeight байтов данных. Могу поспорить, что два числа не совпадают.

...