A doubt in design of a class-BMP file extraction
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 21

Thread: A doubt in design of a class-BMP file extraction

  1. #1
    Join Date
    Feb 2006
    Posts
    205

    A doubt in design of a class-BMP file extraction

    Hi,

    I am writing a program to read a BMP image file.These are the things which i want the program to do:

    1. Read an image file
    2. extract the Height ,width,noof bits ,rasterinformation etc.
    3. if noofbits is 24 i want it to split rasterdata to rgb components.
    4. if noofbits is 8 i want it to read the colortable .
    5.write an image file .

    so this is the design i have in mind:
    1. IMAGEINFO:-

    This class will extract the filesize ,height ,width,noofbits
    2. RGBCLASS:
    This class will read the rasterdata in R,G,B format if the number of bits is 24.this will have related rgb conversion function.
    3. Grayclass:
    This will read data of colortable if the number of bits is 8, and also the rasterdata. when in case of rgb to gray conversion it will load the colortable information.

    I am thinking of making IMAGEINFO as the base class and RGBCLASS and Grayclass as derived class.
    Is this a good design. Need suggestion.
    -swetha

  2. #2
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,297

    Re: A doubt in design of a class-BMP file extraction

    Quote Originally Posted by swetha.bsharma View Post
    Hi,

    I am writing a program to read a BMP image file.These are the things which i want the program to do:

    1. Read an image file
    2. extract the Height ,width,noof bits ,rasterinformation etc.
    3. if noofbits is 24 i want it to split rasterdata to rgb components.
    4. if noofbits is 8 i want it to read the colortable .
    5.write an image file .

    so this is the design i have in mind:
    1. IMAGEINFO:-

    This class will extract the filesize ,height ,width,noofbits
    2. RGBCLASS:
    This class will read the rasterdata in R,G,B format if the number of bits is 24.this will have related rgb conversion function.
    3. Grayclass:
    This will read data of colortable if the number of bits is 8, and also the rasterdata. when in case of rgb to gray conversion it will load the colortable information.

    I am thinking of making IMAGEINFO as the base class and RGBCLASS and Grayclass as derived class.
    Is this a good design. Need suggestion.
    -swetha
    That is a horrible desgin because IMAGEINFO and RGBCLASS/Grayclass have nothing in common.

    the idea of base and derived is that a derived class is a special kind of base class. IE, you'd derive owl class from bird class.

    This is what I would do:
    1 class IMAGEINFO.
    1 abstract class BaseImage
    2 classes that derive from BaseImage: RGBCLASS and Grayclass

    Finally, create an Image class composition, composed of an IMAGEINFO, and a pointer to BaseImage, which could be either RGBCLASS or Grayclass object.

    But that is only one possible solution, and there is probably better

  3. #3
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,145

    Re: A doubt in design of a class-BMP file extraction

    I think you will find that design difficult to expand if you decide to support other data types - and as monarch_dodra has already said, it's not a good design in that it does not follow the is-a relationship that inherited objects should comply with.

    With regard to the load code, think of it this way; at the end of the day, load classes/functions are just a mechanism of getting data out of a file or a stream and into an image object. The important thing to correctly define is the image class.

    All image formats have an uncompressed data format definition (i.e. what the data will be once it has been decompressed/unpacked (if that is necessary), i.e. RGB, YUV, Bayer, Mono etc). The image format itself generally has a header (although not always - some RAW formats are an example of this). As well as the general header information, some image formats will also allow for meta data. The point that I am making is that your design should be able to cope with these aspects. Therefore I would suggest that you create at least the following before you even consider your load code:

    1. A data format class - to decribe the data format
    2. A header class that comprises a data format member and additional information such as height, and width...
    3. A metadata class
    4. An image class that comprises a header member, a metadata member and a data container (vector should be ok in the first instance).

    Images have things in common such as, width, height, bits per channel, bytes per value. After loading data, I'd recommend that you should always store it in an uncompressed, unpacked form (unless you have very good reason not too). This will reduce the number and complexity of data format definitions you'll need and will make life in general easier.

    Your data format class should contain information about the image data format - this data should be const and have things defined such as the number of channels, the number of data planes, and the horizontal and vertical jumps to the next element of that type (these 'jump' values will help you write iterators to traverse the image data).

    Channels represent the number of data elements required to describe the data:

    RGB = 3,
    YUV = 3,
    Bayer = 4,
    Mono = 1.

    Planes represent the number of data elements per pixel in the format:

    RGB = 3,
    YUV = 3,
    Bayer = 1,
    Mono = 1.

    Here's a small explanation. Although the number of channels and the number of planes are the same most of the time, they are not always. For example, the RGB format requires 3 data elements to describe the format (Red, Green and Blue), in addition, each pixel holds 3 data elements (1 Red, 1 Green, 1 Blue), therefore it is 3 channel 3 plane data. Bayer on the other hand requires 4 data elements to describe the format (Red, GreenOnRed, GreenOnBlue, Blue), but each pixel only contains a single data element (i.e. a pixel is either Red, GreenOnRed, GreenOnBlue or Blue), therefore the Bayer format is 4 channel single plane data.

    Your data format class should also have a definition of channels types, this could be an enum e.g.:

    Code:
    enum ChannelType
    {
      Greyscale,
      Red,
      Green,
      Blue,
      Alpha,
      GreenOnRed,
      GreenOnBlue,
      Y,
      U,
      V,
      Cb,
      Cr
    };
    In addition to the enum, each data format will also need to describe which of the above channel types are relevant to it. You could do this by having a vector of channel types as a member.

    Code:
    class DataFormatBase
    {
    public:
      enum ChannelType
      {
        Greyscale,
        Red,
        Green,
        Blue,
        Alpha,
        GreenOnRed,
        GreenOnBlue,
        Y,
        U,
        V,
        Cb,
        Cr
      };
    
      DataFormatBase(size_t planes, size_t hjump, size_t vjump)
        :channels_()
        ,planes_(planes)
        ,hjump_(hjump)
        ,vjump_(vjump)
      {}
    
      size_t channels() const { return channels_.size(); }
      size_t planes() const { return planes_;
    
      ChannelType channel(size_t pos) const
      {
        if(pos >= channels_.size()) throw std::runtime_error("Cannot access channel position - out of bounds!");
        return channels_[pos];
      }
    
      virtual const char* name() const = 0;
    
      virtual ~DataFormatBase()= 0 {};
    
    protected:
      std::vector<ChannelType> channels_;
      const size_t planes_;
      const size_t hjump_;
      const size_t vjump_;
    };
    This will enable you to write data format objects for the different data types easily:

    Code:
    class RGB : public DataFormatBase
    {
    public:
      RGB()
          :DataFormatBase(3,3,1)
      {
           channels_.push_back(Red);
           channels_.push_back(Green);
           channels_.push_back(Blue);
      }
      
         const char* name() const { return "RGB"; }
    };
    To calculate the required data size of an image, you will need to do the following:

    size = width*height*planes*bytesPerValue;

    Thus, as well as the data format class, you'll need a header class that contains data such as the image width, height, bits per value and bytes per value (although the bytes per value can be calculated from the bits per value, it's more efficient to calculate it once per change and store the result).

    Code:
    class Header
    {
    ...
    private:
      size_t width_;
      size_t height_;
      size_t bitsPerValue_;
      size_t bytesPerValue_;
      DataFormatBase* dataFormat; //dynamically allocate/deallocate, use RAII
    };
    Now that the image class is sorted out, I would suggest you write your load code to mirror the layout of the image. In otherwords, write a class to extract the header information and the data format. In addition you will need an object that describes the file format (BMP/JPEG/PNM etc). Once you have these Write a class that will depending on the data format passed and the file format, decompress/unpack/extract the file data from the file stream into the image class.

    I hope I've help you and not confused you. If you don't get it at first, try reading it again, and if it still doesn't make sense then ask.

  4. #4
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,297

    Re: A doubt in design of a class-BMP file extraction

    Sweet, that was some interesting reading.

    This is going to come of as nitpicking but:
    Code:
      ChannelType channel(size_t pos) const
      {
        if(pos >= channels_.size()) throw std::runtime_error("Cannot access channel position - out of bounds!");
        return channels_[pos];
      }
    Why bother with manual exception handling when you can just call channels_.at(pos)? For the custom exception message? Also, wouldn't out_of_range be better?

    But that is only details. I had done some thinking on this problem back in my days, and never got around to writing the code, because I just couldn't find a good solution. I might go back and play around now

  5. #5
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,145

    Re: A doubt in design of a class-BMP file extraction

    I guess I like to know where the problem is, simply using the channels_.at(pos) would sure enough tell me that there an out_of_range exception occured somewhere in the code, but it wouldn't tell me where the exception occurred. The custom message is just a way for me to know that. I guess it just gives more information to the user.

    I guess I could of written "out_of_range" instead of "out of bounds" though.

  6. #6
    Join Date
    Jul 2009
    Posts
    37

    Re: A doubt in design of a class-BMP file extraction

    Do you think that happens to a flat error message ?
    I positively think you do
    Sig-na-tju-(r)

  7. #7
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,145

    Re: A doubt in design of a class-BMP file extraction

    Please explain what you mean.

  8. #8
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,145

    Re: A doubt in design of a class-BMP file extraction

    Quote Originally Posted by ThachQuanVy View Post
    Do you think that happens to a flat error message ?
    I positively think you do
    Ok, I'm going to respond on what I think you mean.

    I think you misunderstood what I was saying when I said "simply using the channels_.at(pos) would sure enough tell me that there an out_of_range exception occured somewhere in the code, but it wouldn't tell me where the exception occurred". Therefore I will clarify.

    An out_of_range message in and of itself, will only tell me that an out_of_range exception somewhere in the code has been thrown, but it will not tell me where. To find out where it happened I would have to use a debugger. The custom message on the other hand tells me the information that I would have attempted to gain with a debugger. It tells me that an exception has been thrown because, specifically I have attempted to access the channels vector out of bounds. From the perspective of a user of the class, this is far more useful than a generic out_of_range exception, because it quickly tells to user exactly what and where the problem is without them having to use a debugger.

  9. #9
    Join Date
    Jul 2009
    Posts
    45

    Re: A doubt in design of a class-BMP file extraction

    Quote Originally Posted by PredicateNormative View Post
    Ok, I'm going to respond on what I think you mean.

    I think you misunderstood what I was saying when I said "simply using the channels_.at(pos) would sure enough tell me that there an out_of_range exception occured somewhere in the code, but it wouldn't tell me where the exception occurred". Therefore I will clarify.

    An out_of_range message in and of itself, will only tell me that an out_of_range exception somewhere in the code has been thrown, but it will not tell me where. To find out where it happened I would have to use a debugger. The custom message on the other hand tells me the information that I would have attempted to gain with a debugger. It tells me that an exception has been thrown because, specifically I have attempted to access the channels vector out of bounds. From the perspective of a user of the class, this is far more useful than a generic out_of_range exception, because it quickly tells to user exactly what and where the problem is without them having to use a debugger.
    To whatever situation one's explanation might fit in. The key point of posts is to be useful to a wide range of online users! Yours is one of such

  10. #10
    Join Date
    Feb 2006
    Posts
    205

    Re: A doubt in design of a class-BMP file extraction

    Hi,
    Thankyou guys.PredicateNormative I do understand what you are saying,but the code is frighitening . I feel a bit confused. i would like to know the following for the start.
    DataFormatBase(size_t planes, size_t hjump, size_t vjump)
    :channels_()
    ,planes_(planes)
    ,hjump_(hjump)
    ,vjump_(vjump)
    {}
    i understand that this is a constructor with arguments, i would like to know what is being done here
    :channels_() ,planes_(planes) ,hjump_(hjump) ,vjump_(vjump)


    ChannelType channel(size_t pos) const
    {
    if(pos >= channels_.size()) throw std::runtime_error("Cannot access channel position - out of bounds!");
    return channels_[pos];
    }
    what is happening here?
    std::vector<ChannelType> channels_;

    RGB()
    : DataFormatBase(3,3,1)
    {
    channels_.push_back(Red);
    channels_.push_back(Green);
    channels_.push_back(Blue);
    }


    What is happening here?

  11. #11
    Join Date
    Feb 2006
    Posts
    205

    Re: A doubt in design of a class-BMP file extraction

    Hi,

    I understand is vector is a Standard library class template which can be used instead of arrays.

    RGB()
    : DataFormatBase(3,3,1)
    {
    channels_.push_back(Red);
    channels_.push_back(Green);
    channels_.push_back(Blue);
    }
    I am confused because we are passing a enumerated data type,i dont understand the use of this function
    -swetha

  12. #12
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,297

    Re: A doubt in design of a class-BMP file extraction

    Quote Originally Posted by swetha.bsharma View Post
    i understand that this is a constructor with arguments, i would like to know what is being done here
    Code:
    :channels_()    ,planes_(planes)    ,hjump_(hjump)    ,vjump_(vjump)
    This is called an "initializer list" it means that your are constructing your variables with a given value, rather than assigning them one. It's hard to explain. Try to research the difference between "construction" and "assignement", and you will understand.

    Quote Originally Posted by swetha.bsharma View Post
    what is happening here?
    Code:
    ChannelType channel(size_t pos) const
      {
             if(pos >= channels_.size()) throw std::runtime_error("Cannot access channel position - out of bounds!");
             return channels_[pos];
      }
    What is happening here?
    What you are seeing is a simple input check, followed by an exception throw if the input is invalid. Take it this way, If you have an array of 5 elements, and the code asks you for element 7. What do you do? You throw an exception, that's what!

    Quote Originally Posted by swetha.bsharma View Post
    Hi,
    I understand is vector is a Standard library class template which can be used instead of arrays.

    I am confused because we are passing a enumerated data type,i dont understand the use of this function
    -swetha
    The code is incomplete. It is missing the actual image payload, but that is for you to figure out.

    as PredicateNormative said:
    Now that the image class is sorted out, I would suggest you write your load code to mirror the layout of the image. In otherwords, write a class to extract the header information and the data format. In addition you will need an object that describes the file format (BMP/JPEG/PNM etc). Once you have these Write a class that will depending on the data format passed and the file format, decompress/unpack/extract the file data from the file stream into the image class.
    What i would do is create a Class called "SingleLayer" or something, which would represent an array of integers, and put a vector of SingleLayer inside your DataFormatBase, for example.

    But I might be wrong, and I'd rather let Predicate answer that one

  13. #13
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,145

    Re: A doubt in design of a class-BMP file extraction

    Unfortunately I'm short of time, I'll try and respond a bit more to this tomorrow.

    Code:
    RGB()
      : DataFormatBase(3,3,1)
    {
      channels_.push_back(Red);
      channels_.push_back(Green);
      channels_.push_back(Blue);
    }
    The red line calls the base class (DataFormatBase) constructor with the specified values. Once that has been constructed it is safe to access its channels_ vector.

    The blue lines are adding elements of type ChannelType to the vector, so that the vector now has three elements.

    Sorry I can't say more today. I'll say more tomorrow, give you a few more lines of code and also correct a couple of syntax errors in the code I've posted so far.

  14. #14
    Join Date
    May 2007
    Location
    Scotland
    Posts
    1,145

    Re: A doubt in design of a class-BMP file extraction

    Did you want more information?

  15. #15
    Join Date
    Apr 2007
    Location
    Mars NASA Station
    Posts
    1,436

    Re: A doubt in design of a class-BMP file extraction

    I wonder how to write a Class Bitmap like C# does.
    Any good reference ?

    Thanks.
    Thanks for your help.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center