File: JpegSegmentData.java

package info (click to toggle)
libmetadata-extractor-java 2.11.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster, forky, sid, trixie
  • size: 6,416 kB
  • sloc: java: 35,343; xml: 200; sh: 11; makefile: 2
file content (270 lines) | stat: -rw-r--r-- 9,690 bytes parent folder | download | duplicates (2)
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/*
 * Copyright 2002-2017 Drew Noakes
 *
 *    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.
 *
 * More information about this project is available at:
 *
 *    https://drewnoakes.com/code/exif/
 *    https://github.com/drewnoakes/metadata-extractor
 */
package com.drew.imaging.jpeg;

import com.drew.lang.annotations.NotNull;
import com.drew.lang.annotations.Nullable;

import java.util.*;

/**
 * Holds a collection of JPEG data segments.  This need not necessarily be all segments
 * within the JPEG. For example, it may be convenient to store only the non-image
 * segments when analysing metadata.
 * <p>
 * Segments are keyed via their {@link JpegSegmentType}. Where multiple segments use the
 * same segment type, they will all be stored and available.
 * <p>
 * Each segment type may contain multiple entries. Conceptually the model is:
 * <code>Map&lt;JpegSegmentType, Collection&lt;byte[]&gt;&gt;</code>. This class provides
 * convenience methods around that structure.
 *
 * @author Drew Noakes https://drewnoakes.com
 */
public class JpegSegmentData
{
    // TODO key this on JpegSegmentType rather than Byte, and hopefully lose much of the use of 'byte' with this class
    @NotNull
    private final HashMap<Byte, List<byte[]>> _segmentDataMap = new HashMap<Byte, List<byte[]>>(10);

    /**
     * Adds segment bytes to the collection.
     *
     * @param segmentType  the type of the segment being added
     * @param segmentBytes the byte array holding data for the segment being added
     */
    @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
    public void addSegment(byte segmentType, @NotNull byte[] segmentBytes)
    {
        getOrCreateSegmentList(segmentType).add(segmentBytes);
    }

    /**
     * Gets the set of JPEG segment type identifiers.
     */
    public Iterable<JpegSegmentType> getSegmentTypes()
    {
        Set<JpegSegmentType> segmentTypes = new HashSet<JpegSegmentType>();

        for (Byte segmentTypeByte : _segmentDataMap.keySet())
        {
            JpegSegmentType segmentType = JpegSegmentType.fromByte(segmentTypeByte);
            if (segmentType == null) {
                throw new IllegalStateException("Should not have a segmentTypeByte that is not in the enum: " + Integer.toHexString(segmentTypeByte));
            }
            segmentTypes.add(segmentType);
        }

        return segmentTypes;
    }

    /**
     * Gets the first JPEG segment data for the specified type.
     *
     * @param segmentType the JpegSegmentType for the desired segment
     * @return a byte[] containing segment data or null if no data exists for that segment
     */
    @Nullable
    public byte[] getSegment(byte segmentType)
    {
        return getSegment(segmentType, 0);
    }

    /**
     * Gets the first JPEG segment data for the specified type.
     *
     * @param segmentType the JpegSegmentType for the desired segment
     * @return a byte[] containing segment data or null if no data exists for that segment
     */
    @Nullable
    public byte[] getSegment(@NotNull JpegSegmentType segmentType)
    {
        return getSegment(segmentType.byteValue, 0);
    }

    /**
     * Gets segment data for a specific occurrence and type.  Use this method when more than one occurrence
     * of segment data for a given type exists.
     *
     * @param segmentType identifies the required segment
     * @param occurrence  the zero-based index of the occurrence
     * @return the segment data as a byte[], or null if no segment exists for the type &amp; occurrence
     */
    @Nullable
    public byte[] getSegment(@NotNull JpegSegmentType segmentType, int occurrence)
    {
        return getSegment(segmentType.byteValue, occurrence);
    }

    /**
     * Gets segment data for a specific occurrence and type.  Use this method when more than one occurrence
     * of segment data for a given type exists.
     *
     * @param segmentType identifies the required segment
     * @param occurrence  the zero-based index of the occurrence
     * @return the segment data as a byte[], or null if no segment exists for the type &amp; occurrence
     */
    @Nullable
    public byte[] getSegment(byte segmentType, int occurrence)
    {
        final List<byte[]> segmentList = getSegmentList(segmentType);

        return segmentList != null && segmentList.size() > occurrence
                ? segmentList.get(occurrence)
                : null;
    }

