/*
* Copyright (C) 2014 Team Kodi
* http://kodi.tv
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* .
*
*/
#include "JPGDecoder.h"
#include "SimpleFS.h"
#include
bool JPGDecoder::CanDecode(const std::string &filename)
{
CFile *fp = new CFile();
bool ret = false;
unsigned char magic[2];
if (fp->Open(filename))
{
//JPEG image files begin with FF D8 and end with FF D9.
// check for FF D8 big + little endian on start
uint64_t readbytes = fp->Read(magic, 2);
if (readbytes == 2)
{
if ((magic[0] == 0xd8 && magic[1] == 0xff) ||
(magic[1] == 0xd8 && magic[0] == 0xff))
ret = true;
}
if (ret)
{
ret = false;
//check on FF D9 big + little endian on end
uint64_t fileSize = fp->GetFileSize();
fp->Seek(fileSize - 2);
readbytes = fp->Read(magic, 2);
if (readbytes == 2)
{
if ((magic[0] == 0xd9 && magic[1] == 0xff) ||
(magic[1] == 0xd9 && magic[0] == 0xff))
ret = true;
}
}
}
delete fp;
return ret;
}
bool JPGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames)
{
#define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4)
CFile *arq = new CFile();
if (!arq->Open(filename))
{
delete arq;
return false;
}
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
int ImageSize;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, arq->getFP());
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
// Image Size is calculated as (width * height * bytes per pixel = 4
ImageSize = cinfo.image_width * cinfo.image_height * 4;
frames.user = NULL;
DecodedFrame frame;
frame.rgbaImage.pixels = (char *)new char[ImageSize];
unsigned char *scanlinebuff = new unsigned char[3 * cinfo.image_width];
unsigned char *dst = (unsigned char *)frame.rgbaImage.pixels;
while (cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines(&cinfo,&scanlinebuff,1);
unsigned char *src2 = scanlinebuff;
unsigned char *dst2 = dst;
for (unsigned int x = 0; x < cinfo.image_width; x++, src2 += 3)
{
*dst2++ = src2[2];
*dst2++ = src2[1];
*dst2++ = src2[0];
*dst2++ = 0xff;
}
dst += cinfo.image_width * 4;
}
delete [] scanlinebuff;
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
frame.rgbaImage.height = cinfo.image_height;
frame.rgbaImage.width = cinfo.image_width;
frame.rgbaImage.bbp = 32;
frame.rgbaImage.pitch = 4 * cinfo.image_width;
frames.frameList.push_back(frame);
delete arq;
return true;
}
void JPGDecoder::FreeDecodedFrames(DecodedFrames &frames)
{
for (unsigned int i = 0; i < frames.frameList.size(); i++)
{
delete [] frames.frameList[i].rgbaImage.pixels;
}
frames.clear();
}
void JPGDecoder::FillSupportedExtensions()
{
m_supportedExtensions.emplace_back(".jpg");
m_supportedExtensions.emplace_back(".jpeg");
}