Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 124241 | Differences between
and this patch

Collapse All | Expand All

(-)Code/IO/itkPNGImageIO.cxx (-201 / +241 lines)
Lines 1-76 Link Here
1
/*=========================================================================
1
/*=========================================================================
2
2
 *
3
  Program:   Insight Segmentation & Registration Toolkit
3
 *  Copyright Insight Software Consortium
4
  Module:    itkPNGImageIO.cxx
4
 *
5
  Language:  C++
5
 *  Licensed under the Apache License, Version 2.0 (the "License");
6
  Date:      $Date$
6
 *  you may not use this file except in compliance with the License.
7
  Version:   $Revision$
7
 *  You may obtain a copy of the License at
8
8
 *
9
  Copyright (c) Insight Software Consortium. All rights reserved.
9
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
10
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
10
 *
11
11
 *  Unless required by applicable law or agreed to in writing, software
12
     This software is distributed WITHOUT ANY WARRANTY; without even 
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
13
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
     PURPOSE.  See the above copyright notices for more information.
14
 *  See the License for the specific language governing permissions and
15
15
 *  limitations under the License.
16
=========================================================================*/
16
 *
17
 *=========================================================================*/
17
#include "itkPNGImageIO.h"
18
#include "itkPNGImageIO.h"
18
#include "itkRGBPixel.h"
19
#include "itkRGBPixel.h"
19
#include "itkRGBAPixel.h"
20
#include "itkRGBAPixel.h"
20
#include "itk_png.h"
21
#include "itk_png.h"
21
#include <itksys/SystemTools.hxx>
22
#include "itksys/SystemTools.hxx"
22
23
23
namespace itk
24
namespace itk
24
{
25
{
25
26
extern "C"
26
extern "C"
27
{
27
{
28
  #include <setjmp.h>
28
  #include <setjmp.h>
29
  /* The PNG library does not expect the error function to return.
29
/* The PNG library does not expect the error function to return.
30
     Therefore we must use this ugly longjmp call.  */
30
   Therefore we must use this ugly longjmp call.  */
31
  void itkPNGWriteErrorFunction(png_structp png_ptr,
31
void itkPNGWriteErrorFunction( png_structp png_ptr,
32
                                png_const_charp itkNotUsed(error_msg))
32
                               png_const_charp itkNotUsed(error_msg) )
33
    {
33
{
34
    longjmp(png_ptr->jmpbuf, 1);
34
  longjmp(png_jmpbuf(png_ptr), 1);
35
    }
35
}
36
}
36
}
37
38
37
39
extern "C"
38
extern "C"
40
{
39
{
41
  void itkPNGWriteWarningFunction(png_structp itkNotUsed(png_ptr),
40
void itkPNGWriteWarningFunction( png_structp itkNotUsed(png_ptr),
42
                                  png_const_charp itkNotUsed(warning_msg))
41
                                 png_const_charp itkNotUsed(warning_msg) )
43
    {
42
{}
44
    }
45
}
43
}
46
44
47
48
// simple class to call fopen on construct and
45
// simple class to call fopen on construct and
49
// fclose on destruct
46
// fclose on destruct
50
class PNGFileWrapper
47
class PNGFileWrapper
51
{
48
{
52
public:
49
public:
53
  PNGFileWrapper(const char * const fname, const char * const openMode):m_FilePointer(NULL)
50
  PNGFileWrapper(const char *const fname, const char *const openMode):m_FilePointer(NULL)
54
    {
51
  {
55
    m_FilePointer = fopen(fname, openMode);
52
    m_FilePointer = fopen(fname, openMode);
56
    }
53
  }
54
57
  virtual ~PNGFileWrapper()
55
  virtual ~PNGFileWrapper()
58
    {
56
  {
59
    if(m_FilePointer)
57
    if ( m_FilePointer )
60
      {
58
      {
61
      fclose(m_FilePointer);
59
      fclose(m_FilePointer);
62
      }
60
      }
63
    }
61
  }
64
  FILE* m_FilePointer;
62
63
  FILE *m_FilePointer;
65
};
64
};
66
65
67
bool PNGImageIO::CanReadFile(const char* file) 
66
bool PNGImageIO::CanReadFile(const char *file)
68
{ 
67
{
69
  // First check the extension
68
  // First check the extension
70
  std::string filename = file;
69
  std::string filename = file;
71
  if(  filename == "" )
70
71
  if (  filename == "" )
72
    {
72
    {
73
    itkDebugMacro(<<"No filename specified.");
73
    itkDebugMacro(<< "No filename specified.");
74
    return false;
74
    return false;
75
    }
75
    }
76
76
Lines 81-116 Link Here
81
  this->AddSupportedReadExtension(".PNG");
81
  this->AddSupportedReadExtension(".PNG");
82
82
83
  // Now check the file header
83
  // Now check the file header
84
  PNGFileWrapper pngfp(file,"rb");
84
  PNGFileWrapper pngfp(file, "rb");
85
  if(pngfp.m_FilePointer==NULL)
85
  if ( pngfp.m_FilePointer == NULL )
86
    {
86
    {
87
    return false;
87
    return false;
88
    }
88
    }
89
  unsigned char header[8];
89
  unsigned char header[8];
90
  fread(header, 1, 8, pngfp.m_FilePointer);
90
  size_t temp = fread(header, 1, 8, pngfp.m_FilePointer);
91
  if( temp != 8 )
92
    {
93
    itkExceptionMacro( "PNGImageIO failed to read header for file: "
94
      << this->GetFileName() << std::endl
95
      << "Reason: fread read only " << temp
96
      << " instead of 8" );
97
    }
91
  bool is_png = !png_sig_cmp(header, 0, 8);
98
  bool is_png = !png_sig_cmp(header, 0, 8);
92
  if(!is_png)
99
  if ( !is_png )
93
    {
100
    {
94
    return false;
101
    return false;
95
    }
102
    }
96
  png_structp png_ptr = png_create_read_struct
103
  png_structp png_ptr = png_create_read_struct
97
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
104
                          (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
98
     NULL, NULL);
105
                          NULL, NULL);
99
  if (!png_ptr)
106
  if ( !png_ptr )
100
    {
107
    {
101
    return false;
108
    return false;
102
    }
109
    }
103
  
110
104
  png_infop info_ptr = png_create_info_struct(png_ptr);
111
  png_infop info_ptr = png_create_info_struct(png_ptr);
105
  if (!info_ptr)
112
  if ( !info_ptr )
106
    {
113
    {
107
    png_destroy_read_struct(&png_ptr,
114
    png_destroy_read_struct(&png_ptr,
108
                            (png_infopp)NULL, (png_infopp)NULL);
115
                            (png_infopp)NULL, (png_infopp)NULL);
109
    return false;
116
    return false;
110
    }
117
    }
111
  
118
112
  png_infop end_info = png_create_info_struct(png_ptr);
119
  png_infop end_info = png_create_info_struct(png_ptr);
113
  if (!end_info)
120
  if ( !end_info )
114
    {
121
    {
115
    png_destroy_read_struct(&png_ptr, &info_ptr,
122
    png_destroy_read_struct(&png_ptr, &info_ptr,
116
                            (png_infopp)NULL);
123
                            (png_infopp)NULL);
Lines 118-190 Link Here
118
    }
125
    }
119
  png_destroy_read_struct(&png_ptr, &info_ptr,
126
  png_destroy_read_struct(&png_ptr, &info_ptr,
120
                          &end_info);
127
                          &end_info);
121
  
128
122
  return true;
129
  return true;
123
}
130
}
124
  
125
  
126
void PNGImageIO::ReadVolume(void*)
127
{
128
  
129
}
130
131
131
  
132
void PNGImageIO::ReadVolume(void *)
132
void PNGImageIO::Read(void* buffer)
133
{}
134
135
void PNGImageIO::Read(void *buffer)
133
{
136
{
134
  itkDebugMacro("Read: file dimensions = " << this->GetNumberOfDimensions() );
137
  itkDebugMacro( "Read: file dimensions = " << this->GetNumberOfDimensions() );
135
  // use this class so return will call close
138
  // use this class so return will call close
136
  PNGFileWrapper pngfp(this->GetFileName(),"rb"); 
139
  PNGFileWrapper pngfp(this->GetFileName(), "rb");
137
  FILE* fp = pngfp.m_FilePointer;
140
  FILE *         fp = pngfp.m_FilePointer;
138
  if(!fp)
141
  if ( !fp )
139
    {
142
    {
140
    itkExceptionMacro("PNGImageIO could not open file: "
143
    itkExceptionMacro( "PNGImageIO could not open file: "
141
                      << this->GetFileName() << " for reading."
144
                       << this->GetFileName() << " for reading."
142
                      << std::endl
145
                       << std::endl
143
                      << "Reason: "
146
                       << "Reason: "
144
                      << itksys::SystemTools::GetLastSystemError());
147
                       << itksys::SystemTools::GetLastSystemError() );
145
    return;
148
    return;
146
    }
149
    }
147
  unsigned char header[8];
150
  unsigned char header[8];
148
  fread(header, 1, 8, fp);
151
  size_t temp = fread(header, 1, 8, fp);
152
  if( temp != 8 )
153
    {
154
    itkExceptionMacro( "PNGImageIO failed to read header for file: "
155
      << this->GetFileName() << std::endl
156
      << "Reason: fread read only " << temp
157
      << " instead of 8" );
158
    }
159
149
  bool is_png = !png_sig_cmp(header, 0, 8);
160
  bool is_png = !png_sig_cmp(header, 0, 8);
150
  if(!is_png)
161
  if ( !is_png )
151
    {
162
    {
152
    itkExceptionMacro("File is not png type: " << this->GetFileName());
163
    itkExceptionMacro( "File is not png type: " << this->GetFileName() );
153
    return;
164
    return;
154
    }
165
    }
155
  png_structp png_ptr = png_create_read_struct
166
  png_structp png_ptr = png_create_read_struct
156
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
167
                          (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
157
     NULL, NULL);
168
                          NULL, NULL);
158
  if (!png_ptr)
169
  if ( !png_ptr )
159
    {
170
    {
160
    itkExceptionMacro("File is not png type" << this->GetFileName());
171
    itkExceptionMacro( "File is not png type" << this->GetFileName() );
161
    return;
172
    return;
162
    }
173
    }
163
  
174
164
  png_infop info_ptr = png_create_info_struct(png_ptr);
175
  png_infop info_ptr = png_create_info_struct(png_ptr);
165
  if (!info_ptr)
176
  if ( !info_ptr )
166
    {
177
    {
167
    png_destroy_read_struct(&png_ptr,
178
    png_destroy_read_struct(&png_ptr,
168
                            (png_infopp)NULL, (png_infopp)NULL);
179
                            (png_infopp)NULL, (png_infopp)NULL);
169
    itkExceptionMacro("File is not png type " << this->GetFileName());
180
    itkExceptionMacro( "File is not png type " << this->GetFileName() );
170
    return;
181
    return;
171
    }
182
    }
172
183
173
  png_infop end_info = png_create_info_struct(png_ptr);
184
  png_infop end_info = png_create_info_struct(png_ptr);
174
  if (!end_info)
185
  if ( !end_info )
175
    {
186
    {
176
    png_destroy_read_struct(&png_ptr, &info_ptr,
187
    png_destroy_read_struct(&png_ptr, &info_ptr,
177
                            (png_infopp)NULL);
188
                            (png_infopp)NULL);
178
    itkExceptionMacro("File is not png type " << this->GetFileName());
189
    itkExceptionMacro( "File is not png type " << this->GetFileName() );
179
    return;
190
    return;
180
    }
191
    }
181
  
192
182
  //  VS 7.1 has problems with setjmp/longjmp in C++ code
193
  //  VS 7.1 has problems with setjmp/longjmp in C++ code
183
#if !defined(MSC_VER) || _MSC_VER != 1310
194
#if !defined( MSC_VER ) || _MSC_VER != 1310
184
  if( setjmp( png_jmpbuf( png_ptr ) ) )
195
  if ( setjmp( png_jmpbuf(png_ptr) ) )
185
    {
196
    {
186
    png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
197
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
187
    itkExceptionMacro("File is not png type " << this->GetFileName());
198
    itkExceptionMacro( "File is not png type " << this->GetFileName() );
188
    return;
199
    return;
189
    }
200
    }
190
#endif
201
#endif
Lines 195-283 Link Here
195
  png_read_info(png_ptr, info_ptr);
206
  png_read_info(png_ptr, info_ptr);
196
207
197
  png_uint_32 width, height;
208
  png_uint_32 width, height;
198
  int bitDepth, colorType, interlaceType;
209
  int         bitDepth, colorType, interlaceType;
199
  int compression_type, filter_method;
210
  int         compression_type, filter_method;
200
  png_get_IHDR(png_ptr, info_ptr, 
211
  png_get_IHDR(png_ptr, info_ptr,
201
               &width, &height,
212
               &width, &height,
202
               &bitDepth, &colorType, &interlaceType,
213
               &bitDepth, &colorType, &interlaceType,
203
               &compression_type, &filter_method);
214
               &compression_type, &filter_method);
204
215
205
  // convert palettes to RGB
216
  // convert palettes to RGB
206
  if (colorType == PNG_COLOR_TYPE_PALETTE)
217
  if ( colorType == PNG_COLOR_TYPE_PALETTE )
207
    {
218
    {
208
    png_set_palette_to_rgb(png_ptr);
219
    png_set_palette_to_rgb(png_ptr);
209
    }
220
    }
210
221
211
  // minimum of a byte per pixel
222
  // minimum of a byte per pixel
212
  if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) 
223
  if ( colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8 )
213
    {
224
    {
225
#if (PNG_LIBPNG_VER_MAJOR < 2 && PNG_LIBPNG_VER_MINOR < 4)
214
    png_set_gray_1_2_4_to_8(png_ptr);
226
    png_set_gray_1_2_4_to_8(png_ptr);
227
#else
228
    png_set_expand_gray_1_2_4_to_8(png_ptr);
229
#endif
215
    }
230
    }
216
231
217
  // add alpha if any alpha found
232
  // add alpha if any alpha found
218
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
233
  if ( png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) )