    /**
     * Returns all instances of a given JPEG segment.  If no instances exist, an empty sequence is returned.
     *
     * @param segmentType a number which identifies the type of JPEG segment being queried
     * @return zero or more byte arrays, each holding the data of a JPEG segment
     */
    @NotNull
    public Iterable<byte[]> getSegments(@NotNull JpegSegmentType segmentType)
    {
        return getSegments(segmentType.byteValue);
    }

    /**
     * Returns all instances of a given JPEG segment.  If no instances exist, an empty sequence is returned.
     *
     * @param segmentType a number which identifies the type of JPEG segment being queried
     * @return zero or more byte arrays, each holding the data of a JPEG segment
     */
    @NotNull
    public Iterable<byte[]> getSegments(byte segmentType)
    {
        final List<byte[]> segmentList = getSegmentList(segmentType);
        return segmentList == null ? new ArrayList<byte[]>() : segmentList;
    }

    @Nullable
    private List<byte[]> getSegmentList(byte segmentType)
    {
        return _segmentDataMap.get(segmentType);
    }

    @NotNull
    private List<byte[]> getOrCreateSegmentList(byte segmentType)
    {
        List<byte[]> segmentList;
        if (_segmentDataMap.containsKey(segmentType)) {
            segmentList = _segmentDataMap.get(segmentType);
        } else {
            segmentList = new ArrayList<byte[]>();
            _segmentDataMap.put(segmentType, segmentList);
        }
        return segmentList;
    }

    /**
     * Returns the count of segment data byte arrays stored for a given segment type.
     *
     * @param segmentType identifies the required segment
     * @return the segment count (zero if no segments exist).
     */
    public int getSegmentCount(@NotNull JpegSegmentType segmentType)
    {
        return getSegmentCount(segmentType.byteValue);
    }

    /**
     * Returns the count of segment data byte arrays stored for a given segment type.
     *
     * @param segmentType identifies the required segment
     * @return the segment count (zero if no segments exist).
     */
    public int getSegmentCount(byte segmentType)
    {
        final List<byte[]> segmentList = getSegmentList(segmentType);
        return segmentList == null ? 0 : segmentList.size();
    }

    /**
     * Removes a specified instance of a segment's data from the collection.  Use this method when more than one
     * occurrence of segment data exists for a given type exists.
     *
     * @param segmentType identifies the required segment
     * @param occurrence  the zero-based index of the segment occurrence to remove.
     */
    @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
    public void removeSegmentOccurrence(@NotNull JpegSegmentType segmentType, int occurrence)
    {
        removeSegmentOccurrence(segmentType.byteValue, occurrence);
    }

    /**
     * Removes a specified instance of a segment's data from the collection.  Use this method when more than one
     * occurrence of segment data exists for a given type exists.
     *
     * @param segmentType identifies the required segment
     * @param occurrence  the zero-based index of the segment occurrence to remove.
     */
    @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
    public void removeSegmentOccurrence(byte segmentType, int occurrence)
    {
        final List<byte[]> segmentList = _segmentDataMap.get(segmentType);
        segmentList.remove(occurrence);
    }

    /**
     * Removes all segments from the collection having the specified type.
     *
     * @param segmentType identifies the required segment
     */
    public void removeSegment(@NotNull JpegSegmentType segmentType)
    {
        removeSegment(segmentType.byteValue);
    }

    /**
     * Removes all segments from the collection having the specified type.
     *
     * @param segmentType identifies the required segment
     */
    public void removeSegment(byte segmentType)
    {
        _segmentDataMap.remove(segmentType);
    }

    /**
     * Determines whether data is present for a given segment type.
     *
     * @param segmentType identifies the required segment
     * @return true if data exists, otherwise false
     */
    public boolean containsSegment(@NotNull JpegSegmentType segmentType)
    {
        return containsSegment(segmentType.byteValue);
    }

    /**
     * Determines whether data is present for a given segment type.
     *
     * @param segmentType identifies the required segment
     * @return true if data exists, otherwise false
     */
    public boolean containsSegment(byte segmentType)
    {
        return _segmentDataMap.containsKey(segmentType);
    }
}