1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
/*
* Copyright Samsung Electronics Co.,LTD.
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __HARDWARE_SAMSUNG_SLSI_EXYNOS_APPMARKER_WRITER_H__
#define __HARDWARE_SAMSUNG_SLSI_EXYNOS_APPMARKER_WRITER_H__
#include <ExynosExif.h>
#include "hwjpeg-internal.h"
#include "include/hardware/exynos/ExynosExif.h"
#define JPEG_MAX_SEGMENT_SIZE ((1 << 16) - 1)
#define JPEG_MARKER_SIZE 2
#define JPEG_SEGMENT_LENFIELD_SIZE 2
#define JPEG_APP1_OEM_RESERVED 200
#define IFD_FIELDCOUNT_SIZE 2
#define IFD_NEXTIFDOFFSET_SIZE 4
#define IFD_TAG_SIZE 2
#define IFD_TYPE_SIZE 2
#define IFD_COUNT_SIZE 4
#define IFD_VALOFF_SIZE 4
#define IFD_FIELD_SIZE (IFD_TAG_SIZE + IFD_TYPE_SIZE + IFD_COUNT_SIZE + IFD_VALOFF_SIZE)
#define EXTRA_APPMARKER_MIN 2
#define EXTRA_APPMARKER_LIMIT 10
#define MAX_GPS_PROCESSINGMETHOD_SIZE 108
#define EXIF_SUBSECTIME_LENGTH 5
#define EXIF_DATETIME_LENGTH 20
#define EXIF_GPSDATESTAMP_LENGTH 11
class CAppMarkerWriter {
char *m_pAppBase;
char *m_pApp1End;
size_t m_szMaxThumbSize; // Maximum available thumbnail stream size minus JPEG_MARKER_SIZE
uint16_t m_szApp1; // The size of APP1 segment without marker
uint16_t m_szApp11; // The size of APP11 segment without marker
uint16_t m_n0thIFDFields;
uint16_t m_n1stIFDFields;
uint16_t m_nExifIFDFields;
uint16_t m_nGPSIFDFields;
exif_attribute_t *m_pExif;
extra_appinfo_t *m_pExtra;
uint32_t m_szMake;
uint32_t m_szSoftware;
uint32_t m_szModel;
uint32_t m_szUniqueID;
char *m_pMainBase;
// The address to write compressed stream of the thumbnail image
char *m_pThumbBase;
// points to the "ValueOffset" field of JPEGInterchangeFormatLen tag of 1st IFD
// This should be updated after compression of thumbnail image.
// Note that the address may not be aligned by 32-bit.
char *m_pThumbSizePlaceholder;
void Init();
char *WriteAPP1(char *base, bool reserve_thumbnail_space, bool updating = false);
char *WriteAPPX(char *base, bool just_reserve);
char *WriteAPP11(char *current, size_t dummy, size_t align);
public:
// dummy: number of dummy bytes written by the compressor of the main image
// this dummy size should be added to the APP1 length. Howerver, this dummy area
// for the main image stream should not be written by neither of appwriter nor
// thumbnail compressor.
CAppMarkerWriter();
CAppMarkerWriter(char *base, exif_attribute_t *exif, debug_attribute_t *debug);
~CAppMarkerWriter() {}
void PrepareAppWriter(char *base, exif_attribute_t *exif, extra_appinfo_t *info);
char *GetMainStreamBase() { return m_pMainBase; }
char *GetThumbStreamBase() { return m_pThumbBase; }
char *GetThumbStreamSizeAddr() {
char *p = m_pThumbSizePlaceholder;
m_pThumbSizePlaceholder = NULL;
return p;
}
size_t GetMaxThumbnailSize() { return m_szMaxThumbSize; }
size_t GetAPP1ResrevedSize() { return JPEG_APP1_OEM_RESERVED; }
// CalculateAPPSize() is valid after Write() is successful.
size_t CalculateAPPSize(size_t thumblen = JPEG_MAX_SEGMENT_SIZE) {
size_t appsize = 0;
if (m_szApp1 > 0) appsize += m_szApp1 + JPEG_MARKER_SIZE;
if (m_pExtra) {
for (int idx = 0; idx < m_pExtra->num_of_appmarker; idx++)
appsize += m_pExtra->appInfo[idx].dataSize + +JPEG_MARKER_SIZE +
JPEG_SEGMENT_LENFIELD_SIZE;
}
if (IsThumbSpaceReserved())
appsize += m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED;
else
appsize += min(m_szMaxThumbSize, thumblen);
return appsize + m_szApp11;
}
char *GetApp1End() { return m_pApp1End; }
void Write(bool reserve_thumbnail_space, size_t dummy, size_t align,
bool reserve_debug = false) {
m_pApp1End = WriteAPP1(m_pAppBase, reserve_thumbnail_space);
char *appXend = WriteAPPX(m_pApp1End, reserve_debug);
char *app11end = WriteAPP11(appXend, dummy, align);
m_szApp11 = PTR_DIFF(appXend, app11end);
m_pMainBase = app11end - dummy;
}
void Update() { WriteAPP1(m_pAppBase, false, true); }
bool IsThumbSpaceReserved() {
return PTR_DIFF(m_pAppBase, m_pApp1End) ==
(m_szApp1 + m_szMaxThumbSize + JPEG_APP1_OEM_RESERVED + JPEG_MARKER_SIZE);
}
void Finalize(size_t thumbsize);
void UpdateApp1Size(size_t amount);
};
#endif //__HARDWARE_SAMSUNG_SLSI_EXYNOS_APPMARKER_WRITER_H__
|