RAWTranslator: switch to libraw as backend when available
tested with .cr2 and .dng single pictures. Change-Id: I9a4802300fd2afe14c085ca18faa8a1e20c52bfd Reviewed-on: https://review.haiku-os.org/c/haiku/+/4452 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
parent
f2a79670ae
commit
40793c1ef6
@ -622,6 +622,23 @@ if [ IsPackageAvailable libdvdnav_devel ] {
|
||||
}
|
||||
|
||||
|
||||
# libraw
|
||||
if [ IsPackageAvailable libraw_devel ] {
|
||||
ExtractBuildFeatureArchives libraw :
|
||||
file: base libraw
|
||||
runtime: lib
|
||||
file: devel libraw_devel
|
||||
depends: base
|
||||
libraries: $(developLibDir)/libraw.so.19
|
||||
headers: $(developHeadersDir)
|
||||
;
|
||||
|
||||
EnableBuildFeatures libraw ;
|
||||
} else {
|
||||
unavailableBuildFeatures += libraw ;
|
||||
}
|
||||
|
||||
|
||||
# libwebp
|
||||
if [ IsPackageAvailable libwebp_devel ] {
|
||||
if $(HAIKU_PACKAGING_ARCH) = x86 && $(TARGET_PACKAGING_ARCH) = x86_gcc2 {
|
||||
|
@ -16,6 +16,10 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USES_LIBRAW
|
||||
#include <libraw/libraw.h>
|
||||
#endif
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "ConfigView"
|
||||
|
||||
@ -39,13 +43,23 @@ ConfigView::ConfigView(uint32 flags)
|
||||
BStringView *fVersion = new BStringView("version", version);
|
||||
|
||||
BStringView *fCopyright = new BStringView("copyright",
|
||||
B_UTF8_COPYRIGHT "2007-2009 Haiku Inc.");
|
||||
B_UTF8_COPYRIGHT "2007-2021 Haiku Inc.");
|
||||
|
||||
#ifdef USES_LIBRAW
|
||||
BString librawInfo = B_TRANSLATE(
|
||||
"Based on libraw %version%");
|
||||
librawInfo.ReplaceAll("%version%", LibRaw::version());
|
||||
BStringView *fCopyright2 = new BStringView("Copyright2",
|
||||
librawInfo.String());
|
||||
BStringView *fCopyright3 = new BStringView("Copyright3",
|
||||
B_TRANSLATE(B_UTF8_COPYRIGHT "Copyright (C) 2008-2021 LibRaw LLC"));
|
||||
#else
|
||||
BStringView *fCopyright2 = new BStringView("copyright2",
|
||||
B_TRANSLATE("Based on Dave Coffin's dcraw 8.63"));
|
||||
|
||||
BStringView *fCopyright3 = new BStringView("copyright3",
|
||||
B_UTF8_COPYRIGHT "1997-2007 Dave Coffin");
|
||||
#endif
|
||||
|
||||
// Build the layout
|
||||
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
|
||||
|
@ -7,16 +7,32 @@ AddResources RAWTranslator : RAWTranslator.rdef ;
|
||||
local architectureObject ;
|
||||
for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
on $(architectureObject) {
|
||||
|
||||
local backend = RAW.cpp ;
|
||||
local libs = ;
|
||||
local defines = ;
|
||||
|
||||
if [ FIsBuildFeatureEnabled libraw ] {
|
||||
UseBuildFeatureHeaders libraw ;
|
||||
backend = LibRAW.cpp ;
|
||||
libs = [ BuildFeatureAttribute libraw : libraries ] ;
|
||||
defines = [ FDefines USES_LIBRAW ] ;
|
||||
Includes [ FGristFiles ConfigView.cpp LibRAW.cpp
|
||||
RAWTranslator.cpp ]
|
||||
: [ BuildFeatureAttribute libraw : headers ] ;
|
||||
}
|
||||
SubDirC++Flags $(defines) ;
|
||||
|
||||
Translator [ MultiArchDefaultGristFiles RAWTranslator ] :
|
||||
# RawTranslator classes
|
||||
main.cpp
|
||||
RAWTranslator.cpp
|
||||
ConfigView.cpp
|
||||
RAW.cpp
|
||||
$(backend)
|
||||
:
|
||||
be translation
|
||||
[ MultiArchDefaultGristFiles libtranslatorsutils.a ]
|
||||
[ TargetLibsupc++ ] localestub
|
||||
[ TargetLibsupc++ ] $(libs) localestub
|
||||
:
|
||||
true
|
||||
;
|
||||
|
359
src/add-ons/translators/raw/LibRAW.cpp
Normal file
359
src/add-ons/translators/raw/LibRAW.cpp
Normal file
@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright 2021, Jérôme Duval, jerome.duval@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "LibRAW.h"
|
||||
|
||||
#include <Message.h>
|
||||
#include <TranslationErrors.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libraw/libraw.h>
|
||||
|
||||
#include "StreamBuffer.h"
|
||||
|
||||
|
||||
//#define TRACE(x...) printf(x)
|
||||
#define TRACE(x...)
|
||||
#define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
|
||||
#define RETURN(x, y) { TRACE("RETURN %s %s\n", __PRETTY_FUNCTION__, x); \
|
||||
return y; }
|
||||
|
||||
static const uint32 kImageBufferCount = 10;
|
||||
static const uint32 kDecodeBufferCount = 2048;
|
||||
|
||||
|
||||
#define P1 fRaw->imgdata.idata
|
||||
#define S fRaw->imgdata.sizes
|
||||
#define C fRaw->imgdata.color
|
||||
#define T fRaw->imgdata.thumbnail
|
||||
#define P2 fRaw->imgdata.other
|
||||
#define OUT fRaw->imgdata.params
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
class LibRaw_haiku_datastream : public LibRaw_abstract_datastream
|
||||
{
|
||||
public:
|
||||
BPositionIO* fStream;
|
||||
virtual ~LibRaw_haiku_datastream();
|
||||
LibRaw_haiku_datastream(BPositionIO* stream);
|
||||
virtual int valid();
|
||||
virtual int read(void *ptr, size_t size, size_t nmemb);
|
||||
virtual int eof();
|
||||
virtual int seek(INT64 o, int whence);
|
||||
virtual INT64 tell();
|
||||
virtual INT64 size();
|
||||
virtual int get_char();
|
||||
virtual char *gets(char *str, int sz);
|
||||
virtual int scanf_one(const char *fmt, void *val);
|
||||
virtual void *make_jas_stream();
|
||||
|
||||
private:
|
||||
StreamBuffer *buffer;
|
||||
off_t fSize;
|
||||
status_t iseof;
|
||||
};
|
||||
|
||||
|
||||
LibRaw_haiku_datastream::LibRaw_haiku_datastream(BPositionIO* stream)
|
||||
{
|
||||
CALLED();
|
||||
iseof = 0;
|
||||
buffer = new StreamBuffer(stream, 2048);
|
||||
fStream = stream;
|
||||
fStream->GetSize(&fSize);
|
||||
}
|
||||
|
||||
LibRaw_haiku_datastream::~LibRaw_haiku_datastream()
|
||||
{
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
LibRaw_haiku_datastream::read(void *ptr, size_t sz, size_t nmemb)
|
||||
{
|
||||
CALLED();
|
||||
TRACE("read %ld %ld\n", sz, nmemb);
|
||||
size_t to_read = sz * nmemb;
|
||||
|
||||
to_read = buffer->Read(ptr, to_read);
|
||||
if (to_read < B_OK)
|
||||
RETURN("ERROR2", to_read);
|
||||
return int((to_read + sz - 1) / (sz > 0 ? sz : 1));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
LibRaw_haiku_datastream::seek(INT64 o, int whence)
|
||||
{
|
||||
CALLED();
|
||||
TRACE("seek %lld %d\n", o, whence);
|
||||
return buffer->Seek(o, whence) < 0;
|
||||
}
|
||||
|
||||
|
||||
INT64
|
||||
LibRaw_haiku_datastream::tell()
|
||||
{
|
||||
CALLED();
|
||||
off_t position = buffer->Position();
|
||||
TRACE("RETURN LibRaw_haiku_datastream::tell %ld\n", position);
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
INT64
|
||||
LibRaw_haiku_datastream::size()
|
||||
{
|
||||
CALLED();
|
||||
TRACE("RETURN size %ld\n", fSize);
|
||||
return fSize;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
LibRaw_haiku_datastream::get_char()
|
||||
{
|
||||
CALLED();
|
||||
unsigned char value;
|
||||
ssize_t error;
|
||||
iseof = 0;
|
||||
error = buffer->Read((void*)&value, sizeof(unsigned char));
|
||||
if (error >= 0)
|
||||
return value;
|
||||
iseof = EOF;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
LibRaw_haiku_datastream::gets(char* s, int sz)
|
||||
{
|
||||
CALLED();
|
||||
if (sz<1)
|
||||
return NULL;
|
||||
int pos = 0;
|
||||
bool found = false ;
|
||||
while (!found && pos < (sz - 1)) {
|
||||
char buffer;
|
||||
if (this->buffer->Read(&buffer, 1) < 1)
|
||||
break;
|
||||
s[pos++] = buffer ;
|
||||
if (buffer == '\n') {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
s[pos] = 0;
|
||||
} else
|
||||
s[sz - 1] = 0 ;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
LibRaw_haiku_datastream::scanf_one(const char *fmt, void *val)
|
||||
{
|
||||
CALLED();
|
||||
int scanf_res = 0;
|
||||
/* if (streampos > streamsize)
|
||||
return 0;
|
||||
scanf_res = sscanf_s((char *)(buf + streampos), fmt, val);
|
||||
if (scanf_res > 0)
|
||||
{
|
||||
int xcnt = 0;
|
||||
while (streampos < streamsize)
|
||||
{
|
||||
streampos++;
|
||||
xcnt++;
|
||||
if (buf[streampos] == 0 || buf[streampos] == ' ' ||
|
||||
buf[streampos] == '\t' || buf[streampos] == '\n' || xcnt > 24)
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
return scanf_res;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
LibRaw_haiku_datastream::eof()
|
||||
{
|
||||
CALLED();
|
||||
return iseof;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
LibRaw_haiku_datastream::valid()
|
||||
{
|
||||
CALLED();
|
||||
return buffer != NULL ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
LibRaw_haiku_datastream::make_jas_stream()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
LibRAW::LibRAW(BPositionIO& stream)
|
||||
:
|
||||
fProgressMonitor(NULL),
|
||||
fRaw(new LibRaw()),
|
||||
fDatastream(new LibRaw_haiku_datastream(&stream))
|
||||
{
|
||||
CALLED();
|
||||
}
|
||||
|
||||
|
||||
LibRAW::~LibRAW()
|
||||
{
|
||||
delete fRaw;
|
||||
delete fDatastream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
LibRAW::Identify()
|
||||
{
|
||||
CALLED();
|
||||
fDatastream->fStream->Seek(0, SEEK_SET);
|
||||
|
||||
status_t status = B_NO_TRANSLATOR;
|
||||
int ret = fRaw->open_datastream(fDatastream);
|
||||
if (ret != LIBRAW_SUCCESS) {
|
||||
TRACE("LibRAW::Identify() open_datastream returned %s\n",
|
||||
libraw_strerror(ret));
|
||||
return status;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LibRAW::ReadImageAt(uint32 index, uint8*& outputBuffer, size_t& bufferSize)
|
||||
{
|
||||
CALLED();
|
||||
if (index >= P1.raw_count)
|
||||
return B_BAD_VALUE;
|
||||
OUT.shot_select = index;
|
||||
OUT.output_bps = 8;
|
||||
OUT.output_tiff = 1;
|
||||
OUT.no_auto_bright = 1;
|
||||
OUT.use_auto_wb = 1;
|
||||
OUT.user_qual = 3;
|
||||
|
||||
if (fRaw->unpack() != LIBRAW_SUCCESS)
|
||||
return B_BAD_DATA;
|
||||
if (fRaw->dcraw_process() != LIBRAW_SUCCESS)
|
||||
return B_BAD_DATA;
|
||||
|
||||
libraw_processed_image_t* img = fRaw->dcraw_make_mem_image();
|
||||
if (img == NULL)
|
||||
return B_BAD_DATA;
|
||||
bufferSize = img->data_size;
|
||||
outputBuffer = (uint8*)malloc(bufferSize);
|
||||
if (outputBuffer == NULL) {
|
||||
fRaw->dcraw_clear_mem(img);
|
||||
throw (status_t)B_NO_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(outputBuffer, img->data, bufferSize);
|
||||
|
||||
fRaw->dcraw_clear_mem(img);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LibRAW::GetMetaInfo(image_meta_info& metaInfo) const
|
||||
{
|
||||
strlcpy(metaInfo.manufacturer, fRaw->imgdata.idata.make,
|
||||
sizeof(metaInfo.manufacturer));
|
||||
strlcpy(metaInfo.model, fRaw->imgdata.idata.model, sizeof(metaInfo.model));
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
LibRAW::CountImages() const
|
||||
{
|
||||
return fRaw->imgdata.idata.raw_count;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LibRAW::ImageAt(uint32 index, image_data_info& info) const
|
||||
{
|
||||
if (index >= fRaw->imgdata.idata.raw_count)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
info.width = S.width;
|
||||
info.height = S.height;
|
||||
info.output_width = S.flip > 4 ? S.iheight : S.iwidth;
|
||||
info.output_height = S.flip > 4 ? S.iwidth : S.iheight;
|
||||
info.flip = S.flip;
|
||||
info.bytes = S.raw_pitch;
|
||||
info.is_raw = 1;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LibRAW::GetEXIFTag(off_t& offset, size_t& length, bool& bigEndian) const
|
||||
{
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LibRAW::SetProgressMonitor(monitor_hook hook, void* data)
|
||||
{
|
||||
fProgressMonitor = hook;
|
||||
fProgressData = data;
|
||||
fRaw->set_progress_handler(hook != NULL ? ProgressCallback : NULL, this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LibRAW::SetHalfSize(bool half)
|
||||
{
|
||||
OUT.half_size = half;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
LibRAW::ProgressCallback(void *data, enum LibRaw_progress p, int iteration,
|
||||
int expected)
|
||||
{
|
||||
return ((LibRAW*)data)->_ProgressCallback(p, iteration, expected);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
LibRAW::_ProgressCallback(enum LibRaw_progress p,int iteration, int expected)
|
||||
{
|
||||
fProgressMonitor(libraw_strprogress(p), iteration * 100 / expected,
|
||||
fProgressData);
|
||||
return 0;
|
||||
}
|
100
src/add-ons/translators/raw/LibRAW.h
Normal file
100
src/add-ons/translators/raw/LibRAW.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2021, Jérôme Duval, jerome.duval@gmail.com.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef LIBRAW_H
|
||||
#define LIBRAW_H
|
||||
|
||||
|
||||
#include <DataIO.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <libraw/libraw_const.h>
|
||||
|
||||
|
||||
class LibRaw;
|
||||
class LibRaw_haiku_datastream;
|
||||
|
||||
|
||||
struct image_meta_info {
|
||||
char manufacturer[64];
|
||||
char model[64];
|
||||
char software[64];
|
||||
float flash_used;
|
||||
float iso_speed;
|
||||
float shutter;
|
||||
float aperture;
|
||||
float focal_length;
|
||||
double pixel_aspect;
|
||||
uint32 raw_width;
|
||||
uint32 raw_height;
|
||||
int flip;
|
||||
uint32 dng_version;
|
||||
uint32 shot_order;
|
||||
int32 black;
|
||||
int32 maximum;
|
||||
float camera_multipliers[4];
|
||||
float pre_multipliers[4];
|
||||
float rgb_camera[3][4]; /* RGB from camera color */
|
||||
time_t timestamp;
|
||||
};
|
||||
|
||||
struct image_data_info {
|
||||
uint32 width;
|
||||
uint32 height;
|
||||
uint32 output_width;
|
||||
uint32 output_height;
|
||||
uint32 bits_per_sample;
|
||||
uint32 compression;
|
||||
uint32 photometric_interpretation;
|
||||
uint32 flip;
|
||||
uint32 samples;
|
||||
uint32 bytes;
|
||||
off_t data_offset;
|
||||
bool is_raw;
|
||||
};
|
||||
|
||||
#define COMPRESSION_NONE 1
|
||||
#define COMPRESSION_OLD_JPEG 6 // Old JPEG (before 6.0)
|
||||
#define COMPRESSION_PACKBITS 32773 // Macintosh RLE
|
||||
|
||||
|
||||
typedef void (*monitor_hook)(const char* message, float percentage, void* data);
|
||||
|
||||
class LibRAW {
|
||||
public:
|
||||
LibRAW(BPositionIO& stream);
|
||||
~LibRAW();
|
||||
|
||||
status_t Identify();
|
||||
status_t ReadImageAt(uint32 index, uint8*& outputBuffer,
|
||||
size_t& bufferSize);
|
||||
|
||||
void GetMetaInfo(image_meta_info& metaInfo) const;
|
||||
uint32 CountImages() const;
|
||||
status_t ImageAt(uint32 index, image_data_info& info)
|
||||
const;
|
||||
|
||||
status_t GetEXIFTag(off_t& offset, size_t& length,
|
||||
bool& bigEndian) const;
|
||||
void SetProgressMonitor(monitor_hook hook,
|
||||
void* data);
|
||||
|
||||
void SetHalfSize(bool half);
|
||||
|
||||
private:
|
||||
static int ProgressCallback(void *data,
|
||||
enum LibRaw_progress p,
|
||||
int iteration, int expected);
|
||||
int _ProgressCallback(enum LibRaw_progress p,
|
||||
int iteration, int expected);
|
||||
|
||||
monitor_hook fProgressMonitor;
|
||||
void* fProgressData;
|
||||
|
||||
LibRaw* fRaw;
|
||||
LibRaw_haiku_datastream* fDatastream;
|
||||
};
|
||||
|
||||
|
||||
#endif // LIBRAW_H
|
@ -6,7 +6,11 @@
|
||||
|
||||
#include "RAWTranslator.h"
|
||||
#include "ConfigView.h"
|
||||
#ifdef USES_LIBRAW
|
||||
#include "LibRAW.h"
|
||||
#else
|
||||
#include "RAW.h"
|
||||
#endif
|
||||
|
||||
#include <Catalog.h>
|
||||
#include <BufferIO.h>
|
||||
@ -127,7 +131,11 @@ RAWTranslator::DerivedIdentify(BPositionIO *stream,
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
BBufferIO io(stream, 128 * 1024, false);
|
||||
#ifdef USES_LIBRAW
|
||||
LibRAW raw(io);
|
||||
#else
|
||||
DCRaw raw(io);
|
||||
#endif
|
||||
status_t status;
|
||||
|
||||
try {
|
||||
@ -199,7 +207,11 @@ RAWTranslator::DerivedTranslate(BPositionIO* stream,
|
||||
return B_NO_TRANSLATOR;
|
||||
|
||||
BBufferIO io(stream, 1024 * 1024, false);
|
||||
#ifdef USES_LIBRAW
|
||||
LibRAW raw(io);
|
||||
#else
|
||||
DCRaw raw(io);
|
||||
#endif
|
||||
|
||||
bool headerOnly = false;
|
||||
|
||||
@ -300,13 +312,23 @@ RAWTranslator::DerivedTranslate(BPositionIO* stream,
|
||||
free(exifBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USES_LIBRAW
|
||||
uint32 dataSize = data.output_width * 3 * data.output_height;
|
||||
#else
|
||||
uint32 dataSize = data.output_width * 4 * data.output_height;
|
||||
#endif
|
||||
|
||||
TranslatorBitmap header;
|
||||
header.magic = B_TRANSLATOR_BITMAP;
|
||||
header.bounds.Set(0, 0, data.output_width - 1, data.output_height - 1);
|
||||
#ifdef USES_LIBRAW
|
||||
header.rowBytes = data.output_width * 3;
|
||||
header.colors = B_RGB24_BIG;
|
||||
#else
|
||||
header.rowBytes = data.output_width * 4;
|
||||
header.colors = B_RGB32;
|
||||
#endif
|
||||
header.dataSize = dataSize;
|
||||
|
||||
// write out Be's Bitmap header
|
||||
|
@ -143,5 +143,8 @@ requires {
|
||||
#ifdef HAIKU_BUILD_FEATURE_%HAIKU_PACKAGING_ARCH%_libwebp_ENABLED
|
||||
lib:libwebp
|
||||
#endif
|
||||
#ifdef HAIKU_BUILD_FEATURE_%HAIKU_PACKAGING_ARCH%_libraw_ENABLED
|
||||
lib:libraw >= 19
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user