[C] Praca na bmp

Banan1311
Użytkownik
Użytkownik
Posty: 13
Rejestracja: 11 kwie 2008, o 19:50
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 1 raz

[C] Praca na bmp

Post autor: Banan1311 »

Otóż mam wykonać coś takiego:
"Napisać program do obróbki cyfrowej bitmap. Program powinien realizować
następujące funkcjonalności:
· Wczytywanie do pamięci bitmapy o dowolnym nieustalonym z góry
rozmiarze (powinna być ona przechowywana jako dynamiczna tablica
struktur)
· Odszumianie wczytanego obrazka (w skali szarości bądź kolorowego 24,
32, lub 16-bitowego) za pomocą filtrów: medianowego, uśredniającego,
minimalnego i maksymalnego o różnych rozmiarach okna (np.: 3x3,
10x10), które mogą być zdefiniowane przez użytkownika
· Konwersja obrazu kolorowego (32, 24, 16, 8-bitowego) na obraz w skali
szarości
· Generowanie negatywu wczytanej bitmapy
· Zapis przekonwertowanych obrazków do oddzielnych plików z
rozszerzeniem BMP"

W życiu napisałem nie więcej niż 10 programów, więc to wydaje mi się dosyć trudne i nie wiem z jakiej strony to ugryźć, nie wiem nawet jakich bibliotek użyć aby to było jak najprostsze. Z góry bardzo dziękuję za wszelkie wskazówki.
Boss
Użytkownik
Użytkownik
Posty: 50
Rejestracja: 19 wrz 2008, o 22:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Pomógł: 14 razy

[C] Praca na bmp

Post autor: Boss »



Żeby napisać taki program najpierw musisz cokolwiek rozumieć o formacie pliku BMP. BMP jest dość prostym formatem. W linku powyżej jest mnóstwo gotowych algorytmów do wczytania i zdekodowania pliku. A sam algorytm filtracji, to nawet miałem gdzieś na wykładzie na studiach. Ogólnie umiejętność algebry na macierzach. Jakbyś chciał jakiś wskazówek to chętnie poradzę na PW.
Xitami

[C] Praca na bmp

Post autor: Xitami »

TWÓrca zadania pisze:[...]powinna być ona przechowywana jako dynamiczna tablica struktur[...]
ja mam pomysł taki

Kod: Zaznacz cały

struct {
    int x, y;
    int r, g, b; } pixel;
Ma ktoś lepszy?
Banan1311
Użytkownik
Użytkownik
Posty: 13
Rejestracja: 11 kwie 2008, o 19:50
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 1 raz

[C] Praca na bmp

Post autor: Banan1311 »

Znalazłem gdzieś taki kod

Kod: Zaznacz cały

#include <painter/bmp.h>
#include <painter/memory.h>
#include <painter/error.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
 
/*==============================================================================
        Windows Bitmap File Format Implementation
 
        Actually compression is not supported.
 
        Supported color depths:
                1bpp - w/r
                4bpp - w/r
                8bpp - w/r
                16bpp - w/r
                24bpp - w/r
                32bpp - w/r
 
        During writing a pixmap with 2bpp or 15bpp it will be automatically written
        as 4bpp or 16bpp.        
 
==============================================================================*/
 
#define BMPID 0x4d42
#define BMPFILEHDR_SZ 14
#define BMPINFOHDR_SZ 40
 
/* File Header */
typedef struct BMPFILEHEADER {
        uint16_t type;
        uint32_t fileSize;
        uint16_t reserved0;
        uint16_t reserved1;
        uint32_t dataOffset;
} BMPFILEHEADER;
 
/* Info Header */
typedef struct BMPINFOHEADER {
        uint32_t hdrSize;
        uint32_t width;
        uint32_t height;
        uint16_t planes;
        uint16_t depth;
        uint32_t compression;
        uint32_t bmpDataSize;
        uint32_t hResolution;
        uint32_t vResolution;
        uint32_t nColors;
        uint32_t nImportantColors;
} BMPINFOHEADER;
 
/**
 * painterSaveBMP - Save bitmap to file.
 * @fileName - file name
 * @pixmap - pixmap
 * @palette - palette (used in indexed color mode - can be NULL)
 *
 * Return 0 if bitmap was saved properly, otherwise -1.  
 * Conversions:
 *                 2 -> 4 bit,
 *                15 -> 16 bit.
 *
 */
