merge with dev

This commit is contained in:
U-PC-BUREAU\jacques
2018-11-11 10:02:38 +01:00
10 changed files with 885 additions and 24 deletions

View File

@@ -2,7 +2,7 @@
This file is part of RawTherapee.
Copyright (c) 2016-2018 TooWaBoo
Version 2.85
Version 2.86
RawTherapee is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -113,6 +113,10 @@ window > box {
dialog {
background-color: @bg-grey;
border-radius: 0;
-GtkDialog-button-spacing: 0;
-GtkDialog-content-area-spacing: 0;
-GtkDialog-content-area-border: 0;
-GtkDialog-action-area-border: 0;
}
dialog > box {
padding: 0.666666666666666666em;
@@ -336,9 +340,13 @@ fontchooser scrolledwindow,
/*** end ***************************************************************************************/
/*** Load - Save dialog ************************************************************************/
filechooser {
margin-bottom: 0.25em;
}
filechooser box > box box > button {
filechooser box > box box > button {
margin-top: 0.5em;
margin-right: 0;
}
filechooser image {
@@ -465,7 +473,7 @@ separator,
background-color: transparent;
}
grid separator.horizontal, box separator.horizontal {
margin: 0.166666666666666666em 0;
margin: 0.333333333333333333em 0.166666666666666666em;
padding: 0;
}
grid separator.vertical, box separator.vertical {
@@ -537,12 +545,12 @@ menu separator {
padding: 0;
}
.scrollableToolbar separator:not(.dummy) {
.scrollableToolbar separator.vertical {
background-color: shade(@bg-light-grey,.75);
margin: 0.166666666666666666em;
}
#MyExpander separator {
#MyExpander separator.horizontal {
background-color: @view-grid-border;
margin: 0.333333333333333333em 0.166666666666666666em;
}
@@ -944,7 +952,8 @@ window.csd:not(.fullscreen) #MainNotebook > header.top {
#PrefNotebook > header {
margin: -0.666666666666666666em -0.666666666666666666em 0.333333333333333333em;
}
#PrefNotebook > header tab label {
#PrefNotebook > header tab label,
#AboutNotebook > header tab label {
padding-top: 0.25em;
padding-bottom: 0.25em;
}
@@ -1409,8 +1418,12 @@ combobox entry + button:not(.dummy) {
border-bottom-left-radius: 0;
border-left: none;
}
#PlacesPaned button.combo {
margin: 0 0 calc(0.416666666666666666em - 8px) 0;
margin: 0;
}
#PlacesPaned combobox {
margin-bottom: calc(0.416666666666666666em - 8px);
}
/* Reset button */
@@ -1435,14 +1448,15 @@ colorchooser colorswatch#add-color-button:first-child {
}
/* Save, Cancel, OK ... buttons */
.dialog-action-area button {
dialog .dialog-action-area button {
min-height: 2.166666666666666666em;
margin-top: 1em;
margin: 0.5em 0 0 0.333333333333333333em;
padding: 0;
}
messagedialog .dialog-action-area button {
min-height: 1.833333333333333333em;
margin: -12px 0.5em 0.5em 0.5em;
margin: -12px 0.5em 0.5em;
padding: 0;
}
messagedialog .dialog-action-area button:not(:only-child):nth-child(1) {
margin-right: 0.25em;
@@ -1789,7 +1803,7 @@ radio:disabled {
radiobutton label,
checkbutton label {
margin: 0 0 0 0.416666666666666666em;
margin: 0 0.416666666666666666em;
padding: 0;
}

View File

@@ -131,6 +131,7 @@ set(RTENGINESOURCEFILES
guidedfilter.cc
ipdehaze.cc
iplabregions.cc
lj92.c
)
if(LENSFUN_HAS_LOAD_DIRECTORY)

View File

@@ -23,6 +23,10 @@
/*RT*/#define LOCALTIME
/*RT*/#define DJGPP
/*RT*/#include "jpeg.h"
/*RT*/#include "lj92.h"
/*RT*/#ifdef _OPENMP
/*RT*/#include <omp.h>
/*RT*/#endif
#include <utility>
#include <vector>
@@ -1124,6 +1128,64 @@ void CLASS ljpeg_idct (struct jhead *jh)
FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c]+0.5);
}
void CLASS lossless_dnglj92_load_raw()
{
BENCHFUN
tiff_bps = 16;
int save = ifp->pos;
uint16_t *lincurve = !strncmp(make,"Blackmagic",10) ? curve : nullptr;
tile_width = tile_length < INT_MAX ? tile_width : raw_width;
size_t tileCount = raw_width / tile_width;
size_t dataOffset[tileCount];
if(tile_length < INT_MAX) {
for (size_t t = 0; t < tileCount; ++t) {
dataOffset[t] = get4();
}
} else {
dataOffset[0] = ifp->pos;
}
uint8_t *data = (uint8_t*)malloc(ifp->size);
fseek(ifp, 0, SEEK_SET);
// read whole file
int data_length = ifp->size;
fread(data, 1, data_length, ifp);
lj92 lj;
int newwidth, newheight, newbps;
lj92_open(&lj, &data[dataOffset[0]], data_length, &newwidth, &newheight, &newbps);
lj92_close(lj);
if (newwidth * newheight * tileCount != raw_width * raw_height) {
// not a lj92 file
fseek(ifp, save, SEEK_SET);
free(data);
lossless_dng_load_raw();
return;
}
#ifdef _OPENMP
#pragma omp parallel for num_threads(std::min<int>(tileCount, omp_get_max_threads()))
#endif
for (size_t t = 0; t < tileCount; ++t) {
size_t tcol = t * tile_width;
lj92 lj;
int newwidth, newheight, newbps;
lj92_open(&lj, &data[dataOffset[t]], data_length, &newwidth, &newheight, &newbps);
uint16_t *target = (uint16_t*)malloc(newwidth * newheight * sizeof *target);
lj92_decode(lj, target, tile_width, 0, lincurve, 0x1000);
for (int y = 0; y < height; ++y) {
for(int x = 0; x < tile_width; ++x) {
RAW(y, x + tcol) = target[y * tile_width + x];
}
}
lj92_close(lj);
free(target);
}
free(data);
}
void CLASS lossless_dng_load_raw()
{
unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col, i, j;
@@ -9280,7 +9342,7 @@ void CLASS identify()
switch (tiff_compress) {
case 0:
case 1: load_raw = &CLASS packed_dng_load_raw; break;
case 7: load_raw = &CLASS lossless_dng_load_raw; break;
case 7: load_raw = (!strncmp(make,"Blackmagic",10) || !strncmp(make,"Canon",5)) ? &CLASS lossless_dnglj92_load_raw : &CLASS lossless_dng_load_raw; break;
case 8: load_raw = &CLASS deflate_dng_load_raw; break;
case 34892: load_raw = &CLASS lossy_dng_load_raw; break;
default: load_raw = 0;

View File

@@ -290,6 +290,7 @@ void ljpeg_idct (struct jhead *jh);
void canon_sraw_load_raw();
void adobe_copy_pixel (unsigned row, unsigned col, ushort **rp);
void lossless_dng_load_raw();
void lossless_dnglj92_load_raw();
void packed_dng_load_raw();
void deflate_dng_load_raw();
void init_fuji_compr(struct fuji_compressed_params* info);

View File

@@ -161,6 +161,13 @@ FrameData::FrameData(rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory*
model = "Unknown";
}
if (model == "Unknown") {
tag = newFrameRootDir->findTag("UniqueCameraModel");
if (tag) {
model = tag->valueToString();
}
}
tag = newFrameRootDir->findTagUpward("Orientation");
if (tag) {

View File

@@ -1079,6 +1079,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
hListener->histogramChanged(histRed, histGreen, histBlue, histLuma, histToneCurve, histLCurve, histCCurve, /*histCLurve, histLLCurve,*/ histLCAM, histCCAM, histRedRaw, histGreenRaw, histBlueRaw, histChroma, histLRETI);
}
}
if (orig_prev != oprevi) {
delete oprevi;
oprevi = nullptr;
}
}

