Praca na bmp w C

0

Otóż mam wykonać coś takiego, w języku C.
"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.

0

Zacznij od przyswojenia sobie formatu pliku BMP: http://pl.wikipedia.org/wiki/Windows_Bitmap a reszta pójdzie, jak z płatka ;)

0

Możesz użyć formatu obrazka PPM bez uszczerbku dla zadania.
Oprogramowanie tego formatu jest banalne.

http://netpbm.sourceforge.net/doc/ppm.html

0

Mam kod w C do wczytywania plikow BMP do pamieci, konwetowania ich formatow i wyswietlania.
Nie mam kodu do odszumiania.

Jak chcesz wiecej to napisz email na [email protected] (pisane wspak)

0

Znalazłem gdzieś taki kod

#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?

0

Tak, da się wszystko ;p Najlepiej napisać samemu a nie szukać gotowców. Mniej czasu to zajmie.

0

Próbowałem samemu, ale nie mam pojęcia jak ma to wyglądać i chcę znaleźć jakiegoś gotowca do samego wczytywania i rozkminić jak to działa, a potem przerobić aby było to odszumianie itp, ale najpierw muszę wiedzieć jak wczytać dane... z dokumentacji itp nie dałem rady.

0

Refresh, może ktoś się zlituje...Błagam, idą święta, może jakiś drobny prezent :(

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0