OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimJpegWriter.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: David Burken
6 //
7 //*******************************************************************
8 // $Id: ossimJpegWriter.cpp 22673 2014-03-13 21:42:34Z dburken $
9 
10 #include <cstdlib>
11 #include <cstdio>
12 
13 //---
14 // Using windows .NET compiler there is a conflict in the libjpeg with INT32
15 // in the file jmorecfg.h. Defining XMD_H fixes this.
16 extern "C"
17 {
18 #if defined(_MSC_VER) || defined(__MINGW32__)
19 # ifndef XMD_H
20 # define XMD_H
21 # endif
22 #endif
23 #include <jpeglib.h>
24 }
25 
28 #include <ossim/base/ossimTrace.h>
29 #include <ossim/base/ossimDpt.h>
37 
39 
40 static const char DEFAULT_FILE_NAME[] = "output.jpg";
41 static const ossim_int32 DEFAULT_JPEG_QUALITY = 100;
42 static ossimTrace traceDebug("ossimJpegWriter:debug");
43 
46  theQuality(DEFAULT_JPEG_QUALITY),
47  theOutputFilePtr(NULL)
48 {
49  // Since there is no internal geometry set the flag to write out one.
51 }
52 
54 {
55  close();
56 }
57 
59 {
60  static const char MODULE[] = "ossimJpegWriter::writeFile";
61 
63  {
64  return false;
65  }
66 
67  bool bandsDontMatch = false;
68  // Get the number of bands. Must be one or three for this writer.
70  ossim_int32 outputComponents = components;
71  if (components != 1 && components != 3)
72  {
73  bandsDontMatch = true;
74  if(components < 3)
75  {
76  outputComponents = 1;
77  }
78  else if(components > 3)
79  {
80  outputComponents = 3;
81  }
82  }
83 
85  {
86  if (!isOpen())
87  {
88  open();
89  }
90 
91  if (!theOutputFilePtr)
92  {
94  << MODULE << " ERROR:"
95  << "\nCannot open: " << theFilename.c_str()
96  << "\nReturning from method." << endl;
97 
98  return false;
99  }
100  }
101  ossimRefPtr<ossimImageSource> savedInput = 0;
102 
104  {
105  savedInput = new ossimScalarRemapper();
106 
107  // Connect scalar remapper to sequencer input.
108  savedInput->connectMyInputTo(0, theInputConnection->getInput(0));
109 
110  // Connect sequencer to the scalar remapper.
111  theInputConnection->connectMyInputTo(0, savedInput.get());
113  }
114 
116  {
117  if (traceDebug())
118  {
119  CLOG << " DEBUG:"
120  << "\nOutput Rect: " << theAreaOfInterest << endl;
121  }
122 
123  ossim_int32 image_height
125  ossim_int32 image_width
129 
130  // Allocate a buffer to hold a row of tiles.
131  ossim_uint32 buf_size = tileHeight*image_width*outputComponents;
132  if (traceDebug())
133  {
134  CLOG << "DEBUG:"
135  << "\nbuf_size: " << buf_size
136  << endl;
137  }
138 
139  std::vector<ossim_uint8> buf(buf_size);
140  ossimRefPtr<ossimImageData> blankTile =
141  new ossimImageData(NULL,
142  OSSIM_UINT8,
143  outputComponents,
144  tileWidth,
145  tileHeight);
147  std::vector<ossim_uint8> tempBuf;
148  if(bandsDontMatch)
149  {
150  tempTile = new ossimImageData(NULL,
151  OSSIM_UINT8,
152  outputComponents,
153  tileWidth,
154  tileHeight);
155  tempTile->initialize();
156  }
157  blankTile->initialize();
158  //
159  // Stuff needed for the jpeg library.
160  // Taken from "example.c" file of the "jpeg-6b" package.
161  //
162  struct jpeg_compress_struct cinfo;
163  struct jpeg_error_mgr jerr;
164  JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
165 
166  // physical row width in image buffer
167  int row_stride = image_width * outputComponents;
168 
169  cinfo.err = jpeg_std_error(&jerr);
170  jpeg_create_compress(&cinfo);
171  jpeg_stdio_dest(&cinfo, theOutputFilePtr);
172  cinfo.image_width = image_width; // image width and height, in pixels
173  cinfo.image_height = image_height;
174  cinfo.input_components = outputComponents; // # of color components per pixel
175 
176  // colorspace of input image
177  if (outputComponents == 3)
178  {
179  cinfo.in_color_space = JCS_RGB;
180  }
181  else
182  {
183  cinfo.in_color_space = JCS_GRAYSCALE;
184  }
185 
186  jpeg_set_defaults(&cinfo);
187  jpeg_set_quality(&cinfo, theQuality, TRUE); //limit to baseline-JPEG values
188  jpeg_start_compress(&cinfo, TRUE);
189 
194 
195  double tileCount = 0.0;
196  double totalTiles = theInputConnection->getNumberOfTiles();
197  //
198  // Ok the jpeg stuff should be set. Loop through and grab a row of tiles
199  // and copy to the buffer. Then write the buffer to the jpeg file.
200  // Get the next row... until finished.
201  //
202  for (ossim_uint32 i=0; ((i<maxY) && (!needsAborting())); ++i)
203  {
204  ossimIrect buf_rect = theAreaOfInterest;
205  buf_rect.set_uly(theAreaOfInterest.ul().y+i*tileHeight);
206  buf_rect.set_lry(buf_rect.ul().y + tileHeight - 1);
207 
208  for (ossim_uint32 j=0; ((j<maxX)&& (!needsAborting())); ++j)
209  {
210  // Grab the tile.
213 
214  if ( t.valid() )
215  {
216  if (t->getDataObjectStatus() != OSSIM_NULL)
217  {
218  if(bandsDontMatch)
219  {
220  tempTile->setImageRectangle(t->getImageRectangle());
222  memcpy(tempTile->getBuf(),
223  t->getBuf(),
224  t->getSizePerBandInBytes()*outputComponents);
225  tempTile->unloadTile(&buf.front(), buf_rect, OSSIM_BIP);
226  }
227  else
228  {
229  // Copy the tile to the buffer.
230  t->unloadTile(&buf.front(), buf_rect, OSSIM_BIP);
231  }
232  }
233  else
234  {
235  blankTile->setOrigin(t->getOrigin());
236  if(bandsDontMatch)
237  {
238  tempTile->setImageRectangle(blankTile->getImageRectangle());
240  memcpy(tempTile->getBuf(), t->getBuf(), t->getSizePerBandInBytes()*outputComponents);
241  blankTile->unloadTile(&buf.front(), buf_rect, OSSIM_BIP);
242  }
243  else
244  {
245  // Copy the tile to the buffer.
246  blankTile->unloadTile(&buf.front(), buf_rect, OSSIM_BIP);
247  }
248  }
249  }
250  ++tileCount;
251  setPercentComplete((100.0*(tileCount/totalTiles)));
252 
253  } // End of loop through tiles in the x direction.
254 
255  // Copy the buffer to the jpeg file.
256  ossim_int32 lines_to_copy =
257  min( (buf_rect.lr().y-buf_rect.ul().y+1),
258  (theAreaOfInterest.lr().y-buf_rect.ul().y+1) );
259 
260  if (traceDebug())
261  {
263  << MODULE
264  << "buf_rect: " << buf_rect
265  << "lines_to_copy: " << lines_to_copy << endl;
266  }
267 
268  if(!needsAborting())
269  {
270  // Now copy the buffer that should be full to the jpeg file.
271  ossim_int32 buf_offset = 0;
272  for (ossim_int32 line=0; line<lines_to_copy; ++line)
273  {
274  row_pointer[0] = &buf[buf_offset];
275  jpeg_write_scanlines(&cinfo, row_pointer, 1);
276  buf_offset += row_stride;
277  }
278  }
279 
280  } // End of loop through tiles in the y direction.
281 
282  // Free memory.
283  if(!needsAborting())
284  {
285  jpeg_finish_compress(&cinfo);
286  }
287 
288  fclose(theOutputFilePtr);
289  theOutputFilePtr = NULL;
290 
291  jpeg_destroy_compress(&cinfo);
292  }
293  else
294  {
296  }
297 
298  // Reset the connection if needed.
299  if(savedInput.valid())
300  {
302  if(obj)
303  {
305  }
306  savedInput = 0;
307  }
308  return true;
309 }
310 
312  const char* prefix)const
313 {
314  kwl.add( prefix,
316  theQuality,
317  true );
318  return ossimImageFileWriter::saveState(kwl, prefix);
319 }
320 
322  const char* prefix)
323 {
324  const char* value =
326  if(value)
327  {
328  setQuality(atoi(value));
329  }
330 
331  theOutputImageType = "jpeg";
332 
333  return ossimImageFileWriter::loadState(kwl, prefix);
334 }
335 
337 {
338  static const char MODULE[] = "ossimJpegWriter::setQuality";
339 
340  // Range 1 to 100 with 100 being best.
341  if (quality > 0 && quality < 101)
342  {
343  theQuality = quality;
344  }
345  else
346  {
347  if (traceDebug())
348  {
350  << MODULE << " DEBUG:"
351  << "\nquality out of range: " << quality
352  << "\nquality has been set to default: "
353  << DEFAULT_JPEG_QUALITY
354  << "\nvalid range: 1 to 100 with 100 being best."
355  << endl;
356  }
357 
358  theQuality = DEFAULT_JPEG_QUALITY;
359  }
360 
361  if (traceDebug())
362  {
364  << MODULE << " DEBUG:"
365  << "\nQuality set to: "
366  << theQuality << endl;
367  }
368 }
369 
371 {
372  return (theOutputFilePtr!=NULL);
373 }
374 
376 {
377  close();
378 
379  // Check for empty filenames.
380  if (theFilename.empty())
381  {
382  return false;
383  }
384 
385  theOutputFilePtr = fopen(theFilename.c_str(), "wb");
386  if(theOutputFilePtr)
387  {
388  return true;
389  }
390  return false;
391 }
392 
394 {
395  if(theOutputFilePtr)
396  {
397  fclose(theOutputFilePtr);
398  theOutputFilePtr = NULL;
399  }
400 }
401 
402 void ossimJpegWriter::getImageTypeList(std::vector<ossimString>& imageTypeList)const
403 {
404  imageTypeList.push_back(ossimString("jpeg"));
405 }
406 
408 {
409  return ossimString("jpg");
410 }
411 
412 bool ossimJpegWriter::hasImageType(const ossimString& imageType) const
413 {
414  if((imageType == "image/jpeg")||
415  (imageType == "image/jpg"))
416  {
417  return true;
418  }
419 
420  return ossimImageFileWriter::hasImageType(imageType);
421 }
422 
424 {
425  if ( property.valid() )
426  {
428  {
429  ossimString stringValue;
430  property->valueToString(stringValue);
431  setQuality( stringValue.toInt32() );
432  }
433  else
434  {
436  }
437  }
438 }
439 
441 {
443  {
444  ossimNumericProperty* prop =
445  new ossimNumericProperty(name,
447  1.0,
448  100.0);
450  return prop;
451  }
452 
454 }
455 
456 void ossimJpegWriter::getPropertyNames(std::vector<ossimString>& propertyNames)const
457 {
459  propertyNames.push_back(name);
460 
462 }
virtual void setProperty(ossimRefPtr< ossimProperty > property)
Will set the property whose name matches the argument "property->getName()".
void set_uly(ossim_int32 y)
Definition: ossimIrect.h:666
virtual bool open()
ossim_int32 theQuality
#define CLOG
Definition: ossimTrace.h:23
virtual void setImageRectangle(const ossimIrect &rect)
virtual ossim_uint32 getTileWidth() const
Returns the default processing tile width.
Represents serializable keyword/value map.
static const ossimErrorCode OSSIM_OK
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
virtual ossimRefPtr< ossimImageData > getNextTile(ossim_uint32 resLevel=0)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
ossimIrect theAreaOfInterest
static ossimString toString(bool aValue)
Numeric to string methods.
const ossimIpt & ul() const
Definition: ossimIrect.h:274
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
Pushes this&#39;s names onto the list of property names.
virtual ossimString getExtension() const
Returns a 3-letter extension from the image type descriptor (theOutputImageType) that can be used for...
Pure virtual base class for image file writers.
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
virtual void initialize()
Initialize the data buffer.
virtual void setQuality(ossim_int32 quality)
Sets the jpeg compression quality.
virtual ossim_uint32 getSizePerBandInBytes() const
Returns the number of bytes in single band of the tile.
ossimConnectableObject * getInput(ossim_uint32 index=0)
returns the object at the specified index.
ossim_int32 toInt32() const
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
#define RTTI_DEF1_INST(cls, name, b1)
Definition: ossimRtti.h:481
virtual void close()
bool hasImageType(const ossimString &imageType) const
bool hasImageType(const ossimString& imageType) const
virtual void setAreaOfInterest(const ossimIrect &areaOfInterest)
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
virtual void getImageTypeList(std::vector< ossimString > &imageTypeList) const
void getImageTypeList(std::vector<ossimString>& imageTypeList)const
virtual void setNumericType(ossimNumericPropertyType type)
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
ossimRefPtr< ossimImageSourceSequencer > theInputConnection
unsigned int ossim_uint32
virtual ossimIrect getImageRectangle() const
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual void unloadTile(void *dest, const ossimIrect &dest_rect, ossimInterleaveType il_type) const
virtual ossim_int32 connectMyInputTo(ossimConnectableObject *inputObject, bool makeOutputConnection=true, bool createEventFlag=true)
Will try to connect this objects input to the passed in object.
virtual bool isOpen() const
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual bool hasImageType(const ossimString &imageType) const
bool hasImageType(const ossimString& imageType) const
virtual void setOrigin(const ossimIpt &origin)
ossim_int64 getNumberOfTilesHorizontal() const
virtual ossim_uint32 getTileHeight() const
Returns the default processing tile height.
virtual void setProperty(ossimRefPtr< ossimProperty > property)
void set_lry(ossim_int32 y)
Definition: ossimIrect.h:702
virtual ossimErrorCode getErrorStatus() const
ossim_int32 y
Definition: ossimIpt.h:142
virtual void setWriteExternalGeometryFlag(bool flag)
virtual const void * getBuf() const
static const char * COMPRESSION_QUALITY_KW
virtual bool writeFile()
Write out the file.
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
bool empty() const
Definition: ossimString.h:411
virtual void setDataObjectStatus(ossimDataObjectStatus status) const
Full list found in ossimConstants.h.
ossim_int32 x
Definition: ossimIpt.h:141
8 bit unsigned integer
virtual void setPercentComplete(double percentComplete)
virtual ~ossimJpegWriter()
virtual destructor
ossimJpegWriter()
default constructor
virtual const ossimIpt & getOrigin() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
ossim_int64 getNumberOfTilesVertical() const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
saves the state of the object.
const ossimString & getName() const
#define min(a, b)
Definition: auxiliary.h:75
int ossim_int32