696
rtengine/lj92.c Normal file
View File

@@ -0,0 +1,696 @@
/*
lj92.c
(c) Andrew Baldwin 2014
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lj92.h"
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
//#define SLOW_HUFF
//#define DEBUG
typedef struct _ljp {
u8* data;
u8* dataend;
int datalen;
int scanstart;
int ix;
int x; // Width
int y; // Height
int bits; // Bit depth
int writelen; // Write rows this long
int skiplen; // Skip this many values after each row
u16* linearize; // Linearization table
int linlen;
int sssshist[16];
// Huffman table - only one supported, and probably needed
#ifdef SLOW_HUFF
int* maxcode;
int* mincode;
int* valptr;
u8* huffval;
int* huffsize;
int* huffcode;
#else
u16* hufflut;
int huffbits;
#endif
// Parse state
int cnt;
u32 b;
u16* image;
u16* rowcache;
u16* outrow[2];
} ljp;
static int find(ljp* self) {
int ix = self->ix;
u8* data = self->data;
while (data[ix] != 0xFF && ix<(self->datalen-1)) {
ix += 1;
}
ix += 2;
if (ix>=self->datalen) return -1;
self->ix = ix;
return data[ix-1];
}
#define BEH(ptr) ((((int)(*&ptr))<<8)|(*(&ptr+1)))
static int parseHuff(ljp* self) {
int ret = LJ92_ERROR_CORRUPT;
u8* huffhead = &self->data[self->ix]; // xstruct.unpack('>HB16B',self.data[self.ix:self.ix+19])
u8* bits = &huffhead[2];
bits[0] = 0; // Because table starts from 1
int hufflen = BEH(huffhead[0]);
if ((self->ix + hufflen) >= self->datalen) return ret;
#ifdef SLOW_HUFF
u8* huffval = calloc(hufflen - 19,sizeof(u8));
if (huffval == NULL) return LJ92_ERROR_NO_MEMORY;
self->huffval = huffval;
for (int hix=0;hix<(hufflen-19);hix++) {
huffval[hix] = self->data[self->ix+19+hix];
#ifdef DEBUG
printf("huffval[%d]=%d\n",hix,huffval[hix]);
#endif
}
self->ix += hufflen;
// Generate huffman table
int k = 0;
int i = 1;
int j = 1;
int huffsize_needed = 1;
// First calculate how long huffsize needs to be
while (i<=16) {
while (j<=bits[i]) {
huffsize_needed++;
k = k+1;
j = j+1;
}
i = i+1;
j = 1;
}
// Now allocate and do it
int* huffsize = calloc(huffsize_needed,sizeof(int));
if (huffsize == NULL) return LJ92_ERROR_NO_MEMORY;
self->huffsize = huffsize;
k = 0;
i = 1;
j = 1;
// First calculate how long huffsize needs to be
int hsix = 0;
while (i<=16) {
while (j<=bits[i]) {
huffsize[hsix++] = i;
k = k+1;
j = j+1;
}
i = i+1;
j = 1;
}
huffsize[hsix++] = 0;
// Calculate the size of huffcode array
int huffcode_needed = 0;
k = 0;
int code = 0;
int si = huffsize[0];
while (1) {
while (huffsize[k] == si) {
huffcode_needed++;
code = code+1;
k = k+1;
}
if (huffsize[k] == 0)
break;
while (huffsize[k] != si) {
code = code << 1;
si = si + 1;
}
}
// Now fill it
int* huffcode = calloc(huffcode_needed,sizeof(int));
if (huffcode == NULL) return LJ92_ERROR_NO_MEMORY;
self->huffcode = huffcode;
int hcix = 0;
k = 0;
code = 0;
si = huffsize[0];
while (1) {
while (huffsize[k] == si) {
huffcode[hcix++] = code;
code = code+1;
k = k+1;
}
if (huffsize[k] == 0)
break;
while (huffsize[k] != si) {
code = code << 1;
si = si + 1;
}
}
i = 0;
j = 0;
int* maxcode = calloc(17,sizeof(int));
if (maxcode == NULL) return LJ92_ERROR_NO_MEMORY;
self->maxcode = maxcode;
int* mincode = calloc(17,sizeof(int));
if (mincode == NULL) return LJ92_ERROR_NO_MEMORY;
self->mincode = mincode;
int* valptr = calloc(17,sizeof(int));
if (valptr == NULL) return LJ92_ERROR_NO_MEMORY;
self->valptr = valptr;
while (1) {
while (1) {
i++;
if (i>16)
break;
if (bits[i]!=0)
break;
maxcode[i] = -1;
}
if (i>16)
break;
valptr[i] = j;
mincode[i] = huffcode[j];
j = j+bits[i]-1;
maxcode[i] = huffcode[j];
j++;
}
free(huffsize);
self->huffsize = NULL;
free(huffcode);
self->huffcode = NULL;
ret = LJ92_ERROR_NONE;
#else
/* Calculate huffman direct lut */
// How many bits in the table - find highest entry
u8* huffvals = &self->data[self->ix+19];
int maxbits = 16;
while (maxbits>0) {
if (bits[maxbits]) break;
maxbits--;
}
self->huffbits = maxbits;
/* Now fill the lut */
u16* hufflut = (u16*)malloc((1<<maxbits) * sizeof(u16));
if (hufflut == NULL) return LJ92_ERROR_NO_MEMORY;
self->hufflut = hufflut;
int i = 0;
int hv = 0;
int rv = 0;
int vl = 0; // i
int hcode;
int bitsused = 1;
#ifdef DEBUG
printf("%04x:%x:%d:%x\n",i,huffvals[hv],bitsused,1<<(maxbits-bitsused));
#endif
while (i<1<<maxbits) {
if (bitsused>maxbits) {
break; // Done. Should never get here!
}
if (vl >= bits[bitsused]) {
bitsused++;
vl = 0;
continue;
}
if (rv == 1 << (maxbits-bitsused)) {
rv = 0;
vl++;
hv++;
#ifdef DEBUG
printf("%04x:%x:%d:%x\n",i,huffvals[hv],bitsused,1<<(maxbits-bitsused));
#endif
continue;
}
hcode = huffvals[hv];
hufflut[i] = hcode<<8 | bitsused;
//printf("%d %d %d\n",i,bitsused,hcode);
i++;
rv++;
}
ret = LJ92_ERROR_NONE;
#endif
return ret;
}
static int parseSof3(ljp* self) {
if (self->ix+6 >= self->datalen) return LJ92_ERROR_CORRUPT;
self->y = BEH(self->data[self->ix+3]);
self->x = BEH(self->data[self->ix+5]);
self->bits = self->data[self->ix+2];
self->ix += BEH(self->data[self->ix]);
return LJ92_ERROR_NONE;
}
static int parseBlock(ljp* self,int marker) {
self->ix += BEH(self->data[self->ix]);
if (self->ix >= self->datalen) return LJ92_ERROR_CORRUPT;
return LJ92_ERROR_NONE;
}
#ifdef SLOW_HUFF
static int nextbit(ljp* self) {
u32 b = self->b;
if (self->cnt == 0) {
u8* data = &self->data[self->ix];
u32 next = *data++;
b = next;
if (next == 0xff) {
data++;
self->ix++;
}
self->ix++;
self->cnt = 8;
}
int bit = b >> 7;
self->cnt--;
self->b = (b << 1)&0xFF;
return bit;
}
static int decode(ljp* self) {
int i = 1;
int code = nextbit(self);
while (code > self->maxcode[i]) {
i++;
code = (code << 1) + nextbit(self);
}
int j = self->valptr[i];
j = j + code - self->mincode[i];
int value = self->huffval[j];
return value;
}
static int receive(ljp* self,int ssss) {
int i = 0;
int v = 0;
while (i != ssss) {
i++;
v = (v<<1) + nextbit(self);
}
return v;
}
static int extend(ljp* self,int v,int t) {
int vt = 1<<(t-1);
if (v < vt) {
vt = (-1 << t) + 1;
v = v + vt;
}
return v;
}
#endif
inline static int nextdiff(ljp* self, int Px) {
#ifdef SLOW_HUFF
int t = decode(self);
int diff = receive(self,t);
diff = extend(self,diff,t);
//printf("%d %d %d %x\n",Px+diff,Px,diff,t);//,index,usedbits);
#else
u32 b = self->b;
int cnt = self->cnt;
int huffbits = self->huffbits;
int ix = self->ix;
int next;
while (cnt < huffbits) {
next = *(u16*)&self->data[ix];
int one = next&0xFF;
int two = next>>8;
b = (b<<16)|(one<<8)|two;
cnt += 16;
ix += 2;
if (one==0xFF) {
//printf("%x %x %x %x %d\n",one,two,b,b>>8,cnt);
b >>= 8;
cnt -= 8;
} else if (two==0xFF) ix++;
}
int index = b >> (cnt - huffbits);
u16 ssssused = self->hufflut[index];
int usedbits = ssssused&0xFF;
int t = ssssused>>8;
self->sssshist[t]++;
cnt -= usedbits;
int keepbitsmask = (1 << cnt)-1;
b &= keepbitsmask;
while (cnt < t) {
next = *(u16*)&self->data[ix];
int one = next&0xFF;
int two = next>>8;
b = (b<<16)|(one<<8)|two;
cnt += 16;
ix += 2;
if (one==0xFF) {
b >>= 8;
cnt -= 8;
} else if (two==0xFF) ix++;
}
cnt -= t;
int diff = b >> cnt;
int vt = 1<<(t-1);
if (diff < vt) {
vt = (-1 << t) + 1;
diff += vt;
}
keepbitsmask = (1 << cnt)-1;
self->b = b & keepbitsmask;
self->cnt = cnt;
self->ix = ix;
//printf("%d %d\n",t,diff);
//printf("%d %d %d %x %x %d\n",Px+diff,Px,diff,t,index,usedbits);
#ifdef DEBUG
#endif
#endif
return diff;
}
static int parsePred6(ljp* self) {
int ret = LJ92_ERROR_CORRUPT;
self->ix = self->scanstart;
//int compcount = self->data[self->ix+2];
self->ix += BEH(self->data[self->ix]);
self->cnt = 0;
self->b = 0;
int write = self->writelen;
// Now need to decode huffman coded values
int c = 0;
int pixels = self->y * self->x;
u16* out = self->image;
u16* temprow;
u16* thisrow = self->outrow[0];
u16* lastrow = self->outrow[1];
// First pixel predicted from base value
int diff;
int Px;
int col = 0;
int row = 0;
int left = 0;
int linear;
// First pixel
diff = nextdiff(self,0);
Px = 1 << (self->bits-1);
left = Px + diff;
if (self->linearize)
linear = self->linearize[left];
else
linear = left;
thisrow[col++] = left;
out[c++] = linear;
if (self->ix >= self->datalen) return ret;
--write;
int rowcount = self->x-1;
while (rowcount--) {
diff = nextdiff(self,0);
Px = left;
left = Px + diff;
if (self->linearize)
linear = self->linearize[left];
else
linear = left;
thisrow[col++] = left;
out[c++] = linear;
//printf("%d %d %d %d %x\n",col-1,diff,left,thisrow[col-1],&thisrow[col-1]);
if (self->ix >= self->datalen) return ret;
if (--write==0) {
out += self->skiplen;
write = self->writelen;
}
}
temprow = lastrow;
lastrow = thisrow;
thisrow = temprow;
row++;
//printf("%x %x\n",thisrow,lastrow);
while (c<pixels) {
col = 0;
diff = nextdiff(self,0);
Px = lastrow[col]; // Use value above for first pixel in row
left = Px + diff;
if (self->linearize) {
if (left>self->linlen) return LJ92_ERROR_CORRUPT;
linear = self->linearize[left];
} else
linear = left;
thisrow[col++] = left;
//printf("%d %d %d %d\n",col,diff,left,lastrow[col]);
out[c++] = linear;
if (self->ix >= self->datalen) break;
rowcount = self->x-1;
if (--write==0) {
out += self->skiplen;
write = self->writelen;
}
while (rowcount--) {
diff = nextdiff(self,0);
Px = lastrow[col] + ((left - lastrow[col-1])>>1);
left = Px + diff;
//printf("%d %d %d %d %d %x\n",col,diff,left,lastrow[col],lastrow[col-1],&lastrow[col]);
if (self->linearize) {
if (left>self->linlen) return LJ92_ERROR_CORRUPT;
linear = self->linearize[left];
} else
linear = left;
thisrow[col++] = left;
out[c++] = linear;
if (--write==0) {
out += self->skiplen;
write = self->writelen;
}
}
temprow = lastrow;
lastrow = thisrow;
thisrow = temprow;
if (self->ix >= self->datalen) break;
}
if (c >= pixels) ret = LJ92_ERROR_NONE;
return ret;
}
static int parseScan(ljp* self) {
int ret = LJ92_ERROR_CORRUPT;
memset(self->sssshist,0,sizeof(self->sssshist));
self->ix = self->scanstart;
int compcount = self->data[self->ix+2];
int pred = self->data[self->ix+3+2*compcount];
if (pred<0 || pred>7) return ret;
if (pred==6) return parsePred6(self); // Fast path
self->ix += BEH(self->data[self->ix]);
self->cnt = 0;
self->b = 0;
int write = self->writelen;
// Now need to decode huffman coded values
int c = 0;
int pixels = self->y * self->x;
u16* out = self->image;
u16* thisrow = self->outrow[0];
u16* lastrow = self->outrow[1];
// First pixel predicted from base value
int diff;
int Px;
int col = 0;
int row = 0;
int left = 0;
while (c<pixels) {
if ((col==0)&&(row==0)) {
Px = 1 << (self->bits-1);
} else if (row==0) {
Px = left;
} else if (col==0) {
Px = lastrow[col]; // Use value above for first pixel in row
} else {
switch (pred) {
case 0:
Px = 0; break; // No prediction... should not be used
case 1:
Px = left; break;
case 2:
Px = lastrow[col]; break;
case 3:
Px = lastrow[col-1];break;
case 4:
Px = left + lastrow[col] - lastrow[col-1];break;
case 5:
Px = left + ((lastrow[col] - lastrow[col-1])>>1);break;
case 6:
Px = lastrow[col] + ((left - lastrow[col-1])>>1);break;
case 7:
Px = (left + lastrow[col])>>1;break;
}
}
diff = nextdiff(self,Px);
left = Px + diff;
//printf("%d %d %d\n",c,diff,left);
int linear;
if (self->linearize) {
if (left>self->linlen) return LJ92_ERROR_CORRUPT;
linear = self->linearize[left];
} else
linear = left;
thisrow[col] = left;
out[c++] = linear;
if (++col==self->x) {
col = 0;
row++;
u16* temprow = lastrow;
lastrow = thisrow;
thisrow = temprow;
}
if (--write==0) {
out += self->skiplen;
write = self->writelen;
}
if (self->ix >= self->datalen+2) break;
}
if (c >= pixels) ret = LJ92_ERROR_NONE;
/*for (int h=0;h<17;h++) {
printf("ssss:%d=%d (%f)\n",h,self->sssshist[h],(float)self->sssshist[h]/(float)(pixels));
}*/
return ret;
}
static int parseImage(ljp* self) {
int ret = LJ92_ERROR_NONE;
while (1) {
int nextMarker = find(self);
if (nextMarker == 0xc4)
ret = parseHuff(self);
else if (nextMarker == 0xc3)
ret = parseSof3(self);
else if (nextMarker == 0xfe)// Comment
ret = parseBlock(self,nextMarker);
else if (nextMarker == 0xd9) // End of image
break;
else if (nextMarker == 0xda) {
self->scanstart = self->ix;
ret = LJ92_ERROR_NONE;
break;
} else if (nextMarker == -1) {
ret = LJ92_ERROR_CORRUPT;
break;
} else
ret = parseBlock(self,nextMarker);
if (ret != LJ92_ERROR_NONE) break;
}
return ret;
}
static int findSoI(ljp* self) {
int ret = LJ92_ERROR_CORRUPT;
if (find(self)==0xd8)
ret = parseImage(self);
return ret;
}
static void free_memory(ljp* self) {
#ifdef SLOW_HUFF
free(self->maxcode);
self->maxcode = NULL;
free(self->mincode);
self->mincode = NULL;
free(self->valptr);
self->valptr = NULL;
free(self->huffval);
self->huffval = NULL;
free(self->huffsize);
self->huffsize = NULL;
free(self->huffcode);
self->huffcode = NULL;
#else
free(self->hufflut);
self->hufflut = NULL;
#endif
free(self->rowcache);
self->rowcache = NULL;
}
int lj92_open(lj92* lj,
uint8_t* data, int datalen,
int* width,int* height, int* bitdepth) {
ljp* self = (ljp*)calloc(sizeof(ljp),1);
if (self==NULL) return LJ92_ERROR_NO_MEMORY;
self->data = (u8*)data;
self->dataend = self->data + datalen;
self->datalen = datalen;
int ret = findSoI(self);
if (ret == LJ92_ERROR_NONE) {
u16* rowcache = (u16*)calloc(self->x * 2,sizeof(u16));
if (rowcache == NULL) ret = LJ92_ERROR_NO_MEMORY;
else {
self->rowcache = rowcache;
self->outrow[0] = rowcache;
self->outrow[1] = &rowcache[self->x];
}
}
if (ret != LJ92_ERROR_NONE) { // Failed, clean up
*lj = NULL;
free_memory(self);
free(self);
} else {
*width = self->x;
*height = self->y;
*bitdepth = self->bits;
*lj = self;
}
return ret;
}
int lj92_decode(lj92 lj,
uint16_t* target,int writeLength, int skipLength,
uint16_t* linearize,int linearizeLength) {
int ret = LJ92_ERROR_NONE;
ljp* self = lj;
if (self == NULL) return LJ92_ERROR_BAD_HANDLE;
self->image = target;
self->writelen = writeLength;
self->skiplen = skipLength;
self->linearize = linearize;
self->linlen = linearizeLength;
ret = parseScan(self);
return ret;
}
void lj92_close(lj92 lj) {
ljp* self = lj;
if (self != NULL)
free_memory(self);
free(self);
}