int painterSaveBMP(const char *fileName, P_Pixmap *pixmap, P_Palette *pal)
{
        FILE *fileHandle = NULL;
 
        BMPFILEHEADER fileHdr;
        BMPINFOHEADER infoHdr;
 
        P_Palette tmppal;
 
 
        int i = 0;
        int depth = 0;
 
        uint8_t *scanLine = NULL;
 
        size_t rowSize = 0;
        size_t scanLineSize = 0;
        size_t dataSize = 0;
        size_t palSize = 0;
 
        uint8_t bSrc, bDest;
        size_t j, x;
 
        assert(fileName);
        assert(pixmap);
 
        memset(&fileHdr, 0, sizeof (fileHdr));
        memset(&infoHdr, 0, sizeof (infoHdr));
 
        memset(tmppal, 0, sizeof (tmppal));
 
        /* saved color depth */        
        depth = pixmap->depth;
        if (depth == 2) depth = 4;
        else if (depth == 15) depth = 16;
 
        /* calculate size of a row */
        /* NOTE: rowSize might be not equal to pixmap->rowSize (ex: 2bpp) */
        rowSize = painterCalcRowSize(depth, pixmap->width); /* NOTE: custom */
 
        /* calculate size of a scan line and create buffer */
        scanLineSize = rowSize;
        if (scanLineSize % 4 != 0) 
                scanLineSize = ((scanLineSize>>2) + 1)<<2; /* 4 byte align */
 
        scanLine = (uint8_t *)painter_malloc(scanLineSize);
        if (!scanLine) {
                return -1;
        }
 
        /* calculate data size */
        dataSize = pixmap->height * scanLineSize;
 
        /* calculate size of the color map table */
        if (depth <= 8)
                palSize = (1<<depth)<<2;
 
        /* fill file header */
        fileHdr.type = BMPID;
        fileHdr.fileSize = BMPFILEHDR_SZ + BMPINFOHDR_SZ + palSize + dataSize;
        fileHdr.dataOffset = BMPFILEHDR_SZ + BMPINFOHDR_SZ + palSize;
 
        /* fill info header */
        infoHdr.hdrSize = BMPINFOHDR_SZ;
        infoHdr.width = pixmap->width;
        infoHdr.height = pixmap->height;
        infoHdr.planes = 1;
        infoHdr.depth = depth;
        infoHdr.compression = 0; /* uncompressed */
        infoHdr.bmpDataSize = dataSize;
        infoHdr.hResolution = 0;
        infoHdr.vResolution = 0;
        if (depth <= 8)
                infoHdr.nColors = infoHdr.nImportantColors = 1<<depth;
 
        /* open file and write header */
        fileHandle = fopen(fileName, "wb");
        if (!fileHandle) {
                painterThrowError(P_ERR_FILESYSTEM, "painterSaveBMP", "Cannot save bitmap to file - '%s'", fileName);
                return -1;
        }
 
        /* file header */
        fwrite(&fileHdr.type, 2, 1, fileHandle);
        fwrite(&fileHdr.fileSize, 4, 1, fileHandle);
        fwrite(&fileHdr.reserved0, 2, 1, fileHandle);
        fwrite(&fileHdr.reserved1, 2, 1, fileHandle);
        fwrite(&fileHdr.dataOffset, 4, 1, fileHandle);
 
        /* info header */
        fwrite(&infoHdr.hdrSize, 4, 1, fileHandle);
        fwrite(&infoHdr.width, 4, 1, fileHandle);
        fwrite(&infoHdr.height, 4, 1, fileHandle);
        fwrite(&infoHdr.planes, 2, 1, fileHandle);
        fwrite(&infoHdr.depth, 2, 1, fileHandle);
        fwrite(&infoHdr.compression, 4, 1, fileHandle);
        fwrite(&infoHdr.bmpDataSize, 4, 1, fileHandle);
        fwrite(&infoHdr.hResolution, 4, 1, fileHandle);
        fwrite(&infoHdr.vResolution, 4, 1, fileHandle);
        fwrite(&infoHdr.nColors, 4, 1, fileHandle);
        fwrite(&infoHdr.nImportantColors, 4, 1, fileHandle);
 
        /* write color map if needed */
        if (depth <= 8) {
                assert(pal);
 
                /* change RGB format to BGR */
                for (i = 0; i < (1<<depth); i++) {
                        tmppal[i].r = (*pal)[i].b;
                        tmppal[i].g = (*pal)[i].g;
                        tmppal[i].b = (*pal)[i].r;
                }
 
                fwrite(tmppal, 4, 1<<depth, fileHandle);
        }
 
        /* write bitmap data */
        i = pixmap->height;
        while (i--) {
 
                /* clear aligning */
                scanLine[scanLineSize-1] = 0;
                scanLine[scanLineSize-2] = 0;
                scanLine[scanLineSize-3] = 0;
                scanLine[scanLineSize-4] = 0;
 
                /* copydata, change pixels order or color depth */
                switch (pixmap->depth) {
 
                        case 1: { /* 12345678 -> 87654321 */
                                j = pixmap->rowSize;
                                while (j--) {
                                        bSrc = pixmap->rows[i][j];
                                        bDest = 0;
 
                                        x = 8;
                                        while (x--) {
                                                if (bSrc & (1<<x))
                                                        bDest |= (1<<(7-x));
                                        }
 
                                        scanLine[j] = bDest;
                                }
                        } break;
 
                        case 2: { /* 2bpp -> 4bpp */
                                x = 0;
                                for (j = 0; j < (unsigned)pixmap->width; j += 4) {
                                        bSrc = pixmap->rows[i][j>>2];
 
                                        scanLine[j>>1] = ((bSrc&0x3)<<4) | ((bSrc&0xc)>>2);
                                        x += 2;
                                        if (x+2 <= (unsigned)pixmap->width) {
                                                scanLine[(j>>1)+1] = (bSrc&0x30) | ((bSrc&0xc0)>>6);
                                        }
                                }
                        } break;
 
                        case 4: { /* 12 -> 21 */
                                j = pixmap->rowSize;
                                while (j--) {
                                        bSrc = pixmap->rows[i][j];
                                        bDest = 0;
 
                                        bDest = bSrc>>4;
                                        bSrc <<= 4;
                                        bSrc |= bDest;
 
                                        scanLine[j] = bSrc;
                                }
                        } break;
 
                        case 32: { /* RGBA -> ARGB */
                                j = pixmap->width;
                                while (j--) {
                                        scanLine[(j<<2)] = pixmap->rows[i][(j<<2)+1] ;
                                        scanLine[(j<<2)+1] = pixmap->rows[i][(j<<2)+2];
                                        scanLine[(j<<2)+2] = pixmap->rows[i][(j<<2)+3];
                                        scanLine[(j<<2)+3] = pixmap->rows[i][(j<<2)];
                                }
                        } break;
 
                        default: {
                                memcpy(scanLine, pixmap->rows[i], pixmap->rowSize);
                        } break;
 
                }
 
                /* write scan line */
                fwrite(scanLine, 1, scanLineSize, fileHandle);
        }
 
        return 0;
}
 