219
    {
234
    {
220
    png_set_tRNS_to_alpha(png_ptr);
235
    png_set_tRNS_to_alpha(png_ptr);
221
    }
236
    }
222
237
223
  if (bitDepth > 8)
238
  if ( bitDepth > 8 )
224
    {
239
    {
225
#ifndef ITK_WORDS_BIGENDIAN
240
#ifndef ITK_WORDS_BIGENDIAN
226
    png_set_swap(png_ptr);
241
    png_set_swap(png_ptr);
227
#endif
242
#endif
228
    }
243
    }
229
244
230
  if (info_ptr->valid & PNG_INFO_sBIT)
245
#if (PNG_LIBPNG_VER_MAJOR < 2 && PNG_LIBPNG_VER_MINOR < 5)
246
  if ( info_ptr->valid & PNG_INFO_sBIT )
247
    {
248
    png_set_shift( png_ptr, &( info_ptr->sig_bit ) );
249
    }
250
#else
251
  if ( png_get_valid(png_ptr, info_ptr,PNG_INFO_sBIT ) )
231
    {
252
    {
232
    png_set_shift(png_ptr, &(info_ptr->sig_bit));
253
    png_color_8p bits;
254
    png_get_sBIT(png_ptr,info_ptr,&bits);
255
    png_set_shift( png_ptr, bits);
233
    }
256
    }