68
rtengine/lj92.h Normal file
View File

@@ -0,0 +1,68 @@
/*
lj92.h
(c) Andrew Baldwin 2014
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef LJ92_H
#define LJ92_H
#ifdef __cplusplus
extern "C"
{
#endif
enum LJ92_ERRORS {
LJ92_ERROR_NONE = 0,
LJ92_ERROR_CORRUPT = -1,
LJ92_ERROR_NO_MEMORY = -2,
LJ92_ERROR_BAD_HANDLE = -3,
LJ92_ERROR_TOO_WIDE = -4,
};
typedef struct _ljp* lj92;
/* Parse a lossless JPEG (1992) structure returning
* - a handle that can be used to decode the data
* - width/height/bitdepth of the data
* Returns status code.
* If status == LJ92_ERROR_NONE, handle must be closed with lj92_close
*/
int lj92_open(lj92* lj, // Return handle here
uint8_t* data,int datalen, // The encoded data
int* width,int* height,int* bitdepth); // Width, height and bitdepth
/* Release a decoder object */
void lj92_close(lj92 lj);
/*
* Decode previously opened lossless JPEG (1992) into a 2D tile of memory
* Starting at target, write writeLength 16bit values, then skip 16bit skipLength value before writing again
* If linearize is not NULL, use table at linearize to convert data values from output value to target value
* Data is only correct if LJ92_ERROR_NONE is returned
*/
int lj92_decode(lj92 lj,
uint16_t* target, int writeLength, int skipLength, // The image is written to target as a tile
uint16_t* linearize, int linearizeLength); // If not null, linearize the data using this table
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -64,7 +64,7 @@ std::vector<Glib::ustring> listSubDirs (const Glib::RefPtr<Gio::File>& dir, bool
} catch (const Glib::Exception& exception) {
if (options.rtSettings.verbose) {
std::cerr << exception.what () << std::endl;
std::cerr << exception.what().c_str() << std::endl;
}
}

