• Aucun résultat trouvé

Dividing the

Dans le document File Formats (Page 27-32)

Colorspace in Half

GLOBAL FREQUENCIES [0..255][0..255][0..255]

Function DivideBlueInHalf Begin

COUNT = 0

For BLUECUT = 0 To 255 Do Begin

For II = 0 To 255 Do Begin

For JJ = 0 To 255 Do Begin

COUNT = COUNT + FREQUENCIES [II][JJ][BLUECUT]

End End

If COUNT > IMAGEHEICHT * IMACEWIDTH / 2 Then Return BLUECUT

End Return 255 End

be 64 megabytes. Even in this era of cheap memory, this is too large for a prac-tical implementation. In fact, the size of the FREQUENCIES array is larger than the pixel data for most images, so in practice we have to reduce the precision of each color value, use dynamic data structures, or use a combination of both. A simple method to reduce the array size is to drop some of the least significant bits from each component value. Using 6 instead of 8 bits reduces the size of the FREQUENCIES array to just 1 megabyte (4 × 26 × 26 × 26).

Figure 1.11

Example of the RGB Colorspace Being Divided Using the Process in

Algorithm 1.2

18 Introduction

Figure 1.12 RGB Colorspace in Figure 1.11, Now Divided along the Green Axis As Well

Figure 1.13 RGB Colorspace in Figure 1.12, Now Divided along the Red Axis As Well

A Common Image Format

A typical application for viewing image files will be able to read and store images using several file formats, and convert files from one format to another. Rather than having a function for viewing each type of file and a separate function for each possible format conversion, it is useful to have a common uncompressed image format that can be used for all types of files supported by the application.

With a common uncompressed format you need only write one display func-tion for the common format. If each image file format has a funcfunc-tion for reading into the common format and a function for writing from the common format, you have everything you need to display, save, and convert among all file formats.

A Common Image Format 19 In addition to supporting all of the anticipated image formats, a common image format ideally is easy to display and portable across various hardware plat-forms. Unfortunately, ease of display and portability are somewhat exclusive. You do not want a common image format and a separate display format. The format in our examples is a compromise, designed to be as easy as possible to use in the Windows environment while at the same time concealing Windows-specific behavior. It is capable of storing images using 1, 4, 8, and 24 bits per pixel. PNG and JPEG are the only formats that store data using other formats. The PNG decoder will convert the data to one of the formats above; the JPEG decoder will only read files with 8-bit sample data.

Datatype Definitions

The source code examples in this book use typedefs for integers that are expected to be a specific size. Table 1.4 lists the integer types used. They are defined in the file datatype.h, which also defines a function for performing endian conver-sions of integers. The existing definitions are suitable for most 32-bit little-endian systems, so if you are porting the code to another type of system, this is the first file you need to modify.

Common Image Class

B i t m a p I m a g e is the name of the common image format class. It is defined in the file bitimage.h. The general process followed by all of the encoders and decoders in this book for reading and writing images is

Table 1.4

Types Defined in datatype.h

BitmapImage image ; XYZDecoder decoder ; XYZEncoder encoder ;

ifstream input ("INPUT.XYZ", ios::binary) ; decoder.ReadImage (input, image) ;

ofstream output ("OUTPUT.XYZ", ios::binary) ; encoder.WriteImage (output, image) ;

where XYZDecoder and XYZEncoder are the decoder and encoder classes for the image type.

Type BYTE1 UBYTE1 BYTE2 UBYTE2 BYTE4 UBYTE4

Use

Signed 8-bit integer Unsigned 8-bit integer Signed 16-bit integer Unsigned 16-bit integer Signed 32-bit integer Unsigned 32-bit integer

The implementation of this class is tailored for Microsoft Windows.

However, the interface is designed to conceal system-specific behavior. The BitmapImage class has two main storage areas: the color map and the pixel data.

An application can store an image in a BitmapImage object by using one of the image decoders in this book (or one you write yourself) or by using the SetSize, ColorMap, and [] operators to write store raw image data.

