|
rpm-build |
d2b433 |
/*
|
|
rpm-build |
d2b433 |
* libopenraw - olympusdecompressor.cpp
|
|
rpm-build |
d2b433 |
*
|
|
rpm-build |
d2b433 |
* Copyright (C) 2011-2016 Hubert Figuiere
|
|
rpm-build |
d2b433 |
* Olympus Decompression copied from RawSpeed
|
|
rpm-build |
d2b433 |
* Copyright (C) 2009 Klaus Post
|
|
rpm-build |
d2b433 |
*
|
|
rpm-build |
d2b433 |
* This library is free software: you can redistribute it and/or
|
|
rpm-build |
d2b433 |
* modify it under the terms of the GNU Lesser General Public License
|
|
rpm-build |
d2b433 |
* as published by the Free Software Foundation, either version 3 of
|
|
rpm-build |
d2b433 |
* the License, or (at your option) any later version.
|
|
rpm-build |
d2b433 |
*
|
|
rpm-build |
d2b433 |
* This library is distributed in the hope that it will be useful,
|
|
rpm-build |
d2b433 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
rpm-build |
d2b433 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
rpm-build |
d2b433 |
* Lesser General Public License for more details.
|
|
rpm-build |
d2b433 |
*
|
|
rpm-build |
d2b433 |
* You should have received a copy of the GNU Lesser General Public
|
|
rpm-build |
d2b433 |
* License along with this library. If not, see
|
|
rpm-build |
d2b433 |
* <http://www.gnu.org/licenses/>.
|
|
rpm-build |
d2b433 |
*/
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
#include <stdlib.h>
|
|
rpm-build |
d2b433 |
#include <string.h>
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
#include <algorithm>
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
#include "rawdata.hpp"
|
|
rpm-build |
d2b433 |
#include "olympusdecompressor.hpp"
|
|
rpm-build |
d2b433 |
#include "bititerator.hpp"
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
namespace OpenRaw {
|
|
rpm-build |
d2b433 |
namespace Internals {
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
static void decompressOlympus(const uint8_t* buffer, size_t size, uint8_t* data,
|
|
rpm-build |
d2b433 |
uint32_t w, uint32_t h);
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
// decompression ported from RawSpeed.
|
|
rpm-build |
d2b433 |
static void decompressOlympus(const uint8_t* buffer, size_t size, uint8_t* data,
|
|
rpm-build |
d2b433 |
uint32_t w, uint32_t h)
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
int nbits, sign, low, high, i, wo0, n, nw0, wo1, nw1;
|
|
rpm-build |
d2b433 |
int acarry0[3], acarry1[3], pred, diff;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
int pitch = w * 2; //(((w * 2/*bpp*/) + 15) / 16) * 16; // TODO make that
|
|
rpm-build |
d2b433 |
//part of the outer datas
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
/* Build a table to quickly look up "high" value */
|
|
rpm-build |
d2b433 |
char bittable[4096];
|
|
rpm-build |
d2b433 |
for (i = 0; i < 4096; i++) {
|
|
rpm-build |
d2b433 |
int b = i;
|
|
rpm-build |
d2b433 |
for (high = 0; high < 12; high++) {
|
|
rpm-build |
d2b433 |
if ((b >> (11 - high)) & 1) {
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
bittable[i] = high;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
wo0 = nw0 = wo1 = nw1 = 0;
|
|
rpm-build |
d2b433 |
buffer += 7;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
BitIterator bits(buffer, size - 7);
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
for (uint32_t y = 0; y < h; y++) {
|
|
rpm-build |
d2b433 |
memset(acarry0, 0, sizeof acarry0);
|
|
rpm-build |
d2b433 |
memset(acarry1, 0, sizeof acarry1);
|
|
rpm-build |
d2b433 |
uint16_t* dest = (uint16_t*)&data[y * pitch];
|
|
rpm-build |
d2b433 |
for (uint32_t x = 0; x < w; x++) {
|
|
rpm-build |
d2b433 |
// bits.checkPos();
|
|
rpm-build |
d2b433 |
// bits.fill();
|
|
rpm-build |
d2b433 |
i = 2 * (acarry0[2] < 3);
|
|
rpm-build |
d2b433 |
for (nbits = 2 + i; (uint16_t)acarry0[0] >> (nbits + i); nbits++) {
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
uint32_t b = bits.peek(15);
|
|
rpm-build |
d2b433 |
sign = (b >> 14) * -1;
|
|
rpm-build |
d2b433 |
low = (b >> 12) & 3;
|
|
rpm-build |
d2b433 |
high = bittable[b & 4095];
|
|
rpm-build |
d2b433 |
// Skip bits used above.
|
|
rpm-build |
d2b433 |
bits.skip(std::min(12 + 3, high + 1 + 3));
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
if (high == 12) {
|
|
rpm-build |
d2b433 |
high = bits.get(16 - nbits) >> 1;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
acarry0[0] = (high << nbits) | bits.get(nbits);
|
|
rpm-build |
d2b433 |
diff = (acarry0[0] ^ sign) + acarry0[1];
|
|
rpm-build |
d2b433 |
acarry0[1] = (diff * 3 + acarry0[1]) >> 5;
|
|
rpm-build |
d2b433 |
acarry0[2] = acarry0[0] > 16 ? 0 : acarry0[2] + 1;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
if (y < 2 || x < 2) {
|
|
rpm-build |
d2b433 |
if (y < 2 && x < 2) {
|
|
rpm-build |
d2b433 |
pred = 0;
|
|
rpm-build |
d2b433 |
} else if (y < 2) {
|
|
rpm-build |
d2b433 |
pred = wo0;
|
|
rpm-build |
d2b433 |
} else {
|
|
rpm-build |
d2b433 |
pred = dest[-pitch + ((int)x)];
|
|
rpm-build |
d2b433 |
nw0 = pred;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
dest[x] = pred + ((diff << 2) | low);
|
|
rpm-build |
d2b433 |
// Set predictor
|
|
rpm-build |
d2b433 |
wo0 = dest[x];
|
|
rpm-build |
d2b433 |
} else {
|
|
rpm-build |
d2b433 |
n = dest[-pitch + ((int)x)];
|
|
rpm-build |
d2b433 |
if (((wo0 < nw0) & (nw0 < n)) | ((n < nw0) & (nw0 < wo0))) {
|
|
rpm-build |
d2b433 |
if (abs(wo0 - nw0) > 32 || abs(n - nw0) > 32) {
|
|
rpm-build |
d2b433 |
pred = wo0 + n - nw0;
|
|
rpm-build |
d2b433 |
} else {
|
|
rpm-build |
d2b433 |
pred = (wo0 + n) >> 1;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
} else {
|
|
rpm-build |
d2b433 |
pred = abs(wo0 - nw0) > abs(n - nw0) ? wo0 : n;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
dest[x] = pred + ((diff << 2) | low);
|
|
rpm-build |
d2b433 |
// Set predictors
|
|
rpm-build |
d2b433 |
wo0 = dest[x];
|
|
rpm-build |
d2b433 |
nw0 = n;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
// _ASSERTE(0 == dest[x] >> 12) ;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
// ODD PIXELS
|
|
rpm-build |
d2b433 |
x += 1;
|
|
rpm-build |
d2b433 |
// bits.checkPos();
|
|
rpm-build |
d2b433 |
// bits.fill();
|
|
rpm-build |
d2b433 |
i = 2 * (acarry1[2] < 3);
|
|
rpm-build |
d2b433 |
for (nbits = 2 + i; (uint16_t)acarry1[0] >> (nbits + i); nbits++) {
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
b = bits.peek(15);
|
|
rpm-build |
d2b433 |
sign = (b >> 14) * -1;
|
|
rpm-build |
d2b433 |
low = (b >> 12) & 3;
|
|
rpm-build |
d2b433 |
high = bittable[b & 4095];
|
|
rpm-build |
d2b433 |
// Skip bits used above.
|
|
rpm-build |
d2b433 |
bits.skip(std::min(12 + 3, high + 1 + 3));
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
if (high == 12) {
|
|
rpm-build |
d2b433 |
high = bits.get(16 - nbits) >> 1;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
acarry1[0] = (high << nbits) | bits.get(nbits);
|
|
rpm-build |
d2b433 |
diff = (acarry1[0] ^ sign) + acarry1[1];
|
|
rpm-build |
d2b433 |
acarry1[1] = (diff * 3 + acarry1[1]) >> 5;
|
|
rpm-build |
d2b433 |
acarry1[2] = acarry1[0] > 16 ? 0 : acarry1[2] + 1;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
if (y < 2 || x < 2) {
|
|
rpm-build |
d2b433 |
if (y < 2 && x < 2) {
|
|
rpm-build |
d2b433 |
pred = 0;
|
|
rpm-build |
d2b433 |
} else if (y < 2) {
|
|
rpm-build |
d2b433 |
pred = wo1;
|
|
rpm-build |
d2b433 |
} else {
|
|
rpm-build |
d2b433 |
pred = dest[-pitch + ((int)x)];
|
|
rpm-build |
d2b433 |
nw1 = pred;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
dest[x] = pred + ((diff << 2) | low);
|
|
rpm-build |
d2b433 |
// Set predictor
|
|
rpm-build |
d2b433 |
wo1 = dest[x];
|
|
rpm-build |
d2b433 |
} else {
|
|
rpm-build |
d2b433 |
n = dest[-pitch + ((int)x)];
|
|
rpm-build |
d2b433 |
if (((wo1 < nw1) & (nw1 < n)) | ((n < nw1) & (nw1 < wo1))) {
|
|
rpm-build |
d2b433 |
if (abs(wo1 - nw1) > 32 || abs(n - nw1) > 32) {
|
|
rpm-build |
d2b433 |
pred = wo1 + n - nw1;
|
|
rpm-build |
d2b433 |
} else {
|
|
rpm-build |
d2b433 |
pred = (wo1 + n) >> 1;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
} else {
|
|
rpm-build |
d2b433 |
pred = abs(wo1 - nw1) > abs(n - nw1) ? wo1 : n;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
dest[x] = pred + ((diff << 2) | low);
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
// Set predictors
|
|
rpm-build |
d2b433 |
wo1 = dest[x];
|
|
rpm-build |
d2b433 |
nw1 = n;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
// _ASSERTE(0 == dest[x] >> 12) ;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
RawDataPtr OlympusDecompressor::decompress()
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
RawDataPtr output(new RawData);
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
output->allocData(m_w * m_h * 2);
|
|
rpm-build |
d2b433 |
decompressOlympus(m_buffer, m_size, (uint8_t*)output->data(), m_w, m_h);
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
// hardcoded 12bits values
|
|
rpm-build |
d2b433 |
output->setBpc(12);
|
|
rpm-build |
d2b433 |
output->setWhiteLevel((1 << 12) - 1);
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
return output;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|