OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. | 2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
152 // The condition check is taken out of the loop to enhance performance. | 152 // The condition check is taken out of the loop to enhance performance. |
153 // This optimization reduces decoding time by about 15% for a 3MB image. | 153 // This optimization reduces decoding time by about 15% for a 3MB image. |
154 if (write_transparent_pixels) { | 154 if (write_transparent_pixels) { |
155 for (; row_begin != row_end; ++row_begin, ++current_address) { | 155 for (; row_begin != row_end; ++row_begin, ++current_address) { |
156 const size_t source_value = *row_begin; | 156 const size_t source_value = *row_begin; |
157 if ((source_value != transparent_pixel) && | 157 if ((source_value != transparent_pixel) && |
158 (source_value < color_table.size())) { | 158 (source_value < color_table.size())) { |
159 *current_address = color_table_iter[source_value]; | 159 *current_address = color_table_iter[source_value]; |
160 } else { | 160 } else { |
161 *current_address = 0; | 161 *current_address = 0; |
162 current_buffer_saw_alpha_ = true; | |
163 } | 162 } |
164 } | 163 } |
165 } else { | 164 } else { |
166 for (; row_begin != row_end; ++row_begin, ++current_address) { | 165 for (; row_begin != row_end; ++row_begin, ++current_address) { |
167 const size_t source_value = *row_begin; | 166 const size_t source_value = *row_begin; |
168 if ((source_value != transparent_pixel) && | 167 if ((source_value != transparent_pixel) && |
169 (source_value < color_table.size())) | 168 (source_value < color_table.size())) |
170 *current_address = color_table_iter[source_value]; | 169 *current_address = color_table_iter[source_value]; |
171 else | |
172 current_buffer_saw_alpha_ = true; | |
173 } | 170 } |
174 } | 171 } |
175 | 172 |
176 // Tell the frame to copy the row data if need be. | 173 // Tell the frame to copy the row data if need be. |
177 if (repeat_count > 1) | 174 if (repeat_count > 1) |
178 buffer.CopyRowNTimes(x_begin, x_end, y_begin, y_end); | 175 buffer.CopyRowNTimes(x_begin, x_end, y_begin, y_end); |
179 | 176 |
180 buffer.SetPixelsChanged(true); | 177 buffer.SetPixelsChanged(true); |
181 return true; | 178 return true; |
182 } | 179 } |
183 | 180 |
184 bool GIFImageDecoder::ParseCompleted() const { | 181 bool GIFImageDecoder::ParseCompleted() const { |
185 return reader_ && reader_->ParseCompleted(); | 182 return reader_ && reader_->ParseCompleted(); |
186 } | 183 } |
187 | 184 |
188 bool GIFImageDecoder::FrameComplete(size_t frame_index) { | 185 bool GIFImageDecoder::FrameComplete(size_t frame_index) { |
189 // Initialize the frame if necessary. Some GIFs insert do-nothing frames, | 186 // Initialize the frame if necessary. Some GIFs insert do-nothing frames, |
scroggo_chromium
2017/05/31 14:27:50
Should we consider the case of a do-nothing frame?
cblume
2017/05/31 20:35:05
I imagine there might be two types of do-nothing f
scroggo_chromium
2017/05/31 21:12:15
Notice the comment - a "do-nothing" frame means we
| |
190 // in which case we never reach HaveDecodedRow() before getting here. | 187 // in which case we never reach HaveDecodedRow() before getting here. |
191 if (!InitFrameBuffer(frame_index)) | 188 if (!InitFrameBuffer(frame_index)) |
192 return SetFailed(); | 189 return SetFailed(); |
193 | 190 |
194 if (!current_buffer_saw_alpha_) | 191 ImageFrame& buffer = frame_buffer_cache_[frame_index]; |
195 CorrectAlphaWhenFrameBufferSawNoAlpha(frame_index); | |
196 | 192 |
197 frame_buffer_cache_[frame_index].SetStatus(ImageFrame::kFrameComplete); | 193 const GIFFrameContext* frame_context = reader_->FrameContext(frame_index); |
194 const size_t transparent_pixel = frame_context->TransparentPixel(); | |
195 const GIFColorMap::Table& color_table = | |
196 frame_context->LocalColorMap().IsDefined() | |
197 ? frame_context->LocalColorMap().GetTable() | |
198 : reader_->GlobalColorMap().GetTable(); | |
199 buffer.SetHasAlpha(transparent_pixel <= color_table.size()); | |
200 | |
201 buffer.SetStatus(ImageFrame::kFrameComplete); | |
198 | 202 |
199 return true; | 203 return true; |
200 } | 204 } |
201 | 205 |
202 void GIFImageDecoder::ClearFrameBuffer(size_t frame_index) { | 206 void GIFImageDecoder::ClearFrameBuffer(size_t frame_index) { |
203 if (reader_ && frame_buffer_cache_[frame_index].GetStatus() == | 207 if (reader_ && frame_buffer_cache_[frame_index].GetStatus() == |
204 ImageFrame::kFramePartial) { | 208 ImageFrame::kFramePartial) { |
205 // Reset the state of the partial frame in the reader so that the frame | 209 // Reset the state of the partial frame in the reader so that the frame |
206 // can be decoded again when requested. | 210 // can be decoded again when requested. |
207 reader_->ClearDecodeState(frame_index); | 211 reader_->ClearDecodeState(frame_index); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 | 266 |
263 if (!reader_) { | 267 if (!reader_) { |
264 reader_ = WTF::MakeUnique<GIFImageReader>(this); | 268 reader_ = WTF::MakeUnique<GIFImageReader>(this); |
265 reader_->SetData(data_); | 269 reader_->SetData(data_); |
266 } | 270 } |
267 | 271 |
268 if (!reader_->Parse(query)) | 272 if (!reader_->Parse(query)) |
269 SetFailed(); | 273 SetFailed(); |
270 } | 274 } |
271 | 275 |
272 void GIFImageDecoder::OnInitFrameBuffer(size_t frame_index) { | |
273 current_buffer_saw_alpha_ = false; | |
274 } | |
275 | |
276 bool GIFImageDecoder::CanReusePreviousFrameBuffer(size_t frame_index) const { | 276 bool GIFImageDecoder::CanReusePreviousFrameBuffer(size_t frame_index) const { |
277 DCHECK(frame_index < frame_buffer_cache_.size()); | 277 DCHECK(frame_index < frame_buffer_cache_.size()); |
278 return frame_buffer_cache_[frame_index].GetDisposalMethod() != | 278 return frame_buffer_cache_[frame_index].GetDisposalMethod() != |
279 ImageFrame::kDisposeOverwritePrevious; | 279 ImageFrame::kDisposeOverwritePrevious; |
280 } | 280 } |
281 | 281 |
282 } // namespace blink | 282 } // namespace blink |
OLD | NEW |