257
#endif
234
  // have libpng handle interlacing
258
  // have libpng handle interlacing
235
  //int number_of_passes = png_set_interlace_handling(png_ptr);
259
  //int number_of_passes = png_set_interlace_handling(png_ptr);
236
  // update the info now that we have defined the filters
260
  // update the info now that we have defined the filters
237
  png_read_update_info(png_ptr, info_ptr);
261
  png_read_update_info(png_ptr, info_ptr);
238
262
239
  unsigned long rowbytes = png_get_rowbytes(png_ptr, info_ptr);
263
  SizeValueType  rowbytes = png_get_rowbytes(png_ptr, info_ptr);
240
  unsigned char *tempImage = static_cast<unsigned char*>(buffer);
264
  unsigned char *tempImage = static_cast< unsigned char * >( buffer );
241
  png_bytep *row_pointers = new png_bytep [height];
265
  png_bytep *    row_pointers = new png_bytep[height];
242
  for (unsigned int ui = 0; ui < height; ++ui)
266
  for ( unsigned int ui = 0; ui < height; ++ui )
243
    {
267
    {
244
    row_pointers[ui] = tempImage + rowbytes*ui;
268
    row_pointers[ui] = tempImage + rowbytes * ui;
245
    }
269
    }
246
  png_read_image(png_ptr, row_pointers);
