Skip to content

Commit 3de1e5a

Browse files
committed
SPIFF: handle orieintation
1 parent 06f1886 commit 3de1e5a

File tree

3 files changed

+43
-23
lines changed

3 files changed

+43
-23
lines changed

src/gpujpeg_marker.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @file
3-
* Copyright (c) 2011-2024, CESNET
3+
* Copyright (c) 2011-2025, CESNET, zájmové sdružení právnických osob
44
* Copyright (c) 2011, Silicon Genome, LLC.
55
*/
66
/*
@@ -111,6 +111,7 @@ enum gpujpeg_marker_code {
111111
#define SPIFF_VERSION 0x100 // Version 1.00
112112
#define SPIFF_COMPRESSION_JPEG 5
113113
#define SPIFF_ENTRY_TAG_EOD 0x1
114+
#define SPIFF_ENTRY_TAG_ORIENATAION 0x4
114115
#define SPIFF_ENTRY_TAG_EOD_LENGHT 8 // length is 2 bytes longer for EOD to contain also following SOI
115116
#define SPIFF_MARKER_LEN 32 ///< including length field
116117

src/gpujpeg_reader.c

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
#include <string.h> // for memcmp, strlen, memcpy
3636

3737
#include "../libgpujpeg/gpujpeg_decoder.h"
38-
#include "../libgpujpeg/gpujpeg_encoder.h" // for enum gpujpeg_header_type
38+
#include "../libgpujpeg/gpujpeg_type.h" // for gpujpeg_color_space, gpuj...
3939
#include "gpujpeg_decoder_internal.h"
4040
#include "gpujpeg_exif.h"
4141
#include "gpujpeg_marker.h"
@@ -446,32 +446,42 @@ gpujpeg_reader_read_spiff_header(uint8_t** image, int verbose, enum gpujpeg_colo
446446
/** @retval -1 error
447447
* @retval 0 no error */
448448
static int
449-
gpujpeg_reader_read_spiff_directory(uint8_t** image, const uint8_t* image_end, int verbose, int length, _Bool *in_spiff)
449+
gpujpeg_reader_read_spiff_directory(uint8_t** image, struct gpujpeg_reader *reader, int length)
450450
{
451451
if ( length < 8 ) { // ELEN at least 8
452452
ERROR_MSG("APP8 SPIFF directory too short (%d bytes)\n", length);
453453
image += length - 2;
454454
return -1;
455455
}
456456
uint32_t tag = gpujpeg_reader_read_4byte(*image);
457-
DEBUG2_MSG(verbose, "Read SPIFF tag 0x%x with length %d.\n", tag, length);
457+
DEBUG2_MSG(reader->param.verbose, "Read SPIFF tag 0x%x with length %d.\n", tag, length);
458458
if ( tag == SPIFF_ENTRY_TAG_EOD && length == SPIFF_ENTRY_TAG_EOD_LENGHT ) {
459-
int marker_soi = gpujpeg_reader_read_marker(image, image_end, verbose);
459+
int marker_soi = gpujpeg_reader_read_marker(image, reader->image_end, reader->param.verbose);
460460
if ( marker_soi != GPUJPEG_MARKER_SOI ) {
461-
VERBOSE_MSG(verbose, "SPIFF entry 0x1 should be followed directly with SOI.\n");
461+
VERBOSE_MSG(reader->param.verbose, "SPIFF entry 0x1 should be followed directly with SOI.\n");
462462
return -1;
463463
}
464-
DEBUG2_MSG(verbose, "SPIFF EOD presented.\n");
465-
*in_spiff = 0;
464+
DEBUG2_MSG(reader->param.verbose, "SPIFF EOD presented.\n");
465+
reader->in_spiff = false;
466466
return 0;
467467
}
468468

469469
if ( tag >> 24U != 0 ) { // given by the standard
470-
VERBOSE_MSG(verbose, "Erroneous SPIFF tag 0x%x (first byte should be 0).", tag);
470+
VERBOSE_MSG(reader->param.verbose, "Erroneous SPIFF tag 0x%x (first byte should be 0).", tag);
471471
*image += length - 6;
472472
return 0;
473473
}
474-
DEBUG2_MSG(verbose, "SPIFF tag 0x%x with length %d presented.\n", tag, length);
474+
if ( tag == SPIFF_ENTRY_TAG_ORIENATAION ) {
475+
int rotation = gpujpeg_reader_read_byte(*image);
476+
bool flip = gpujpeg_reader_read_byte(*image);
477+
reader->metadata.vals[GPUJPEG_METADATA_ORIENTATION].orient.rotation = rotation;
478+
reader->metadata.vals[GPUJPEG_METADATA_ORIENTATION].orient.flip = flip;
479+
reader->metadata.vals[GPUJPEG_METADATA_ORIENTATION].set = 1;
480+
DEBUG_MSG(reader->param.verbose, "SPIFF CW rotation: %d deg%s\n", rotation * 90, flip ? ", mirrored" : "");
481+
*image += 2; // 2 bytes reserved
482+
return 0;
483+
}
484+
DEBUG2_MSG(reader->param.verbose, "Unhandled SPIFF tag 0x%x with length %d presented.\n", tag, length);
475485
*image += length - 6;
476486
return 0;
477487
}
@@ -487,26 +497,25 @@ gpujpeg_reader_read_spiff_directory(uint8_t** image, const uint8_t* image_end, i
487497
* @return 0 if succeeds, otherwise nonzero
488498
*/
489499
static int
490-
gpujpeg_reader_read_app8(uint8_t** image, const uint8_t* image_end, enum gpujpeg_color_space* color_space,
491-
enum gpujpeg_header_type* header_type, int verbose, _Bool* in_spiff)
500+
gpujpeg_reader_read_app8(uint8_t** image, struct gpujpeg_reader* reader)
492501
{
493-
if(image_end - *image < 2) {
502+
if ( reader->image_end - *image < 2 ) {
494503
fprintf(stderr, "[GPUJPEG] [Error] Could not read APP8 marker length (end of data)\n");
495504
return -1;
496505
}
497506
int length = gpujpeg_reader_read_2byte(*image);
498507
length -= 2;
499-
if(image_end - *image < length) {
508+
if ( reader->image_end - *image < length ) {
500509
fprintf(stderr, "[GPUJPEG] [Error] APP8 marker goes beyond end of data\n");
501510
return -1;
502511
}
503512

504-
if (*in_spiff) {
505-
return gpujpeg_reader_read_spiff_directory(image, image_end, verbose, length + 2, in_spiff);
513+
if ( reader->in_spiff ) {
514+
return gpujpeg_reader_read_spiff_directory(image, reader, length + 2);
506515
}
507516

508517
if (length + 2 != SPIFF_MARKER_LEN) {
509-
VERBOSE_MSG(verbose, "APP8 segment length is %d, expected 32 for SPIFF.\n", length + 2);
518+
VERBOSE_MSG(reader->param.verbose, "APP8 segment length is %d, expected 32 for SPIFF.\n", length + 2);
510519
*image += length;
511520
return 0;
512521
}
@@ -522,13 +531,15 @@ gpujpeg_reader_read_app8(uint8_t** image, const uint8_t* image_end, enum gpujpeg
522531
length -= sizeof marker_name;
523532

524533
if (strcmp(marker_name, spiff_marker_name) != 0) {
525-
VERBOSE_MSG(verbose, "APP8 marker identifier should be 'SPIFF\\0' but '%-6.6s' was presented!\n", marker_name);
534+
VERBOSE_MSG(reader->param.verbose, "APP8 marker identifier should be 'SPIFF\\0' but '%-6.6s' was presented!\n",
535+
marker_name);
526536
*image += length - 2;
527537
return 0;
528538
}
529539

530-
*header_type = GPUJPEG_HEADER_SPIFF;
531-
return gpujpeg_reader_read_spiff_header(image, verbose, color_space, in_spiff);
540+
reader->header_type = GPUJPEG_HEADER_SPIFF;
541+
return gpujpeg_reader_read_spiff_header(image, reader->param.verbose, &reader->header_color_space,
542+
&reader->in_spiff);
532543
}
533544

534545
/**
@@ -1391,8 +1402,7 @@ gpujpeg_reader_read_common_markers(uint8_t** image, int marker, struct gpujpeg_r
13911402
gpujpeg_reader_read_app1(image, reader);
13921403
break;
13931404
case GPUJPEG_MARKER_APP8:
1394-
if ( gpujpeg_reader_read_app8(image, reader->image_end, &reader->header_color_space, &reader->header_type,
1395-
reader->param.verbose, &reader->in_spiff) != 0 ) {
1405+
if ( gpujpeg_reader_read_app8(image, reader) != 0 ) {
13961406
return -1;
13971407
}
13981408
break;

src/gpujpeg_writer.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,14 @@ static void gpujpeg_writer_write_spiff_directory_eod(struct gpujpeg_writer* writ
225225
static void gpujpeg_writer_write_spiff_directory(struct gpujpeg_encoder* encoder)
226226
{
227227
struct gpujpeg_writer* writer = encoder->writer;
228+
if ( encoder->writer->metadata.vals[GPUJPEG_METADATA_ORIENTATION].set ) {
229+
gpujpeg_writer_write_app8(writer);
230+
gpujpeg_writer_emit_2byte(writer, 10);
231+
gpujpeg_writer_emit_4byte(writer, SPIFF_ENTRY_TAG_ORIENATAION);
232+
gpujpeg_writer_emit_byte(writer, encoder->writer->metadata.vals[GPUJPEG_METADATA_ORIENTATION].orient.rotation);
233+
gpujpeg_writer_emit_byte(writer, encoder->writer->metadata.vals[GPUJPEG_METADATA_ORIENTATION].orient.flip);
234+
gpujpeg_writer_emit_2byte(writer, 0); // reserved
235+
}
228236
gpujpeg_writer_write_spiff_directory_eod(writer); // this must be last directory entry
229237
}
230238

@@ -446,7 +454,8 @@ gpujpeg_writer_write_header(struct gpujpeg_encoder* encoder)
446454

447455
switch (encoder->header_type) {
448456
case GPUJPEG_HEADER_DEFAULT:
449-
if ( encoder->coder.param.comp_count == 4 ) {
457+
if ( encoder->coder.param.comp_count == 4 ||
458+
encoder->writer->metadata.vals[GPUJPEG_METADATA_ORIENTATION].set ) {
450459
gpujpeg_writer_write_spiff(encoder);
451460
} else {
452461
switch (encoder->coder.param.color_space_internal) {

0 commit comments

Comments
 (0)