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 java.awt.image.BufferedImage;
20  import java.io.ByteArrayOutputStream;
21  import java.io.IOException;
22  
23  import org.apache.commons.imaging.common.BinaryOutputStream;
24  import org.apache.commons.imaging.palette.SimplePalette;
25  
26  final class BmpWriterPalette implements BmpWriter {
27  
28      private final SimplePalette palette;
29      private final int bitsPerSample;
30  
31      BmpWriterPalette(final SimplePalette palette) {
32          this.palette = palette;
33  
34          if (palette.length() <= 2) {
35              bitsPerSample = 1;
36          } else if (palette.length() <= 16) {
37              bitsPerSample = 4;
38          } else {
39              bitsPerSample = 8;
40          }
41      }
42  
43      @Override
44      public int getBitsPerPixel() {
45          return bitsPerSample;
46      }
47  
48      @Override
49      public byte[] getImageData(final BufferedImage src) {
50          final int width = src.getWidth();
51          final int height = src.getHeight();
52  
53          final ByteArrayOutputStream baos = new ByteArrayOutputStream();
54  
55          int bitCache = 0;
56          int bitsInCache = 0;
57  
58          int byteCount = 0;
59          for (int y = height - 1; y >= 0; y--) {
60              for (int x = 0; x < width; x++) {
61                  final int argb = src.getRGB(x, y);
62                  final int rgb = 0xffffff & argb;
63  
64                  final int index = palette.getPaletteIndex(rgb);
65  
66                  if (bitsPerSample == 8) {
67                      baos.write(0xff & index);
68                      byteCount++;
69                  } else {
70                      // 4 or 1
71                      bitCache = bitCache << bitsPerSample | index;
72                      bitsInCache += bitsPerSample;
73                      if (bitsInCache >= 8) {
74                          baos.write(0xff & bitCache);
75                          byteCount++;
76                          bitCache = 0;
77                          bitsInCache = 0;
78                      }
79                  }
80              }
81  
82              if (bitsInCache > 0) {
83                  bitCache = bitCache << 8 - bitsInCache;
84  
85                  baos.write(0xff & bitCache);
86                  byteCount++;
87                  bitCache = 0;
88                  bitsInCache = 0;
89              }
90  
91              while (byteCount % 4 != 0) {
92                  baos.write(0);
93                  byteCount++;
94              }
95          }
96  
97          return baos.toByteArray();
98      }
99  
100     @Override
101     public int getPaletteSize() {
102         return palette.length();
103     }
104 
105     @Override
106     public void writePalette(final BinaryOutputStream bos) throws IOException {
107         for (int i = 0; i < palette.length(); i++) {
108             final int rgb = palette.getEntry(i);
109 
110             final int red = 0xff & rgb >> 16;
111             final int green = 0xff & rgb >> 8;
112             final int blue = 0xff & rgb >> 0;
113 
114             bos.write(blue);
115             bos.write(green);
116             bos.write(red);
117             bos.write(0);
118         }
119     }
120 }