/**
 * painterLoadBMP - Create new pixmap and load bitmap data
 * @fileName - file name
 * @pal - pointer to palette
 *
 * Return pointer to new pixmap or NULL if error.
 */
P_Pixmap *painterLoadBMP(const char *fileName, P_Palette *pal)
{
        P_Pixmap *pixmap = NULL;
 
        FILE *fileHandle = NULL;
 
        BMPFILEHEADER fileHdr;
        BMPINFOHEADER infoHdr;
 
        P_Palette tmppal;
 
        uint8_t *scanLine = NULL;
        size_t scanLineSize = 0;
        size_t rowSize = 0;
 
        int i = 0;
        uint8_t bSrc, bDest;
        size_t j, x;
 
        assert(fileName);
 
        memset(&fileHdr, 0, sizeof (fileHdr));
        memset(&infoHdr, 0, sizeof (infoHdr));
 
        fileHandle = fopen(fileName, "rb+");
        if (!fileHandle) {
                painterThrowError(P_ERR_FILESYSTEM, "painterLoadBMP", "Cannot load bitmap from file - '%s'", fileName);
                return NULL;
        }
 
        /* read and verify file header */
        fread(&fileHdr.type, 2, 1, fileHandle);
        fread(&fileHdr.fileSize, 4, 1, fileHandle);
        fread(&fileHdr.reserved0, 2, 1, fileHandle);
        fread(&fileHdr.reserved1, 2, 1, fileHandle);
        fread(&fileHdr.dataOffset, 4, 1, fileHandle);
 
        if (fileHdr.type != BMPID) {
                fclose(fileHandle);
                painterThrowError(P_ERR_BMP_INVALIDHEADER, "painterLoadBMP", "Invalid file type - '%s'", fileName);
                return NULL;
        }
 
        /* read info header */
        fread(&infoHdr.hdrSize, 4, 1, fileHandle);
        fread(&infoHdr.width, 4, 1, fileHandle);
        fread(&infoHdr.height, 4, 1, fileHandle);
        fread(&infoHdr.planes, 2, 1, fileHandle);
        fread(&infoHdr.depth, 2, 1, fileHandle);
        fread(&infoHdr.compression, 4, 1, fileHandle);
        fread(&infoHdr.bmpDataSize, 4, 1, fileHandle);
        fread(&infoHdr.hResolution, 4, 1, fileHandle);
        fread(&infoHdr.vResolution, 4, 1, fileHandle);
        fread(&infoHdr.nColors, 4, 1, fileHandle);
        fread(&infoHdr.nImportantColors, 4, 1, fileHandle);
 
        /* debug */
        /*
        printf("type=%u\n", fileHdr.type);
        printf("fileSize=%u\n", fileHdr.fileSize);
        printf("dataOffset=%u\n", fileHdr.dataOffset);
        printf("hdrSize=%u\n", infoHdr.hdrSize);
        printf("width=%u\n", infoHdr.width);
        printf("height=%u\n", infoHdr.height);
        printf("planes=%u\n", infoHdr.planes);
        printf("depth=%u\n", infoHdr.depth);
        printf("compression=%u\n", infoHdr.compression);
        printf("bmpDataSize=%u\n", infoHdr.bmpDataSize);
        printf("hResolution=%u\n", infoHdr.hResolution);
        printf("vResolution=%u\n", infoHdr.vResolution);
        printf("nColors=%u\n", infoHdr.nColors);
        printf("nImportantColors=%u\n", infoHdr.nImportantColors);
        */
 
        /* check colour depth */
        if (infoHdr.depth != 1 && infoHdr.depth != 4 && 
                infoHdr.depth != 8 && infoHdr.depth != 16 &&
                infoHdr.depth != 24 && infoHdr.depth != 32) {
                fclose(fileHandle);
                painterThrowError(P_ERR_BMP_UNSUPPORTED, "painterLoadBMP", "Unsupported color depth - %ubpp", infoHdr.depth);
                return NULL;
        }
 
        /* compression support */
        if (infoHdr.compression != 0) {
                fclose(fileHandle);
                painterThrowError(P_ERR_BMP_UNSUPPORTED, "painterLoadBMP", "Compression is not supported");
                return NULL;
        }
 
        /* read color map */
        if (infoHdr.depth <= 8) {
                assert(pal);
 
                /*fseek(fileHandle, 14 + infoHdr.hdrSize, SEEK_SET);*/
                fread(tmppal, 4, 1<<infoHdr.depth, fileHandle);
 
                /* move data and change BGR format to RGB */
                for (i = 0; i < (1<<infoHdr.depth); i++) {
                        (*pal)[i].r = tmppal[i].b;
                        (*pal)[i].g = tmppal[i].g;
                        (*pal)[i].b = tmppal[i].r;
                        (*pal)[i].a = 0;
                }
        }
 
        /* calculate size of each row in bytes */
        rowSize = painterCalcRowSize(infoHdr.depth, infoHdr.width);
 
        /* create scan line buffer */
        scanLineSize = rowSize;
        if (scanLineSize % 4 != 0) 
                scanLineSize = ((scanLineSize>>2) + 1)<<2; /* 4 byte align */
        scanLine = (uint8_t *)painter_malloc(scanLineSize);
        if (!scanLine) {
                fclose(fileHandle);
                return NULL;
        }
 
        /* debug */
        /*
        printf("rowSize=%u\n", rowSize);
        printf("scanLineSize=%u\n", scanLineSize);        
        */
 
        /* create new pixmap */
        pixmap = painterCreatePixmap(infoHdr.width, infoHdr.height, infoHdr.depth);
        if (!pixmap) {
                fclose(fileHandle);
                return NULL;        
        }
 
        /* read bitmap data */
        /*
        fseek(fileHandle, 14 + infoHdr.hdrSize, SEEK_SET);
        if (infoHdr.depth <= 8)
                fseek(fileHandle, (1<<infoHdr.depth)<<2, SEEK_CUR);
        */
 
        i = infoHdr.height;
        while (i--) {
                fread(scanLine, 1, scanLineSize, fileHandle);
 
                /* copy data, change pixels order */
                switch (infoHdr.depth) {
 
                        case 1: { /* 87654321 -> 12345678 */
                                j = rowSize;
                                while (j--) {
                                        bSrc = scanLine[j];
                                        bDest = 0;
 
                                        x = 8;
                                        while (x--) {
                                                if (bSrc & (1<<x))
                                                        bDest |= (1<<(7-x));
                                        }
 
                                        pixmap->rows[i][j] = bDest;
                                }
                        } break;
 
                        case 4: { /* 21 -> 12 */
                                j = rowSize;
                                while (j--) {
                                        bSrc = scanLine[j];
                                        bDest = 0;
 
                                        bDest = bSrc>>4;
                                        bSrc <<= 4;
                                        bSrc |= bDest;
 
                                        pixmap->rows[i][j] = bSrc;
                                }
                        } break;                                
 
                        case 32: { /* RGBA -> ARGB */
                                j = pixmap->width;
                                while (j--) {
                                        pixmap->rows[i][(j<<2)] = scanLine[(j<<2)+1];
                                        pixmap->rows[i][(j<<2)+1] = scanLine[(j<<2)+2];
                                        pixmap->rows[i][(j<<2)+2] = scanLine[(j<<2)+3];
                                        pixmap->rows[i][(j<<2)+3] = scanLine[(j<<2)];
                                }
                        } break;
 
                        default: {
                                memcpy(pixmap->rows[i], scanLine, rowSize);
                        } break;
 
                }
 
        }
 
        fclose(fileHandle);
 
        return pixmap;
}



