PageRenderTime 913ms CodeModel.GetById 154ms app.highlight 272ms RepoModel.GetById 152ms app.codeStats 0ms

/Source/System/FileIO/OSB/OSGOSBImageElement.cpp

https://github.com/msteners/OpenSGDevMaster_Toolbox
C++ | 306 lines | 178 code | 57 blank | 71 comment | 28 complexity | 0d2384d05550541a3a860cd146dad9b8 MD5 | raw file
  1/*---------------------------------------------------------------------------*\
  2 *                                OpenSG                                     *
  3 *                                                                           *
  4 *                                                                           *
  5 *                   Copyright (C) 2007 by the OpenSG Forum                  *
  6 *                                                                           *
  7 *                            www.opensg.org                                 *
  8 *                                                                           *
  9 *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
 10 *                                                                           *
 11\*---------------------------------------------------------------------------*/
 12/*---------------------------------------------------------------------------*\
 13 *                                License                                    *
 14 *                                                                           *
 15 * This library is free software; you can redistribute it and/or modify it   *
 16 * under the terms of the GNU Library General Public License as published    *
 17 * by the Free Software Foundation, version 2.                               *
 18 *                                                                           *
 19 * This library is distributed in the hope that it will be useful, but       *
 20 * WITHOUT ANY WARRANTY; without even the implied warranty of                *
 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
 22 * Library General Public License for more details.                          *
 23 *                                                                           *
 24 * You should have received a copy of the GNU Library General Public         *
 25 * License along with this library; if not, write to the Free Software       *
 26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
 27 *                                                                           *
 28\*---------------------------------------------------------------------------*/
 29/*---------------------------------------------------------------------------*\
 30 *                                Changes                                    *
 31 *                                                                           *
 32 *                                                                           *
 33 *                                                                           *
 34 *                                                                           *
 35 *                                                                           *
 36 *                                                                           *
 37\*---------------------------------------------------------------------------*/
 38
 39#include "OSGOSBImageElement.h"
 40
 41#include "OSGOSBRootElement.h"
 42#include "OSGImage.h"
 43#include "OSGImageFileHandler.h"
 44
 45OSG_USING_NAMESPACE
 46
 47/*-------------------------------------------------------------------------*/
 48/* OSBImageElement                                                         */
 49/*-------------------------------------------------------------------------*/
 50
 51/*-------------------------------------------------------------------------*/
 52/* Static members                                                          */
 53
 54OSBElementRegistrationHelper<OSBImageElement>
 55    OSBImageElement::_regHelper =
 56        OSBElementRegistrationHelper<OSBImageElement>("Image");
 57
 58const UInt8 OSBImageElement::FlagPixelDataCompressedMask;
 59const UInt8 OSBImageElement::FlagPixelDataCompressed;
 60const UInt8 OSBImageElement::FlagPixelDataOutOfLineMask;
 61const UInt8 OSBImageElement::FlagPixelDataOutOfLine;
 62
 63/*-------------------------------------------------------------------------*/
 64/* Constructor                                                             */
 65
 66OSBImageElement::OSBImageElement(OSBRootElement *root)
 67    : Inherited      (root, OSGOSBHeaderVersion200),
 68      _hasJPEGSupport(false                        ),
 69      _version       (OSGOSBHeaderVersion200      )
 70{
 71}
 72
 73/*-------------------------------------------------------------------------*/
 74/* Destructor                                                              */
 75
 76OSBImageElement::~OSBImageElement(void)
 77{
 78}
 79
 80/*-------------------------------------------------------------------------*/
 81/* Reading                                                                 */
 82
 83void
 84OSBImageElement::read(const std::string &typeName)
 85{
 86    OSG_OSB_LOG(("OSBImageElement::read [%s]\n", typeName.c_str()));
 87
 88    const OSBRootElement *root      = getRoot();
 89    BinaryReadHandler     *rh        = editRoot()->getReadHandler();
 90    UInt8                  fcPtrType;
 91
 92    if(root->getHeaderVersion() >= OSGOSBHeaderVersion200)
 93    {
 94        if(root->getHeaderVersion() > OSGOSBHeaderVersion200)
 95        {
 96            FINFO(("OSBImageElement::read: "
 97                   "Unknown version, trying to process as latest.\n"));
 98        }
 99
100        rh->getValue(fcPtrType);
101    }
102
103    ImageUnrecPtr img = Image::create();
104    setContainer(img);
105
106    rh->getValue(_version);
107
108    if(_version >= OSGOSBHeaderVersion200)
109    {
110        UInt8 flags;
111        rh->getValue(flags);
112
113        if(flags & FlagPixelDataCompressedMask)
114        {
115            // compressed inline texture
116            std::string endMarker = "'pixel'";
117            std::string fieldName = readFields("", endMarker);
118
119            if(fieldName == "pixel")
120            {
121                readCompressedPixelData();
122            }
123        }
124        else
125        {
126            // read fields stored in file
127            readFields("", "");
128            
129            if(flags & FlagPixelDataOutOfLineMask)
130            {
131                // read out-of-line image data
132                const std::string &fileName = img->getName();
133                img = ImageFileHandler::the()->read(fileName.c_str());
134                setContainer(img);
135            }
136        }
137    }
138    else if(_version >= OSGOSBHeaderVersion100)
139    {
140        std::string endMarker = "'cpixel'";
141        std::string fieldName = readFields("", endMarker);
142
143        // read compressed pixel data - should be the last field
144        if(fieldName == "cpixel")
145        {
146            readCompressedPixelData();
147        }
148
149        // read any remaining fields - should be none, but this is safe to do.
150        readFieldsContinue(fieldName, "", "");
151
152        // read out-of-line image data
153        if(img->getMFPixel()->empty())
154        {
155            const std::string &fileName = img->getName();
156            img = ImageFileHandler::the()->read(fileName.c_str());
157            setContainer(img);
158        }
159    }
160}
161
162void
163OSBImageElement::postRead(void)
164{
165    // nothing to do
166}
167
168/*-------------------------------------------------------------------------*/
169/* Writing                                                                 */
170
171void
172OSBImageElement::preWrite(FieldContainer * const fc)
173{
174    OSG_OSB_LOG(("OSBImageElement::preWrite\n"));
175
176    preWriteFieldContainer(fc, "");
177}
178
179void
180OSBImageElement::write(void)
181{
182    OSG_OSB_LOG(("OSBImageElement::write\n"));
183
184    if(getContainer() == NULL)
185    {
186        FWARNING(("OSBImageElement::write: Attempt to write NULL.\n"));
187        return;
188    }
189
190    Image                *img   = dynamic_cast<Image *>(getContainer());
191    BinaryWriteHandler   *wh    = editRoot()->getWriteHandler();
192    const OSBRootElement *root  = getRoot();
193    UInt8                 flags = 0;
194
195    wh->putValue(getFCPtrType(getContainer()));
196    wh->putValue(getVersion()                );
197
198    std::string excludeFields    = "";
199    bool        compressTextures = false;
200
201    if(getRoot()->getOptions().inlineTextures() == false)
202    {
203        // only write "name" field
204        flags |= FlagPixelDataOutOfLine;
205        excludeFields.append("'dimension' 'width' 'height' 'depth' 'bpp' "
206                             "'mipMapCount' 'frameCount' 'frameDelay' "
207                             "'pixelFormat' 'pixel' 'frameSize' "         );
208    }
209    else
210    {
211        if(_hasJPEGSupport && root->getOptions().compressTextures() &&
212           (img->getDataType() == Image::OSG_UINT8_IMAGEDATA)       &&
213           ((img->getBpp() == 1) || (img->getBpp() == 3))             )
214        {
215            compressTextures =  true;
216            flags            |= FlagPixelDataCompressed;
217            excludeFields.append("'pixel'");
218        }
219    }
220
221    // write flags
222    wh->putValue(flags);
223
224    // write all fields that do not require special handling
225    writeFields(excludeFields, false);
226
227    if(compressTextures)
228        writeCompressedPixelData();
229
230    writeEndMarker();
231}
232
233/*-------------------------------------------------------------------------*/
234/* Reading Helper Functions                                                */
235
236void
237OSBImageElement::readCompressedPixelData(void)
238{
239    BinaryReadHandler *rh  = editRoot()->getReadHandler();
240    Image             *img = dynamic_cast<Image *>(getContainer());
241
242    std::string        fieldTypeName;
243    UInt32             fieldSize;
244    UInt32             byteSize;
245    std::vector<UInt8> buffer;
246
247    rh->getValue(fieldTypeName);
248    rh->getValue(fieldSize    );
249
250    if(!_hasJPEGSupport)
251    {
252        FWARNING(("OSBImageElement::readCompressedPixelData: "
253                  "JPEG Support not available, skipping compressed "
254                  "texture data.\n"));
255        rh->skip(fieldSize);
256        return;
257    }
258
259    rh->getValue(byteSize);
260
261    // allocate and fill buffer
262    buffer.resize(byteSize);
263    rh->getValues(&buffer.front(), byteSize);
264
265    img->restore(&buffer.front(), byteSize);
266}
267
268/*-------------------------------------------------------------------------*/
269/* Writing Helper Functions                                                */
270
271void
272OSBImageElement::writeCompressedPixelData(void)
273{
274    // FIXME Inline Images are disabled right now. A more recent versin of
275    //       the ImageFileHandler from CVS needs to be ported to OpenSG 2.
276
277    const OSBRootElement *root = getRoot();
278    BinaryWriteHandler   *wh   = editRoot()->getWriteHandler();
279
280    Image       *img       = dynamic_cast<Image *>(getContainer());
281    std::string  imageType = root->getOptions().texturesImageType();
282//     std::string imageType = "jpeg";
283
284    std::vector<UInt8> buffer;
285    UInt32             factor = 1;
286
287    // JPEG always uses RGB, so single channel images need additional memory
288    if((imageType == "jpeg") && (img->getBpp() == 1))
289        factor = 3;
290
291    // some extra space is needed for the image header
292    UInt32 bufferSize =
293       ImageFileHandler::the()->getDefaultType()->maxBufferSize(img) * factor +
294           16384;
295
296    buffer.resize(bufferSize);
297    UInt64 compressedSize = img->store(imageType.c_str(), &buffer.front());
298//     UInt64 compressedSize = 0;
299
300    UInt32 byteSize  = static_cast<UInt32>(compressedSize);
301    UInt32 fieldSize = sizeof(UInt32) + sizeof(UInt8) * byteSize;
302
303    wh->putValue (fieldSize                );
304    wh->putValue (byteSize                 );
305    wh->putValues(&buffer.front(), byteSize);
306}