libopenraw
|
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