root/OpenSceneGraph/trunk/examples/osgphotoalbum/PhotoArchive.cpp @ 5954

Revision 5954, 12.6 kB (checked in by robert, 8 years ago)

Ported following examples to osgViewer:

osgparticleeffects
osgphotoalbum
osgpick
osgpoints
osgpointsprite
osgprecipitation
osgprerender
osgprerendercubemap
osgreflect
osgscalarbar
osgscribe
osgsequence
osgplanets

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This application is open source and may be redistributed and/or modified under 
4 * the terms of the GNU Public License (GPL) version 1.0 or
5 * (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * OpenSceneGraph Public License for more details.
11*/
12
13#include "PhotoArchive.h"
14
15#include <osg/GLU>
16#include <osg/Notify>
17#include <osgDB/ReadFile>
18
19#include <osg/GraphicsContext>
20
21#include <fstream>
22#include <iostream>
23
24
25
26const std::string FILE_IDENTIFER("osgphotoalbum photo archive");
27
28class MyGraphicsContext {
29    public:
30        MyGraphicsContext()
31        {
32            osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
33            traits->x = 0;
34            traits->y = 0;
35            traits->width = 1;
36            traits->height = 1;
37            traits->windowDecoration = false;
38            traits->doubleBuffer = false;
39            traits->sharedContext = 0;
40            traits->pbuffer = true;
41
42            _gc = osg::GraphicsContext::createGraphicsContext(traits.get());
43
44            if (!_gc)
45            {
46                osg::notify(osg::NOTICE)<<"Failed to create pbuffer, failing back to normal graphics window."<<std::endl;
47               
48                traits->pbuffer = false;
49                _gc = osg::GraphicsContext::createGraphicsContext(traits.get());
50            }
51
52            if (_gc.valid())
53           
54           
55            {
56                _gc->realize();
57                _gc->makeCurrent();
58                std::cout<<"Realized window"<<std::endl;
59            }
60        }
61       
62        bool valid() const { return _gc.valid() && _gc->isRealized(); }
63       
64    private:
65        osg::ref_ptr<osg::GraphicsContext> _gc;
66};
67
68PhotoArchive::PhotoArchive(const std::string& filename)
69{
70    readPhotoIndex(filename);
71}
72
73bool PhotoArchive::readPhotoIndex(const std::string& filename)
74{
75    std::ifstream in(filename.c_str());
76   
77    char* fileIndentifier = new char [FILE_IDENTIFER.size()];
78    in.read(fileIndentifier,FILE_IDENTIFER.size());
79    if (FILE_IDENTIFER!=fileIndentifier) return false;
80   
81    unsigned int numPhotos;
82    in.read((char*)&numPhotos,sizeof(numPhotos));
83
84    _photoIndex.resize(numPhotos);
85
86    in.read((char*)&_photoIndex.front(),sizeof(PhotoHeader)*numPhotos);
87   
88    // success record filename.
89    _archiveFileName = filename;
90   
91    return true;
92}
93
94void PhotoArchive::getImageFileNameList(FileNameList& filenameList)
95{
96    for(PhotoIndexList::const_iterator itr=_photoIndex.begin();
97        itr!=_photoIndex.end();
98        ++itr)
99    {
100        filenameList.push_back(std::string(itr->filename));
101    }
102                       
103}
104
105osg::Image* PhotoArchive::readImage(const std::string& filename,
106                                    unsigned int target_s, unsigned target_t,
107                                    float& original_s, float& original_t)
108{
109    for(PhotoIndexList::const_iterator itr=_photoIndex.begin();
110        itr!=_photoIndex.end();
111        ++itr)
112    {
113        if (filename==itr->filename)
114        {
115            const PhotoHeader& photoHeader = *itr;
116       
117            if  (target_s <= photoHeader.thumbnail_s &&
118                 target_t <= photoHeader.thumbnail_t &&
119                 photoHeader.thumbnail_position != 0)
120            {
121                std::ifstream in(_archiveFileName.c_str(),std::ios::in | std::ios::binary);
122               
123                // find image
124                in.seekg(photoHeader.thumbnail_position);
125               
126                // read image header
127                ImageHeader imageHeader;
128                in.read((char*)&imageHeader,sizeof(ImageHeader));
129                unsigned char* data = new unsigned char[imageHeader.size];
130                in.read((char*)data,imageHeader.size);
131               
132                osg::Image* image = new osg::Image;
133                image->setImage(photoHeader.thumbnail_s,photoHeader.thumbnail_t,1,
134                                imageHeader.pixelFormat,imageHeader.pixelFormat,imageHeader.type,
135                                data,osg::Image::USE_NEW_DELETE);
136                               
137                original_s =  photoHeader.original_s;
138                original_t =  photoHeader.original_t;
139               
140                return image;
141            }
142                 
143            if  (photoHeader.fullsize_s &&
144                 photoHeader.fullsize_t &&
145                 photoHeader.fullsize_position != 0)
146            {
147                std::ifstream in(_archiveFileName.c_str(),std::ios::in | std::ios::binary);
148               
149                // find image
150                in.seekg(photoHeader.fullsize_position);
151               
152                // read image header
153                ImageHeader imageHeader;
154                in.read((char*)&imageHeader,sizeof(ImageHeader));
155                unsigned char* data = new unsigned char[imageHeader.size];
156                in.read((char*)data,imageHeader.size);
157               
158                osg::Image* image = new osg::Image;
159                image->setImage(photoHeader.fullsize_s,photoHeader.fullsize_t,1,
160                                imageHeader.pixelFormat,imageHeader.pixelFormat,imageHeader.type,
161                                data,osg::Image::USE_NEW_DELETE);
162                               
163                original_s =  photoHeader.original_s;
164                original_t =  photoHeader.original_t;
165               
166                return image;
167           }
168
169       }
170
171    }
172    return NULL;
173}
174
175void PhotoArchive::buildArchive(const std::string& filename, const FileNameList& imageList, unsigned int thumbnailSize, unsigned int maximumSize, bool /*compressed*/)
176{
177
178    PhotoIndexList photoIndex;
179    photoIndex.reserve(imageList.size());
180    for(FileNameList::const_iterator fitr=imageList.begin();
181        fitr!=imageList.end();
182        ++fitr)
183    {
184        PhotoHeader header;
185       
186        // set name
187        strncpy(header.filename,fitr->c_str(),255);
188        header.filename[255]=0;
189       
190        header.thumbnail_s = thumbnailSize;
191        header.thumbnail_t = thumbnailSize;
192        header.thumbnail_position = 0;
193       
194        header.fullsize_s = thumbnailSize;
195        header.fullsize_t = thumbnailSize;
196        header.fullsize_position = 0;
197
198        photoIndex.push_back(header);
199       
200    }
201
202    std::cout<<"Building photo archive containing "<<photoIndex.size()<<" pictures"<<std::endl;
203
204    // create a graphics context so we can do data operations
205    MyGraphicsContext context;
206
207    // open up the archive for writing to   
208    std::ofstream out(filename.c_str(), std::ios::out | std::ios::binary);
209
210    // write out file indentifier.
211    out.write(FILE_IDENTIFER.c_str(),FILE_IDENTIFER.size());
212
213    unsigned int numPhotos = photoIndex.size();
214    out.write((char*)&numPhotos,sizeof(unsigned int));
215
216    // write the photo index to ensure we can the correct amount of space
217    // available.
218    unsigned int startOfPhotoIndex = out.tellp();
219    out.write((char*)&photoIndex.front(),sizeof(PhotoHeader)*photoIndex.size());
220
221    unsigned int photoCount=1;   
222    for(PhotoIndexList::iterator pitr=photoIndex.begin();
223        pitr!=photoIndex.end();
224        ++pitr,++photoCount)
225    {
226        PhotoHeader& photoHeader = *pitr;
227       
228       
229        std::cout<<"Processing image "<<photoCount<<" of "<< photoIndex.size()<<" filename="<< photoHeader.filename << std::endl;
230        std::cout<<"    reading image...";std::cout.flush();
231       
232        osg::ref_ptr<osg::Image> image = osgDB::readImageFile(photoHeader.filename);
233       
234        std::cout<<"done."<< std::endl;
235       
236        photoHeader.original_s = image->s();
237        photoHeader.original_t = image->t();
238
239        {
240
241            std::cout<<"    creating thumbnail image...";
242            // first need to rescale image to the require thumbnail size
243            unsigned int newTotalSize =
244                image->computeRowWidthInBytes(thumbnailSize,image->getPixelFormat(),image->getDataType(),image->getPacking())*
245                thumbnailSize;
246
247            // need to sort out what size to really use...
248            unsigned char* newData = new unsigned char [newTotalSize];
249            if (!newData)
250            {
251                // should we throw an exception???  Just return for time being.
252                osg::notify(osg::FATAL) << "Error scaleImage() did not succeed : out of memory."<<newTotalSize<<std::endl;
253                return;
254            }
255
256            glPixelStorei(GL_PACK_ALIGNMENT,image->getPacking());
257            glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
258
259            GLint status = gluScaleImage(image->getPixelFormat(),
260                image->s(),
261                image->t(),
262                image->getDataType(),
263                image->data(),
264                thumbnailSize,
265                thumbnailSize,
266                image->getDataType(),
267                newData);
268
269            if (status!=0)
270            {
271               delete [] newData;
272
273                osg::notify(osg::WARN) << "Error scaleImage() did not succeed : errorString = "<<gluErrorString((GLenum)status)<<std::endl;
274            }
275   
276            // now set up the photo header.
277            photoHeader.thumbnail_s = thumbnailSize;
278            photoHeader.thumbnail_t = thumbnailSize;
279            photoHeader.thumbnail_position = (unsigned int)out.tellp();
280
281            // set up image header
282            ImageHeader imageHeader;
283            imageHeader.s = thumbnailSize;
284            imageHeader.t = thumbnailSize;
285            imageHeader.internalTextureformat = image->getInternalTextureFormat();
286            imageHeader.pixelFormat = image->getPixelFormat();
287            imageHeader.type = image->getDataType();
288            imageHeader.size = newTotalSize;
289
290            // write out image header and image data.
291            out.write((char*)&imageHeader,sizeof(ImageHeader));
292            out.write((char*)newData,imageHeader.size);
293           
294            delete [] newData;
295
296            std::cout<<"done."<< std::endl;
297
298        }
299       
300        {
301            std::cout<<"    creating fullsize image...";std::cout.flush();
302
303
304            photoHeader.fullsize_s = osg::minimum((unsigned int)image->s(),maximumSize);
305            photoHeader.fullsize_t = osg::minimum((unsigned int)image->t(),maximumSize);
306            photoHeader.fullsize_position = (unsigned int)out.tellp();
307
308            // first need to rescale image to the require thumbnail size
309            unsigned int newTotalSize =
310                image->computeRowWidthInBytes(photoHeader.fullsize_s,image->getPixelFormat(),image->getDataType(),image->getPacking())*
311                photoHeader.fullsize_t;
312
313            // need to sort out what size to really use...
314            unsigned char* newData = new unsigned char [newTotalSize];
315            if (!newData)
316            {
317                // should we throw an exception???  Just return for time being.
318                osg::notify(osg::FATAL) << "Error scaleImage() did not succeed : out of memory."<<newTotalSize<<std::endl;
319                return;
320            }
321
322            glPixelStorei(GL_PACK_ALIGNMENT,image->getPacking());
323            glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
324
325            GLint status = gluScaleImage(image->getPixelFormat(),
326                image->s(),
327                image->t(),
328                image->getDataType(),
329                image->data(),
330                photoHeader.fullsize_s,
331                photoHeader.fullsize_t,
332                image->getDataType(),
333                newData);
334
335            if (status!=0)
336            {
337               delete [] newData;
338
339                osg::notify(osg::WARN) << "Error scaleImage() did not succeed : errorString = "<<gluErrorString((GLenum)status)<<std::endl;
340            }
341
342            ImageHeader imageHeader;
343            imageHeader.s = photoHeader.fullsize_s;
344            imageHeader.t = photoHeader.fullsize_t;
345            imageHeader.internalTextureformat = image->getInternalTextureFormat();
346            imageHeader.pixelFormat = image->getPixelFormat();
347            imageHeader.type = image->getDataType();
348            imageHeader.size = newTotalSize;
349
350            out.write((char*)&imageHeader,sizeof(ImageHeader));
351            out.write((char*)newData,imageHeader.size);
352            //out.write((char*)image->data(),imageHeader.size);
353
354            delete [] newData;
355
356            std::cout<<"done."<< std::endl;
357        }
358       
359    }
360
361    // rewrite photo index now it has the correct sizes set
362    out.seekp(startOfPhotoIndex);
363    out.write((char*)&photoIndex.front(),sizeof(PhotoHeader)*photoIndex.size());
364
365}
Note: See TracBrowser for help on using the browser.