⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch7.htm

📁 JAVA Developing Professional JavaApplets
💻 HTM
📖 第 1 页 / 共 5 页
字号:
image contain the RGB values directly. This is also known as &quot;truecolor.&quot; There are two constructors-one with an alpha channel,one without. To create the model, you need to specify only thenumber of bits per pixel and which bits correspond to which color:<UL><LI><TT>public DirectColorModel(int bits,int rmask, int gmask, int bmask);</TT><LI><TT>public DirectColorModel(int bits,int rmask, int gmask, int bmask, int amask);</TT></UL><P>The mask values for Java's default RGB model are the following:<UL><LI><TT>r</TT> = <TT>0x00ff0000</TT><LI><TT>g</TT> = <TT>0x0000ff00</TT><LI><TT>b</TT> = <TT>0x000000ff</TT><LI><TT>a</TT> = <TT>0xff000000</TT></UL><H3><A NAME="IndexColor">Index Color</A></H3><P>The IndexColorModel is used when the underlying pixels in an imagerepresent an index into a color table. Most bitmaps fall intothis category because the actual colors are contained in a colormap somewhere in the file. The actual pixel data represent indexesinto the color map instead of complete RGB values. There are fiveconstructors for this model:<UL><LI><TT>public IndexColorModel(int bits,int size, byte r[], byte g[], byte b[]);</TT><LI><TT>public IndexColorModel(int bits,int size, byte r[], byte g[], byte b[], int trans);</TT><LI><TT>public IndexColorModel(int bits,int size, byte r[], byte g[], byte b[], byte a[]);</TT><LI><TT>public IndexColorModel(int bits,int size, byte cmap[], int start, boolean hasalpha);</TT><LI><TT>public IndexColorModel(int bits,int size, byte cmap[], int start, boolean hasalpha, int trans);</TT></UL><P>The parameter <TT>bits</TT> representshow many bits per pixel in the image, and <TT>size</TT>specifies the length of each color array. The colors themselvescan be passed as individual arrays or packed into one large array(all reds, then all greens, and so forth). The parameter <TT>hasalpha</TT>signals the presence (or absence) of alpha information at theend of the packed array, and the <TT>trans</TT>parameter indicates which index is to be considered transparent,regardless of its alpha channel setting.<H2><A NAME="ChapterProjectDisplayingaWindowsBM"><FONT SIZE=5 COLOR=#FF0000>ChapterProject: Displaying a Windows BMP Image</FONT></A></H2><P>Java has built-in support for GIF and JPEG format images, butwhat if you want to display an image using a different format?This chapter's project creates a class to display Windows BMPimages. The principles involved in the display can be appliedto almost any image format.<H3><A NAME="UsingImageTypesNotSupportedbyJava">Using Image TypesNot Supported by Java</A></H3><P>The goal of this project is to create a class that accepts a URLand filename just as <TT>getImage()</TT>does. Although <TT>getImage()</TT>returns an image, the BmpImage class will return an ImageProducer.The caller of the class will have to use the producer to createan image:<BLOCKQUOTE><TT>producer = BmpImage.getImageProducer(getCodeBase(),&quot;Forest.bmp&quot;);<BR>myImage = createImage(producer);<BR></TT></BLOCKQUOTE><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD><B>Note</B></TD></TR><TR VALIGN=TOP><TD><BLOCKQUOTE>BmpImage could return an image, but the class would have had to be a component subclass to create an image. I didn't want to apply any restrictions to using BmpImage.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><H3><A NAME="MemoryImages">Memory Images</A></H3><P>External image formats are most easily displayed by using theJava class MemoryImageSource, which allows an arbitrary arrayof pixels to be stored and used as the source for an ImageProducer.Because MemoryImageSource uses the ImageProducer interface, itcan be used as the source for an image in the same way a GIF orJPEG image is used. The class has six different constructors:<UL><LI><TT>public MemoryImageSource(int w, inth, ColorModel cm, byte pix[], int off, int scan);</TT><LI><TT>public MemoryImageSource(int w, inth, ColorModel cm, byte pix[], int off, int scan, Hashtable props);</TT><LI><TT>public MemoryImageSource(int w, inth, ColorModel cm, int pix[], int off, int scan);</TT><LI><TT>public MemoryImageSource(int w, inth, ColorModel cm, int pix[], int off, int scan, Hashtable props);</TT><LI><TT>public MemoryImage(int w, int h,int pix[], int off, int scan);</TT><LI><TT>public MemoryImage(int w, int h,int pix[], int off, int scan, Hashtable props);</TT></UL><P>The first four pass in a ColorModel, but the final two do not.No ColorModel indicates that the passed pixel array uses the defaultRGB model. Hashtable <TT>props</TT>will be passed in the ImageConsumer call <TT>setProperties(Hashtable)</TT>.Normally, the props constructors are not used unless your imageconsumer uses the <TT>setProperties()</TT>method.<P>Now that you know how to create a suitable ImageProducer, theonly remaining mystery is how to load and convert an arbitraryBMP image into the correct constructor arguments for MemoryImageSource.<H3><A NAME="LoadingForeignImages">Loading Foreign Images</A></H3><P>Foreign images, such as BMP, are loaded by using the Java URLclass. The following code snippet creates an input stream fora URL:<BLOCKQUOTE><TT>InputStream is = new URL(getCodeBase(),filename).openStream();</TT></BLOCKQUOTE><P>Once created, the input stream is read until all the informationneeded to create the image has been extracted.<H3><A NAME="BMPFileFormat">BMP File Format</A></H3><P>The Windows and OS/2 BMP formats are simple color map images;Figure 7.2 lays out the formats. All quantities are in Intel little-endianformat. This means that all multibyte quantities, such as a 2-byteshort, are stored as low byte, then high byte. Java uses big endianfor all I/O reads (high byte, then low byte). You cannot use Java's<TT>readShort()</TT> or <TT>readInt()</TT>method to parse the file.<P><A HREF="f7-2.gif" ><B>Figure 7.2 : </B><I>Layout of Windows and OS/2 BMP files </I></A><BR><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD><B>Note</B></TD></TR><TR VALIGN=TOP><TD><BLOCKQUOTE>The 2-byte quantity <TT>0x1234</TT> appears in memory differently depending on the system's endian order. In a little-endian system, the number would be stored in memory as 34, 12 (low byte first). Big-endian systems would store the number in memory as 12, 34 (high byte first).</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><P>Windows color maps are stored as 4 bytes per index. Each indexconsists of blue, green, red, and reserved bytes, in that order.The number of indexes is determined from either the number ofcolors specified in the header or the number of bits per pixel.If the number of colors in the header is zero, than bits per pixelis converted into number of colors. Images having 1, 4, or 8 bitsper pixel use 2, 16, or 256 colors, respectively. OS/2 BMP imagesstore colors as 3 bytes per index. Each OS/2 index consists ofblue, green, and red bytes, in that order.<H3><A NAME="ReadingUnsignedBinaryinJava">Reading Unsigned Binaryin Java</A></H3><P>I created a single method to read in a multibyte little-endiansequence:<BLOCKQUOTE><TT>/**<BR>&nbsp;* A private method for extracting little endian<BR></TT>&nbsp;<TT>* quantities from adata input stream.<BR>&nbsp;* @param is contains the input stream<BR></TT>&nbsp;<TT>* @param len is thenumber of bytes in the quantity<BR>&nbsp;* @returns the result as an integer<BR></TT>&nbsp;<TT>*/<BR>private int pullVal(DataInputStream is, int len)<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;throwsIOException<BR>{<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;intvalue = 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;int temp;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;for ( int x = 0; x &lt; len; x++ )<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp = is.readUnsignedByte();<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value+= (temp &lt;&lt; (x * 8));<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;returnvalue;<BR>}</TT></BLOCKQUOTE><P>Each byte is read as an unsigned quantity and shifted into theproper position before being added to the total. Little-endianvalues are stored in completely reversed format, so the routineshifts each byte in multiples of 8 bits.<BR><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD><B>Note</B></TD></TR><TR VALIGN=TOP><TD><BLOCKQUOTE>The Java method <TT>readUnsignedByte()</TT> returns an integer, not a byte. Java bytes are signed quantities, so a larger storage variable had to be used to contain the unsigned value.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><H3><A NAME="CreatingtheColorTable">Creating the Color Table</A></H3><P>Since the colors are stored in RGB format, you will create separatearrays for each color. One large array could have been used, butmanaging it would have been more complex. Once the color arrayshave been stored, they are used to create a ColorModel:<BLOCKQUOTE><TT>/**<BR>&nbsp;* A private method for extracting the color table from<BR></TT>&nbsp;<TT>* a BMP type file.<BR>&nbsp;* @param is contains the input stream<BR></TT>&nbsp;<TT>* @param numColorscontains the biClrUsed (for Windows) or zero<BR>&nbsp;*/<BR>private void extractColorMap(DataInputStream is, int numColors)<BR>&nbsp;&nbsp;&nbsp;&nbsp;throws IOException, AWTException<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;byte blues[], reds[], greens[];<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;// if passed count is zero, then determinethe<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;//number of entries from bits per pixel.<BR>&nbsp;&nbsp;&nbsp;&nbsp;if ( numColors == 0 )<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp; switch ( biBitCount )<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp; case 1:&nbsp;&nbsp;numColors =&nbsp;&nbsp;&nbsp;2;break;<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;case 4:&nbsp;&nbsp;numColors =&nbsp;&nbsp;16; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp; case 8:&nbsp;&nbsp;numColors = 256; break;<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;case 24: numColors =&nbsp;&nbsp;&nbsp;0; break;<BR>&nbsp;&nbsp;&nbsp;&nbsp; default: numColors =&nbsp;&nbsp;-1; break;<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;}<BR>}<BR>if ( numColors == -1 )<BR>&nbsp;&nbsp;&nbsp;&nbsp;throw new AWTException(&quot;Invalid bitsper pixel: &quot; + biBitCount);<BR>else if ( numColors == 0 )<BR>&nbsp;&nbsp;&nbsp;&nbsp;colorModel = new DirectColorModel(24,255 * 3, 255 * 2, 255);<BR>else<BR>{<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;reds= new byte[numColors];<BR>&nbsp;&nbsp;&nbsp;&nbsp;blues = new byte[numColors];<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;greens= new byte[numColors];<BR>&nbsp;&nbsp;&nbsp;&nbsp;for ( int x = 0; x &lt; numColors; x++)<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp; blues[x] = is.readByte();<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;greens[x] = is.readByte();<BR>&nbsp;&nbsp;&nbsp;&nbsp; reds[x] = is.readByte();<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;if ( windowsStyle )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is.skipBytes(1);<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;colorModel = new IndexColorModel( biBitCount,numColors,<BR></TT>&nbsp;<TT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reds,greens, blues );<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}</TT></BLOCKQUOTE><P>DirectColorModel is used for true color BMP images; IndexColorModel,for all other representations.<H3><A NAME="ConstructingtheImage">Constructing the Image</A></H3><P>The image data itself is stored differently depending on the numberof bits per pixel and whether the data is compressed. BMPImagewill only support uncompressed 4 and 8 bits per pixel, thoughit can easily be extended to support all other modes.<P>All modes store the image in rows from the bottom of the imageto the top. Yes, this means that the image is stored upside down.For 8 bits per pixel, each row is stored as single bytes and paddedto a 4-byte boundary. The following code block extracts uncompressed,8-bits-per-pixel images:<BLOCKQUOTE><TT>/**<BR>&nbsp;* A private method for extracting 8 bit per pixel<BR>&nbsp;* image data.<BR>&nbsp;* @param is contains the input stream<BR>&nbsp;*/<BR>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -