void dng_memory_stream::DoRead (void *data, uint32 count, uint64 offset) { if (offset + count > fMemoryStreamLength) { ThrowEndOfFile (); } uint64 baseOffset = offset; while (count) { uint32 pageIndex = (uint32) (offset / fPageSize); uint32 pageOffset = (uint32) (offset % fPageSize); uint32 blockCount = Min_uint32 (fPageSize - pageOffset, count); const uint8 *sPtr = fPageList [pageIndex]->Buffer_uint8 () + pageOffset; uint8 *dPtr = ((uint8 *) data) + (uint32) (offset - baseOffset); DoCopyBytes (sPtr, dPtr, blockCount); offset += blockCount; count -= blockCount; } }
void dng_image::Put (const dng_pixel_buffer &buffer) { // Move the overlapping pixels. dng_rect overlap = buffer.fArea & fBounds; if (overlap.NotEmpty ()) { dng_pixel_buffer temp (buffer); temp.fArea = overlap; temp.fData = (void *) buffer.ConstPixel (overlap.t, overlap.l, buffer.fPlane); // Move the overlapping planes. if (temp.fPlane < Planes ()) { temp.fPlanes = Min_uint32 (temp.fPlanes, Planes () - temp.fPlane); DoPut (temp); } } }
void dng_memory_stream::DoWrite (const void *data, uint32 count, uint64 offset) { DoSetLength (Max_uint64 (fMemoryStreamLength, offset + count)); uint64 baseOffset = offset; while (count) { uint32 pageIndex = (uint32) (offset / fPageSize); uint32 pageOffset = (uint32) (offset % fPageSize); uint32 blockCount = Min_uint32 (fPageSize - pageOffset, count); const uint8 *sPtr = ((const uint8 *) data) + (uint32) (offset - baseOffset); uint8 *dPtr = fPageList [pageIndex]->Buffer_uint8 () + pageOffset; DoCopyBytes (sPtr, dPtr, blockCount); offset += blockCount; count -= blockCount; } }
void dng_opcode_GainMap::ProcessArea (dng_negative & /* negative */, uint32 /* threadIndex */, dng_pixel_buffer &buffer, const dng_rect &dstArea, const dng_rect &imageBounds) { dng_rect overlap = fAreaSpec.Overlap (dstArea); if (overlap.NotEmpty ()) { uint32 cols = overlap.W (); uint32 colPitch = fAreaSpec.ColPitch (); for (uint32 plane = fAreaSpec.Plane (); plane < fAreaSpec.Plane () + fAreaSpec.Planes () && plane < buffer.Planes (); plane++) { uint32 mapPlane = Min_uint32 (plane, fGainMap->Planes () - 1); for (int32 row = overlap.t; row < overlap.b; row += fAreaSpec.RowPitch ()) { real32 *dPtr = buffer.DirtyPixel_real32 (row, overlap.l, plane); dng_gain_map_interpolator interp (*fGainMap, imageBounds, row, overlap.l, mapPlane); for (uint32 col = 0; col < cols; col += colPitch) { real32 gain = interp.Interpolate (); dPtr [col] = Min_real32 (dPtr [col] * gain, 1.0f); for (uint32 j = 0; j < colPitch; j++) { interp.Increment (); } } } } } }
void dng_info::ParseDNGPrivateData (dng_host &host, dng_stream &stream) { if (fShared->fDNGPrivateDataCount < 2) { return; } // DNG private data should always start with a null-terminated // company name, to define the format of the private data. dng_string privateName; { char buffer [64]; stream.SetReadPosition (fShared->fDNGPrivateDataOffset); uint32 readLength = Min_uint32 (fShared->fDNGPrivateDataCount, sizeof (buffer) - 1); stream.Get (buffer, readLength); buffer [readLength] = 0; privateName.Set (buffer); } // Pentax is storing their MakerNote in the DNGPrivateData data. if (privateName.StartsWith ("PENTAX" ) || privateName.StartsWith ("SAMSUNG")) { #if qDNGValidate if (gVerbose) { printf ("Parsing Pentax/Samsung DNGPrivateData\n\n"); } #endif stream.SetReadPosition (fShared->fDNGPrivateDataOffset + 8); bool bigEndian = stream.BigEndian (); uint16 endianMark = stream.Get_uint16 (); if (endianMark == byteOrderMM) { bigEndian = true; } else if (endianMark == byteOrderII) { bigEndian = false; } TempBigEndian temp_endian (stream, bigEndian); ParseMakerNoteIFD (host, stream, fShared->fDNGPrivateDataCount - 10, fShared->fDNGPrivateDataOffset + 10, fShared->fDNGPrivateDataOffset, fShared->fDNGPrivateDataOffset, fShared->fDNGPrivateDataOffset + fShared->fDNGPrivateDataCount, tcPentaxMakerNote); return; } // Stop parsing if this is not an Adobe format block. if (!privateName.Matches ("Adobe")) { return; } TempBigEndian temp_order (stream); uint32 section_offset = 6; while (section_offset + 8 < fShared->fDNGPrivateDataCount) { stream.SetReadPosition (fShared->fDNGPrivateDataOffset + section_offset); uint32 section_key = stream.Get_uint32 (); uint32 section_count = stream.Get_uint32 (); if (section_key == DNG_CHAR4 ('M','a','k','N') && section_count > 6) { #if qDNGValidate if (gVerbose) { printf ("Found MakerNote inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint64 old_offset = stream.Get_uint32 (); uint32 tempSize = section_count - 6; AutoPtr<dng_memory_block> tempBlock (host.Allocate (tempSize)); uint64 positionInOriginalFile = stream.PositionInOriginalFile(); stream.Get (tempBlock->Buffer (), tempSize); dng_stream tempStream (tempBlock->Buffer (), tempSize, positionInOriginalFile); tempStream.SetBigEndian (order_mark == byteOrderMM); ParseMakerNote (host, tempStream, tempSize, 0, 0 - old_offset, 0, tempSize); } else if (section_key == DNG_CHAR4 ('S','R','2',' ') && section_count > 6) { #if qDNGValidate if (gVerbose) { printf ("Found Sony private data inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint64 old_offset = stream.Get_uint32 (); uint64 new_offset = fShared->fDNGPrivateDataOffset + section_offset + 14; TempBigEndian sr2_order (stream, order_mark == byteOrderMM); ParseSonyPrivateData (host, stream, section_count - 6, old_offset, new_offset); } else if (section_key == DNG_CHAR4 ('R','A','F',' ') && section_count > 4) { #if qDNGValidate if (gVerbose) { printf ("Found Fuji RAF tags inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint32 tagCount = stream.Get_uint32 (); uint64 tagOffset = stream.Position (); if (tagCount) { TempBigEndian raf_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcFujiRAF, tcFujiHeader, ttUndefined, tagCount, tagOffset, 0); stream.SetReadPosition (tagOffset + tagCount); } tagCount = stream.Get_uint32 (); tagOffset = stream.Position (); if (tagCount) { TempBigEndian raf_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcFujiRAF, tcFujiRawInfo1, ttUndefined, tagCount, tagOffset, 0); stream.SetReadPosition (tagOffset + tagCount); } tagCount = stream.Get_uint32 (); tagOffset = stream.Position (); if (tagCount) { TempBigEndian raf_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcFujiRAF, tcFujiRawInfo2, ttUndefined, tagCount, tagOffset, 0); stream.SetReadPosition (tagOffset + tagCount); } } else if (section_key == DNG_CHAR4 ('C','n','t','x') && section_count > 4) { #if qDNGValidate if (gVerbose) { printf ("Found Contax Raw header inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint32 tagCount = stream.Get_uint32 (); uint64 tagOffset = stream.Position (); if (tagCount) { TempBigEndian contax_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcContaxRAW, tcContaxHeader, ttUndefined, tagCount, tagOffset, 0); } } else if (section_key == DNG_CHAR4 ('C','R','W',' ') && section_count > 4) { #if qDNGValidate if (gVerbose) { printf ("Found Canon CRW tags inside DNGPrivateData\n\n"); } #endif uint16 order_mark = stream.Get_uint16 (); uint32 entries = stream.Get_uint16 (); uint64 crwTagStart = stream.Position (); for (uint32 parsePass = 1; parsePass <= 2; parsePass++) { stream.SetReadPosition (crwTagStart); for (uint32 index = 0; index < entries; index++) { uint32 tagCode = stream.Get_uint16 (); uint32 tagCount = stream.Get_uint32 (); uint64 tagOffset = stream.Position (); // We need to grab the model id tag first, and then all the // other tags. if ((parsePass == 1) == (tagCode == 0x5834)) { TempBigEndian tag_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, tcCanonCRW, tagCode, ttUndefined, tagCount, tagOffset, 0); } stream.SetReadPosition (tagOffset + tagCount); } } } else if (section_count > 4) { uint32 parentCode = 0; bool code32 = false; bool hasType = true; switch (section_key) { case DNG_CHAR4 ('M','R','W',' '): { parentCode = tcMinoltaMRW; code32 = true; hasType = false; break; } case DNG_CHAR4 ('P','a','n','o'): { parentCode = tcPanasonicRAW; break; } case DNG_CHAR4 ('L','e','a','f'): { parentCode = tcLeafMOS; break; } case DNG_CHAR4 ('K','o','d','a'): { parentCode = tcKodakDCRPrivateIFD; break; } case DNG_CHAR4 ('K','D','C',' '): { parentCode = tcKodakKDCPrivateIFD; break; } default: break; } if (parentCode) { #if qDNGValidate if (gVerbose) { printf ("Found %s tags inside DNGPrivateData\n\n", LookupParentCode (parentCode)); } #endif uint16 order_mark = stream.Get_uint16 (); uint32 entries = stream.Get_uint16 (); for (uint32 index = 0; index < entries; index++) { uint32 tagCode = code32 ? stream.Get_uint32 () : stream.Get_uint16 (); uint32 tagType = hasType ? stream.Get_uint16 () : ttUndefined; uint32 tagCount = stream.Get_uint32 (); uint32 tagSize = tagCount * TagTypeSize (tagType); uint64 tagOffset = stream.Position (); TempBigEndian tag_order (stream, order_mark == byteOrderMM); ParseTag (host, stream, fExif.Get (), fShared.Get (), NULL, parentCode, tagCode, tagType, tagCount, tagOffset, 0); stream.SetReadPosition (tagOffset + tagSize); } } } section_offset += 8 + section_count; if (section_offset & 1) { section_offset++; } } }
void dng_host::ValidateSizes () { // The maximum size limits the other two sizes. if (MaximumSize ()) { SetMinimumSize (Min_uint32 (MinimumSize (), MaximumSize ())); SetPreferredSize (Min_uint32 (PreferredSize (), MaximumSize ())); } // If we have a preferred size, it limits the minimum size. if (PreferredSize ()) { SetMinimumSize (Min_uint32 (MinimumSize (), PreferredSize ())); } // Else find default value for preferred size. else { // If preferred size is zero, then we want the maximim // size image. if (MaximumSize ()) { SetPreferredSize (MaximumSize ()); } } // If we don't have a minimum size, find default. if (!MinimumSize ()) { // A common size for embedded thumbnails is 120 by 160 pixels, // So allow 120 by 160 pixels to be used for thumbnails when the // preferred size is 256 pixel. if (PreferredSize () >= 160 && PreferredSize () <= 256) { SetMinimumSize (160); } // Many sensors are near a multiple of 1024 pixels in size, but after // the default crop, they are a just under. We can get an extra factor // of size reduction if we allow a slight undershoot in the final size // when computing large previews. else if (PreferredSize () >= 490 && PreferredSize () <= 512) { SetMinimumSize (490); } else if (PreferredSize () >= 980 && PreferredSize () <= 1024) { SetMinimumSize (980); } else if (PreferredSize () >= 1470 && PreferredSize () <= 1536) { SetMinimumSize (1470); } else if (PreferredSize () >= 1960 && PreferredSize () <= 2048) { SetMinimumSize (1960); } // Else minimum size is same as preferred size. else { SetMinimumSize (PreferredSize ()); } } }
dng_point dng_area_task::FindTileSize (const dng_rect &area) const { dng_rect repeatingTile1 = RepeatingTile1 (); dng_rect repeatingTile2 = RepeatingTile2 (); dng_rect repeatingTile3 = RepeatingTile3 (); if (repeatingTile1.IsEmpty ()) { repeatingTile1 = area; } if (repeatingTile2.IsEmpty ()) { repeatingTile2 = area; } if (repeatingTile3.IsEmpty ()) { repeatingTile3 = area; } uint32 repeatV = Min_uint32 (Min_uint32 (repeatingTile1.H (), repeatingTile2.H ()), repeatingTile3.H ()); uint32 repeatH = Min_uint32 (Min_uint32 (repeatingTile1.W (), repeatingTile2.W ()), repeatingTile3.W ()); dng_point maxTileSize = MaxTileSize (); dng_point tileSize (maxTileSize); tileSize.v = Min_int32 (tileSize.v, repeatV); tileSize.h = Min_int32 (tileSize.h, repeatH); uint32 countV = (repeatV + tileSize.v - 1) / tileSize.v; uint32 countH = (repeatH + tileSize.h - 1) / tileSize.h; tileSize.v = (repeatV + countV - 1) / countV; tileSize.h = (repeatH + countH - 1) / countH; dng_point unitCell = UnitCell (); tileSize.v = ((tileSize.v + unitCell.v - 1) / unitCell.v) * unitCell.v; tileSize.h = ((tileSize.h + unitCell.h - 1) / unitCell.h) * unitCell.h; if (tileSize.v > maxTileSize.v) { tileSize.v = (maxTileSize.v / unitCell.v) * unitCell.v; } if (tileSize.h > maxTileSize.h) { tileSize.h = (maxTileSize.h / unitCell.h) * unitCell.h; } return tileSize; }