File libopenraw-orf-thumbnail.patch of Package libopenraw

From 9be26e10ecbf89ce99b294906be1208d5a484c7e Mon Sep 17 00:00:00 2001
From: Hubert Figuiere <hub@figuiere.net>
Date: Fri, 18 Mar 2011 23:41:38 -0700
Subject: [PATCH 1/2] Better support for compression ID
 Implement Olympus decompression (with decompressor borrowed from RawSpeed)

---
 AUTHORS                     |    3 +
 lib/Makefile.am             |    2 +
 lib/bititerator.cpp         |   30 +++++--
 lib/bititerator.h           |    4 +-
 lib/dngfile.cpp             |    2 +-
 lib/ifd.h                   |    4 +-
 lib/ifdfile.cpp             |   14 +++-
 lib/ifdfile.h               |    7 ++
 lib/olympusdecompressor.cpp |  205 +++++++++++++++++++++++++++++++++++++++++++
 lib/olympusdecompressor.h   |   51 +++++++++++
 lib/orffile.cpp             |   28 +++++-
 lib/orffile.h               |    5 +
 lib/peffile.cpp             |    2 +-
 13 files changed, 338 insertions(+), 19 deletions(-)
 create mode 100644 lib/olympusdecompressor.cpp
 create mode 100644 lib/olympusdecompressor.h

Index: libopenraw-0.0.8/AUTHORS
===================================================================
--- libopenraw-0.0.8.orig/AUTHORS
+++ libopenraw-0.0.8/AUTHORS
@@ -4,6 +4,9 @@ MRW support:       Bradley Broom
 NEF decompression: Rafael EspĂ­ndola
 Python bindings:   Brian Quinlan
 
+Indirect contributors:
+Klaus Post for code from RawSpeed.
+
 Sponsors:
 Novell sponsored time to work on libopenraw as part of their ITO programme 
 (and HackWeek in February 2008)
Index: libopenraw-0.0.8/lib/Makefile.am
===================================================================
--- libopenraw-0.0.8.orig/lib/Makefile.am
+++ libopenraw-0.0.8/lib/Makefile.am
@@ -32,6 +32,7 @@ noinst_HEADERS = or_debug.h \
 	ljpegdecompressor.h \
 	ljpegdecompressor_priv.h \
 	crwdecompressor.h \
+	olympusdecompressor.h \
 	exception.h \
 	endianutils.h \
 	metavalue.h \
@@ -83,6 +84,7 @@ libopenraw_la_SOURCES = \
 	decompressor.cpp \
 	ljpegdecompressor.cpp \
 	crwdecompressor.cpp \
+	olympusdecompressor.cpp \
 	metavalue.cpp \
 	unpack.cpp \
 	bimedian_demosaic.cpp demosaic.h \
Index: libopenraw-0.0.8/lib/bititerator.cpp
===================================================================
--- libopenraw-0.0.8.orig/lib/bititerator.cpp
+++ libopenraw-0.0.8/lib/bititerator.cpp
@@ -20,6 +20,7 @@
  */
 
 #include <assert.h>
+#include <algorithm>
 #include "bititerator.h"
 
 namespace OpenRaw {
@@ -53,22 +54,35 @@ void BitIterator::load(size_t numBits)
 
 uint32_t BitIterator::get(size_t n)
 {
-	assert(n <= 25);
+	uint32_t ret = peek(n);
+
+	skip(n);
 
+	return ret;
+}
+
+uint32_t BitIterator::peek(size_t n)
+{
+	assert(n <= 25);
+	
 	if (n == 0)
 		return 0;
-
+	
 	if (n > m_bitsOnBuffer)
 		load(n - m_bitsOnBuffer);
-
+	
 	assert(n <= m_bitsOnBuffer);
+	
+	return m_bitBuffer >> (32 - n);
+}
 
-	uint32_t ret = m_bitBuffer >> (32 - n);
-	m_bitsOnBuffer -= n;
-	m_bitBuffer <<= n;
-
-	return ret;
+void BitIterator::skip(size_t n)
+{
+	size_t num_bits = std::min(n, m_bitsOnBuffer);
+	m_bitsOnBuffer -= num_bits;
+	m_bitBuffer <<= num_bits;
 }
 
+	
 }
 }
