View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.imaging.formats.bmp;
18  
19  import static org.apache.commons.imaging.common.BinaryFunctions.read2Bytes;
20  import static org.apache.commons.imaging.common.BinaryFunctions.read3Bytes;
21  import static org.apache.commons.imaging.common.BinaryFunctions.read4Bytes;
22  import static org.apache.commons.imaging.common.BinaryFunctions.readByte;
23  
24  import java.io.IOException;
25  import java.nio.ByteOrder;
26  
27  import org.apache.commons.imaging.ImagingException;
28  
29  final class PixelParserBitFields extends AbstractPixelParserSimple {
30  
31      private final int redShift;
32      private final int greenShift;
33      private final int blueShift;
34      private final int alphaShift;
35  
36      private final int redMask;
37      private final int greenMask;
38      private final int blueMask;
39      private final int alphaMask;
40  
41      private int byteCount;
42  
43      PixelParserBitFields(final BmpHeaderInfo bhi, final byte[] colorTable, final byte[] imageData) {
44          super(bhi, colorTable, imageData);
45  
46          redMask = bhi.redMask;
47          greenMask = bhi.greenMask;
48          blueMask = bhi.blueMask;
49          alphaMask = bhi.alphaMask;
50  
51          redShift = getMaskShift(redMask);
52          greenShift = getMaskShift(greenMask);
53          blueShift = getMaskShift(blueMask);
54          alphaShift = alphaMask != 0 ? getMaskShift(alphaMask) : 0;
55      }
56  
57      private int getMaskShift(int mask) {
58          if (mask == 0) {
59              return 0;
60          }
61  
62          int trailingZeroes = 0;
63  
64          while ((0x1 & mask) == 0) {
65              mask = 0x7fffffff & mask >> 1;
66              trailingZeroes++;
67          }
68  
69          int maskLength = 0;
70  
71          while ((0x1 & mask) == 1) {
72              mask = 0x7fffffff & mask >> 1;
73              maskLength++;
74          }
75  
76          return trailingZeroes - (8 - maskLength);
77      }
78  
79      @Override
80      public int getNextRgb() throws ImagingException, IOException {
81          final int data;
82          switch (bhi.bitsPerPixel) {
83          case 8:
84              data = 0xff & imageData[byteCount + 0];
85              byteCount += 1;
86              break;
87          case 24:
88              data = read3Bytes("Pixel", is, "BMP Image Data", ByteOrder.LITTLE_ENDIAN);
89              byteCount += 3;
90              break;
91          case 32:
92              data = read4Bytes("Pixel", is, "BMP Image Data", ByteOrder.LITTLE_ENDIAN);
93              byteCount += 4;
94              break;
95          case 16:
96              data = read2Bytes("Pixel", is, "BMP Image Data", ByteOrder.LITTLE_ENDIAN);
97              byteCount += 2;
98              break;
99          default:
100             throw new ImagingException("Unknown BitsPerPixel: " + bhi.bitsPerPixel);
101         }
102 
103         int red = redMask & data;
104         int green = greenMask & data;
105         int blue = blueMask & data;
106         int alpha = alphaMask != 0 ? alphaMask & data : 0xff;
107 
108         red = redShift >= 0 ? red >> redShift : red << -redShift;
109         green = greenShift >= 0 ? green >> greenShift : green << -greenShift;
110         blue = blueShift >= 0 ? blue >> blueShift : blue << -blueShift;
111         alpha = alphaShift >= 0 ? alpha >> alphaShift : alpha << -alphaShift;
112 
113         return alpha << 24 | red << 16 | green << 8 | blue << 0;
114     }
115 
116     @Override
117     public void newline() throws ImagingException, IOException {
118         while (byteCount % 4 != 0) {
119             readByte("Pixel", is, "BMP Image Data");
120             byteCount++;
121         }
122     }
123 }