270
  png_read_image(png_ptr, row_pointers);
247
  delete [] row_pointers;
271
  delete[] row_pointers;
248
  // close the file
272
  // close the file
249
  png_read_end(png_ptr, NULL);
273
  png_read_end(png_ptr, NULL);
250
  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
274
  png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
251
252
}
275
}
253
276
254
255
PNGImageIO::PNGImageIO()
277
PNGImageIO::PNGImageIO()
256
{
278
{
257
  this->SetNumberOfDimensions(2);
279
  this->SetNumberOfDimensions(2);
258
  m_PixelType = SCALAR;
280
  m_PixelType = SCALAR;
259
  m_ComponentType = UCHAR;
281
  m_ComponentType = UCHAR;
260
  m_UseCompression = false;
282
  m_UseCompression = false;
261
  m_CompressionLevel = 4; // Range 0-9; 0 = no file compression, 9 = maximum file compression
283
  m_CompressionLevel = 4; // Range 0-9; 0 = no file compression, 9 = maximum
284
                          // file compression
262
  m_Spacing[0] = 1.0;
285
  m_Spacing[0] = 1.0;
263
  m_Spacing[1] = 1.0;
286
  m_Spacing[1] = 1.0;
264
  
287
265
  m_Origin[0] = 0.0;
288
  m_Origin[0] = 0.0;
266
  m_Origin[1] = 0.0;
289
  m_Origin[1] = 0.0;
267
}
290
}
268
291
269
PNGImageIO::~PNGImageIO()
292
PNGImageIO::~PNGImageIO()
270
{
293
{}
271
}
272
294
273
void PNGImageIO::PrintSelf(std::ostream& os, Indent indent) const
295
void PNGImageIO::PrintSelf(std::ostream & os, Indent indent) const
274
{
296
{
275
  Superclass::PrintSelf(os, indent);
297
  Superclass::PrintSelf(os, indent);
276
  os << indent << "Compression Level : " << m_CompressionLevel << "\n";
298
  os << indent << "Compression Level : " << m_CompressionLevel << "\n";
277
}
299
}
278
300
279
  
280
  
