Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: third_party/gif_player/src/jp/tomorrowkey/android/gifplayer/BaseGifImage.java

Issue 1343913002: Introduce Animated Logo to Chrome on Android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: lots of renamings Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 package jp.tomorrowkey.android.gifplayer;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.nio.ByteBuffer;
7
8 /**
9 * A base wrapper for GIF image data.
10 */
11 public class BaseGifImage {
12 private final byte[] mData;
13 private final int mOffset;
14 private int mWidth;
15 private int mHeight;
16
17 private static final byte[] sColorTableBuffer = new byte[256 * 3];
18
19 int mHeaderSize;
20 boolean mGlobalColorTableUsed;
21 boolean mError;
22 int[] mGlobalColorTable = new int[256];
23 int mGlobalColorTableSize;
24 int mBackgroundColor;
25 int mBackgroundIndex;
26
27 public BaseGifImage(byte[] data) {
28 this(data, 0);
29 }
30
31 /**
32 * Unlike the desktop JVM, ByteBuffers created with allocateDirect() can (an d since froyo, do)
33 * provide a backing array, enabling zero-copy interop with native code. How ever, they are
34 * aligned on a byte boundary, meaning that they often have an arrayOffset a s well - in those
35 * cases, we can avoid allocating large byte arrays and a copy.
36 */
37 public BaseGifImage(ByteBuffer data) {
38 this(bufferToArray(data), bufferToOffset(data));
39 }
40
41 private static int bufferToOffset(ByteBuffer buffer) {
42 return buffer.hasArray() ? buffer.arrayOffset() : 0;
43 }
44
45 private static byte[] bufferToArray(ByteBuffer buffer) {
46 if (buffer.hasArray()) {
47 return buffer.array();
48 } else {
49 int position = buffer.position();
50 try {
51 byte[] newData = new byte[buffer.capacity()];
52 buffer.get(newData);
53 return newData;
54 } finally {
55 buffer.position(position);
56 }
57 }
58 }
59
60 public BaseGifImage(byte[] data, int offset) {
61 mData = data;
62 mOffset = offset;
63
64 GifHeaderStream stream = new GifHeaderStream(data);
65 stream.skip(offset);
66 try {
67 readHeader(stream);
68 mHeaderSize = stream.getPosition();
69 } catch (IOException e) {
70 mError = true;
71 }
72
73 try {
74 stream.close();
75 } catch (IOException e) {
76 // Ignore
77 }
78 }
79
80 public byte[] getData() {
81 return mData;
82 }
83
84 public int getDataOffset() {
85 return mOffset;
86 }
87
88 public int getWidth() {
89 return mWidth;
90 }
91
92 public int getHeight() {
93 return mHeight;
94 }
95
96 /**
97 * Returns an estimate of the size of the object in bytes.
98 */
99 public int getSizeEstimate() {
100 return mData.length + mGlobalColorTable.length * 4;
101 }
102
103 /**
104 * Reads GIF file header information.
105 */
106 private void readHeader(InputStream stream) throws IOException {
107 boolean valid = stream.read() == 'G';
108 valid = valid && stream.read() == 'I';
109 valid = valid && stream.read() == 'F';
110 if (!valid) {
111 mError = true;
112 return;
113 }
114
115 // Skip the next three letter, which represent the variation of the GIF standard.
116 stream.skip(3);
117
118 readLogicalScreenDescriptor(stream);
119
120 if (mGlobalColorTableUsed && !mError) {
121 readColorTable(stream, mGlobalColorTable, mGlobalColorTableSize);
122 mBackgroundColor = mGlobalColorTable[mBackgroundIndex];
123 }
124 }
125
126 /**
127 * Reads Logical Screen Descriptor
128 */
129 private void readLogicalScreenDescriptor(InputStream stream) throws IOExcept ion {
130 // logical screen size
131 mWidth = readShort(stream);
132 mHeight = readShort(stream);
133 // packed fields
134 int packed = stream.read();
135 mGlobalColorTableUsed = (packed & 0x80) != 0; // 1 : global color table flag
136 // 2-4 : color resolution - ignore
137 // 5 : gct sort flag - ignore
138 mGlobalColorTableSize = 2 << (packed & 7); // 6-8 : gct size
139 mBackgroundIndex = stream.read();
140 stream.skip(1); // pixel aspect ratio - ignore
141 }
142
143 /**
144 * Reads color table as 256 RGB integer values
145 *
146 * @param ncolors int number of colors to read
147 */
148 static boolean readColorTable(InputStream stream, int[] colorTable, int ncol ors)
149 throws IOException {
150 synchronized (sColorTableBuffer) {
151 int nbytes = 3 * ncolors;
152 int n = stream.read(sColorTableBuffer, 0, nbytes);
153 if (n < nbytes) {
154 return false;
155 } else {
156 int i = 0;
157 int j = 0;
158 while (i < ncolors) {
159 int r = sColorTableBuffer[j++] & 0xff;
160 int g = sColorTableBuffer[j++] & 0xff;
161 int b = sColorTableBuffer[j++] & 0xff;
162 colorTable[i++] = 0xff000000 | (r << 16) | (g << 8) | b;
163 }
164 }
165 }
166
167 return true;
168 }
169
170 /**
171 * Reads next 16-bit value, LSB first
172 */
173 private int readShort(InputStream stream) throws IOException {
174 // read 16-bit value, LSB first
175 return stream.read() | (stream.read() << 8);
176 }
177
178 private final class GifHeaderStream extends ByteArrayInputStream {
179
180 private GifHeaderStream(byte[] buf) {
181 super(buf);
182 }
183
184 public int getPosition() {
185 return pos;
186 }
187 }
188 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698