blob: d7cb72d5f0f82484c72b0189e8fd841ead69adb1 [file]
/* -*- C++ -*-
* Copyright 2019-2025 LibRaw LLC (info@libraw.org)
*
LibRaw is free software; you can redistribute it and/or modify
it under the terms of the one of two licenses as you choose:
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
(See file LICENSE.LGPL provided in LibRaw distribution archive for details).
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
(See file LICENSE.CDDL provided in LibRaw distribution archive for details).
*/
#include "third_party/libraw/internal/dcraw_defs.h"
void LibRaw::nikon_he_load_raw()
{
if(dng_version)
throw LIBRAW_EXCEPTION_UNSUPPORTED_FORMAT; // Never reached
throw LIBRAW_EXCEPTION_UNSUPPORTED_FORMAT;
}
void LibRaw::packed_tiled_dng_load_raw()
{
ushort *rp;
unsigned row, col;
int ss = shot_select;
shot_select = libraw_internal_data.unpacker_data.dng_frames[LIM(ss, 0, (LIBRAW_IFD_MAXCOUNT * 2 - 1))] & 0xff;
std::vector<ushort> pixel;
try
{
int ntiles = 1 + (raw_width) / tile_width;
if ((unsigned)ntiles * tile_width > raw_width * 2u) throw LIBRAW_EXCEPTION_ALLOC;
pixel.resize(tile_width * ntiles * tiff_samples);
}
catch (...)
{
throw LIBRAW_EXCEPTION_ALLOC; // rethrow
}
try
{
unsigned trow = 0, tcol = 0;
INT64 save;
while (trow < raw_height)
{
checkCancel();
save = ftell(ifp);
if (tile_length < INT_MAX)
fseek(ifp, get4(), SEEK_SET);
for (row = 0; row < tile_length && (row + trow) < raw_height; row++)
{
if (tiff_bps == 16)
read_shorts(pixel.data(), tile_width * tiff_samples);
else
{
getbits(-1);
for (col = 0; col < tile_width * tiff_samples; col++)
pixel[col] = getbits(tiff_bps);
}
for (rp = pixel.data(), col = 0; col < tile_width; col++)
adobe_copy_pixel(trow+row, tcol+col, &rp);
}
fseek(ifp, save + 4, SEEK_SET);
if ((tcol += tile_width) >= raw_width)
trow += tile_length + (tcol = 0);
}
}
catch (...)
{
shot_select = ss;
throw;
}
shot_select = ss;
}
void LibRaw::sony_ljpeg_load_raw()
{
unsigned trow = 0, tcol = 0, jrow, jcol, row, col;
INT64 save;
struct jhead jh;
while (trow < raw_height)
{
checkCancel();
save = ftell(ifp); // We're at
if (tile_length < INT_MAX)
fseek(ifp, get4(), SEEK_SET);
if (!ljpeg_start(&jh, 0))
break;
try
{
for (row = jrow = 0; jrow < (unsigned)jh.high && trow+row < raw_height-1; jrow++, row += 2)
{
checkCancel();
ushort(*rowp)[4] = (ushort(*)[4])ljpeg_row(jrow, &jh);
for (col = jcol = 0; jcol < (unsigned)jh.wide && tcol+col < raw_width-1; jcol++, col += 2)
{
RAW(trow + row, tcol + col) = rowp[jcol][0];
RAW(trow + row, tcol + col + 1) = rowp[jcol][1];
RAW(trow + row + 1, tcol + col) = rowp[jcol][2];
RAW(trow + row + 1, tcol + col + 1) = rowp[jcol][3];
}
}
}
catch (...)
{
ljpeg_end(&jh);
throw;
}
fseek(ifp, save + 4, SEEK_SET);
if ((tcol += tile_width) >= raw_width)
trow += tile_length + (tcol = 0);
ljpeg_end(&jh);
}
}
void LibRaw::nikon_coolscan_load_raw()
{
int clrs = colors == 3 ? 3 : 1;
if (clrs == 3 && !image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
if(clrs == 1 && !raw_image)
throw LIBRAW_EXCEPTION_IO_CORRUPT;
int bypp = tiff_bps <= 8 ? 1 : 2;
int bufsize = width * clrs * bypp;
unsigned char *buf = (unsigned char *)calloc(bufsize,1);
unsigned short *ubuf = (unsigned short *)buf;
if (tiff_bps <= 8)
gamma_curve(1.0 / imgdata.rawparams.coolscan_nef_gamma, 0., 1, 255);
else
gamma_curve(1.0 / imgdata.rawparams.coolscan_nef_gamma, 0., 1, 65535);
fseek(ifp, data_offset, SEEK_SET);
for (int row = 0; row < raw_height; row++)
{
if (tiff_bps <= 8)
{
if (fread(buf, 1, bufsize, ifp) < bufsize)
derror(); // will raise EOF exception on eof
}
else
read_shorts(ubuf,width*clrs);
unsigned short(*ip)[4] = (unsigned short(*)[4])image + row * width;
unsigned short *rp = raw_image + row * raw_width;
if (is_NikonTransfer == 2)
{ // it is also (tiff_bps == 8)
if (clrs == 3)
{
for (int col = 0; col < width; col++)
{
ip[col][0] = ushort(((float)curve[buf[col * 3]]) / 255.0f);
ip[col][1] = ushort(((float)curve[buf[col * 3 + 1]]) / 255.0f);
ip[col][2] = ushort(((float)curve[buf[col * 3 + 2]]) / 255.0f);
ip[col][3] = 0;
}
}
else
{
for (int col = 0; col < width; col++)
rp[col] = ushort(((float)curve[buf[col]]) / 255.0f);
}
}
else if (tiff_bps <= 8)
{
if (clrs == 3)
{
for (int col = 0; col < width; col++)
{
ip[col][0] = curve[buf[col * 3]];
ip[col][1] = curve[buf[col * 3 + 1]];
ip[col][2] = curve[buf[col * 3 + 2]];
ip[col][3] = 0;
}
}
else
{
for (int col = 0; col < width; col++)
rp[col] = curve[buf[col]];
}
}
else
{
if (clrs == 3)
{
for (int col = 0; col < width; col++)
{
ip[col][0] = curve[ubuf[col * 3]];
ip[col][1] = curve[ubuf[col * 3 + 1]];
ip[col][2] = curve[ubuf[col * 3 + 2]];
ip[col][3] = 0;
}
}
else
{
for (int col = 0; col < width; col++)
rp[col] = curve[ubuf[col]];
}
}
}
free(buf);
}
void LibRaw::broadcom_load_raw()
{
uchar *dp;
int rev, row, col, c;
rev = 3 * (order == 0x4949);
std::vector<uchar> data(raw_stride * 2);
for (row = 0; row < raw_height; row++)
{
if (fread(data.data() + raw_stride, 1, raw_stride, ifp) < raw_stride)
derror();
FORC(raw_stride) data[c] = data[raw_stride + (c ^ rev)];
for (dp = data.data(), col = 0; col < raw_width; dp += 5, col += 4)
FORC4 RAW(row, col + c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
}
}
void LibRaw::android_tight_load_raw()
{
uchar *data, *dp;
int bwide, row, col, c;
bwide = -(-5 * raw_width >> 5) << 3;
data = (uchar *)calloc(bwide,1);
for (row = 0; row < raw_height; row++)
{
if (fread(data, 1, bwide, ifp) < bwide)
derror();
for (dp = data, col = 0; col < raw_width; dp += 5, col += 4)
FORC4 RAW(row, col + c) = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
}
free(data);
}
void LibRaw::android_loose_load_raw()
{
uchar *data, *dp;
int bwide, row, col, c;
UINT64 bitbuf = 0;
bwide = (raw_width + 5) / 6 << 3;
data = (uchar *)calloc(bwide,1);
for (row = 0; row < raw_height; row++)
{
if (fread(data, 1, bwide, ifp) < bwide)
derror();
for (dp = data, col = 0; col < raw_width; dp += 8, col += 6)
{
FORC(8) bitbuf = (bitbuf << 8) | dp[c ^ 7];
FORC(6) RAW(row, col + c) = (bitbuf >> c * 10) & 0x3ff;
}
}
free(data);
}
void LibRaw::unpacked_load_raw_reversed()
{
int row, col, bits = 0;
while (1 << ++bits < (int)maximum)
;
for (row = raw_height - 1; row >= 0; row--)
{
checkCancel();
read_shorts(&raw_image[row * raw_width], raw_width);
for (col = 0; col < raw_width; col++)
if ((RAW(row, col) >>= load_flags) >> bits &&
(unsigned)(row - top_margin) < height &&
(unsigned)(col - left_margin) < width)
derror();
}
}
#ifdef USE_6BY9RPI
void LibRaw::rpi_load_raw8()
{
uchar *data, *dp;
int rev, dwide, row, col, c;
double sum[] = { 0,0 };
rev = 3 * (order == 0x4949);
if (raw_stride == 0)
dwide = raw_width;
else
dwide = raw_stride;
data = (uchar *)calloc(dwide, 2);
for (row = 0; row < raw_height; row++) {
if (fread(data + dwide, 1, dwide, ifp) < dwide) derror();
FORC(dwide) data[c] = data[dwide + (c ^ rev)];
for (dp = data, col = 0; col < raw_width; dp++, col++)
RAW(row, col + c) = dp[c];
}
free(data);
maximum = 0xff;
if (!strcmp(make, "OmniVision") ||
!strcmp(make, "Sony") ||
!strcmp(make, "RaspberryPi")) return;
row = raw_height / 2;
FORC(width - 1) {
sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
}
if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
}
void LibRaw::rpi_load_raw12()
{
uchar *data, *dp;
int rev, dwide, row, col, c;
double sum[] = { 0,0 };
rev = 3 * (order == 0x4949);
if (raw_stride == 0)
dwide = (raw_width * 3 + 1) / 2;
else
dwide = raw_stride;
data = (uchar *)calloc(dwide, 2);
for (row = 0; row < raw_height; row++) {
if (fread(data + dwide, 1, dwide, ifp) < dwide) derror();
FORC(dwide) data[c] = data[dwide + (c ^ rev)];
for (dp = data, col = 0; col < raw_width; dp += 3, col += 2)
FORC(2) RAW(row, col + c) = (dp[c] << 4) | (dp[2] >> (c << 2) & 0xF);
}
free(data);
maximum = 0xfff;
if (!strcmp(make, "OmniVision") ||
!strcmp(make, "Sony") ||
!strcmp(make, "RaspberryPi")) return;
row = raw_height / 2;
FORC(width - 1) {
sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
}
if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
}
void LibRaw::rpi_load_raw14()
{
uchar *data, *dp;
int rev, dwide, row, col, c;
double sum[] = { 0,0 };
rev = 3 * (order == 0x4949);
if (raw_stride == 0)
dwide = ((raw_width * 7) + 3) >> 2;
else
dwide = raw_stride;
data = (uchar *)calloc(dwide, 2);
for (row = 0; row < raw_height; row++) {
if (fread(data + dwide, 1, dwide, ifp) < dwide) derror();
FORC(dwide) data[c] = data[dwide + (c ^ rev)];
for (dp = data, col = 0; col < raw_width; dp += 7, col += 4) {
RAW(row, col + 0) = (dp[0] << 6) | (dp[4] >> 2);
RAW(row, col + 1) = (dp[1] << 6) | ((dp[4] & 0x3) << 4) | ((dp[5] & 0xf0) >> 4);
RAW(row, col + 2) = (dp[2] << 6) | ((dp[5] & 0xf) << 2) | ((dp[6] & 0xc0) >> 6);
RAW(row, col + 3) = (dp[3] << 6) | ((dp[6] & 0x3f) << 2);
}
}
free(data);
maximum = 0x3fff;
if (!strcmp(make, "OmniVision") ||
!strcmp(make, "Sony") ||
!strcmp(make, "RaspberryPi")) return;
row = raw_height / 2;
FORC(width - 1) {
sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
}
if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
}
void LibRaw::rpi_load_raw16()
{
uchar *data, *dp;
int rev, dwide, row, col, c;
double sum[] = { 0,0 };
rev = 3 * (order == 0x4949);
if (raw_stride == 0)
dwide = (raw_width * 2);
else
dwide = raw_stride;
data = (uchar *)calloc(dwide, 2);
for (row = 0; row < raw_height; row++) {
if (fread(data + dwide, 1, dwide, ifp) < dwide) derror();
FORC(dwide) data[c] = data[dwide + (c ^ rev)];
for (dp = data, col = 0; col < raw_width; dp += 2, col++)
RAW(row, col + c) = (dp[1] << 8) | dp[0];
}
free(data);
maximum = 0xffff;
if (!strcmp(make, "OmniVision") ||
!strcmp(make, "Sony") ||
!strcmp(make, "RaspberryPi")) return;
row = raw_height / 2;
FORC(width - 1) {
sum[c & 1] += SQR(RAW(row, c) - RAW(row + 1, c + 1));
sum[~c & 1] += SQR(RAW(row + 1, c) - RAW(row, c + 1));
}
if (sum[1] > sum[0]) filters = 0x4b4b4b4b;
}
#endif