libopenraw
|
00001 /* 00002 * libopenraw - ifdfile.cpp 00003 * 00004 * Copyright (C) 2006-2008 Hubert Figuiere 00005 * Copyright (C) 2008 Novell, Inc. 00006 * 00007 * This library is free software: you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License 00009 * as published by the Free Software Foundation, either version 3 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library. If not, see 00019 * <http://www.gnu.org/licenses/>. 00020 */ 00021 00022 #include <algorithm> 00023 #include <numeric> 00024 #include <boost/scoped_ptr.hpp> 00025 #include <boost/scoped_array.hpp> 00026 00027 #include <libopenraw++/thumbnail.h> 00028 #include <libopenraw++/rawdata.h> 00029 00030 #include "trace.h" 00031 #include "io/stream.h" 00032 #include "io/streamclone.h" 00033 #include "io/file.h" 00034 #include "ifd.h" 00035 #include "ifdfile.h" 00036 #include "ifdfilecontainer.h" 00037 #include "jfifcontainer.h" 00038 #include "neffile.h" // I wonder if this is smart as it break the abstraction. 00039 #include "metavalue.h" 00040 #include "unpack.h" 00041 00042 using namespace Debug; 00043 using boost::scoped_ptr; 00044 00045 00046 namespace OpenRaw { 00047 namespace Internals { 00048 00049 00050 IFDFile::IFDFile(IO::Stream *s, Type _type, 00051 bool instantiateContainer) 00052 : RawFile(s, _type), 00053 m_thumbLocations(), 00054 m_io(s), 00055 m_container(NULL) 00056 { 00057 if(instantiateContainer) { 00058 m_container = new IFDFileContainer(m_io, 0); 00059 } 00060 } 00061 00062 IFDFile::~IFDFile() 00063 { 00064 delete m_container; 00065 delete m_io; 00066 } 00067 00068 // this one seems to be pretty much the same for all the 00069 // IFD based raw files 00070 IFDDir::Ref IFDFile::_locateExifIfd() 00071 { 00072 m_mainIfd = _locateMainIfd(); 00073 if (!m_mainIfd) { 00074 Trace(ERROR) << "IFDFile::_locateExifIfd() " 00075 "main IFD not found\n"; 00076 return IFDDir::Ref(); 00077 } 00078 return m_mainIfd->getExifIFD(); 00079 } 00080 00081 00082 void IFDFile::_identifyId() 00083 { 00084 if(!m_mainIfd) { 00085 m_mainIfd = _locateMainIfd(); 00086 } 00087 if(!m_mainIfd) { 00088 Trace(ERROR) << "Main IFD not found to identify the file.\n"; 00089 return; 00090 } 00091 std::string model; 00092 if(m_mainIfd->getValue(IFD::EXIF_TAG_MODEL, model)) { 00093 _setTypeId(_typeIdFromModel(model)); 00094 } 00095 } 00096 00097 00098 00099 ::or_error IFDFile::_enumThumbnailSizes(std::vector<uint32_t> &list) 00100 { 00101 ::or_error err = OR_ERROR_NONE; 00102 00103 Trace(DEBUG1) << "_enumThumbnailSizes()\n"; 00104 std::vector<IFDDir::Ref> & dirs = m_container->directories(); 00105 std::vector<IFDDir::Ref>::iterator iter; 00106 00107 Trace(DEBUG1) << "num of dirs " << dirs.size() << "\n"; 00108 for(iter = dirs.begin(); iter != dirs.end(); ++iter) 00109 { 00110 IFDDir::Ref & dir = *iter; 00111 dir->load(); 00112 or_error ret = _locateThumbnail(dir, list); 00113 if (ret == OR_ERROR_NONE) 00114 { 00115 Trace(DEBUG1) << "Found " << list.back() << " pixels\n"; 00116 } 00117 std::vector<IFDDir::Ref> subdirs; 00118 if(dir->getSubIFDs(subdirs)) { 00119 Trace(DEBUG1) << "Iterating subdirs\n"; 00120 std::vector<IFDDir::Ref>::iterator iter2; 00121 for(iter2 = subdirs.begin(); iter2 != subdirs.end(); 00122 ++iter2) 00123 { 00124 IFDDir::Ref & dir2 = *iter2; 00125 dir2->load(); 00126 ret = _locateThumbnail(dir2, list); 00127 if (ret == OR_ERROR_NONE) 00128 { 00129 Trace(DEBUG1) << "Found " << list.back() << " pixels\n"; 00130 } 00131 } 00132 } 00133 } 00134 if (list.size() <= 0) { 00135 err = OR_ERROR_NOT_FOUND; 00136 } 00137 return err; 00138 } 00139 00140 00141 ::or_error IFDFile::_locateThumbnail(const IFDDir::Ref & dir, 00142 std::vector<uint32_t> &list) 00143 { 00144 ::or_error ret = OR_ERROR_NOT_FOUND; 00145 bool got_it; 00146 uint32_t x = 0; 00147 uint32_t y = 0; 00148 ::or_data_type _type = OR_DATA_TYPE_NONE; 00149 uint32_t subtype = 0; 00150 00151 Trace(DEBUG1) << "_locateThumbnail\n"; 00152 00153 got_it = dir->getValue(IFD::EXIF_TAG_NEW_SUBFILE_TYPE, subtype); 00154 Trace(DEBUG1) << "subtype " << subtype << "\n"; 00155 if(!got_it) { 00156 if(!m_cfaIfd) { 00157 m_cfaIfd = _locateCfaIfd(); 00158 } 00159 if(m_cfaIfd == dir) { 00160 return OR_ERROR_NOT_FOUND; 00161 } 00162 else { 00163 subtype = 1; 00164 } 00165 } 00166 if (subtype == 1) { 00167 00168 uint16_t photom_int = 0; 00169 got_it = dir->getValue(IFD::EXIF_TAG_PHOTOMETRIC_INTERPRETATION, 00170 photom_int); 00171 00172 if (got_it) { 00173 Trace(DEBUG1) << "photometric int " << photom_int << "\n"; 00174 } 00175 // photometric interpretation is RGB by default 00176 else { 00177 photom_int = 2; 00178 Trace(DEBUG1) << "assume photometric int is RGB\n"; 00179 } 00180 00181 got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_WIDTH, x); 00182 got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_LENGTH, y); 00183 00184 uint16_t compression = 0; 00185 got_it = dir->getValue(IFD::EXIF_TAG_COMPRESSION, compression); 00186 00187 uint32_t offset = 0; 00188 got_it = dir->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset); 00189 if (!got_it || (compression == 6) || (compression == 7)) { 00190 if(!got_it) { 00191 got_it = dir->getValue(IFD::EXIF_TAG_JPEG_INTERCHANGE_FORMAT, 00192 offset); 00193 } 00194 if (got_it) { 00195 // workaround for CR2 files where 8RGB data is marked 00196 // as JPEG. Check the real data size. 00197 uint32_t byte_count = 0; 00198 if(x && y && dir->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_count)) { 00199 if(byte_count >= (x * y * 3)) { 00200 _type = OR_DATA_TYPE_PIXMAP_8RGB; 00201 } 00202 else { 00203 _type = OR_DATA_TYPE_JPEG; 00204 } 00205 } 00206 else { 00207 _type = OR_DATA_TYPE_JPEG; 00208 Trace(DEBUG1) << "looking for JPEG at " << offset << "\n"; 00209 if (x == 0 || y == 0) { 00210 scoped_ptr<IO::StreamClone> s(new IO::StreamClone(m_io, offset)); 00211 scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0)); 00212 if (jfif->getDimensions(x,y)) { 00213 Trace(DEBUG1) << "JPEG dimensions x=" << x 00214 << " y=" << y << "\n"; 00215 } 00216 else { 00217 _type = OR_DATA_TYPE_NONE; 00218 Trace(WARNING) << "Couldn't get JPEG " 00219 "dimensions.\n"; 00220 } 00221 } 00222 else { 00223 Trace(DEBUG1) << "JPEG (supposed) dimensions x=" << x 00224 << " y=" << y << "\n"; 00225 } 00226 } 00227 00228 } 00229 } 00230 else if (photom_int == 6) { 00231 Trace(WARNING) << "Unsupported YCbCr photometric " 00232 "interpretation in non JPEG.\n"; 00233 ret = OR_ERROR_INVALID_FORMAT; 00234 } 00235 else { 00236 Trace(DEBUG1) << "found strip offsets\n"; 00237 if (x != 0 && y != 0) { 00238 _type = OR_DATA_TYPE_PIXMAP_8RGB; 00239 } 00240 } 00241 if(_type != OR_DATA_TYPE_NONE) { 00242 uint32_t dim = std::max(x, y); 00243 m_thumbLocations[dim] = IFDThumbDesc(x, y, _type, dir); 00244 list.push_back(dim); 00245 ret = OR_ERROR_NONE; 00246 } 00247 } 00248 00249 return ret; 00250 } 00251 00252 00253 ::or_error IFDFile::_getThumbnail(uint32_t size, Thumbnail & thumbnail) 00254 { 00255 ::or_error ret = OR_ERROR_NOT_FOUND; 00256 ThumbLocations::iterator iter = m_thumbLocations.find(size); 00257 if(iter != m_thumbLocations.end()) 00258 { 00259 bool got_it; 00260 00261 IFDThumbDesc & desc = iter->second; 00262 thumbnail.setDataType(desc.type); 00263 uint32_t byte_length= 0; 00264 uint32_t offset = 0; 00265 uint32_t x = desc.x; 00266 uint32_t y = desc.y; 00267 00268 switch(desc.type) 00269 { 00270 case OR_DATA_TYPE_JPEG: 00271 got_it = desc.ifddir 00272 ->getValue(IFD::EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, 00273 byte_length); 00274 if(got_it) { 00275 got_it = desc.ifddir 00276 ->getValue(IFD::EXIF_TAG_JPEG_INTERCHANGE_FORMAT, 00277 offset); 00278 } 00279 else { 00280 // some case it is STRIP_OFFSETS for JPEG 00281 got_it = desc.ifddir 00282 ->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset); 00283 got_it = desc.ifddir 00284 ->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length); 00285 } 00286 break; 00287 case OR_DATA_TYPE_PIXMAP_8RGB: 00288 got_it = desc.ifddir 00289 ->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset); 00290 got_it = desc.ifddir 00291 ->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length); 00292 00293 got_it = desc.ifddir 00294 ->getIntegerValue(IFD::EXIF_TAG_IMAGE_WIDTH, x); 00295 got_it = desc.ifddir 00296 ->getIntegerValue(IFD::EXIF_TAG_IMAGE_LENGTH, y); 00297 break; 00298 default: 00299 break; 00300 } 00301 if (byte_length != 0) { 00302 void *p = thumbnail.allocData(byte_length); 00303 size_t real_size = m_container->fetchData(p, offset, 00304 byte_length); 00305 if (real_size < byte_length) { 00306 Trace(WARNING) << "Size mismatch for data: ignoring.\n"; 00307 } 00308 00309 thumbnail.setDimensions(x, y); 00310 ret = OR_ERROR_NONE; 00311 } 00312 } 00313 00314 return ret; 00315 } 00316 00317 00318 MetaValue *IFDFile::_getMetaValue(int32_t meta_index) 00319 { 00320 MetaValue * val = NULL; 00321 IFDDir::Ref ifd; 00322 if(META_INDEX_MASKOUT(meta_index) == META_NS_TIFF) { 00323 if(!m_mainIfd) { 00324 m_mainIfd = _locateMainIfd(); 00325 } 00326 ifd = m_mainIfd; 00327 } 00328 else if(META_INDEX_MASKOUT(meta_index) == META_NS_EXIF) { 00329 if(!m_exifIfd) { 00330 m_exifIfd = _locateExifIfd(); 00331 } 00332 ifd = m_exifIfd; 00333 } 00334 else { 00335 Trace(ERROR) << "Unknown Meta Namespace\n"; 00336 } 00337 if(ifd) { 00338 Trace(DEBUG1) << "Meta value for " 00339 << META_NS_MASKOUT(meta_index) << "\n"; 00340 00341 IFDEntry::Ref e = ifd->getEntry(META_NS_MASKOUT(meta_index)); 00342 if(e) { 00343 val = new MetaValue(e); 00344 } 00345 } 00346 return val; 00347 } 00348 00349 00350 namespace { 00351 00352 RawData::CfaPattern 00353 _convertArrayToCfaPattern(const std::vector<uint8_t> &cfaPattern) 00354 { 00355 RawData::CfaPattern cfa_pattern = OR_CFA_PATTERN_NON_RGB22; 00356 if(cfaPattern.size() != 4) { 00357 Trace(WARNING) << "Unsupported bayer pattern\n"; 00358 } 00359 else { 00360 Trace(DEBUG2) << "patter is = " << cfaPattern[0] << ", " 00361 << cfaPattern[1] << ", " << cfaPattern[2] 00362 << ", " << cfaPattern[3] << "\n"; 00363 switch(cfaPattern[0]) { 00364 case IFD::CFA_RED: 00365 switch(cfaPattern[1]) { 00366 case IFD::CFA_GREEN: 00367 if((cfaPattern[2] == IFD::CFA_GREEN) 00368 && (cfaPattern[3] == IFD::CFA_BLUE)) 00369 { 00370 cfa_pattern = OR_CFA_PATTERN_RGGB; 00371 } 00372 break; 00373 } 00374 break; 00375 case IFD::CFA_GREEN: 00376 switch(cfaPattern[1]) { 00377 case IFD::CFA_RED: 00378 if((cfaPattern[2] == 2) 00379 && (cfaPattern[3] == IFD::CFA_GREEN)) 00380 { 00381 cfa_pattern = OR_CFA_PATTERN_GRBG; 00382 } 00383 break; 00384 case 2: 00385 if((cfaPattern[2] == IFD::CFA_RED) 00386 && (cfaPattern[3] == IFD::CFA_GREEN)) 00387 { 00388 cfa_pattern = OR_CFA_PATTERN_GBRG; 00389 } 00390 break; 00391 } 00392 break; 00393 case IFD::CFA_BLUE: 00394 switch(cfaPattern[1]) { 00395 case IFD::CFA_GREEN: 00396 if((cfaPattern[2] == IFD::CFA_GREEN) 00397 && (cfaPattern[3] == IFD::CFA_RED)) 00398 { 00399 cfa_pattern = OR_CFA_PATTERN_BGGR; 00400 } 00401 break; 00402 } 00403 break; 00404 } 00405 // 00406 } 00407 return cfa_pattern; 00408 } 00409 00410 RawData::CfaPattern _convertNewCfaPattern(const IFDEntry::Ref & e) 00411 { 00412 RawData::CfaPattern cfa_pattern = OR_CFA_PATTERN_NONE; 00413 if(!e || (e->count() < 4)) { 00414 return cfa_pattern; 00415 } 00416 00417 uint16_t hdim = IFDTypeTrait<uint16_t>::get(*e, 0, true); 00418 uint16_t vdim = IFDTypeTrait<uint16_t>::get(*e, 1, true); 00419 if(hdim != 2 && vdim != 2) { 00420 cfa_pattern = OR_CFA_PATTERN_NON_RGB22; 00421 } 00422 else { 00423 std::vector<uint8_t> cfaPattern; 00424 cfaPattern.push_back(IFDTypeTrait<uint8_t>::get(*e, 4, true)); 00425 cfaPattern.push_back(IFDTypeTrait<uint8_t>::get(*e, 5, true)); 00426 cfaPattern.push_back(IFDTypeTrait<uint8_t>::get(*e, 6, true)); 00427 cfaPattern.push_back(IFDTypeTrait<uint8_t>::get(*e, 7, true)); 00428 cfa_pattern = _convertArrayToCfaPattern(cfaPattern); 00429 } 00430 return cfa_pattern; 00431 } 00432 00433 00435 RawData::CfaPattern _convertCfaPattern(const IFDEntry::Ref & e) 00436 { 00437 std::vector<uint8_t> cfaPattern; 00438 RawData::CfaPattern cfa_pattern = OR_CFA_PATTERN_NONE; 00439 00440 e->getArray(cfaPattern); 00441 if(!cfaPattern.empty()) { 00442 cfa_pattern = _convertArrayToCfaPattern(cfaPattern); 00443 } 00444 return cfa_pattern; 00445 } 00446 00452 static RawData::CfaPattern _getCfaPattern(const IFDDir::Ref & dir) 00453 { 00454 Trace(DEBUG1) << __FUNCTION__ << "\n"; 00455 RawData::CfaPattern cfa_pattern = OR_CFA_PATTERN_NONE; 00456 try { 00457 IFDEntry::Ref e = dir->getEntry(IFD::EXIF_TAG_CFA_PATTERN); 00458 if(e) { 00459 cfa_pattern = _convertCfaPattern(e); 00460 } 00461 else { 00462 e = dir->getEntry(IFD::EXIF_TAG_NEW_CFA_PATTERN); 00463 if(e) { 00464 cfa_pattern = _convertNewCfaPattern(e); 00465 } 00466 } 00467 } 00468 catch(...) 00469 { 00470 Trace(ERROR) << "Exception in _getCfaPattern().\n"; 00471 } 00472 return cfa_pattern; 00473 } 00474 00475 } // end anon namespace 00476 00477 ::or_error IFDFile::_getRawDataFromDir(RawData & data, IFDDir::Ref & dir) 00478 { 00479 ::or_error ret = OR_ERROR_NONE; 00480 00481 uint16_t bpc = 0; 00482 uint32_t offset = 0; 00483 uint32_t byte_length = 0; 00484 bool got_it; 00485 uint32_t x, y; 00486 x = 0; 00487 y = 0; 00488 00489 if(!dir) { 00490 Trace(ERROR) << "dir is NULL\n"; 00491 return OR_ERROR_NOT_FOUND; 00492 } 00493 got_it = dir->getValue(IFD::EXIF_TAG_BITS_PER_SAMPLE, bpc); 00494 if(!got_it) { 00495 Trace(ERROR) << "unable to guess Bits per sample\n"; 00496 } 00497 00498 got_it = dir->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset); 00499 if(got_it) { 00500 IFDEntry::Ref e = dir->getEntry(IFD::EXIF_TAG_STRIP_BYTE_COUNTS); 00501 if(e) { 00502 std::vector<uint32_t> counts; 00503 e->getArray(counts); 00504 Trace(DEBUG1) << "counting tiles\n"; 00505 byte_length = std::accumulate(counts.begin(), counts.end(), 0); 00506 } 00507 else { 00508 Trace(DEBUG1) << "byte len not found\n"; 00509 return OR_ERROR_NOT_FOUND; 00510 } 00511 } 00512 else { 00513 // the tile are individual JPEGS.... 00514 // TODO extract all of them. 00515 IFDEntry::Ref e = dir->getEntry(IFD::TIFF_TAG_TILE_OFFSETS); 00516 if(e) { 00517 std::vector<uint32_t> offsets; 00518 e->getArray(offsets); 00519 if(offsets.size() > 1) { 00520 offset = offsets[0]; 00521 } 00522 else { 00523 Trace(DEBUG1) << "tile offsets empty\n"; 00524 return OR_ERROR_NOT_FOUND; 00525 } 00526 } 00527 else { 00528 Trace(DEBUG1) << "tile offsets not found\n"; 00529 return OR_ERROR_NOT_FOUND; 00530 } 00531 e = dir->getEntry(IFD::TIFF_TAG_TILE_BYTECOUNTS); 00532 if(e) { 00533 std::vector<uint32_t> counts; 00534 e->getArray(counts); 00535 Trace(DEBUG1) << "counting tiles\n"; 00536 byte_length = std::accumulate(counts.begin(), counts.end(), 0); 00537 } 00538 else { 00539 Trace(DEBUG1) << "tile byte counts not found\n"; 00540 return OR_ERROR_NOT_FOUND; 00541 } 00542 } 00543 got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_WIDTH, x); 00544 if(!got_it) { 00545 Trace(DEBUG1) << "X not found\n"; 00546 return OR_ERROR_NOT_FOUND; 00547 } 00548 got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_LENGTH, y); 00549 if(!got_it) { 00550 Trace(DEBUG1) << "Y not found\n"; 00551 return OR_ERROR_NOT_FOUND; 00552 } 00553 00554 uint32_t compression = 0; 00555 got_it = dir->getIntegerValue(IFD::EXIF_TAG_COMPRESSION, compression); 00556 if(!got_it) 00557 { 00558 Trace(DEBUG1) << "Compression type not found\n"; 00559 } 00560 BitmapData::DataType data_type = OR_DATA_TYPE_NONE; 00561 00562 switch(compression) 00563 { 00564 case IFD::COMPRESS_NONE: 00565 data_type = OR_DATA_TYPE_CFA; 00566 break; 00567 case IFD::COMPRESS_NIKON_PACK: 00568 data_type = OR_DATA_TYPE_CFA; 00569 break; 00570 case IFD::COMPRESS_NIKON_QUANTIZED: 00571 // must check whether it is really compressed 00572 // only for D100 00573 if( !NEFFile::isCompressed(*m_container, offset) ) { 00574 compression = IFD::COMPRESS_NIKON_PACK; 00575 data_type = OR_DATA_TYPE_CFA; 00576 // this is a hack. we should check if 00577 // we have a D100 instead, but that case is already 00578 // a D100 corner case. WILL BREAK on compressed files. 00579 // according to dcraw we must increase the size by 6. 00580 x += 6; 00581 break; 00582 } 00583 default: 00584 data_type = OR_DATA_TYPE_COMPRESSED_CFA; 00585 break; 00586 } 00587 00588 Trace(DEBUG1) << "RAW Compression is " << compression << "\n"; 00589 00590 RawData::CfaPattern cfa_pattern = _getCfaPattern(dir); 00591 if(cfa_pattern == OR_CFA_PATTERN_NONE) { 00592 // some file have it in the exif IFD instead. 00593 if(!m_exifIfd) { 00594 m_exifIfd = _locateExifIfd(); 00595 } 00596 cfa_pattern = _getCfaPattern(m_exifIfd); 00597 } 00598 00599 00600 if((bpc == 12 || bpc == 14) && (compression == 1) 00601 && (byte_length == (x * y * 2))) 00602 { 00603 Trace(DEBUG1) << "setting bpc from " << bpc 00604 << " to 16\n"; 00605 bpc = 16; 00606 } 00607 if((bpc == 16) || (data_type == OR_DATA_TYPE_COMPRESSED_CFA)) { 00608 void *p = data.allocData(byte_length); 00609 size_t real_size = m_container->fetchData(p, offset, 00610 byte_length); 00611 if (real_size < byte_length) { 00612 Trace(WARNING) << "Size mismatch for data: ignoring.\n"; 00613 } 00614 } 00615 else if((bpc == 12) || (bpc == 8)) { 00616 size_t fetched = 0; 00617 Unpack unpack(x, compression); 00618 const size_t blocksize = (bpc == 8 ? x : unpack.block_size()); 00619 Trace(DEBUG1) << "Block size = " << blocksize << "\n"; 00620 Trace(DEBUG1) << "dimensions (x, y) " << x << ", " 00621 << y << "\n"; 00622 boost::scoped_array<uint8_t> block(new uint8_t[blocksize]); 00623 uint8_t * outdata = (uint8_t*)data.allocData(x * y * 2); 00624 size_t got; 00625 Trace(DEBUG1) << "offset of RAW data = " << offset << "\n"; 00626 do { 00627 got = m_container->fetchData (block.get(), 00628 offset, blocksize); 00629 fetched += got; 00630 offset += got; 00631 if(got) { 00632 if(bpc == 12) { 00633 size_t out = unpack.unpack_be12to16(outdata, 00634 block.get(), 00635 got); 00636 outdata += out; 00637 } 00638 else { 00639 // outdata point to uint16_t 00640 std::copy(block.get(), block.get()+got, 00641 (uint16_t*)outdata); 00642 outdata += (got << 1); 00643 } 00644 } 00645 } while((got != 0) && (fetched < byte_length)); 00646 } 00647 else { 00648 Trace(ERROR) << "Unsupported bpc " << bpc << "\n"; 00649 return OR_ERROR_INVALID_FORMAT; 00650 } 00651 data.setCfaPattern(cfa_pattern); 00652 data.setDataType(data_type); 00653 data.setCompression(data_type == OR_DATA_TYPE_COMPRESSED_CFA 00654 ? compression : 1); 00655 if((data_type == OR_DATA_TYPE_CFA) && (data.max() == 0)) { 00656 data.setMax((1 << bpc) - 1); 00657 } 00658 data.setDimensions(x, y); 00659 00660 return ret; 00661 } 00662 00663 } 00664 } 00665 00666 /* 00667 Local Variables: 00668 mode:c++ 00669 c-file-style:"stroustrup" 00670 c-file-offsets:((innamespace . 0)) 00671 indent-tabs-mode:nil 00672 fill-column:80 00673 End: 00674 */