2 * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 // Implementation notes:
20 // Current implementation provides the source image size without doing a full
21 // decode. It seems that libimg does not support partial decoding.
24 #include "JPEGImageDecoder.h"
29 #include <wtf/OwnArrayPtr.h>
30 #include <wtf/PassOwnPtr.h>
34 static img_lib_t s_ilib;
36 static inline int libInit()
38 static bool s_initialized;
42 if (img_lib_attach(&s_ilib) != IMG_ERR_OK) {
43 LOG_ERROR("Unable to attach to libimg.");
52 ImageReader(const char* data, size_t dataSize)
61 void updateData(const char* data, size_t dataSize);
62 int setSize(size_t width, size_t height);
63 int sizeExtract(size_t& width, size_t& height);
64 int decode(size_t width, size_t height, ImageFrame*);
73 // Function to get the original size of an image
74 static int imgDecodeSetup(_Uintptrt data, img_t* img, unsigned flags)
76 ImageReader* reader = reinterpret_cast<ImageReader*>(data);
78 if ((img->flags & (IMG_W | IMG_H)) == (IMG_W | IMG_H))
79 reader->setSize(img->w, img->h);
81 // Always: want to stop processing whether get a size or not.
85 void ImageReader::updateData(const char* data, size_t dataSize)
91 int ImageReader::setSize(size_t width, size_t height)
98 int ImageReader::sizeExtract(size_t& width, size_t& height)
100 img_decode_callouts_t callouts;
102 io_stream_t* iostream = io_open(IO_MEM, IO_READ, m_size, m_data);
106 memset(&img, 0, sizeof(img));
107 memset(&callouts, 0, sizeof(callouts));
108 callouts.setup_f = imgDecodeSetup;
109 callouts.data = reinterpret_cast<_Uintptrt>(this);
111 int rc = img_load(s_ilib, iostream, &callouts, &img);
113 if (rc != IMG_ERR_INTR)
115 if (!m_width || !m_height)
124 int ImageReader::decode(size_t width, size_t height, ImageFrame* aFrame)
130 memset(&img, 0, sizeof(img));
131 img.format = IMG_FMT_RGB888;
135 const int ColorComponents = 3;
136 // Use a multiple of 2 bytes to improve performance
137 int stride = (ColorComponents * width + 3) & ~3;
138 OwnArrayPtr<_uint8> buffer = adoptArrayPtr(new _uint8[stride * height]);
141 img.access.direct.data = buffer.get();
142 img.access.direct.stride = stride;
143 img.flags = IMG_W | IMG_H | IMG_DIRECT | IMG_FORMAT;
145 io_stream_t* iostream = io_open(IO_MEM, IO_READ, m_size, m_data);
149 int rc = img_load_resize(s_ilib, iostream, 0, &img);
151 if (rc != IMG_ERR_OK)
154 for (unsigned j = 0; j < height; j++) {
155 _uint8* curPtr = buffer.get() + j * stride;
156 for (unsigned i = 0; i < width; i++) {
157 aFrame->setRGBA(i, j, curPtr[0], curPtr[1], curPtr[2], 255);
164 JPEGImageDecoder::JPEGImageDecoder(ImageSource::AlphaOption alphaOption,
165 ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
166 : ImageDecoder(alphaOption, gammaAndColorProfileOption)
170 void JPEGImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
172 ImageDecoder::setData(data, allDataReceived);
175 m_reader->updateData(m_data->data(), m_data->size());
178 bool JPEGImageDecoder::isSizeAvailable()
180 if (!ImageDecoder::isSizeAvailable()) {
183 m_reader = adoptPtr(new ImageReader(m_data->data(), m_data->size()));
187 size_t width, height;
189 if (m_reader->sizeExtract(width, height) == -1)
191 if (!setSize(width, height))
195 return ImageDecoder::isSizeAvailable();
198 ImageFrame* JPEGImageDecoder::frameBufferAtIndex(size_t index)
200 if (!isAllDataReceived())
206 if (m_frameBufferCache.isEmpty())
207 m_frameBufferCache.resize(1);
209 ImageFrame& frame = m_frameBufferCache[0];
211 // Check to see if it's already decoded.
212 // FIXME: Could size change between calls to this method?
213 if (frame.status() == ImageFrame::FrameComplete)
216 if (frame.status() == ImageFrame::FrameEmpty) {
217 if (!size().width() || !size().height()) {
218 if (!isSizeAvailable())
221 if (!frame.setSize(size().width(), size().height())) {
225 frame.setStatus(ImageFrame::FramePartial);
226 // For JPEGs, the frame always fills the entire image.
227 frame.setOriginalFrameRect(IntRect(IntPoint(), size()));
230 if (!m_reader || m_reader->decode(size().width(), size().height(), &frame) == -1) {
235 frame.setStatus(ImageFrame::FrameComplete);
239 } // namespace WebCore