Dot matrix with device-independent

xiaoxiao2021-03-06  45

In the previous chapter, we learned that the Windows GDI dot matrix object (also known as a dot matrix map, or DDB) has many programming purposes. But I didn't show the way these dot matrix maps to the magnetic file or load them into the memory. This is the method used in Windows, it is now not available. Since the bit element format of the dot matrix is ​​relatively dependent on the device, the DDB does not apply to image exchange. There is no color control table in the DDB to specify the connection between the bit and the color of the point. DDB is only meaningful when Windows is created and cleared during the life period of the shutdown. A dot matrix (DIB) independent of the device is published in Windows 3.0, providing an image file format for exchange. As you know, other image file formats like .gif or .jpeg are more common than DIB files on the Internet. This is mainly because .gif and .jpeg format compressed, it has significantly reduced the download time. Although there is a compression scheme for DIB, it is very useful. The dot matrix map in the DIB is almost all compressed. This is actually an advantage if you want to operate a point in your program. DIB is not like .gif and .jpeg file, the Windows API directly supports DIB. If there is DIB in the memory, you can provide an indicator to the DIB as a parameter of some functions to display DIB or convert DIB to DDB.

DIB file format

Interestingly, DIB format is not from Windows. It is first defined in the 1.1 version of OS / 2, which was initially developed by IBM and Microsoft in the middle of the 1980s. OS / 2 1.1 is released in 1988 and is the first OS / 2 version containing a graphical user interface similar to Windows, which is called "Presentation Manager (PM)". "Presentation Manager" contains the "Graphic Program" (GPI) of the definition point array format.

The OS / 2 dot matrix map format is then used in Windows 3.0 (posted in 1990), which is called Dib. Windows 3.0 also includes variants in the original DIB format and becomes a standard under Windows. Some other enhancements have been defined under Windows 95 (and Windows NT 4.0) and Windows 98 (and Windows NT 5.0), I will discuss them in this chapter.

DIB first acts as a file format, its secondary file name is .bmp, under very small case .dib. The dot matrix image used by the Windows application is created as a DIB file and is stored as a prior to the existing resource. The illustration and the mouse cursor is also a slightly different DIB file.

The program can subtract DIB files into a continuous memory block of the first 14 positions. At this time, it can be called "Packed Dib (Packed-DIB) format." The application executed under Windows can use the PACKED DIB format to exchange images or create a brush through the Windows Scrapbook. The program can also completely access the contents of the DIB and modify the DIB in any manner.

The program can also create your own DIB in the memory and then put them into the file. Program uses a GDI-like call to "draw" images in these DIBs, and can also use other memory DIBs to set and operate the icon dollar in the program.

After the DIB is loaded in the memory, the program can also use DIB information through several Windows API cards, I will discuss related content in this chapter. API calls related to DIB are very small, and mainly related to the video display or printer page, which is related to the converted GDI dot matrix object.

In addition to these contents, there are many DIB tasks that need to be completed, and these tasks Windows job systems are not supported. For example, a program may access 24-bit dib and want to convert it to an 8-bit dib with an optimized 256-color tone disk, and Windows will not perform these operations for you. But in this chapter and the next chapter will display a way to operate DIB outside the Windows API. OS / 2 style DIB

Don't fall into too many details, let's take a look at the Windows DIB format that is first compatible with the dot matrix format that appears in OS / 2 1.1.

There are four main parts: DIB files:

Archive Head Sports Header RGB Color Control Table (Not necessarily) Dynamic Picture Graphic Position You can view the first two parts as C's data structure, regard the third part as an array of data structures. These structures are described in Windows Header Archive Wingdi.h. There are three parts in the PACKED DIB format in the memory:

Information header RGB color control table (not necessarily) dot matrix graphics, except that there is no archive, the other parts are the same as the DIB stored in the file.

DIB file (not a PACKED DIB in memory) to define the archive header of the 14-bit groups of the following structure:

typedef struct tagBITMAPFILEHEADER // bmfh {WORD bfType; // signature word "BM" or 0x4D42DWORD bfSize; // entire size of fileWORD bfReserved1; // must be zeroWORD bfReserved2; // must be zeroDWORD bfOffsetBits; // offset in file of DIB Pixel Bits} BitmapfileHeader, * PbitmapfileHead; the structure defined in Wingdi.h may be unsatisfactory as this, but is functionally identical. The first annotation (that is, text "BMFH") pointed out the abbreviations recommended when naming this data variable change. If you see a variable named PBMFH in my program, this may be a metrics pointing to the BitmapFileHeader structure or pointing to the PbitmapFileHeader variable.

The structure has a length of 14-bit group, which starts with two letters "BM" to indicate a dot matrix file. This is a Word value 0x4d42. The DWORD followed by "BM" pointed out the size of the file including the archive header. The next two Word fields are set to 0. (In the case of a mouse tag file similar to the DIB file format, these two fields pointed out the "Hot Spot" of the cursor. The structure also contains a DWORD field that indicates the bit element group offset in the status of the status of the status in the file. This value comes from the information in the DIB information header, which is provided here in order to use.

In the DIB in OS / 2 style, the BitmapFileHeader structure followed the BitmapCorehead structure, which provides basic information about DIB images. The tightened DIB (Packed DIB) begins in BitmapCoreheader:

typedef struct tagBITMAPCOREHEADER // bmch {DWORD bcSize; // size of the structure = 12WORD bcWidth; // width of image in pixelsWORD bcHeight; // height of image in pixelsWORD bcPlanes; // = 1WORD bcBitCount; // bits per pixel ( 1, 4, 8, or 24)} Bitmapcoreheader, * Pbitmapcorehead; "Core)" It looks a bit strange here, which means that this format is the basis of other dot matrix formats derived. The BitmapCorehead has the BCSIZE field indicates the size of the data structure, in which case 12-bit groups.

The BCWIDTH and BCHEIGHT fields contain a dot matrix size in a primary. Although these fields use Word means a DIB may be 65,535 odds and wide, but we have little unit hardly use.

The value of the BCPLANES field is always 1. This field is the residue of the early Windows GDI dot matrix object we encountered in the previous chapter.

The BCBITCOUNT field indicates the number of bit elements per status. For the DIB of OS / 2 style, this may be 1, 4, 8 or 24. The number of colors in the DIB image is equal to 2bmch.bcbitcount, or expressed as the syntax of C:

1 << BMCH.BCBITCOUNT, the BCBITCOUNT field is equal to:

1 Represents 2 color DIB 4 represents 16 color DIB 8 represents 256 color DIB 24 represents Full -Color Dib When I mention "8-bit dib", it is said that each image occupies 8-bit dib.

For the first three situations (that is, the number of bits is 1, 4 and 8), Bitmapcorehead is tightened with the color control, and the 24-bit DIB has no color comparison table. Color control table is an array of 3-bit yuan group RGBTRIPLE structure, each element in the array represents each color in the image:

Typedef struct tagrgbtriple // rgbt {byte rgbtblue; // blue levelbyte rgbtgreen; // Green LevelByte rgbtriple; // red level} RGBTRIPLE; this to arrange color controls so that the most important color in DIB is first displayed, we will explain the next chapter the reason.

Wingdi.h header file also defines the following structure:

typedef struct tagBITMAPCOREINFO // bmci {BITMAPCOREHEADER bmciHeader; // core-header structureRGBTRIPLE bmciColors [1]; // color table array} BITMAPCOREINFO, * PBITMAPCOREINFO; the structure of the header information combined color table. Although the number of RGBTRIPLE structures is equal to 1 in this structure, you will never find only one RGBTRIPLE in the DIB file. Depending on the number of bits of each of the primers, the size of the color control table is always 2,16 or 256 RGBTRIPLE structures. If you need to configure the PbitmapCoreInfo structure for 8-bit DIB, you can do this:

PBMCI = Malloc (SizeOf (BitmapCoreInfo) 255 * sizeof (RGBTRIPLE)); then you can access the RGBTRIPLE structure:

PBMCI-> BMCIICOLORS [i] Because the length of the RGBTrIPLE structure is 3-bit group, many RGBTRIPLE structures may start at the odd number of devices in DIB. However, since there is always an even RGBTrIPLE structure in the DIB file, the data block immediately following the array of color control tables always starts with the Word address boundaries. The information followed by the color control table (24-bit DIB is the information header) is the primary element.

Upward

Like most dot matrix maps, the icon in the DIB is based on the horizontal tissue, and the term "scan line" is referred to as a "scan line" with the hard body of the video display. The number of lines is equal to the BitmapCorehead structure of the BCHEIGHT field. However, different from most dot matrix map formats, DIB starts from the bottom row of the image, indicating the image.

Here, some terms should be defined. When we say "top row" and "bottom line", it refers to the top and bottom of the virtual image when it correctly displays correctly on the page of the display or printer. It seems that the top row of portraits is hair, the bottom is chin, "The first line" in the DIB file refers to the pattern of the color control of the DIB file, "the last line" refers to the most end of the file. Pestine.

Therefore, in DIB, the bottom row of the image is the first line of the file, and the top line of the image is the last line of the file. This is called the underlying tissue. Because this kind of organization and intuition, you may ask: Why do you want to do this?

Ok, now we go back to OS / 2 Presentation Manager. IBM believes that the coordinate system in the PM - includes window, graphics, and dot matrix - should be consistent. This has arramed that most people, including programmakers working in full-screen text mode and window environments, believe that the vertical seating should be used to increase the coast on the screen. However, computer graphics writers believe that video is displayed using a mathematical approach to parsing geometries, which is a vertical horn, a vertical (or Cartesian) coordinate system, which is increased in space.

In short, the mathematics method wins. All things in the PM are in the lower left corner (including the window seat), so DIB has that way.

DIB icon

The last part of the DIB file (in most cases, the main body of the DIB file) consists of the actual DIB's icon element. The primer is based on a horizontal tissue that begins from the bottom row of the image and grows upward along the image.

The number of rows in the DIB is equal to the BitmapCoreheader structure of the BCHEIGHT field. The number of graphs per line is equal to the BCWIDTH field of the structure. Every line starts from the leftmost status until the right side of the image. The number of bits of each primer can be obtained from the BCBITCOUNT field, which is 1, 4, 8 or 24.

The length of each line in the bit group is always 4 times. The length of the line can be calculated:

RowLength = 4 * (BMCH.BCWIDTH * BMCH.BCBITCOUNT 31) / 32); or more effective ways within C:

RowLength = (BMCH.BCWIDTH * BMCH.BCBITCOUNT 31) & ~ 31) >> 3; The total number of primary pits of the primary position is equal to the product of RowLength and BMCH.BCHEIGHT.

To understand the way in the way, let us consider four situations. In the following chart, each bit element group is displayed in the box and has a number, 7 represents the highest bit element, 0 represents the lowest bit element. The pattern also numbered from 0 from the leftmost line.

For the 1-bit diblium per status, each packet corresponds to 8 primubes. The leftmost chamber is the highest bit of the first bit component:

Each status can be 0 or 1.0 to indicate that the color of the icon is given by the first RGBTRIPLE item in the color control table. 1 Represents the color of the icon by the second item of the color comparison table. For DIBs of the 4-bit dollar per image, each bit is corresponding to two icons. The leftmost chamber is the highest level of the first bit group, push:

The value of the 4-bit dollar per image is from 0 to 15. This value is the index of 16 items in color control tables.

For the DIB of 8 bits per status, each bit is set to 1 primitive:

The value of the bit is from 0 to 255. Similarly, this also points to 256 projects in color control tables.

For the 24-bit dib, each of the dies is required to represent the color value of red, green and blue. Each line of the primary element is basically the array of RGBTRIPLE structures, which may need to be in each row of 0 so that the behavior of 4-bit groups:

There is no color comparison table for 24-bit dibes per status.

Extended Windows DIB

Now we have mastered the DIB that is compatible with OS / 2 in Windows 3.0, and also look at the extension version of DIB in Windows.

This DIB is the same as the front format, starting with the BitmapFileHeader structure, but then the BitmapInfoHeader structure, not the BitmapCoreheader structure:

typedef struct tagBITMAPINFOHEADER // bmih {DWORD biSize; // size of the structure = 40LONG biWidth; // width of the image in pixelsLONG biHeight; // height of the image in pixelsWORD biPlanes; // = 1WORD biBitCount; // bits per pixel (1, 4, 8, 16, 24, or 32) DWORD biCompression; // compression codeDWORD biSizeImage; // number of bytes in imageLONG biXPelsPerMeter; // horizontal resolutionLONG biYPelsPerMeter; // vertical resolutionDWORD biClrUsed; // number of colors Useddword Biclrimportant; // Number of Important Colors} BitmapInfoHeader, * PbitmapInfoHead; You can distinguish between Dib and Windows DIBs compatible with OS / 2 by checking the first field of the structure, the former 12, the latter is 40.

You will notice that there are six additional fields in this structure, but BitMapInfoHeader is not simply plus some new fields with BitmapCoreheader. Take a closer look: In the BitmapCoreheader structure, the BCWIDTH and BCHEIGHT fields are 16-bit Word value; and they are 32-bit long values ​​in the BitmapInfoHeader structure. This is an annoying small change, it will bring you trouble.

Another change is: For 1-bit, 4-bit, and 8-bit dib, 4-bit and 8-bit dib, which use the BitmapInfoHeader structure, the color control table is not an array of RGBTRIPLE structures. Instead, the BitmapInfoHeader structure is tightly followed by an array of RGBQUAD structures:

Typedef struct tagrgbquad // rgb {byte rgbblue; // blue levelbyte rgbgreen; // red levelbyte rgbred; // red levelbyte rgbreserved; // = 0} RGBQUAD; except that the fourth field is always set to 0 The same as the RGBTRIPLE structure. WINGDI.H header file also defines the following structure: typedef struct tagBITMAPINFO // bmi {BITMAPINFOHEADER bmiHeader; // info-header structureRGBQUAD bmiColors [1]; // color table array} BITMAPINFO, * PBITMAPINFO; Note, if the structure BITMAPINFO The 32-bit address boundary begins because the length of the BitmapInfoHeader structure is 40-bit groups, so each item in the RGBQUAD array is also starting with a 32-bit boundary. This ensures that the color control form data is addressed more effectively through the 32-bit microprocessor.

Although BitmapInfoHeader was originally defined in Windows 3.0, many columns were redefined in Windows 95 and Windows NT 4.0 and were brought into Windows 98 and Windows NT 5.0. For example, in the current file: "If Biheight is negative, the point line is from the upper and lower DIB, the origin is in the upper left corner." This is good, but when someone has done this decision in 1990, it will be better. My suggestion is to avoid establishing the upward DIB. Some programs did not consider this new "characteristic" when writing, and will be lost when encountering a negative Biheight field. There is also a Microsoft Word 97 with Microsoft Photo Editor reports "image height is not legal" when encountering the top-down DIB (although Word 97 itself will not be wrong).

The BIPLANES field is always 1, but the BIBITCOUNT field can now be 16 or 32 and 1, 4, 8 or 24. This is also new features in Windows 95 and Windows NT 4.0. I will introduce these additional format works in a while.

Let us now skip the Bicompression and BisizeImage fields, and discuss them in a while.

Bixpelspermeter and Biypelspermeter fields indicate the actual size of the image with how many icons per meter. ("Pel" - Picture Element (Image Element) - is the name of IBM to the title.) Windows does not use such information internally. However, the application can display DIB with an accurate size. These fields are useful if DIB is derived from a device that does not have a comparable. In most DIBs, these fields are set to 0, which means that there is no suggestion. The resolution of 72 points per inch (sometimes used for video displays, although the actual resolution dependent on the display of the display) approximately 2835 composers per meter, the resolution of the ordinary printers of 300 DPI is 11,811 per meter 11,811 Composition.

Biclrused is a very important field because it affects the number of items in the color control table. For 4-bit and 8-bit dib, it indicates that the color control table contains less than 16 or 256 items, respectively. Although it is not common, this is a method of narrowing DIB sizes. For example, assuming that the DIB image includes only 64 grayscale, the biclrused field is set to 64, and the color control panel of 256 bit groups contains 64 RGBQUAD structures. The range value ranges from 0x00 to 0x3f. DIB still requires a 1-bit group per status, but the height of each of the primary groups is zero. If the Biclrused field is set to 0, it means that the color control table contains all the number of items represented by the BIBITCOUNT field. Starting from Windows 95, the Biclrused field can be non-zero for 16-bit dollars, 24-bit or 32-bit dib. In these cases, Windows does not use the color control table to explain the chammetric unit. Conversely, it indicates the size of the color control table in DIB, and the program uses this information to display the DIB on the 256-color video display. You may think of the 24-bit dib without a color comparison table in the OS / 2 compatibility format. In the extension format in Windows 3.0, it is also like this. In Windows 95, the 24-bit DIB has a color control table, and the BICLRUSED field indicates its size.

Summarized as follows:

For 1-bit dib, Biclrused is always 0 or 2. There are always two items in color control table. For 4-bit dib, if the BICLRUSED field is 0 or 16, there is 16 items in color control tables. If it is from 2 to 15, it refers to the number of items in the color control table. The maximum value of each primary is less than the number of 1. For 8-bit dib, if the BICLRUSED field is 0 or 256, there is 256 items in color control. If it is from 2 to 225, it refers to the number of items in the color control table. The maximum value of each primary is less than the number of 1. For 16-bit, 24-bit or 32-bit dib, the BICLRUSED field is usually 0. If it is not 0, it refers to the number of items in the color control table. Applies to a 256-color display card can use these items to set a palette for DIB. Another warning: The original use of the early DIB files does not support the color control in 24-bit DIB, if the color of the 24-bit DIB is used in the program, it is necessary to take a certain risk.