ale tu są niestandardowe biblioteki i trochę tego dużo, czy potrzebuję wszystkich tych rzeczy? I czy da się to przekształcić aby działało bez tych innych bibliotek?
Boss
Użytkownik
Użytkownik
Posty: 50
Rejestracja: 19 wrz 2008, o 22:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Pomógł: 14 razy

[C] Praca na bmp

Post autor: Boss »

Nie szukaj gotowych rozwiązań żeby się z nich nauczyć. Masz konkretną robotę do wykonania. Najpierw porządnie przeczytaj dokumentację formatu, algorytmy manipulowania na plikach BMP, a dopiero później zobacz jak inni do tego się zabrali. Wzorowanie się na cudzym kodzie prowadzi w ślepe uliczki. Szczególnie w takim języku jak C.
Banan1311
Użytkownik
Użytkownik
Posty: 13
Rejestracja: 11 kwie 2008, o 19:50
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 1 raz

[C] Praca na bmp

Post autor: Banan1311 »

Ja chcę tylko zobaczyć jak się wczytuje bmp, resztę chcę zrobić sam, ale nie mam pojęcia jak działa to wczytywanie, dokumentacje bmp czytałem.
Boss
Użytkownik
Użytkownik
Posty: 50
Rejestracja: 19 wrz 2008, o 22:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Pomógł: 14 razy

