Skip to content

Commit 77fe7e6

Browse files
Respect exif orientation
1 parent 5830f8f commit 77fe7e6

File tree

3 files changed

+141
-14
lines changed

3 files changed

+141
-14
lines changed

omxiv.c

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,16 @@ static const struct option longOpts[] = {
4242
{"info", no_argument, 0, 'i'},
4343
{"no-keys", no_argument, 0, 'k'},
4444
{"soft", no_argument, 0, 's'},
45+
{"ignore-exif", no_argument, 0, 0x103},
4546
{0, 0, 0, 0}
4647
};
4748

4849
static ILCLIENT_T *client=NULL;
4950
static char end = 0;
5051

51-
static char info = 0, blank = 0, soft = 0, keys = 1, center = 0;
52+
static char info = 0, blank = 0, soft = 0, keys = 1, center = 0, exifOrient = 1, mirror = 0;
5253
static uint32_t sWidth, sHeight;
53-
static int initRotation = 0;
54+
static int initRotation = 0, rotateInc = 90;
5455

5556
static OMX_RENDER render = INIT_OMX_RENDER, render2;
5657
static OMX_RENDER* pCurRender = &render;
@@ -159,7 +160,8 @@ void printUsage(const char *progr){
159160
printf(" -d --display n Display number\n");
160161
printf(" -i --info Print some additional infos\n");
161162
printf(" -k --no-keys Disable keyboard input\n");
162-
printf(" -s --soft Force software decoding\n\n");
163+
printf(" -s --soft Force software decoding\n");
164+
printf(" --ignore-exif Ignore exif orientation\n\n");
163165
printf("KEY CONFIGURATION:\n\n");
164166
printf(" ESC, q : Quit\n");
165167
printf(" LEFT : Previous image\n");
@@ -211,7 +213,43 @@ static int renderImage(IMAGE *image, ANIM_IMAGE *anim){
211213
}
212214
}
213215

214-
dispConfig.rotation = initRotation;
216+
dispConfig.rotation = 0;
217+
switch(exifOrient){
218+
case 7:
219+
dispConfig.rotation += 90;
220+
case 4:
221+
dispConfig.rotation += 90;
222+
case 5:
223+
dispConfig.rotation += 90;
224+
case 2:
225+
dispConfig.rotation += (360 - initRotation);
226+
if(mirror == 0){
227+
rotateInc = 270;
228+
dispConfig.configFlags |= OMX_DISP_CONFIG_FLAG_MIRROR;
229+
}else{
230+
rotateInc = 90;
231+
dispConfig.configFlags &= ~OMX_DISP_CONFIG_FLAG_MIRROR;
232+
}
233+
break;
234+
case 8:
235+
dispConfig.rotation += 90;
236+
case 3:
237+
dispConfig.rotation += 90;
238+
case 6:
239+
dispConfig.rotation += 90;
240+
case 1:
241+
case 0:
242+
dispConfig.rotation += initRotation;
243+
if(mirror == 1){
244+
rotateInc = 270;
245+
dispConfig.configFlags |= OMX_DISP_CONFIG_FLAG_MIRROR;
246+
}else{
247+
rotateInc = 90;
248+
dispConfig.configFlags &= ~OMX_DISP_CONFIG_FLAG_MIRROR;
249+
}
250+
break;
251+
}
252+
dispConfig.rotation%=360;
215253

