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

Revision 11829, 11.9 kB (checked in by robert, 4 years ago)

Introduced osg namespace to new local GLU functions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgphotoalbum.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include "PhotoArchive.h"
20
21#include <osg/GLU>
22#include <osg/Notify>
23#include <osgDB/ReadFile>
24#include <osgDB/fstream>
25
26#include <osg/GraphicsContext>
27
28#include <iostream>
29#include <string.h>
30
31const std::string FILE_IDENTIFER("osgphotoalbum photo archive");
32
33PhotoArchive::PhotoArchive(const std::string& filename)
34{
35    readPhotoIndex(filename);
36}
37
38bool PhotoArchive::readPhotoIndex(const std::string& filename)
39{
40    osgDB::ifstream in(filename.c_str());
41   
42    char* fileIndentifier = new char [FILE_IDENTIFER.size()];
43    in.read(fileIndentifier,FILE_IDENTIFER.size());
44    if (FILE_IDENTIFER!=fileIndentifier) return false;
45   
46    unsigned int numPhotos;
47    in.read((char*)&numPhotos,sizeof(numPhotos));
48
49    _photoIndex.resize(numPhotos);
50
51    in.read((char*)&_photoIndex.front(),sizeof(PhotoHeader)*numPhotos);
52   
53    // success record filename.
54    _archiveFileName = filename;
55   
56    return true;
57}
58
59void PhotoArchive::getImageFileNameList(FileNameList& filenameList)
60{
61    for(PhotoIndexList::const_iterator itr=_photoIndex.begin();
62        itr!=_photoIndex.end();
63        ++itr)
64    {
65        filenameList.push_back(std::string(itr->filename));
66    }
67                       
68}
69
70osg::Image* PhotoArchive::readImage(const std::string& filename,
71                                    unsigned int target_s, unsigned target_t,
72                                    float& original_s, float& original_t)
73{
74    for(PhotoIndexList::const_iterator itr=_photoIndex.begin();
75        itr!=_photoIndex.end();
76        ++itr)
77    {
78        if (filename==itr->filename)
79        {
80            const PhotoHeader& photoHeader = *itr;
81       
82            if  (target_s <= photoHeader.thumbnail_s &&
83                 target_t <= photoHeader.thumbnail_t &&
84                 photoHeader.thumbnail_position != 0)
85            {
86                osgDB::ifstream in(_archiveFileName.c_str(),std::ios::in | std::ios::binary);
87               
88                // find image
89                in.seekg(photoHeader.thumbnail_position);
90               
91                // read image header
92                ImageHeader imageHeader;
93                in.read((char*)&imageHeader,sizeof(ImageHeader));
94                unsigned char* data = new unsigned char[imageHeader.size];
95                in.read((char*)data,imageHeader.size);
96               
97                osg::Image* image = new osg::Image;
98                image->setImage(photoHeader.thumbnail_s,photoHeader.thumbnail_t,1,
99                                imageHeader.pixelFormat,imageHeader.pixelFormat,imageHeader.type,
100                                data,osg::Image::USE_NEW_DELETE);
101                               
102                original_s =  photoHeader.original_s;
103                original_t =  photoHeader.original_t;
104               
105                return image;
106            }
107                 
108            if  (photoHeader.fullsize_s &&
109                 photoHeader.fullsize_t &&
110                 photoHeader.fullsize_position != 0)
111            {
112                osgDB::ifstream in(_archiveFileName.c_str(),std::ios::in | std::ios::binary);
113               
114                // find image
115                in.seekg(photoHeader.fullsize_position);
116               
117                // read image header
118                ImageHeader imageHeader;
119                in.read((char*)&imageHeader,sizeof(ImageHeader));
120                unsigned char* data = new unsigned char[imageHeader.size];
121                in.read((char*)data,imageHeader.size);
122               
123                osg::Image* image = new osg::Image;
124                image->setImage(photoHeader.fullsize_s,photoHeader.fullsize_t,1,
125                                imageHeader.pixelFormat,imageHeader.pixelFormat,imageHeader.type,
126                                data,osg::Image::USE_NEW_DELETE);
127                               
128                original_s =  photoHeader.original_s;
129                original_t =  photoHeader.original_t;
130               
131                return image;
132           }
133
134       }
135
136    }
137    return NULL;
138}
139
140void PhotoArchive::buildArchive(const std::string& filename, const FileNameList& imageList, unsigned int thumbnailSize, unsigned int maximumSize, bool /*compressed*/)
141{
142
143    PhotoIndexList photoIndex;
144    photoIndex.reserve(imageList.size());
145    for(FileNameList::const_iterator fitr=imageList.begin();
146        fitr!=imageList.end();
147        ++fitr)
148    {
149        PhotoHeader header;
150       
151        // set name
152        strncpy(header.filename,fitr->c_str(),255);
153        header.filename[255]=0;
154       
155        header.thumbnail_s = thumbnailSize;
156        header.thumbnail_t = thumbnailSize;
157        header.thumbnail_position = 0;
158       
159        header.fullsize_s = thumbnailSize;
160        header.fullsize_t = thumbnailSize;
161        header.fullsize_position = 0;
162
163        photoIndex.push_back(header);
164       
165    }
166
167    std::cout<<"Building photo archive containing "<<photoIndex.size()<<" pictures"<<std::endl;
168
169    // open up the archive for writing to
170    osgDB::ofstream out(filename.c_str(), std::ios::out | std::ios::binary);
171
172    // write out file indentifier.
173    out.write(FILE_IDENTIFER.c_str(),FILE_IDENTIFER.size());
174
175    unsigned int numPhotos = photoIndex.size();
176    out.write((char*)&numPhotos,sizeof(unsigned int));
177
178    // write the photo index to ensure we can the correct amount of space
179    // available.
180    unsigned int startOfPhotoIndex = out.tellp();
181    out.write((char*)&photoIndex.front(),sizeof(PhotoHeader)*photoIndex.size());
182
183    unsigned int photoCount=1;   
184    for(PhotoIndexList::iterator pitr=photoIndex.begin();
185        pitr!=photoIndex.end();
186        ++pitr,++photoCount)
187    {
188        PhotoHeader& photoHeader = *pitr;
189       
190       
191        std::cout<<"Processing image "<<photoCount<<" of "<< photoIndex.size()<<" filename="<< photoHeader.filename << std::endl;
192        std::cout<<"    reading image...";std::cout.flush();
193       
194        osg::ref_ptr<osg::Image> image = osgDB::readImageFile(photoHeader.filename);
195       
196        std::cout<<"done."<< std::endl;
197       
198        photoHeader.original_s = image->s();
199        photoHeader.original_t = image->t();
200
201        {
202
203            std::cout<<"    creating thumbnail image...";
204            // first need to rescale image to the require thumbnail size
205            unsigned int newTotalSize =
206                image->computeRowWidthInBytes(thumbnailSize,image->getPixelFormat(),image->getDataType(),image->getPacking())*
207                thumbnailSize;
208
209            // need to sort out what size to really use...
210            unsigned char* newData = new unsigned char [newTotalSize];
211            if (!newData)
212            {
213                // should we throw an exception???  Just return for time being.
214                osg::notify(osg::FATAL) << "Error scaleImage() did not succeed : out of memory."<<newTotalSize<<std::endl;
215                return;
216            }
217
218            osg::PixelStorageModes psm;
219            psm.pack_alignment = image->getPacking();
220            psm.unpack_alignment = image->getPacking();
221
222            GLint status = osg::gluScaleImage(&psm, image->getPixelFormat(),
223                image->s(),
224                image->t(),
225                image->getDataType(),
226                image->data(),
227                thumbnailSize,
228                thumbnailSize,
229                image->getDataType(),
230                newData);
231
232            if (status!=0)
233            {
234               delete [] newData;
235
236                osg::notify(osg::WARN) << "Error scaleImage() did not succeed : errorString = "<<osg::gluErrorString((GLenum)status)<<std::endl;
237            }
238   
239            // now set up the photo header.
240            photoHeader.thumbnail_s = thumbnailSize;
241            photoHeader.thumbnail_t = thumbnailSize;
242            photoHeader.thumbnail_position = (unsigned int)out.tellp();
243
244            // set up image header
245            ImageHeader imageHeader;
246            imageHeader.s = thumbnailSize;
247            imageHeader.t = thumbnailSize;
248            imageHeader.internalTextureformat = image->getInternalTextureFormat();
249            imageHeader.pixelFormat = image->getPixelFormat();
250            imageHeader.type = image->getDataType();
251            imageHeader.size = newTotalSize;
252
253            // write out image header and image data.
254            out.write((char*)&imageHeader,sizeof(ImageHeader));
255            out.write((char*)newData,imageHeader.size);
256           
257            delete [] newData;
258
259            std::cout<<"done."<< std::endl;
260
261        }
262       
263        {
264            std::cout<<"    creating fullsize image...";std::cout.flush();
265
266
267            photoHeader.fullsize_s = osg::minimum((unsigned int)image->s(),maximumSize);
268            photoHeader.fullsize_t = osg::minimum((unsigned int)image->t(),maximumSize);
269            photoHeader.fullsize_position = (unsigned int)out.tellp();
270
271            // first need to rescale image to the require thumbnail size
272            unsigned int newTotalSize =
273                image->computeRowWidthInBytes(photoHeader.fullsize_s,image->getPixelFormat(),image->getDataType(),image->getPacking())*
274                photoHeader.fullsize_t;
275
276            // need to sort out what size to really use...
277            unsigned char* newData = new unsigned char [newTotalSize];
278            if (!newData)
279            {
280                // should we throw an exception???  Just return for time being.
281                osg::notify(osg::FATAL) << "Error scaleImage() did not succeed : out of memory."<<newTotalSize<<std::endl;
282                return;
283            }
284
285            osg::PixelStorageModes psm;
286            psm.pack_alignment = image->getPacking();
287            psm.unpack_alignment = image->getPacking();
288
289            GLint status = osg::gluScaleImage(&psm, image->getPixelFormat(),
290                image->s(),
291                image->t(),
292                image->getDataType(),
293                image->data(),
294                photoHeader.fullsize_s,
295                photoHeader.fullsize_t,
296                image->getDataType(),
297                newData);
298
299            if (status!=0)
300            {
301               delete [] newData;
302
303                osg::notify(osg::WARN) << "Error scaleImage() did not succeed : errorString = "<<osg::gluErrorString((GLenum)status)<<std::endl;
304            }
305
306            ImageHeader imageHeader;
307            imageHeader.s = photoHeader.fullsize_s;
308            imageHeader.t = photoHeader.fullsize_t;
309            imageHeader.internalTextureformat = image->getInternalTextureFormat();
310            imageHeader.pixelFormat = image->getPixelFormat();
311            imageHeader.type = image->getDataType();
312            imageHeader.size = newTotalSize;
313
314            out.write((char*)&imageHeader,sizeof(ImageHeader));
315            out.write((char*)newData,imageHeader.size);
316            //out.write((char*)image->data(),imageHeader.size);
317
318            delete [] newData;
319
320            std::cout<<"done."<< std::endl;
321        }
322       
323    }
324
325    // rewrite photo index now it has the correct sizes set
326    out.seekp(startOfPhotoIndex);
327    out.write((char*)&photoIndex.front(),sizeof(PhotoHeader)*photoIndex.size());
328
329}
Note: See TracBrowser for help on using the browser.