JpegCompression.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2020 Intel Corporation. All Rights Reserved.
3 
4 #include "JpegCompression.h"
5 #include "jpeglib.h"
6 #include <cstdint>
7 #include <cstring>
8 #include <iostream>
10 #include <stdio.h>
11 #include <time.h>
12 
13 JpegCompression::JpegCompression(int t_width, int t_height, rs2_format t_format, int t_bpp)
14  :ICompression(t_width, t_height, t_format, t_bpp)
15 {
16  m_cinfo.err = jpeg_std_error(&m_jerr);
17  m_dinfo.err = jpeg_std_error(&m_jerr);
18  jpeg_create_compress(&m_cinfo);
19  jpeg_create_decompress(&m_dinfo);
20  m_cinfo.input_components = m_bpp;
22  {
23  m_cinfo.in_color_space = JCS_YCbCr;
24  m_cinfo.input_components = 3; //yuyv and uyvy is 2 bpp, converted to yuv that is 3 bpp.
25  }
26  else if(m_format == RS2_FORMAT_Y8)
27  {
28  m_cinfo.in_color_space = JCS_GRAYSCALE;
29  m_cinfo.input_components = 1;
30  }
32  {
33  m_cinfo.in_color_space = JCS_RGB;
34  }
35  else
36  {
37  ERR << "unsupported format " << t_format << " for JPEG compression";
38  }
39  m_rowBuffer = new unsigned char[m_cinfo.input_components * t_width];
40  m_destBuffer = (*m_cinfo.mem->alloc_sarray)((j_common_ptr)&m_cinfo, JPOOL_IMAGE, m_cinfo.input_components * t_width, 1);
41  jpeg_set_defaults(&m_cinfo);
42 }
43 
45 {
46  delete[] m_rowBuffer;
47  jpeg_destroy_decompress(&m_dinfo);
48  jpeg_destroy_compress(&m_cinfo);
49 }
50 
51 void JpegCompression::convertYUYVtoYUV(unsigned char** t_buffer)
52 {
53  for(unsigned i = 0; i < m_cinfo.image_width; i += 2)
54  {
55  m_rowBuffer[i * 3] = (*t_buffer)[i * 2 + 0]; // Y
56  m_rowBuffer[i * 3 + 1] = (*t_buffer)[i * 2 + 1]; // U
57  m_rowBuffer[i * 3 + 2] = (*t_buffer)[i * 2 + 3]; // V
58  m_rowBuffer[i * 3 + 3] = (*t_buffer)[i * 2 + 2]; // Y
59  m_rowBuffer[i * 3 + 4] = (*t_buffer)[i * 2 + 1]; // U
60  m_rowBuffer[i * 3 + 5] = (*t_buffer)[i * 2 + 3]; // V
61  }
63  (*t_buffer) += m_cinfo.image_width * m_bpp;
64 }
65 
66 void JpegCompression::convertUYVYtoYUV(unsigned char** t_buffer)
67 {
68  for(unsigned i = 0; i < m_cinfo.image_width; i += 2)
69  {
70  m_rowBuffer[i * 3] = (*t_buffer)[i * 2 + 1]; // Y
71  m_rowBuffer[i * 3 + 1] = (*t_buffer)[i * 2 + 0]; // U
72  m_rowBuffer[i * 3 + 2] = (*t_buffer)[i * 2 + 2]; // V
73  m_rowBuffer[i * 3 + 3] = (*t_buffer)[i * 2 + 3]; // Y
74  m_rowBuffer[i * 3 + 4] = (*t_buffer)[i * 2 + 0]; // U
75  m_rowBuffer[i * 3 + 5] = (*t_buffer)[i * 2 + 2]; // V
76  }
78  (*t_buffer) += m_cinfo.image_width * m_bpp;
79 }
80 
81 void JpegCompression::convertYUVtoYUYV(unsigned char** t_uncompressBuff)
82 {
83  for(unsigned i = 0; i < m_dinfo.output_width; i += 2)
84  {
85  (*t_uncompressBuff)[i * 2] = m_destBuffer[0][i * 3]; // Y
86  (*t_uncompressBuff)[i * 2 + 1] = m_destBuffer[0][i * 3 + 1]; // U
87  (*t_uncompressBuff)[i * 2 + 2] = m_destBuffer[0][i * 3 + 3]; // Y
88  (*t_uncompressBuff)[i * 2 + 3] = m_destBuffer[0][i * 3 + 2]; // V
89  }
90  (*t_uncompressBuff) += m_dinfo.output_width * m_bpp;
91 }
92 
93 void JpegCompression::convertYUVtoUYVY(unsigned char** t_uncompressBuff)
94 {
95  for(unsigned i = 0; i < m_dinfo.output_width; i += 2)
96  {
97  (*t_uncompressBuff)[i * 2] = m_destBuffer[0][i * 3 + 1]; // U
98  (*t_uncompressBuff)[i * 2 + 1] = m_destBuffer[0][i * 3 + 0]; // Y
99  (*t_uncompressBuff)[i * 2 + 2] = m_destBuffer[0][i * 3 + 2]; // V
100  (*t_uncompressBuff)[i * 2 + 3] = m_destBuffer[0][i * 3 + 3]; // Y
101  }
102  (*t_uncompressBuff) += m_dinfo.output_width * m_bpp;
103 }
104 
105 void JpegCompression::convertBGRtoRGB(unsigned char** t_buffer)
106 {
107  for(unsigned i = 0; i < m_cinfo.image_width * m_bpp; i += 3)
108  {
109  m_rowBuffer[i] = (*t_buffer)[i + 2]; // R
110  m_rowBuffer[i + 1] = (*t_buffer)[i + 1]; // G
111  m_rowBuffer[i + 2] = (*t_buffer)[i]; // B
112  }
114  (*t_buffer) += m_cinfo.image_width * m_bpp;
115 }
116 
117 void JpegCompression::convertRGBtoBGR(unsigned char** t_uncompressBuff)
118 {
119  for(unsigned i = 0; i < m_dinfo.output_width * m_bpp; i += 3)
120  {
121  (*t_uncompressBuff)[i] = m_destBuffer[0][i + 2]; // B
122  (*t_uncompressBuff)[i + 1] = m_destBuffer[0][i + 1]; // G
123  (*t_uncompressBuff)[i + 2] = m_destBuffer[0][i]; // R
124  }
125  (*t_uncompressBuff) += m_dinfo.output_width * m_bpp;
126 }
127 
128 int JpegCompression::compressBuffer(unsigned char* t_buffer, int t_size, unsigned char* t_compressedBuf)
129 {
130  long unsigned int compressedSize = 0;
131  unsigned char* data = nullptr;
132  jpeg_mem_dest(&m_cinfo, &data, &compressedSize);
133  m_cinfo.image_width = m_width;
134  m_cinfo.image_height = m_height;
135  uint64_t row_stride = m_cinfo.image_width * m_cinfo.input_components;
136  jpeg_start_compress(&m_cinfo, TRUE);
137  while(m_cinfo.next_scanline < m_cinfo.image_height)
138  {
140  {
141  m_row_pointer[0] = &t_buffer[m_cinfo.next_scanline * row_stride];
142  }
143  else if(m_format == RS2_FORMAT_YUYV)
144  {
145  convertYUYVtoYUV(&t_buffer);
146  }
147  else if(m_format == RS2_FORMAT_UYVY)
148  {
149  convertUYVYtoYUV(&t_buffer);
150  }
151  else if(m_format == RS2_FORMAT_BGR8)
152  {
153  convertBGRtoRGB(&t_buffer);
154  }
155  else
156  {
157  ERR << "unsupported format " << m_format << " for JPEG compression";
158  return -1;
159  }
160  jpeg_write_scanlines(&m_cinfo, m_row_pointer, 1);
161  }
162  jpeg_finish_compress(&m_cinfo);
163  int compressWithHeaderSize = compressedSize + sizeof(int);
164  if(compressWithHeaderSize > t_size)
165  {
166  ERR << "compression overflow, destination buffer is smaller than the compressed size";
167  return -1;
168  }
169  memcpy(t_compressedBuf, &compressedSize, sizeof(int));
170  memcpy(t_compressedBuf + sizeof(int), data, compressedSize);
171  if(m_compFrameCounter++ % 50 == 0)
172  {
173  INF << "frame " << m_compFrameCounter << "\tcolor\tcompression\tJPEG\t" << t_size << "\t/\t" << compressedSize;
174  }
175  free(data);
176  return compressWithHeaderSize;
177 }
178 
179 int JpegCompression::decompressBuffer(unsigned char* t_buffer, int t_compressedSize, unsigned char* t_uncompressedBuf)
180 {
181  unsigned char* ptr = t_uncompressedBuf;
182  unsigned char* data = t_buffer;
183  unsigned int jpegHeader{}, res{};
184  jpeg_mem_src(&m_dinfo, data, t_compressedSize);
185  if(t_buffer != nullptr)
186  {
187  memcpy(&jpegHeader, t_buffer, sizeof(unsigned int));
188  }
189  if(jpegHeader != 0xE0FFD8FF)
190  { //check header integrity if = E0FF D8FF - the First 4 bytes jpeg standards.
191  ERR << "Not a JPEG frame, skipping";
192  return -1;
193  }
194  res = jpeg_read_header(&m_dinfo, TRUE);
195  if(!res)
196  {
197  ERR << "Cannot read JPEG header";
198  return -1;
199  }
201  {
202  m_dinfo.out_color_space = JCS_RGB;
203  }
205  {
206  m_dinfo.out_color_space = JCS_YCbCr;
207  }
208  else if(m_format == RS2_FORMAT_Y8)
209  {
210  m_dinfo.out_color_space = JCS_GRAYSCALE;
211  }
212  else
213  {
214  ERR << "Unsupported format " << m_format << " for the JPEG compression";
215  return -1;
216  }
217  res = jpeg_start_decompress(&m_dinfo);
218  if(!res)
219  {
220  ERR << "jpeg_start_decompress failed";
221  return -1;
222  }
223  uint64_t row_stride = m_dinfo.output_width * m_dinfo.output_components;
224  while(m_dinfo.output_scanline < m_dinfo.output_height)
225  {
226  int numLines = jpeg_read_scanlines(&m_dinfo, m_destBuffer, 1);
227  if(numLines <= 0)
228  {
229  ERR << "jpeg_read_scanlines failed at " << numLines;
230  return -1;
231  }
233  {
234  memcpy(ptr, m_destBuffer[0], row_stride);
235  ptr += row_stride;
236  }
237  else if(m_format == RS2_FORMAT_YUYV)
238  {
239  convertYUVtoYUYV(&ptr);
240  }
241  else if(m_format == RS2_FORMAT_UYVY)
242  {
243  convertYUVtoUYVY(&ptr);
244  }
245  else if(m_format == RS2_FORMAT_BGR8)
246  {
247  convertRGBtoBGR(&ptr);
248  }
249  }
250  res = jpeg_finish_decompress(&m_dinfo);
251  if(!res)
252  {
253  ERR << "jpeg_finish_decompress failed";
254  return -1;
255  }
256  int uncompressedSize = m_dinfo.output_width * m_dinfo.output_height * m_bpp;
257  if(m_decompFrameCounter++ % 50 == 0)
258  {
259  INF << "frame " << m_decompFrameCounter << "\tcolor\tdecompression\tJPEG\t" << t_compressedSize << "\t/\t" << uncompressedSize;
260  }
261  return uncompressedSize;
262 }
struct jpeg_compress_struct m_cinfo
void convertYUVtoUYVY(unsigned char **t_uncompressBuff)
#define ERR
Definition: NetdevLog.h:9
int m_compFrameCounter
Definition: ICompression.h:21
void convertUYVYtoYUV(unsigned char **t_buffer)
#define INF
Definition: NetdevLog.h:11
int compressBuffer(unsigned char *t_buffer, int t_size, unsigned char *t_compressedBuf)
int m_decompFrameCounter
Definition: ICompression.h:21
JSAMPROW m_row_pointer[1]
JpegCompression(int t_width, int t_height, rs2_format t_format, int t_bpp)
void convertRGBtoBGR(unsigned char **t_uncompressBuff)
int decompressBuffer(unsigned char *t_buffer, int t_size, unsigned char *t_uncompressedBuf)
struct jpeg_error_mgr m_jerr
unsigned __int64 uint64_t
Definition: stdint.h:90
JSAMPARRAY m_destBuffer
rs2_format
A stream&#39;s format identifies how binary data is encoded within a frame.
Definition: rs_sensor.h:59
rs2_format m_format
Definition: ICompression.h:20
void convertYUYVtoYUV(unsigned char **t_buffer)
LZ4LIB_API char int compressedSize
Definition: lz4.h:456
unsigned char * m_rowBuffer
void convertBGRtoRGB(unsigned char **t_buffer)
void convertYUVtoYUYV(unsigned char **t_uncompressBuff)
#define TRUE
Definition: tinycthread.c:50
int i
GLuint res
Definition: glext.h:8856
struct jpeg_decompress_struct m_dinfo
Definition: parser.hpp:150


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:20