@@ -723,8 +723,8 @@ uint8_t* Image::WriteBuffer(
723723 linesize = p_width * p_colours;
724724 subpixelorder = p_subpixelorder;
725725 pixels = height*width;
726- AVPixelFormat format = imagePixFormat = AVPixFormat ();
727726
727+ AVPixelFormat format = imagePixFormat = AVPixFormat ();
728728 unsigned int newsize = av_image_get_buffer_size (static_cast <AVPixelFormat>(format), width, height, 32 );
729729
730730 if ( buffer == nullptr ) {
@@ -749,8 +749,17 @@ uint8_t* Image::WriteBuffer(
749749 linesize = p_width * p_colours;
750750 subpixelorder = p_subpixelorder;
751751 pixels = height*width;
752+ imagePixFormat = AVPixFormat ();
752753 } // end if need to re-alloc buffer
753754
755+ if ( imagePixFormat == AV_PIX_FMT_YUV420P or imagePixFormat == AV_PIX_FMT_YUVJ420P) {
756+ u_buffer = buffer + width * height;
757+ v_buffer = u_buffer + (width * height / 2 );
758+ } else {
759+ u_buffer = nullptr ;
760+ v_buffer = nullptr ;
761+ }
762+
754763 return buffer;
755764}
756765
@@ -1113,7 +1122,12 @@ bool Image::WriteRaw(const std::string &filename) const {
11131122
11141123bool Image::ReadJpeg (const std::string &filename, unsigned int p_colours, unsigned int p_subpixelorder) {
11151124
1116- unsigned int new_width, new_height, new_colours, new_subpixelorder;
1125+ FILE *infile;
1126+ if ((infile = fopen (filename.c_str (), " rb" )) == nullptr ) {
1127+ Error (" Can't open %s: %s" , filename.c_str (), strerror (errno));
1128+ return false ;
1129+ }
1130+
11171131
11181132 if (!readjpg_dcinfo) {
11191133 readjpg_dcinfo = new jpeg_decompress_struct;
@@ -1123,13 +1137,9 @@ bool Image::ReadJpeg(const std::string &filename, unsigned int p_colours, unsign
11231137 jpeg_create_decompress (readjpg_dcinfo);
11241138 }
11251139
1126- FILE *infile;
1127- if ((infile = fopen (filename.c_str (), " rb" )) == nullptr ) {
1128- Error (" Can't open %s: %s" , filename.c_str (), strerror (errno));
1129- return false ;
1130- }
11311140
11321141 if (setjmp (jpg_err.setjmp_buffer )) {
1142+ Error (" setjmp" );
11331143 jpeg_abort_decompress (readjpg_dcinfo);
11341144 fclose (infile);
11351145 return false ;
@@ -1152,6 +1162,7 @@ bool Image::ReadJpeg(const std::string &filename, unsigned int p_colours, unsign
11521162 zm_use_std_huff_tables (readjpg_dcinfo);
11531163 }
11541164
1165+ unsigned int new_width, new_height, new_colours, new_subpixelorder;
11551166 new_width = readjpg_dcinfo->image_width ;
11561167 new_height = readjpg_dcinfo->image_height ;
11571168
@@ -1169,17 +1180,14 @@ bool Image::ReadJpeg(const std::string &filename, unsigned int p_colours, unsign
11691180// case ZM_COLOUR_YUV420P:
11701181// case ZM_COLOUR_YUVJ420P:
11711182 if (p_subpixelorder == ZM_SUBPIX_ORDER_YUV420P) {
1172- Debug (1 , " Reading YUV420P" );
11731183 readjpg_dcinfo->out_color_space = JCS_YCbCr;
11741184 new_colours = ZM_COLOUR_YUV420P;
11751185 new_subpixelorder = ZM_SUBPIX_ORDER_YUV420P;
11761186 } else if (p_subpixelorder == ZM_SUBPIX_ORDER_YUVJ420P) {
1177- Debug (1 , " Reading YUVJ420P" );
11781187 readjpg_dcinfo->out_color_space = JCS_YCbCr;
11791188 new_colours = ZM_COLOUR_YUVJ420P;
11801189 new_subpixelorder = ZM_SUBPIX_ORDER_YUVJ420P;
11811190 } else {
1182- Debug (1 , " Reading GRAY" );
11831191 readjpg_dcinfo->out_color_space = JCS_GRAYSCALE;
11841192 new_colours = ZM_COLOUR_GRAY8;
11851193 new_subpixelorder = ZM_SUBPIX_ORDER_NONE;
@@ -1208,15 +1216,14 @@ bool Image::ReadJpeg(const std::string &filename, unsigned int p_colours, unsign
12081216#endif
12091217 case ZM_COLOUR_RGB24:
12101218 default :
1211- Debug (1 , " Reading RGB24" );
12121219 new_colours = ZM_COLOUR_RGB24;
12131220 if (p_subpixelorder == ZM_SUBPIX_ORDER_BGR) {
12141221#ifdef JCS_EXTENSIONS
12151222 readjpg_dcinfo->out_color_space = JCS_EXT_BGR;
12161223 new_subpixelorder = ZM_SUBPIX_ORDER_BGR;
12171224#else
12181225 Warning (" libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead." );
1219- cinfo ->out_color_space = JCS_RGB;
1226+ readjpg_dcinfo ->out_color_space = JCS_RGB;
12201227 new_subpixelorder = ZM_SUBPIX_ORDER_RGB;
12211228#endif
12221229 } else {
@@ -1241,22 +1248,80 @@ cinfo->out_color_space = JCS_RGB;
12411248 return false ;
12421249 }
12431250
1251+
12441252 jpeg_start_decompress (readjpg_dcinfo);
12451253
1246- JSAMPROW row_pointer = buffer;
1247- while (readjpg_dcinfo->output_scanline < readjpg_dcinfo->output_height ) {
1248- JDIMENSION lines = jpeg_read_scanlines (readjpg_dcinfo, &row_pointer, 1 );
1249- if (lines != 1 ) {
1250- Error (" jpeg_read_scanlines returned != 1 lines %d" , lines);
1254+ if (p_subpixelorder == ZM_SUBPIX_ORDER_YUV420P or p_subpixelorder == ZM_SUBPIX_ORDER_YUVJ420P) {
1255+ unsigned char cb_block[4 ], cr_block[4 ];
1256+ JSAMPARRAY row_buffer = (readjpg_dcinfo->mem ->alloc_sarray )((j_common_ptr) readjpg_dcinfo, JPOOL_IMAGE, new_width * 3 , 1 );
1257+ if (!(u_buffer or v_buffer)) {
1258+ Debug (1 , " Need to setup u_buffer and v_buffer" );
1259+ if (!u_buffer || !v_buffer) {
1260+ u_buffer = buffer + new_width*new_height;
1261+ v_buffer = u_buffer + new_width*new_height/4 ;
1262+ }
1263+ }
1264+
1265+ for (unsigned int row = 0 ; row < readjpg_dcinfo->output_height ; ++row) {
1266+ JDIMENSION lines = jpeg_read_scanlines (readjpg_dcinfo, row_buffer, 1 );
1267+ if (lines != 1 ) {
1268+ Error (" jpeg_read_scanlines returned != 1 lines %d" , lines);
1269+ }
1270+
1271+ for (unsigned int col = 0 ; col < new_width; ++col) {
1272+ int idx = col * 3 ;
1273+ uint8_t y = row_buffer[0 ][idx + 0 ];
1274+ uint8_t cb = row_buffer[0 ][idx + 1 ];
1275+ uint8_t cr = row_buffer[0 ][idx + 2 ];
1276+
1277+ // Write Y
1278+ buffer[row * new_width + col] = y;
1279+ // (*buffer)[row * new_width + col] = y;
1280+
1281+ // For chroma: 2x2 block average for subsampling
1282+ if ((row % 2 == 0 ) && (col % 2 == 0 )) {
1283+ // gather 2x2 Cb/Cr block
1284+ int block_count = 0 ;
1285+ for (int dy = 0 ; dy < 2 ; ++dy) {
1286+ for (int dx = 0 ; dx < 2 ; ++dx) {
1287+ unsigned int r = row + dy;
1288+ unsigned int c = col + dx;
1289+ if (r < new_height && c < new_width) {
1290+ unsigned int i = c * 3 ;
1291+ cb_block[block_count] = row_buffer[0 ][i + 1 ];
1292+ cr_block[block_count] = row_buffer[0 ][i + 2 ];
1293+ } else {
1294+ cb_block[block_count] = cb;
1295+ cr_block[block_count] = cr;
1296+ }
1297+ block_count++;
1298+ }
1299+ }
1300+ // Average and store in U/V plane
1301+ int uv_index = (row/2 ) * (new_width/2 ) + (col/2 );
1302+ unsigned int cb_sum = cb_block[0 ] + cb_block[1 ] + cb_block[2 ] + cb_block[3 ];
1303+ unsigned int cr_sum = cr_block[0 ] + cr_block[1 ] + cr_block[2 ] + cr_block[3 ];
1304+ u_buffer[uv_index] = (cb_sum / 4 );
1305+ v_buffer[uv_index] = (cr_sum / 4 );
1306+ }
1307+ } // end foreach col
1308+ } // end foreach row
1309+ } else {
1310+ JSAMPROW row_pointer = buffer;
1311+ while (readjpg_dcinfo->output_scanline < readjpg_dcinfo->output_height ) {
1312+ JDIMENSION lines = jpeg_read_scanlines (readjpg_dcinfo, &row_pointer, 1 );
1313+ if (lines != 1 ) {
1314+ Error (" jpeg_read_scanlines returned != 1 lines %d" , lines);
1315+ }
1316+ row_pointer += linesize;
12511317 }
1252- row_pointer += linesize;
12531318 }
12541319
12551320 jpeg_finish_decompress (readjpg_dcinfo);
12561321 fclose (infile);
12571322
12581323 return true ;
1259- }
1324+ } // end bool Image::ReadJpeg(const std::string &filename, unsigned int p_colours, unsigned int p_subpixelorder)
12601325
12611326// Multiple calling formats to permit inclusion (or not) of non blocking, quality_override and timestamp (exif), with suitable defaults.
12621327// Note quality=zero means default
0 commit comments