Index: libopenraw-0.0.8/lib/bititerator.h
===================================================================
--- libopenraw-0.0.8.orig/lib/bititerator.h
+++ libopenraw-0.0.8/lib/bititerator.h
@@ -31,12 +31,14 @@ namespace Internals {
 class BitIterator {
 	const uint8_t* m_p;
 	uint32_t m_bitBuffer;
-	uint8_t m_bitsOnBuffer;
+	size_t m_bitsOnBuffer;
 	void load(size_t numBits);
 
  public:
 	BitIterator(const void *);
 	uint32_t get(size_t);
+	uint32_t peek(size_t);
+	void skip(size_t);
 };
 
 }
Index: libopenraw-0.0.8/lib/dngfile.cpp
===================================================================
--- libopenraw-0.0.8.orig/lib/dngfile.cpp
+++ libopenraw-0.0.8/lib/dngfile.cpp
@@ -89,7 +89,7 @@ namespace OpenRaw {
 				if(ret == OR_ERROR_NONE) {
 					uint16_t compression = 0;
 					if (m_cfaIfd->getValue(IFD::EXIF_TAG_COMPRESSION, compression) &&
-						compression == 7) {
+						compression == IFD::COMPRESS_LJPEG) {
 						// if the option is not set, decompress
 						if ((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
 							boost::scoped_ptr<IO::Stream> s(new IO::MemStream(data.data(),
Index: libopenraw-0.0.8/lib/ifd.h
===================================================================
--- libopenraw-0.0.8.orig/lib/ifd.h
+++ libopenraw-0.0.8/lib/ifd.h
@@ -69,8 +69,10 @@ namespace OpenRaw {
 			typedef enum {
 				COMPRESS_NONE = 1,
 				COMPRESS_JPEG = 6,
+				COMPRESS_LJPEG = 7, /**< Lossless JPEG, see DNG */
 				COMPRESS_NIKON_PACK = 32769,
-				COMPRESS_NIKON_QUANTIZED = 34713
+				COMPRESS_NIKON_QUANTIZED = 34713,
+				COMPRESS_CUSTOM = 65535 /**< The value everybody seems to use */
 			} TiffCompress;
 		}
 	}
Index: libopenraw-0.0.8/lib/ifdfile.cpp
===================================================================
--- libopenraw-0.0.8.orig/lib/ifdfile.cpp
+++ libopenraw-0.0.8/lib/ifdfile.cpp
@@ -339,6 +339,15 @@ MetaValue *IFDFile::_getMetaValue(int32_
     }
     return val;
 }
+	
+/** by default we don't translate the compression 
+ */
+uint32_t IFDFile::_translateCompressionType(IFD::TiffCompress tiffCompression)
+{
+	return (uint32_t)tiffCompression;
+}
+
+
 
 
 namespace {
@@ -541,14 +550,15 @@ static RawData::CfaPattern _getCfaPatter
         return OR_ERROR_NOT_FOUND;
     }
 
-    uint32_t compression = 0;
-    got_it = dir->getIntegerValue(IFD::EXIF_TAG_COMPRESSION, compression);
+    uint16_t tiffCompression = 0;
+    got_it = dir->getValue(IFD::EXIF_TAG_COMPRESSION, tiffCompression);
     if(!got_it)
     {
         Trace(DEBUG1) << "Compression type not found\n";
     }
     BitmapData::DataType data_type = OR_DATA_TYPE_NONE;
 
+	uint32_t compression = _translateCompressionType((IFD::TiffCompress)tiffCompression);
     switch(compression) 
     {
     case IFD::COMPRESS_NONE:
Index: libopenraw-0.0.8/lib/ifdfile.h
===================================================================
--- libopenraw-0.0.8.orig/lib/ifdfile.h
+++ libopenraw-0.0.8/lib/ifdfile.h
@@ -102,6 +102,13 @@ namespace OpenRaw {
 
 			virtual MetaValue *_getMetaValue(int32_t meta_index);
 
+			/** Translate the compression type from the tiff type (16MSB) 
+			 * to the RAW specific type if needed (16MSB)
+			 * @param tiffCompression the 16 bits value from TIFF
+			 * @return the actually value. Anything >= 2^16 is specific the RAW type
+			 */
+			virtual uint32_t _translateCompressionType(IFD::TiffCompress tiffCompression);
+ 
 			IFDDir::Ref       m_cfaIfd;  /**< the IFD for the CFA */
 			IFDDir::Ref       m_mainIfd; /**< the IFD for the main image 
 										  * does not necessarily reference 
Index: libopenraw-0.0.8/lib/olympusdecompressor.cpp
===================================================================
--- /dev/null
+++ libopenraw-0.0.8/lib/olympusdecompressor.cpp
@@ -0,0 +1,207 @@
+/*
+ * libopenraw - olympusdecompressor.cpp
+ *
+ * Copyright (C) 2011 Hubert Figuiere
+ * Olympus Decompression copied from RawSpeed
+ * Copyright (C) 2009 Klaus Post
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include <libopenraw++/rawdata.h>
+
+#include "io/stream.h"
+#include "olympusdecompressor.h"
+#include "bititerator.h"
+
+
+namespace OpenRaw {
+namespace Internals {
+
+static void decompressOlympus(const uint8_t* buffer, uint8_t* data, uint32_t w, uint32_t h);
+
+// decompression ported from RawSpeed.
+static void decompressOlympus(const uint8_t* buffer, uint8_t* data, uint32_t w, uint32_t h)
+{
+	int nbits, sign, low, high, i, wo0, n, nw0, wo1, nw1;
+	int acarry0[3], acarry1[3], pred, diff;
+
+	int pitch = w * 2; //(((w * 2/*bpp*/) + 15) / 16) * 16; // TODO make that part of the outer datas
+
+	/* Build a table to quickly look up "high" value */
+	char bittable[4096];
+	for (i = 0; i < 4096; i++) {
+		int b = i;
+		for (high = 0; high < 12; high++) {
+			if ((b>>(11-high))&1) {
+				break;
+			}
+		}
+		bittable[i] = high;
+	}
+	wo0 = nw0 = wo1 = nw1 = 0;
+	buffer += 7;
+	
+	BitIterator bits(buffer);
+
+	for (uint32_t y = 0; y < h; y++) {
+		memset(acarry0, 0, sizeof acarry0);
+		memset(acarry1, 0, sizeof acarry1);
+		uint16_t* dest = (uint16_t*) & data[y*pitch];
+		for (uint32_t x = 0; x < w; x++) {
+//			bits.checkPos();
+//			bits.fill();
+			i = 2 * (acarry0[2] < 3);
+			for (nbits = 2 + i; (uint16_t) acarry0[0] >> (nbits + i); nbits++) {
+				
+			}
+
+			uint32_t b = bits.peek(15);
+			sign = (b >> 14) * -1;
+			low  = (b >> 12) & 3;
+			high = bittable[b&4095];
+			// Skip bits used above.
+			bits.skip(std::min(12+3, high + 1 + 3));
+
+			if (high == 12) {
+				high = bits.get(16 - nbits) >> 1;
+			}
+
+			acarry0[0] = (high << nbits) | bits.get(nbits);
+			diff = (acarry0[0] ^ sign) + acarry0[1];
+			acarry0[1] = (diff * 3 + acarry0[1]) >> 5;
+			acarry0[2] = acarry0[0] > 16 ? 0 : acarry0[2] + 1;
+
+			if (y < 2 || x < 2) {
+				if (y < 2 && x < 2) {
+					pred = 0;
+				}
+				else if (y < 2) {
+					pred = wo0;
+				}
+				else { 
+					pred = dest[-pitch+((int)x)];
+					nw0 = pred;
+				}
+				dest[x] = pred + ((diff << 2) | low);
+				// Set predictor
+				wo0 = dest[x];
+			} 
+			else {
+				n  = dest[-pitch+((int)x)];
+				if (((wo0 < nw0) & (nw0 < n)) | ((n < nw0) & (nw0 < wo0))) {
+					if (abs(wo0 - nw0) > 32 || abs(n - nw0) > 32) {
+						pred = wo0 + n - nw0;
+					}
+					else {
+						pred = (wo0 + n) >> 1;
+					}
+				} 
+				else {
+					pred = abs(wo0 - nw0) > abs(n - nw0) ? wo0 : n;
+				}
+
+				dest[x] = pred + ((diff << 2) | low);
+				// Set predictors
+				wo0 = dest[x];
+				nw0 = n;
+			}
+		//      _ASSERTE(0 == dest[x] >> 12) ;
+
+			// ODD PIXELS
+			x += 1;
+//			bits.checkPos();
+//			bits.fill();
+			i = 2 * (acarry1[2] < 3);
+			for (nbits = 2 + i; (uint16_t) acarry1[0] >> (nbits + i); nbits++) {
+				
+			}
+			b = bits.peek(15);
+			sign = (b >> 14) * -1;
+			low  = (b >> 12) & 3;
+			high = bittable[b&4095];
+			// Skip bits used above.
+			bits.skip(std::min(12+3, high + 1 + 3));
+
+			if (high == 12) {
+				high = bits.get(16 - nbits) >> 1;
+			}
+
+			acarry1[0] = (high << nbits) | bits.get(nbits);
+			diff = (acarry1[0] ^ sign) + acarry1[1];
+			acarry1[1] = (diff * 3 + acarry1[1]) >> 5;
+			acarry1[2] = acarry1[0] > 16 ? 0 : acarry1[2] + 1;
+
+			if (y < 2 || x < 2) {
+				if (y < 2 && x < 2) {
+					pred = 0;
+				}
+				else if (y < 2) {
+					pred = wo1;
+				}
+				else { 
+					pred = dest[-pitch+((int)x)];
+					nw1 = pred;
+				}
+				dest[x] = pred + ((diff << 2) | low);
+				// Set predictor
+				wo1 = dest[x];
+			} 
+			else {
+				n  = dest[-pitch+((int)x)];
+				if (((wo1 < nw1) & (nw1 < n)) | ((n < nw1) & (nw1 < wo1))) {
+					if (abs(wo1 - nw1) > 32 || abs(n - nw1) > 32) {
+						pred = wo1 + n - nw1;
+					}
+					else {
+						pred = (wo1 + n) >> 1;
+					}
+				} 
+				else {
+					pred = abs(wo1 - nw1) > abs(n - nw1) ? wo1 : n;
+				}
+
+				dest[x] = pred + ((diff << 2) | low);
+
+				// Set predictors
+				wo1 = dest[x];
+				nw1 = n;
+			}
+	//      _ASSERTE(0 == dest[x] >> 12) ;
+		}
+	}
+}
+
+RawData *OlympusDecompressor::decompress(RawData *in)
+{
+	RawData *output;
+	if(in) {
+		output = in;
+	}
+	else {
+		output = new RawData;
+	}
+	
+	output->allocData(m_w * m_h * 2);
+	decompressOlympus(m_buffer, (uint8_t*)output->data(), m_w, m_h);
+	
+	return output;
+}
+
+
+}
+}
Index: libopenraw-0.0.8/lib/olympusdecompressor.h
===================================================================
--- /dev/null
+++ libopenraw-0.0.8/lib/olympusdecompressor.h
@@ -0,0 +1,51 @@
+/*
+ * libopenraw - olympusdecompressor.cpp
+ *
+ * Copyright (C) 2011 Hubert Figuiere
+ *
+ * This library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __OPENRAW_OLYMPUSDECOMPRESSOR_H__
+#define __OPENRAW_OLYMPUSDECOMPRESSOR_H__
+
+#include "decompressor.h"
+
+namespace OpenRaw {
+namespace Internals {
+
+class OlympusDecompressor
+	: public Decompressor
+{
+public:
+	OlympusDecompressor(const uint8_t *buffer,
+				 RawContainer * container, uint32_t w, uint32_t h)
+	: Decompressor(NULL, container)
+	, m_buffer(buffer)
+	, m_h(h)
+	, m_w(w)
+	{
+	}
+	virtual RawData *decompress(RawData *in = NULL);
+private:
+	const uint8_t *m_buffer;
+	uint32_t m_h;
+	uint32_t m_w;
+};
+
+}
+}
+#endif
Index: libopenraw-0.0.8/lib/orffile.cpp
===================================================================
--- libopenraw-0.0.8.orig/lib/orffile.cpp
+++ libopenraw-0.0.8/lib/orffile.cpp
@@ -27,6 +27,7 @@
 #include "ifddir.h"
 #include "ifdentry.h"
 #include "orfcontainer.h"
+#include "olympusdecompressor.h"
 #include "io/file.h"
 
 using namespace Debug;
@@ -103,19 +104,27 @@ namespace OpenRaw {
 				// ORF files seems to be marked as uncompressed even if they are.
 				uint32_t x = data.x();
 				uint32_t y = data.y();
-				uint16_t compression = 0;
+				uint32_t compression = 0;
 				if(data.size() < x * y * 2) {
-                    compression = 65535;
-                    data.setCompression(65535);
+                    compression = ORF_COMPRESSION;
+                    data.setCompression(ORF_COMPRESSION);
 					data.setDataType(OR_DATA_TYPE_COMPRESSED_CFA);
 				}
                 else {
                     compression = data.compression();
                 }
                 switch(compression) {
-                case 65535:
+                case ORF_COMPRESSION:
                     if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
-                        // TODO decompress
+						OlympusDecompressor decomp((const uint8_t*)data.data(), m_container, x, y);
+						RawData *dData = decomp.decompress(NULL);
+						if (dData != NULL) {
+							dData->setCfaPattern(data.cfaPattern());
+							data.swap(*dData);
+							data.setDataType(OR_DATA_TYPE_CFA);
+							data.setDimensions(x, y);
+							delete dData;
+						}
                     }
 					break;
 				default:
@@ -124,6 +133,15 @@ namespace OpenRaw {
 			}
 			return err;
 		}
+	
+uint32_t OrfFile::_translateCompressionType(IFD::TiffCompress tiffCompression)
+{
+	if(tiffCompression == IFD::COMPRESS_CUSTOM) {
+		return ORF_COMPRESSION;
+	}
+	return (uint32_t)tiffCompression;
+}
+
 
 }
 }
Index: libopenraw-0.0.8/lib/orffile.h
===================================================================
--- libopenraw-0.0.8.orig/lib/orffile.h
+++ libopenraw-0.0.8/lib/orffile.h
@@ -43,11 +43,16 @@ namespace OpenRaw {
 			OrfFile(IO::Stream *);
 			virtual ~OrfFile();
 
+			enum {
+				ORF_COMPRESSION = 0x10000
+			};
+ 
 		protected:
 			virtual IFDDir::Ref  _locateCfaIfd();
 			virtual IFDDir::Ref  _locateMainIfd();
 
 			virtual ::or_error _getRawData(RawData & data, uint32_t options);
+			virtual uint32_t _translateCompressionType(IFD::TiffCompress tiffCompression);
 		private:
 			static RawFile::TypeId _typeIdFromModel(const std::string & model);
 
Index: libopenraw-0.0.8/lib/peffile.cpp
===================================================================
--- libopenraw-0.0.8.orig/lib/peffile.cpp
+++ libopenraw-0.0.8/lib/peffile.cpp
@@ -95,7 +95,7 @@ namespace OpenRaw {
 			if(err == OR_ERROR_NONE) {
                 uint16_t compression = data.compression();
                 switch(compression) {
-                case 65535:
+                case IFD::COMPRESS_CUSTOM:
                     if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
                         // TODO decompress
                     }