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  
18  package org.apache.commons.imaging.formats.pnm;
19  
20  import java.io.IOException;
21  import java.io.InputStream;
22  
23  import org.apache.commons.imaging.ImageFormat;
24  import org.apache.commons.imaging.ImageFormats;
25  import org.apache.commons.imaging.ImageInfo;
26  import org.apache.commons.imaging.ImagingException;
27  
28  final class PamFileInfo extends AbstractFileInfo {
29      private final class ColorTupleReader extends TupleReader {
30          @Override
31          public ImageInfo.ColorType getColorType() {
32              return ImageInfo.ColorType.RGB;
33          }
34  
35          @Override
36          public int getRgb(final InputStream is) throws IOException {
37              int red = readSample(is, bytesPerSample);
38              int green = readSample(is, bytesPerSample);
39              int blue = readSample(is, bytesPerSample);
40  
41              red = scaleSample(red, scale, maxval);
42              green = scaleSample(green, scale, maxval);
43              blue = scaleSample(blue, scale, maxval);
44  
45              int alpha = 0xff;
46              if (hasAlpha) {
47                  alpha = readSample(is, bytesPerSample);
48                  alpha = scaleSample(alpha, scale, maxval);
49              }
50  
51              return (0xff & alpha) << 24 | (0xff & red) << 16 | (0xff & green) << 8 | (0xff & blue) << 0;
52          }
53      }
54  
55      private final class GrayscaleTupleReader extends TupleReader {
56          private final ImageInfo.ColorType colorType;
57  
58          GrayscaleTupleReader(final ImageInfo.ColorType colorType) {
59              this.colorType = colorType;
60          }
61  
62          @Override
63          public ImageInfo.ColorType getColorType() {
64              return colorType;
65          }
66  
67          @Override
68          public int getRgb(final InputStream is) throws IOException {
69              int sample = readSample(is, bytesPerSample);
70              sample = scaleSample(sample, scale, maxval);
71  
72              int alpha = 0xff;
73              if (hasAlpha) {
74                  alpha = readSample(is, bytesPerSample);
75                  alpha = scaleSample(alpha, scale, maxval);
76              }
77  
78              return (0xff & alpha) << 24 | (0xff & sample) << 16 | (0xff & sample) << 8 | (0xff & sample) << 0;
79          }
80      }
81  
82      private abstract static class TupleReader {
83          public abstract ImageInfo.ColorType getColorType();
84  
85          public abstract int getRgb(InputStream is) throws IOException;
86      }
87  
88      private final int depth;
89      private final int maxval;
90      private final float scale;
91  
92      private final int bytesPerSample;
93  
94      private final boolean hasAlpha;
95  
96      private final TupleReader tupleReader;
97  
98      PamFileInfo(final int width, final int height, final int depth, final int maxval, final String tupleType) throws ImagingException {
99          super(width, height, true);
100         this.depth = depth;
101         this.maxval = maxval;
102         if (maxval <= 0) {
103             throw new ImagingException("PAM maxVal " + maxval + " is out of range [1;65535]");
104         }
105         if (maxval <= 255) {
106             scale = 255f;
107             bytesPerSample = 1;
108         } else if (maxval <= 65535) {
109             scale = 65535f;
110             bytesPerSample = 2;
111         } else {
112             throw new ImagingException("PAM maxVal " + maxval + " is out of range [1;65535]");
113         }
114 
115         hasAlpha = tupleType.endsWith("_ALPHA");
116         switch (tupleType) {
117         case "BLACKANDWHITE":
118         case "BLACKANDWHITE_ALPHA":
119             tupleReader = new GrayscaleTupleReader(ImageInfo.ColorType.BW);
120             break;
121         case "GRAYSCALE":
122         case "GRAYSCALE_ALPHA":
123             tupleReader = new GrayscaleTupleReader(ImageInfo.ColorType.GRAYSCALE);
124             break;
125         case "RGB":
126         case "RGB_ALPHA":
127             tupleReader = new ColorTupleReader();
128             break;
129         default:
130             throw new ImagingException("Unknown PAM tupletype '" + tupleType + "'");
131         }
132     }
133 
134     @Override
135     public int getBitDepth() {
136         return maxval;
137     }
138 
139     @Override
140     public ImageInfo.ColorType getColorType() {
141         return tupleReader.getColorType();
142     }
143 
144     @Override
145     public ImageFormat getImageType() {
146         return ImageFormats.PAM;
147     }
148 
149     @Override
150     public String getImageTypeDescription() {
151         return "PAM: portable arbitrary map file format";
152     }
153 
154     @Override
155     public String getMimeType() {
156         return "image/x-portable-arbitrary-map";
157     }
158 
159     @Override
160     public int getNumComponents() {
161         return depth;
162     }
163 
164     @Override
165     public int getRgb(final InputStream is) throws IOException {
166         return tupleReader.getRgb(is);
167     }
168 
169     @Override
170     public int getRgb(final WhiteSpaceReader wsr) throws IOException {
171         throw new UnsupportedOperationException("PAM files are only ever binary");
172     }
173 
174     @Override
175     public boolean hasAlpha() {
176         return hasAlpha;
177     }
178 }