281
void PNGImageIO::ReadImageInformation()
301
void PNGImageIO::ReadImageInformation()
282
{
302
{
283
  m_Spacing[0] = 1.0;  // We'll look for PNG pixel size information later,
303
  m_Spacing[0] = 1.0;  // We'll look for PNG pixel size information later,
Lines 287-315 Link Here
287
  m_Origin[1] = 0.0;
307
  m_Origin[1] = 0.0;
288
308
289
  // use this class so return will call close
309
  // use this class so return will call close
290
  PNGFileWrapper pngfp(m_FileName.c_str(),"rb");
310
  PNGFileWrapper pngfp(m_FileName.c_str(), "rb");
291
  FILE* fp = pngfp.m_FilePointer;
311
  FILE *         fp = pngfp.m_FilePointer;
292
  if(!fp)
312
  if ( !fp )
293
    {
313
    {
294
    return;
314
    return;
295
    }
315
    }
296
  unsigned char header[8];
316
  unsigned char header[8];
297
  fread(header, 1, 8, fp);
317
  size_t temp = fread(header, 1, 8, fp);
318
  if( temp != 8 )
319
    {
320
    itkExceptionMacro( "PNGImageIO failed to read header for file: "
321
      << this->GetFileName() << std::endl
322
      << "Reason: fread read only " << temp
323
      << " instead of 8" );
324
    }
325
298
  bool is_png = !png_sig_cmp(header, 0, 8);
326
  bool is_png = !png_sig_cmp(header, 0, 8);
299
  if(!is_png)
327
  if ( !is_png )
300
    {
328
    {
301
    return;
329
    return;
302
    }
330
    }
303
  png_structp png_ptr = png_create_read_struct
331
  png_structp png_ptr = png_create_read_struct
304
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
332
                          (PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
305
     NULL, NULL);
333
                          NULL, NULL);
306
  if (!png_ptr)
334
  if ( !png_ptr )
307
    {
335
    {
308
    return;
336
    return;
309
    }
337
    }
310
  
338
311
  png_infop info_ptr = png_create_info_struct(png_ptr);
339
  png_infop info_ptr = png_create_info_struct(png_ptr);
312
  if (!info_ptr)
340
  if ( !info_ptr )
313
    {
341
    {
314
    png_destroy_read_struct(&png_ptr,
342
    png_destroy_read_struct(&png_ptr,
315
                            (png_infopp)NULL, (png_infopp)NULL);
343
                            (png_infopp)NULL, (png_infopp)NULL);
Lines 317-356 Link Here
317
    }
345
    }
318
346
319
  png_infop end_info = png_create_info_struct(png_ptr);
347
  png_infop end_info = png_create_info_struct(png_ptr);
320
  if (!end_info)
348
  if ( !end_info )
321
    {
349
    {
322
    png_destroy_read_struct(&png_ptr, &info_ptr,
350
    png_destroy_read_struct(&png_ptr, &info_ptr,
323
                            (png_infopp)NULL);
351
                            (png_infopp)NULL);
324
    return;
352
    return;
325
    }
353
    }
326
  
354
327
  png_init_io(png_ptr, fp);
355
  png_init_io(png_ptr, fp);
328
  png_set_sig_bytes(png_ptr, 8);
356
  png_set_sig_bytes(png_ptr, 8);
329
357
330
  png_read_info(png_ptr, info_ptr);
358
  png_read_info(png_ptr, info_ptr);
331
359
332
  png_uint_32 width, height;
360
  png_uint_32 width, height;
333
  int bitDepth, colorType, interlaceType;
361
  int         bitDepth, colorType, interlaceType;
334
  int compression_type, filter_method;
362
  int         compression_type, filter_method;
335
  png_get_IHDR(png_ptr, info_ptr, 
363
  png_get_IHDR(png_ptr, info_ptr,
336
               &width, &height,
364
               &width, &height,
337
               &bitDepth, &colorType, &interlaceType,
365
               &bitDepth, &colorType, &interlaceType,
338
               &compression_type, &filter_method);
366
               &compression_type, &filter_method);
339
367
340
  // convert palettes to RGB
368
  // convert palettes to RGB
341
  if (colorType == PNG_COLOR_TYPE_PALETTE)
369
  if ( colorType == PNG_COLOR_TYPE_PALETTE )
342
    {
370
    {
343
    png_set_palette_to_rgb(png_ptr);
371
    png_set_palette_to_rgb(png_ptr);
344
    }
372
    }
345
373
346
  // minimum of a byte per pixel
374
  // minimum of a byte per pixel
347
  if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) 
375
  if ( colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8 )
348
    {
376
    {
377
#if (PNG_LIBPNG_VER_MAJOR < 2 && PNG_LIBPNG_VER_MINOR < 4)
349
    png_set_gray_1_2_4_to_8(png_ptr);
378
    png_set_gray_1_2_4_to_8(png_ptr);
379
#else
380
    png_set_expand_gray_1_2_4_to_8(png_ptr);
381
#endif
350
    }
382
    }
351
383
352
  // add alpha if any alpha found
384
  // add alpha if any alpha found
353
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) 
385
  if ( png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) )
354
    {
386
    {
355
    png_set_tRNS_to_alpha(png_ptr);
387
    png_set_tRNS_to_alpha(png_ptr);
356
    }
388
    }
Lines 360-366 Link Here
360
  this->SetNumberOfDimensions(2);
392
  this->SetNumberOfDimensions(2);
361
  m_Dimensions[0] = width;
393
  m_Dimensions[0] = width;
362
  m_Dimensions[1] = height;
394
  m_Dimensions[1] = height;
363
  if (bitDepth <= 8)
395
  if ( bitDepth <= 8 )
364
    {
396
    {
365
    m_PixelType = SCALAR;
397
    m_PixelType = SCALAR;
366
    m_ComponentType = UCHAR;
398
    m_ComponentType = UCHAR;
Lines 370-382 Link Here
370
    m_PixelType = SCALAR;
402
    m_PixelType = SCALAR;
371
    m_ComponentType = USHORT;
403
    m_ComponentType = USHORT;
372
    }
404
    }
373
  this->SetNumberOfComponents(png_get_channels(png_ptr, info_ptr));
405
  this->SetNumberOfComponents( png_get_channels(png_ptr, info_ptr) );
374
406
375
  if (this->GetNumberOfComponents() == 3)
