comparison Core/FileFormats/PngReader.cpp @ 797:37adac56017a

ImageAccessor abstraction
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 06 May 2014 12:47:26 +0200
parents 2d0a347e8cfc
children e1d27ee2114a
comparison
equal deleted inserted replaced
796:e7b1ca0f1e04 797:37adac56017a
129 } 129 }
130 } 130 }
131 131
132 PngReader::PngReader() 132 PngReader::PngReader()
133 { 133 {
134 width_ = 0;
135 height_ = 0;
136 pitch_ = 0;
137 format_ = PixelFormat_Grayscale8;
138 } 134 }
139 135
140 void PngReader::Read(PngRabi& rabi) 136 void PngReader::Read(PngRabi& rabi)
141 { 137 {
142 png_set_sig_bytes(rabi.png_, 8); 138 png_set_sig_bytes(rabi.png_, 8);
150 png_get_IHDR(rabi.png_, rabi.info_, 146 png_get_IHDR(rabi.png_, rabi.info_,
151 &width, &height, 147 &width, &height,
152 &bit_depth, &color_type, &interlace_type, 148 &bit_depth, &color_type, &interlace_type,
153 &compression_type, &filter_method); 149 &compression_type, &filter_method);
154 150
151 PixelFormat format;
152 unsigned int pitch;
153
154 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 8)
155 {
156 format = PixelFormat_Grayscale8;
157 pitch = width;
158 }
159 else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16)
160 {
161 format = PixelFormat_Grayscale16;
162 pitch = 2 * width;
163
164 if (Toolbox::DetectEndianness() == Endianness_Little)
165 {
166 png_set_swap(rabi.png_);
167 }
168 }
169 else if (color_type == PNG_COLOR_TYPE_RGB && bit_depth == 8)
170 {
171 format = PixelFormat_RGB24;
172 pitch = 3 * width;
173 }
174 else
175 {
176 throw OrthancException(ErrorCode_NotImplemented);
177 }
178
179 data_.resize(height * pitch);
180
181 if (height == 0 || width == 0)
182 {
183 // Empty image, we are done
184 AssignEmpty(format);
185 return;
186 }
187
188 png_read_update_info(rabi.png_, rabi.info_);
189
190 std::vector<png_bytep> rows(height);
191 for (size_t i = 0; i < height; i++)
192 {
193 rows[i] = &data_[0] + i * pitch;
194 }
195
196 png_read_image(rabi.png_, &rows[0]);
197
198 AssignReadOnly(format, width, height, pitch, &data_[0]);
199 }
200
201 void PngReader::ReadFromFile(const char* filename)
202 {
203 FileRabi f(filename);
204
205 char header[8];
206 if (fread(header, 1, 8, f.fp_) != 8)
207 {
208 throw OrthancException(ErrorCode_BadFileFormat);
209 }
210
211 CheckHeader(header);
212
213 PngRabi rabi;
214
215 if (setjmp(png_jmpbuf(rabi.png_)))
216 {
217 rabi.Destruct();
218 throw OrthancException(ErrorCode_BadFileFormat);
219 }
220
221 png_init_io(rabi.png_, f.fp_);
222
223 Read(rabi);
224 }
225
226
227 void* ImageAccessor::GetBuffer()
228 {
229 if (readOnly_)
230 {
231 throw OrthancException(ErrorCode_ReadOnly);
232 }
233
234 return buffer_;
235 }
236
237
238 const void* ImageAccessor::GetConstRow(unsigned int y) const
239 {
240 if (buffer_ != NULL)
241 {
242 return reinterpret_cast<const uint8_t*>(buffer_) + y * pitch_;
243 }
244 else
245 {
246 return NULL;
247 }
248 }
249
250
251 void* ImageAccessor::GetRow(unsigned int y)
252 {
253 if (readOnly_)
254 {
255 throw OrthancException(ErrorCode_ReadOnly);
256 }
257
258 if (buffer_ != NULL)
259 {
260 return reinterpret_cast<uint8_t*>(buffer_) + y * pitch_;
261 }
262 else
263 {
264 return NULL;
265 }
266 }
267
268
269 void ImageAccessor::AssignEmpty(PixelFormat format)
270 {
271 readOnly_ = false;
272 format_ = format;
273 width_ = 0;
274 height_ = 0;
275 pitch_ = 0;
276 buffer_ = NULL;
277 }
278
279
280 void ImageAccessor::AssignReadOnly(PixelFormat format,
281 unsigned int width,
282 unsigned int height,
283 unsigned int pitch,
284 const void *buffer)
285 {
286 readOnly_ = true;
287 format_ = format;
155 width_ = width; 288 width_ = width;
156 height_ = height; 289 height_ = height;
157 290 pitch_ = pitch;
158 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 8) 291 buffer_ = const_cast<void*>(buffer);
159 { 292 }
160 format_ = PixelFormat_Grayscale8; 293
161 pitch_ = width_; 294
162 } 295 void ImageAccessor::AssignWritable(PixelFormat format,
163 else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16) 296 unsigned int width,
164 { 297 unsigned int height,
165 format_ = PixelFormat_Grayscale16; 298 unsigned int pitch,
166 pitch_ = 2 * width_; 299 void *buffer)
167 300 {
168 if (Toolbox::DetectEndianness() == Endianness_Little) 301 readOnly_ = false;
169 { 302 format_ = format;
170 png_set_swap(rabi.png_); 303 width_ = width;
171 } 304 height_ = height;
172 } 305 pitch_ = pitch;
173 else if (color_type == PNG_COLOR_TYPE_RGB && bit_depth == 8) 306 buffer_ = buffer;
174 {
175 format_ = PixelFormat_Grayscale8;
176 pitch_ = 3 * width_;
177 }
178 else
179 {
180 throw OrthancException(ErrorCode_NotImplemented);
181 }
182
183 buffer_.resize(height_ * pitch_);
184
185 if (height_ == 0 || width_ == 0)
186 {
187 // Empty image, we are done
188 return;
189 }
190
191 png_read_update_info(rabi.png_, rabi.info_);
192
193 std::vector<png_bytep> rows(height_);
194 for (size_t i = 0; i < height_; i++)
195 {
196 rows[i] = &buffer_[0] + i * pitch_;
197 }
198
199 png_read_image(rabi.png_, &rows[0]);
200 }
201
202 void PngReader::ReadFromFile(const char* filename)
203 {
204 FileRabi f(filename);
205
206 char header[8];
207 if (fread(header, 1, 8, f.fp_) != 8)
208 {
209 throw OrthancException(ErrorCode_BadFileFormat);
210 }
211
212 CheckHeader(header);
213
214 PngRabi rabi;
215
216 if (setjmp(png_jmpbuf(rabi.png_)))
217 {
218 rabi.Destruct();
219 throw OrthancException(ErrorCode_BadFileFormat);
220 }
221
222 png_init_io(rabi.png_, f.fp_);
223
224 Read(rabi);
225 } 307 }
226 308
227 309
228 310
229 namespace 311 namespace
296 } 378 }
297 379
298 void PngReader::ReadFromMemory(const std::string& buffer) 380 void PngReader::ReadFromMemory(const std::string& buffer)
299 { 381 {
300 if (buffer.size() != 0) 382 if (buffer.size() != 0)
383 {
301 ReadFromMemory(&buffer[0], buffer.size()); 384 ReadFromMemory(&buffer[0], buffer.size());
385 }
302 else 386 else
387 {
303 ReadFromMemory(NULL, 0); 388 ReadFromMemory(NULL, 0);
389 }
304 } 390 }
305 } 391 }