1 /*=========================================================================
4 Module: $RCSfile: gdcmPixelWriteConvert.cxx,v $
6 Date: $Date: 2007/08/21 12:51:10 $
7 Version: $Revision: 1.15 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "gdcmDebug.h"
20 #include "gdcmPixelWriteConvert.h"
26 #define WITHOFFSETTABLE 1
28 namespace GDCM_NAME_SPACE
30 //-----------------------------------------------------------------------------
33 //-----------------------------------------------------------------------------
36 //-----------------------------------------------------------------------------
39 // Constructor / Destructor
43 PixelWriteConvert::PixelWriteConvert()
56 PixelWriteConvert::~PixelWriteConvert()
65 * \brief sets Read Data (and size)
66 * @param data data (uint8_t is for prototyping. if your data is not uint8_t
67 * just cast the pointer for calling the method)
68 * @param size data size, in bytes
70 void PixelWriteConvert::SetReadData(uint8_t *data, size_t size)
77 * \brief Sets the internal pointer to the caller's inData
78 * image representation, WITHOUT COPYING THE DATA.
79 * - 'image' Pixels are presented as C-like 2D arrays : line per line.
80 * - 'volume'Pixels are presented as C-like 3D arrays : plane per plane
81 * \warning Since the pixels are not copied, it is the caller's responsability
82 * not to deallocate its data before gdcm uses them (e.g. with
83 * the Write() method )
84 * @param data data (uint8_t is for prototyping. if your data is not uint8_t
85 * just cast the pointer for calling the method)
86 * @param size size, in bytes.
88 void PixelWriteConvert::SetUserData(uint8_t *data, size_t size)
95 * \brief Get Data (UserData or ReadData)
96 * @return data (uint8_t is for prototyping. if your data is *not* uint8_t
97 * just cast the returned pointer)
99 uint8_t *PixelWriteConvert::GetData()
112 * \brief Get Data Size (UserData or ReadData)
113 * @return size, in bytes.
115 size_t PixelWriteConvert::GetDataSize()
128 typedef std::pair<size_t, uint32_t> JpegPair; //offset, jpeg size
129 typedef std::vector<JpegPair> JpegVector;
131 bool gdcm_write_JPEG2000_file (std::ostream *of, char *inputdata, size_t inputlength,
132 int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated,
133 int sign, int quality);
136 void WriteDICOMItems(std::ostream *fp, JpegVector &v)
139 uint16_t group = 0xfffe;
140 uint16_t elem = 0xe000;
141 GDCM_NAME_SPACE::binary_write(*fp, group);
142 GDCM_NAME_SPACE::binary_write(*fp, elem);
144 uint32_t dummy = 0x12345678;
145 size_t offset = fp->tellp();
149 GDCM_NAME_SPACE::binary_write(*fp, dummy);
153 void EncodeWithoutBasicOffsetTable(std::ostream *fp, int numFrag)// JpegVector& v) //, uint32_t length)
155 assert( numFrag == 1);
158 uint16_t group = 0xfffe;
159 uint16_t elem = 0xe000;
160 GDCM_NAME_SPACE::binary_write(*fp, group);
161 GDCM_NAME_SPACE::binary_write(*fp, elem);
163 uint32_t item_length = 0x0000;
164 GDCM_NAME_SPACE::binary_write(*fp, item_length);
169 void EncodeWithBasicOffsetTable(std::ostream *fp, int numFrag, size_t &start)
172 uint16_t group = 0xfffe;
173 uint16_t elem = 0xe000;
174 GDCM_NAME_SPACE::binary_write(*fp, group);
175 GDCM_NAME_SPACE::binary_write(*fp, elem);
177 uint32_t item_length = numFrag*4; // sizeof(uint32_t)
178 GDCM_NAME_SPACE::binary_write(*fp, item_length);
180 // Just prepare the space
181 start = fp->tellp(); //to be able to rewind
182 for(int i=0; i<numFrag;++i)
184 uint32_t dummy = 0x0000;
185 GDCM_NAME_SPACE::binary_write(*fp, dummy);
189 void UpdateBasicOffsetTable(std::ostream *fp, JpegVector const &v, size_t pos)
191 JpegVector::const_iterator i;
193 const JpegPair &first = v[0];
194 for(i=v.begin(); i!=v.end(); ++i)
196 const JpegPair &jp = *i;
197 if(i == v.begin() ){ assert( jp.first - first.first == 0); }
198 uint32_t offset = (uint32_t)(jp.first - first.first);
199 gdcm::binary_write(*fp, offset);
200 //std::cerr << "Updating Table:" << jp.first - first.first << std::endl;
204 void UpdateJpegFragmentSize(std::ostream *fp, JpegVector const &v)
206 JpegVector::const_iterator i;
207 for(i= v.begin(); i!=v.end(); ++i)
209 const JpegPair &jp = *i;
210 fp->seekp( jp.first );
211 uint32_t length = jp.second;
212 GDCM_NAME_SPACE::binary_write(*fp, length);
213 //std::cerr << "Updating:" << jp.first << "," << jp.second << std::endl;
217 void CloseJpeg(std::ostream *fp, JpegVector &v)
219 // sequence terminator
220 uint16_t group = 0xfffe;
221 uint16_t elem = 0xe0dd;
222 GDCM_NAME_SPACE::binary_write(*fp, group);
223 GDCM_NAME_SPACE::binary_write(*fp, elem);
225 uint32_t length = 0x0;
226 GDCM_NAME_SPACE::binary_write(*fp, length);
228 // Jpeg is done, now update the frag length
229 UpdateJpegFragmentSize(fp, v);
232 // I need to pass the File*. I do not understand how PixelWriteConvert is supposed
233 // to access this information otherwise
234 // size can now be computer from File attributes (what an API...)
235 void PixelWriteConvert::SetCompressJPEG2000UserData(uint8_t *data, size_t size, File *image)
238 //char * userData = reinterpret_cast<char*>(UserData);
240 std::ostringstream *of = new std::ostringstream();
241 int xsize = image->GetXSize();
242 int ysize = image->GetYSize();
243 int zsize = image->GetZSize();
244 int samplesPerPixel = image->GetSamplesPerPixel();
245 //std::cout << "X: " << xsize << std::endl;
246 //std::cout << "Y: " << ysize << std::endl;
247 //std::cout << "Sample: " << samplesPerPixel << std::endl;
248 int bitsallocated = image->GetBitsAllocated();
249 int sign = image->IsSignedPixelData();
250 unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
251 assert( fragment_size*zsize == size );
253 JpegVector JpegFragmentSize;
255 size_t bots; //basic offset table start
256 EncodeWithBasicOffsetTable(of, zsize, bots);
258 EncodeWithoutBasicOffsetTable(of, 1);
260 uint8_t *pImageData = data;
261 for(int i=0; i<zsize;i++)
263 WriteDICOMItems(of, JpegFragmentSize);
264 size_t beg = of->tellp();
265 gdcm_write_JPEG2000_file(of, (char*)pImageData,size,
266 image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
267 image->GetBitsAllocated(), sign, 100);
268 //userData, UserDataSize);
269 // CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize,
270 // samplesPerPixel, quality, JpegFragmentSize);
271 //assert( !(fragment_size % 2) );
272 // Update the JpegVector with offset
273 size_t end = of->tellp();
275 JpegPair &jp = JpegFragmentSize[i];
276 jp.second = (uint32_t)(end-beg);
277 if( ((end-beg) % 2) )
282 assert( !(jp.second % 2) );
283 //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
285 pImageData += fragment_size;
287 CloseJpeg(of, JpegFragmentSize);
289 UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
293 size_t of_size = of->str().size();
294 UserData = new uint8_t[of_size];
295 memcpy(UserData, of->str().c_str(), of_size);
296 UserDataSize = of_size;
300 bool gdcm_write_JPEG_file8 (std::ostream *fp, char *inputdata, size_t inputlength,
301 int image_width, int image_height, int numZ,
302 int sample_pixel, int bitsallocated, int quality);
303 bool gdcm_write_JPEG_file12 (std::ostream *fp, char *inputdata, size_t inputlength,
304 int image_width, int image_height, int numZ,
305 int sample_pixel, int bitsallocated, int quality);
306 bool gdcm_write_JPEG_file16 (std::ostream *fp, char *inputdata, size_t inputlength,
307 int image_width, int image_height, int numZ,
308 int sample_pixel, int bitsallocated, int quality);
310 void PixelWriteConvert::SetCompressJPEGUserData(uint8_t *data, size_t size, File *image)
313 std::cerr << "entree ds PixelWriteConvert::SetCompressJPEGUserData" << std::endl;
319 //char * userData = reinterpret_cast<char*>(UserData);
321 std::ostringstream *of = new std::ostringstream();
322 int xsize = image->GetXSize();
323 int ysize = image->GetYSize();
324 int zsize = image->GetZSize();
325 int samplesPerPixel = image->GetSamplesPerPixel();
326 //std::cout << "X: " << xsize << std::endl;
327 //std::cout << "Y: " << ysize << std::endl;
328 //std::cout << "Sample: " << samplesPerPixel << std::endl;
329 int bitsallocated = image->GetBitsAllocated();
330 unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
331 assert( fragment_size*zsize == size );
333 JpegVector JpegFragmentSize;
335 size_t bots; //basic offset table start
336 EncodeWithBasicOffsetTable(of, zsize, bots);
338 EncodeWithoutBasicOffsetTable(of, 1);
340 uint8_t *pImageData = data;
341 for(int i=0; i<zsize;i++)
343 WriteDICOMItems(of, JpegFragmentSize);
344 size_t beg = of->tellp();
345 if( bitsallocated == 8 )
347 gdcm_write_JPEG_file8(of, (char*)pImageData,size,
348 image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
349 image->GetBitsAllocated(), 100 );
351 else if (bitsallocated <= 12)
353 assert( bitsallocated >= 8 );
354 gdcm_write_JPEG_file12(of, (char*)pImageData,size,
355 image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
356 image->GetBitsAllocated(), 100);
358 else if (bitsallocated <= 16)
360 assert( bitsallocated >= 12 );
361 gdcm_write_JPEG_file16(of, (char*)pImageData,size,
362 image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
363 image->GetBitsAllocated(), 100);
369 size_t end = of->tellp();
371 JpegPair &jp = JpegFragmentSize[i];
372 jp.second = (uint32_t)(end-beg);
373 if( ((end-beg) % 2) )
378 assert( !(jp.second % 2) );
379 //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
382 //JpegPair &jp = v[0];
386 //userData, UserDataSize);
387 // CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize,
388 // samplesPerPixel, quality, JpegFragmentSize);
389 //assert( !(fragment_size % 2) );
390 pImageData += fragment_size;
392 CloseJpeg(of, JpegFragmentSize);
394 UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
398 size_t of_size = of->str().size();
399 UserData = new uint8_t[of_size];
400 memcpy(UserData, of->str().c_str(), of_size);
401 UserDataSize = of_size;
406 //-----------------------------------------------------------------------------
408 //bool PixelWriteConvert::CompressJPEG2000(uint8_t *data, size_t size)
412 //-----------------------------------------------------------------------------
415 //-----------------------------------------------------------------------------
418 //-----------------------------------------------------------------------------
419 } // end namespace gdcm