Skip to content

Commit 543c225

Browse files
Add loading jpeg into a YUV buffer
1 parent b2ae17d commit 543c225

File tree

1 file changed

+84
-19
lines changed

1 file changed

+84
-19
lines changed

src/zm_image.cpp

Lines changed: 84 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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

11141123
bool 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

Comments
 (0)