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