Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 14
  1. #1

    [C++] Bitmap

    Ciao a tutti.

    Sto provando a creare una classe Bitmap che mi permetta di caricare o di creare file .bmp.

    Mi sono letto tutta la pagina di Wikipedia e ho una vaga idea di come procedere.

    Però ho un problema. In C++ come faccio a specificare la dimensione di una variabile come numero di bytes?
    In pratica ho bisogno di creare vari campi di lunghezza prestabilita.

    Ho proceduto in questo modo:
    codice:
    #ifndef DATATYPE_H
    #define DATATYPE_H
    
    typedef unsigned char uint8_t;
    typedef unsigned short uint16_t;
    typedef int int32_t;
    typedef unsigned int uint32_t;
    
    typedef struct BITMAPFILETYPE
    {
    	unsigned char magic[2]; // Magic number (identify BMP file)
    } bfType;
    
    typedef struct BITMAPFILEHEADER
    {
    	uint32_t bfSize; // Size of BMP file in byte
    	uint16_t bfReserved1;
    	uint16_t bfReserved2;
    	uint32_t bmpOffset; // Offset starting address
    } BitmapFileHeader;
    
    typedef struct BITMAPINFOHEADER
    {
    	uint32_t biSize; // Size of this header
    	int32_t biWidth; // Bitmap whidt in pixels
    	int32_t biHeight; // Bitmap whidt in pixels
    	uint16_t biPlanes; // Number of color planes being used
    	uint16_t biBitCount; // Number of bits per pixel
    	uint32_t biCompression; // Compression method being used
    	uint32_t biSizeImage; // Image size
    	int32_t biXPixelPerMeter; // Horizontal resolution of the image
    	int32_t biYPixelPerMeter; // Vertical resolutions
    	uint32_t biClrUsed; // Number of colors in the color palette
    	uint32_t biClrImportant; // Number of important color used
    } BitmapInfoHeader;
    
    typedef struct PIXEL
    {
    	uint8_t B; // Blue color
    	uint8_t G; // Green color
    	uint8_t R; // Red color
    	uint8_t reserved; // Reserved
    } Pixel;
    
    #endif
    Però la lunghezza degli int o dei char dipende dalla macchina, quindi le variabili che ho creato non hanno una lunghezza fissa, ma sono dipendenti dalla macchina (32, 64, ... bit), giusto? Come faccio a renderle lunghezze fisse?!
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  2. #2
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Originariamente inviato da MItaly
    http://en.wikipedia.org/wiki/Stdint.h
    Avevo già visto questa libreria...
    Ma non trovo la corrispondente in C++!
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  4. #4
    Il problema è che <cstdint> esisterà nel prossimo standard C++ (il cosiddetto C++0x), anche se ormai tutti i compilatori recenti lo forniscono; VC++ se non erro lo supporta dalla versione 2010, ma anche per le precedenti trovi in rete degli stdint.h già pronti.

    In ogni caso, praticamente ogni compilatore fornisce una qualche sintassi per usare i tipi a dimensioni fissate, guarda nella documentazione del tuo compilatore.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Originariamente inviato da MItaly
    Il problema è che <cstdint> esisterà nel prossimo standard C++ (il cosiddetto C++0x), anche se ormai tutti i compilatori recenti lo forniscono; VC++ se non erro lo supporta dalla versione 2010, ma anche per le precedenti trovi in rete degli stdint.h già pronti.

    In ogni caso, praticamente ogni compilatore fornisce una qualche sintassi per usare i tipi a dimensioni fissate, guarda nella documentazione del tuo compilatore.
    Io utilizzo GCC sotto Xcode. Ho appena installato l'ultima versione di Xcode, ma ho notato che GCC non viene aggiornato (è fermo alla versione 4.2.1).
    Comunque guarderò nella documentazione del mio compilatore. Grazie per le dritte!
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  6. #6
    lascia tutto cosi e racchiudi le struct fra #pragma pack(1) e #pragma pack()
    pochi giorni fa ho fatto una classe analoga che mi permette di lavorare con i file bmp, e ha funzionato semplicemente utilizzando uint 16/32 e #pragma pack

    in ogni caso non so se lo sai ma in windows.h sono già fornite tutte le structs per i bitmap già pronte (una volta capita la struttura mi sono riscritto tutta la classe usando quelle giusto per essere sicuro):
    http://msdn.microsoft.com/en-us/library/dd183374(v=vs.85).aspx
    http://msdn.microsoft.com/en-us/library/aa930622.aspx
    http://msdn.microsoft.com/en-us/library/dd162939(v=vs.85).aspx

    non c'è bisogno di ri-diachiararle, basta includere Windows.h
    Il piccolo programma di base che avevo fatto prima di scrivere la classe usando le struct di Windows.h: http://pastebin.com/PfMCbER3
    gira sia su VC++ che su GCC senza problemi, l'unica cosa è che devi sostituire il fopen_s con il fopen normale se compili su gcc

  7. #7
    Comunque, per quanto riguarda i tipi a dimensione fissata, nulla che non si possa risolvere con un po' di abuso di metaprogrammazione template e qualche macro:
    codice:
    #ifndef EXACTWIDTH_HPP_INCLUDED
    #define EXACTWIDTH_HPP_INCLUDED
    
    #include <limits>
    
    namespace ExactWidthInt
    {
    
    namespace Implementation // Implementazione
    {
    
    // Tipo di base usato per registrare i tipi di interi disponibili
    template<int Size, bool Signed, unsigned int LineNumber>
    struct Imp_ExactBitWidthInt
    {
        static const bool Defined=false;
    };
    
    #define EXACTWIDTH_BEGINTYPETABLE \
    const unsigned int Imp_TableFirstLine=__LINE__;
    
    #define EXACTWIDTH_ADDTYPE(type) \
    template<> \
    struct Imp_ExactBitWidthInt< \
        sizeof(type)*std::numeric_limits<unsigned char>::digits,\
            std::numeric_limits<type>::is_signed, \
            __LINE__ > \
    { \
        typedef type T; \
        static const bool Defined=true; \
    };
    
    #define EXACTWIDTH_ENDTYPETABLE \
    const unsigned int Imp_TableLastLine=__LINE__;
    
    // Tabella dei tipi - si inizia con questa macro...
    EXACTWIDTH_BEGINTYPETABLE
    // Qui in mezzo si mettono tutti i tipi che si vogliono coinvolgere nella ricerca
    // Di base metto solo i tipi standard
    EXACTWIDTH_ADDTYPE(signed char)
    EXACTWIDTH_ADDTYPE(unsigned char)
    EXACTWIDTH_ADDTYPE(signed short int)
    EXACTWIDTH_ADDTYPE(unsigned short int)
    EXACTWIDTH_ADDTYPE(signed int)
    EXACTWIDTH_ADDTYPE(unsigned int)
    EXACTWIDTH_ADDTYPE(signed long)
    EXACTWIDTH_ADDTYPE(unsigned long)
    // ... e si finisce con questa
    EXACTWIDTH_ENDTYPETABLE
    
    #undef EXACTWIDTH_ADDTYPE
    #undef EXACTWIDTH_BEGINTYPETABLE
    #undef EXACTWIDTH_ENDTYPETABLE
    
    // Ricerca ricorsiva del tipo che soddisfa le richieste
    
    // Caso generale (mai richiamato, da solo la signature del template e l'argomento di default)
    template<int Size, bool Signed, unsigned int LineNumber=Imp_TableFirstLine, bool Found=Imp_ExactBitWidthInt<Size, Signed, LineNumber>::Defined>
    struct Imp_FindExactBitWidthInt;
    
    // Tipo trovato: fornisce effettivamente il tipo richiesto come typedef
    template<int Size, bool Signed, unsigned int LineNumber>
    struct Imp_FindExactBitWidthInt<Size, Signed, LineNumber, true>
    {
        typedef typename Imp_ExactBitWidthInt<Size, Signed, LineNumber>::T T;
    };
    
    // Tipo non trovato: continua la ricerca, passando alla linea successiva
    template<int Size, bool Signed, unsigned int LineNumber>
    struct Imp_FindExactBitWidthInt<Size, Signed, LineNumber, false>
        : Imp_FindExactBitWidthInt<Size, Signed, LineNumber+1>
    {
    };
    
    // Caso base: tipo non trovato, tabella dei tipi finita; non definisce ::T, così
    // si ottiene un errore di compilazione
    template<int Size, bool Signed>
    struct Imp_FindExactBitWidthInt<Size, Signed, Imp_TableLastLine, false>
    {
    };
    
    // Tutto il giochino della ricerca anche per linea si rende necessario perché
    // più tipi possono avere le medesime dimensioni; se così non fosse, basterebbe
    // una tabella dei tipi senza numeri di riga e non sarebbe necessaria la ricerca
    // ricorsiva
    
    } // namespace Implementation
        
    // Le due classi da usare per davvero:
    
    // Fornisce come typedef ::T il tipo che corrisponde alla dimensione richiesta (in bit)
    // con segno o meno a seconda del secondo parametro
    template<int Size, bool Signed>
    struct ExactBitWidthInt
    {
        typedef typename Implementation::Imp_FindExactBitWidthInt<Size, Signed>::T  T;
    };
    
    // Fornisce come typedef ::T il tipo che corrisponde alla dimensione richiesta (in byte)
    // con segno o meno a seconda del secondo parametro
    template<int Size, bool Signed>
    struct ExactByteWidthInt
    {
        typedef typename ExactBitWidthInt<Size*std::numeric_limits<unsigned char>::digits, Signed>::T T;
    };
    
    }
    
    /*
        Esempio:
        
        typedef ExactWidthInt::ExactBitWidthInt<32, false>::T   myuint32;
        typedef ExactWidthInt::ExactByteWidthInt<2, true>::T    my2bytesint;
    
    */
    #endif
    È venuto un pelo più complicato del previsto (per via del fatto che più tipi possono avere le stesse dimensioni), ma dovrebbe comunque funzionare bene. La cosa divertente è che se il tipo che corrisponda alle richieste (in termini di bit e di signed/unsigned) non è presente tra quelli della tabella si ha un errore di compilazione.

    Per farti un esempio, per avere un intero a 32 bit senza segno basta fare
    codice:
    ExactWidthInt::ExactBitWidthInt<32, false>::T var;
    Naturalmente come notazione è un po' pesante, per cui potresti voler fare una roba del tipo:
    codice:
    typedef ExactWidthInt::ExactBitWidthInt<32, false>::T    UInt32;
    typedef ExactWidthInt::ExactBitWidthInt<16, false>::T    UInt16;
    // ... eccetera
    anche per evitare di rischiare l'istanziazione di quella caterva di template ogni volta che vuoi usare una variabile a dimensione fissata.
    Amaro C++, il gusto pieno dell'undefined behavior.

  8. #8
    ... o comunque c'è sempre la boost integer library.
    http://www.boost.org/doc/libs/releas...ger/index.html
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    Originariamente inviato da KoutaOyamada
    lascia tutto cosi e racchiudi le struct fra #pragma pack(1) e #pragma pack()
    pochi giorni fa ho fatto una classe analoga che mi permette di lavorare con i file bmp, e ha funzionato semplicemente utilizzando uint 16/32 e #pragma pack

    in ogni caso non so se lo sai ma in windows.h sono già fornite tutte le structs per i bitmap già pronte (una volta capita la struttura mi sono riscritto tutta la classe usando quelle giusto per essere sicuro):
    http://msdn.microsoft.com/en-us/library/dd183374(v=vs.85).aspx
    http://msdn.microsoft.com/en-us/library/aa930622.aspx
    http://msdn.microsoft.com/en-us/library/dd162939(v=vs.85).aspx

    non c'è bisogno di ri-diachiararle, basta includere Windows.h
    Il piccolo programma di base che avevo fatto prima di scrivere la classe usando le struct di Windows.h: http://pastebin.com/PfMCbER3
    gira sia su VC++ che su GCC senza problemi, l'unica cosa è che devi sostituire il fopen_s con il fopen normale se compili su gcc
    Lavoro con Mac OS X e occasionalmente anche con Linux, quindi windows.h è esclusa a priori. Poi comunque volevo implementare io la classe da zero! =)
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  10. #10
    Originariamente inviato da MItaly
    Comunque, per quanto riguarda i tipi a dimensione fissata, nulla che non si possa risolvere con un po' di abuso di metaprogrammazione template e qualche macro:
    codice:
    #ifndef EXACTWIDTH_HPP_INCLUDED
    #define EXACTWIDTH_HPP_INCLUDED
    
    #include <limits>
    
    namespace ExactWidthInt
    {
    
    namespace Implementation // Implementazione
    {
    
    // Tipo di base usato per registrare i tipi di interi disponibili
    template<int Size, bool Signed, unsigned int LineNumber>
    struct Imp_ExactBitWidthInt
    {
        static const bool Defined=false;
    };
    
    #define EXACTWIDTH_BEGINTYPETABLE \
    const unsigned int Imp_TableFirstLine=__LINE__;
    
    #define EXACTWIDTH_ADDTYPE(type) \
    template<> \
    struct Imp_ExactBitWidthInt< \
        sizeof(type)*std::numeric_limits<unsigned char>::digits,\
            std::numeric_limits<type>::is_signed, \
            __LINE__ > \
    { \
        typedef type T; \
        static const bool Defined=true; \
    };
    
    #define EXACTWIDTH_ENDTYPETABLE \
    const unsigned int Imp_TableLastLine=__LINE__;
    
    // Tabella dei tipi - si inizia con questa macro...
    EXACTWIDTH_BEGINTYPETABLE
    // Qui in mezzo si mettono tutti i tipi che si vogliono coinvolgere nella ricerca
    // Di base metto solo i tipi standard
    EXACTWIDTH_ADDTYPE(signed char)
    EXACTWIDTH_ADDTYPE(unsigned char)
    EXACTWIDTH_ADDTYPE(signed short int)
    EXACTWIDTH_ADDTYPE(unsigned short int)
    EXACTWIDTH_ADDTYPE(signed int)
    EXACTWIDTH_ADDTYPE(unsigned int)
    EXACTWIDTH_ADDTYPE(signed long)
    EXACTWIDTH_ADDTYPE(unsigned long)
    // ... e si finisce con questa
    EXACTWIDTH_ENDTYPETABLE
    
    #undef EXACTWIDTH_ADDTYPE
    #undef EXACTWIDTH_BEGINTYPETABLE
    #undef EXACTWIDTH_ENDTYPETABLE
    
    // Ricerca ricorsiva del tipo che soddisfa le richieste
    
    // Caso generale (mai richiamato, da solo la signature del template e l'argomento di default)
    template<int Size, bool Signed, unsigned int LineNumber=Imp_TableFirstLine, bool Found=Imp_ExactBitWidthInt<Size, Signed, LineNumber>::Defined>
    struct Imp_FindExactBitWidthInt;
    
    // Tipo trovato: fornisce effettivamente il tipo richiesto come typedef
    template<int Size, bool Signed, unsigned int LineNumber>
    struct Imp_FindExactBitWidthInt<Size, Signed, LineNumber, true>
    {
        typedef typename Imp_ExactBitWidthInt<Size, Signed, LineNumber>::T T;
    };
    
    // Tipo non trovato: continua la ricerca, passando alla linea successiva
    template<int Size, bool Signed, unsigned int LineNumber>
    struct Imp_FindExactBitWidthInt<Size, Signed, LineNumber, false>
        : Imp_FindExactBitWidthInt<Size, Signed, LineNumber+1>
    {
    };
    
    // Caso base: tipo non trovato, tabella dei tipi finita; non definisce ::T, così
    // si ottiene un errore di compilazione
    template<int Size, bool Signed>
    struct Imp_FindExactBitWidthInt<Size, Signed, Imp_TableLastLine, false>
    {
    };
    
    // Tutto il giochino della ricerca anche per linea si rende necessario perché
    // più tipi possono avere le medesime dimensioni; se così non fosse, basterebbe
    // una tabella dei tipi senza numeri di riga e non sarebbe necessaria la ricerca
    // ricorsiva
    
    } // namespace Implementation
        
    // Le due classi da usare per davvero:
    
    // Fornisce come typedef ::T il tipo che corrisponde alla dimensione richiesta (in bit)
    // con segno o meno a seconda del secondo parametro
    template<int Size, bool Signed>
    struct ExactBitWidthInt
    {
        typedef typename Implementation::Imp_FindExactBitWidthInt<Size, Signed>::T  T;
    };
    
    // Fornisce come typedef ::T il tipo che corrisponde alla dimensione richiesta (in byte)
    // con segno o meno a seconda del secondo parametro
    template<int Size, bool Signed>
    struct ExactByteWidthInt
    {
        typedef typename ExactBitWidthInt<Size*std::numeric_limits<unsigned char>::digits, Signed>::T T;
    };
    
    }
    
    /*
        Esempio:
        
        typedef ExactWidthInt::ExactBitWidthInt<32, false>::T   myuint32;
        typedef ExactWidthInt::ExactByteWidthInt<2, true>::T    my2bytesint;
    
    */
    #endif
    È venuto un pelo più complicato del previsto (per via del fatto che più tipi possono avere le stesse dimensioni), ma dovrebbe comunque funzionare bene. La cosa divertente è che se il tipo che corrisponda alle richieste (in termini di bit e di signed/unsigned) non è presente tra quelli della tabella si ha un errore di compilazione.

    Per farti un esempio, per avere un intero a 32 bit senza segno basta fare
    codice:
    ExactWidthInt::ExactBitWidthInt<32, false>::T var;
    Naturalmente come notazione è un po' pesante, per cui potresti voler fare una roba del tipo:
    codice:
    typedef ExactWidthInt::ExactBitWidthInt<32, false>::T    UInt32;
    typedef ExactWidthInt::ExactBitWidthInt<16, false>::T    UInt16;
    // ... eccetera
    anche per evitare di rischiare l'istanziazione di quella caterva di template ogni volta che vuoi usare una variabile a dimensione fissata.
    Non ho capito una mazza del tuo codice!xD. Mi sa che è a un livello troppo avanzato per me!xD.
    Proverò ad appoggiarmi alla libreria che mi hai indicato!=).
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.