216254
if(anim->frameCount < 2){
217255
ret = omxRenderImage(pCurRender, image);
@@ -238,6 +276,8 @@ static int decodeImage(const char *filePath, IMAGE *image, ANIM_IMAGE *anim){
238276
size_t size = 0;
239277
char magNum[8];
240278

279+
exifOrient = (exifOrient == 0) ? 0 : 1;
280+
241281
if(strncmp(filePath, "http://", 7) == 0 || strncmp(filePath, "https://", 8) == 0){
242282
if(info)
243283
printf("Open Url: %s\n", filePath);
@@ -275,6 +315,9 @@ static int decodeImage(const char *filePath, IMAGE *image, ANIM_IMAGE *anim){
275315
return ret;
276316
}
277317

318+
if(exifOrient != 0)
319+
exifOrient = jInfo.orientation;
320+
278321
rewind(imageFile);
279322

280323
if(soft || jInfo.mode == JPEG_MODE_PROGRESSIVE || jInfo.nColorComponents != 3){
@@ -420,8 +463,7 @@ int main(int argc, char *argv[]){
420463
dispConfig.rotation = initRotation;
421464
break;
422465
case 'm':
423-
dispConfig.configFlags |= OMX_DISP_CONFIG_FLAG_MIRROR;
424-
break;
466+
mirror = 1; break;
425467
case 'l':
426468
dispConfig.layer = strtol(optarg, NULL, 10);
427469
break;
@@ -434,6 +476,8 @@ int main(int argc, char *argv[]){
434476
keys = 0; break;
435477
case 's':
436478
soft = 1; break;
479+
case 0x103:
480+
exifOrient = 0; break;
437481
default:
438482
return EXIT_FAILURE;
439483
}
@@ -544,6 +588,7 @@ int main(int argc, char *argv[]){
544588
}else if(c == 'm' || c =='M'){
545589
tcflush(0, TCIFLUSH);
546590
dispConfig.configFlags^= OMX_DISP_CONFIG_FLAG_MIRROR;
591+
rotateInc = (rotateInc + 180)%360;
547592
ret = setOmxDisplayConfig(pCurRender);
548593
if(ret != 0){
549594
fprintf(stderr, "dispConfig set returned 0x%x\n", ret);
@@ -556,18 +601,14 @@ int main(int argc, char *argv[]){
556601
c = getch(1);
557602
tcflush(0, TCIFLUSH);
558603
if(c == 0x41){
559-
if(dispConfig.rotation>0)
560-
dispConfig.rotation-= 90;
561-
else
562-
dispConfig.rotation=270;
604+
dispConfig.rotation = (dispConfig.rotation + 360 -rotateInc)%360;
563605
ret = setOmxDisplayConfig(pCurRender);
564606
if(ret != 0){
565607
fprintf(stderr, "dispConfig set returned 0x%x\n", ret);
566608
break;
567609
}
568610
}else if(c == 0x42){
569-
dispConfig.rotation+= 90;
570-
dispConfig.rotation%=360;
611+
dispConfig.rotation = (dispConfig.rotation + rotateInc)%360;
571612
ret = setOmxDisplayConfig(pCurRender);
572613
if(ret != 0){
573614
fprintf(stderr, "dispConfig set returned 0x%x\n", ret);

soft_image.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
#define MIN_FRAME_DELAY_CS 2
4343
#define BUMP_UP_FRAME_DELAY_CS 10
4444

45+
static const char magExif[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
46+
4547
struct my_error_mgr {
4648
struct jpeg_error_mgr pub;
4749
jmp_buf setjmp_buffer;
@@ -73,6 +75,7 @@ int readJpegHeader(FILE *infile, JPEG_INFO *jpegInfo){
7375

7476
jpeg_create_decompress(&cinfo);
7577
jpeg_stdio_src(&cinfo, infile);
78+
jpeg_save_markers(&cinfo, JPEG_APP0+1, 0xffff);
7679
jpeg_read_header(&cinfo, TRUE);
7780

7881
if(cinfo.progressive_mode)
@@ -82,6 +85,88 @@ int readJpegHeader(FILE *infile, JPEG_INFO *jpegInfo){
8285

8386
jpegInfo->nColorComponents = cinfo.num_components;
8487

88+
89+
// read EXIF orientation
90+
// losely base on: http://sylvana.net/jpegcrop/jpegexiforient.c
91+
jpegInfo->orientation = 1; // Default
92+
jpeg_saved_marker_ptr pMarker = cinfo.marker_list;
93+
94+
if(pMarker != NULL && pMarker->data_length >= 20 &&
95+
memcmp(pMarker->data, magExif, sizeof(magExif)) == 0) {
96+
97+
unsigned int exifLen = pMarker->data_length;
98+
uint8_t* exifData = pMarker->data;
99+
short motorola;
100+
101+
// byte order
102+
if(exifData[6] == 0x49 && exifData[7] == 0x49)
103+
motorola = 0;
104+
else if(exifData[6] == 0x4D && exifData[7] == 0x4D)
105+
motorola = 1;
106+
else
107+
goto cleanExit;
108+
109+
if (motorola) {
110+
if(exifData[8] != 0 || exifData[9] != 0x2A)
111+
goto cleanExit;
112+
} else {
113+
if(exifData[9] != 0 || exifData[8] != 0x2A)
114+
goto cleanExit;
115+
}
116+
117+
unsigned int offset;
118+
// read offset to IFD0
119+
if(motorola) {
120+
if (exifData[10] != 0 || exifData[11] != 0)
121+
goto cleanExit;
122+
offset = (exifData[12]<<8) + exifData[13] + 6;
123+
} else {
124+
if (exifData[12] != 0 || exifData[13] != 0)
125+
goto cleanExit;
126+
offset = (exifData[11]<<8) + exifData[10] + 6;
127+
}
128+
if(offset > exifLen - 14)
129+
goto cleanExit;
130+
131+
unsigned int nTags;
132+
133+
// read number of tags in IFD0
134+
if(motorola)
135+
nTags = (exifData[offset]<<8) + exifData[offset+1];
136+
else
137+
nTags = (exifData[offset+1]<<8) + exifData[offset];
138+
139+
offset += 2;
140+
141+
while(1) {
142+
if (nTags-- == 0 || offset > exifLen - 12)
143+
goto cleanExit;
144+
145+
unsigned int tag;
146+
if (motorola)
147+
tag = (exifData[offset]<<8) + exifData[offset+1];
148+
else
149+
tag = (exifData[offset+1]<<8) + exifData[offset];
150+
151+
if (tag == 0x0112) break; // orientation tag found
152+
153+
offset += 12;
154+
}
155+
156+
unsigned char orientation = 9;
157+
158+
if (motorola && exifData[offset+8] == 0) {
159+
orientation = exifData[offset+9];
160+
} else if(exifData[offset+9] == 0) {
161+
orientation = exifData[offset+8];
162+
}
163+
164+
if (orientation <= 8 && orientation != 0)
165+
jpegInfo->orientation = orientation;
166+
}
167+
168+
cleanExit:
169+
85170
jpeg_destroy_decompress(&cinfo);
86171

87172
return SOFT_IMAGE_OK;

soft_image.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ void destroyAnimIm(ANIM_IMAGE *animIm);
4545
#define JPEG_MODE_NON_PROGRESSIVE 1
4646

4747
typedef struct JPEG_INFO {
48-
int nColorComponents;
49-
int mode;
48+
int nColorComponents; // number of color components
49+
int mode; // progressive or non progressive
50+
char orientation; // orientation according to exif tag (1..8, default: 1)
5051
} JPEG_INFO;
5152

5253
int readJpegHeader(FILE *jpegFile, JPEG_INFO *jpegInfo);

0 commit comments

Comments
 (0)