|
Carlos Lopez |
a09598 |
/* === S Y N F I G ========================================================= */
|
|
Carlos Lopez |
a09598 |
/*! \file mptr_jpeg.cpp
|
|
Carlos Lopez |
a09598 |
** \brief ppm Target Module
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** $Id$
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** \legal
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
** Copyright (c) 2015 Jérôme Blanchi
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is free software; you can redistribute it and/or
|
|
Carlos Lopez |
a09598 |
** modify it under the terms of the GNU General Public License as
|
|
Carlos Lopez |
a09598 |
** published by the Free Software Foundation; either version 2 of
|
|
Carlos Lopez |
a09598 |
** the License, or (at your option) any later version.
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is distributed in the hope that it will be useful,
|
|
Carlos Lopez |
a09598 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Carlos Lopez |
a09598 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Carlos Lopez |
a09598 |
** General Public License for more details.
|
|
Carlos Lopez |
a09598 |
** \endlegal
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** === N O T E S ===========================================================
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** ========================================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/*! \todo Support 16 bit JPEG files
|
|
Carlos Lopez |
a09598 |
** \todo Support for paletted JPEG files
|
|
Carlos Lopez |
a09598 |
** \todo Support GAMMA correction
|
|
Carlos Lopez |
a09598 |
** \todo Fix memory leaks
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === H E A D E R S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#ifdef USING_PCH
|
|
Carlos Lopez |
a09598 |
# include "pch.h"
|
|
Carlos Lopez |
a09598 |
#else
|
|
Carlos Lopez |
a09598 |
#ifdef HAVE_CONFIG_H
|
|
Carlos Lopez |
a09598 |
# include <config.h></config.h>
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#include "mptr_jpeg.h"
|
|
Carlos Lopez |
a09598 |
#include <synfig importer.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig time.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include <synfig general.h=""></synfig>
|
|
bw |
94d8a6 |
#include <synfig localization.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#include <cstdio></cstdio>
|
|
Carlos Lopez |
a09598 |
#include <algorithm></algorithm>
|
|
Carlos Lopez |
a09598 |
#include <functional></functional>
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
#include <sstream></sstream>
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M A C R O S ========================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
using namespace synfig;
|
|
Carlos Lopez |
a09598 |
using namespace std;
|
|
Carlos Lopez |
a09598 |
using namespace etl;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#define JPEG_CHECK_BYTES 8
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === G L O B A L S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
SYNFIG_IMPORTER_INIT(jpeg_mptr);
|
|
Carlos Lopez |
a09598 |
SYNFIG_IMPORTER_SET_NAME(jpeg_mptr,"jpeg");
|
|
Carlos Lopez |
a09598 |
SYNFIG_IMPORTER_SET_EXT(jpeg_mptr,"jpg");
|
|
Carlos Lopez |
a09598 |
SYNFIG_IMPORTER_SET_VERSION(jpeg_mptr,"0.1");
|
|
Carlos Lopez |
a09598 |
SYNFIG_IMPORTER_SET_CVS_ID(jpeg_mptr,"$Id$");
|
|
|
58094c |
SYNFIG_IMPORTER_SET_SUPPORTS_FILE_SYSTEM_WRAPPER(jpeg_mptr, false);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M E T H O D S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
struct my_error_mgr {
|
|
Carlos Lopez |
a09598 |
struct jpeg_error_mgr pub; /* "public" fields */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
jmp_buf setjmp_buffer; /* for return to caller */
|
|
Carlos Lopez |
a09598 |
};
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
typedef struct my_error_mgr * my_error_ptr;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/*
|
|
Carlos Lopez |
a09598 |
* Here's the routine that will replace the standard error_exit method:
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
jpeg_mptr::my_error_exit (j_common_ptr cinfo)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
|
Carlos Lopez |
a09598 |
my_error_ptr myerr = (my_error_ptr) cinfo->err;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Always display the message. */
|
|
Carlos Lopez |
a09598 |
/* We could postpone this until after returning, if we chose. */
|
|
|
2da2e1 |
//(*cinfo->err->output_message) (cinfo);
|
|
|
2da2e1 |
|
|
|
2da2e1 |
char jpegLastErrorMsg[JMSG_LENGTH_MAX];
|
|
|
2da2e1 |
( *(cinfo->err->format_message) ) (cinfo, jpegLastErrorMsg);
|
|
|
2da2e1 |
error(String("Jpeg error: ") + jpegLastErrorMsg);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Return control to the setjmp point */
|
|
Carlos Lopez |
a09598 |
longjmp(myerr->setjmp_buffer, 1);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
|
fcad0d |
jpeg_mptr::jpeg_mptr(const synfig::FileSystem::Identifier &identifier):
|
|
|
fcad0d |
Importer(identifier)
|
|
Carlos Lopez |
a09598 |
{
|
|
|
718ada |
}
|
|
|
718ada |
|
|
|
718ada |
jpeg_mptr::~jpeg_mptr()
|
|
|
718ada |
{
|
|
|
718ada |
}
|
|
|
718ada |
|
|
|
718ada |
bool
|
|
|
718ada |
jpeg_mptr::get_frame(synfig::Surface &surface, const synfig::RendDesc &/*renddesc*/, Time, synfig::ProgressCallback */*cb*/)
|
|
|
718ada |
{
|
|
|
718ada |
jpeg_decompress_struct cinfo;
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
struct my_error_mgr jerr;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Open the file pointer */
|
|
|
e59227 |
FileSystem::ReadStream::Handle stream = identifier.get_read_stream();
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
if (!stream)
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
{
|
|
[d.j.a.y] Jerome Blanchi |
0c77bd |
throw String("Error on jpeg importer, unable to physically open "+identifier.filename);
|
|
|
718ada |
return false;
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Step 1: allocate and initialize JPEG decompression object */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* We set up the normal JPEG error routines, then override error_exit. */
|
|
Carlos Lopez |
a09598 |
cinfo.err = jpeg_std_error(&jerr.pub);
|
|
Carlos Lopez |
a09598 |
jerr.pub.error_exit = my_error_exit;
|
|
Carlos Lopez |
a09598 |
/* Establish the setjmp return context for my_error_exit to use. */
|
|
Carlos Lopez |
a09598 |
if (setjmp(jerr.setjmp_buffer)) {
|
|
Carlos Lopez |
a09598 |
/* If we get here, the JPEG code has signaled an error.
|
|
Carlos Lopez |
a09598 |
* We need to clean up the JPEG object, close the input file, and return.
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
jpeg_destroy_decompress(&cinfo);
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
stream.reset();
|
|
[d.j.a.y] Jerome Blanchi |
0c77bd |
throw String("Error on jpeg importer, unable to connect to jpeg library");
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
/* Now we can initialize the JPEG decompression object. */
|
|
Carlos Lopez |
a09598 |
jpeg_create_decompress(&cinfo);
|
|
Carlos Lopez |
a09598 |
|
|
luz.paz |
99f3ef |
/* Step 2: specify data source (eg, from memory thru a String) */
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
std::ostringstream tmp;
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
tmp << stream->rdbuf();
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
String streamString = tmp.str();
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
stream.reset();
|
|
Carlos Lopez |
a09598 |
|
|
[d.j.a.y] Jerome Blanchi |
6485c7 |
jpeg_mem_src(&cinfo, (unsigned char*)streamString.c_str(), streamString.size());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Step 3: read file parameters with jpeg_read_header() */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
(void) jpeg_read_header(&cinfo, TRUE);
|
|
Carlos Lopez |
a09598 |
/* We can ignore the return value from jpeg_read_header since
|
|
Carlos Lopez |
a09598 |
* (a) suspension is not possible with the stdio data source, and
|
|
Carlos Lopez |
a09598 |
* (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
|
Carlos Lopez |
a09598 |
* See libjpeg.doc for more info.
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Step 4: set parameters for decompression */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* In this example, we don't need to change any of the defaults set by
|
|
Carlos Lopez |
a09598 |
* jpeg_read_header(), so we do nothing here.
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Step 5: Start decompressor */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
(void) jpeg_start_decompress(&cinfo);
|
|
Carlos Lopez |
a09598 |
/* We can ignore the return value since suspension is not possible
|
|
Carlos Lopez |
a09598 |
* with the stdio data source.
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
JSAMPARRAY buffer; /* Output row buffer */
|
|
Carlos Lopez |
a09598 |
int row_stride; /* physical row width in output buffer */
|
|
Carlos Lopez |
a09598 |
row_stride = cinfo.output_width * cinfo.output_components;
|
|
Carlos Lopez |
a09598 |
/* Make a one-row-high sample array that will go away when done with image */
|
|
Carlos Lopez |
a09598 |
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(!buffer)
|
|
Carlos Lopez |
a09598 |
{
|
|
[d.j.a.y] Jerome Blanchi |
0c77bd |
synfig::error("Error on jpeg importer, alloc of \"buffer\" failed (bug?)");
|
|
[d.j.a.y] Jerome Blanchi |
0c77bd |
throw String("Error on jpeg importer, alloc of \"buffer\" failed (bug?)");
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
|
a4bbdd |
surface.set_wh(cinfo.output_width, cinfo.output_height);
|
|
|
a4bbdd |
const ColorReal k = 1/255.0;
|
|
Carlos Lopez |
a09598 |
switch(cinfo.output_components)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
case 3:
|
|
|
a4bbdd |
for(int y = 0; y < surface.get_h(); ++y) {
|
|
Carlos Lopez |
a09598 |
jpeg_read_scanlines(&cinfo, buffer, 1);
|
|
|
a4bbdd |
for(int x = 0; x < surface.get_w(); ++x)
|
|
|
718ada |
surface[y][x]=Color(
|
|
|
a4bbdd |
((unsigned char)buffer[0][x*3+0])*k,
|
|
|
a4bbdd |
((unsigned char)buffer[0][x*3+1])*k,
|
|
|
a4bbdd |
((unsigned char)buffer[0][x*3+2])*k );
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
case 1:
|
|
|
a4bbdd |
for(int y = 0; y < surface.get_h(); ++y) {
|
|
Carlos Lopez |
a09598 |
jpeg_read_scanlines(&cinfo, buffer, 1);
|
|
|
a4bbdd |
for(int x = 0; x < surface.get_w(); ++x) {
|
|
|
a4bbdd |
ColorReal gray = ((unsigned char)buffer[0][x])*k;
|
|
|
a4bbdd |
surface[y][x]=Color(gray, gray, gray);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
default:
|
|
[d.j.a.y] Jerome Blanchi |
0c77bd |
synfig::error("Error on jpeg importer, Unsupported color type");
|
|
Carlos Lopez |
a09598 |
//! \todo THROW SOMETHING
|
|
[d.j.a.y] Jerome Blanchi |
0c77bd |
throw String("Error on jpeg importer, Unsupported color type");
|
|
|
718ada |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Step 7: Finish decompression */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
(void) jpeg_finish_decompress(&cinfo);
|
|
Carlos Lopez |
a09598 |
/* We can ignore the return value since suspension is not possible
|
|
Carlos Lopez |
a09598 |
* with the stdio data source.
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Step 8: Release JPEG decompression object */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* This is an important step since it will release a good deal of memory. */
|
|
Carlos Lopez |
a09598 |
jpeg_destroy_decompress(&cinfo);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|