libopenraw
unpack.cpp
1 /* -*- tab-width:4; indent-tabs-mode:'t c-file-style:"stroustrup" -*- */
2 /*
3  * libopenraw - unpack.cpp
4  *
5  * Copyright (C) 2008 Hubert Figuiere
6  * Copyright (C) 2008 Novell, Inc.
7  *
8  * This library is free software: you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see
20  * <http://www.gnu.org/licenses/>.
21  */
22 
23 
24 #include <assert.h>
25 #include "unpack.h"
26 #include "trace.h"
27 #include "ifd.h"
28 
29 namespace OpenRaw { namespace Internals {
30 
31  using namespace Debug;
32 
33  Unpack::Unpack(uint32_t w, uint32_t t)
34  : m_w(w), m_type(t)
35  {
36  }
37 
38  /* Return the size of an image row. */
39  size_t Unpack::block_size()
40  {
41  size_t bs;
42  if(m_type == IFD::COMPRESS_NIKON_PACK) {
43  bs = (m_w / 2 * 3) + (m_w / 10);
44  }
45  else {
46  bs = m_w / 2 * 3;
47  }
48  return bs;
49  }
50 
51 
56  size_t Unpack::unpack_be12to16(uint8_t *dest, const uint8_t *src,
57  size_t size)
58  {
59  uint16_t *dest16 = reinterpret_cast<uint16_t *>(dest);
60  size_t pad = (m_type == IFD::COMPRESS_NIKON_PACK) ? 1 : 0;
61  size_t n = size / (15 + pad);
62  size_t rest = size % (15 + pad);
63  size_t ret = n * 20 + rest / 3 * 4;
64 
65  /* The inner loop advances 10 columns, which corresponds to 15 input
66  bytes, 20 output bytes and, in a Nikon pack, one padding byte.*/
67  if (pad) {
68  assert (size % 16 == 0);
69  }
70  assert (rest % 3 == 0);
71 
72  for (size_t i = 0; i < n + 1; i++) {
73  size_t m = i == n ? rest / 3 : 5;
74  for(size_t j = 0; j < m; j++) {
75  /* Read 3 bytes */
76  uint32_t t = *src++;
77  t <<= 8;
78  t |= *src++;
79  t <<= 8;
80  t |= *src++;
81 
82  /* Write two 16 bit values. */
83  *dest16 = (t & (0xfff << 12)) >> 12;
84  dest16++;
85 
86  *dest16 = t & 0xfff;
87  dest16++;
88  }
89 
90  src += pad;
91  }
92 
93  return ret;
94  }
95 
96 } }