neffile.cpp

00001 /* -*- tab-width:4; c-basic-offset:4 -*- */
00002 
00003 /*
00004  * libopenraw - neffile.cpp
00005  *
00006  * Copyright (C) 2006-2008 Hubert Figuiere
00007  * Copyright (C) 2008 Novell, Inc.
00008  *
00009  * This library is free software: you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public License
00011  * as published by the Free Software Foundation, either version 3 of
00012  * the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library.  If not, see
00021  * <http://www.gnu.org/licenses/>.
00022  */
00023 
00024 
00025 #include <iostream>
00026 #include <vector>
00027 #include <libopenraw++/thumbnail.h>
00028 #include <libopenraw++/rawdata.h>
00029 
00030 #include "debug.h"
00031 #include "ifd.h"
00032 #include "ifdfilecontainer.h"
00033 #include "ifddir.h"
00034 #include "ifdentry.h"
00035 #include "io/file.h"
00036 #include "huffman.h"
00037 #include "nefdiffiterator.h"
00038 #include "nefcfaiterator.h"
00039 #include "neffile.h"
00040 
00041 using namespace Debug;
00042 
00043 namespace OpenRaw {
00044 
00045 
00046     namespace Internals {
00047         const IFDFile::camera_ids_t NEFFile::s_def[] = {
00048             { "NIKON D1 ", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00049                                                OR_TYPEID_NIKON_D1) },
00050             { "NIKON D100 ", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00051                                                OR_TYPEID_NIKON_D100) },
00052             { "NIKON D1X", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00053                                                OR_TYPEID_NIKON_D1X) },
00054             { "NIKON D200", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00055                                                 OR_TYPEID_NIKON_D200) },
00056             { "NIKON D2H", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00057                                                OR_TYPEID_NIKON_D2H ) },
00058             { "NIKON D2X", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00059                                                OR_TYPEID_NIKON_D2X ) },
00060             { "NIKON D3", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00061                                               OR_TYPEID_NIKON_D3) },
00062             { "NIKON D300", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00063                                                 OR_TYPEID_NIKON_D300) },
00064             { "NIKON D40", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00065                                                OR_TYPEID_NIKON_D40) },
00066             { "NIKON D40X", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00067                                                OR_TYPEID_NIKON_D40X) },
00068             { "NIKON D50", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00069                                                OR_TYPEID_NIKON_D50) },
00070             { "NIKON D70", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00071                                                OR_TYPEID_NIKON_D70) },
00072             { "NIKON D70s", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00073                                                OR_TYPEID_NIKON_D70S) },
00074             { "NIKON D80", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 
00075                                                OR_TYPEID_NIKON_D80) },
00076             { 0, 0 }
00077         };
00078 
00079         RawFile *NEFFile::factory(IO::Stream* _filename)
00080         {
00081             return new NEFFile(_filename);
00082         }
00083 
00084         NEFFile::NEFFile(IO::Stream* _filename)
00085             : TiffEpFile(_filename, OR_RAWFILE_TYPE_NEF)
00086         {
00087             _setIdMap(s_def);
00088         }
00089 
00090 
00091         NEFFile::~NEFFile()
00092         {
00093         }
00094 
00095         bool NEFFile::isCompressed(RawContainer & container, uint32_t offset)
00096         {
00097             int i;
00098             uint8_t buf[256];
00099             size_t real_size = container.fetchData(buf, offset, 
00100                                                    256);
00101             if(real_size != 256) {
00102                 return true;
00103             }
00104             for(i = 15; i < 256; i+= 16) {
00105                 if(buf[i]) {
00106                     Trace(DEBUG1) << "isCompressed: true\n";
00107                     return true;
00108                 }
00109             }
00110             Trace(DEBUG1) << "isCompressed: false\n";
00111             return false;
00112         }
00113 
00114         ::or_error NEFFile::_decompressNikonQuantized(RawData & data)
00115         {
00116             NEFCompressionInfo c;
00117             if (!_getCompressionCurve(data, c)) {
00118                 return OR_ERROR_NOT_FOUND;
00119             }
00120             const uint32_t rows = data.y();
00121             const uint32_t raw_columns = data.x();
00122 
00123             //FIXME: not always true
00124             const uint32_t columns = raw_columns - 1;
00125 
00126             NefDiffIterator
00127                 diffs(c.huffman, data.data());
00128             NefCfaIterator iter(diffs, rows, raw_columns, c.vpred);
00129 
00130             RawData newData;
00131             uint16_t *p = (uint16_t *) newData.allocData(rows * columns * 2);
00132             newData.setDimensions(columns, rows);
00133             newData.setDataType(OR_DATA_TYPE_CFA);
00134             uint16_t bpc = data.bpc();
00135             newData.setBpc(bpc);
00136             newData.setMax((1 << bpc) - 1);
00137             newData.setCfaPattern(data.cfaPattern());
00138        
00139             for (unsigned int i = 0; i < rows; i++) {
00140                 for (unsigned int j = 0; j < raw_columns; j++) {
00141                     uint16_t t = iter.get();
00142                     if (j < columns) {
00143                         unsigned shift = 16 - data.bpc();
00144                         p[i * columns + j] =  c.curve[t & 0x3fff] << shift;
00145                     }
00146                 }
00147             }
00148 
00149             data.swap(newData);
00150             return OR_ERROR_NONE;
00151         }
00152 
00153         ::or_error NEFFile::_decompressIfNeeded(RawData & data,
00154                                                 uint32_t options)
00155         {
00156             uint32_t compression = data.compression();
00157             if((options & OR_OPTIONS_DONT_DECOMPRESS) ||
00158                compression == IFD::COMPRESS_NONE) {
00159                 return OR_ERROR_NONE;
00160             } else if(compression == IFD::COMPRESS_NIKON_QUANTIZED) {
00161                 return _decompressNikonQuantized(data);
00162             } else {
00163                 return OR_ERROR_INVALID_FORMAT;
00164             }
00165         }
00166 
00167         int NEFFile::_getCompressionCurve(RawData & data,  NEFFile::NEFCompressionInfo& c)
00168         {
00169             if(!m_exifIfd) {
00170                 m_exifIfd = _locateExifIfd();
00171             }
00172             if(!m_exifIfd) {
00173                 return 0;
00174             }
00175 
00176             IFDEntry::Ref maker_ent =
00177                 m_exifIfd->getEntry(IFD::EXIF_TAG_MAKER_NOTE);
00178             if(!maker_ent) {
00179                 return 0;
00180             }
00181 
00182             uint32_t off = maker_ent->offset();
00183             uint32_t base = off + 10;
00184 
00185             IFDDir::Ref ref(new IFDDir(base + 8, *m_container));
00186             ref->load();
00187             IFDEntry::Ref curveEntry = ref->getEntry(0x0096);
00188             if(!curveEntry) {
00189                 return 0;
00190             }
00191 
00192             size_t pos = base + curveEntry->offset();
00193 
00194             IO::Stream *file = m_container->file();
00195             file->seek(pos, SEEK_SET);
00196 
00197             int16_t aux;
00198 
00199             uint16_t header;
00200             bool read = m_container->readInt16(file, aux);
00201             header = aux;
00202             if(!read) {
00203                 return 0;
00204             }
00205 
00206             if (header == 0x4410) {
00207                 c.huffman = NefDiffIterator::Lossy12Bit;
00208                 data.setBpc(12);
00209             } else if (header == 0x4630) {
00210                 c.huffman = NefDiffIterator::LossLess14Bit;
00211                 data.setBpc(14);
00212             } else {
00213                 return 0;
00214             }
00215 
00216             for (int i = 0; i < 2; ++i) {
00217                 for (int j = 0; j < 2; ++j) {
00218                     read = m_container->readInt16(file, aux);
00219                     if(!read) {
00220                         return 0;
00221                     }
00222                     c.vpred[i][j] = aux;
00223                 }
00224             }
00225 
00226             if (header == 0x4410) {
00227                 size_t nelems;
00228                 read = m_container->readInt16(file, aux);
00229                 nelems = aux;
00230 
00231                 for (size_t i = 0; i < nelems; ++i) {
00232                     read = m_container->readInt16(file, aux);
00233                     if (!read)
00234                         return 0;
00235                     c.curve.push_back(aux);
00236                 }
00237             } else if (header == 0x4630) {
00238                 for (size_t i = 0; i <= 0x3fff; ++i) {
00239                     c.curve.push_back(i);
00240                 }
00241             }
00242 
00243             return 1;
00244         }
00245 
00246         ::or_error NEFFile::_getRawData(RawData & data, uint32_t options)
00247         {
00248             ::or_error ret = OR_ERROR_NONE;
00249             m_cfaIfd = _locateCfaIfd();
00250             Trace(DEBUG1) << "_getRawData()\n";
00251 
00252             if(m_cfaIfd) {
00253                 ret = _getRawDataFromDir(data, m_cfaIfd);
00254                 if (ret != OR_ERROR_NONE) {
00255                     return ret;
00256                 }
00257                 ret = _decompressIfNeeded(data, options);
00258             }
00259             else {
00260                 ret = OR_ERROR_NOT_FOUND;
00261             }
00262             return ret;
00263         }
00264 
00265     }
00266 }
00267 

Generated on Wed Aug 25 01:26:34 2010 for libopenraw by  doxygen 1.5.9