Skip to content

Commit 8e6c21d

Browse files
committed
add gpujpeg_decoder_get_image_info2
to be used instead of gpujpeg_decoder_get_image_info
1 parent 92ae822 commit 8e6c21d

File tree

9 files changed

+101
-57
lines changed

9 files changed

+101
-57
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required(VERSION 3.10.0 FATAL_ERROR)
22
# change version also in configure.ac
3-
project(gpujpeg VERSION 0.27.8 LANGUAGES C CUDA)
3+
project(gpujpeg VERSION 0.27.9 LANGUAGES C CUDA)
44

55
# options
66
set(BUILD_OPENGL OFF CACHE STRING "Build with OpenGL support, options are: AUTO ON OFF")

NEWS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
2025-10-20 - 0.27.9
2+
----------
3+
4+
- add gpujpeg_decoder_get_image_info2 as a extensible replacement for
5+
gpujpeg_decoder_get_image_info
6+
17
2025-08-22 - 0.27.8
28
----------
39

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
AC_PREREQ([2.65])
22
# change version also in CMakeLists.txt
3-
AC_INIT([libgpujpeg],[0.27.8],[https://github.com/CESNET/GPUJPEG/issues],[libgpujpeg],[https://github.com/CESNET/GPUJPEG])
3+
AC_INIT([libgpujpeg],[0.27.9],[https://github.com/CESNET/GPUJPEG/issues],[libgpujpeg],[https://github.com/CESNET/GPUJPEG])
44
AC_CONFIG_MACRO_DIR([m4])
55
AC_CONFIG_SRCDIR([src/main.c])
66
AC_CONFIG_AUX_DIR([.])

libgpujpeg/gpujpeg_common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ gpujpeg_print_devices_info(void);
142142
/**
143143
* Init CUDA device
144144
*
145+
* This call is not mandatory if you do not want to use other than default CUDA
146+
* device (if not set with cudaSetDevice()) or to specify flags. The advantage is
147+
* that this will check CUDA device operability early.
148+
*
145149
* @param device_id CUDA device id (starting at 0)
146150
* @param flags @ref Flags, e.g. if device info should be printed out (@ref GPUJPEG_INIT_DEV_VERBOSE) or
147151
* enable OpenGL interoperability (@ref GPUJPEG_OPENGL_INTEROPERABILITY)

libgpujpeg/gpujpeg_decoder.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,27 @@ gpujpeg_decoder_set_output_format(struct gpujpeg_decoder* decoder,
261261
enum gpujpeg_color_space color_space,
262262
enum gpujpeg_pixel_format pixel_format);
263263

264+
enum {
265+
GPUJPEG_COUNT_SEG_COUNT_REQ = 1 << 0, ///< count up segment_count
266+
};
267+
struct gpujpeg_image_info {
268+
union {
269+
struct
270+
{
271+
struct gpujpeg_image_parameters param_image;
272+
struct gpujpeg_parameters param;
273+
int segment_count;
274+
};
275+
char reserved[128]; // for further extensions
276+
};
277+
};
264278
/**
265279
* @copydoc gpujpeg_reader_get_image_info
266280
*/
267281
GPUJPEG_API int
282+
gpujpeg_decoder_get_image_info2(uint8_t *image, size_t image_size, struct gpujpeg_image_info *info, int verbose, unsigned flags);
283+
/// use gpujpeg_decoder_get_image_info2()
284+
GPUJPEG_API int
268285
gpujpeg_decoder_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_image_parameters *param_image, struct gpujpeg_parameters *param, int *segment_count);
269286

270287
/// use RLE when writing TGA with gpujpeg_image_save_to_file (default is true), 0 or 1 please note that the option is

src/gpujpeg_decoder.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,27 @@ gpujpeg_decoder_destroy(struct gpujpeg_decoder* decoder)
551551

552552
int
553553
gpujpeg_decoder_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_image_parameters *param_image, struct gpujpeg_parameters *param, int *segment_count) {
554-
return gpujpeg_reader_get_image_info(image, image_size, param_image, param, segment_count);
554+
struct gpujpeg_image_info info = { 0 };
555+
const unsigned flags = segment_count == NULL ? 0 : GPUJPEG_COUNT_SEG_COUNT_REQ;
556+
const int verbose = param->verbose;
557+
const int rc = gpujpeg_reader_get_image_info(image, image_size, &info, verbose, flags);
558+
if ( rc != GPUJPEG_NOERR ) {
559+
return rc;
560+
};
561+
memcpy(param_image, &info.param_image, sizeof *param_image);
562+
memcpy(param, &info.param, sizeof *param);
563+
param->verbose = verbose;
564+
if ( segment_count != NULL ) {
565+
*segment_count = info.segment_count;
566+
}
567+
return GPUJPEG_NOERR;
568+
}
569+
570+
GPUJPEG_API int
571+
gpujpeg_decoder_get_image_info2(uint8_t* image, size_t image_size, struct gpujpeg_image_info* info, int verbose,
572+
unsigned flags)
573+
{
574+
return gpujpeg_reader_get_image_info(image, image_size, info, verbose, flags);
555575
}
556576

557577
/* vi: set expandtab sw=4 : */

src/gpujpeg_reader.c

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,8 +1664,10 @@ gcd(int a, int b)
16641664

16651665
/* Documented at declaration */
16661666
int
1667-
gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_image_parameters *param_image, struct gpujpeg_parameters *param, int *segment_count)
1667+
gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_image_info *info, int verbose, unsigned flags)
16681668
{
1669+
// gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_image_parameters *param_image,
1670+
// struct gpujpeg_parameters *param, int *segment_count)
16691671
int segments = 0;
16701672
int unused[4];
16711673
uint8_t unused2[4];
@@ -1674,11 +1676,11 @@ gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_
16741676
uint8_t *image_end = image + image_size;
16751677
struct gpujpeg_exif_parameters exif_metadata;
16761678

1677-
param->interleaved = 0;
1678-
param->restart_interval = 0;
1679+
info->param.interleaved = 0;
1680+
info->param.restart_interval = 0;
16791681

16801682
// Check first SOI marker
1681-
int marker_soi = gpujpeg_reader_read_marker(&image, image_end, param->verbose);
1683+
int marker_soi = gpujpeg_reader_read_marker(&image, image_end, verbose);
16821684
if (marker_soi != GPUJPEG_MARKER_SOI) {
16831685
fprintf(stderr, "[GPUJPEG] [Error] JPEG data should begin with SOI marker, but marker %s was found!\n", gpujpeg_marker_name((enum gpujpeg_marker_code)marker_soi));
16841686
return -1;
@@ -1688,15 +1690,15 @@ gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_
16881690
_Bool in_spiff = 0;
16891691
while (eoi_presented == 0) {
16901692
// Read marker
1691-
int marker = gpujpeg_reader_read_marker(&image, image_end, param->verbose);
1693+
int marker = gpujpeg_reader_read_marker(&image, image_end, verbose);
16921694
if (marker == -1) {
16931695
return -1;
16941696
}
16951697

16961698
// Read more info according to the marker
16971699
int rc =
1698-
gpujpeg_reader_read_common_markers(&image, image_end, marker, param->verbose, false, &header_color_space,
1699-
&header_type, &param->restart_interval, &in_spiff, &exif_metadata);
1700+
gpujpeg_reader_read_common_markers(&image, image_end, marker, verbose, false, &header_color_space,
1701+
&header_type, &info->param.restart_interval, &in_spiff, &exif_metadata);
17001702
if ( rc < 0 ) {
17011703
return rc;
17021704
}
@@ -1708,12 +1710,12 @@ gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_
17081710
case GPUJPEG_MARKER_SOF0: // Baseline
17091711
case GPUJPEG_MARKER_SOF1: // Extended sequential with Huffman coder
17101712
{
1711-
param->color_space_internal = header_color_space;
1712-
if ( gpujpeg_reader_read_sof0(param, param_image, header_color_space, header_type, unused, unused2, &image,
1713+
info->param.color_space_internal = header_color_space;
1714+
if ( gpujpeg_reader_read_sof0(&info->param, &info->param_image, header_color_space, header_type, unused, unused2, &image,
17131715
image_end) != 0 ) {
17141716
return -1;
17151717
}
1716-
param_image->color_space = param->color_space_internal;
1718+
info->param_image.color_space = info->param.color_space_internal;
17171719
break;
17181720
}
17191721
case GPUJPEG_MARKER_RST0:
@@ -1738,9 +1740,9 @@ gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_
17381740
assert(length > 3);
17391741
int comp_count = (int) gpujpeg_reader_read_byte(image); // comp count in the segment
17401742
if (comp_count > 1) {
1741-
param->interleaved = 1;
1743+
info->param.interleaved = 1;
17421744
}
1743-
if (segment_count == NULL) { // if not counting segments, we can skip the rest
1745+
if ( (flags & GPUJPEG_COUNT_SEG_COUNT_REQ) != 0 ) { // if not counting segments, we can skip the rest
17441746
eoi_presented = 1;
17451747
}
17461748
}
@@ -1787,55 +1789,53 @@ gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_
17871789
}
17881790
}
17891791

1790-
if (segment_count != NULL) {
1791-
*segment_count = segments;
1792-
}
1792+
info->segment_count = segments;
17931793

1794-
param_image->pixel_format = GPUJPEG_PIXFMT_NONE;
1794+
info->param_image.pixel_format = GPUJPEG_PIXFMT_NONE;
17951795

1796-
if ( param->comp_count == 1 ) {
1797-
param_image->pixel_format = GPUJPEG_U8;
1796+
if ( info->param.comp_count == 1 ) {
1797+
info->param_image.pixel_format = GPUJPEG_U8;
17981798
}
1799-
if ( param->comp_count == 3 ) {
1799+
if ( info->param.comp_count == 3 ) {
18001800
// reduce [2, 2; 1, 2; 1, 2] (FFmpeg) to [2, 1; 1, 1; 1, 1]
1801-
int horizontal_gcd = param->sampling_factor[0].horizontal;
1802-
int vertical_gcd = param->sampling_factor[0].vertical;
1801+
int horizontal_gcd = info->param.sampling_factor[0].horizontal;
1802+
int vertical_gcd = info->param.sampling_factor[0].vertical;
18031803
for (int i = 1; i < 3; ++i) {
1804-
horizontal_gcd = gcd(horizontal_gcd, param->sampling_factor[i].horizontal);
1805-
vertical_gcd = gcd(vertical_gcd, param->sampling_factor[i].vertical);
1804+
horizontal_gcd = gcd(horizontal_gcd, info->param.sampling_factor[i].horizontal);
1805+
vertical_gcd = gcd(vertical_gcd, info->param.sampling_factor[i].vertical);
18061806
}
18071807
for (int i = 0; i < 3; ++i) {
1808-
param->sampling_factor[i].horizontal /= horizontal_gcd;
1809-
param->sampling_factor[i].vertical /= vertical_gcd;
1808+
info->param.sampling_factor[i].horizontal /= horizontal_gcd;
1809+
info->param.sampling_factor[i].vertical /= vertical_gcd;
18101810
}
18111811

1812-
if (param->sampling_factor[1].horizontal == 1 && param->sampling_factor[1].vertical == 1
1813-
&& param->sampling_factor[2].horizontal == 1 && param->sampling_factor[2].vertical == 1) {
1814-
int sum = param->interleaved << 16 | param->sampling_factor[0].horizontal << 8 |
1815-
param->sampling_factor[0].vertical; // NOLINT
1812+
if (info->param.sampling_factor[1].horizontal == 1 && info->param.sampling_factor[1].vertical == 1
1813+
&& info->param.sampling_factor[2].horizontal == 1 && info->param.sampling_factor[2].vertical == 1) {
1814+
int sum = info->param.interleaved << 16 | info->param.sampling_factor[0].horizontal << 8 |
1815+
info->param.sampling_factor[0].vertical; // NOLINT
18161816
switch (sum) {
1817-
case 1<<16 | 1<<8 | 1: param_image->pixel_format = GPUJPEG_444_U8_P012; break; // NOLINT
1818-
case 0<<16 | 1<<8 | 1: param_image->pixel_format = GPUJPEG_444_U8_P0P1P2; break; // NOLINT
1819-
case 1<<16 | 2<<8 | 1: param_image->pixel_format = GPUJPEG_422_U8_P1020; break; // NOLINT
1820-
case 0<<16 | 2<<8 | 1: param_image->pixel_format = GPUJPEG_422_U8_P0P1P2; break; // NOLINT
1817+
case 1<<16 | 1<<8 | 1: info->param_image.pixel_format = GPUJPEG_444_U8_P012; break; // NOLINT
1818+
case 0<<16 | 1<<8 | 1: info->param_image.pixel_format = GPUJPEG_444_U8_P0P1P2; break; // NOLINT
1819+
case 1<<16 | 2<<8 | 1: info->param_image.pixel_format = GPUJPEG_422_U8_P1020; break; // NOLINT
1820+
case 0<<16 | 2<<8 | 1: info->param_image.pixel_format = GPUJPEG_422_U8_P0P1P2; break; // NOLINT
18211821
case 1<<16 | 2<<8 | 2: // we have only one pixfmt for 420, so use for both NOLINT
1822-
case 0<<16 | 2<<8 | 2: param_image->pixel_format = GPUJPEG_420_U8_P0P1P2; break; // NOLINT
1822+
case 0<<16 | 2<<8 | 2: info->param_image.pixel_format = GPUJPEG_420_U8_P0P1P2; break; // NOLINT
18231823
default: break;
18241824
}
18251825
}
18261826
}
18271827

1828-
if ( param->comp_count == 4 ) {
1828+
if ( info->param.comp_count == 4 ) {
18291829
_Bool subsampling_is4444 = 1;
18301830
for (int i = 1; i < 4; ++i) {
1831-
if (param->sampling_factor[i].horizontal != param->sampling_factor[0].horizontal
1832-
|| param->sampling_factor[i].vertical != param->sampling_factor[0].vertical) {
1831+
if (info->param.sampling_factor[i].horizontal != info->param.sampling_factor[0].horizontal
1832+
|| info->param.sampling_factor[i].vertical != info->param.sampling_factor[0].vertical) {
18331833
subsampling_is4444 = 0;
18341834
break;
18351835
}
18361836
}
18371837
if (subsampling_is4444) {
1838-
param_image->pixel_format = GPUJPEG_4444_U8_P0123;
1838+
info->param_image.pixel_format = GPUJPEG_4444_U8_P0123;
18391839
}
18401840
}
18411841

src/gpujpeg_reader.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file
3-
* Copyright (c) 2011-2023, CESNET z.s.p.o
3+
* Copyright (c) 2011-2025, CESNET zájmové sdružení právnických osob
44
* Copyright (c) 2011, Silicon Genome, LLC.
55
*
66
* All rights reserved.
@@ -32,13 +32,15 @@
3232
#define GPUJPEG_READER_H
3333

3434
#include "../libgpujpeg/gpujpeg_common.h"
35+
#include <stddef.h>
3536

3637
#ifdef __cplusplus
3738
extern "C" {
3839
#endif
3940

4041
/** JPEG decoder structure predeclaration */
4142
struct gpujpeg_decoder;
43+
struct gpujpeg_image_info; // declared in libgpujpeg/gpujpeg_decoder.h
4244

4345
/**
4446
* Read JPEG image from data buffer
@@ -60,15 +62,14 @@ gpujpeg_reader_read_image(struct gpujpeg_decoder* decoder, uint8_t* image, size_
6062
*
6163
* @param image Image data
6264
* @param image_size Image data size
63-
* @param[out] param_image parameters obtained from image, must not be NULL
64-
* @param[in,out] param parameters obtained from image (verbose parameter is used as an input param), non-NULL
65-
* @param[out] segment_count number of segments (may be NULL if parameter segment_count is not needed)
65+
* @param[out] info parameters obtained from image, must not be NULL
66+
* @param[in] flags - 0 or GPUJPEG_COUNT_SEG_COUNT
6667
* @return 0 if succeeds, otherwise nonzero
6768
*
6869
* @todo refactorize common code with gpujpeg_reader_read_image()
6970
*/
7071
int
71-
gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_image_parameters *param_image, struct gpujpeg_parameters *param, int *segment_count);
72+
gpujpeg_reader_get_image_info(uint8_t *image, size_t image_size, struct gpujpeg_image_info *info, int verbose, unsigned flags);
7273

7374
#ifdef __cplusplus
7475
}

src/main.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -200,17 +200,13 @@ static int print_image_info_jpeg(const char *filename, int verbose) {
200200
fprintf(stderr, "Cannot read image contents.\n");
201201
return 1;
202202
}
203-
struct gpujpeg_image_parameters params_image = gpujpeg_default_image_parameters();
204-
params_image.pixel_format = GPUJPEG_PIXFMT_NONE;
205-
struct gpujpeg_parameters params = gpujpeg_default_parameters();
206-
params.verbose = verbose;
207-
int segment_count = 0;
208-
if (gpujpeg_decoder_get_image_info(jpeg, len, &params_image, &params, &segment_count) == 0) {
209-
print_gpujpeg_image_parameters(params_image, false,
210-
gpujpeg_subsampling_get_name(params.comp_count, params.sampling_factor));
211-
printf("interleaved: %d\n", params.interleaved);
212-
if ( segment_count ) {
213-
printf("segment count: %d (DRI = %d)\n", segment_count, params.restart_interval);
203+
struct gpujpeg_image_info info = { 0 };
204+
if (gpujpeg_decoder_get_image_info2(jpeg, len, &info, verbose, GPUJPEG_COUNT_SEG_COUNT_REQ) == 0) {
205+
print_gpujpeg_image_parameters(info.param_image, false,
206+
gpujpeg_subsampling_get_name(info.param.comp_count, info.param.sampling_factor));
207+
printf("interleaved: %d\n", info.param.interleaved);
208+
if ( info.segment_count ) {
209+
printf("segment count: %d (DRI = %d)\n", info.segment_count, info.param.restart_interval);
214210
}
215211
}
216212
free(jpeg);

0 commit comments

Comments
 (0)