Преобразовать цветное изображение в черно-белое - C (СИ)

Узнай цену своей работы

Формулировка задачи:

Интересует не вычисление порога, и не алгоритм. В c# я загружаю изображение в bitmap, лочу, загружаю через marshal copy в память, редактирую байты в массиве , унлочу. А как эту задачу решить в си?

Решение задачи: «Преобразовать цветное изображение в черно-белое»

textual
Листинг программы
#include <stdio.h>
#include <malloc.h>
#include <stdint.h>
 
//только для 24/32-битных растров
int bmp_to_gray(const char* fn){
    int       bpp, width, height, r, g, b;
    long      off;
    size_t    num, size, i;
    uint8_t*  bits, *pb;
    uint16_t  finf[7];
    uint32_t  inf[10];
    
    FILE* fp = fopen(fn, "rb+");
    if(fp == NULL)
        return 0;
 
    num = fread((void*)&finf[0], sizeof(finf[0]), 7, fp);
    if((finf[0] != 0x4D42) || (num != 7)){
        fclose(fp);
        return 0;
    }
 
    num = fread((void*)&inf[0], sizeof(inf[0]), 10, fp);
    bpp = (int)((inf[3] >> 16) & 0xFFFF);
    if((inf[4] != 0) || (bpp < 24) || (bpp > 32) || (num != 10)){
        fclose(fp);
        return 0;
    }
 
    off = (long)((uint32_t)finf[6] << 16) | finf[5];
    fseek(fp, off, SEEK_SET);
    if(feof(fp)){
        fclose(fp);
        return 0;
    }
    width  = (int)inf[1];
    height = (int)inf[2];
    if(height < 0)
        height = 0 - height;
 
    size   = (size_t)((width * bpp + 31) & ~31) / 8 * height;
    bits   = (uint8_t*)malloc(size);
    if(bits == NULL){
        fclose(fp);
        return 0;
    }
 
    num = fread((void*)bits, 1, size, fp);
    if(num != size){
        fclose(fp);
        free(bits);
        return 0;
    }
    
    bpp /= 8;
    pb   = bits;
    for(i = 0; i < size; i += bpp){
        r     = (int)pb[0];
        g     = (int)pb[1];
        b     = (int)pb[2];
        pb[0] = (uint8_t)((r * 77 + g * 150 + b * 29 + 128) / 256);
        pb[1] = pb[0];
        pb[2] = pb[0];
        pb   += bpp;
    }
    fseek(fp, off, SEEK_SET);
    num = fwrite((const void*)bits, 1, size, fp);
    fflush(fp);
    fclose(fp);
    
    free(bits);
    if(num != size)
        num = 0;
    return (num > 0);
}
 
int main(void) {
    if(bmp_to_gray("image.bmp"))
        puts("yes to gray.");
    else
        puts("error convert!");
    return 0;
}

Объяснение кода листинга программы

Вот что делает этот код:

  1. Открывает файл изображения. Функция fopen используется для открытия файла с именем image.bmp в режиме чтения (rb+). Если файл не может быть открыт, функция возвращает NULL.
  2. Проверяет, является ли файл изображением BMP. Функция fread используется для чтения первых 7 байтов файла. Затем проверяется, являются ли первые 2 байта (код файла) равными 0x4D42 (BMP). Если это не так или чтение не удалось, файл закрывается и возвращается 0.
  3. Проверяет, является ли файл 24- или 32-битным изображением. Функция fread используется для чтения следующих 10 байтов файла. Затем извлекаются следующие 3 байта (информация о глубине цвета) и проверяются. Если глубина цвета не равна 24 или 32, файл закрывается и возвращается 0.
  4. Находит смещение данных изображения. Следующие 2 байта (информация о размере) считываются и используются для вычисления смещения данных изображения.
  5. Считывает данные изображения и преобразует их в оттенки серого. Функция fread используется для считывания данных изображения. Затем данные перебираются, и для каждого пикселя вычисляется средний цвет (красный, зеленый и синий пиксели считаются одинаковыми). Этот средний цвет затем записывается обратно в файл.
  6. Закрывает файл и проверяет успешность операции. Функция fclose используется для закрытия файла. Затем проверяется, удалось ли записать данные в файл (возвращается fwrite). Если операция не удалась, файл открывается заново и возвращается 0.
  7. Выводит сообщение об успехе или ошибке. В функции main выводится сообщение yes to gray. или error convert!, в зависимости от того, вернула ли функция bmp_to_gray значение больше 0.

Оцени полезность:

5   голосов , оценка 3.4 из 5
Похожие ответы