The BICLRIMPORTANT field does not have a biclrused field. It is usually set to 0 to indicate that all colors in the color control table are important, or it has the same value as biclrused. Both methods means the same thing, if it is set to 0 and biclrused, it means that the DIB image can be reasonably acquired only by the first Biclrimportant project in the color control table. This is useful when displaying two or more 8-bit dib on a 256-color display card.

For the DIB of 1-bit, 4-bit, 8-bit and 24-bit di, the structure of the icon element and the OS / 2 compatible DIB are the same, I will discuss 16 yuan and 32-bit DIB for a while. .

Real inspection

What do you want to find when you encounter a DIB established by other programs or others?

Despite the first launch of Windows 3.0, the DIB of OS / 2 style is already very common, but this format has rarely appeared in this format. Many posts writers ignore them when they actually write fast DIBs. Any 4-bit dib you encounter may be built using a 16-color video display using a 16-color video display, which has a standard 16 colors of the color control table on these displays.

The most common DIB may be 8 bits per status. The 8-bit dibric dib is divided into two categories: grayscale DIB and mixed color DIB. Unfortunately, the header information is not pointed out in the 8-bit DIB.

Many grayscale DIBs have a biclrused field equal to 64, pointing to 64 items in the color control table. These items are usually arranged in a rising grayscale, that is, the color control table begins with the RGB value of 00-00-00, 04-04-04, 08-08-08, 0C-0C-0C, and includes F0-F0 -F0, F4-F4-F4, the RGB value of F8-F8-F8 and FC-FC-Fc. Such color comparisal tables can be calculated by the following formula: RGB [i] .RGBRED = RGB [i] .RGBGREEN = RGB [i] .RGBBLUE = i * 256/64; RGB is the array of RGBQUAD structure, I 0 to 63. The grayscale color control table can be calculated by the following formula:

RGB [i] .RGBRED = RGB [i] .rgbgreen = RGB [i] .RGBBLUE = i * 255/63; thus ending with FF-FF-FF.

In fact, which calculation formula does not differ. Many video display cards and displays are not more color accuracy than 6-bit metals. The first formula recognized this fact. However, when generating a gray scale of less than 64 - may be 16 or 32 (in this case, the divisor of the formula is 15 and 31) - the second formula is used is more suitable because it ensures that the last item of the color control table is FF-FF-FF, that is, white.

When some 8-bit grayscale DIB has 64 items in the color control table, there will be 256 projects in other grayscale DIBs. The BICLRUSED field can actually be 0 (pointing out 256 items in the color control table) or from 2 to 256. Of course, there is no meaning if the biclrused value is 2, because such an 8-bit dib can be used as a 1-bit dib re-encoded) or less than or equal to 16 is meaningless (because it can be used as a 4-bit dib Reproduced). In any case, the number of items in the color control table must be the same as the Biclrused field (if biclrused is 0, it is 256), and the status value cannot exceed the value of the color control table item. This is because the iconic value is the index of the color control table array. The range of 8-bit dib, the primary dib, the value of the biclrused value is from 0x00 to 0x3f.

Here, you should remember an important thing: when the 8-bit dib has a color comparison table composed of the entire grayscale (that is, when red, green, and blue is equal), or when these grayscale layers are in colors. When the control table is incremented (like the above described above), the prime value itself represents the extent of gray. That is, if biclrused is 64, then the 0x00 iconic value is black, the 0x20 is a 50% grayscale, and the 0x3f is a graphic value of the 0x3F.

This is important for some image processing homework because you can completely ignore the color control table, just process the iconic value. This is very useful. If you let me go back to the time to make a simple change to the BitmapInfoHeader structure, I will add a flag to indicate that the DIB mapping is ash, if so, Dib has no color control table, and the iconic value Directly represent grayscale.

The 8-bit dibly mixed 8-bit DIB generally uses the entire color control table, and its Biclrused field is 0 or 256. However, you may also encounter less colors, such as 236. We should recognize a fact: program usually only change 236 projects in the Windows color plane to display these DIBs correctly, I will discuss this in the next chapter.

Bixpelspermeter and Biypelspermeter are rarely non-zero, and the BICLRIMPORTANT field is not a 0 or biclrused value.

DIB compression

I didn't discuss the BiCompression and BisizeImage fields in BitmapInfoHeader, and now we discuss these values. The BiCompression field can be one of four constants, which are: Bi_RGB, Bi_RLE8, BI_RLE4, or BI_BITFIELDS. They are defined in the WINGDI.H header file, and the values ​​are 0 to 3, respectively. This field has two uses: For 4-bit and 8-bit dib, it indicates that the icon element is compressed in a run-length encoding. For 16-bit and 32-bit dib, it is pointed out whether color masking is used to encode the icon element. These two features are published in Windows 95.

Let us first look down RLE compression:

For 1-bit dib, the Bicompression field is always bi_rgb. For 4-bit dib, the BiCompression field can be BI_RGB or BI_RLE4. For 8-bit dib, the BiCompression field can be BI_RGB or BI_RLE8. For the 24-bit dib, the Bicompression field is always bi_rgb. If the value is a Bi_RGB, the icon is stored, the operation length encoding the compressed icon unit is used as if the OS / 2 is compatible.

Running Length Coding (RLE) is the simplest data compressed form, which is based on the DIB mapping in one column. This fact is often available. RLE saves space by coding the value and repetition of the repeating set, and the RLE scheme for DIB defines a few rectangular DIB images, that is, some areas of the rectangle are undefined, this energy It is used to represent a non-rectangular image.

The 8-bit dib's run length encoding is simpler, so let us start from here. Table 15-1 will help you understand the encoding method of the icon element when the BiCompression field is equal to BI_RGB8.

Table 15-1

2-bit group 1 bit group 2 bits group 3-bit group 4 meaning 00 00 00 01 map tail 00 02 DX DY moved to (x DX, Y DY) 00 n = 03 to FF using N Image N = 01 to FF 1 Repeat 1 N times

When decoding the compressed DIB, view the DIB data bit group, such as "bit yuan group 1" and "bitgroup 2" in this table. The form is arranged in an increasing manner of these bitgroup values, but this form will be more meaningful by discussing this form.

If the first bit element group is non-zero (the case of the last line of the table), it is the repetition factor of the run length. The following status is repeated, for example, the bit element group pair

The 0x05 0x27 decoded is:

0x27 0x27 0x27 0x27 0x27 Of course, there are many data that will not be the duplicate to the duplicate, the table countdown second row is handled, which indicates that the number of icons followed should be used one by one. For example: Consider sequence

0x00 0x06 0x45 0x32 0x77 0x34 0x59 0x90 decoded after:

0x45 0x32 0x77 0x34 0x59 0x90 These sequences are always arranged in a 2-bit group boundary. If the second bit group is odd, there is an unused multiple packet group in the sequence. For example, sequence

0x00 0x05 0x45 0x32 0x77 0x34 0x59 0x00 decoded after:

0x45 0x32 0x77 0x34 0x59 This is how to run length coding. Obviously, if there is no duplicate in the DIB image, use this compression technology actually increases the size of the DIB file.

The top three lines of the above table indicate that some parts of the rectangular DIB image may not be defined. Imagine, the program you write is decompressed against the compressed DIB, in which you will keep a pair of numbers (x, y), starting (0,0). Each pair of decodes, the value of X is increased, and the X is reset to 0 and the value of Y is added each of the completion line. When you encounter a bitgroup 0x00 with 0x02, you read the next two bit groups and add them as an increment that does not have a fixed number to the current X and Y values, then continue to decode. When you encounter 0x00 with 0x00, you will have a line, you should set X 0 and increase the Y value. When you encounter 0x00 with 0x01, you complete the decoding. These code allows DIB to include those undefined areas, which are used for non-rectangular image encoding or is very useful when making digital animations and movies (because almost every image comes from the previous information without re-coding) .

For 4-bit dib, the encoding is generally the same, but more complex because the bit element group and the chamber are not one-on-one relationship.

If the first bit element group read is not zero, it is a repetition factor n. The second bit group (repeated) contains two elements, alternate in the decoded sequence of n icons. For example, bit yuan group pair

0x07 0x35 is decoded as:

0x35 0x35 0x35 0x3? The question mark indicates that the icon is not known, if it is the 0x07 0x35 displayed above, follow the bit yuan group pair below:

0x05 0x24 The sequence of the entire decoding is:

0x35 0x35 0x35 0x32 0x42 0x42 If the first bit group in the bit element group pair is 0x00, the second bit element group is 0x03 or more, the number of the second packet pointed out is used. For example, sequence

0x00 0x05 0x23 0x57 0x10 0x00 decoding is:

0x23 0x57 0x1? Note that the decoded sequence must be filled to make it an even bit group.

Regardless of the BiCompression field, Bi_RLE4 or BI_RLE8, BisizeImage fields point out the size of DIB iconic data in the bitgroup. If the BiCompression field is Bi_RGB, BisizeImage is usually 0, but it can be set to Biheight multiplier in the linen bit group length, just as in front of this chapter.

The current document says "The Dib cannot be compressed by the upper and lower DIBs." The up-to-lower DIB is in the case where the BiHeight field is negative.

Color masking

The BiCompression field is also used to connect new 16-bit and 32-bit dibs that appear in Windows 95. For these DIBs, the Bicompression field can be bi_rgb or bi_bitfields (all defined as value 3).

Let's take a look at the 24-bit DIB of Dib's graphic format, which has always had a BiCompression field equal to Bi_RGB:

That is, each line is basically the array of RGBTRIPLE structures, and there is a possible addition to supplement at the end of each row to make the bit group in the row.

For a 16-bit dibric that has a BiCompression field equal to BI_RGB, each of the compliance needs two bit yuan groups. Color is called like this:

Use 5 bits per color. For the first pattern in the line, the blue value is the minimum five-bit element of the first bit. The green value has a bit in the first and second bit groups: the two highest bit of the green value is the two minimum bits in the second bit group, and the three minimum bits of the green value are The three highest bit in the first bit component group. The red value is 2 to 6 yuan in the second bit group. The highest bit element of the second bit component is 0.

This will make more meaningless when you access a chamfer value at a 16-bit group. Because the minimum position of the plurality of bit sets is first stored, the primary group is as follows: assuming that 16-bit elevations are stored in WPIXEL, you can calculate red, green, and blue values ​​with the following formula:

RED = ((0x7c00 & wpixel) >> 10) << 3; Green = ((0x03E0 & WPIXEL) >> 5) << 3; Blue = ((0x001F & WPIXEL) >> 0) << 3; First, Use the mask value with the chamber and computation. This result is: red to the right, move the right, green to the right, move the 0 bit to the right. (I called "right shift value"). This creates a color value from 0x00 and 0x1f, which must move 3 bits to the left to synthesize the color value from 0x00 to 0xF8. (I call it "left shift value".)

Remember: If the 1-bit dib dib is odd, each line is supplemented at the end to allow the bit tuple width to be 4.

For 32-bit dib, if BiCompression is equal to BI_RGB, each of the totes requires a 4-bit group. The blue value is the first bit group, green is the second, red is the third, the fourth bit group equal to 0. It can also be said that the primary is an array of RGBQUAD structures. Because each of the length is 4-bit group, the bit group is not required in the end of the column.

If you want to access each icon with a 32-bit dual word group, it is like this:

If dwpixel is a 32-bit dual-word group,

RED = ((0x00FF0000 & dwpixel) >> 16) << 0; Green = ((0x0000FF00 & dwpixel) >> 8) << 0; blue = ((0x000000FF & dwpixel) >> 0) << 0; left shift The value is all zero, because the color value is in 0xff is the biggest. Note that this double word group is inconsistent with the 32-bit set colorref value of the RGB color in the Windows GDI card call. In the ColorRef value, the red is a bit group of the lowest position.

So far, we discussed the internal setting of the 16-bit and 32-bit dibly when the BiCompression field is Bi_RGB. If the BiCompression field is bi_bitfields, follow the DIB's BitmapInfoHeader structure is three 32-bit color masks, the first for red, the second for green, the third for blue. These masks can be applied to a thermostat of 16-bit or 32-bit dollars using C bit element AND operator (&). Then move the result to the right by right moving, and these values ​​can only be known after the mask is checked. The rules of the color mask should be clear: 1 in each color mask bitter must be continuous, and 1 cannot overlap in three mask bits.

Let us give an example if you have a 16-bit dib, and the BiCompression field is bi_bitfields. You should check the top three double word groups after the BitmapInfoheader structure:

0x0000F8000x000007E00X0000001F Note, because this is 16-bit dib, so only the bit value of the 16-bit element is set to 1. You can set variable dwmask [0], dwmask [1], and dwmask [2] to these values. You can now prepare some of the commonly translated and left-shift values ​​from the mask:

INT MaskTorshift (DWORD DWMASK) {INT ISHIFT; if (dwmask == 0) Return 0; for (iShift = 0;! (dwmask & 1); iShift ) dwmask >> = 1;

Return ishift;}

INT Masktolshift (DWORD DWMASK) {ISHIFT; if (dwmask == 0) Return 0;

While (! (DWMASK & 1)) DWMASK >> = 1;

For (iShift = 0; dwmask & 1; ishift ) dwmask >> = 1;

Return 8 - iShift;} Then call the Masktorshift letter three times to get the right shift value:

Irshift [0] = Masktorshift (dwmask [0]); Irshift [1] = Masktorshift (dwmask [1]); Irshift [2] = Masktorshift (dwmask [2]); value 11, 5 and 0 respectively Then call Masktolshift:

Ilshift [0] = Masktolshift (dwmask [0]); Ilshift [1] = Masktolshift (dwmask [1]); Ilshift [2] = Masktolshift (dwmask [2]); 5, 2, and 3 are obtained. You can now extract each color from the pattern:

