53 static const std::array<char, 16> magic = {{
'F',
'U',
'J',
'I',
'F',
'I',
'L',
54 'M',
'C',
'C',
'D',
'-',
'R',
'A',
57 return 0 == memcmp(data.
begin(), magic.data(), magic.size());
61 [[maybe_unused]]
Buffer file) {
62 const auto id = rootIFD->
getID();
63 const std::string& make =
id.
make;
67 return make ==
"FUJIFILM";
83 ThrowRDE(
"Unable to locate image size");
86 if (width == 0 || height == 0 || width > 11808 || height > 8754)
87 ThrowRDE(
"Unexpected image dimensions found: (%u; %u)", width, height);
104 mRaw->metadata.mode =
"compressed";
128 if (8UL * counts->
getU32() >= 2UL * 16UL * width * height) {
131 }
else if (8UL * counts->
getU32() >= 2UL * 14UL * width * height) {
134 }
else if (8UL * counts->
getU32() >= 2UL * 12UL * width * height) {
137 }
else if (8UL * counts->
getU32() >= 16UL * width * height) {
139 double_width =
false;
140 }
else if (8UL * counts->
getU32() >= 14UL * width * height) {
142 double_width =
false;
143 }
else if (8UL * counts->
getU32() >= 12UL * width * height) {
145 double_width =
false;
147 ThrowRDE(
"Can not detect bitdepth. StripByteCounts = %u, width = %u, "
149 counts->
getU32(), width, height);
152 double_width =
hints.contains(
"double_width_unpacked");
153 const uint32_t real_width = double_width ? 2U * width : width;
162 u.readUncompressedRaw();
170 u.readUncompressedRaw();
173 if (
hints.contains(
"jpeg32_bitorder")) {
177 u.readUncompressedRaw();
182 u.readUncompressedRaw();
191 ThrowRDE(
"Unknown camera. Will not guess.");
194 mRaw->metadata.mode =
"compressed";
199 ThrowRDE(
"Couldn't find camera %s %s",
id.make.c_str(),
id.model.c_str());
215 new_size = vendor_crop.
dim;
216 crop_offset = vendor_crop.
pos;
218 bool double_width =
hints.contains(
"double_width_unpacked");
220 if (new_size.
x <= 0) {
222 mRaw->dim.x / (double_width ? 2 : 1) - crop_offset.
x + new_size.
x;
224 new_size.
x /= (double_width ? 2 : 1);
227 new_size.
y =
mRaw->dim.y - crop_offset.
y + new_size.
y;
230 bool rotate =
hints.contains(
"fuji_rotate");
239 rotatedsize = new_size.
y + new_size.
x / 2;
240 rotationPos = new_size.
x / 2 - 1;
242 rotatedsize = new_size.
x + new_size.
y / 2;
243 rotationPos = new_size.
x - 1;
246 iPoint2D final_size(rotatedsize, rotatedsize - 1);
253 auto srcImg =
mRaw->getU16DataAsUncroppedArray2DRef();
256 for (
int y = 0;
y < new_size.
y;
y++) {
257 for (
int x = 0;
x < new_size.
x;
x++) {
261 h = rotatedsize - (new_size.
y + 1 -
y + (
x >> 1));
262 w = ((
x + 1) >> 1) +
y;
264 h = new_size.
x - 1 -
x + (
y >> 1);
265 w = ((
y + 1) >> 1) +
x;
267 if (h < rotated->
dim.y && w < rotated->
dim.x)
268 dstImg(h, w) = srcImg(crop_offset.
y +
y, crop_offset.
x +
x);
270 ThrowRDE(
"Trying to write out of bounds");
283 mRaw->metadata.isoSpeed = iso;
291 ThrowRDE(
"Unexpected bit depth: %u", bps);
312 if (sep_black->
count == 4) {
313 mRaw->blackLevelSeparate =
315 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
316 for (
int k = 0; k < 4; k++)
317 blackLevelSeparate1D(k) = sep_black->
getU32(k);
318 }
else if (sep_black->
count == 36) {
319 mRaw->blackLevelSeparate =
321 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
322 for (
int& k : blackLevelSeparate1D)
325 for (
int y = 0;
y < 6;
y++) {
326 for (
int x = 0;
x < 6;
x++)
327 blackLevelSeparate1D((2 * (
y % 2)) + (
x % 2)) +=
331 for (
int& k : blackLevelSeparate1D)
337 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
338 for (
int b : blackLevelSeparate1D)
340 mRaw->blackLevel = (sum + 2) >> 2;
345 mRaw->blackLevel = sensor->mBlackLevel;
346 mRaw->whitePoint = sensor->mWhiteLevel;
357 mRaw->metadata.make =
id.make;
358 mRaw->metadata.model =
id.model;
363 if (wb->
count == 3) {
364 std::array<float, 4> wbCoeffs = {};
368 mRaw->metadata.wbCoeffs = wbCoeffs;
372 if (wb->
count == 8) {
373 std::array<float, 4> wbCoeffs = {};
377 mRaw->metadata.wbCoeffs = wbCoeffs;
395 ThrowRDE(
"Unable to locate image size");
398 if (width == 0 || height == 0 || width > 11808 || height > 8754)
399 ThrowRDE(
"Unexpected image dimensions found: (%u; %u)", width, height);
412 return count * 8 / (width * height) < bps;
422 const uint16_t topBorder = pos->getU16(0);
423 const uint16_t leftBorder = pos->getU16(1);
427 return {leftBorder, topBorder, width, height};
429 ThrowRDE(
"Cannot figure out vendor crop. Required entries were not found: "
iPoint2D dim(rawspeed::implicit_cast< int >(ceil(sqSide *sqARatio)), rawspeed::implicit_cast< int >(ceil(sqSide/sqARatio)))
assert(dim.area() >=area)
bool checkCameraSupported(const CameraMetaData *meta, const TiffID &id, const std::string &mode)
TiffRootIFDOwner mRootIFD
Buffer getSubView(size_type offset, size_type size_) const
const uint8_t * begin() const
ByteStream getSubStream(size_type offset, size_type size_) const
std::string canonical_alias
std::string canonical_model
std::string canonical_make
std::vector< BlackArea > blackAreas
const CameraSensorInfo * getSensorInfo(int iso) const
std::vector< NotARational< int > > color_matrix
Endianness getByteOrder() const
static bool isAppropriateDecoder(const TiffRootIFD *rootIFD, Buffer file)
static bool isRAF(Buffer input)
void decodeMetaDataInternal(const CameraMetaData *meta) override
iRectangle2D getDefaultCrop() override
void checkSupportInternal(const CameraMetaData *meta) override
void applyCorrections(const Camera *cam)
RawImage decodeRawInternal() override
bool uncorrectedRawValues
Array2DRef< uint16_t > getU16DataAsUncroppedArray2DRef() noexcept
void clearArea(iRectangle2D area)
static RawImage create(RawImageType type=RawImageType::UINT16)
DataBuffer getRootIfdData() const
float getFloat(uint32_t index=0) const
uint32_t getU32(uint32_t index=0) const
uint16_t getU16(uint32_t index=0) const
uint8_t getByte(uint32_t index=0) const
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Array2DRef(Array1DRef< T > data, int width, int height, int pitch) -> Array2DRef< T >
Endianness getHostEndianness()
@ FUJI_RAWIMAGECROPPEDSIZE
@ FUJI_RAWIMAGEFULLHEIGHT
@ FUJI_RAWIMAGECROPTOPLEFT