View File

@@ -1208,7 +1208,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel()
startupdir = Gtk::manage(new Gtk::Entry());
Gtk::Button* sdselect = Gtk::manage(new Gtk::Button());
sdselect->set_image (*Gtk::manage (new RTImage ("folder-open.png")));
sdselect->set_image (*Gtk::manage (new RTImage ("folder-open-small.png")));
Gtk::RadioButton::Group opts = sdcurrent->get_group();
sdlast->set_group(opts);
@@ -1277,20 +1277,26 @@ Gtk::Widget* Preferences::getFileBrowserPanel()
Gtk::Frame* frmnu = Gtk::manage(new Gtk::Frame(M("PREFERENCES_MENUOPTIONS")));
Gtk::Grid* menuGrid = Gtk::manage(new Gtk::Grid());
menuGrid->get_style_context()->add_class("grid-spacing");
setExpandAlignProperties(menuGrid, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
ckbmenuGroupRank = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_MENUGROUPRANK")));
setExpandAlignProperties(ckbmenuGroupRank, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
ckbmenuGroupLabel = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_MENUGROUPLABEL")));
ckbmenuGroupFileOperations = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_MENUGROUPFILEOPERATIONS")));
setExpandAlignProperties(ckbmenuGroupFileOperations, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
ckbmenuGroupProfileOperations = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_MENUGROUPPROFILEOPERATIONS")));
ckbmenuGroupExtProg = Gtk::manage(new Gtk::CheckButton(M("PREFERENCES_MENUGROUPEXTPROGS")));
Gtk::VBox* vbmnu = Gtk::manage(new Gtk::VBox());
menuGrid->attach (*ckbmenuGroupRank, 0, 0, 1, 1);
menuGrid->attach (*ckbmenuGroupLabel, 1, 0, 1, 1);
menuGrid->attach (*ckbmenuGroupFileOperations, 0, 1, 1, 1);
menuGrid->attach (*ckbmenuGroupProfileOperations, 1, 1, 1, 1);
menuGrid->attach (*ckbmenuGroupExtProg, 0, 2, 2, 1);
vbmnu->pack_start(*ckbmenuGroupRank, Gtk::PACK_SHRINK, 0);
vbmnu->pack_start(*ckbmenuGroupLabel, Gtk::PACK_SHRINK, 0);
vbmnu->pack_start(*ckbmenuGroupFileOperations, Gtk::PACK_SHRINK, 0);
vbmnu->pack_start(*ckbmenuGroupProfileOperations, Gtk::PACK_SHRINK, 0);
vbmnu->pack_start(*ckbmenuGroupExtProg, Gtk::PACK_SHRINK, 0);
frmnu->add(*vbmnu);
frmnu->add (*menuGrid);
Gtk::Frame* fre = Gtk::manage(new Gtk::Frame(M("PREFERENCES_PARSEDEXT")));
@@ -1362,7 +1368,8 @@ Gtk::Widget* Preferences::getFileBrowserPanel()
// Separation is needed so that a button is not accidentally clicked when one wanted
// to click a spinbox. Ideally, the separation wouldn't require attaching a widget, but how?
Gtk::Label *separator = Gtk::manage (new Gtk::Label());
Gtk::HSeparator *cacheSeparator = Gtk::manage (new Gtk::HSeparator());
cacheSeparator->get_style_context()->add_class("grid-row-separator");
Gtk::Label* clearThumbsLbl = Gtk::manage (new Gtk::Label(M("PREFERENCES_CACHECLEAR_ALLBUTPROFILES")));
setExpandAlignProperties(clearThumbsLbl, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
@@ -1380,7 +1387,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel()
cacheGrid->attach (*maxThumbHeightSB, 1, 0, 1, 1);
cacheGrid->attach (*maxCacheEntriesLbl, 0, 1, 1, 1);
cacheGrid->attach (*maxCacheEntriesSB, 1, 1, 1, 1);
cacheGrid->attach (*separator, 0, 2, 2, 1);
cacheGrid->attach (*cacheSeparator, 0, 2, 2, 1);
cacheGrid->attach (*clearThumbsLbl, 0, 3, 1, 1);
cacheGrid->attach (*clearThumbsBtn, 1, 3, 1, 1);
if (moptions.saveParamsCache) {