/* * Copyright 2011-2019, European Organisation for the Exploitation of Meteorological Satellites (EUMETSAT) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //:Ignore ////////////////////////////////////////////////////////////////////////// // // FileName: CImage.cpp // // Date Created: 14/8/1998 // // Author: Van Wynsberghe Laurent // // // Description: pack and unpack functions, and random packed buffer generator // // // Last Modified: $Dmae: 1999/04/20 08:49:05 $ // // RCS Id: $Id: CImage.cpp,v 1.34 1999/04/20 08:49:05 youag Exp $ // // $Rma: CImage.cpp,v $ // Revision 1.34 1999/04/20 08:49:05 youag // Optimizing CImage pack & unpack for NR = 8, 10, 12 and 16 // // Revision 1.33 1999/04/16 17:03:31 youag // Optimizing pack and unpack functions using *pointer++ // // Revision 1.32 1999/04/16 11:03:32 youag // Cleaning the code from commented lines // // Revision 1.31 1999/04/15 17:49:57 youag // Buf correction in CImage pack(), bug introduced by previous optimization // // Revision 1.30 1999/04/15 15:24:20 youag // CImage optimization of pack and unpack functions (removing un-needed masks) // // Revision 1.29 1999/03/24 12:53:40 youag // Intel / Alpha optimisation tests // // Revision 1.28 1999/03/23 15:40:26 xne // Optimized Cget/Cset data members for alpha // // Revision 1.27 1999/03/01 20:07:40 xne // (Re)introducing CVS/RCS commit messages // //////////////////////////////////////////////////////////////////////////// //:End Ignore #include #include #include "CImage.h" namespace COMP { //------------------------------------------------------------------------ CImage::CImage(unsigned short i_NC, unsigned short i_NL, unsigned short i_NB) { COMP_TRYTHIS Resize(i_NC, i_NL, i_NB); COMP_CATCHTHIS } //------------------------------------------------------------------------ CImage::CImage(const Util::CDataFieldUncompressedImage &i_cdfui) { COMP_TRYTHIS // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Optimized version for (NB == NR) in 8, 10 or 12 bits // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Assert(i_cdfui.GetNR() >= i_cdfui.GetNB(), Util::CParamException()); Assert((i_cdfui.GetNR() == 8) || (i_cdfui.GetNR() == 10) || (i_cdfui.GetNR() == 12) || (i_cdfui.GetNR() == 16), Util::CParamException()); Resize(i_cdfui.GetNC(), i_cdfui.GetNL(), i_cdfui.GetNB()); unsigned short word_IN, word_OUT; const unsigned char *pIn = i_cdfui.get(); unsigned short *pOut = &m_data[0]; ResetState(); switch (i_cdfui.GetNR()) { case 16: while (m_index < m_size) { word_IN = *pIn++; word_OUT = word_IN << 8; // 1111.1111 word_IN = *pIn++; word_OUT |= word_IN; // 1111.1111 *pOut++ = word_OUT; m_index++; } break; case 12: while (m_index < m_size) { // read 2 pixels = 3 bytes and write 2 pixels = 4 bytes word_IN = *pIn++; word_OUT = word_IN << 4; // 1111.1111 word_IN = *pIn++; word_OUT |= word_IN >> 4; // 1111.0000 *pOut++ = word_OUT; m_index++; if (m_index < m_size) { word_OUT = (word_IN & 0x0F) << 8; // 0000.1111 word_IN = *pIn++; word_OUT |= word_IN; // 1111.1111 *pOut++ = word_OUT; m_index++; } } break; case 10: while (m_index < m_size) { // read 5 bytes=4 pixels and write 4 pixels=8 bytes word_IN = *pIn++; word_OUT = word_IN << 2; // 1111.1111 word_IN = *pIn++; word_OUT |= word_IN >> 6; // 1100.0000 *pOut++ = word_OUT; m_index++; if (m_index < m_size) { word_OUT = (word_IN & 0x3F) << 4; // 0011.1111 word_IN = *pIn++; word_OUT |= word_IN >> 4; // 1111.0000 *pOut++ = word_OUT; m_index++; if (m_index < m_size) { word_OUT = (word_IN & 0x0F) << 6; // 0000.1111 word_IN = *pIn++; word_OUT |= word_IN >> 2; // 1111.1100 *pOut++ = word_OUT; m_index++; if (m_index < m_size) { word_OUT = (word_IN & 0x03) << 8; // 0000.0011 word_IN = *pIn++; word_OUT |= word_IN; // 1111.1111 *pOut++ = word_OUT; m_index++; } } } } break; case 8: while (m_index < m_size) { word_IN = *pIn++; word_OUT = word_IN; // 1111.1111 *pOut++ = word_OUT; m_index++; } break; default: // Not (yet) implemented Assert(0, Util::CParamException()); } ResetState(); COMP_CATCHTHIS } //------------------------------------------------------------------------ void CImage::Resize(unsigned short i_NC, unsigned short i_NL, unsigned short i_NB) { COMP_TRYTHIS m_NB = i_NB; m_NC = i_NC; m_NL = i_NL; m_size = (unsigned long)i_NC * i_NL; m_data.clear(); m_dataptr.clear(); if (m_size > 0) { m_data.resize(m_size, 0); Assert(m_data.size() == m_size, Util::CCLibException()); m_dataptr.resize(m_NL, NULL); Assert(m_dataptr.size() == m_NL, Util::CCLibException()); for (short i = 0; i < m_NL; i++) m_dataptr[i] = &m_data[i * m_NC]; } ResetState(); COMP_CATCHTHIS } //------------------------------------------------------------------------ void CImage::Forward_point_transform(unsigned short i_pt) { COMP_TRYTHIS // Perform the point transform on every pixel // pixel = pixel / 2^(i_pt) Assert(i_pt <= 16, Util::CParamException()); if (i_pt) for (unsigned long i = 0; i < m_size; i++) m_data[i] >>= i_pt; COMP_CATCHTHIS } //------------------------------------------------------------------------ void CImage::Inverse_point_transform(unsigned short i_pt) { COMP_TRYTHIS // Perform the inverse point transform on every pixel // pixel = pixel * 2^(i_pt) Assert(i_pt <= 16, Util::CParamException()); if (i_pt) for (unsigned long i = 0; i < m_size; i++) m_data[i] <<= i_pt; COMP_CATCHTHIS } //------------------------------------------------------------------------ Util::CDataFieldUncompressedImage CImage::pack(unsigned short i_NR) { COMP_TRYTHIS // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Optimized version for (NB == NR) in 8, 10 or 12 bits // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Assert(i_NR >= m_NB, Util::CParamException()); // this check is also performed in the CDFUI constructor Assert(i_NR == 8 || i_NR == 10 || i_NR == 12 || i_NR == 16, Util::CParamException()); Util::CDataFieldUncompressedImage cdfui((unsigned char)m_NB, m_NC, m_NL, (unsigned char)i_NR); unsigned short word_IN, word_OUT; const unsigned short *pIn = &m_data[0]; unsigned char *pOut = cdfui.get(); ResetState(); switch (i_NR) { case 16: while (m_index < m_size) { // read 1 pixel = 2 bytes and write 1 pixel = 2 bytes word_IN = *pIn++; m_index++; word_OUT = word_IN >> 8; // 1111.1111.0000.0000 *pOut++ = (unsigned char)word_OUT; word_OUT = word_IN & 0xFF; // 0000.0000.1111.1111 *pOut++ = (unsigned char)word_OUT; } break; case 12: while (m_index < m_size) { // read 2 pixels = 4 bytes and write 2 pixels = 3 bytes word_IN = *pIn++ & 0xFFF; m_index++; word_OUT = word_IN >> 4; // 1111.1111.0000 *pOut++ = (unsigned char)word_OUT; word_OUT = (word_IN & 0x00F) << 4; // 0000.0000.1111 if (m_index < m_size) { word_IN = *pIn++ & 0xFFF; m_index++; word_OUT |= word_IN >> 8; // 1111.0000.0000 *pOut++ = (unsigned char)word_OUT; word_OUT = word_IN & 0x0FF; // 0000.1111.1111 *pOut++ = (unsigned char)word_OUT; } else *pOut++ = (unsigned char)word_OUT; } break; case 10: while (m_index < m_size) { // read 4 pixels = 8 bytes and write 4 pixels = 5 bytes word_IN = *pIn++ & 0x3FF; m_index++; word_OUT = word_IN >> 2; // 11.1111.1100 *pOut++ = (unsigned char)word_OUT; word_OUT = (word_IN & 0x003) << 6; // 00.0000.0011 if (m_index < m_size) { word_IN = *pIn++ & 0x3FF; m_index++; word_OUT |= word_IN >> 4; // 11.1111.0000 *pOut++ = (unsigned char)word_OUT; word_OUT = (word_IN & 0x00F) << 4; // 00.0000.1111 if (m_index < m_size) { word_IN = *pIn++ & 0x3FF; m_index++; word_OUT |= word_IN >> 6; // 11.1100.0000 *pOut++ = (unsigned char)word_OUT; word_OUT = (word_IN & 0x03F) << 2; // 00.0011.1111 if (m_index < m_size) { word_IN = *pIn++ & 0x3FF; m_index++; word_OUT |= word_IN >> 8; // 11.0000.0000 *pOut++ = (unsigned char)word_OUT; word_OUT = word_IN & 0x0FF; // 00.1111.1111 *pOut++ = (unsigned char)word_OUT; } else *pOut++ = (unsigned char)word_OUT; } else *pOut++ = (unsigned char)word_OUT; } else *pOut++ = (unsigned char)word_OUT; } break; case 8: while (m_index < m_size) { word_IN = *pIn++ & 0xFF; m_index++; word_OUT = word_IN; // 1111.1111 *pOut++ = (unsigned char)word_OUT; } break; default: // Not (yet) implemented Assert(0, Util::CParamException()); } ResetState(); return cdfui; COMP_CATCHTHIS } //------------------------------------------------------------------------ void CImage::Requantize(COMP::ERequantizationMode i_mode) { COMP_TRYTHIS unsigned long i; unsigned short *pData = &m_data[0]; switch (i_mode) { case COMP::e_NoRequantization: return; case COMP::e_10to12: Assert(m_NB == 10, Util::CParamException()); m_NB = 12; return; case COMP::e_10to8_floor: Assert(m_NB == 10, Util::CParamException()); for (i = 0; i < m_size; i++) *pData++ >>= 2; m_NB = 8; return; case COMP::e_10to8_floor1: Assert(m_NB == 10, Util::CParamException()); for (i = 0; i < m_size; i++) { unsigned short c = *pData; c = (c + 1) >> 2; if (c > 255) c = 255; *pData++ = c; } m_NB = 8; return; case COMP::e_10to8_round: Assert(m_NB == 10, Util::CParamException()); for (i = 0; i < m_size; i++) { unsigned short c = *pData; c = (c + 2) >> 2; if (c > 255) c = 255; *pData++ = c; } m_NB = 8; return; case COMP::e_10to8_ceil: Assert(m_NB == 10, Util::CParamException()); for (i = 0; i < m_size; i++) { unsigned short c = *pData; c = (c + 3) >> 2; if (c > 255) c = 255; *pData++ = c; } m_NB = 8; return; default: Assert(0, Util::CParamException()); } COMP_CATCHTHIS } //------------------------------------------------------------------------ void CImage::ResetState(void) { COMP_TRYTHIS m_index = 0; m_cur_L = 0; m_cur_C = 0; m_cur_RI = 0; COMP_CATCHTHIS } //------------------------------------------------------------------------ } // end namespace COMP