407
  if ( this->GetNumberOfComponents() == 3 )
376
    {
408
    {
377
    m_PixelType = RGB;
409
    m_PixelType = RGB;
378
    }
410
    }
379
  else if (this->GetNumberOfComponents() == 4)
411
  else if ( this->GetNumberOfComponents() == 4 )
380
    {
412
    {
381
    m_PixelType = RGBA;
413
    m_PixelType = RGBA;
382
    }
414
    }
Lines 384-396 Link Here
384
  // see if the PNG file stored spacing information,
416
  // see if the PNG file stored spacing information,
385
  // ignore the units (for now).
417
  // ignore the units (for now).
386
  double px_width = 1.0, px_height = 1.0; // use default values if not in file
418
  double px_width = 1.0, px_height = 1.0; // use default values if not in file
387
  int units = PNG_SCALE_UNKNOWN;
419
  int    units = PNG_SCALE_UNKNOWN;
388
  png_get_sCAL(png_ptr, info_ptr, &units, &px_width, &px_height);
420
  png_get_sCAL(png_ptr, info_ptr, &units, &px_width, &px_height);
389
421
390
  m_Spacing[0] = px_width;
422
  m_Spacing[0] = px_width;
391
  m_Spacing[1] = px_height;
423
  m_Spacing[1] = px_height;
392
424
393
394
  // clean up
425
  // clean up
395
  png_destroy_read_struct(&png_ptr, &info_ptr,
426
  png_destroy_read_struct(&png_ptr, &info_ptr,
396
                          &end_info);
427
                          &end_info);
Lines 398-460 Link Here
398
  return;
429
  return;
