| 155 | } |
| 156 | |
| 157 | const uint8 * RLE_Data::Encode(const uint8 *data, int inlen, int &outlen, bool &changed) |
| 158 | { |
| 159 | changed = Realloc(inlen); // adjust size if necessary |
| 160 | |
| 161 | if (m_len <= 0) { |
| 162 | outlen = 0; |
| 163 | return NULL; |
| 164 | } |
| 165 | // |
| 166 | // calculate difference from prev |
| 167 | // |
| 168 | if ( m_use_diff ) { |
| 169 | for (int i = 0; i < m_len; i++) { |
| 170 | m_buff[i] ^= data[i]; |
| 171 | if (m_buff[i]) { |
| 172 | changed = true; |
| 173 | } |
| 174 | } |
| 175 | } else { |
| 176 | memcpy(m_buff, data, m_len); |
| 177 | changed = true; |
| 178 | } |
| 179 | |
| 180 | // |
| 181 | // now RLE |
| 182 | // |
| 183 | // In worst case 2-byte sequence is encoded as 3. So, data can grow by 50%. |
| 184 | uint8 * enc_buff = new uint8[static_cast<size_t>(m_len) * 3 / 2 + 1]; |
| 185 | int i = 0, j = 0; |
| 186 | while ( i != m_len ) { |
| 187 | uint8 curr_val = m_buff[i]; |
| 188 | int seq_start = i; |
| 189 | while ( (i != m_len) && (curr_val == m_buff[i]) && ((i - seq_start) < 0xff)) { |
| 190 | i++; |
| 191 | } |
| 192 | if (i - seq_start > 1) { |
| 193 | // if there's 2 or more equal vals - put it twice in stream |
| 194 | enc_buff[j++] = curr_val; |
| 195 | enc_buff[j++] = curr_val; |
| 196 | enc_buff[j++] = i - seq_start; |
| 197 | } else { |
| 198 | // single value - put it as is |
| 199 | enc_buff[j++] = curr_val; |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | outlen = j; |
| 204 | |
| 205 | // |
| 206 | // If using differential encoder, remember current data for |
| 207 | // later use |
| 208 | if ( m_use_diff ) { |
| 209 | memcpy(m_buff, data, m_len); |
| 210 | } |
| 211 | |
| 212 | return enc_buff; |
| 213 | } |
| 214 | |