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 |