SetSize

The SetSize function allocates the dynamic memory used to store image data within a BitmapImage object. An application must call this function before attempting to store image data into the object.

ColorMap

The ColorMap functions are used to access the image's color palette. For images with a bit depth of 8 or fewer the application must fill in the color map. If the image has a bit depth of 24 this function should not be used.

[] (Subscript) Operator

The subscript operator is used to access individual bytes in the image pixel data.

The format of this data depends upon the bit depth of the image. For images that use 8 bits per pixel each data byte is an index into the color map (accessed through the ColorMap functions). If the bit depth is fewer than 8, multiple color indices are packed into the data bytes. The higher-order bits contain the leftmost pixel values. For 24-bit images each pixel is represented by 3 bytes. The usual ordering for color bytes in a 24-bit image is RGB, but Windows expects the val-ues in BGR order. The BitmapImage class defines the valval-ues RedOffset, GreenOffset, and BlueOffset used by the programming examples to specify the ordering of these bytes. If your system does not use BGR ordering, you can change the values of these offsets.

Another Windows'ism that the subscript operator conceals is Windows images will be stored starting with the bottommost row. In order to make dis-playing an image as easy as possible on Windows, this implementation of the BitmapImage class stores the rows in bottom-to-top order, as Windows expects them to be. However, the subscript operator reverses the row order so that [0]

returns the topmost row of the image. Windows also expects the length of each image row to be a multiple of 4 bytes. The subscript operator automatically takes this padding into account so that [N][0] always returns the first pixel byte for the Nth row. By making the implementation of BitmapImage independent of the interface it is possible to change the implementation to support different systems without affecting the image encoders and decoders.

There are two implementations of the subscript operator. If the CHECK_RANGE preprocessor symbol is defined, the subscript operator performs range checking on all values. If CHECK_RANGE is not defined, no range checking is done. The

Introduction 20

Conclusion

latter implementation is significantly faster, but the former is better for use while debugging.

CetRGB

The GetRGB function returns the RGB color value for a given pixel in the image.

An image encoder can use this function to get pixel values without having to deal with different sample precision values.

EightBitQuantization

The EightBitQuantization function converts a 24-bits-per-pixel image to an 8-bits per pixel image using the mean cut processes. About half of the source code for the BitmapImage function is devoted to color quantization. This imple-mentation makes two passes through the image. On the first pass the FindColorUsage function creates a ColorUsage structure for each color used in the image. These structures are inserted into three linked lists sorted by the Red, Green, and Blue component values. Next the recursive SplitAreaInHalf function repeatedly divides the RGB colorspace into two areas that contain half of the weighted color values of the original.

At this point we have defined the 256 color areas for the image. The CreateColor function defines a single color that is the average for a box. This gives the "best" colors to use for the image. Finally, QuantizeSourceImage makes a second pass over the image data to replace the colors in the source image with a color from among the 256 colors that were defined in the preceding passes.

In this chapter we covered the basics of bitmap image formats. We explained the difference between bitmap and vector image formats and the way images are dis-played on output devices. We also covered the representation of color and described some of the color models used by graphics file formats. The chapter presented a brief introduction to color quantization and the compression tech-niques used by the file formats covered in this book.

Foley et al. (1996) describes the operation of computer displays in greater detail than we have here. It also contains excellent descriptions of colorspaces.

Brown and Shepherd (1995) and Murray and van Ryper (1994) contain intro-ductory descriptions of a large number of graphics file formats.

In this book we will cover only the specific compression techniques used by file formats under discussion. Nelson (1992) is the best introduction to com-pression techniques available and an excellent source for their history and rela-tionships.

The medium cut algorithm is described in Heckbert (1982). Lindley (1995) and (Rimmer (1993) describe this algorithm and take a different approach to implementing it.

Conclusion 21

Data Ordering

Format: Windows BMP

Dans le document File Formats (Page 27-32)