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:
Jérôme Duval 2021-09-07 18:04:53 +02:00
parent f2a79670ae
commit 40793c1ef6
7 changed files with 534 additions and 3 deletions

View File

@ -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 {

View File

@ -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)

View File

@ -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
;

View 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;
}

View 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

View File

@ -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

View File

@ -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
}