399
}
430
}
400
431
401
bool PNGImageIO::CanWriteFile( const char * name )
432
bool PNGImageIO::CanWriteFile(const char *name)
402
{
433
{
403
  std::string filename = name;
434
  std::string filename = name;
404
435
405
  if (filename == "")
436
  if ( filename == "" )
406
    {
437
    {
407
    return false;
438
    return false;
408
    }
439
    }
409
  
440
410
  std::string::size_type pngPos = filename.rfind(".png");
441
  std::string::size_type pngPos = filename.rfind(".png");
411
  if ( (pngPos != std::string::npos)
442
  if ( ( pngPos != std::string::npos )
412
       && (pngPos == filename.length() - 4) )
443
       && ( pngPos == filename.length() - 4 ) )
413
    {
444
    {
414
    return true;
445
    return true;
415
    }
446
    }
416
447
417
  pngPos = filename.rfind(".PNG");
448
  pngPos = filename.rfind(".PNG");
418
  if ( (pngPos != std::string::npos)
449
  if ( ( pngPos != std::string::npos )
419
       && (pngPos == filename.length() - 4) )
450
       && ( pngPos == filename.length() - 4 ) )
420
    {
451
    {
421
    return true;
452
    return true;
422
    }
453
    }
423
454
424
425
  return false;
455
  return false;
426
}
456
}
427
457
428
429
void PNGImageIO::WriteImageInformation(void)
458
void PNGImageIO::WriteImageInformation(void)
430
{
459
{}
431
}
432
460
433
void PNGImageIO::Write(const void* buffer)
461
void PNGImageIO::Write(const void *buffer)
434
{
462
{
435
  this->WriteSlice(m_FileName, buffer);
463
  this->WriteSlice(m_FileName, buffer);
436
}
464
}
437
465
438
void PNGImageIO::WriteSlice(const std::string& fileName, const void* buffer)
466
void PNGImageIO::WriteSlice(const std::string & fileName, const void *buffer)
439
{
467
{
440
  volatile const unsigned char *outPtr = ( (const unsigned char *) buffer);
441
442
  // use this class so return will call close
468
  // use this class so return will call close
443
  PNGFileWrapper pngfp(fileName.c_str(),"wb");
469
  PNGFileWrapper pngfp(fileName.c_str(), "wb");
444
  FILE* fp = pngfp.m_FilePointer;
470
  FILE *         fp = pngfp.m_FilePointer;
445
  if(!fp)
471
472
  if ( !fp )
446
    {
473
    {
447
    // IMPORTANT: The itkExceptionMacro() cannot be used here due to a bug in Visual
474
    // IMPORTANT: The itkExceptionMacro() cannot be used here due to a bug in
448
    //            Studio 7.1 in release mode. That compiler will corrupt the RTTI type
475
    // Visual
476
    //            Studio 7.1 in release mode. That compiler will corrupt the
477
    // RTTI type
449
    //            of the Exception and prevent the catch() from recognizing it.
478
    //            of the Exception and prevent the catch() from recognizing it.
450
    //            For details, see Bug # 1872 in the bugtracker.
479
    //            For details, see Bug #1872 in the bugtracker.
451
480
452
    ::itk::ExceptionObject excp(__FILE__, __LINE__, "Problem while opening the file.", ITK_LOCATION); 
481
    ::itk::ExceptionObject excp(__FILE__, __LINE__, "Problem while opening the file.", ITK_LOCATION);
453
    throw excp; 
482
    throw excp;
454
    }
483
    }
455
484
456
  volatile int bitDepth;
485
  volatile int bitDepth;
457
  switch (this->GetComponentType())
486
  switch ( this->GetComponentType() )
458
    {
487
    {
459
    case UCHAR:
488
    case UCHAR:
460
      bitDepth = 8;
489
      bitDepth = 8;
Lines 466-533 Link Here
466
495
467
    default:
496
    default:
468
      {
497
      {
469
      // IMPORTANT: The itkExceptionMacro() cannot be used here due to a bug in Visual
498
      // IMPORTANT: The itkExceptionMacro() cannot be used here due to a bug in
470
      //            Studio 7.1 in release mode. That compiler will corrupt the RTTI type
499
      // Visual
471
      //            of the Exception and prevent the catch() from recognizing it.
500
      //            Studio 7.1 in release mode. That compiler will corrupt the
472
      //            For details, see Bug # 1872 in the bugtracker.
501
      // RTTI type
502
      //            of the Exception and prevent the catch() from recognizing
503
      // it.
504
      //            For details, see Bug #1872 in the bugtracker.
473
      ::itk::ExceptionObject excp(__FILE__, __LINE__, "PNG supports unsigned char and unsigned short", ITK_LOCATION);
505
      ::itk::ExceptionObject excp(__FILE__, __LINE__, "PNG supports unsigned char and unsigned short", ITK_LOCATION);
474
      throw excp; 
506
      throw excp;
475
      }
507
      }
476
    }
508
    }
477
  
509
478
  png_structp png_ptr = png_create_write_struct
510
  png_structp png_ptr = png_create_write_struct
479
    (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
511
                          (PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL);
480
  if (!png_ptr)
512
  if ( !png_ptr )
481
    {
513
    {
482
    itkExceptionMacro(<<"Unable to write PNG file! png_create_write_struct failed.");
514
    itkExceptionMacro(<< "Unable to write PNG file! png_create_write_struct failed.");
483
    }
515
    }
484
  
516
485
  png_infop info_ptr = png_create_info_struct(png_ptr);
517
  png_infop info_ptr = png_create_info_struct(png_ptr);
486
  if (!info_ptr)
518
  if ( !info_ptr )
487
    {
519
    {
488
    png_destroy_write_struct(&png_ptr,
520
    png_destroy_write_struct(&png_ptr,
489
                             (png_infopp)NULL);
521
                             (png_infopp)NULL);
490
    itkExceptionMacro(<<"Unable to write PNG file!. png_create_info_struct failed.");
522
    itkExceptionMacro(<< "Unable to write PNG file!. png_create_info_struct failed.");
491
    }
523
    }
492
524
493
  png_init_io(png_ptr, fp);
525
  png_init_io(png_ptr, fp);
494
526
495
//  VS 7.1 has problems with setjmp/longjmp in C++ code
527
//  VS 7.1 has problems with setjmp/longjmp in C++ code
496
#if !defined(_MSC_VER) || _MSC_VER != 1310
528
#if !defined( _MSC_VER ) || _MSC_VER != 1310
497
  png_set_error_fn(png_ptr, png_ptr,
529
  png_set_error_fn(png_ptr, png_ptr,
498
                   itkPNGWriteErrorFunction, itkPNGWriteWarningFunction);
530
                   itkPNGWriteErrorFunction, itkPNGWriteWarningFunction);
499
  if (setjmp(png_ptr->jmpbuf))
531
  if ( setjmp(png_jmpbuf(png_ptr)) )
500
    {
532
    {
501
    fclose(fp);
533
    fclose(fp);
502
    itkExceptionMacro("Error while writing Slice to file: "
534
    itkExceptionMacro( "Error while writing Slice to file: "
503
                      <<this->GetFileName()
535
                       << this->GetFileName()
504
                      << std::endl
536
                       << std::endl
505
                      << "Reason: "
537
                       << "Reason: "
506
                      << itksys::SystemTools::GetLastSystemError());
538
                       << itksys::SystemTools::GetLastSystemError() );
507
    return;
539
    return;
508
    } 
540
    }
509
#endif
541
#endif
510
542
511
  int colorType;
543
  int          colorType;
512
  unsigned int numComp = this->GetNumberOfComponents();
544
  unsigned int numComp = this->GetNumberOfComponents();
513
  switch ( numComp )
545
  switch ( numComp )
514
    {
546
    {
515
    case 1: colorType = PNG_COLOR_TYPE_GRAY;
547
    case 1:
548
      colorType = PNG_COLOR_TYPE_GRAY;
516
      break;
549
      break;
517
    case 2: colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
550
    case 2:
551
      colorType = PNG_COLOR_TYPE_GRAY_ALPHA;
518
      break;
552
      break;
519
    case 3: colorType = PNG_COLOR_TYPE_RGB;
553
    case 3:
554
      colorType = PNG_COLOR_TYPE_RGB;
520
      break;
555
      break;
521
    default: colorType = PNG_COLOR_TYPE_RGB_ALPHA;
556
    default:
557
      colorType = PNG_COLOR_TYPE_RGB_ALPHA;
522
      break;
558
      break;
523
    }
559
    }
524
  
560
525
  png_uint_32 width, height;
561
  png_uint_32 width, height;
526
  double rowSpacing, colSpacing;
562
  double      rowSpacing, colSpacing;
527
  width = this->GetDimensions(0);
563
  width = this->GetDimensions(0);
528
  colSpacing = m_Spacing[0];
564
  colSpacing = m_Spacing[0];
529
565
530
  if( m_NumberOfDimensions > 1 )
566
  if ( m_NumberOfDimensions > 1 )
531
    {
567
    {
532
    height = this->GetDimensions(1);
568
    height = this->GetDimensions(1);
533
    rowSpacing = m_Spacing[1];
569
    rowSpacing = m_Spacing[1];
Lines 537-586 Link Here
537
    height = 1;
573
    height = 1;
538
    rowSpacing = 1;
574
    rowSpacing = 1;
539
    }
575
    }
540
  
576
541
  png_set_IHDR(png_ptr, info_ptr, width, height,
577
  png_set_IHDR(png_ptr, info_ptr, width, height,
542
               bitDepth, colorType, PNG_INTERLACE_NONE,
578
               bitDepth, colorType, PNG_INTERLACE_NONE,
543
               PNG_COMPRESSION_TYPE_DEFAULT, 
579
               PNG_COMPRESSION_TYPE_DEFAULT,
544
               PNG_FILTER_TYPE_DEFAULT);
580
               PNG_FILTER_TYPE_DEFAULT);
545
  // interlaceType - PNG_INTERLACE_NONE or
581
  // interlaceType - PNG_INTERLACE_NONE or
546
  //                 PNG_INTERLACE_ADAM7
582
  //                 PNG_INTERLACE_ADAM7
547
    
583
548
  if(m_UseCompression)
584
  if ( m_UseCompression )
549
    {
585
    {
550
    // Set the image compression level.
586
    // Set the image compression level.
551
    png_set_compression_level(png_ptr, m_CompressionLevel); 
587
    png_set_compression_level(png_ptr, m_CompressionLevel);
552
    }
588
    }
553
589
554
  // write out the spacing information:
590
  // write out the spacing information:
555
  //      set the unit_type to unknown.  if we add units to ITK, we should
591
  //      set the unit_type to unknown.  if we add units to ITK, we should
556
  //          convert pixel size to meters and store units as meters (png
592
  //          convert pixel size to meters and store units as meters (png
557
  //          has three set of units: meters, radians, and unknown).
593
  //          has three set of units: meters, radians, and unknown).
594
#if (PNG_LIBPNG_VER_MAJOR < 2 && PNG_LIBPNG_VER_MINOR < 4)
558
  png_set_sCAL(png_ptr, info_ptr, PNG_SCALE_UNKNOWN, colSpacing,
595
  png_set_sCAL(png_ptr, info_ptr, PNG_SCALE_UNKNOWN, colSpacing,
559
               rowSpacing);
596
               rowSpacing);
597
#endif
560
598
561
  //std::cout << "PNG_INFO_sBIT: " << PNG_INFO_sBIT << std::endl;
599
  //std::cout << "PNG_INFO_sBIT: " << PNG_INFO_sBIT << std::endl;
562
600
563
  png_write_info(png_ptr, info_ptr);
601
  png_write_info(png_ptr, info_ptr);
564
  // default is big endian
602
  // default is big endian
565
  if (bitDepth > 8)
603
  if ( bitDepth > 8 )
566
    {
604
    {
567
#ifndef ITK_WORDS_BIGENDIAN
605
#ifndef ITK_WORDS_BIGENDIAN
568
    png_set_swap(png_ptr);
606
    png_set_swap(png_ptr);
569
#endif
607
#endif
570
    }
608
    }
571
  png_byte **row_pointers = new png_byte *[height];
609
  png_byte **row_pointers = new png_byte *[height];
572
  int rowInc = width*numComp*bitDepth/8;
610
573
  for (unsigned int ui = 0; ui < height; ui++)
574
    {
611
    {
575
    row_pointers[ui] = const_cast<png_byte *>(outPtr);
612
    const int        rowInc = width * numComp * bitDepth / 8;
576
    outPtr = const_cast<unsigned char *>(outPtr) + rowInc;
613
    volatile const unsigned char *outPtr = ( (const unsigned char *)buffer );
614
    for ( unsigned int ui = 0; ui < height; ui++ )
615
      {
616
      row_pointers[ui] = const_cast< png_byte * >( outPtr );
617
      outPtr = const_cast< unsigned char * >( outPtr ) + rowInc;
618
      }
577
    }
619
    }
578
  png_write_image(png_ptr, row_pointers);
620
  png_write_image(png_ptr, row_pointers);
579
  png_write_end(png_ptr, info_ptr);
621
  png_write_end(png_ptr, info_ptr);
580
622
581
  delete [] row_pointers;
623
  delete[] row_pointers;
582
  png_destroy_write_struct(&png_ptr, &info_ptr);
624
  png_destroy_write_struct(&png_ptr, &info_ptr);
583
}
625
}
584
585
586
} // end namespace itk
626
} // end namespace itk

Return to bug 124241