RED = ((DWMASK [0] & wpixel >> Irshift [0]) << ilshift [0]; green = ((DWMask [1] & wpixel >> Irshift [1]) << ilshift [1]; Blue = ((DWMask [2] & wpixel >> Irshift [2]) << ilshift [2]; except for color tags to be greater than 0x0000FFF (this is the largest mask value of 16-bit DIB), the program and 32 Like the bit dib.

-------------------------------------------------- ------------------------------

note:

For 16-bit or 32-bit dib, red, green, and blue values ​​can be greater than 255. In fact, in 32-bit dib, two are 0 in the mask, the third should be 32-bit color value 0xFffffFFFFFF. Of course, this is a bit ridiculous, but don't worry about this problem.

-------------------------------------------------- ------------------------------

Unlike Windows NT, Windows 95 and Windows 98 have many restrictions in using color masks. The available values ​​are shown in Table 15-2.

Table 15-2

16-bit dib 16-bit dib 32-bit dib red mask 0x00007C00 0x0000F800 0x00FF0000 green mask 0x000003E0 0x000007E0 0x0000FF00 blue mask 0x0000000000FF speed is 5-5-5 5-6-5 8-8-8

In other words, when BiCompression is BI_RGB, you can use the two groups of masks, including the mask groups shown in the previous example. The table bottom line shows a shorthand symbol to point out the number of bits per status of red, green and blue. 4th version of Header

I said that Windows 95 has changed some definitions of some original BitmapInfoHeader fields. Windows 95 also includes a new extension information header called Bitmapv4Header. If you know that Windows 95 is called Windows 4.0, you will understand the name of this structure, and Windows NT 4.0 also supports this structure.

typedef struct {DWORD bV4Size; // size of the structure = 120LONG bV4Width; // width of the image in pixelsLONG bV4Height; // height of the image in pixelsWORD bV4Planes; // = 1WORD bV4BitCount; // bits per pixel (1, 4, 8, 16, 24, or 32) DWORD bV4Compression; // compression codeDWORD bV4SizeImage; // number of bytes in imageLONG bV4XPelsPerMeter; // horizontal resolutionLONG bV4YPelsPerMeter; // vertical resolutionDWORD bV4ClrUsed; // number of colors usedDWORD bV4ClrImportant; / / number of important colorsDWORD bV4RedMask; // Red color maskDWORD bV4GreenMask; // Green color maskDWORD bV4BlueMask; // Blue color maskDWORD bV4AlphaMask; // Alpha maskDWORD bV4CSType; // color space typeCIEXYZTRIPLE bV4Endpoints; // XYZ valuesDWORD bV4GammaRed; // Red gamma valueDWORD bV4GammaGreen; // Green gamma valueDWORD bV4GammaBlue; // Blue gamma value} BITMAPV4HEADER, * PBITMAPV4HEADER; 11 same field and in the previous note BITMAPINFOHEADER structure, the five support image field color Windows 95 and Windows NT 4.0 in Falling technology. You should use BitmapInfoHeader (or Bitmapv5Header) unless you use the Bitmapv4Header structure.

When the BV4Compression field is equal to BI_BITFIELDS, BV4redmask, BV4Greenmask and BV4BLUEMask can be used for 16-bit and 32-bit dib. They are used as a color mask defined in the BitmapInfoHeader structure for use in the same function, and when using the original structure other than the clear structural field, they actually appear in the same location of the DIB file. As I know, the BV4alphamask field is not used.

Bitmapv5Header Structure The remaining fields include "Image Color Management", which exceeds the scope of this book, but understands that some background will be beneficial to you.

The problem with the RGB scheme for color is that it relies on display technology of video displays, color cameras, and color scanners. If the color is specified as the RGB value (255, 0, 0) means that the maximum voltage should be applied to the red electron gun in the cathode ray tube, and the RGB value (128, 0, 0) represents using a half voltage. Different displays produce different effects. Moreover, the printing machine uses a different color representation to represent colors in cyan, magenta, yellow and black. These methods are called CMY (Cyan-Magenta-Yellow: Cyan-Magenta-Yellow) and CMYK (cyan-mage-yelow-black: cyan - magenta - yellow - black). The mathematical formula converts the RGB value into CMY and CMYK, but cannot guarantee that the printing machine color is in line with the display color. "Color Future Technology" is an attempt to link the color with standards that have nothing to do. The phenomenon of colors is related to the wavelength of visible light, and the wavelength ranges from 380 nm (blue) to 780 nm (red). Everything we can detect is a combination of different wavelengths in the visible spectrum. In 1931, Commission International, Illumination, or CIE developed a scientific metrics. This includes using three color-assay functions (names x, y, and z), which published in the form of the form (with values ​​with every 5 nm) in Table 2.1, "ColorimeTry, Second Edition" .

The color of the color (S) is a set of values ​​that indicate each wavelength intensity. If you know the spectrum, you can apply a function-related function to the spectrum to calculate x, y, and z:

These values ​​are called large x, large y and big z. Y color matching function is equal to the reaction of the naked eye to the visible spectral inner light. (He looks like a clock curve from 380 nm and 780 nm to 0). Y is called CIE brightness because it indicates the overall strength of the light.

If you use a Bitmapv5Header structure, the BV4cStype field must be set to LCS_Calibrated_RGB, its value is 0. The last four bit groups must be set to a valid value.

The CIEXYZTRIPLE structure defines as follows:

Typexyz CIEXYZGREEN; CIEXYZ CIEXYZGREEN; CIEXYZ CIEXYZBLUE;} CIEXYZTRIPLE, * LPCIEXYZTRIPLE;

TypedEf struct tagciexyz {fxpt2dot30 ciexyzx; fxpt2dot30 ciexyzy; fxpt2dot30 ciexyzz;} CIEXYZ, * LPCIEXYZ; these three fields are defined as fxpt2 dot30 values, meaning that they are a fixed point value with a 2-bit integer part and 30-bit partial part. In this way, 0x40000000 is 1.0,0X48000000 is 1.5. The maximum 0xfffffff is only a little bit of 4.0.

The BV4ENDPOINTS field provides three x, y, and z values ​​associated with RGB colors (255, 0), (0, 255, 0) and (0, 0, 255). These values ​​should be inserted from the application of DIB to indicate the meaning of the device of these RGB colors.

Bitmapv4Header remaining three fields refers to the "Gamma Value" (Greek's lowercase letters γ), which points out nonlinearity in the color level specification. In Dib, red, green, and blue range from 0 to 225. On the display card, these three values ​​are converted to three types ratio voltage used by the display, and the voltage determines the strength of each. However, due to the electronic characteristics of the electronic gun in the cathode ray tube, the intensity (i) of the primer is not linear with the voltage (V), and their relationship is: ε is a black grade that is controlled by the "brightness" control of the display (ideal) The value is 0). Index γ is set by the "image" or "contrast" control of the display. For most displays, γ is about 2.5.

In order to compensate this nonlinearity, the camera contains "gamma correction" in the line. Index 0.45 fixes the light entering the camera, which means the gamma of the video display is 2.2. (The high gamma value of the video display increases the contrast, which is usually not required because the surrounding light is more suitable for low contrast.)

This non-linear response to the video display is actually very appropriate because the reaction of the human to the light is also non-linear. I have mentioned that Y is called CIE brightness, which is linear light metric. CIE also defines a brightness value close to human feel. The brightness is L * (pronounce "Ell Star"), by using the following formula:

This YN is a white level. The first portion of the formula is a small linear portion. Generally, the brightness of human beings is related to the cube root of linear brightness, which is pointed out by the second formula. L * ranges from 0 to 100, each time L * increases, assuming that the minimum change in the brightness that humans can feel.

Based on the sensation brightness rather than the linear brightness, it is better to encode the light intensity. This reduces the number of bits to a reasonable degree and also reduces netup on the class ratio.

Let's take a look at the entire program. The primary (P) ranges from 0 to 255, which is linearly converted into a voltage level, and we assume that standardization is between 0.0 and 1.0. Assume that the display of the display is set to 0, the strength of the icon is:

Here γ is approximately 2.5. The brightness (L *) of human feels depends on this intensity cube root and changes from 0 to 100, so about:

The index value is approximately 0.85. If the index value is 1, then the CIE brightness is fully matched with the iconic value. Of course, it is not entirely that case, but if the value indicates that the linear brightness is very close.

The last three fields of Bitmapv4Header provide a method for setting a gamma value that is assumed to establish a dib. These values ​​are described by a small number of 16-bit integer values ​​and 16-bit dollars. For example, 0x10000 is 1.0. If DIB is established by capturing an actual image, the image capture hard body may contain this gamma value, and may be 2.2 (encoded is 0x23333). If DIB is generated by a program through the algorithm, the program will use a function to convert any linear brightness it used to CIE brightness.

5th edition of Header

The program written for Windows 98 and Windows NT 5.0 (ie Windows 2000) can use DIBs with new Bitmapv5Header information structure:

typedef struct {DWORD bV5Size; // size of the structure = 120LONG bV5Width; // width of the image in pixelsLONG bV5Height; // height of the image in pixelsWORD bV5Planes; // = 1WORD bV5BitCount; // bits per pixel (1, 4,8,16,24, or32) DWORD bV5Compression; // compression codeDWORD bV5SizeImage; // number of bytes in imageLONG bV5XPelsPerMeter; // horizontal resolutionLONG bV5YPelsPerMeter; // vertical resolutionDWORD bV5ClrUsed; // number of colors usedDWORD bV5ClrImportant; // number of important colorsDWORD bV5RedMask; // Red color maskDWORD bV5GreenMask; // Green color maskDWORD bV5BlueMask; // Blue color maskDWORD bV5AlphaMask; // Alpha maskDWORD bV5CSType; // color space typeCIEXYZTRIPLE bV5Endpoints; // XYZ valuesDWORD bV5GammaRed; // Red gamma valueDWORD bV5GammaGreen; // Green gamma valueDWORD bV5GammaBlue; // Blue gamma valueDWORD bV5Intent; // rendering intentDWORD bV5ProfileData; // profile data or filenameDWORD bV5ProfileSize; // size of embedded data or FilenamedWord Bv5ReServed;} Bitmapv5Header, * Pbitmapv5Header; Here there are four new fields, only three of them are useful. These fields support ICC Profile Format Specification, which is established by the International Color Consortium (INTERNATIONAL COLORTIUM "(consisting of Adobe, AGFA, Apple, Kodak, Microsoft, Silicon Graphics, Sun Microsystems, and other companies). You can get this standard copy on http://www.icc.org. Basically, each input (scanner and camera), output (printer and film recorder), and display (display) devices are associated with the original device related color (typically RGB or CMYK), the device independent color specification The fixed case is related to the CIE XYZ value to correct color. These settings files are the reposition name of .ICM (refer to "Image Color Management: Image Color Management"). The setting file can be embedded in the DIB file or link from the DIB file to point to the way DIB. You can get detailed information about Windows "Image Color Management" in / Platform SDK / Graphics and MultiMedia Services / Color Management.

Bitmapv5Header's BV5cStype field can have several different values. If it is lcs_calibrated_rgb, it is compatible with the Bitmapv4Header structure. The BV5ENDPOINTS field and the gamma column must be valid. If the BV5CStype field is LCS_SRGB, you do not have to set the remaining fields. The preset color space is the "standard" RGB color space, which is mainly designed by Microsoft and Hewlett-Packard, which contains content-independent content without a large number of settings files. This file is located at http://www.color.org/contrib/srgb.html.

If the BV5cStype field is LCS_WINDOWS_COLOR_SPACE, you don't have to set the remaining fields. Windows uses a preset color space to display a dot mapping in a preset color space via an API card.

If the BV5CSTYPE field is profile_embedded, the DIB file contains an ICC setting file. If the field is profile_linked, the DIB file contains the full path and archive name of the ICC setting file. In both cases, BV5ProfileData starts from Bitmapv5Header to the offset of the setting file data or file name starting position. The BV5PrOFileSize field gives the size of the information or file name. There is no need to set BV5ENDPOINTS and Gamma field.

Show DIB Information

Let us look at some program code. In fact, we don't fully understand the knowledge of the Dib, but at least the table is displayed from the head structure information about DIB. As shown in Dibhots, 15-1 Dibheads.

Program 15-1 dibheadsdibheads.c / * --------------------------------------- --------------------------------- Dibheads.c - Displays Dib Header Information (c) Charles Petzold, 1998 -------------------------------------------------- ------------------------- * /

#include #include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "DibHeads"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HACCEL hAccel; HWND hwnd; MSG msg WNDCLASS WNDCLASS;

wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); WNDCLASS.HBRBACKGROUND = (Hbrush) getStockObject (white_brush); WNDCLASS.LPSZMENUNAME = SZAPPNAME; WNDCLASS.LPSZCLASSNAME = szAppname;

if {MessageBox (NULL, TEXT (), szAppName, MB_ICONERROR "This program requires Windows NT!"); return 0;} (RegisterClass (& wndclass)!) hwnd = CreateWindow (szAppName, TEXT ( "DIB Headers"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); hAccel = LoadAccelerators (hInstance, szAppName); while (GetMessage (& msg, NULL, 0, 0) ) {if (! TranslateMCELERATOR (& MSG)) {TranslateMessage (& MSG); DispatchMessage (& MSG);}} Return Msg.wParam;}

Void Printf (HWND HWND, TCHAR * SZFORMAT, ...) {Tchar Szbuffer [1024]; VA_LIST PARGLIST

VA_Start (Parglist, Szformat); WVsPrintf (Szbuffer, Szformat, Parglist); VA_END (PARGLIS);

SendMessage (hwnd, EM_SETSEL, (WPARAM) -1, (LPARAM) -1); SendMessage (hwnd, EM_REPLACESEL, FALSE, (LPARAM) szBuffer); SendMessage (hwnd, EM_SCROLLCARET, 0, 0);} void DisplayDibHeaders (HWND hwnd , TCHAR * szFileName) {static TCHAR * szInfoName [] = {TEXT ( "BITMAPCOREHEADER"), TEXT ( "BITMAPINFOHEADER"), TEXT ( "BITMAPV4HEADER"), TEXT ( "BITMAPV5HEADER")}; static TCHAR * szCompression [] = {TEXT ( "BI_RGB"), TEXT ( "BI_RLE8"), TEXT ( "BI_RLE4"), TEXT ( "BI_BITFIELDS"), TEXT ( "unknown")}; BITMAPCOREHEADER * pbmch; BITMAPFILEHEADER * pbmfh; BITMAPV5HEADER * pbmih; BOOL Bsuccess; dWord dwfilesize, dwhight dwfilesize, dwhight; dwbytesread; handle hfile; int i; pbyte pfile; tchar * szv;

// Display the file name

Printf (hwnd, TEXT ( "File:% s / r / n / r / n"), szFileName); // Open the filehFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if ( Hfile == invalid_handle_value) {Printf (HWND, Text ("canNot Open file./r/n/n")); return;} // Get the size of the filedwfilesize = getFileSize (Hfile, & Dwhight); if ( DWHIGHSIZE) {Printf ("Cannot Deal with> 4G files./r/n/r/N"); CloseHandle; Return;} // allocate memory for the filepfile = malloc (dwfilesis); IF (! pfile) {Printf (hwnd, text ("cannot allocate memory./r/n/r/N")); CloseHandle (HFILE); Return;} // read the filesetcursor (loadcursor (null, idc_wait)) Showcursor (TRUE);

Bsuccess = Readfile (Hfile, Pfile, DwFileSize, & dwbytesread, null; showcursor (false); setcursor (loadcursor (null, idc_arrow);

IF (! bsuccess || (dwbytesread! = dwfilesize)) {Printf (hwnd, text ("could not read file./r/n/r/n"); CloseHandle; Free (Pfile); Return; }

// Close the fileCloseHandle (hFile); // Display file sizePrintf (hwnd, TEXT ( "File size =% u bytes / r / n / r / n"), dwFileSize); // Display BITMAPFILEHEADER structurepbmfh = (BITMAPFILEHEADER *) Pfile; Printf ("BitmapFileHeader / R / N"); Printf (hwnd, text ("/t.bfType = 0x% x / r / n"), PBMFH-> bftype); Printf (hwnd, TEXT ("/T.bfsize =% u / r / n"), PBMFH-> bfsize; printf (hwnd, text ("/t.bfreserved1 =% u / r / n"), PBMFH-> bFRESERVED1); Printf (hwnd, text ("/t.bfreserved2 =% u / r / n"), PBMFH-> bFRESERVED2); Printf (hwnd, text ("/t.bfofbits =% U / R / N / R / N" ), PBMFH-> bfoffbits;

// Determine which information structure we havepbmih = (BITMAPV5HEADER *) (pFile sizeof (BITMAPFILEHEADER)); switch (pbmih-> bV5Size) {case sizeof (BITMAPCOREHEADER): i = 0; break; case sizeof (BITMAPINFOHEADER): i = 1; szv = text ("i"); Break; Case SizeOf (Bitmapv4Header): i = 2; SZV = Text ("V4"); Break; Case SizeOf (Bitmapv5Hheader): i = 3; SZV = Text ("V5 "); Break; default: Printf (HWnd, Text (" Unknown Header Size of% U. / R / N / R / N "), PBMIH-> BV5Size); Free (pfile);}

Printf (hwnd, text ("% s / r / n"), SZINFONAME [I]); // Display the bitmapcoreheader fieldsif (pbmih-> bv5size == sizeof (bitmapcorehead) {PBMCH = (Bitmapcoreheader *) PBMIH; Printf (hwnd, text ("/ t.bcsize =% u / r / n"), PBMCH-> BCSIZE); Printf (hwnd, text ("/ t.bcwidth =% u / r / n"), PBMCH-> BCWIDTH); Printf (hwnd, text ("/ t.bcHeight =% u / r / n"), PBMCH-> bcHeight; printf (hwnd, text ("/ t.bcplanes =% u / r / n") , PBMCH-> BCPLANES); Printf (hwnd, text ("/ t.bcbitcount =% u / r / n / r / n"), PBMCH-> bcbitcount; free (pfile);}

// Display the bitmapinfoheader fieldsprintf (hwnd, text ("/ tb% ssize =% u / r / n"), SZV, PBMIH-> BV5Size); Printf (hwnd, text ("/ tb% SWIDTH =% I / R / N "), SZV, PBMIH-> BV5WIDTH); Printf (hWnd, Text (" / TB% Sheight =% I / R / N "), SZV, PBMIH-> BV5HEIGHT); Printf (hwnd, text (" / TB% Splanes =% U / R / N "), SZV, PBMIH-> BV5PLANES); Printf (hwnd, text (" / tb% sbitcount =% u / r / n "), SZV, PBMIH-> bv5bitcount; Printf (hwnd, text ("/ tb% scompression =% s / r / n"), SZV, SZCompression [MIN (4, PBMIH-> BV5Compression]); Printf (hwnd, text ("/ tb% ssizeImage =% U / R / N "), SZV, PBMIH-> BV5SIZEIMAGE); Printf (HWnd, Text (" / TB% SXPELSPERMETER =% I / R / N "), SZV, PBMIH-> BV5XPELSPERMETER); Printf (hwnd, text ("/ TB% Sypelspermeter =% I / R / N"), SZV, PBMIH-> BV5ypelspermeter; Printf (hwnd, text ("/ tb% SCLRUSED =% I / R / N"), SZV, PBMIH-> BV5clrused; Printf ("/ tb% SCLRIMPORTANT =% I / R / N / R / N"), SZV, PBMIH-> BV5clrimportant); if (PBMIH-> bv5size == sizeof (bitmapInfoheader) { IF (pbmih-> bv5compression == bi_bitfields) {printf (hwnd, text ("red mask =% 08x / r / n"), PBMI H-> bv5redmask; Printf (HWnd, Text ("Green Mask =% 08x / R / N"), PBMIH-> BV5Greenmask; Printf (HWnd, Text ("Blue Mask =% 08x / R / N / R / N "), PBMIH-> BV5BLUEMASK);} free (pfile);}

// Display Additional Bitmapv4Header Fieldsprintf (HWnd, Text ("/ TB% Sredmask =% 08x / R / N"), SZV, PBMIH-> BV5Redmask; Printf (hwnd, text ("/ tb% sgreenmask =% 08x / r / N "), SZV, PBMIH-> BV5Greenmask; Printf (hwnd, text (" / tb% sbluemask =% 08x / r / n "), SZV, PBMIH-> BV5BLUEMASK); Printf (hwnd, text (" / TB% Salphamask =% 08X / R / N "), SZV, PBMIH-> BV5Alphamask; Printf (hwnd, text (" / tb% scStype =% u / r / n "), SZV, PBMIH-> BV5CSTYPE); Printf (hwnd, text ("/tb%sendpoints.ciexyzred.ciexyzx =% 08x / r / n"), SZV, PBMIH-> BV5ENDPOINTS.CIEXYZRED.cIEXYZX); Printf (hwnd, text ("/tb%sendpoints.ciexyzred .ciexyzy =% 08x / r / n "), SZV, PBMIH-> BV5ENDPOINTS.CIEXYZRED.ciexyzy); Printf (hwnd, text (" /tb%sendpoints.ciexyzred.ciexyzz =% 08x / r / n "), SZV , PBMIH-> BV5ENDPOINTS.CIEXYZRED.cIEXYZZ); Printf (HWnd, Text ("/TB%SendPoints.ciexyzgreen.ciexyzx =% 08x / R / N"), SZV, PBMIH-> BV5ENDPOINTS.CIEXYZGREEN.CIEXYZX); Printf HWnd, Text ("/TB%Sendpoints.ciexyzgreen.ciexyzy =% 08x / r / n"), SZV, PBMIH-> BV5ENDPOINTS.CIEXYZGREEN.CIEXYZY); PRI NTF (HWnd, Text ("/TB%SendPoints.ciexyzgreen.ciexyzz =% 08X / R / N"), SZV, PBMIH-> BV5ENDPOINTS.CIEXYZGREEN.CIEXYZZ); Printf (hWnd, Text ("/TB%SendPoints.ciexyzblue .ciexyzx =% 08x / r / n "), SZV, PBMIH-> BV5ENDPOINTS.CIEXYZBLUE.CIEXYZX); Printf (hwnd, text (" /tb%sendpoints.ciexyzblue.ciexyze =% 08x / r / n "), SZV , PBMIH-> BV5ENDPOINTS.CIEXYZBLUE.CIEXYZY); Printf (hwnd, text ("/tb%sendpoints.ciexyzblue.ciexyzz =% 08x / r / n"), SZV, PBMIH-> BV5ENDPOINTS.CIEXYZBLUE.CIEXYZZ); Printf HWnd, Text ("/ tb% sgammared =% 08x / r / n"), SZV, PBMIH->

BV5gammared); Printf (hwnd, text ("/ tb% sgammagreen =% 08x / r / n"), SZV, PBMIH-> BV5GAMMAGREEN; Printf (hwnd, text ("/ tb% sgammablue =% 08x / r / n / r / n "), SZV, PBMIH-> BV5Gammablue); if (pbmih-> bv5size == sizeof (bitmapv4header)) {free (pfile);}

// Display additional Bitmapv5Header Fieldsprintf (hwnd, text ("/ tb% sintent =% u / r / n"), SZV, PBMIH-> BV5INTENT); Printf (hwnd, text ("/ tb% sprofiledata =% U / R / N "), SZV, PBMIH-> BV5PrOFiledata); Printf (hwnd, text (" / tb% sprofilesize =% u / R / N "), SZV, PBMIH-> BV5PROFILESIZE); Printf (hWnd, Text (" / TB% Snderved =% u / r / n / r / n "), SZV, PBMIH-> BV5RESERVED);

Free (pfile); Return;

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static HWND hwndEdit; static OPENFILENAME ofn; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; static TCHAR szFilter [] = TEXT ( "Bitmap Files (* .BMP) / 0*.BMP/0 ") Text (" All Files (*. *) / 0 *. * / 0/0 "); Switch (Message) {Case WM_CREATE: HWndit = CREATEWINDOW (Text (" Edit "), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY, 0, 0, 0, 0, hwnd, (HMENU) 1, ((LPCREATESTRUCT) lParam) -> hInstance, NULL);

ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName ; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn .lpstrdefext = text ("bmp"); off.lcustdata = 0; off.lpfnhook = null; off.lpTemplatename = null; return 0; Case WM_SIZE: MoveWindow (Hwndedit, 0, 0, Loword (LPARAM), HiWord ), True); RETURN 0;

Case WM_COMMAND: Switch (WPARAM) {CASE IDM_FILE_OPEN: IF (GetopenFileName (& OFN)) DisplayDibheaders (HWndedit, SzFileName);

return 0;} break; case WM_DESTROY:. PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} DIBHEADS.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource .h "#include" afxres.h "

//// AcceleratorDibheads Accelerators Discardable Begin "O", IDM_FILE_OPEN, VIRTKEY, Control, NOINVERTEND

///// MenuDIBHEADS MENU DISCARDABLE BEGINPOPUP "& File" BEGINMENUITEM "& Open / tCtrl O", IDM_FILE_OPENENDENDRESOURCE.H (excerpt) // Microsoft Developer Studio generated include file.// Used by DibHeads.rc

#define idm_file_open 40001 This program has a short WndProc function that establishes a very read edit window to fill its display area, which also handles the "File Open" command on the function table. It uses the standard "File Open" dialog box by calling the GetopenFileName, and then calls the displayDibheaders. This card reads the entire DIB file into the memory and displays all header information.

Display and printing

The dot matrix is ​​used. In this section, let's take a look at the two functions that support the DIB on the video display or the print page. To get better performance, you can use a circle method to display a point of view, I will discuss this method later, but first study these two functions will be better. These two functions are called setDibitstodevice (pronunciation to "set dee eye bits to device") and stretchdibits (pronunciation "Stretch Dee Eye Bits"). Each of the functions uses DIB stored in the memory and can display the entire DIB or its rectangular portion. When using SetDibitStodevice, the size of the map displayed in the group is the same as the size of the DIB. For example, a 640 × 480 DIB will occupy the entire standard VGA screen, but it is only about 2.1 × 1.6 inches on the 300dpi laser plate. StretchDIBITS can extend and reduce the DIB size rows and columns to display a specific size on the output device.

Understand DIB

When you call one of two functions to display DIB, you need a few information about the image. As I said earlier, the DIB file contains the following sections:

The DIB file can be loaded into the memory. If the entire file is stored in the continuous block of the memory, the entire file is pointed to the beginning of the memory block (that is, the beginning of the information header) is referred to as a indicator pointing to the PACKED DIB (see the figure below) ).

This is the format used by the scrapbook transmission DIB, and it is also the format used when you create a brush from DIB. Since the entire DIB is referenced by a single indicator (such as a PPACKEDDIB), the packed dib is a convenient way to store DIB in the memory, which you can define the indicator as a indicator pointing to byte. Using the structural definition shown in the previous section, all information stored in DIB, including color control tables and individual icons.

However, if you want to get so much information, you still need some program code. For example, you cannot simply obtain the DIB width:

iWidth = (PbitmapInfoHeader) PPACKEDDIB) -> BiWidth; DIB may be OS / 2 compatibility. In that format, the Packed DIB starts in the BitmapCorehead structure, and the DIB's primary width and height are stored in a 16-bit element Word, instead of 32-bit dollar LONG. Therefore, the first must check if the DIB is an old format, and then performs a corresponding operation:

if (((PBITMAPCOREHEADER) pPackedDib) -> bcSize == sizeof (BITMAPCOREHEADER)) iWidth = ((PBITMAPCOREHEADER) pPackedDib) -> bcWidth; elseiWidth = ((PBITMAPINFOHEADER) pPackedDib) -> biWidth; of course, it is not bad, but It is better to be clearly known.

There is now a very interesting experiment: given a metrics pointing to Packed Dib, we have to find a graphic value located on the coordinate (5, 27). Even if Dib is not a format of the OS / 2, you also need to know the width, height, and bit number of DIBs. You need to calculate the bit element group length of each column, determine the number of items within the color control table, and whether the color control table includes three 32-bit color masks. You also need to check if DIB is compressed, in which case the icon cannot be directly obtained by the address.

If you need to access all DIB icons (just like many graphics processing work), this may increase a point. For this reason, it is convenient to store a indicator to Packed Dib, but this is not an efficient solution. Another beautiful solution is to define a C category containing sufficient member information to DIB, allowing fast to randomly access DIB icons. However, I have promised the reader without knowing C in this book, I will explain a C's solution in the next chapter. For SetDibitStodevice and STRETCHDIBITS functions, the required information includes an indicator of the BitmapInfo structure of DIB. You should recall, the BitmapInfo structure consists of BitmapInfoHeader structure and color comparison. So this is only a indicator pointing to Packed DIB.

A function also requires an indicator pointing to the icon. Although the program code is very unpleasant, this indicator can also be launched from the information in the information head. Note that this indicator can be easily calculated when you access the BitmapFileHeader structure's BFOFFBITS field. The BFOFFBITS field indicates the offset from the beginning of the DIB file to the icon element. You can simply add this offset to the BitmapInfo indicator and subtract the size of the BitmapFileHeader structure. However, this does not work when you get the indicator of Packed Dib from the scrapbook, because there is no BitmapFileHeader structure.

This chart shows two desired indicators:

SetDibitStodevice and StretchDibits are two indicators to DIB, because the two parts are not in a continuous memory block. You may have two memory:

Indeed, it is useful to divide the DIB into two memory blocks, but we prefer to deal with the entire DIB stored in the Packed DIB of a single memory block.

In addition to these two indicators, SetDibitStodevice and StretchDibits typographically also require DIB's primary and height. If you just want to display part of the DIB, you don't have to know these values ​​clearly, but they will define the upper limit of the rectangle that you define within the DIB icon dollar array.

Point-to-point icon display

SetDibitStodevice Versions Displays DIBs that extends and reduced. Each of the DIB corresponds to an output device, and the image in the DIB will be displayed correctly - that is, the top column of the image is above. Any coordinate conversion that will affect the content of the device affects the start position of the display DIB, but does not affect the image size and direction displayed. The letter is as follows:

iLines = SetDIBitsToDevice (hdc, // device context handlexDst, // x destination coordinateyDst, // y destination coordinatecxSrc, // source rectangle widthcySrc, // source rectangle heightxSrc, // x source coordinateySrc, // y source coordinateyScan, // First Scan Line to DrawCyscans, // Number of Scan Lines To Drawpbits, // Pointer To Dib Pixel Bitspinfo, // Pointer To Dib InformationFclRuse; // Color Use Flag Don't be bored by the number of parameters, in most cases, letters It is easy to use than it looks. However, in other uses, its usage is really messy, but we will learn how to use it.

Like the GDI display, the first parameter of SetDibitStodevice is the device content code, which indicates the device that displays DIB. The following two parameters XDST and YDST are the logic hosting of the output device, indicating that the coordinates of the left upper left corner of the DIB image ("upper end" refer to visually above, not the first row of DIB.). Note that these are logical hosts, so they are attached to any seat-oriented way to actually act or - any spatial conversion set in Windows NT-set. In the desired mm_text mapping mode, these parameters can be set to 0, and the DIB image is displayed from the display plane to the left. You can display the entire DIB image or only part of it, this is the role of the next four parameters. However, there has been a lot of misunderstandings from the upside direction of DIB iconic information. It should now be clear that when the entire DIB is displayed, the XSRC and YSRC should be set to 0, and the CXSRC and CysRc should be equal to the dib of the DIB. Note that because the Biheight field of the BitmapInfoHeader structure is negative for the top DIB, the CysRC should be set to the absolute value of the Biheight field.

This form of file (/ Platform SDK / Graphics and MultiMAP Reference / Bitmap Functions / SetDibitStode) says XSRC, YSRC, CXSRC, and Cysrc parameters are logical units. This is incorrect, they are the coordinates and sizes of the icon. There is no significance of having logical coordinates and units for a status in DIB. Moreover, no matter what map, the DIB displayed on the output device is always CxSRC primary and Cysrc.

This two parameters YSCAN and Cyscan are now discussed in detail. These parameters use a small portion of the DIB to reduce the demand for the memory by a small portion of the DIB from the magnetic sheet or by the data machine. Typically, YSCAN is set to 0, and Cyscan is set to the height of DIB.

The PBITS parameter is an indicator to the DIB icon element. The Pinfo parameter is an indicator of the BitmapInfo structure of DIB. Although the location of the BitmapInfo structure is the same as the location of the BitmapInfoHeader structure, the SetDibitStodevice structure is defined as the use of BitmapInfo structure, suggesting: for 1-bit, 4-bit and 8-bit dib, the dot mapping information header must Follow the color comparison table. Although the Pinfo parameter is defined as an indicator to the BitMapInfo structure, it also points to the BitmapCoreInfo, Bitmapv4Header or Bitmapv5Header structure.

The last parameter is DIB_RGB_COLORS or DIB_PAL_COLORS, which is defined as 0 and 1 in WINGDI.H. If you use DIB_RGB_COLORS, this means that DIB contains a color control table. The DIB_PAL_COLORS flag indicates that the color control table in the DIB has been directed to the 16-bit index of the toner of the selected and identified tunnel in the device content. In the next chapter we will learn this option. Now use DIB_RGB_COLORS, or 0.

SetDIBITSTODEVICE Versatteby The number of scan lines shown.

Therefore, to call SetDibitStodevice to display the entire DIB image, you need the following information:

The device content of the HDC's destination code number XDST and YDST image of the destination coordinate CxDIB and Cydib DIB in the upper left corner, where CYDIB is the absolute value of the Biheight field in the BitmapInfoheader structure. pInfo and pBits pointer to a bitmap information bit pixel portion and then the call SetDIBitsToDevice following manner: SetDIBitsToDevice (hdc, // device context handlexDst, // x destination coordinateyDst, // y destination coordinatecxDib, // source rectangle widthcyDib , // source rectangle height0, // x source coordinate0, // y source coordinate0, // first scan line to drawcyDib, // number of scan lines to drawpBits, // pointer to DIB pixel bitspInfo, // pointer to DIB information0 ); // Color USE FLAG, therefore, in 12 parameters of the DIB, four settings are 0, one is repeated.

Cheng Form 15-2 showdib1 displays DIB by using the SetDibitStodevice function.

Cheng Form 15-2 Showdib1Showdib1.c / * ----------------------------------------- --------------------------- Showdib1.c - shows a dib in the client area (c) Charles Petzold, 1998 --- -------------------------------------------------- ---------------- * /

#include #include "dibfile.h" #include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "ShowDib1"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HACCEL hAccel; HWND hwnd; MSG msg WNDCLASS WNDCLASS;

wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); WNDCLASS.HBRBACKGROUND = (Hbrush) getStockObject (white_brush); WNDCLASS.LPSZMENUNAME = SZAPPNAME; WNDCLASS.LPSZCLASSNAME = szAppname;

if {MessageBox (NULL, TEXT ( "This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0;} (RegisterClass (& wndclass)!) hwnd = CreateWindow (szAppName, TEXT ( "Show DIB # 1"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, HINSTANCE, NULL

ShowWindow (hwnd, icmdshow); UpdateWindow (HWND);

hAccel = LoadAccelerators (hInstance, szAppName); while (GetMessage (& msg, NULL, 0, 0)) {if {TranslateMessage (& msg) (TranslateAccelerator (hwnd, hAccel, & msg)!); DispatchMessage (& msg);}} return msg .wpaham;

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static BITMAPFILEHEADER * pbmfh; static BITMAPINFO * pbmi; static BYTE * pBits; static int cxClient, cyClient, cxDib, cyDib; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; BOOL BSUCCESS; HDC HDC; PAINTSTRUCT PS;

Switch (Message) {Case WM_CREATE: DibfileInitialize (hwnd); Return 0;

Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0;

Case WM_INITMENUPOPUP: EnableMenuItem ((HMENU) WPARAM, IDM_FILE_SAVE, PBMFH? MF_ENABED: MF_GRAYED; RETURN 0;

Case WM_Command: Switch (WPARAM) {CASE IDM_FILE_Open: // show the file open dialog box

IF (! DibfileOpendlg (hwnd, szfilename, sztitlename) Return 0; //iff there's an existing dib, free the memory

IF (PBMFH) {free (PBMFH); PBMFH = null;} // load the entire dib Into Memory

SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE);

PBMFH = DibloadImage (SZFileName); Showcursor (false); setcursor (loadcursor (null, idc_arrow);

// invalidate the client area for latter Update

InvalidateRect (HWND, NULL, TRUE);

IF (PBMFH == NULL) {MessageBox (HWND, Text ("Cannot Load Dib file"), SZAPPName, 0); Return 0;} // Get Pointers to the info structure & the bitspbmi = (BitmapInfo *) (PBMFH 1); PBITS = (Byte *) PBMFH PBMFH-> bfoffbits;

// Get the Dib Width and Height

if (pbmi-> bmiHeader.biSize == sizeof (BITMAPCOREHEADER)) {cxDib = ((BITMAPCOREHEADER *) pbmi) -> bcWidth; cyDib = ((BITMAPCOREHEADER *) pbmi) -> bcHeight;} else {cxDib = pbmi-> Bmiheader.biwidth; cydib = abs (pbmi-> bmiheader.biheight);} return 0;

Case idm_file_save: // show the file save dialog box

IF (! dibfilesavedlg (hwnd, szfilename, sztitlename) Return 0; // save the dib to memory

SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE);

Bsuccess = dibsaveImage (SZFileName, PBMFH); showcursor (false); setcursor (loadcursor (null, idc_arrow);

IF (! bsuccess) MessageBox (HWnd, Text ("Cannot Save Dib File"), Szappname, 0); Return 0;} Break

Case WM_Paint: HDC = BeginPaint (HWND, & PS);

IF (PBMFH) SetDibitStodevice (HDC, 0, // xdst0, // ydstcxdib, // cxsrccydib, // cysrc0, // xsrc0, // ysrc0, //first scan linecydib, // number of scan linespbits, pbmi, dib_rgb_colors ); EndPaint (hwnd, & ps); return 0; case wm_destroy: IF (PBMFH) Free (PBMFH);

Postquitmessage (0); return 0;} return defWindowProc (hwnd, message, wparam, lparam);} dibfile.h / * ----------------------- -------------------------------------------------- Dibfile.h - Header File for Dibfile.c --------------------------------------- ------------------------------ * / void DibfileInitialize (HWND HWND); BOOL DIBFILEOPENDLG (HWND HWND, PTSTR PSTRFILENAME, PTSTR pstrTitleName); BOOL DibFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName); BITMAPFILEHEADER * DibLoadImage (PTSTR pstrFileName); BOOL DibSaveImage (PTSTR pstrFileName, BITMAPFILEHEADER *); DIBFILE.C / * ---------- -------------------------------------------------- --------------- Dibfile.c - DIB File functions --------------------------- ------------------------------------------------------------------- * /

#include #include #include "dibfile.h"

Static OpenFileName OFN; Void DibfileInitialize (hwnd hwnd) {static tchar szfilter [] = text ("Bitmap files (* .bmp) / 0*.bmp/0") / text ("all files (*. *) / 0 * . * / 0/0 "); ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn. nFilterIndex = 0; ofn.lpstrFile = NULL; // Set in Open and Close functionsofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = NULL; // Set in Open and Close functionsofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn. LPSTRTILE = 0; // set in open and close functionSofn.nfileoffset = 0; off.nfileextension = 0; off.lpstrdeFext = text ("bmp"); OFN.LCUSTDATA = 0; OFN.LPFNHOOK = NULL; ofn.lpTemplateName = NULL;} BOOL DibFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) {ofn.hwndOwner = hwnd; ofn.lpstrFile = pstrFileName; ofn.lpstrFileTitle = pstrTitleName; ofn.Flags = 0; return GetOpenFileName (& ofn }} Bool Dibfilesavedlg (H WND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) {ofn.hwndOwner = hwnd; ofn.lpstrFile = pstrFileName; ofn.lpstrFileTitle = pstrTitleName; ofn.Flags = OFN_OVERWRITEPROMPT; return GetSaveFileName (& ofn);}

BitmapfileHeader * DibloadImage (PTSTR PStrfilename) {Bool Bsuccess; DWORD DWFILESIZE, DWHIGHSIZE, DWBYTESREAD; Handle Hfile; BitmapFileHeader * PBMFH;

Hfile = Createfile (pstrfilename, generic_read, file_share_read, null, open_existing, file_flag_sequential_scan, null);

IF (hfile == invalid_handle_value) Return NULL;

DWFILESIZE = GetFileSize (Hfile, & dwhight);

IF (dwhight) {closeHandle (HFILE); RETURN NULL;} PBMFH = malloc (dwfilesis); if (! pbmfh) {closeHandle (HFILE); Return null;}

Bsuccess = readfile (HFile, PBMFH, DWFILESIZE, & DWBYTESREAD, NULL); CloseHandle (HFILE);

IF (! BSuccess || (dwbytesRead! = dwfilesize) || (PBMFH-> BFTYPE! = * (Word *) "BM") || (PBMFH-> BFSIZE! = dwfilesize) {free (PBMFH); Return Null } return pbmfh;}

Bool DibsaveImage (PTSTR PSTRFILENAME (BitmapfileHeader * PBMFH) {BOOL BSUCCESS; DWORD DWBYTESWRITEN; Handle Hfile

Hfile = cretefile (pstrfilename, generic_write, 0, null, create_always, file_attribute_normal, null);

IF (HFILE == Invalid_Handle_Value) Return False; bsuCcess = Writefile (HFILE, PBMFH, PBMFH-> BFSIZE, & DWBYTESWRITEN, NULL); CloseHandle (HFILE);

if (bSuccess || (dwBytesWritten = pbmfh-> bfSize)!!) {DeleteFile (pstrFileName); return FALSE;} return TRUE;.} SHOWDIB1.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource. H "#include" afxres.h "

/// MenuSHOWDIB1 MENU DISCARDABLE BEGINPOPUP "& File" BEGINMENUITEM "& Open ...", IDM_FILE_OPENMENUITEM "& Save ...", IDM_FILE_SAVEENDENDRESOURCE.H (excerpt) // Microsoft Developer Studio generated include file.// Used by ShowDib1.rc

#define idm_file_open 40001 # Define IDM_File_Save 40002Dibfile.c file contains a common style that displays the "File Open" and "File Save" dialogue, and the entire DIB file (with BitmapFileHeader structure) to the single memory block. The program will also write such a memory area to the file.

When the "File Open" command is executed in ShowDib1.c Enter the DIB file, the offset of the BitmapInfoheader structure and the icon element in the program is calculated in the program, and the program is also obtained by DIB's icing width and height. All information is stored in static variables. During the processing of WM_PAINT messages, the program is displayed by calling SetDibitStodevice.

Of course, ShowDIB1 lacks some functions. For example, if DIB is too large for the display area, no roll column can be used to move viewing. These defects will be modified at the end of the next chapter. Dib's reverse world

We will get an important lesson that is not only important in life, but also is also important in the design of the application interface of the operating system. This lesson is: it is difficult to cover water.

Back to OS / 2 Presentation Manager, the definition of the lower DIB icon, such definition is a bit reason, because any seat system within the PM has a fixed top left corner origin. For example: In the PM window, the internal (0, 0) origin is the upper left corner of the window. (If you think this is very quirky, many people feel like you feel. If you don't think weird, then you might be a mathematician.) The drawing of the dot matrix is ​​also specified according to the destination according to the lower left corner.

Therefore, if the destination coordinate (0,0) is specified within OS / 2, the image will be displayed from the lower left corner of the window to the right, as shown in Figure 15-1.

Figure 15-1 Dot matrix shown in (0,0) in OS / 2

On a suggested machine, you can actually see the computer by the downward drawings.

Although the OS / 2 coordinate system is very quirky, its advantages are highly consistent. The origin of the (0,0) origin of the dot matrix is ​​the first set of the first line in the dot matrix map, and this graph is mapped to the destination coordinates specified in the dot matrix drawing.

The problem with Windows does not maintain internal consistency. When you display a small number of rectangles throughout the DIB image, use parameters XSRC, YSRC, CXSRC, and CysRC. These source coordinates and size are related to the first row of DIB data (the last line of images). This is similar to OS / 2, unlike OS / 2, Windows displays the top column of the image on the destination coordinator. Therefore, if the entire DIB image is displayed, the icon shown in (xDST, YDST) is a chamber located at the coordinate (0, CYDIB - 1). The last column of the DIB data is the top column of the graph. If only part of the image is displayed, the icon displayed in (xDST, YDST) is a DIB icon located at the coordinate (XSRC, YSRC CYSRC - 1).

Figure 15-2 shows the charts will help you understand the content of this. You can use the DIB shown below as a storage in the memory - that is, upside down. The origin of the coordinate is consistent with the first bit of DIB iconic information. SetDibitStodevice's XSRC parameter is based on the left side of DIB, and CXSRC is the image width on the right side of XSRC, which is very intuitive. The YSRC parameter is based on the first column of DIB (that is, the bottom of the image), and the CysRC is an image height from the end of YSRC to the end of the data (the top of the image).

Figure 15-2 Jobs of normal DIB (from below)

If the destination device has a relationship between the rectangular icon using the MM_Text mapping method, the relationship between the source rectangle and the destination rectangular corner session is shown in Table 15-3.

Table 15-3

Source Rectangle Destination Rectangle (XSRC, YSRC) (XDST, YDST CYSRC - 1) (XSRC CXSRC - 1, YSRC) (XDST CXSRC - 1, YDST CysRC - 1) (XSRC, YSRC CYSRC - 1) ( XDST, YDST) (XSRC CXSRC - 1, YSRC CYSRC - 1) (XDST CXSRC - 1, YDST)

(XSRC, YSRC) is not mapped to (XDST, YDST), making the form look very confusing. In other mapping methods, points (XSRC, YSRC CYSRC - 1) are always mapped to logical points (XDST, YDST), the image is also the same as MM_Text. So far, we discuss the normal situation when the Biheight field of the BitmapInfoHeader structure is positive. If the BiHeight field is negative, the DIB data will be arranged in a reasonable scripture. You may think that this will solve all problems, if you think so, then you are wrong.

Obviously, someone thinks if the DIB is upside down, rotate each row, then set a positive value for Biheight, which will operate like normal by the lower DIB, all the existing code related to the DIB rectangle Do not have to be modified. I think this is a reasonable purpose, but it has forgotten a fact that the program needs to be modified to handle the Dib, so it will not use a negative height.

Moreover, the result of this decision means that there is an origin by the last column of the Source of the top DIB on the DIB data, which is also the base of the image. This is completely different from what we encounter. DIB icon in (0) origin is no longer the first primitive reference to the PBITS indicator, nor is the last set of the DIB file, which is located between the two.

Figure 15-3 The chart shown illustrates a method of specifying a rectangle in the top DIB, and it is stored in a file or memory.

Figure 15-3 Specifies the coordinate of the top-down DIB

In any case, the actual advantage of this program is that the parameters of the setDibitstodevice function are independent of the direction of the DIB data. If there is two DIBs shown in the same image (one by the bottom, the other is upward. Indicates the column order in the two DIB files), you can use the same parameter call setDibitStodevice to select the display image The same part.

As shown in the formula 15-3 Apollo11.

Program 15-3 apollo11apollo11.c / * ----------------------------------------- -------------------------------- Apollo11.c - Program for Screen Captures (C) Charles Petzold, 1998 - -------------------------------------------------- ------------------ * /

#include #include "dibfile.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "Apollo11"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HWND hwnd; MSG msg; WNDCLAS wndclass ;

wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName;! if (RegisterClass (& wndclass)) {MessageBox (NULL, TEXT ( "This program requires Windows NT! "), szAppName, MB_ICONERROR); return 0;} hwnd = CreateWindow (szAppName, TEXT (" Apollo 11 "), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

ShowWindow (hwnd, icmdshow); UpdateWindow (HWND);

While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);} return msg.wparam;}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static BITMAPFILEHEADER * pbmfh [2]; static BITMAPINFO * pbmi [2]; static BYTE * pBits [2]; static int cxClient, cyClient, cxDib [2 ], Cydib [2]; HDC HDC; PaintStruct PS;

Switch (Message) {case wm_create: PBMFH [0] = DibloadImage ("apollo11.bmp")); PBMFH [1] = DibloadImage ("apollotd.bmp"));

IF (PBMFH [0] == NULL || PBMFH [1] == null) {MessageBox (hwnd, text ("cannot loading dib file"), szappname, 0); return 0;} // Get Pointers to the info Structure & the bits

PBMI [0] = (BitmapInfo *) (PBMFH [0] 1); PBMI [1] = (BitmapInfo *) (PBMFH [1] 1); PBITS [0] = (Byte *) PBMFH [0] PBMFH [0] -> bfoffbits; pbits [1] = (byte *) PBMFH [1] PBMFH [1] -> bfoffbits;

// get the dib width and height (assume bitmapinfoheader) // Note That cydib is the Absolute value of the header value !!! cxdib [0] = pbmi [0] -> bmiheader.biwidth; cxdib [1] = PBMI [ 1] -> bmiheader.biwidth;

Cydib [0] = ABS (PBMI [0] -> bmiheader.biheight); Cydib [1] = ABS (PBMI [1] -> bmiheader.biheight); Return 0;

Case WM_SIZE: CXClient = Loword (LPARAM); cyclient = HiWord (LPARAM); Return 0; Case WM_Paint: HDC = BeginPaint (HWND, & PS);

// bottom-up dib full size

SetDibitStodevice (HDC, 0, // xdstcyclient / 4, // ydstcxdib [0], // cxsrccydib [0], // cysrc0, // xsrc0, // ysrc0, // first scan linecydib [0], // number er Of scan linespbits [0], pbmi [0], dib_rgb_colors);

// bottom-up DIB Partial

SetDibitStodevice (HDC, 240, // xdstcyclient / 4, // ydst80, // cxsrc166, // cysrc80, // xsrc60, // ysrc0, //first scan linecydib [0], // number of scan linespbits [0] , PBMI [0], DIB_RGB_COLORS;

// Top-down Dib Full Size

SetDibitStodevice (HDC, 340, // xdstcyclient / 4, // ydstcxdib [0], // cxsrccydib [0], // cysrc0, // xsrc0, // ysrc0, //first scan linecydib [0], // number Of scan linespbits [0], pbmi [0], dib_rgb_colors);

// Top-down Dib Partial

SetDibitStodevice (HDC, 580, // xdstcyclient / 4, // YDST80, // cxsrc166, // cysrc80, // xsrc60, // ysrc0, // number scan linecydib [1], // number of scan linespbits [1] , PBMI [1], DIB_RGB_COLORS;

Endpaint (hwnd, & ps); Return 0; Case WM_DESTROY: IF (PBMFH [0]) Free (PBMFH [0]); if (PBMFH [1]) Free (PBMFH [1]);

PostquitMessage (0); Return 0;} Return DefWindowProc (HWND, Message, WPARAM, LPARAM);} The program is loaded with apollo11.bmp (from bottom to version) and apollotd.bmp (by top and bottom version) Two DIBs. They are all 220 primers wide and 240 primers. Note that when the width and height of the DIB is determined from the header information structure, it uses the ABS to get the absolute value of the BiHeight field. When DIB is displayed in all sizes or scope, the XSRC, YSRC, CXSRC, and CysRC coordinations are the same regardless of the type of display point array. The results are shown in Figure 15-4. Figure 15-4 Screen display of Apollo11

Note that the "first scanning line" and "number of scan lines" parameters remain unchanged, I will tell later. The PBITS parameter is not changed, do not try to change PBITS just to point to the area you need to display.

I spent so many times in this question, not because I have to try some compromises that have problems with the API definition, but I want you not to be nervous because of this confusing issue. stand up. This problem is confusing because it has been confused.

I also want you to pay attention to some of the narratives in the Windows file, such as the SETDIBITSTODEVICE, the file saying: "The origin of the down DIB is the bottom left corner of the dot matrix; the origin of the top Dib is the upper left corner". This is not only blurred, but also wrong. I can use a better way to describe: The origin of the lower DIB is the upper left corner of the dot matrix image, which is the first primitive of the first column of the dot matrix. The origin of the upper and lower DIB is also the lower left corner of the dot matrix image, but in this case, the lower left corner is the first primitive of the last column of the dot matrix data.

If you want to write a function of accessing DIB individual yuan, the problem will change worse. This should be consistent with the coordinates you specified for the display section DIB mapping, and my solution is (I will use it in the DIB program library in Chapter 16) to refer to DIB and coordinates, just like When the image is correctly displayed (0,0) origin, it is the leftmost chamber of the DIB image.

Sequentially display

It has a large number of memory to make sure the program is more easily performed. To display DIB in the magnetic file, you can divide two separate work: load DIB into the memory and display it.

However, you may also display DIB without loading the entire archive into the memory. Even if there is enough entity memory to DIB, move the DIB into the memory will also force Windows virtual memory system to shift other data and program codes in the memory to the magnetic sheet. This is very annoying if DIB is only used to display and immediately eliminate it.

There is another problem: assuming that the DIB is located on a slow storage medium such as a floppy disc, or is transmitted by the data machine, or a conversion common to the scanner or video interception. Do you have to wait until the entire DIB is loaded into the memory? Start when you get DIB from a magnetic or telephone line or scanner?

Solving these issues is the purpose of the YSCAN and CysCans parameters in the setDibitStodevice function. To use this feature, you need to call SetDibitStodevice multiple times, in most cases the same parameters. However, for each call, the PBITS parameter points to the different parts of the overall arrangement of the point graph chart. The YSCANS parameter indicates the line of PBITS points to the primary, and the CysCans parameter is the number of rows referenced by PBITS. This has reduced memory requirements. You only need to configure enough memory to store DIB information section (BitmapInfoHeader structure and color control table) and at least one line of status.

For example, suppose DIBs have 23 lines, you want to display this DIB each time you up to 5 lines. You may want to configure a memory block referenced by variable PINFO to store the DIB's BitmapInfo section, then read the DIB from the file. After checking the field of this structure, the bit element group length can be calculated. Multiply another memory block (PBITS) that is configured with this size. Now read the top 5 lines, call your normal use, set the YSCAN to 0, set the CysCans to 5. Now the next 5 lines are read from the file. This time sets the YSCAN to 5, continue to set the YSCAN to 10, and then 15. Finally, read the last 3 line to the memory block pointing to the PBITS, and set the YSCAN to 20, set CysCans to 3 to call SetDibitStodevice. There is a bad message now. First, this feature of this feature of SETDIBITSTODEVICE is quite closely integrated and the data display element is combined. This is usually not ideal because you must switch between getting data and display data. First, you will delay the entire program; Second, SetDibitStodevice is the only dot matrix showing this feature. The StretchDibits function does not include this feature, so you cannot use it to display the published DIB with different icons size. You must call STRETCHDIBITS multiple times, change the information in the BitmapInfoHeader structure each time, and display results on different regions of the screen.

Cheng Form 15-4 SEQDISP shows how this function is used.

Cheng Form 15-4 seqdispseqdisp.c / * ----------------------------------------- ----------------------------------- Seqdisp.c - sequential display of dibs (c) Charles Petzold, 1998 ------------------------------------- ---------------------------- * /

#include #include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "SeqDisp"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HACCEL hAccel; HWND hwnd; MSG msg WNDCLASS WNDCLASS;

wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); WNDCLASS.HBRBACKGROUND = (Hbrush) getStockObject (white_brush); WNDCLASS.LPSZMENUNAME = SZAPPNAME; WNDCLASS.LPSZCLASSNAME = szAppname;

if {MessageBox (NULL, TEXT ( "This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0;} (RegisterClass (& wndclass)!) hwnd = CreateWindow (szAppName, TEXT ( "DIB Sequential Display"), WS_OVERLAPPEDWINDOW , CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); hAccel = LoadAccelerators (hInstance, szAppName); while (GetMessage (& msg, NULL, 0, 0 )) {if (! "}; translateMessage (& MSG); DispatchMessage (& MSG);}} Return Msg.wParam;

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static BITMAPINFO * pbmi; static BYTE * pBits; static int cxDib, cyDib, cBits; static OPENFILENAME ofn; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH] static tchar szfilter [] = text ("Bitmap files (* .bmp) / 0*.bmp/0") Text ("All Files (*. *) / 0 *. * / 0/0"); BitmapFileHeader BMFH ; BOOL bSuccess, bTopDown; DWORD dwBytesRead; HANDLE hFile; HDC hdc; hMENU hMenu; int iInfoSize, iBitsSize, iRowLength, y; PAINTSTRUCT ps; switch (message) {case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName ; OFN.LPSTRINTILALDIR = NULL; OFN.LPSTRTILALDIR = NULL; OFN.LPSTRTILE = NULL; OFN.FLAGS = 0; OFN.NFILEOFFSET = 0; OFN.NFILEEXTENSION = 0; OFN.LPSTRDEFEXT = TEXT ("BMP"); OFN. LCUSTDATA = 0; OFN.LPFNHOOK = NULL; OFN.LPTEMPLATENAME = NULL; RETURN 0; Case WM_COMMAND: HMENU = GetMenu (hwnd);

Switch (loword (wparam)) {copy IDm_file_open: // display file open dialogif (! getopenfilename (& off)) Return 0;

// Get Rid of Old DIB

IF (PBMI) {free (PBMI); PBMI = NULL;}

IF (PBITS) {Free (PBITS); PBITS = NULL;

// generate WM_Paint Message To Erase Background

INVALIDATERECT (HWND, NULL, TRUE); UpdateWindow (HWND);

// Open the file

Hfile = createfile (szfilename, generic_read, file_share_read, null, open_existing, file_flag_sequential_scan, null);

IF (HFILE == Invalid_Handle_Value) {MessageBox (HWND, Text ("Cannot Open File."), SZAppName, MB_ICONWARNING | MB_OK; RETURN 0;} // read in the bitmapfileHeader

Bsuccess = readfile (HFile, & BMFH, Sizeof (BitmapfileHeader), & DWBYTESREAD, NULL

IF (! Bsuccess || dwbytesread! = sizeof (bitmapfileHeader)) {MessageBox (HWND, Text ("Cannot Read File."), Szappname, MB_ICONWARNING | MB_OK); CloseHandle (HFILE);}

// Check That it's a bitmap

IF (BMFH.BFTYPE! = * (Word *) "BM") {MessageBox ("File IS Not A Bitmap."), SZAPPNAME, MB_ICONWARNING | MB_OK); CloseHandle (HFILE); Return 0;}

// Allocate Memory for Header and Bits

IINFOSIZE = BMFH.BFOFFBITS - SIZEOF (BitmapfileHeader); ibitsize = bmfh.bfsize - bmfh.bfoffbits;

PBMI = Malloc (IINFSIS); PBITS = Malloc (ibitsize);

IF (PBMI == Null || PBITS == NULL) {MessageBox ("cannot Allocate Memory."), SZAPPNAME, MB_ICONWARNING | MB_OK); IF (PBMI) Free (PBMI); if (PBITS) Free PBISEHANDLE (HFILE); RETURN 0;}

// read in the information header

Bsuccess = readfile (Hfile, PBMI, IINFOSIZE, & DWBYTESREAD, NULL);

IF (! bsuccess || (int) dwbytesread! = iinfosize) {MessageBox (HWND, Text ("Cannot Read file."), SZAPPNAME, MB_ICONWARNING | MB_OK); IF (PBMI) Free (PBMI); if (PBITS) Free (PBISEHANDE (HFILE); RETURN 0;}

// Get the Dib Width and Height

Btopdown = false;

if (pbmi-> bmiHeader.biSize == sizeof (BITMAPCOREHEADER)) {cxDib = ((BITMAPCOREHEADER *) pbmi) -> bcWidth; cyDib = ((BITMAPCOREHEADER *) pbmi) -> bcHeight; cBits = ((BITMAPCOREHEADER *) pbmi ) -> bcBitCount;} else {if (pbmi-> bmiHeader.biHeight <0) bTopDown = TRUE; cxDib = pbmi-> bmiHeader.biWidth; cyDib = abs (pbmi-> bmiHeader.biHeight); cBits = pbmi-> bmiHeader .biBITCOUNT;

if (!! pbmi-> bmiHeader.biCompression = BI_RGB && pbmi-> bmiHeader.biCompression = BI_BITFIELDS) {MessageBox (hwnd, TEXT (), szAppName, MB_ICONWARNING | MB_OK "File is compressed."); if (pbmi) free (pbmi ); if (pBITS); closehandle (hfile); return 0;}} // Get the row length

IrowLength = ((CXDIB * CBITS 31) & ~ 31) >> 3;

// read and DisplaySetCursor (loadcursor (null, idc_wait); showcursor (true);

HDC = Getdc (hwnd);

For (y = 0; y

Case WM_Paint: HDC = BeginPaint (HWND, & PS);

IF (PBMI && Pbits) setDibitStodevice (HDC, 0, // xdst0, // ydstcxdib, // cxsrccydib, // cysrc0, // xsrc0, // ysrc0, //first scan linecydib, // number of scan linespbits, dib_rgb_colors ); EndPaint (hwnd, & ps); Return 0; Case WM_DESTROY: IF (PBMI) Free (PBITS) FREE (PBITS);

PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} SEQDISP.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. "/// AcceleratorseqDisp Accelerators Discardable Begin" O ", IDM_FILE_OPEN, VIRTKEY, Control, NOINVERTEND

/// MenuSEQDISP MENU DISCARDABLE BEGINPOPUP "& File" BEGINMENUITEM "& Open ... / tCtrl O", IDM_FILE_OPENENDENDRESOURCE.H (excerpt) // Microsoft Developer Studio generated include file.// Used by SeqDisp.rc

#define idm_file_open 40001 During the Processing "File Open" function table, all file I / O in SeqDisp.c will happen. At the end of processing WM_COMMAND, the program enters the read single line icon and uses setDibitStodevice to display the ring circle of the row. The entire DIB is stored in the memory to display it during processing WM_PAINT.

Zoom to the appropriate size

SetDibitStodevice completes the display program that gives DIB's statue to the output device. This is not large for the printing DIB. The higher the parser of the printing machine, the smaller the image obtained, and you will eventually get an image such as a stamp size.

To display it on the output device by narrowing or enlargeing DIB, you can use StretchDibits:

iLines = StretchDIBits (hdc, // device context handlexDst, // x destination coordinateyDst, // y destination coordinatecxDst, // destination rectangle widthcyDst, // destination rectangle heightxSrc, // x source coordinateySrc, // y source coordinatecxSrc, // source rectangle widthcySrc, // source rectangle heightpBits, // pointer to DIB pixel bitspInfo, // pointer to DIB informationfClrUse, // color use flagdwRop); // raster operation function in addition to the following three parameters are the same as SetDIBitsToDevice.

The destination coordinates include logical width (CxDST) and height (Cydst), and start points. The memory needs cannot be reduced by continuous display DIB. The last parameter is a bit element mapping operation mode, which points out how the DIB icon is combined with the output device, which will learn these content in the last chapter. Now we are set to Srccopy for this parameter. There is another thinner difference. If you look at the declaration of SetDibitStodevice, you will find that CXSRC and CysRC are DWORD, this is a 32-bit dollar without a negative intensity. In StretchDibits, CXSRC and Cysrc (and CXDST and CYDST) are defined as integers with positive negative, which means they can be negative, and they will be seen, they can do it. Negative numbers. If you have started to check if other parameters can be negative, let me declare that in two functions, XSRC and YSRC are defined as int, but this is wrong, which is always non-negative. Source rectangles in the DIB are mapped to the destination rectangle, as shown in Table 15-4.

Table 15-4

Source rectangular rectangle (XSRC, YSRC) (XDST, YDST CYDST - 1) (XSRC CXSRC - 1, YSRC) (XDST CXDST - 1, YDST CYDST - 1) (XSRC, YSRC CYSRC - 1) ( XDST, YDST (XSRC CXSRC - 1, YSRC CYSRC - 1) (XDST CXDST - 1, YDST)

The -1 item in the right column is inaccurate because the degree of magnification (and the mapping method and other transformation) can produce a slight different result.

For example, consider a 2 × 2 DIB, where the XSRC and YSRC parameters of StretchDibits are 0, and CXSRC and CysRC are 2. Assuming that the contents of the device we have displayed have a mm_text mapping method and does not transform. If XDST and YDST are 0, CXDST and CYDST are 4, then we will enlarge DIB in multiple 2. Each Source Thermostat (X, Y) will be mapped to the four destination elements shown below:

(0, 0) -> (0, 2) AND (0, 3) AND (1, 3) (1, 0) -> (2, 2) AND (3, 2) AND (2, 3) and (3, 3) -> (0, 0) AND (1, 0) AND (0, 1) AND (1, 1) (1, 1) - > (2, 0) AND (3, 0) and (2, 1) and (3, 1) The above table correctly points out the angle of the purpose, (0, 3), (3, 3), (0,0 ) And (3, 0). In other cases, the coordinate may be a big sum.

The impact of the purpose of the device content on SetDibitStodevice is only because XDST and YDST are logical hosts. StretchDibits is fully affected by the mapping. For example, if you set a metric mapping mode increment upward, DIB will reverse it.

You can make up for this situation by setting CyDST to negative numbers. In fact, you can turn the width and height of any parameters to a negative value to flip the DIB level or vertically. In MM_TEXT mapping mode, if the CysRC and CYDST symbols, DIB flips along the horizontal axis and reverse the display. If the CXSRC and CXDST symbols are reversed, DIB flips and displays its mirror images along the vertical axis.

Below is a summary of the arithmetic formula, XMM and YMM indicating the mapping mode, and if the X value increases to the right, the XMM value is 1; if the X value grows to the left, the value is -1. Similarly, if the Y value grows down, the YMM value is 1; if the Y value increases upward, the value is -1. The SIGN function returns to Ture for positive values. IF (! SIGN (XMM × CXSRC × CXDS) DIB IS Flipped on Its Vertical Axis (Mirror Image) IF (! Sign (YMM × Cysrc × Cydst) DIB IS Flipped on Its Horizontal Axis (Upside Down) If you have any questions, Check out Table 15-4.

Cheng Form 15-5 showDIB displays DIB in an actual size, enlarges to the size of the display area window, the print DIB, and transfer DIB to the scrapbook.

Co-style 15-5 showdibshowdib2.c / * ----------------------------------------- --------------------------------- Showdib2.c - shows a dib in the client area (c) Charles Petzold 1998 ------------------------------------------------ --------------------------- * /

#include #include "dibfile.h" #include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName [] = TEXT ( "ShowDib2"); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {HACCEL hAccel; HWND hwnd; MSG msg ; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); WNDCLASS.HBRBACKGROUND = (HBrush) getStockObject (White_brush); WNDCLASS.LPSZMENUNAME = SZAPPNAME; WNDCLASS.LPSZCLASSNAME = Szappname;

IF (! RegisterClass (& Wndclass)) {MessageBox (Null, Text ("This Program Requires Windows NT!"), SZAPPNAME, MB_ICONERROR); RETURN 0;}

hwnd = CreateWindow (szAppName, TEXT ( "Show DIB # 2"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd);

hAccel = LoadAccelerators (hInstance, szAppName); while (GetMessage (& msg, NULL, 0, 0)) {if {TranslateMessage (& msg) (TranslateAccelerator (hwnd, hAccel, & msg)!); DispatchMessage (& msg);}} return msg .wpaham;

int ShowDib (HDC hdc, BITMAPINFO * pbmi, BYTE * pBits, int cxDib, int cyDib, int cxClient, int cyClient, WORD wShow) {switch (wShow) {case IDM_SHOW_NORMAL: return SetDIBitsToDevice (hdc, 0, 0, cxDib, cyDib , 0, 0, 0, Cydib, PBIS, PBMI, DIB_RGB_COLORS; CASE IDM_SHOW_CENTER: RETURN SETDIBITSTODEVICE (HDC, CXClient - CXDIB) / 2, (Cyclient - Cydib) / 2, CXDIB, CYDIB, 0, 0, 0, CYDIB, PBITS, PBMI, DIB_RGB_COLORS;

Case IDM_SHOW_STRETCH: SetStretchBltmode (HDC, Coloroncolor); Return Stretchdibits (HDC, 0, 0, CxClient, Cyclient, 0, 0, CXDIB, Cydib, Pbits, PBMI, DIB_RGB_COLORS, SRCCPY);

case IDM_SHOW_ISOSTRETCH: SetStretchBltMode (hdc, COLORONCOLOR); SetMapMode (hdc, MM_ISOTROPIC); SetWindowExtEx (hdc, cxDib, cyDib, NULL); SetViewportExtEx (hdc, cxClient, cyClient, NULL); SetWindowOrgEx (hdc, cxDib / 2, cyDib / 2 , NULL); SetViewPortorgex (HDC, CXClient / 2, Cyclient / 2, NULL);

Return Stretchdibits (HDC, 0, 0, CXDIB, CYDIB, 0, 0, CXDIB, CYDIB, PBITS, PBMI, DIB_RGB_COLORS, SRCCPY);}}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static BITMAPFILEHEADER * pbmfh; static BITMAPINFO * pbmi; static BYTE * pBits; static DOCINFO di = {sizeof (DOCINFO), TEXT ( "ShowDib2: Printing") }; static int cxClient, cyClient, cxDib, cyDib; static PRINTDLG printdlg = {sizeof (PRINTDLG)}; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; static WORD wShow = IDM_SHOW_NORMAL; BOOL bSuccess; HDC hdc, hdcPrn; HGLOBAL HGlobal; HMenu Hmenu; int CXPAGE, CYPAGE, IENABLE; PAINTSTRUCT PS; BYTE * PGLOBAL; SWITCH (MSSAGE) {Case WM_CREATE: DIBFILEINIALIZE (HWND); RETURN 0;

Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0;

Case WM_INITMENUPOPUP: HMENU = GetMenu (HWND);

INABLE = MF_ENABLED; Elseienable = mf_grayed;

EnableMenuItem (hMenu, IDM_FILE_SAVE, iEnable); EnableMenuItem (hMenu, IDM_FILE_PRINT, iEnable); EnableMenuItem (hMenu, IDM_EDIT_CUT, iEnable); EnableMenuItem (hMenu, IDM_EDIT_COPY, iEnable); EnableMenuItem (hMenu, IDM_EDIT_DELETE, iEnable); return 0;

Case WM_COMMAND: HMENU = GetMenu (HWND);

Switch (loword (wparam) {copy idm_file_open: // show the file open dialog box

IF (! DibfileOpendlg (hwnd, szfilename, sztitlename) Return 0; // if there's an existing dib, free the memoryif (PBMFH) {free (PBMFH); PBMFH = null;} // load the entire dib Into Memory

SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE);

PBMFH = DibloadImage (SZFileName);

Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW);

// invalidate the client area for latter Update

InvalidateRect (HWND, NULL, TRUE);

if (pbmfh == NULL) {MessageBox (hwnd, TEXT ( "Can not load DIB file"), szAppName, MB_ICONEXCLAMATION | MB_OK); return 0;} // Get pointers to the info structure & the bitspbmi = (BITMAPINFO *) ( PBMFH 1); PBITS = (Byte *) PBMFH PBMFH-> bfoffbits;

// Get the Dib Width and Height

if (pbmi-> bmiHeader.biSize == sizeof (BITMAPCOREHEADER)) {cxDib = ((BITMAPCOREHEADER *) pbmi) -> bcWidth; cyDib = ((BITMAPCOREHEADER *) pbmi) -> bcHeight;} else {cxDib = pbmi-> Bmiheader.biwidth; cydib = abs (pbmi-> bmiheader.biheight);} return 0;

Case idm_file_save: // show the file save dialog box

IF (! dibfilesavedlg (hwnd, szfilename, sztitlename) Return 0; // save the dib to a disk file

SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE);

Bsuccess = DibsaveImage (SZFileName, PBMFH);

Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW);

IF (! bsuccess) MessageBox (HWND, Text ("Cannot Save Dib File", Szappname, MB_ICONEXCLAMATION | MB_OK); RETURN 0;

Case IDM_File_Print: if (! pbmfh) return 0;

// Get Printer DC

Printdlg.flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION;

IF (! Printdlg (& PrintDLG) Return 0;

IF (null == (hdcprn = printdlg.hdc)) {MessageBox (HWND, Text ("Cannot Obtain Printer DC"), Szappname, MB_ICONEXCLAMATION | MB_OK; RETURN 0;}

// Check Whather the Printer Can Print Bitmaps

if ((RC_BITBLT & GetDeviceCaps (hdcPrn, RASTERCAPS))!) {DeleteDC (hdcPrn); MessageBox (hwnd, TEXT ( "Printer can not print bitmaps"), szAppName, MB_ICONEXCLAMATION | MB_OK); return 0;} // Get size of Printable area of ​​page

CXPAGE = getDeviceCaps (HDCPRN, HORZRES); cypage = getDeviceCaps (HDCPRN, Vertres); bsuccess = false; // send the dib to the printer

SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE);

IF (STARTDOC (HDCPRN, & DI)> 0) && (SHOWDIB (HDCPRN, PBMI, PBITS, CXDIB, CYDIB, CXPAGE, CYPAGE, WSHOW); IF (Endpage (HDCPRN)> 0 ) {bsuccess = true; enddoc (hdcprn);}} showcursor (false); setcursor (NULL, IDC_ARROW);

Deletedc (HDCPRN);

IF (! bsuccess) MessageBox (HWND, Text ("Could Not Print Bitmap"), SZAPPNAME, MB_ICONEXCLAMATION | MB_OK; RETURN 0;

Case IDM_EDIT_COPY: CASE IDM_EDIT_CUT: IF (! PBMFH) Return 0;

// make a copy of the packed dib

Hglobal = GLOBALLOC (GHND | GMEM_SHARE, PBMFH-> BFSIZE --SIZEOF (BitmapfileHeader);

Pglobal = Globalock (Hglobal);

CopyMemory (pglobal, (byte *) PBMFH SIZEOF (BitmapfileHeader), PBMFH-> BFSIZE - SIZEOF (BitmapFileHeader);

GlobalUnlock (Hglobal);

// Transfer it to the clipboard

OpenClipboard (hwnd); EmptyClipboard (); setClipboardData (CF_DIB, HGLOBAL); CloseClipboard ();

if (LOWORD (wParam) == IDM_EDIT_COPY) return 0; // fall through if IDM_EDIT_CUT case IDM_EDIT_DELETE: if (pbmfh) {free (pbmfh); pbmfh = NULL; InvalidateRect (hwnd, NULL, TRUE);} return 0;

case IDM_SHOW_NORMAL: case IDM_SHOW_CENTER: case IDM_SHOW_STRETCH: case IDM_SHOW_ISOSTRETCH: CheckMenuItem (hMenu, wShow, MF_UNCHECKED); wShow = LOWORD (wParam); CheckMenuItem (hMenu, wShow, MF_CHECKED); InvalidateRect (hwnd, NULL, TRUE); return 0;} Break; Case WM_Paint: HDC = Beginpaint (HWND, & PS);

IF (PBMFH) Showdib (HDC, PBMI, PBITS, CXDIB, CYDIB, CXClient, Cyclient, WSHOW);

Endpaint (hwnd, & ps); RETURN 0; Case WM_DESTROY: IF (PBMFH) Free (PBMFH); PostquitMessage (0); Return 0;} Return DEFWINDOWPROC (HWND, Message, WParam, LParam);} showdib2.rc (excerp) // Microsoft Developer Studio generated resource script. # Include "resource.h" #include "afxres.h"

/// MenuSHOWDIB2 MENU DISCARDABLE BEGINPOPUP "& File" BEGINMENUITEM "& Open ... / tCtrl O", IDM_FILE_OPENMENUITEM "& Save ... / tCtrl S", IDM_FILE_SAVEMENUITEM SEPARATORMENUITEM "& Print / tCtrl P", IDM_FILE_PRINTENDPOPUP "& Edit" BEGINMENUITEM " Cu & t / tCtrl X ", IDM_EDIT_CUTMENUITEM" & Copy / tCtrl C ", IDM_EDIT_COPYMENUITEM" & Delete / tDelete ", IDM_EDIT_DELETEENDPOPUP" & Show "BEGINMENUITEM" & Actual Size ", IDM_SHOW_NORMAL, CHECKEDMENUITEM" & Center ", IDM_SHOW_CENTERMENUITEM" & Stretch to Window ", IDM_SHOW_STRETCHMENUITEM" Stretch & Isotropically ", IDM_SHOW_ISOSSTRETCHENDEND

/// AcceleratorSHOWDIB2 ACCELERATORS DISCARDABLE BEGIN "C", IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT "O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT "P", IDM_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT "S", IDM_FILE_SAVE, VIRTKEY, CONTROL, NOINVERTVK_DELETE, IDM_EDIT_DELETE, VIRTKEY, NOINVERT "X", IDM_EDIT_CUT, VIRTKEY, CONTROL, NOINVERTENDRESOURCE.H (excerpt) // Microsoft Developer Studio generated include file.// Used by ShowDib2.rc

#define IDM_FILE_OPEN 40001 # define IDM_SHOW_NORMAL 40002 # define IDM_SHOW_CENTER 40003 # define IDM_SHOW_STRETCH 40004 # define IDM_SHOW_ISOSTRETCH 40005 # define IDM_FILE_PRINT 40006 # define IDM_EDIT_COPY 40007 # define IDM_EDIT_CUT 40008 # define IDM_EDIT_DELETE 40009 # define IDM_FILE_SAVE 40010 Interestingly ShowDib function, it depends on The function table is selected to display the DIB in a four different way. You can display DIB from the top left corner of the display area or at the center of the display area. There are also two options that use StretchDibits, and DIB can enlarge the entire display area. In this case it may be deformed, or it can be displayed, that is, it will not be deformed. Copy DIB to the scrapbook includes: Copy the Packed Dib Memory Block in the overall shared memory. The scrapbook data is CF_DIB. The program does not list the method of copying DIB from the scrapbook because more steps are required to determine the offset of the icon in the case where there is only a metrics that point to the PACKED DIB. I will demonstrate how to do this at the end of the next chapter.

You may notice some of SHOWDIB2 some of the shortcomings. If you perform Windows in a 256-color display mode, you will see the problem that appears in addition to other graphics other than the monochrome or 4-bit dib, you can't see the true color. Access those colors need to use a palette, which will do these work in the next chapter. You may also pay attention to speed issues, especially when showdib2 is executed under Windows NT. In the next chapter, when Packed Dib and dot mapping, I will show the process. I also display the DIB to add a rolling column, which can also view DIBs larger than the screen with the actual size.

Color conversion, palette and display efficiency

I remember that in another movie script "All the President's Men" in Tiger Goldman, Deep Throat tells Bob Woodward to uncover the secret of the water door to "follow the money". The key to getting advanced performance in the dot matrix display is to "follow the icon dollar" and the timing of understanding color conversion. DIB is a format independent of the device, and the video display memory is almost always different from the chain format. During the SetDibitStodevice or StretchDibits Verslen Call, each status (may have millions of million) must be converted into the device-related format from the device.

In many cases, this conversion is very cumbersome. For example, a 24-bit element DIB is displayed on the 24-bit volatile display, and the display driving program is to switch red, green, and blue bit group order. The 16-bit dioss DIB is displayed on the 24-bit device, and the movement and trim of the bit element are required. 4-bit or 8-bit dibly DIB is displayed on the 24-bit device request to find the DIB icon in the DIB color control table, and then rearrange the bit element group.

But what happens when a 16-bit or 8-bit or 32-bit dib, a 4-bit or 8-bit video display? A completely different color conversion occurs. For each pattern in the DIB, the device driver must "find the closest color" between the color available on the chamber and the display, including the loop and calculation. (GDI letter GetnearestColor "closest to color search".)

The three-dimensional array of the entire RGB color can be represented by a cube. The distance between any two points in the curve is:

The two colors here are R1G1B1 and R2G2B2. Perform the closest color search includes the shortest distance from one color to other color sets. Fortunately, when the "compare" distance in the RGB color cube does not need to calculate the square root part. However, each of the needs to be converted must be compared to all the colors of the device to discover the closest color. This is a considerable work. (Although the 8-bit di Dib is displayed on the 8-bit device, it is also possible to perform the closest color search, but it does not have to do everything, it only needs to be found on each color of the Dib Color Converaints.) For the above reasons, the 16-bit, 24-bit or 32-bit DIB is displayed on the 8-bit metallographic display card using SetDibitStodevice or StretchDibits. DIB should be converted to 8-bit dib, or 8-bit ddb for better display performance. In fact, you can speed up the speed of displaying any DIB via converting DIB to DDB and using Bitblt and StretchBLT display images.

If Windows (or only switching to 8-bit element mode is performed on the 8-bit metallographic display), you may notice another question: DIB does not display all colors. Any DIB on the 8-bit emblem display is just limited in 20 colors. How to get more than 20 colors is the task of "Toner Disk Manager", which will be mentioned in the next chapter.

Finally, if Windows 98 and Windows NT are performed on the same machine, you may notice that for the same display mode, Windows NT shows that large DIB spends longer. This is the result of the client / server architecture of Windows NT, which allows a lot of information to take more time when transmitting to the API function. The solution is to convert DIB to DDB. And I will wait for the CREATEDIBSECTION card that will be talked particularly useful.

Binding to DIB and DDB

You can do many things to discover DIB's format and call two DIB drawing functions: SetDibitStodevice and StretchDibits. You can directly access the various bits, bit yuan groups, and icons in DIB, and once you have a plurality of functions that allow you to interpire and change your information in a structured manner, you have to handle Dib. Tube.

In fact, we have found some restrictions. In the previous chapter, we understand how to draw images on DDB using GDI. So far, there is no way to draw on DIB. Another problem is that setDibitStodevice and StretchDibits do not have Bitblt and StretchBLT speed, especially in the Windows NT environment, and perform many closest color searches (for example, display 24-bit DIB on the 8-bit vocal video card).

Therefore, the conversion between DIB and DDB is advantageous. For example, if we have a number of DIBs that need to display many times on the screen, it makes sense to convert DIB to DDB, so we can use fast Bitblt and StretchBLT functions to display it.

Establish DDB from DIB

Is it possible to establish a GDI dot matrix object from DIB? Basically we already know how to: If you have DIB, you can use CreateCompAMPLEBITMAP to establish the same GDI dot matrix object as the DIB size and compatible with the video display. Then, the dot matrix object is then selected into the memory device and call SetDibitStodevice draws on that memory DC. The result is that DDB has the same image as DIB, but has a color tissue compatible with the video display.

You can also complete the above work with several steps by calling createDibitmap. The syntax of the function is:

hbitmap = createdibitmap (HDC, // Device Context Handle

PinfoHDR, / / ​​POINTER TO DIB Information Headerfinit, // 0 or CBM_INITPBITS, / / ​​POINTER TO DIB PIXEL Bitspinfo, // Poin Dib InformationFclRuse; // Color Use Flag Please pay attention to PinfoHDR and PINFO these two parameters, they define In order to point to the BitmapInfoHeader structure and the BitmapInfo structure. As we know, the BitmapInfo structure is the BitmapInfoHeader structure that follows the color control table. We will see the role of this difference in a while. The last parameter is DIB_RGB_ Colors (equal to 0) or DIB_PAL_COLORS, which is used in the SetDibitStodevice function. Next chapter I will discuss more content in this regard. It is important to understand the role of dot mapping in WINDOWS. Do not consider the name of the CreatedIBitMap letter, it does not build a "devices independent dot matrix", which establishes "Device-related dot mapping" from the specification independent of the device. Note that the letter will return to the code of the GDI dot matrix, CreateBitmap, CreateBitMapIndirect and CreateCompatibleBitmap are the same as it.

The simplest method for calling createDibitmap functions is:

Hbitmap = createdibitmap (NULL, PBMIH, 0, NULL, NULL, 0); unique parameters are indicators to BitmapInfoheader structures (without color control table). In this form, a single-color GDI dot matrix object is established. The second simple method is:

HBitmap = Createdibitmap (HDC, PBMIH, 0, NULL, NULL, 0); In this form, the function is established with the DDB compatible with the device content, which is indicated by the HDC parameter. So far, we have completed some work through CreateBitmap or CreateCompatibleBitmap (dot mapping with video displays).

In these two simplified modes of CreateDibitmap, the icons have not been initialized. If the third parameter of CREATEDIBITMAP is CBM_INIT, Windows will establish DDB and initialize the dot matrix element using the last three parameters. The Pinfo parameter is an indicator of the BitmapInfo structure including a color control table. The PBITS parameter is a indicator of the bit element array in the color format pointed out by the BitmapInfo structure, which is converted to the color format of the device according to the color control table, which is the same as the SETDIBITSTODEVICE. In fact, the entire CREATEDIBITMAP function can be used in the following program:

Hbitmap Createdibitmap (HDC HDC, Const BitmapInfoHeader * PBMIH, DWORD FINIT, Const Void * Pbits, Const BitmapInfo * PBMI, UINT FUSAGE) {hbitmap hbitmap; hdc hdc; int CX, CY, IbitCount;

if (pbmih-> biSize == sizeof (BITMAPCOREHEADER)) {cx = ((PBITMAPCOREHEADER) pbmih) -> bcWidth; cy = ((PBITMAPCOREHEADER) pbmih) -> bcHeight; iBitCount = ((PBITMAPCOREHEADER) pbmih) -> bcBitCount; } else {cx = pbmih-> biwidth; cy = pbmih-> biheight; ibitcount = pbmih-> bibitcount;}} hbitmap = createcompatibleBitmap (HDC, CX, CY); elsehbitmap = CreateBitmap (CX, CY, 1, 1, null; if (finit == cbm_init) {hdcmem = creteCompatibleDC (HDC); SelectObject (HDCMEM, HBitmap); SetDibitStodevice (HDCMEM, 0, 0, CX, CY, 0, 0, 0 CY, PBITS, PBMI, Fusage); deletedc (hdcmem);} return hbitmap;} If you only need to display DIB once and worry that the setDibitStodevice display is too slow, call CREATEDIBITMAP and use Bitblt or StretchBLT to display DDB. Because SetDibitStodevice and CreateDibitMap perform color conversion, these two work will take up the same long time. This conversion is made only when DIB is displayed multiple times (for example, when processing the WM_PAINT message).

Cheng Form 15-6 DibCONV shows how to convert DIB files to DDB using SetDibitStodevice.

Cheng 15-6 DibconvdibConv.c / * ----------------------------------------- -------------------------------- Dibconv.c - Converts a dib to a ddb (c) Charles Petzold, 1998 ------------------------------------- --------------------------- * /

#include #include #include "resource.h"

LResult Callback WndProc (HWND, UINT, WPARAM, LPARAM); Tchar Szappname [] = Text ("Dibconv");

Int WinApi Winmain (Hinstance Hinstance, Pstr Szcmdline, int icmdshow) {hwnd hwnd; msg msg; WNDCLASS WNDCLASS;

wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName;! if (RegisterClass (& wndclass)) {MessageBox (NULL, TEXT ( "This program requires Windows NT! "), szappname, MB_ICONERROR); RETURN 0;}

HWnd = CREATEWINDOW (Szappname, Text ("Dib to DDB Conversion"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, HINSTANCE, NULL;

ShowWindow (hwnd, icmdshow); UpdateWindow (HWND);

While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);

} Return msg.wParam;} HBITMAP CreateBitmapObjectFromDibFile (HDC hdc, PTSTR szFileName) {BITMAPFILEHEADER * pbmfh; BOOL bSuccess; DWORD dwFileSize, dwHighSize, dwBytesRead; HANDLE hFile; HBITMAP hBitmap;

// Open the file: read access, prohibit Write Access

Hfile = createfile (szfilename, generic_read, file_share_read, null, open_existing, file_flag_sequential_scan, null); if (hfile == invalid_handle_value) Return NULL;

// read in The Whole File

DWFILESIZE = GetFileSize (Hfile, & dwhight);

IF (dwhighsize) {closeHandle (HFILE); Return Null;}

PBMFH = Malloc (dwfilesize);

IF (! pbmfh) {closeHandle (HFILE); Return NULL;}

Bsuccess = readfile (HFile, PBMFH, DWFILESIZE, & DWBYTESREAD, NULL); CloseHandle (HFILE);

// verify the fileif (! Bsuccess | = dwfilesize) || (PBMFH-> bftype! = * (Word *) "bm") || (PBMFH-> bFSize! = Dwfilesize) {free (PBMFH) Return null;} // create the ddb hbitmap = createDibitmap (HDC, (BitmapInfoHeader *) (PBMFH 1), CBM_INIT, (BYTE *) PBMFH PBMFH-> BFOffBits, (BitmapInfo *) (PBMFH 1), DIB_RGB_COLORS); free (pbmfh); return hBitmap;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static HBITMAP hBitmap; static int cxClient, cyClient; static OPENFILENAME ofn; static TCHAR szFileName [MAX_PATH], SZTITLENAME [MAX_PATH]; Static Tchar Szfilter [] = text ("Bitmap Files (*. BMP) / 0*.BMP/0") Text ("all files (*. *) / 0 *. * / 0/0" Bitmap Bitmap; HDC HDC, HDCMEM; PAINTSTRUCT PS;

switch (message) {case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; ofn.nFileOffset = 0 ; OFN.NFILEEXTENSION = 0; OFN.LPSTRDEFEXT = TEXT ("BMP"); OFN.LCUSTDATA = 0; OFN.LPFNHOOK = NULL; OFN.LPTEMPLATENAME = NULL;

Return 0;

Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0;

Case WM_Command: Switch (WPARAM) {CASE IDM_FILE_OPEN:

// Show the file open dialog box

IF (! getopenfilename (& off)) Return 0; // if there's an existing dib, delete it

IF (hbitmap) {deleteObject (hbitmap); hbitmap = null;} // create the ddb from the dibsetCursor (NULL, IDC_WAIT); showcursor (TRUE);

HDC = GETDC (HWND); hbitmap = CreateBitmapObjectFromDibfile (HDC, SZFileName); ReleaseDC (HWND, HDC);

Showcursor (False); SetCursor (LoadCursor (NULL, IDC_ARROW);

// invalidate the client area for latter Update

InvalidateRect (hwnd, null, true); if (hbitmap == null) {MessageBox (HWnd, Text ("Cannot Load Dib file"), Szappname, MB_OK | MB_ICONEXCLAMATION;} return 0;} Break;

Case WM_Paint: HDC = BeginPaint (HWND, & PS);

IF (hbitmap) {GetObject (Hbitmap, Sizeof (Bitmap), & Bitmap

HDCMEM = CREATECOMPATIPLEDC (HDC); SELECTOBJECT (HDCMEM, HBitmap);

Bitblt (HDC, 0, 0, Bitmap.bmwidth, Bitmap.Bmheight, HDCMEM, 0, 0, SRCCopy);

Deletedc (HDCMEM);

Endpaint (hwnd, & ps); Return 0; Case WM_DESTROY: IF (HBitmap) deleteObject (Hbitmap);

PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} DIBCONV.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. "/// MenudibConv Menu Discardable Beginpopup" & File "BeginMenuItem" & Open ", IDM_FILE_OPENENDENDERESOPERES.H (Explore) // Microsoft Developer Studio generated include file.// buy by dibconv.rc

#define idm_file_open 40001dibconv.c itself is complete, does not need the previous file. In response to its only functional table command ("File Open"), the CreateBitMapObjectFromDibfile in the WndProc Call program. This file reads the entire file into the memory and passes the indicator of the memory block to the CREATEDIBITMAP function, the code of the letter transfer point, and then contains the memory block of the DIB to be released. During WM_PAINT message processing, WndProc selects a dot matrix map to display a dot mapping in the display area using Bitblt (not setDibitStodeVice). It collects the width and height of the point pattern by using the Patomap code code call with the Bitmap structure. When you create a dot mapping from createDibitmap, you don't have to initialize the DDB icon, then you can call the setDibits initialization chammetric. The syntax of the function is as follows:

iLines = SetDIBits (hdc, // device context handlehBitmap, // bitmap handleyScan, // first scan line to convertcyScans, // number of scan lines to convertpBits, // pointer to pixel bitspInfo, // pointer to DIB informationfClrUse); / / Color Use Flag Funken Use the color control pair of BitmapInfo to convert bit elements to device-related formats. The device content code is only required when the last parameter is set to DIB_PAL_COLORS.

From DDB to DIB

Similar to the setDibits card is getDibits, you can use this card to convert DDB to DIB:

int WINAPI GetDIBits (hdc, // device context handlehBitmap, // bitmap handleyScan, // first scan line to convertcyScans, // number of scan lines to convertpBits, // pointer to pixel bits (out) pInfo, // pointer to DIB Information (out) fclruse; // Color USE FLAG However, this one of this fifth is not the result of setDibits. In general, if you use createDibitMap and setDibits to convert DIB to DDB, then use getDibits to convert DDB back to DIB, you will not get the original image. This is because there is some information to be lost when DIB is converted to device-related formats. The loss of lost information depends on the display mode executed by Windows when converting.

You may find that there is no need to use GetDibits. Consider: In any environment, your program is found to have a little graphic code, but is not used to establish a point-made information in the starting position? scrapbook? But the scrapbook provides automatic conversion for DIB. An example of a GETDIBITS function is to capture the screen display content, for example, in Chapter 14, the Blowup program. I don't show this card, but there are some information in the Knowledge Base article Q80080 of the Microsoft website.

DIB block

I hope that you have a clear concept of the difference between the device-related and installation-independent points. DIB can have one of several color organizations, and DDB must be monochrome or with the same format as the real output device. DIB is a file or memory block; DDB is a GDI dot matrix object and is represented by a dot matrix. The DIB can be displayed or converted to DDB and converted back to DIB, but here includes a conversion program between the device's unacceptable element and the device-related bit element. Now you will encounter a letter, it breaks these rules. This card is published in the 32-bit WINDOWS version called createDibSECTION, the syntax is:

hBitmap = CreateDIBSection (hdc, // device context handlepInfo, // pointer to DIB informationfClrUse, // color use flagppBits, // pointer to pointer variablehSection, // file-mapping object handledwOffset); // offset to bits in file-mapping ObjectCreatedibsection is one of the most important functions in the Windows API (at least when using dot mapping), you will find it very well and difficult to understand.

Let us start from its name, we know what DIB is, but what is "Dib Section"? When you check the createDibsection for the first time, you may look for how the letter is working with the DIB block. This is correct, what is diBsection is part of the establishment of a part of the DIB (the memory block of the dot mapping graphic).

Now let's take a look at the value, it is the code of the GDI dot matrix object, which may be part of the letter to the player. The return value seems to impose that CreatedibSecion is functionally identical to createDibitmap. In fact, it is just similar but completely. In fact, the dot matrix code recorded from the CREATEDIBSECTION is in this chapter in this chapter and the previous chapter.

Once you understand the true characteristics of createDibsection, you may feel weird why you don't define the return value. You may also conclude that CreateDibsection should be called createDibitmap, and the createDibitmap indicated earlier is CreatedDbitmap.

Let us first check how to simplify createDibsection and use it correctly. First, the last two parameters HSECTION and DWOFFSET are set to NULL and 0, respectively, and I will discuss these parameters in this chapter. Second, only the HDC parameter is used only when the FColorUse parameter is set to DIB_ PAL_COLORS, and if fcoloruse is DIB_RGB_COLORS (or 0), HDC will be ignored (this is different from CreatedIbitMap, the HDC parameter is used to obtain the DDB compatible device) Color format).

Therefore, the simplest form of CreateDibSecion requires only second and fourth parameters. The second parameter is an indicator of the BitmapInfo structure, we have used it before. I want to point to indicators defined by the fourth parameters not to make you confused, it is actually very simple.

Suppose you want to establish a 384 × 256-bit dib, 24-bit format, 24-bit format, is not required for 24-bit format, so it is the easiest, so we can use the BitMapInfoHeader structure for BitmapInfo parameters.

You need to define three varies: BitmapInfoHeader structure, byte indicator and dot matrix code: BitmapInfoHeader Bmih; Byte * Pbits; hbitmap hbitmap; Now initialize the BitMapInfoHeader structure

bmih-> biSize = sizeof (BITMAPINFOHEADER); bmih-> biWidth = 384; bmih-> biHeight = 256; bmih-> biPlanes = 1; bmih-> biBitCount = 24; bmih-> biCompression = BI_RGB; bmih-> biSizeImage = 0; BMIH-> Bixpelspermeter = 0; bmih-> biypelspermeter = 0; bmih-> biclrused = 0; bmih-> biclrimportant = 0; after basics, we call the form:

Hbitmap = createdibsection (NULL, (BitmapInfo *) & BMIH, 0, & PBITS, NULL, 0); Note that we give the second parameter to the location of the BitmapInfoHeader structure. This is common, but an address of a BYIE indicator PBITS is not common. In this way, the fourth parameter is the indicator of the pointing indicator required by the function.

This is a card-called call: createDibsection checks the BitmapInfoHeader structure and configures enough memory blocks to load the DIB icon. (In this example, the size of the memory block is 384 × 256 x 3-bit group.) It stores an indicator to this memory block in the PBITS parameters you provide. The letter is called the code, as I said, it is different from CreateDibitMap and other dot mapping.

However, we have not finished yet, the dot mapping is not initialized. If you are reading a DIB file, you can simply pass the PBITS parameters to the ReadFile letter and read them. Or you can use some program code "manual" setting.

Cheng Form 15-7 Dibsect In addition to calling createDibSECTION, it is similar to the DibConv program except CREATEDIBSECAP.

Cheng Form 15-7 DibsectDibsect.c / * ----------------------------------------- ---------------------------------- Dibsect.c - Displays a Dib Section in The Client Area (C CHARLES PETZOLD, 1998 --------------------------------------------- ------------------------------- * /

#include #include

Tchar szappname [] = text ("Dibsect"); int WinApi Winmain (Hinstance Hinstance, Hinstance Hprevinstance, Pstr Szcmdline, ICMDSHOW) {hwnd hwnd; msg msg; wndclass wndclass;

wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL , IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName;! if (RegisterClass (& wndclass)) {MessageBox (NULL, TEXT ( "This program requires Windows NT! "), szappname, MB_ICONERROR); RETURN 0;}

HWND = CREATEWINDOW (Szappname, Text ("Dib Section Display"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, HINSTANCE, NULL;

ShowWindow (hwnd, icmdshow); UpdateWindow (HWND);

While (GetMessage (& MSG, NULL, 0, 0)) {TranslateMessage (& MSG); DispatchMessage (& MSG);

} Return msg.wParam;} HBITMAP CreateDIBsectionFromDibFile (PTSTR szFileName) {BITMAPFILEHEADER bmfh; BITMAPINFO * pbmi; BYTE * pBits; BOOL bSuccess; DWORD dwInfoSize, dwBytesRead; HANDLE hFile; HBITMAP hBitmap;

// Open the file: read access, prohibit Write Access

hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) return NULL; // Read in the BITMAPFILEHEADERbSuccess = ReadFile (hFile, & bmfh, sizeof (BITMAPFILEHEADER), & dwBytesRead, NULL );

IF (! bsuccess || (dwbytesread!) || (BMFH.BFTYPE! = * (Word *) "BM")) {CloseHandle (HFile); Return Null;}

// Allocate memory for the BITMAPINFO structure & read it indwInfoSize = bmfh.bfOffBits - sizeof (BITMAPFILEHEADER); pbmi = malloc (dwInfoSize); bSuccess = ReadFile (hFile, pbmi, dwInfoSize, & dwBytesRead, NULL); if (bSuccess ||! (dwBytesRead = dwInfoSize!)) {free (pbmi); CloseHandle (hFile); return NULL;} // Create the DIB SectionhBitmap = CreateDIBSection (NULL, pbmi, DIB_RGB_COLORS, & pBits, NULL, 0); if (hBitmap == NULL ) {free (hfile); return null;} // read in The Bitmap BitsReadfile (HFILE, PBITS, BMFH.BFSIZE - BMFH.BFOFFBITS, & DWBYTESREAD, NULL); Free (PBMI); CloseHandle (HFILE) ;

Return hbitmap;

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {static HBITMAP hBitmap; static int cxClient, cyClient; static OPENFILENAME ofn; static TCHAR szFileName [MAX_PATH], szTitleName [MAX_PATH]; static TCHAR szFilter [] = TEXT ("Bitmap Files (* .bmp) / 0*.bmp/0") Text ("All Files (*. *) / 0 *. * / 0/0"); Bitmap Bitmap; HDC HDC, HDCMEM; PaintStruct PS ;

switch (message) {case WM_CREATE: ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hwnd; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = 0; ofn.nFileOffset = 0 ; OFN.NFILEEXTENSION = 0; OFN.LPSTRDEFEXT = TEXT ("BMP"); OFN.LCUSTDATA = 0; OFN.LPFNHOOK = NULL; OFN.LPTEMPLATENAME = NULL;

Return 0;

Case WM_SIZE: CXClient = loword (lparam); cyclient = HiWord (LPARAM); Return 0; Case WM_COMMAND: Switch (WPARAM) {CASE IDM_FILE_OPEN:

// Show the file open dialog box

IF (! getopenfilename (& off)) Return 0; // if there is an existing bitmap, delete it

IF (hbitmap) {deleteObject (hbitmap); hbitmap = null;} // create the dib section from the dib file

SetCursor (LoadCursor (NULL, IDC_WAIT); showcursor (TRUE);

Hbitmap = createdIbsectionFromDibfile (SZFileName); showcursor (false); setcursor (loadcursor (null, idc_arrow);

// invalidate the client area for latter Update

InvalidateRect (HWND, NULL, TRUE);

IF (hbitmap == null) {MessageBox (hwnd, text ("cannot loading dib file"), szappname, MB_OK | MB_ICONEXCLAMATION;} return 0;} Break;

Case WM_Paint: HDC = BeginPaint (HWND, & PS);

IF (hbitmap) {GetObject (Hbitmap, Sizeof (Bitmap), & Bitmap

HDCMEM = CREATECOMPATIPLEDC (HDC); SELECTOBJECT (HDCMEM, HBitmap);

Bitblt (HDC, 0, 0, Bitmap.bmwidth, Bitmap.Bmheight, HDCMEM, 0, 0, SRCCopy);

Deletedc (HDCMEM);

Endpaint (hwnd, & ps); Return 0; Case WM_DESTROY: IF (HBitmap) deleteObject (Hbitmap);

PostQuitMessage (0); return 0;} return DefWindowProc (hwnd, message, wParam, lParam);} DIBSECT.RC (excerpt) // Microsoft Developer Studio generated resource script # include "resource.h" #include "afxres.h. "

//////////Udibsect menu discardable beginpopup "& file" BeginMenuItem "& Open", IDM_FILE_OPENENDENDRESOPER.H (Explore) // Microsoft Developer Studio generated include file.// buy by dibsect.rc

#define idm_file_open 40001 Note that the CreateBitMapObjectFromDibfile in the Dibconv is the difference between the CreateDibSecionFromDibfile function in Dibsect. DibConv reads the entire file and then passes the indicator of the DIB memory block to the CreatedIbitmap. Dibsect first read information in the BitmapFileHeader structure, then determines the size of the BitmapInfo structure, configure the memory for this, and read it into the memory in the second ReadFile call. Then, the function passes the indicator of the BitmapInfo structure and the indicator variable PBITS to createDibsection. The letter is recorded and set to the PBITS pointing to read the memory block of the DIB icon. PBITS pointing to the memory block of the system. When the dot mapping is deleted by calling the deleteObject, the memory is automatically released. However, the program can use this indicator to change the DIB bit. When the application passes a large number of memory blocks through the API, as long as the system has these memory blocks, it will not affect the speed under Windows NT.

I have said before, when I display DIB on the video display, some way of transition from the device-independent indicator to the device related to the device, sometimes these formats may be considerably. Take a look at the three methods for displaying DIB:

When using SetDibitStodevice or StretchDibits to display DIB directly on the screen, format translation occurs during SetDibitStodevice or StretchDibits call. When using createDibitmap and (possibly) setDibits convert DIB to DDB, then use BitBLT or StretchBLT to display it, if the CBM_INIT flag is set, the format is transformed during CREATEDIBITMAP or SETDIBITS. The DIB block is created using CREATEDIBSECTION, and then use Bitblt or StretchBLT to display it, the format is converted during Bitblt to the call for StretchBLT. Read these narratives again, make sure you don't misunderstand it. This is a place from the CREATEDIBSECTION code to which the code number is different from the other dot matrix code we have encountered. This image code actually points to the DIB stored by the system maintained by the system, but the application can be accessed. When needed, DIB will convert to a specific color format, usually when displaying a bit mapping with a Bitblt or STRETCHBLT.

You can also select the dot matrix code to the memory device content and draw it using the GDI. The result will be reflected in the DIB in the PBITS variable. Because of the GDI card in Windows NT, the GDIFLUSH will be called before the memory device is drawn and the "artificial" access bit is drawn.

In Dibsect, we clear PBITS variables because the program no longer needs this variable. The main reason you use CreatedibSecion is that you need to change bitmaps directly. There is no other method after the CreateDibSECTION call.

Other differences in DIB blocks

From the CREATEDIBITMAP, the dot matrix code recorded with the function of the HDC parameter referenced by the Form, has the same plane and the primary organization. You can check this by getObject call with a Bitmap structure.

CreatedibSECTION is different. If you call GetObject if the bitmap structure (Bitmap structure) of the dot matrix record, you will find that the color organization with the dot matrix has the same column with the BitmapInfoheader structure. You can select this code into the memory device content compatible with the video display. This is contradictory with the previous chapter about the content of DDB, but this is what I said that this DIB block is different from the code.

Another wonderful thing is: You may still remember that the length group length of the PIN in DIB is always 4 times. The length group length of the line in the GDI dot matrix object is the length of the BTMAP structure from the Bitmap structure, which is always 2 times. If you set the BitmapInfoHeader structure for 24-bit and width 2 per status and then call getObject, you will find that the BMWIDTHBYTES field is 8 instead of 6. Use the dot matrix map recorded from the CREATEDIBSECTION, you can also use the DibSECTION structure call GetObject:

GetObject (HbitMap, SizeOf (Dibsection), & Dibsection; This function cannot handle some dot matrix code for other dot matrix building functions. The DIBSECTION structure is defined as follows:

typedef struct tagDIBSECTION // ds {BITMAP dsBm; // BITMAP structureBITMAPINFOHEADER dsBmih; // DIB information headerDWORD dsBitfields [3]; // color masksHANDLE dshSection; // file-mapping object handleDWORD dsOffset; // offset to bitmap bits} DIBSECTION, * PDIBSECTION; this structure contains Bitmap structure and BitmapInfoHeader structure. The last two fields are the last two parameters passed to createDibsection, and they will discuss them.

The DIBSECTION structure includes many of the contents of the point array in addition to the color control table. When the DIB block dot matrix is ​​selected to the memory device content, you can get a color control table by calling getDibcolortable:

hdcMem = CreateCompatibleDC (NULL); SelectObject (hdcMem, hBitmap); GetDIBColorTable (hdcMem, uFirstIndex, uNumEntries, & rgb); DeleteDC (hdcMem); Similarly, you can set the color table by calling SetDIBColorTable items.

Archive mapping option

We have not discussed the last two parameters of createDibsection, which are the code of the file mapping object and the offset starting in the file in the file. The archive mapping object allows you to process files as files in memory. That is, the file can be accessed by using a memory index, but the file does not require the entire load memory.

In the case of large DIB, this technology is very helpful for reducing memory demand. The DIB icon is capable of being stored on the magnetic sheet, but can still be used as in the memory, although it will affect the program performance. The problem is that when the chamber bit is actually stored on the magnetic sheet, they cannot be part of the actual DIB file. They must be in other files.

To show this program, the plurality of the following displays are similar to those in dibsect, in addition to reading the resection of the icon into the memory. However, it provides a file mapping object and passes to the CreatedibSECTION function:

HBITMAP CreateDIBsectionMappingFromFile (PTSTR szFileName) {BITMAPFILEHEADER bmfh; BITMAPINFO * pbmi; BYTE * pBits; BOOL bSuccess; DWORD dwInfoSize, dwBytesRead; HANDLE hFile, hFileMap; HBITMAP hBitmap;

hFile = CreateFile (! szFileName, GENERIC_READ | GENERIC_WRITE, 0, // No sharing NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) return NULL; bSuccess = ReadFile (hFile, & bmfh, sizeof (BITMAPFILEHEADER), & dwBytesRead NULL);

IF (! BSuccess || (BitmapfileHead) || (BMFH.BFTYPE! = * (Word *) "BM")) {closeHandle (HFILE); Return null;} dwinfosize = bmfh.bfoffbits - sizeof (BitmapFileHeader); PBMI = Malloc (dwinfosize); bsuccess = readfile (HFile, PBMI, Dwinfosize, & DwbytesRead, null);

if (bSuccess || (dwBytesRead = dwInfoSize)!!) {free (pbmi); CloseHandle (hFile); return NULL;} hFileMap = CreateFileMapping (hFile, NULL, PAGE_READWRITE, 0, 0, NULL); hBitmap = CreateDIBSection (NULL , PBMI, DIB_RGB_COLORS, & PBITS, HFILEMAP, BMFH.BFOFFBITS; Free (PBMI); return hbitmap; }haha! This program will not move. The file of createDibsection states that "the last parameter of the dwoffset" must be a multiple of DWORD size. " Although the size of the information header is always a multiple of 4 and the size of the color control table is always 4 times, but the point-in-frame archive head is not, it is a 14-bit group. Therefore, BMFH.BFoffBits will never be a multiple of 4.

to sum up

If you have a small DIB and need frequent operation of the icon, you can use SetDibitStodeVice and StretchDibits to display them. However, for large DIBs, this technique encounters a problem of displaying performance, especially in the 8-bit metamorphic display and the Windows NT environment.

You can convert DIB to DDB using createDibitMap and setDibits. Now, the display dot mapping can be made using the fast Bitblt and StretchBLT functions. However, you cannot directly access the icons that are not related to the device.

CreateDibsection is a good compromise. Using a dot matrix code by Bitblt and StretchBLT under Windows NT, you will get better efficiency than using setDibitStodevice and StretchDibits (but no DDB defects). You can still access DIB icon.

The next chapter will enter the discussion of the "Windows Toner Manager".

转载请注明原文地址:https://www.9cbs.com/read-54516.html

New Post(0)