OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimPngReader.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // License: LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: David Burken
8 //
9 // Description: OSSIM Portable Network Graphics (PNG) reader (tile source).
10 //
11 //----------------------------------------------------------------------------
12 // $Id: ossimPngReader.cpp 23355 2015-06-01 23:55:15Z dburken $
13 
14 
15 #include "ossimPngReader.h"
18 #include <ossim/base/ossimEndian.h>
20 #include <ossim/base/ossimIpt.h>
21 #include <ossim/base/ossimIrect.h>
26 #include <ossim/base/ossimTrace.h>
28 
29 #include <zlib.h>
30 
31 #include <cstddef> /* for NULL */
32 #include <cmath> /* for pow */
33 #include <fstream>
34 
35 // If true alpha channel is passed as a layer.
36 static const std::string USE_ALPHA_KW = "use_alpha"; // boolean
37 
38 RTTI_DEF1(ossimPngReader, "ossimPngReader", ossimImageHandler)
39 
40 #ifdef OSSIM_ID_ENABLED
41  static const char OSSIM_ID[] = "$Id: ossimPngReader.cpp 23355 2015-06-01 23:55:15Z dburken $";
42 #endif
43 
44 static ossimTrace traceDebug("ossimPngReader:degug");
45 
47  :
49  m_tile(0),
50  m_cacheTile(0),
51  m_lineBuffer(0),
52  m_lineBufferSizeInBytes(0),
53  m_str(0),
54  m_bufferRect(0, 0, 0, 0),
55  m_imageRect(0, 0, 0, 0),
56  m_numberOfInputBands(0),
57  m_numberOfOutputBands(0),
58  m_bytePerPixelPerBand(1),
59  m_cacheSize(0),
60  m_cacheId(-1),
61  m_pngReadPtr(0),
62  m_pngReadInfoPtr(0),
63  m_pngColorType(PNG_COLOR_TYPE_GRAY),
64  m_currentRow(0),
65  m_outputScalarType(OSSIM_UINT8),
66  m_interlacePasses(1),
67  m_bitDepth(8),
68  m_readMode(ossimPngReadUnknown),
69  m_maxPixelValue(),
70  m_swapFlag(false),
71  m_useAlphaChannelFlag(false)
72 {
73  if (traceDebug())
74  {
76  << "ossimPngReader::ossimPngReader entered..." << std::endl;
78 #ifdef OSSIM_ID_ENABLED
80  << "OSSIM_ID: " << OSSIM_ID << endl;
81 #endif
82  }
83 }
84 
86 {
87  if (isOpen())
88  {
89  close();
90  }
91 }
92 
94 {
95  destroy();
97 }
98 
100 {
102 
103  // ossimRefPtrs so assign to 0(unreferencing) will handle memory.
104  m_tile = 0;
105  m_cacheTile = 0;
106 
107  if (m_lineBuffer)
108  {
109  delete [] m_lineBuffer;
110  m_lineBuffer = 0;
111  }
112 
113  if (m_pngReadPtr)
114  {
115  png_destroy_read_struct(&m_pngReadPtr, &m_pngReadInfoPtr, NULL);
116  m_pngReadPtr = 0;
117  m_pngReadInfoPtr = 0;
118  }
119 
120  // Stream data member m_str is share pointer now:
121  m_str = 0;
122 }
123 
125 {
126  // Make the cache tile the height of one tile by the image width.
129 
132  newTileCache(m_imageRect, m_cacheSize);
133 
136  m_tile->initialize();
137 
138  ossimIrect cache_rect(m_imageRect.ul().x,
139  m_imageRect.ul().y,
140  m_imageRect.ul().x + (m_cacheSize.x-1),
141  m_imageRect.ul().y + (m_cacheSize.y-1));
142 
143  m_cacheTile->setImageRectangle(cache_rect);
145 
146  if(m_lineBuffer)
147  {
148  delete [] m_lineBuffer;
149  }
151 
152  if (traceDebug())
153  {
155  << "ossimPngReader::allocate DEBUG:"
156  << "\nm_cacheTile:\n" << *(m_cacheTile.get())
157  << "\nm_tile:\n" << *(m_tile.get())
158  << "\ncache tile size: " << m_cacheSize
159  << "\nimage width: " << m_imageRect.width()
160  << "\nimage height: " << m_imageRect.height()
161  << "\nnumber of bands: " << m_numberOfOutputBands
162  << "\nline buffer size: " << m_lineBufferSizeInBytes
163  << endl;
164  }
165 }
166 
168  const ossimIrect& rect, ossim_uint32 resLevel)
169 {
170  if ( !m_tile )
171  {
172  // First time through. Allocate memory...
173  allocate();
174  }
175 
176  if (m_tile.valid())
177  {
178  // Image rectangle must be set prior to calling getTile.
179  m_tile->setImageRectangle(rect);
180 
181  if ( getTile( m_tile.get(), resLevel ) == false )
182  {
184  {
185  m_tile->makeBlank();
186  }
187  }
188  }
189 
190  return m_tile;
191 }
192 
194  ossim_uint32 resLevel)
195 {
196  bool status = false;
197 
198  //---
199  // Not open, this tile source bypassed, or invalid res level,
200  // return a blank tile.
201  //---
202  if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
203  result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
204  {
205  result->ref(); // Increment ref count.
206 
207  //---
208  // Check for overview tile. Some overviews can contain r0 so always
209  // call even if resLevel is 0. Method returns true on success, false
210  // on error.
211  //---
212  status = getOverviewTile(resLevel, result);
213 
214  if (status)
215  {
217  {
218  //---
219  // Temp fix:
220  // The overview handler could return a tile of OSSIM_USHORT11 if
221  // the max sample value was not set to 2047.
222  //
223  // To prevent a scalar mismatch set
224  //---
226  }
227  }
228 
229  if (!status) // Did not get an overview tile.
230  {
231  status = true;
232 
233  ossimIrect tile_rect = result->getImageRectangle();
234 
235  if ( ! tile_rect.completely_within(getImageRectangle(0)) )
236  {
237  // We won't fill totally so make blank first.
238  m_tile->makeBlank();
239  }
240 
241  if (getImageRectangle(0).intersects(tile_rect))
242  {
243  // Make a clip rect.
244  ossimIrect clip_rect = tile_rect.clipToRect(getImageRectangle(0));
245 
246  // This will validate the tile at the end.
247  fillTile(clip_rect, result);
248  }
249  }
250 
251  result->unref(); // Decrement ref count.
252  }
253 
254  return status;
255 }
256 
257 void ossimPngReader::fillTile(const ossimIrect& clip_rect,
258  ossimImageData* tile)
259 {
260  if (!tile || !m_str) return;
261 
262  ossimIrect buffer_rect = clip_rect;
263  buffer_rect.stretchToTileBoundary(m_cacheSize);
264  buffer_rect.set_ulx(0);
265  buffer_rect.set_lrx(getImageRectangle(0).lr().x);
266 
267  ossim_int32 number_of_cache_tiles = buffer_rect.height()/m_cacheSize.y;
268 
269 #if 0
270  if (traceDebug())
271  {
273  << "tiles high: " << number_of_cache_tiles
274  << endl;
275  }
276 #endif
277 
278  ossimIpt origin = buffer_rect.ul();
279 
280  for (int tileIdx = 0; tileIdx < number_of_cache_tiles; ++tileIdx)
281  {
282  // See if it's in the cache already.
284  tempTile = ossimAppFixedTileCache::instance()->
285  getTile(m_cacheId, origin);
286  if (tempTile.valid())
287  {
288  tile->loadTile(tempTile.get());
289  }
290  else
291  {
292  // Have to read from the png file.
293  ossim_uint32 startLine = static_cast<ossim_uint32>(origin.y);
294  ossim_uint32 stopLine =
295  static_cast<ossim_uint32>( min(origin.y+m_cacheSize.y-1,
296  getImageRectangle().lr().y) );
297  ossimIrect cache_rect(origin.x,
298  origin.y,
299  origin.x+m_cacheSize.x-1,
300  origin.y+m_cacheSize.y-1);
301 
302  m_cacheTile->setImageRectangle(cache_rect);
303 
306  {
308  }
309 
310  if (startLine < m_currentRow)
311  {
312  // Must restart the compression process again.
313  restart();
314  }
315 
316  // Gobble any not needed lines.
317  while(m_currentRow < startLine)
318  {
319  png_read_row(m_pngReadPtr, m_lineBuffer, NULL);
320  ++m_currentRow;
321  }
322 
323  switch (m_readMode)
324  {
325  case ossimPngRead8:
326  {
327  copyLines(ossim_uint8(0), stopLine);
328  break;
329  }
330  case ossimPngRead16:
331  {
332  copyLines(ossim_uint16(0), stopLine);
333  break;
334  }
335  case ossimPngRead8a:
336  {
338  {
339  copyLines(ossim_uint8(0), stopLine);
340  }
341  else
342  {
343  // Will burn alpha value into the other bands.
344  copyLinesWithAlpha(ossim_uint8(0), stopLine);
345  }
346  break;
347  }
348  case ossimPngRead16a:
349  {
351  {
352  copyLines(ossim_uint16(0), stopLine);
353  }
354  else
355  {
356  // Will burn alpha value into the other bands.
357  copyLinesWithAlpha(ossim_uint16(0), stopLine);
358  }
359  break;
360  }
361  case ossimPngReadUnknown:
362  default:
363  {
364  break; // should never happen.
365  }
366  }
367 
369 
370  tile->loadTile(m_cacheTile.get());
371 
372  // Add it to the cache for the next time.
374  m_cacheTile);
375 
376  } // End of reading for png file.
377 
378  origin.y += m_cacheSize.y;
379 
380  } // for (int tile = 0; tile < number_of_cache_tiles; ++tile)
381 
382  tile->validate();
383 }
384 
387 {
388  return ossimIrect(0,
389  0,
390  getNumberOfSamples(reduced_res_level) - 1,
391  getNumberOfLines(reduced_res_level) - 1);
392 }
393 
395  const char* prefix) const
396 {
397  std::string p = ( prefix ? prefix : "" );
399  kwl.addPair( p, USE_ALPHA_KW, v, true );
400  return ossimImageHandler::saveState(kwl, prefix);
401 }
402 
404  const char* prefix)
405 {
406  bool result = false;
407  if (ossimImageHandler::loadState(kwl, prefix))
408  {
409  // this was causing core dumps. Mainly because if prefix is null then
410  // standard string core dumps. So wrapped with OSSIM string that checks
411  // for this and inits with empty string if null
412  //
413  ossimString value = kwl.findKey( ossimString(prefix).c_str(), USE_ALPHA_KW );
414  if ( value.size() )
415  {
416  ossimString s = value;
418  }
419  result = open();
420  }
421  return result;
422 }
423 
425 {
426  if ( property.valid() )
427  {
428  if ( property->getName().string() == USE_ALPHA_KW )
429  {
430  ossimString s;
431  property->valueToString(s);
433  }
434  else
435  {
437  }
438  }
439 }
440 
442 {
444  if ( name.string() == USE_ALPHA_KW )
445  {
447  }
448  else
449  {
450  prop = ossimImageHandler::getProperty(name);
451  }
452  return prop;
453 }
454 
455 void ossimPngReader::getPropertyNames(std::vector<ossimString>& propertyNames)const
456 {
457  propertyNames.push_back( ossimString(USE_ALPHA_KW) );
459 }
460 
462 {
463  static const char MODULE[] = "ossimPngReader::open()";
464  if (traceDebug())
465  {
467  << MODULE << " entered...\n" << "File: " << theImageFile.c_str()
468  << "\n";
469  }
470 
471  bool result = false;
472 
473  // Start with a clean slate.
474  if (isOpen())
475  {
476  close();
477  }
478 
479  // Check for empty filename.
480  if ( theImageFile.size() )
481  {
482  // Open up a stream to the file.
483  std::shared_ptr<ossim::istream> str = ossim::StreamFactoryRegistry::instance()->
484  createIstream( theImageFile.string(), ios::in | ios::binary);
485  if ( str )
486  {
487  // Pass to our open that takes a stream:
488  result = open( str );
489  }
490  }
491 
492  if (traceDebug())
493  {
495  << "ossimPngReader::open() exit status: " << (result?"true":"false") << "\n";
496  }
497 
498  return result;
499 }
500 
501 bool ossimPngReader::open( std::shared_ptr<ossim::istream>& str,
502  const std::string& connectionString )
503 {
504  bool result = open( str );
505  if ( result )
506  {
507  theImageFile = connectionString;
508  }
509  return result;
510 }
511 
512 bool ossimPngReader::open( std::shared_ptr<ossim::istream>& str )
513 {
514  bool result = false;
515 
516  if (isOpen())
517  {
518  close();
519  }
520 
521  if ( str )
522  {
523  str->seekg( 0, std::ios_base::beg );
524 
525  if ( checkSignature( *str ) )
526  {
527  // Store the pointer:
528  m_str = str;
529 
530  result = readPngInit();
531  if ( result )
532  {
533  result = initReader();
534  if ( result )
535  {
536  completeOpen();
537  }
538  }
539  else
540  {
541  destroy();
542  }
543  }
544  else
545  {
546  if (traceDebug())
547  {
549  << "ossimPngReader::open NOTICE:\n"
550  << "Could not open stream!\n";
551  }
552  }
553  }
554 
555  return result;
556 }
557 
559 {
560  return ( m_tile.valid() ? m_tile->getWidth() : 0 );
561 }
562 
564 {
565  return ( m_tile.valid() ? m_tile->getHeight() : 0 );
566 }
567 
569 {
570  if (reduced_res_level == 0)
571  {
572  return m_imageRect.height();
573  }
574  else if ( theOverview.valid() )
575  {
576  return theOverview->getNumberOfLines(reduced_res_level);
577  }
578 
579  return 0;
580 }
581 
583 {
584  if (reduced_res_level == 0)
585  {
586  return m_imageRect.width();
587  }
588  else if ( theOverview.valid() )
589  {
590  return theOverview->getNumberOfSamples(reduced_res_level);
591  }
592 
593  return 0;
594 }
595 
597 {
598  return 0;
599 }
600 
602 {
603  return 0;
604 }
605 
607 {
608  return ossimString("ossim_png_reader");
609 }
610 
612 {
613  return ossimString("ossim png reader");
614 }
615 
617 {
618  return ossimString("ossimPngReader");
619 }
620 
622 {
623  //---
624  // NOTE: If there is an alpha channel the input band will be one more than
625  // the output bands. For library purposes the output bands and input bands
626  // are the same.
627  //---
628  return m_numberOfOutputBands;
629 }
630 
632 {
633  return m_numberOfOutputBands;
634 }
635 
637 {
638  return m_outputScalarType;
639 }
640 
642 {
643  if ( m_str ) return m_str->good();
644 
645  return false;
646 }
647 
649 {
650  //---
651  // Note the size of m_maxPixelValue can be one greater than output bands
652  // if there is an alpa channel.
653  //---
654  if (band < m_numberOfOutputBands)
655  {
656  return m_maxPixelValue[band];
657  }
658  return 255.0;
659 }
660 
662 {
663  if ( m_str )
664  {
665  // Destroy the existing memory associated with png structs.
667  {
668  png_destroy_read_struct(&m_pngReadPtr, &m_pngReadInfoPtr, NULL);
669  }
670 
671  m_pngReadPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
672  NULL,
673  NULL,
674  NULL);
675  m_pngReadInfoPtr = png_create_info_struct(m_pngReadPtr);
676 
677  if ( setjmp( png_jmpbuf(m_pngReadPtr) ) )
678  {
680  << "Error while reading. File corrupted? "
681  << theImageFile
682  << std::endl;
683 
684  return;
685  }
686 
687  // Reset the file pointer.
688  m_str->seekg( 0, std::ios_base::beg );
689 
690  //---
691  // Pass the static read method to libpng to allow us to use our
692  // c++ stream instead of doing "png_init_io (pp, ...);" with
693  // c stream.
694  //---
695  png_set_read_fn( m_pngReadPtr,
696  (png_voidp)m_str.get(),
697  (png_rw_ptr)&ossimPngReader::pngReadData );
698 
699  //---
700  // Note we won't do png_set_sig_bytes(png_ptr, 8) here because we are not
701  // rechecking for png signature.
702  //---
703  png_read_info(m_pngReadPtr, m_pngReadInfoPtr);
704 
705  //---
706  // If png_set_expand used:
707  // Expand data to 24-bit RGB, or 8-bit grayscale,
708  // with alpha if available.
709  //---
710  bool expandFlag = false;
711 
712  if ( m_pngColorType == PNG_COLOR_TYPE_PALETTE )
713  {
714  expandFlag = true;
715  }
716  if ( (m_pngColorType == PNG_COLOR_TYPE_GRAY) && (m_bitDepth < 8) )
717  {
718  expandFlag = true;
719  }
720  if ( png_get_valid(m_pngReadPtr, m_pngReadInfoPtr, PNG_INFO_tRNS) )
721  {
722  expandFlag = true;
723  }
724 
725  //---
726  // If png_set_packing used:
727  // Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
728  //---
729  bool packingFlag = false;
730 
731  if ( (m_bitDepth < 8) && (m_pngColorType == PNG_COLOR_TYPE_GRAY) )
732  {
733  packingFlag = true;
734  }
735 
736  if (expandFlag)
737  {
738  png_set_expand(m_pngReadPtr);
739  }
740  if (packingFlag)
741  {
742  png_set_packing(m_pngReadPtr);
743  }
744 
745  // Gamma correction.
746  // ossim_float64 gamma;
747  // if (png_get_gAMA(m_pngReadPtr, m_pngReadInfoPtr, &gamma))
748  // {
749  // png_set_gamma(m_pngReadPtr, display_exponent, gamma);
750  // }
751 
752  //---
753  // Turn on interlace handling... libpng returns just 1 (ie single pass)
754  // if the image is not interlaced
755  //---
756  png_set_interlace_handling (m_pngReadPtr);
757 
758  //---
759  // Update the info structures after the transformations take effect
760  //---
761  png_read_update_info (m_pngReadPtr, m_pngReadInfoPtr);
762 
763  // We're back on row 0 or first line.
764  m_currentRow = 0;
765  }
766 }
767 
769 {
770  bool result = false;
771 
772  //---
773  // Verify the file is a png by checking the first eight bytes:
774  // 0x 89 50 4e 47 0d 0a 1a 0a
775  //---
776  ossim_uint8 sig[8];
777  str.read( (char*)sig, 8);
778  if ( str.good() )
779  {
780  if ( png_sig_cmp(sig, 0, 8) == 0 )
781  {
782  result = true;
783  }
784  }
785 
786  return result;
787 }
788 
790 {
791  if ( !theGeometry )
792  {
793  //---
794  // Check factory for external geom:
795  //---
797 
798  if ( !theGeometry )
799  {
800  // Fist time through:
802 
803  //---
804  // This code does not call ossimImageGeometryRegistry::extendGeometry
805  // by design to avoid wasted factory calls.
806  //---
807  }
808 
809  // Set image things the geometry object should know about.
811  }
812  return theGeometry;
813 }
814 
816 {
817  bool result = false;
818  if ( m_str )
819  {
820  if ( m_str->good() )
821  {
822  m_pngReadPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
823  NULL,
824  NULL,
825  NULL);
826  if ( m_pngReadPtr )
827  {
828  m_pngReadInfoPtr = png_create_info_struct(m_pngReadPtr);
829  if ( m_pngReadInfoPtr )
830  {
831  if ( setjmp( png_jmpbuf(m_pngReadPtr) ) == 0 )
832  {
833  //---
834  // Pass the static read method to libpng to allow us to use our
835  // c++ stream instead of doing "png_init_io (pp, ...);" with
836  // c stream.
837  //---
838  png_set_read_fn( m_pngReadPtr,
839  (png_voidp)m_str.get(),
840  (png_rw_ptr)&ossimPngReader::pngReadData );
841  png_set_sig_bytes(m_pngReadPtr, 8);
842  png_read_info(m_pngReadPtr, m_pngReadInfoPtr);
843  result = true;
844  }
845  }
846  else
847  {
848  // Out of memory?
849  png_destroy_read_struct(&m_pngReadPtr, NULL, NULL);
850  }
851  }
852  }
853  }
854  return result;
855 
856 } // End: ossimPngReader::readPngInit()
857 
859 {
860  bool result = true;
861 
862  ossim_uint32 height = png_get_image_height(m_pngReadPtr, m_pngReadInfoPtr);
863  ossim_uint32 width = png_get_image_width(m_pngReadPtr, m_pngReadInfoPtr);
864  m_bitDepth = png_get_bit_depth(m_pngReadPtr, m_pngReadInfoPtr);
865  m_pngColorType = png_get_color_type(m_pngReadPtr, m_pngReadInfoPtr);
866 
867  m_imageRect = ossimIrect(0, 0, width - 1, height - 1);
868 
869  if (m_bitDepth == 16)
870  {
871  // png_set_strip_16 (m_pngReadPtr);
874  }
875  else
876  {
878  }
879 
880  // Set the read mode from scalar and color type.
882  {
883  if ( (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) ||
884  (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA) )
885  {
887  }
888  else
889  {
891  }
892  }
893  else
894  {
895  if ( (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA) ||
896  (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA) )
897  {
899  }
900  else
901  {
903  }
904 
905  // Set the swap flag. PNG stores data in network byte order(big endian).
907  {
908  m_swapFlag = true;
909  }
910  }
911 
912  //---
913  // If png_set_expand used:
914  // Expand data to 24-bit RGB, or 8-bit grayscale,
915  // with alpha if available.
916  //---
917  bool expandFlag = false;
918 
919  if ( m_pngColorType == PNG_COLOR_TYPE_PALETTE )
920  {
921  expandFlag = true;
922  }
923  if ( (m_pngColorType == PNG_COLOR_TYPE_GRAY) && (m_bitDepth < 8) )
924  {
925  expandFlag = true;
926  }
927  if ( png_get_valid(m_pngReadPtr, m_pngReadInfoPtr, PNG_INFO_tRNS) )
928  {
929  expandFlag = true;
930  }
931 
932  //---
933  // If png_set_packing used:
934  // Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
935  //---
936  bool packingFlag = false;
937 
938  if ( (m_bitDepth < 8) && (m_pngColorType == PNG_COLOR_TYPE_GRAY) )
939  {
940  packingFlag = true;
941  }
942 
943  if (expandFlag)
944  {
945  png_set_expand(m_pngReadPtr);
946  }
947  if (packingFlag)
948  {
949  png_set_packing(m_pngReadPtr);
950  }
951 
952  // Gamma correction.
953  // ossim_float64 gamma;
954  // if (png_get_gAMA(m_pngReadPtr, m_pngReadInfoPtr, &gamma))
955  // {
956  // png_set_gamma(png_ptr, display_exponent, gamma);
957  // }
958 
959  //---
960  // Turn on interlace handling... libpng returns just 1 (ie single pass)
961  // if the image is not interlaced
962  //---
963  m_interlacePasses = png_set_interlace_handling (m_pngReadPtr);
964 
965  //---
966  // Update the info structures after the transformations take effect
967  //---
968  png_read_update_info (m_pngReadPtr, m_pngReadInfoPtr);
969 
970  // TODO:
971  // Add check for image offsets.
972  // Add check for resolution.
973  // Add check for colormap.
974 
975  switch (m_pngColorType)
976  {
977  case PNG_COLOR_TYPE_RGB: /* RGB */
978  {
981  break;
982  }
983  case PNG_COLOR_TYPE_RGB_ALPHA: /* RGBA */
984  {
987  {
989  }
990  else
991  {
993  }
994  break;
995  }
996  case PNG_COLOR_TYPE_GRAY: /* Grayscale */
997  {
1000  break;
1001  }
1002  case PNG_COLOR_TYPE_GRAY_ALPHA: /* Grayscale + alpha */
1003  {
1006  {
1007  m_numberOfOutputBands = 2;
1008  }
1009  else
1010  {
1012  }
1013  break;
1014  }
1015  case PNG_COLOR_TYPE_PALETTE: /* Indexed */
1016  {
1019  break;
1020  }
1021  default: /* Unknown type */
1022  {
1023  result = false;
1024  }
1025  }
1026 
1027  if ( result )
1028  {
1030 
1031  // Set the max pixel value.
1032  setMaxPixelValue();
1033 
1034  // Set to OSSIM_USHORT11 for use of specialized tile.
1035  if (m_maxPixelValue[0] == 2047.0)
1036  {
1038  }
1039 
1040  // We're on row 0 or first line.
1041  m_currentRow = 0;
1042 
1043  if (traceDebug())
1044  {
1046  << "ossimPngReader::initReader DEBUG:"
1047  << "\nm_imageRect: " << m_imageRect
1048  << "\nm_bitDepth: " << int(m_bitDepth)
1049  << "\nm_pngColorType: "
1051  << "\nm_numberOfInputBands: " << m_numberOfInputBands
1052  << "\nm_numberOfOutputBands: " << m_numberOfOutputBands
1053  << "\nm_bytePerPixelPerBand: " << m_bytePerPixelPerBand
1054  << "\nm_lineBufferSizeInBytes: " << m_lineBufferSizeInBytes
1055  << "\nm_interlacePasses: " << m_interlacePasses
1056  << "\npalette expansion: "
1057  << (expandFlag?"on":"off")
1058  << "\npacking (1,2,4 bit to one byte): "
1059  << (packingFlag?"on":"off")
1060  << "\nm_readMode: " << m_readMode
1061  << "\nm_swapFlag: " << m_swapFlag
1062  << std::endl;
1063 
1064  for (ossim_uint32 band = 0; band < m_numberOfInputBands; ++band)
1065  {
1067  << "max[" << band << "]: " << m_maxPixelValue[band]
1068  << std::endl;
1069  }
1070  }
1071  }
1072 
1073  return result;
1074 
1075 } // End: ossimPngReader::initReader()
1076 
1078 {
1080  << "ossimPngReader::readPngVersionInfo\nCompiled with:"
1081  << "\nlibpng " << PNG_LIBPNG_VER_STRING
1082  << " using libpng " << PNG_LIBPNG_VER
1083  << "\nzlib " << ZLIB_VERSION " using zlib "
1084  << zlib_version << std::endl;
1085 }
1086 
1088 {
1089  ossimString result = "unknown";
1090  if (m_pngColorType == PNG_COLOR_TYPE_GRAY)
1091  {
1092  return ossimString("PNG_COLOR_TYPE_GRAY");
1093  }
1094  else if (m_pngColorType == PNG_COLOR_TYPE_PALETTE)
1095  {
1096  return ossimString("PNG_COLOR_TYPE_PALETTE");
1097  }
1098  else if (m_pngColorType == PNG_COLOR_TYPE_RGB)
1099  {
1100  return ossimString("PNG_COLOR_TYPE_RGB");
1101  }
1102  else if (m_pngColorType == PNG_COLOR_TYPE_RGB_ALPHA)
1103  {
1104  return ossimString("PNG_COLOR_TYPE_RGB_ALPHA");
1105  }
1106  else if (m_pngColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
1107  {
1108  return ossimString("PNG_COLOR_TYPE_GRAY_ALPHA");
1109  }
1110 
1111  return ossimString("unknown");
1112 }
1113 
1115 {
1116  ossim_uint32 band;
1118  for (band = 0; band < m_numberOfInputBands; ++band)
1119  {
1120  m_maxPixelValue[band] = 0.0;
1121  }
1122 
1123  if (png_get_valid(m_pngReadPtr, m_pngReadInfoPtr, PNG_INFO_sBIT ))
1124  {
1125  png_color_8p sig_bit;
1126  png_get_sBIT(m_pngReadPtr, m_pngReadInfoPtr, &sig_bit);
1127  if (traceDebug())
1128  {
1130  << "ossimPngReader::setMaxPixelValue DEBUG:"
1131  << "\nsig_bit->red: " << int(sig_bit->red)
1132  << "\nsig_bit->green: " << int(sig_bit->green)
1133  << "\nsig_bit->blue: " << int(sig_bit->blue)
1134  << "\nsig_bit->gray: " << int(sig_bit->gray)
1135  << "\nsig_bit->alpa: " << int(sig_bit->alpha)
1136  << endl;
1137  }
1138  switch (m_pngColorType)
1139  {
1140  case PNG_COLOR_TYPE_RGB: /* RGB */
1141  m_maxPixelValue[0] = pow(2.0, double(sig_bit->red))-1.0;
1142  m_maxPixelValue[1] = pow(2.0, double(sig_bit->green))-1.0;
1143  m_maxPixelValue[2] = pow(2.0, double(sig_bit->blue))-1.0;
1144  break;
1145  case PNG_COLOR_TYPE_RGB_ALPHA: /* RGBA */
1146  m_maxPixelValue[0] = pow(2.0, double(sig_bit->red))-1.0;
1147  m_maxPixelValue[1] = pow(2.0, double(sig_bit->green))-1.0;
1148  m_maxPixelValue[2] = pow(2.0, double(sig_bit->blue))-1.0;
1149  m_maxPixelValue[3] = pow(2.0, double(sig_bit->alpha))-1.0;
1150  break;
1151  case PNG_COLOR_TYPE_GRAY: /* Grayscale */
1152  m_maxPixelValue[0] = pow(2.0, double(sig_bit->gray))-1.0;
1153  break;
1154  case PNG_COLOR_TYPE_GRAY_ALPHA: /* Grayscale + alpha */
1155  m_maxPixelValue[0] = pow(2.0, double(sig_bit->gray))-1.0;
1156  m_maxPixelValue[1] = pow(2.0, double(sig_bit->alpha))-1.0;
1157  break;
1158  case PNG_COLOR_TYPE_PALETTE: /* Indexed */
1159  m_maxPixelValue[0] = 255.0;
1160  m_maxPixelValue[1] = 255.0;
1161  m_maxPixelValue[2] = 255.0;
1162  break;
1163  default: /* Aie! Unknown type */
1164  break;
1165  }
1166  }
1167 
1168  // Sanity check.
1169  for (ossim_uint32 band = 0; band < m_numberOfInputBands; ++band)
1170  {
1171  if (m_maxPixelValue[band] == 0.0)
1172  {
1173  if (m_bitDepth <= 8)
1174  {
1175  m_maxPixelValue[band] = 255.0;
1176  }
1177  else
1178  {
1179  m_maxPixelValue[band] = 65535.0;
1180  }
1181  }
1182  }
1183 }
1184 
1185 template <class T> void ossimPngReader::copyLines(
1186  T /*dummy*/, ossim_uint32 stopLine)
1187 {
1188  const ossim_uint32 SAMPLES = m_imageRect.width();
1189 
1190  T* src = (T*)m_lineBuffer;
1191  std::vector<T*> dst(m_numberOfOutputBands);
1192 
1193  ossim_uint32 band = 0;
1194  for (band = 0; band < m_numberOfOutputBands; ++band)
1195  {
1196  dst[band] = (T*) m_cacheTile->getBuf(band);
1197  }
1198 
1199  ossim_int32 bufIdx = 0;
1200 
1201  while (m_currentRow <= stopLine)
1202  {
1203  // Read a line from the jpeg file.
1204  png_read_row(m_pngReadPtr, m_lineBuffer, NULL);
1205  ++m_currentRow;
1206 
1207  if(m_swapFlag)
1208  {
1209  ossimEndian endian;
1210  endian.swap(src, SAMPLES*m_numberOfInputBands);
1211  }
1212 
1213  //---
1214  // Copy the line which is band interleaved by pixel the the band
1215  // separate buffers.
1216  //---
1217  ossim_uint32 index = 0;
1218  for (ossim_uint32 sample = 0; sample < SAMPLES; ++sample)
1219  {
1220  for (band = 0; band < m_numberOfOutputBands; ++band)
1221  {
1222  dst[band][bufIdx] = src[index];
1223  ++index;
1224  }
1225  ++bufIdx;
1226  }
1227  }
1228 }
1229 
1230 template <class T> void ossimPngReader::copyLinesWithAlpha(
1231  T, ossim_uint32 stopLine)
1232 {
1233  ossim_float64 denominator;
1235  {
1236  denominator = m_maxPixelValue[m_numberOfInputBands-1];
1237  }
1238  else
1239  {
1240  denominator = m_maxPixelValue[m_numberOfInputBands-1];
1241  }
1242 
1243  const ossim_uint32 SAMPLES = m_imageRect.width();
1244 
1245  T* src = (T*) m_lineBuffer;
1246 
1247  std::vector<T*> dst(m_numberOfOutputBands);
1248  std::vector<T> p(m_numberOfOutputBands);
1249 
1250  ossim_float64 alpha;
1251 
1252  const ossim_float64 MIN_PIX = m_cacheTile->getMinPix(0);
1253  const ossim_float64 MAX_PIX = m_cacheTile->getMaxPix(0);
1254  const ossim_float64 NULL_PIX = m_cacheTile->getNullPix(0);
1255 
1256  ossim_uint32 band = 0;
1257  for (band = 0; band < m_numberOfOutputBands; ++band)
1258  {
1259  dst[band] = (T*)m_cacheTile->getBuf(band);
1260  }
1261 
1262  ossim_int32 dstIdx = 0;
1263 
1264  while (m_currentRow <= stopLine)
1265  {
1266  // Read a line from the jpeg file.
1267  png_read_row(m_pngReadPtr, m_lineBuffer, NULL);
1268  ++m_currentRow;
1269 
1270  if(m_swapFlag)
1271  {
1272  ossimEndian endian;
1273  endian.swap(src, SAMPLES*m_numberOfInputBands);
1274  }
1275 
1276  //---
1277  // Copy the line which is band interleaved by pixel the the band
1278  // separate buffers.
1279  //---
1280  ossim_uint32 srcIdx = 0;
1281  for (ossim_uint32 sample = 0; sample < SAMPLES; ++sample)
1282  {
1283  // Copy the pixels.
1284  for (band = 0; band < m_numberOfOutputBands; ++band)
1285  {
1286  p[band] = src[srcIdx++];
1287  }
1288 
1289  // Get the alpha channel.
1290  alpha = src[srcIdx++];
1291  alpha = alpha / denominator;
1292 
1293  if (alpha == 1.0)
1294  {
1295  for (band = 0; band < m_numberOfOutputBands; ++band)
1296  {
1297  dst[band][dstIdx] = p[band];
1298  }
1299  }
1300  else if (alpha == 0.0)
1301  {
1302  for (band = 0; band < m_numberOfOutputBands; ++band)
1303  {
1304  dst[band][dstIdx] = static_cast<T>(NULL_PIX);
1305  }
1306  }
1307  else
1308  {
1309  for (band = 0; band < m_numberOfOutputBands; ++band)
1310  {
1311  ossim_float64 f = p[band];
1312  f = f * alpha;
1313  if (f != NULL_PIX)
1314  {
1315  dst[band][dstIdx] =
1316  static_cast<T>( (f>=MIN_PIX) ?
1317  ( (f<=MAX_PIX) ? f : MAX_PIX ) :
1318  MIN_PIX );
1319  }
1320  else
1321  {
1322  dst[band][dstIdx] = static_cast<T>(NULL_PIX);
1323  }
1324  }
1325  }
1326  ++dstIdx; // next sample...
1327 
1328  } // End of sample loop.
1329 
1330  } // End of line loop.
1331 }
1332 
1333 // Static function to read from c++ stream.
1334 void ossimPngReader::pngReadData( png_structp png_ptr, png_bytep data, png_size_t length )
1335 {
1336  ossim::istream* str = (ossim::istream*)png_get_io_ptr(png_ptr);
1337  if ( str )
1338  {
1339  str->read( (char*)data, length );
1340  }
1341 }
virtual void deleteCache(ossimAppFixedCacheId cacheId)
virtual ossim_uint32 getWidth() const
ossim_uint32 x
virtual ossim_uint32 getImageTileWidth() const
Returns the tile width of the image or 0 if the image is not tiled.
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
void fillTile(const ossimIrect &clip_rect, ossimImageData *tile)
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
Get propterty method.
ossimRefPtr< ossimImageGeometry > theGeometry
virtual const ossim_float64 * getMaxPix() const
void destroy()
Free tile and buffer memory.
bool isOpen() const
Derived classes must implement this method to be concrete.
virtual ossim_uint32 getNumberOfBands() const
ossimFilename theImageFile
virtual void setImageRectangle(const ossimIrect &rect)
16 bit unsigned integer
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &rect, ossim_uint32 resLevel=0)
Returns a pointer to a tile given an origin representing the upper left corner of the tile to grab fr...
std::shared_ptr< ossim::istream > m_str
void allocate()
Initializes tiles and buffers.
ossimIrect m_imageRect
void copyLines(T dummy, ossim_uint32 stopLine)
Represents serializable keyword/value map.
const std::string & findKey(const std::string &key) const
Find methods that take std::string(s).
ossim_uint32 y
virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level=0) const
Returns the zero based image rectangle for the reduced resolution data set (rrds) passed in...
bool valid() const
Definition: ossimRefPtr.h:75
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
Get propterty names.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
ossimAppFixedTileCache::ossimAppFixedCacheId m_cacheId
ossim_uint32 height() const
Definition: ossimIrect.h:487
ossim_uint8 * m_lineBuffer
bool initReader()
Initializes this reader from libpng m_pngPtr and infoPtr.
static ossimString toString(bool aValue)
Numeric to string methods.
png_structp m_pngReadPtr
OSSIM_DLL void defaultTileSize(ossimIpt &tileSize)
const ossimIpt & ul() const
Definition: ossimIrect.h:274
bool checkSignature(std::istream &str)
std::vector< ossim_float64 > m_maxPixelValue
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
void addPair(const std::string &key, const std::string &value, bool overwrite=true)
OSSIM_DLL ossimByteOrder byteOrder()
Definition: ossimCommon.cpp:54
virtual void setProperty(ossimRefPtr< ossimProperty > property)
Set propterty method.
static StreamFactoryRegistry * instance()
ossimRefPtr< ossimImageData > m_cacheTile
unsigned short ossim_uint16
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual void setProperty(ossimRefPtr< ossimProperty > property)
ossim_uint32 m_lineBufferSizeInBytes
virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level=0) const
Returns the number of lines in the image.
void ref() const
increment the reference count by one, indicating that this object has another pointer which is refere...
virtual void initialize()
Initialize the data buffer.
ossimString getPngColorTypeString() const
static ossimAppFixedTileCache * instance(ossim_uint32 maxSize=0)
virtual ossimObject * dup() const
virtual bool isValidRLevel(ossim_uint32 resLevel) const
Determines if the passed in reslution level is valid.
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
bool completely_within(const ossimIrect &rect) const
Definition: ossimIrect.cpp:425
ossimPngReader()
default constructor
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
double ossim_float64
virtual void loadTile(const void *src, const ossimIrect &src_rect, ossimInterleaveType il_type)
ossimPngReadMode m_readMode
virtual bool getOverviewTile(ossim_uint32 resLevel, ossimImageData *result)
Method to get an overview tile.
static ossimImageDataFactory * instance()
virtual ossimDataObjectStatus validate() const
std::string::size_type size() const
Definition: ossimString.h:405
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Gets the image geometry.
bool toBool() const
String to numeric methods.
ossim_uint32 m_numberOfInputBands
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
virtual ossim_uint32 getTileHeight() const
Returns the height of the output tile.
virtual ossimIrect getImageRectangle() const
void copyLinesWithAlpha(T, ossim_uint32 stopLine)
bool m_useAlphaChannelFlag
virtual ossimScalarType getOutputScalarType() const
Returns the output pixel type of the tile source.
virtual void close()
Deletes the overview and clears the valid image vertices.
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
void initImageParameters(ossimImageGeometry *geom) const
Convenience method to set things needed in the image geometry from the image handler.
ossimIrect clipToRect(const ossimIrect &rect) const
Definition: ossimIrect.cpp:501
ossim_int8 m_bitDepth
ossim_int8 m_pngColorType
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
ossimScalarType
void unref() const
decrement the reference count by one, indicating that a pointer to this object is referencing it...
virtual ossimString getShortName() const
virtual ~ossimPngReader()
virtual destructor
void setMaxPixelValue()
the max pixel value.
virtual const ossim_float64 * getMinPix() const
virtual ossimString getLongName() const
virtual ossimRefPtr< ossimImageGeometry > getExternalImageGeometry() const
Returns the image geometry object associated with this tile source or NULL if non defined...
void set_lrx(ossim_int32 x)
Definition: ossimIrect.h:693
return status
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual ossimString getClassName() const
virtual void makeBlank()
Initializes data to null pixel values.
virtual void completeOpen()
Will complete the opening process.
16 bit unsigned integer (11 bits used)
std::basic_istream< char > istream
Base class for char input streams.
Definition: ossimIosFwd.h:20
ossim_uint32 m_bytePerPixelPerBand
ossimRefPtr< ossimImageHandler > theOverview
ossim_uint32 m_numberOfOutputBands
This class defines an abstract Handler which all image handlers(loaders) should derive from...
ossimIpt m_cacheSize
ossim_int32 y
Definition: ossimIpt.h:142
virtual ossim_uint32 getImageTileHeight() const
Returns the tile width of the image or 0 if the image is not tiled.
ossimRefPtr< ossimImageData > m_tile
virtual const void * getBuf() const
virtual void close()
Close method.
void restart()
Method to restart reading from the beginning (for backing up).
virtual ossim_uint32 getTileWidth() const
Returns the width of the output tile.
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
virtual bool open()
open method.
virtual ossim_uint32 getNumberOfInputBands() const
Returns the number of bands in the image.
void stretchToTileBoundary(const ossimIpt &tileWidthHeight)
Definition: ossimIrect.cpp:212
ossim_int32 m_interlacePasses
ossim_uint32 m_currentRow
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
ossim_int32 x
Definition: ossimIpt.h:141
static void pngReadData(png_structp png_ptr, png_bytep data, png_size_t length)
Callback method for reading from a stream.
8 bit unsigned integer
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
virtual void setScalarType(ossimScalarType type)
See ossimScalarType in ossimConstants for a full list.
int completely_within(extent_type extent1, extent_type extent2)
void swap(ossim_sint8 &)
Definition: ossimEndian.h:26
unsigned char ossim_uint8
png_infop m_pngReadInfoPtr
ossimRefPtr< ossimImageData > addTile(ossimAppFixedCacheId cacheId, ossimRefPtr< ossimImageData > data, bool duplicateData=true)
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
ossimScalarType m_outputScalarType
const ossimString & getName() const
#define min(a, b)
Definition: auxiliary.h:75
int ossim_int32
void set_ulx(ossim_int32 x)
Definition: ossimIrect.h:657
const std::string & string() const
Definition: ossimString.h:414
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level=0) const
Returns the number of samples in the image.
bool readPngInit()
Performs signature check and initializes png_structp and png_infop.