[C] Praca na bmp

Post autor: Boss »

Przecież to najzwyklejszy odczyt binarny.
Banan1311
Użytkownik
Użytkownik
Posty: 13
Rejestracja: 11 kwie 2008, o 19:50
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 1 raz

[C] Praca na bmp

Post autor: Banan1311 »

Boss pisze:Przecież to najzwyklejszy odczyt binarny.
no właśnie a ja nie wiem jak to wygląda i chętnie bym się dowiedział, googlowałem kilka dni i nic.
abc666

[C] Praca na bmp

Post autor: abc666 »

Patrzysz w dokumentację. Mamy dwa bajty z pewnymi informacjami. Czytasz pierwsze dwa bajty przez fread() i zapisujesz sobie, robisz coś z nimi. Np. te dwa pierwsze bajty identyfikują rodzaj bitmapy. Potem mamy 4 bajty na których zapisany jest rozmiar. Wczytujesz 4 bajty i zapisujesz sobie jako rozmiar. Potem 4 bajty pomijasz. Kolejne cztery wczytujesz i zapisujesz sobie jako offset itd. itd.
Banan1311
Użytkownik
Użytkownik
Posty: 13
Rejestracja: 11 kwie 2008, o 19:50
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 1 raz

[C] Praca na bmp

Post autor: Banan1311 »

Refresh, może ktoś się zlituje...Błagam, idą święta, może jakiś drobny prezent
Avarroku
Użytkownik
Użytkownik
Posty: 1
Rejestracja: 1 sty 2012, o 13:47
Płeć: Mężczyzna
Lokalizacja: Warszawa

[C] Praca na bmp

Post autor: Avarroku »

Też potrzebuję kodu na wczytywanie bmp w c z użyciem tylko standardowych blbliotek. NIe potrafię znaleźć, a opisy z wikipedii itp nic nie dają. Z góry dizęki
ODPOWIEDZ