mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-23 10:22:52 +00:00
gwenview: get rid of custom jpeg handler
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
7c098060fd
commit
ce3e932c94
53 changed files with 10 additions and 10960 deletions
|
@ -38,7 +38,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
// Local
|
||||
#include <lib/about.h>
|
||||
#include <lib/imageformats/imageformats.h>
|
||||
#include "mainwindow.h"
|
||||
|
||||
class StartHelper
|
||||
|
@ -127,7 +126,6 @@ int main(int argc, char *argv[])
|
|||
KCmdLineArgs::addCmdLineOptions(options);
|
||||
|
||||
KApplication app;
|
||||
Gwenview::ImageFormats::registerPlugins();
|
||||
|
||||
// startHelper must live for the whole life of the application
|
||||
StartHelper startHelper;
|
||||
|
|
|
@ -30,7 +30,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
// Local
|
||||
#include <lib/about.h>
|
||||
#include <lib/imageformats/imageformats.h>
|
||||
#include "importdialog.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -65,8 +64,6 @@ int main(int argc, char *argv[])
|
|||
QString deviceUdi = args->isSet("udi") ? args->getOption("udi") : QString();
|
||||
args->clear();
|
||||
|
||||
Gwenview::ImageFormats::registerPlugins();
|
||||
|
||||
Gwenview::ImportDialog* dialog = new Gwenview::ImportDialog();
|
||||
dialog->show();
|
||||
QMetaObject::invokeMethod(dialog, "setSourceUrl", Qt::QueuedConnection, Q_ARG(KUrl, url), Q_ARG(QString, deviceUdi));
|
||||
|
|
|
@ -1,66 +1,17 @@
|
|||
project(gwenviewlib)
|
||||
|
||||
# Extract version of libjpeg so that we can use the appropriate dir
|
||||
# See bug #227313
|
||||
message(STATUS "Looking for libjpeg version in ${JPEG_INCLUDE_DIR}/jpeglib.h")
|
||||
file(READ "${JPEG_INCLUDE_DIR}/jpeglib.h" jpeglib_h_content)
|
||||
string(REGEX MATCH "#define +JPEG_LIB_VERSION +([0-9]+)" "\\1" jpeglib_version "${jpeglib_h_content}")
|
||||
set(jpeglib_version ${CMAKE_MATCH_1})
|
||||
|
||||
if ("${jpeglib_version}" STREQUAL "")
|
||||
message(STATUS "No version defined in ${JPEG_INCLUDE_DIR}/jpeglib.h, looking for jconfig.h")
|
||||
# libjpeg-turbo keeps JPEG_LIB_VERSION in jconfig.h, not jpeglib.h :/
|
||||
find_file(JCONFIG_H jconfig.h
|
||||
PATHS "${JPEG_INCLUDE_DIR}"
|
||||
PATH_SUFFIXES "${CMAKE_LIBRARY_ARCHITECTURE}"
|
||||
)
|
||||
if (NOT EXISTS "${JCONFIG_H}")
|
||||
message(FATAL_ERROR "Could not find jconfig.h. This file comes with libjpeg. You can specify its path with -DJCONFIG_H=/path/to/jconfig.h.")
|
||||
endif()
|
||||
message(STATUS "Found jconfig.h: ${JCONFIG_H}")
|
||||
message(STATUS "Looking for libjpeg version in ${JCONFIG_H}")
|
||||
file(READ "${JCONFIG_H}" jconfig_h_content)
|
||||
string(REGEX MATCH "#define +JPEG_LIB_VERSION +([0-9]+)" "\\1" jpeglib_version "${jconfig_h_content}")
|
||||
set(jpeglib_version ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
|
||||
if ("${jpeglib_version}" LESS 80)
|
||||
set(GV_JPEG_DIR libjpeg-62)
|
||||
endif()
|
||||
|
||||
if ("${jpeglib_version}" EQUAL 80)
|
||||
set(GV_JPEG_DIR libjpeg-80)
|
||||
endif()
|
||||
|
||||
if ("${jpeglib_version}" EQUAL 90)
|
||||
set(GV_JPEG_DIR libjpeg-90)
|
||||
endif()
|
||||
|
||||
if ("${GV_JPEG_DIR}" STREQUAL "")
|
||||
message(FATAL_ERROR "Unknown libjpeg version: ${jpeglib_version}")
|
||||
endif()
|
||||
|
||||
message(STATUS "libjpeg version: ${jpeglib_version}")
|
||||
|
||||
add_definitions(-Dlibjpeg_EXPORTS)
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${GV_JPEG_DIR}
|
||||
# For config-gwenview.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${EXIV2_INCLUDE_DIR}
|
||||
${JPEG_INCLUDE_DIR}
|
||||
${PNG_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# For config-gwenview.h
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
)
|
||||
)
|
||||
|
||||
set(gwenviewlib_SRCS
|
||||
cms/iccjpeg.c
|
||||
cms/cmsprofile.cpp
|
||||
cms/cmsprofile_png.cpp
|
||||
contextmanager.cpp
|
||||
crop/cropwidget.cpp
|
||||
crop/cropimageoperation.cpp
|
||||
|
@ -72,7 +23,6 @@ set(gwenviewlib_SRCS
|
|||
document/documentfactory.cpp
|
||||
document/documentloadedimpl.cpp
|
||||
document/emptydocumentimpl.cpp
|
||||
document/jpegdocumentloadedimpl.cpp
|
||||
document/loadingdocumentimpl.cpp
|
||||
document/loadingjob.cpp
|
||||
document/savejob.cpp
|
||||
|
@ -113,15 +63,10 @@ set(gwenviewlib_SRCS
|
|||
hud/hudtheme.cpp
|
||||
hud/hudwidget.cpp
|
||||
graphicswidgetfloater.cpp
|
||||
imageformats/imageformats.cpp
|
||||
imageformats/jpegplugin.cpp
|
||||
imageformats/jpeghandler.cpp
|
||||
imagemetainfomodel.cpp
|
||||
imagescaler.cpp
|
||||
imageutils.cpp
|
||||
invisiblebuttongroup.cpp
|
||||
iodevicejpegsourcemanager.cpp
|
||||
jpegcontent.cpp
|
||||
kindproxymodel.cpp
|
||||
memoryutils.cpp
|
||||
mimetypeutils.cpp
|
||||
|
@ -159,12 +104,6 @@ set(gwenviewlib_SRCS
|
|||
zoomslider.cpp
|
||||
zoomwidget.cpp
|
||||
sorteddirmodel.cpp
|
||||
${GV_JPEG_DIR}/transupp.c
|
||||
crop/cropwidget.ui
|
||||
documentview/messageview.ui
|
||||
print/printoptionspage.ui
|
||||
redeyereduction/redeyereductionwidget.ui
|
||||
resize/resizeimagewidget.ui
|
||||
)
|
||||
|
||||
set_source_files_properties(
|
||||
|
|
|
@ -1,249 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
// Self
|
||||
#include "cmsprofile.h"
|
||||
|
||||
// Local
|
||||
#include <cms/cmsprofile_png.h>
|
||||
#include <gvdebug.h>
|
||||
#include <iodevicejpegsourcemanager.h>
|
||||
#include <jpegerrormanager.h>
|
||||
|
||||
extern "C" {
|
||||
#include <cms/iccjpeg.h>
|
||||
}
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
|
||||
// Qt
|
||||
#include <QBuffer>
|
||||
|
||||
// lcms
|
||||
#include <lcms2.h>
|
||||
|
||||
// X11
|
||||
#ifdef Q_WS_X11
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <fixx11h.h>
|
||||
#include <QX11Info>
|
||||
#endif
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
#undef ENABLE_LOG
|
||||
#undef LOG
|
||||
//#define ENABLE_LOG
|
||||
#ifdef ENABLE_LOG
|
||||
#define LOG(x) kDebug() << x
|
||||
#else
|
||||
#define LOG(x) ;
|
||||
#endif
|
||||
|
||||
namespace Cms
|
||||
{
|
||||
|
||||
//- JPEG -----------------------------------------------------------------------
|
||||
static cmsHPROFILE loadFromJpegData(const QByteArray& data)
|
||||
{
|
||||
cmsHPROFILE profile = 0;
|
||||
struct jpeg_decompress_struct srcinfo;
|
||||
|
||||
JPEGErrorManager srcErrorManager;
|
||||
srcinfo.err = &srcErrorManager;
|
||||
jpeg_create_decompress(&srcinfo);
|
||||
if (setjmp(srcErrorManager.jmp_buffer)) {
|
||||
kError() << "libjpeg error in src\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
QBuffer buffer(const_cast<QByteArray*>(&data));
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
IODeviceJpegSourceManager::setup(&srcinfo, &buffer);
|
||||
|
||||
setup_read_icc_profile(&srcinfo);
|
||||
jpeg_read_header(&srcinfo, true);
|
||||
jpeg_start_decompress(&srcinfo);
|
||||
|
||||
uchar* profile_data;
|
||||
uint profile_len;
|
||||
if (read_icc_profile(&srcinfo, &profile_data, &profile_len)) {
|
||||
LOG("Found a profile, length:" << profile_len);
|
||||
profile = cmsOpenProfileFromMem(profile_data, profile_len);
|
||||
}
|
||||
|
||||
jpeg_destroy_decompress(&srcinfo);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
//- Profile class --------------------------------------------------------------
|
||||
struct ProfilePrivate
|
||||
{
|
||||
cmsHPROFILE mProfile;
|
||||
|
||||
void reset()
|
||||
{
|
||||
if (mProfile) {
|
||||
cmsCloseProfile(mProfile);
|
||||
}
|
||||
mProfile = 0;
|
||||
}
|
||||
|
||||
QString readInfo(cmsInfoType info)
|
||||
{
|
||||
GV_RETURN_VALUE_IF_FAIL(mProfile, QString());
|
||||
wchar_t buffer[1024];
|
||||
int size = cmsGetProfileInfo(mProfile, info, "en", "US", buffer, 1024);
|
||||
return QString::fromWCharArray(buffer, size);
|
||||
}
|
||||
};
|
||||
|
||||
Profile::Profile()
|
||||
: d(new ProfilePrivate)
|
||||
{
|
||||
d->mProfile = 0;
|
||||
}
|
||||
|
||||
Profile::Profile(cmsHPROFILE hProfile)
|
||||
: d(new ProfilePrivate)
|
||||
{
|
||||
d->mProfile = hProfile;
|
||||
}
|
||||
|
||||
Profile::~Profile()
|
||||
{
|
||||
d->reset();
|
||||
delete d;
|
||||
}
|
||||
|
||||
Profile::Ptr Profile::loadFromImageData(const QByteArray& data, const QByteArray& format)
|
||||
{
|
||||
Profile::Ptr ptr;
|
||||
cmsHPROFILE hProfile = 0;
|
||||
if (format == "png") {
|
||||
hProfile = loadFromPngData(data);
|
||||
}
|
||||
if (format == "jpeg") {
|
||||
hProfile = loadFromJpegData(data);
|
||||
}
|
||||
if (hProfile) {
|
||||
ptr = new Profile(hProfile);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
Profile::Ptr Profile::loadFromExiv2Image(const Exiv2::Image* image)
|
||||
{
|
||||
Profile::Ptr ptr;
|
||||
cmsHPROFILE hProfile = 0;
|
||||
|
||||
const Exiv2::ExifData& exifData = image->exifData();
|
||||
Exiv2::ExifKey key("Exif.Image.InterColorProfile");
|
||||
Exiv2::ExifData::const_iterator it = exifData.findKey(key);
|
||||
if (it == exifData.end()) {
|
||||
LOG("No profile found");
|
||||
return ptr;
|
||||
}
|
||||
int size = it->size();
|
||||
LOG("size:" << size);
|
||||
|
||||
QByteArray data;
|
||||
data.resize(size);
|
||||
it->copy(reinterpret_cast<Exiv2::byte*>(data.data()), Exiv2::invalidByteOrder);
|
||||
hProfile = cmsOpenProfileFromMem(data, size);
|
||||
|
||||
if (hProfile) {
|
||||
ptr = new Profile(hProfile);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
cmsHPROFILE Profile::handle() const
|
||||
{
|
||||
return d->mProfile;
|
||||
}
|
||||
|
||||
QString Profile::copyright() const
|
||||
{
|
||||
return d->readInfo(cmsInfoCopyright);
|
||||
}
|
||||
|
||||
QString Profile::description() const
|
||||
{
|
||||
return d->readInfo(cmsInfoDescription);
|
||||
}
|
||||
|
||||
QString Profile::manufacturer() const
|
||||
{
|
||||
return d->readInfo(cmsInfoManufacturer);
|
||||
}
|
||||
|
||||
QString Profile::model() const
|
||||
{
|
||||
return d->readInfo(cmsInfoModel);
|
||||
}
|
||||
|
||||
Profile::Ptr Profile::getMonitorProfile()
|
||||
{
|
||||
cmsHPROFILE hProfile = 0;
|
||||
// Get the profile from you config file if the user has set it.
|
||||
// if the user allows override through the atom, do this:
|
||||
#ifdef Q_WS_X11
|
||||
|
||||
// get the current screen...
|
||||
int screen = -1;
|
||||
|
||||
Atom type;
|
||||
int format;
|
||||
unsigned long nitems;
|
||||
unsigned long bytes_after;
|
||||
quint8 *str;
|
||||
|
||||
static Atom icc_atom = XInternAtom(QX11Info::display(), "_ICC_PROFILE", True);
|
||||
|
||||
if (XGetWindowProperty(QX11Info::display(),
|
||||
QX11Info::appRootWindow(screen),
|
||||
icc_atom,
|
||||
0,
|
||||
INT_MAX,
|
||||
False,
|
||||
XA_CARDINAL,
|
||||
&type,
|
||||
&format,
|
||||
&nitems,
|
||||
&bytes_after,
|
||||
(unsigned char **) &str) == Success
|
||||
) {
|
||||
hProfile = cmsOpenProfileFromMem((void*)str, nitems);
|
||||
}
|
||||
#endif
|
||||
if (!hProfile) {
|
||||
hProfile = cmsCreate_sRGBProfile();
|
||||
}
|
||||
return Profile::Ptr(new Profile(hProfile));
|
||||
}
|
||||
|
||||
} // namespace Cms
|
||||
|
||||
} // namespace Gwenview
|
|
@ -1,79 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef CMSPROFILE_H
|
||||
#define CMSPROFILE_H
|
||||
|
||||
#include <lib/gwenviewlib_export.h>
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
#include <KSharedPtr>
|
||||
|
||||
// Qt
|
||||
#include <QSharedData>
|
||||
|
||||
// Exiv2
|
||||
#include <exiv2/image.hpp>
|
||||
|
||||
class QByteArray;
|
||||
class QString;
|
||||
|
||||
typedef void* cmsHPROFILE;
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
namespace Cms
|
||||
{
|
||||
|
||||
struct ProfilePrivate;
|
||||
/**
|
||||
* Wrapper for lcms color profile
|
||||
*/
|
||||
class GWENVIEWLIB_EXPORT Profile : public QSharedData
|
||||
{
|
||||
public:
|
||||
typedef KSharedPtr<Profile> Ptr;
|
||||
|
||||
Profile();
|
||||
~Profile();
|
||||
|
||||
QString description() const;
|
||||
QString manufacturer() const;
|
||||
QString model() const;
|
||||
QString copyright() const;
|
||||
|
||||
cmsHPROFILE handle() const;
|
||||
|
||||
static Profile::Ptr loadFromImageData(const QByteArray& data, const QByteArray& format);
|
||||
static Profile::Ptr loadFromExiv2Image(const Exiv2::Image* image);
|
||||
static Profile::Ptr getMonitorProfile();
|
||||
|
||||
private:
|
||||
Profile(cmsHPROFILE);
|
||||
ProfilePrivate* const d;
|
||||
};
|
||||
|
||||
} // namespace Cms
|
||||
} // namespace Gwenview
|
||||
|
||||
#endif /* CMSPROFILE_H */
|
|
@ -1,115 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
// Self
|
||||
#include "cmsprofile_png.h"
|
||||
|
||||
// Local
|
||||
#include <gvdebug.h>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
|
||||
// Qt
|
||||
#include <QBuffer>
|
||||
|
||||
// lcms
|
||||
#include <lcms2.h>
|
||||
|
||||
// libpng
|
||||
#include <png.h>
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
namespace Cms
|
||||
{
|
||||
|
||||
static void readPngChunk(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
QIODevice *in = (QIODevice *)png_get_io_ptr(png_ptr);
|
||||
|
||||
while (length) {
|
||||
int nr = in->read((char*)data, length);
|
||||
if (nr <= 0) {
|
||||
png_error(png_ptr, "Read Error");
|
||||
return;
|
||||
}
|
||||
length -= nr;
|
||||
}
|
||||
}
|
||||
|
||||
cmsHPROFILE loadFromPngData(const QByteArray& data)
|
||||
{
|
||||
QBuffer buffer;
|
||||
buffer.setBuffer(const_cast<QByteArray*>(&data));
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
|
||||
// Initialize the internal structures
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
|
||||
GV_RETURN_VALUE_IF_FAIL(png_ptr, 0);
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
if (!info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
|
||||
kWarning() << "Could not create info_struct";
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_infop end_info = png_create_info_struct(png_ptr);
|
||||
if (!end_info) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
kWarning() << "Could not create info_struct2";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Catch errors
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
kWarning() << "Error decoding png file";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialize the special
|
||||
png_set_read_fn(png_ptr, &buffer, readPngChunk);
|
||||
|
||||
// read all PNG info up to image data
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
// Get profile
|
||||
png_charp profile_name;
|
||||
#if PNG_LIBPNG_VER_MAJOR >= 1 && PNG_LIBPNG_VER_MINOR >= 5
|
||||
png_bytep profile_data;
|
||||
#else
|
||||
png_charp profile_data;
|
||||
#endif
|
||||
int compression_type;
|
||||
png_uint_32 proflen;
|
||||
|
||||
cmsHPROFILE profile = 0;
|
||||
if (png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &proflen)) {
|
||||
profile = cmsOpenProfileFromMem(profile_data, proflen);
|
||||
}
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||
return profile;
|
||||
}
|
||||
|
||||
} // namespace Cms
|
||||
} // namespace Gwenview
|
|
@ -1,49 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef CMSPROFILE_PNG_H
|
||||
#define CMSPROFILE_PNG_H
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
typedef void* cmsHPROFILE;
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
namespace Cms
|
||||
{
|
||||
|
||||
/**
|
||||
* This code is in its own file because it cannot be compiled in the same .cpp
|
||||
* file as jpeg code: libpng complains about setjmp being included twice.
|
||||
*/
|
||||
|
||||
cmsHPROFILE loadFromPngData(const QByteArray& data);
|
||||
|
||||
} // namespace Cms
|
||||
} // namespace Gwenview
|
||||
|
||||
#endif /* CMSPROFILE_PNG_H */
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
* Little cms
|
||||
* Copyright (C) 1998-2004 Marti Maria <x@unknown.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
* KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* iccprofile.c
|
||||
*
|
||||
* This file provides code to read and write International Color Consortium
|
||||
* (ICC) device profiles embedded in JFIF JPEG image files. The ICC has
|
||||
* defined a standard format for including such data in JPEG "APP2" markers.
|
||||
* The code given here does not know anything about the internal structure
|
||||
* of the ICC profile data; it just knows how to put the profile data into
|
||||
* a JPEG file being written, or get it back out when reading.
|
||||
*
|
||||
* This code depends on new features added to the IJG JPEG library as of
|
||||
* IJG release 6b; it will not compile or work with older IJG versions.
|
||||
*
|
||||
* NOTE: this code would need surgery to work on 16-bit-int machines
|
||||
* with ICC profiles exceeding 64K bytes in size. If you need to do that,
|
||||
* change all the "unsigned int" variables to "INT32". You'll also need
|
||||
* to find a malloc() replacement that can allocate more than 64K.
|
||||
*/
|
||||
|
||||
#include "iccjpeg.h"
|
||||
#include <stdlib.h> /* define malloc() */
|
||||
|
||||
|
||||
/*
|
||||
* Since an ICC profile can be larger than the maximum size of a JPEG marker
|
||||
* (64K), we need provisions to split it into multiple markers. The format
|
||||
* defined by the ICC specifies one or more APP2 markers containing the
|
||||
* following data:
|
||||
* Identifying string ASCII "ICC_PROFILE\0" (12 bytes)
|
||||
* Marker sequence number 1 for first APP2, 2 for next, etc (1 byte)
|
||||
* Number of markers Total number of APP2's used (1 byte)
|
||||
* Profile data (remainder of APP2 data)
|
||||
* Decoders should use the marker sequence numbers to reassemble the profile,
|
||||
* rather than assuming that the APP2 markers appear in the correct sequence.
|
||||
*/
|
||||
|
||||
#define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */
|
||||
#define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */
|
||||
#define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */
|
||||
#define MAX_DATA_BYTES_IN_MARKER (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
|
||||
|
||||
|
||||
/*
|
||||
* This routine writes the given ICC profile data into a JPEG file.
|
||||
* It *must* be called AFTER calling jpeg_start_compress() and BEFORE
|
||||
* the first call to jpeg_write_scanlines().
|
||||
* (This ordering ensures that the APP2 marker(s) will appear after the
|
||||
* SOI and JFIF or Adobe markers, but before all else.)
|
||||
*/
|
||||
|
||||
void
|
||||
write_icc_profile (j_compress_ptr cinfo,
|
||||
const JOCTET *icc_data_ptr,
|
||||
unsigned int icc_data_len)
|
||||
{
|
||||
unsigned int num_markers; /* total number of markers we'll write */
|
||||
int cur_marker = 1; /* per spec, counting starts at 1 */
|
||||
unsigned int length; /* number of bytes to write in this marker */
|
||||
|
||||
/* Calculate the number of markers we'll need, rounding up of course */
|
||||
num_markers = icc_data_len / MAX_DATA_BYTES_IN_MARKER;
|
||||
if (num_markers * MAX_DATA_BYTES_IN_MARKER != icc_data_len)
|
||||
num_markers++;
|
||||
|
||||
while (icc_data_len > 0) {
|
||||
/* length of profile to put in this marker */
|
||||
length = icc_data_len;
|
||||
if (length > MAX_DATA_BYTES_IN_MARKER)
|
||||
length = MAX_DATA_BYTES_IN_MARKER;
|
||||
icc_data_len -= length;
|
||||
|
||||
/* Write the JPEG marker header (APP2 code and marker length) */
|
||||
jpeg_write_m_header(cinfo, ICC_MARKER,
|
||||
(unsigned int) (length + ICC_OVERHEAD_LEN));
|
||||
|
||||
/* Write the marker identifying string "ICC_PROFILE" (null-terminated).
|
||||
* We code it in this less-than-transparent way so that the code works
|
||||
* even if the local character set is not ASCII.
|
||||
*/
|
||||
jpeg_write_m_byte(cinfo, 0x49);
|
||||
jpeg_write_m_byte(cinfo, 0x43);
|
||||
jpeg_write_m_byte(cinfo, 0x43);
|
||||
jpeg_write_m_byte(cinfo, 0x5F);
|
||||
jpeg_write_m_byte(cinfo, 0x50);
|
||||
jpeg_write_m_byte(cinfo, 0x52);
|
||||
jpeg_write_m_byte(cinfo, 0x4F);
|
||||
jpeg_write_m_byte(cinfo, 0x46);
|
||||
jpeg_write_m_byte(cinfo, 0x49);
|
||||
jpeg_write_m_byte(cinfo, 0x4C);
|
||||
jpeg_write_m_byte(cinfo, 0x45);
|
||||
jpeg_write_m_byte(cinfo, 0x0);
|
||||
|
||||
/* Add the sequencing info */
|
||||
jpeg_write_m_byte(cinfo, cur_marker);
|
||||
jpeg_write_m_byte(cinfo, (int) num_markers);
|
||||
|
||||
/* Add the profile data */
|
||||
while (length--) {
|
||||
jpeg_write_m_byte(cinfo, *icc_data_ptr);
|
||||
icc_data_ptr++;
|
||||
}
|
||||
cur_marker++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prepare for reading an ICC profile
|
||||
*/
|
||||
|
||||
void
|
||||
setup_read_icc_profile (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* Tell the library to keep any APP2 data it may find */
|
||||
jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Handy subroutine to test whether a saved marker is an ICC profile marker.
|
||||
*/
|
||||
|
||||
static boolean
|
||||
marker_is_icc (jpeg_saved_marker_ptr marker)
|
||||
{
|
||||
return
|
||||
marker->marker == ICC_MARKER &&
|
||||
marker->data_length >= ICC_OVERHEAD_LEN &&
|
||||
/* verify the identifying string */
|
||||
GETJOCTET(marker->data[0]) == 0x49 &&
|
||||
GETJOCTET(marker->data[1]) == 0x43 &&
|
||||
GETJOCTET(marker->data[2]) == 0x43 &&
|
||||
GETJOCTET(marker->data[3]) == 0x5F &&
|
||||
GETJOCTET(marker->data[4]) == 0x50 &&
|
||||
GETJOCTET(marker->data[5]) == 0x52 &&
|
||||
GETJOCTET(marker->data[6]) == 0x4F &&
|
||||
GETJOCTET(marker->data[7]) == 0x46 &&
|
||||
GETJOCTET(marker->data[8]) == 0x49 &&
|
||||
GETJOCTET(marker->data[9]) == 0x4C &&
|
||||
GETJOCTET(marker->data[10]) == 0x45 &&
|
||||
GETJOCTET(marker->data[11]) == 0x0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* See if there was an ICC profile in the JPEG file being read;
|
||||
* if so, reassemble and return the profile data.
|
||||
*
|
||||
* TRUE is returned if an ICC profile was found, FALSE if not.
|
||||
* If TRUE is returned, *icc_data_ptr is set to point to the
|
||||
* returned data, and *icc_data_len is set to its length.
|
||||
*
|
||||
* IMPORTANT: the data at **icc_data_ptr has been allocated with malloc()
|
||||
* and must be freed by the caller with free() when the caller no longer
|
||||
* needs it. (Alternatively, we could write this routine to use the
|
||||
* IJG library's memory allocator, so that the data would be freed implicitly
|
||||
* at jpeg_finish_decompress() time. But it seems likely that many apps
|
||||
* will prefer to have the data stick around after decompression finishes.)
|
||||
*
|
||||
* NOTE: if the file contains invalid ICC APP2 markers, we just silently
|
||||
* return FALSE. You might want to issue an error message instead.
|
||||
*/
|
||||
|
||||
boolean
|
||||
read_icc_profile (j_decompress_ptr cinfo,
|
||||
JOCTET **icc_data_ptr,
|
||||
unsigned int *icc_data_len)
|
||||
{
|
||||
jpeg_saved_marker_ptr marker;
|
||||
int num_markers = 0;
|
||||
int seq_no;
|
||||
JOCTET *icc_data;
|
||||
unsigned int total_length;
|
||||
#define MAX_SEQ_NO 255 /* sufficient since marker numbers are bytes */
|
||||
char marker_present[MAX_SEQ_NO+1]; /* 1 if marker found */
|
||||
unsigned int data_length[MAX_SEQ_NO+1]; /* size of profile data in marker */
|
||||
unsigned int data_offset[MAX_SEQ_NO+1]; /* offset for data in marker */
|
||||
|
||||
*icc_data_ptr = NULL; /* avoid confusion if FALSE return */
|
||||
*icc_data_len = 0;
|
||||
|
||||
/* This first pass over the saved markers discovers whether there are
|
||||
* any ICC markers and verifies the consistency of the marker numbering.
|
||||
*/
|
||||
|
||||
for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
|
||||
marker_present[seq_no] = 0;
|
||||
|
||||
for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
|
||||
if (marker_is_icc(marker)) {
|
||||
if (num_markers == 0)
|
||||
num_markers = GETJOCTET(marker->data[13]);
|
||||
else if (num_markers != GETJOCTET(marker->data[13]))
|
||||
return FALSE; /* inconsistent num_markers fields */
|
||||
seq_no = GETJOCTET(marker->data[12]);
|
||||
if (seq_no <= 0 || seq_no > num_markers)
|
||||
return FALSE; /* bogus sequence number */
|
||||
if (marker_present[seq_no])
|
||||
return FALSE; /* duplicate sequence numbers */
|
||||
marker_present[seq_no] = 1;
|
||||
data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_markers == 0)
|
||||
return FALSE;
|
||||
|
||||
/* Check for missing markers, count total space needed,
|
||||
* compute offset of each marker's part of the data.
|
||||
*/
|
||||
|
||||
total_length = 0;
|
||||
for (seq_no = 1; seq_no <= num_markers; seq_no++) {
|
||||
if (marker_present[seq_no] == 0)
|
||||
return FALSE; /* missing sequence number */
|
||||
data_offset[seq_no] = total_length;
|
||||
total_length += data_length[seq_no];
|
||||
}
|
||||
|
||||
if (total_length <= 0)
|
||||
return FALSE; /* found only empty markers? */
|
||||
|
||||
/* Allocate space for assembled data */
|
||||
icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET));
|
||||
if (icc_data == NULL)
|
||||
return FALSE; /* oops, out of memory */
|
||||
|
||||
/* and fill it in */
|
||||
for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
|
||||
if (marker_is_icc(marker)) {
|
||||
JOCTET FAR *src_ptr;
|
||||
JOCTET *dst_ptr;
|
||||
unsigned int length;
|
||||
seq_no = GETJOCTET(marker->data[12]);
|
||||
dst_ptr = icc_data + data_offset[seq_no];
|
||||
src_ptr = marker->data + ICC_OVERHEAD_LEN;
|
||||
length = data_length[seq_no];
|
||||
while (length--) {
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*icc_data_ptr = icc_data;
|
||||
*icc_data_len = total_length;
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Little cms
|
||||
* Copyright (C) 1998-2004 Marti Maria <x@uknown.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||
* KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* iccprofile.h
|
||||
*
|
||||
* This file provides code to read and write International Color Consortium
|
||||
* (ICC) device profiles embedded in JFIF JPEG image files. The ICC has
|
||||
* defined a standard format for including such data in JPEG "APP2" markers.
|
||||
* The code given here does not know anything about the internal structure
|
||||
* of the ICC profile data; it just knows how to put the profile data into
|
||||
* a JPEG file being written, or get it back out when reading.
|
||||
*
|
||||
* This code depends on new features added to the IJG JPEG library as of
|
||||
* IJG release 6b; it will not compile or work with older IJG versions.
|
||||
*
|
||||
* NOTE: this code would need surgery to work on 16-bit-int machines
|
||||
* with ICC profiles exceeding 64K bytes in size. See iccprofile.c
|
||||
* for details.
|
||||
*/
|
||||
#ifndef ICCJPEG
|
||||
#define ICCJPEG
|
||||
|
||||
#include <stdio.h> /* needed to define "FILE", "NULL" */
|
||||
#include "jpeglib.h"
|
||||
|
||||
|
||||
/*
|
||||
* This routine writes the given ICC profile data into a JPEG file.
|
||||
* It *must* be called AFTER calling jpeg_start_compress() and BEFORE
|
||||
* the first call to jpeg_write_scanlines().
|
||||
* (This ordering ensures that the APP2 marker(s) will appear after the
|
||||
* SOI and JFIF or Adobe markers, but before all else.)
|
||||
*/
|
||||
|
||||
extern void write_icc_profile JPP((j_compress_ptr cinfo,
|
||||
const JOCTET *icc_data_ptr,
|
||||
unsigned int icc_data_len));
|
||||
|
||||
|
||||
/*
|
||||
* Reading a JPEG file that may contain an ICC profile requires two steps:
|
||||
*
|
||||
* 1. After jpeg_create_decompress() but before jpeg_read_header(),
|
||||
* call setup_read_icc_profile(). This routine tells the IJG library
|
||||
* to save in memory any APP2 markers it may find in the file.
|
||||
*
|
||||
* 2. After jpeg_read_header(), call read_icc_profile() to find out
|
||||
* whether there was a profile and obtain it if so.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Prepare for reading an ICC profile
|
||||
*/
|
||||
|
||||
extern void setup_read_icc_profile JPP((j_decompress_ptr cinfo));
|
||||
|
||||
|
||||
/*
|
||||
* See if there was an ICC profile in the JPEG file being read;
|
||||
* if so, reassemble and return the profile data.
|
||||
*
|
||||
* true is returned if an ICC profile was found, false if not.
|
||||
* If true is returned, *icc_data_ptr is set to point to the
|
||||
* returned data, and *icc_data_len is set to its length.
|
||||
*
|
||||
* IMPORTANT: the data at **icc_data_ptr has been allocated with malloc()
|
||||
* and must be freed by the caller with free() when the caller no longer
|
||||
* needs it. (Alternatively, we could write this routine to use the
|
||||
* IJG library's memory allocator, so that the data would be freed implicitly
|
||||
* at jpeg_finish_decompress() time. But it seems likely that many apps
|
||||
* will prefer to have the data stick around after decompression finishes.)
|
||||
*/
|
||||
|
||||
extern boolean read_icc_profile JPP((j_decompress_ptr cinfo,
|
||||
JOCTET **icc_data_ptr,
|
||||
unsigned int *icc_data_len));
|
||||
|
||||
#endif
|
|
@ -92,9 +92,4 @@ void AbstractDocumentImpl::setDocumentErrorString(const QString& string)
|
|||
d->mDocument->setErrorString(string);
|
||||
}
|
||||
|
||||
void AbstractDocumentImpl::setDocumentCmsProfile(Cms::Profile::Ptr profile)
|
||||
{
|
||||
d->mDocument->setCmsProfile(profile);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -110,7 +110,6 @@ protected:
|
|||
void setDocumentFormat(const QByteArray& format);
|
||||
void setDocumentExiv2Image(Exiv2::Image::AutoPtr);
|
||||
void setDocumentDownSampledImage(const QImage&, int invertedZoom);
|
||||
void setDocumentCmsProfile(Cms::Profile::Ptr profile);
|
||||
void setDocumentErrorString(const QString&);
|
||||
void switchToImpl(AbstractDocumentImpl* impl);
|
||||
|
||||
|
|
|
@ -182,7 +182,6 @@ void Document::reload()
|
|||
d->mImageMetaInfoModel.setUrl(d->mUrl);
|
||||
d->mUndoStack.clear();
|
||||
d->mErrorString.clear();
|
||||
d->mCmsProfile = 0;
|
||||
|
||||
switchToImpl(new LoadingDocumentImpl(this));
|
||||
}
|
||||
|
@ -563,14 +562,4 @@ QSvgRenderer* Document::svgRenderer() const
|
|||
return d->mImpl->svgRenderer();
|
||||
}
|
||||
|
||||
void Document::setCmsProfile(Cms::Profile::Ptr ptr)
|
||||
{
|
||||
d->mCmsProfile = ptr;
|
||||
}
|
||||
|
||||
Cms::Profile::Ptr Document::cmsProfile() const
|
||||
{
|
||||
return d->mCmsProfile;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -35,7 +35,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
// Local
|
||||
#include <lib/mimetypeutils.h>
|
||||
#include <lib/cms/cmsprofile.h>
|
||||
|
||||
class QImage;
|
||||
class QRect;
|
||||
|
@ -169,8 +168,6 @@ public:
|
|||
*/
|
||||
QByteArray rawData() const;
|
||||
|
||||
Cms::Profile::Ptr cmsProfile() const;
|
||||
|
||||
/**
|
||||
* Returns a QSvgRenderer which can be used to render this document if it is
|
||||
* an SVG image. Returns a NULL pointer otherwise.
|
||||
|
@ -241,7 +238,6 @@ private:
|
|||
void setDownSampledImage(const QImage&, int invertedZoom);
|
||||
void switchToImpl(AbstractDocumentImpl* impl);
|
||||
void setErrorString(const QString&);
|
||||
void setCmsProfile(Cms::Profile::Ptr);
|
||||
|
||||
Document(const KUrl&);
|
||||
DocumentPrivate * const d;
|
||||
|
|
|
@ -61,7 +61,6 @@ struct DocumentPrivate
|
|||
ImageMetaInfoModel mImageMetaInfoModel;
|
||||
QUndoStack mUndoStack;
|
||||
QString mErrorString;
|
||||
Cms::Profile::Ptr mCmsProfile;
|
||||
/** @} */
|
||||
|
||||
void scheduleImageLoading(int invertedZoom);
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2007 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
// Self
|
||||
#include "jpegdocumentloadedimpl.h"
|
||||
|
||||
// Qt
|
||||
#include <QImage>
|
||||
#include <QIODevice>
|
||||
|
||||
// KDE
|
||||
|
||||
// Local
|
||||
#include "jpegcontent.h"
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
struct JpegDocumentLoadedImplPrivate
|
||||
{
|
||||
JpegContent* mJpegContent;
|
||||
};
|
||||
|
||||
JpegDocumentLoadedImpl::JpegDocumentLoadedImpl(Document* doc, JpegContent* jpegContent)
|
||||
: DocumentLoadedImpl(doc, QByteArray() /* rawData */)
|
||||
, d(new JpegDocumentLoadedImplPrivate)
|
||||
{
|
||||
Q_ASSERT(jpegContent);
|
||||
d->mJpegContent = jpegContent;
|
||||
}
|
||||
|
||||
JpegDocumentLoadedImpl::~JpegDocumentLoadedImpl()
|
||||
{
|
||||
delete d->mJpegContent;
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool JpegDocumentLoadedImpl::saveInternal(QIODevice* device, const QByteArray& format)
|
||||
{
|
||||
if (format == "jpeg") {
|
||||
d->mJpegContent->resetOrientation();
|
||||
if (!d->mJpegContent->thumbnail().isNull()) {
|
||||
QImage thumbnail = document()->image().scaled(128, 128, Qt::KeepAspectRatio);
|
||||
d->mJpegContent->setThumbnail(thumbnail);
|
||||
}
|
||||
|
||||
bool ok = d->mJpegContent->save(device);
|
||||
if (!ok) {
|
||||
setDocumentErrorString(d->mJpegContent->errorString());
|
||||
}
|
||||
return ok;
|
||||
} else {
|
||||
return DocumentLoadedImpl::saveInternal(device, format);
|
||||
}
|
||||
}
|
||||
|
||||
void JpegDocumentLoadedImpl::setImage(const QImage& image)
|
||||
{
|
||||
d->mJpegContent->setImage(image);
|
||||
DocumentLoadedImpl::setImage(image);
|
||||
}
|
||||
|
||||
void JpegDocumentLoadedImpl::applyTransformation(Orientation orientation)
|
||||
{
|
||||
DocumentLoadedImpl::applyTransformation(orientation);
|
||||
d->mJpegContent->transform(orientation);
|
||||
}
|
||||
|
||||
QByteArray JpegDocumentLoadedImpl::rawData() const
|
||||
{
|
||||
return d->mJpegContent->rawData();
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -1,61 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2007 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef JPEGDOCUMENTLOADEDIMPL_H
|
||||
#define JPEGDOCUMENTLOADEDIMPL_H
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
|
||||
// Local
|
||||
#include <lib/document/documentloadedimpl.h>
|
||||
|
||||
class QByteArray;
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
class JpegContent;
|
||||
|
||||
struct JpegDocumentLoadedImplPrivate;
|
||||
class JpegDocumentLoadedImpl : public DocumentLoadedImpl
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
JpegDocumentLoadedImpl(Document*, JpegContent*);
|
||||
~JpegDocumentLoadedImpl();
|
||||
virtual QByteArray rawData() const;
|
||||
|
||||
protected:
|
||||
virtual bool saveInternal(QIODevice* device, const QByteArray& format);
|
||||
|
||||
// AbstractDocumentEditor
|
||||
virtual void setImage(const QImage&);
|
||||
virtual void applyTransformation(Orientation orientation);
|
||||
//
|
||||
|
||||
private:
|
||||
JpegDocumentLoadedImplPrivate* const d;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* JPEGDOCUMENTLOADEDIMPL_H */
|
|
@ -47,15 +47,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
// Local
|
||||
#include "animateddocumentloadedimpl.h"
|
||||
#include "cms/cmsprofile.h"
|
||||
#include "document.h"
|
||||
#include "documentloadedimpl.h"
|
||||
#include "emptydocumentimpl.h"
|
||||
#include "exiv2imageloader.h"
|
||||
#include "gvdebug.h"
|
||||
#include "imageutils.h"
|
||||
#include "jpegcontent.h"
|
||||
#include "jpegdocumentloadedimpl.h"
|
||||
#include "orientation.h"
|
||||
#include "svgdocumentloadedimpl.h"
|
||||
#include "urlutils.h"
|
||||
|
@ -99,9 +96,7 @@ struct LoadingDocumentImplPrivate
|
|||
QByteArray mFormat;
|
||||
QSize mImageSize;
|
||||
Exiv2::Image::AutoPtr mExiv2Image;
|
||||
std::auto_ptr<JpegContent> mJpegContent;
|
||||
QImage mImage;
|
||||
Cms::Profile::Ptr mCmsProfile;
|
||||
|
||||
/**
|
||||
* Determine kind of document and switch to an implementation if it is not
|
||||
|
@ -193,9 +188,6 @@ struct LoadingDocumentImplPrivate
|
|||
if (KDcrawIface::KDcraw::rawFilesList().contains(QString(mFormatHint))) {
|
||||
QByteArray previewData;
|
||||
|
||||
// if the image is in format supported by dcraw, fetch its embedded preview
|
||||
mJpegContent.reset(new JpegContent());
|
||||
|
||||
// use KDcraw for getting the embedded preview
|
||||
// KDcraw functionality cloned locally (temp. solution)
|
||||
bool ret = KDcrawIface::KDcraw::loadEmbeddedPreview(previewData, buffer);
|
||||
|
@ -255,30 +247,8 @@ struct LoadingDocumentImplPrivate
|
|||
mExiv2Image = loader.popImage();
|
||||
}
|
||||
|
||||
if (mFormat == "jpeg" && mExiv2Image.get()) {
|
||||
mJpegContent.reset(new JpegContent());
|
||||
}
|
||||
|
||||
if (mJpegContent.get()) {
|
||||
if (!mJpegContent->loadFromData(mData, mExiv2Image.get()) &&
|
||||
!mJpegContent->loadFromData(mData)) {
|
||||
kWarning() << "Unable to use preview of " << q->document()->url().fileName();
|
||||
return false;
|
||||
}
|
||||
// Use the size from JpegContent, as its correctly transposed if the
|
||||
// image has been rotated
|
||||
mImageSize = mJpegContent->size();
|
||||
|
||||
mCmsProfile = Cms::Profile::loadFromExiv2Image(mExiv2Image.get());
|
||||
|
||||
}
|
||||
|
||||
LOG("mImageSize" << mImageSize);
|
||||
|
||||
if (!mCmsProfile) {
|
||||
mCmsProfile = Cms::Profile::loadFromImageData(mData, mFormat);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -311,12 +281,6 @@ struct LoadingDocumentImplPrivate
|
|||
return;
|
||||
}
|
||||
|
||||
if (mJpegContent.get() && GwenviewConfig::applyExifOrientation()) {
|
||||
Gwenview::Orientation orientation = mJpegContent->orientation();
|
||||
QMatrix matrix = ImageUtils::transformMatrix(orientation);
|
||||
mImage = mImage.transformed(matrix);
|
||||
}
|
||||
|
||||
if (reader.supportsAnimation()
|
||||
&& reader.nextImageDelay() > 0 // Assume delay == 0 <=> only one frame
|
||||
) {
|
||||
|
@ -482,7 +446,6 @@ void LoadingDocumentImpl::slotMetaInfoLoaded()
|
|||
setDocumentFormat(d->mFormat);
|
||||
setDocumentImageSize(d->mImageSize);
|
||||
setDocumentExiv2Image(d->mExiv2Image);
|
||||
setDocumentCmsProfile(d->mCmsProfile);
|
||||
|
||||
d->mMetaInfoLoaded = true;
|
||||
emit metaInfoLoaded();
|
||||
|
@ -532,15 +495,9 @@ void LoadingDocumentImpl::slotImageLoaded()
|
|||
LOG("Loaded a full image");
|
||||
setDocumentImage(d->mImage);
|
||||
DocumentLoadedImpl* impl;
|
||||
if (d->mJpegContent.get()) {
|
||||
impl = new JpegDocumentLoadedImpl(
|
||||
document(),
|
||||
d->mJpegContent.release());
|
||||
} else {
|
||||
impl = new DocumentLoadedImpl(
|
||||
document(),
|
||||
d->mData);
|
||||
}
|
||||
impl = new DocumentLoadedImpl(
|
||||
document(),
|
||||
d->mData);
|
||||
switchToImpl(impl);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
|
|||
// Local
|
||||
#include <lib/documentview/abstractrasterimageviewtool.h>
|
||||
#include <lib/imagescaler.h>
|
||||
#include <lib/cms/cmsprofile.h>
|
||||
#include <lib/gvdebug.h>
|
||||
|
||||
// KDE
|
||||
|
@ -67,44 +66,6 @@ struct RasterImageViewPrivate
|
|||
|
||||
QWeakPointer<AbstractRasterImageViewTool> mTool;
|
||||
|
||||
bool mApplyDisplayTransform; // Defaults to true. Can be set to false if there is no need or no way to apply color profile
|
||||
cmsHTRANSFORM mDisplayTransform;
|
||||
|
||||
void updateDisplayTransform(QImage::Format format)
|
||||
{
|
||||
GV_RETURN_IF_FAIL(format != QImage::Format_Invalid);
|
||||
mApplyDisplayTransform = false;
|
||||
if (mDisplayTransform) {
|
||||
cmsDeleteTransform(mDisplayTransform);
|
||||
}
|
||||
mDisplayTransform = 0;
|
||||
|
||||
Cms::Profile::Ptr profile = q->document()->cmsProfile();
|
||||
if (!profile) {
|
||||
return;
|
||||
}
|
||||
Cms::Profile::Ptr monitorProfile = Cms::Profile::getMonitorProfile();
|
||||
if (!monitorProfile) {
|
||||
kWarning() << "Could not get monitor color profile";
|
||||
return;
|
||||
}
|
||||
|
||||
cmsUInt32Number cmsFormat = 0;
|
||||
switch (format) {
|
||||
case QImage::Format_RGB32:
|
||||
case QImage::Format_ARGB32:
|
||||
cmsFormat = TYPE_BGRA_8;
|
||||
break;
|
||||
default:
|
||||
kWarning() << "This image has a color profile, but Gwenview can only apply color profile on RGB32 or ARGB32 images";
|
||||
return;
|
||||
}
|
||||
mDisplayTransform = cmsCreateTransform(profile->handle(), cmsFormat,
|
||||
monitorProfile->handle(), cmsFormat,
|
||||
INTENT_PERCEPTUAL, cmsFLAGS_BLACKPOINTCOMPENSATION);
|
||||
mApplyDisplayTransform = true;
|
||||
}
|
||||
|
||||
void createBackgroundTexture()
|
||||
{
|
||||
mBackgroundTexture = QPixmap(32, 32);
|
||||
|
@ -191,8 +152,6 @@ RasterImageView::RasterImageView(QGraphicsItem* parent)
|
|||
{
|
||||
d->q = this;
|
||||
d->mEmittedCompleted = false;
|
||||
d->mApplyDisplayTransform = true;
|
||||
d->mDisplayTransform = 0;
|
||||
|
||||
d->mAlphaBackgroundMode = AlphaBackgroundCheckBoard;
|
||||
d->mAlphaBackgroundColor = Qt::black;
|
||||
|
@ -209,9 +168,6 @@ RasterImageView::RasterImageView(QGraphicsItem* parent)
|
|||
|
||||
RasterImageView::~RasterImageView()
|
||||
{
|
||||
if (d->mDisplayTransform) {
|
||||
cmsDeleteTransform(d->mDisplayTransform);
|
||||
}
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
@ -308,16 +264,6 @@ void RasterImageView::slotDocumentIsAnimatedUpdated()
|
|||
|
||||
void RasterImageView::updateFromScaler(int zoomedImageLeft, int zoomedImageTop, const QImage& image)
|
||||
{
|
||||
if (d->mApplyDisplayTransform) {
|
||||
if (!d->mDisplayTransform) {
|
||||
d->updateDisplayTransform(image.format());
|
||||
}
|
||||
if (d->mDisplayTransform) {
|
||||
quint8 *bytes = const_cast<quint8*>(image.bits());
|
||||
cmsDoTransform(d->mDisplayTransform, bytes, bytes, image.width() * image.height());
|
||||
}
|
||||
}
|
||||
|
||||
d->resizeBuffer();
|
||||
int viewportLeft = zoomedImageLeft - scrollPos().x();
|
||||
int viewportTop = zoomedImageTop - scrollPos().y();
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
// Self
|
||||
#include "imageformats.h"
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
// Include QImageIOPlugin to get qRegisterStaticPluginInstanceFunction(), which
|
||||
// does not come with QPluginLoader.
|
||||
#include <QtGui/qimageiohandler.h>
|
||||
|
||||
// KDE
|
||||
|
||||
// Local
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
QObject* qt_plugin_instance_JpegPlugin();
|
||||
|
||||
namespace ImageFormats
|
||||
{
|
||||
|
||||
static bool sPluginsRegistered = false;
|
||||
void registerPlugins()
|
||||
{
|
||||
if (sPluginsRegistered) {
|
||||
return;
|
||||
}
|
||||
sPluginsRegistered = true;
|
||||
qRegisterStaticPluginInstanceFunction(qt_plugin_instance_JpegPlugin);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
|
@ -1,43 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef IMAGEFORMATS_H
|
||||
#define IMAGEFORMATS_H
|
||||
|
||||
#include <lib/gwenviewlib_export.h>
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
|
||||
// Local
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
namespace ImageFormats
|
||||
{
|
||||
|
||||
GWENVIEWLIB_EXPORT void registerPlugins();
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif /* IMAGEFORMATS_H */
|
|
@ -1,537 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
--
|
||||
|
||||
The content of this file is based on qjpeghandler.cpp
|
||||
Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
|
||||
|
||||
*/
|
||||
// Self
|
||||
#include "jpeghandler.h"
|
||||
|
||||
// Qt
|
||||
#include <QImage>
|
||||
#include <QSize>
|
||||
#include <QVariant>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
|
||||
// libjpeg
|
||||
#include <setjmp.h>
|
||||
#define XMD_H
|
||||
extern "C" {
|
||||
#include <jpeglib.h>
|
||||
}
|
||||
|
||||
// Local
|
||||
#include "../iodevicejpegsourcemanager.h"
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
#undef ENABLE_LOG
|
||||
#undef LOG
|
||||
//#define ENABLE_LOG
|
||||
#ifdef ENABLE_LOG
|
||||
#define LOG(x) kDebug() << x
|
||||
#else
|
||||
#define LOG(x) ;
|
||||
#endif
|
||||
|
||||
struct JpegFatalError : public jpeg_error_mgr
|
||||
{
|
||||
jmp_buf mJmpBuffer;
|
||||
|
||||
static void handler(j_common_ptr cinfo)
|
||||
{
|
||||
JpegFatalError* error = static_cast<JpegFatalError*>(cinfo->err);
|
||||
(error->output_message)(cinfo);
|
||||
longjmp(error->mJmpBuffer, 1);
|
||||
}
|
||||
};
|
||||
|
||||
static void expand24to32bpp(QImage* image)
|
||||
{
|
||||
for (int j = 0; j < image->height(); ++j) {
|
||||
uchar *in = image->scanLine(j) + (image->width() - 1) * 3;
|
||||
QRgb *out = (QRgb*)(image->scanLine(j)) + image->width() - 1;
|
||||
|
||||
for (int i = image->width() - 1; i >= 0; --i, --out, in -= 3) {
|
||||
*out = qRgb(in[0], in[1], in[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void convertCmykToRgb(QImage* image)
|
||||
{
|
||||
for (int j = 0; j < image->height(); ++j) {
|
||||
uchar *in = image->scanLine(j) + image->width() * 4;
|
||||
QRgb *out = (QRgb*)image->scanLine(j);
|
||||
|
||||
for (int i = image->width() - 1; i >= 0; --i) {
|
||||
in -= 4;
|
||||
int k = in[3];
|
||||
out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static QSize getJpegSize(QIODevice* ioDevice)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
QSize size;
|
||||
|
||||
// Error handling
|
||||
struct JpegFatalError jerr;
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
cinfo.err->error_exit = JpegFatalError::handler;
|
||||
if (setjmp(jerr.mJmpBuffer)) {
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return size;
|
||||
}
|
||||
|
||||
// Init decompression
|
||||
jpeg_create_decompress(&cinfo);
|
||||
Gwenview::IODeviceJpegSourceManager::setup(&cinfo, ioDevice);
|
||||
jpeg_read_header(&cinfo, true);
|
||||
|
||||
size = QSize(cinfo.image_width, cinfo.image_height);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return size;
|
||||
}
|
||||
|
||||
static bool loadJpeg(QImage* image, QIODevice* ioDevice, QSize scaledSize)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
|
||||
// Error handling
|
||||
struct JpegFatalError jerr;
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
cinfo.err->error_exit = JpegFatalError::handler;
|
||||
if (setjmp(jerr.mJmpBuffer)) {
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Init decompression
|
||||
jpeg_create_decompress(&cinfo);
|
||||
Gwenview::IODeviceJpegSourceManager::setup(&cinfo, ioDevice);
|
||||
jpeg_read_header(&cinfo, true);
|
||||
|
||||
// Compute scale value
|
||||
cinfo.scale_num = 1;
|
||||
if (!scaledSize.isEmpty()) {
|
||||
// Use !scaledSize.isEmpty(), not scaledSize.isValid() because
|
||||
// isValid() returns true if both the width and height is equal to or
|
||||
// greater than 0, so it is possible to get a division by 0.
|
||||
cinfo.scale_denom = qMin(cinfo.image_width / scaledSize.width(),
|
||||
cinfo.image_height / scaledSize.height());
|
||||
if (cinfo.scale_denom < 2) {
|
||||
cinfo.scale_denom = 1;
|
||||
} else if (cinfo.scale_denom < 4) {
|
||||
cinfo.scale_denom = 2;
|
||||
} else if (cinfo.scale_denom < 8) {
|
||||
cinfo.scale_denom = 4;
|
||||
} else {
|
||||
cinfo.scale_denom = 8;
|
||||
}
|
||||
} else {
|
||||
cinfo.scale_denom = 1;
|
||||
}
|
||||
LOG("cinfo.scale_denom=" << cinfo.scale_denom);
|
||||
|
||||
// Init image
|
||||
jpeg_start_decompress(&cinfo);
|
||||
switch (cinfo.output_components) {
|
||||
case 3:
|
||||
case 4:
|
||||
*image = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_RGB32);
|
||||
break;
|
||||
case 1: // B&W image
|
||||
*image = QImage(cinfo.output_width, cinfo.output_height, QImage::Format_Indexed8);
|
||||
image->setColorCount(256);
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
image->setColor(i, qRgba(i, i, i, 255));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
uchar *line = image->scanLine(cinfo.output_scanline);
|
||||
jpeg_read_scanlines(&cinfo, &line, 1);
|
||||
}
|
||||
|
||||
switch (cinfo.out_color_space) {
|
||||
case JCS_CMYK:
|
||||
convertCmykToRgb(image);
|
||||
break;
|
||||
case JCS_RGB:
|
||||
case JCS_GRAYSCALE:
|
||||
break;
|
||||
default:
|
||||
kWarning() << "Unhandled JPEG colorspace" << cinfo.out_color_space;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cinfo.output_components == 3) {
|
||||
expand24to32bpp(image);
|
||||
}
|
||||
|
||||
const QSize actualSize(cinfo.output_width, cinfo.output_height);
|
||||
if (scaledSize.isValid() && actualSize != scaledSize) {
|
||||
*image = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
This code is a copy of qjpeghandler.cpp because I can't find a way to fallback
|
||||
to it for image writing.
|
||||
BEGIN_COPY
|
||||
****************************************************************************/
|
||||
struct my_error_mgr : public jpeg_error_mgr
|
||||
{
|
||||
jmp_buf setjmp_buffer;
|
||||
};
|
||||
|
||||
#if defined(Q_C_CALLBACKS)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static void my_error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
my_error_mgr* myerr = (my_error_mgr*) cinfo->err;
|
||||
char buffer[JMSG_LENGTH_MAX];
|
||||
(*cinfo->err->format_message)(cinfo, buffer);
|
||||
qWarning("%s", buffer);
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
#if defined(Q_C_CALLBACKS)
|
||||
}
|
||||
#endif
|
||||
|
||||
static const int max_buf = 4096;
|
||||
|
||||
struct my_jpeg_destination_mgr : public jpeg_destination_mgr
|
||||
{
|
||||
// Nothing dynamic - cannot rely on destruction over longjump
|
||||
QIODevice *device;
|
||||
JOCTET buffer[max_buf];
|
||||
|
||||
public:
|
||||
my_jpeg_destination_mgr(QIODevice *);
|
||||
};
|
||||
|
||||
#if defined(Q_C_CALLBACKS)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static void qt_init_destination(j_compress_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
static boolean qt_empty_output_buffer(j_compress_ptr cinfo)
|
||||
{
|
||||
my_jpeg_destination_mgr* dest = (my_jpeg_destination_mgr*)cinfo->dest;
|
||||
|
||||
int written = dest->device->write((char*)dest->buffer, max_buf);
|
||||
if (written == -1)
|
||||
(*cinfo->err->error_exit)((j_common_ptr)cinfo);
|
||||
|
||||
dest->next_output_byte = dest->buffer;
|
||||
dest->free_in_buffer = max_buf;
|
||||
|
||||
#if defined(Q_OS_UNIXWARE)
|
||||
return B_TRUE;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void qt_term_destination(j_compress_ptr cinfo)
|
||||
{
|
||||
my_jpeg_destination_mgr* dest = (my_jpeg_destination_mgr*)cinfo->dest;
|
||||
qint64 n = max_buf - dest->free_in_buffer;
|
||||
|
||||
qint64 written = dest->device->write((char*)dest->buffer, n);
|
||||
if (written == -1)
|
||||
(*cinfo->err->error_exit)((j_common_ptr)cinfo);
|
||||
}
|
||||
|
||||
#if defined(Q_C_CALLBACKS)
|
||||
}
|
||||
#endif
|
||||
|
||||
inline my_jpeg_destination_mgr::my_jpeg_destination_mgr(QIODevice *device)
|
||||
{
|
||||
jpeg_destination_mgr::init_destination = qt_init_destination;
|
||||
jpeg_destination_mgr::empty_output_buffer = qt_empty_output_buffer;
|
||||
jpeg_destination_mgr::term_destination = qt_term_destination;
|
||||
this->device = device;
|
||||
next_output_byte = buffer;
|
||||
free_in_buffer = max_buf;
|
||||
}
|
||||
|
||||
static bool write_jpeg_image(const QImage &sourceImage, QIODevice *device, int sourceQuality)
|
||||
{
|
||||
bool success = false;
|
||||
const QImage image = sourceImage;
|
||||
const QVector<QRgb> cmap = image.colorTable();
|
||||
|
||||
struct jpeg_compress_struct cinfo;
|
||||
JSAMPROW row_pointer[1];
|
||||
row_pointer[0] = 0;
|
||||
|
||||
struct my_jpeg_destination_mgr *iod_dest = new my_jpeg_destination_mgr(device);
|
||||
struct my_error_mgr jerr;
|
||||
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jerr.error_exit = my_error_exit;
|
||||
|
||||
if (!setjmp(jerr.setjmp_buffer)) {
|
||||
// WARNING:
|
||||
// this if loop is inside a setjmp/longjmp branch
|
||||
// do not create C++ temporaries here because the destructor may never be called
|
||||
// if you allocate memory, make sure that you can free it (row_pointer[0])
|
||||
jpeg_create_compress(&cinfo);
|
||||
|
||||
cinfo.dest = iod_dest;
|
||||
|
||||
cinfo.image_width = image.width();
|
||||
cinfo.image_height = image.height();
|
||||
|
||||
bool gray = false;
|
||||
switch (image.depth()) {
|
||||
case 1:
|
||||
case 8:
|
||||
gray = true;
|
||||
for (int i = image.colorCount(); gray && i--;) {
|
||||
gray = gray & (qRed(cmap[i]) == qGreen(cmap[i]) &&
|
||||
qRed(cmap[i]) == qBlue(cmap[i]));
|
||||
}
|
||||
cinfo.input_components = gray ? 1 : 3;
|
||||
cinfo.in_color_space = gray ? JCS_GRAYSCALE : JCS_RGB;
|
||||
break;
|
||||
case 32:
|
||||
cinfo.input_components = 3;
|
||||
cinfo.in_color_space = JCS_RGB;
|
||||
}
|
||||
|
||||
jpeg_set_defaults(&cinfo);
|
||||
|
||||
qreal diffInch = qAbs(image.dotsPerMeterX() * 2.54 / 100. - qRound(image.dotsPerMeterX() * 2.54 / 100.))
|
||||
+ qAbs(image.dotsPerMeterY() * 2.54 / 100. - qRound(image.dotsPerMeterY() * 2.54 / 100.));
|
||||
qreal diffCm = (qAbs(image.dotsPerMeterX() / 100. - qRound(image.dotsPerMeterX() / 100.))
|
||||
+ qAbs(image.dotsPerMeterY() / 100. - qRound(image.dotsPerMeterY() / 100.))) * 2.54;
|
||||
if (diffInch < diffCm) {
|
||||
cinfo.density_unit = 1; // dots/inch
|
||||
cinfo.X_density = qRound(image.dotsPerMeterX() * 2.54 / 100.);
|
||||
cinfo.Y_density = qRound(image.dotsPerMeterY() * 2.54 / 100.);
|
||||
} else {
|
||||
cinfo.density_unit = 2; // dots/cm
|
||||
cinfo.X_density = (image.dotsPerMeterX() + 50) / 100;
|
||||
cinfo.Y_density = (image.dotsPerMeterY() + 50) / 100;
|
||||
}
|
||||
|
||||
int quality = sourceQuality >= 0 ? qMin(sourceQuality, 100) : 75;
|
||||
#if defined(Q_OS_UNIXWARE)
|
||||
jpeg_set_quality(&cinfo, quality, B_TRUE /* limit to baseline-JPEG values */);
|
||||
jpeg_start_compress(&cinfo, B_TRUE);
|
||||
#else
|
||||
jpeg_set_quality(&cinfo, quality, true /* limit to baseline-JPEG values */);
|
||||
jpeg_start_compress(&cinfo, true);
|
||||
#endif
|
||||
|
||||
row_pointer[0] = new uchar[cinfo.image_width * cinfo.input_components];
|
||||
int w = cinfo.image_width;
|
||||
while (cinfo.next_scanline < cinfo.image_height) {
|
||||
uchar *row = row_pointer[0];
|
||||
switch (image.depth()) {
|
||||
case 1:
|
||||
if (gray) {
|
||||
const uchar* data = image.scanLine(cinfo.next_scanline);
|
||||
if (image.format() == QImage::Format_MonoLSB) {
|
||||
for (int i = 0; i < w; i++) {
|
||||
bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7)));
|
||||
row[i] = qRed(cmap[bit]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < w; i++) {
|
||||
bool bit = !!(*(data + (i >> 3)) & (1 << (7 - (i & 7))));
|
||||
row[i] = qRed(cmap[bit]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const uchar* data = image.scanLine(cinfo.next_scanline);
|
||||
if (image.format() == QImage::Format_MonoLSB) {
|
||||
for (int i = 0; i < w; i++) {
|
||||
bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7)));
|
||||
*row++ = qRed(cmap[bit]);
|
||||
*row++ = qGreen(cmap[bit]);
|
||||
*row++ = qBlue(cmap[bit]);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < w; i++) {
|
||||
bool bit = !!(*(data + (i >> 3)) & (1 << (7 - (i & 7))));
|
||||
*row++ = qRed(cmap[bit]);
|
||||
*row++ = qGreen(cmap[bit]);
|
||||
*row++ = qBlue(cmap[bit]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (gray) {
|
||||
const uchar* pix = image.scanLine(cinfo.next_scanline);
|
||||
for (int i = 0; i < w; i++) {
|
||||
*row = qRed(cmap[*pix]);
|
||||
++row; ++pix;
|
||||
}
|
||||
} else {
|
||||
const uchar* pix = image.scanLine(cinfo.next_scanline);
|
||||
for (int i = 0; i < w; i++) {
|
||||
*row++ = qRed(cmap[*pix]);
|
||||
*row++ = qGreen(cmap[*pix]);
|
||||
*row++ = qBlue(cmap[*pix]);
|
||||
++pix;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 32: {
|
||||
QRgb* rgb = (QRgb*)image.scanLine(cinfo.next_scanline);
|
||||
for (int i = 0; i < w; i++) {
|
||||
*row++ = qRed(*rgb);
|
||||
*row++ = qGreen(*rgb);
|
||||
*row++ = qBlue(*rgb);
|
||||
++rgb;
|
||||
}
|
||||
}
|
||||
}
|
||||
jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||||
}
|
||||
|
||||
jpeg_finish_compress(&cinfo);
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
success = true;
|
||||
} else {
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
success = false;
|
||||
}
|
||||
|
||||
delete iod_dest;
|
||||
delete [] row_pointer[0];
|
||||
return success;
|
||||
}
|
||||
/****************************************************************************
|
||||
END_COPY
|
||||
****************************************************************************/
|
||||
|
||||
struct JpegHandlerPrivate
|
||||
{
|
||||
QSize mScaledSize;
|
||||
int mQuality;
|
||||
};
|
||||
|
||||
JpegHandler::JpegHandler()
|
||||
: d(new JpegHandlerPrivate)
|
||||
{
|
||||
d->mQuality = 75;
|
||||
}
|
||||
|
||||
JpegHandler::~JpegHandler()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool JpegHandler::canRead() const
|
||||
{
|
||||
if (canRead(device())) {
|
||||
setFormat("jpeg");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JpegHandler::canRead(QIODevice* device)
|
||||
{
|
||||
if (!device) {
|
||||
kWarning() << "called with no device";
|
||||
return false;
|
||||
}
|
||||
|
||||
return device->peek(2) == "\xFF\xD8";
|
||||
}
|
||||
|
||||
bool JpegHandler::read(QImage* image)
|
||||
{
|
||||
LOG("");
|
||||
if (!canRead()) {
|
||||
return false;
|
||||
}
|
||||
return loadJpeg(image, device(), d->mScaledSize);
|
||||
}
|
||||
|
||||
bool JpegHandler::write(const QImage& image)
|
||||
{
|
||||
LOG("");
|
||||
return write_jpeg_image(image, device(), d->mQuality);
|
||||
}
|
||||
|
||||
bool JpegHandler::supportsOption(ImageOption option) const
|
||||
{
|
||||
return option == ScaledSize || option == Size || option == Quality;
|
||||
}
|
||||
|
||||
QVariant JpegHandler::option(ImageOption option) const
|
||||
{
|
||||
if (option == ScaledSize) {
|
||||
return d->mScaledSize;
|
||||
} else if (option == Size) {
|
||||
if (canRead() && !device()->isSequential()) {
|
||||
qint64 pos = device()->pos();
|
||||
QSize size = getJpegSize(device());
|
||||
device()->seek(pos);
|
||||
return size;
|
||||
}
|
||||
} else if (option == Quality) {
|
||||
return d->mQuality;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void JpegHandler::setOption(ImageOption option, const QVariant &value)
|
||||
{
|
||||
if (option == ScaledSize) {
|
||||
d->mScaledSize = value.toSize();
|
||||
} else if (option == Quality) {
|
||||
d->mQuality = value.toInt();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -1,60 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef JPEGHANDLER_H
|
||||
#define JPEGHANDLER_H
|
||||
|
||||
// Qt
|
||||
#include <QImageIOHandler>
|
||||
|
||||
// KDE
|
||||
|
||||
// Local
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
struct JpegHandlerPrivate;
|
||||
/**
|
||||
* A Jpeg handler which is more aggressive when loading down sampled images.
|
||||
*/
|
||||
class JpegHandler : public QImageIOHandler
|
||||
{
|
||||
public:
|
||||
JpegHandler();
|
||||
~JpegHandler();
|
||||
|
||||
bool canRead() const;
|
||||
bool read(QImage *image);
|
||||
bool write(const QImage& image);
|
||||
|
||||
static bool canRead(QIODevice *device);
|
||||
|
||||
QVariant option(ImageOption option) const;
|
||||
void setOption(ImageOption option, const QVariant &value);
|
||||
bool supportsOption(ImageOption option) const;
|
||||
|
||||
private:
|
||||
JpegHandlerPrivate* const d;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* JPEGHANDLER_H */
|
|
@ -1,72 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#define QT_STATICPLUGIN
|
||||
|
||||
// Self
|
||||
#include "jpegplugin.h"
|
||||
|
||||
// Qt
|
||||
#include <QImageIOHandler>
|
||||
|
||||
// Local
|
||||
#include "jpeghandler.h"
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
QStringList JpegPlugin::keys() const
|
||||
{
|
||||
return QStringList() << QLatin1String("jpeg") << QLatin1String("jpg");
|
||||
}
|
||||
|
||||
QImageIOPlugin::Capabilities JpegPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||
{
|
||||
if (format == "jpeg" || format == "jpg") {
|
||||
return Capabilities(CanRead | CanWrite);
|
||||
}
|
||||
if (!format.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
if (!device->isOpen()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Capabilities cap;
|
||||
if (device->isReadable() && JpegHandler::canRead(device)) {
|
||||
cap |= CanRead;
|
||||
}
|
||||
if (device->isWritable()) {
|
||||
cap |= CanWrite;
|
||||
}
|
||||
return cap;
|
||||
}
|
||||
|
||||
QImageIOHandler *JpegPlugin::create(QIODevice *device, const QByteArray &format) const
|
||||
{
|
||||
QImageIOHandler *handler = new JpegHandler;
|
||||
handler->setDevice(device);
|
||||
handler->setFormat(format);
|
||||
return handler;
|
||||
}
|
||||
|
||||
Q_EXPORT_STATIC_PLUGIN(JpegPlugin)
|
||||
|
||||
} // namespace
|
|
@ -1,45 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef JPEGPLUGIN_H
|
||||
#define JPEGPLUGIN_H
|
||||
|
||||
// Qt
|
||||
#include <QByteArray>
|
||||
#include <QtGui/qimageiohandler.h>
|
||||
|
||||
class QImageIOHandler;
|
||||
class QIODevice;
|
||||
class QStringList;
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
class JpegPlugin : public QImageIOPlugin
|
||||
{
|
||||
public:
|
||||
QStringList keys() const;
|
||||
Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
|
||||
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* JPEGPLUGIN_H */
|
|
@ -1,115 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
// Self
|
||||
#include "iodevicejpegsourcemanager.h"
|
||||
|
||||
// Qt
|
||||
#include <QIODevice>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
|
||||
// libjpeg
|
||||
#include <stdio.h>
|
||||
#define XMD_H
|
||||
extern "C" {
|
||||
#include <jpeglib.h>
|
||||
}
|
||||
|
||||
// Local
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
namespace IODeviceJpegSourceManager
|
||||
{
|
||||
|
||||
#define SOURCE_MANAGER_BUFFER_SIZE 4096
|
||||
struct IODeviceJpegSourceManager : public jpeg_source_mgr
|
||||
{
|
||||
QIODevice* mIODevice;
|
||||
JOCTET mBuffer[SOURCE_MANAGER_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
static boolean fill_input_buffer(j_decompress_ptr cinfo)
|
||||
{
|
||||
IODeviceJpegSourceManager* src = static_cast<IODeviceJpegSourceManager*>(cinfo->src);
|
||||
Q_ASSERT(src->mIODevice);
|
||||
int readSize = src->mIODevice->read((char*)src->mBuffer, SOURCE_MANAGER_BUFFER_SIZE);
|
||||
if (readSize > 0) {
|
||||
src->next_input_byte = src->mBuffer;
|
||||
src->bytes_in_buffer = readSize;
|
||||
} else {
|
||||
/**
|
||||
* JPEG file is broken. We feed the decoder with fake EOI, as specified
|
||||
* in the libjpeg documentation.
|
||||
*/
|
||||
static JOCTET fakeEOI[2] = { JOCTET(0xFF), JOCTET(JPEG_EOI)};
|
||||
kWarning() << "Image is incomplete";
|
||||
cinfo->src->next_input_byte = fakeEOI;
|
||||
cinfo->src->bytes_in_buffer = 2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init_source(j_decompress_ptr cinfo)
|
||||
{
|
||||
fill_input_buffer(cinfo);
|
||||
}
|
||||
|
||||
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long) cinfo->src->bytes_in_buffer) {
|
||||
num_bytes -= (long) cinfo->src->bytes_in_buffer;
|
||||
fill_input_buffer(cinfo);
|
||||
/**
|
||||
* we assume that fill_input_buffer will never return FALSE, so
|
||||
* suspension need not be handled.
|
||||
*/
|
||||
}
|
||||
cinfo->src->next_input_byte += (size_t) num_bytes;
|
||||
cinfo->src->bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void term_source(j_decompress_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
void setup(j_decompress_ptr cinfo, QIODevice* ioDevice)
|
||||
{
|
||||
Q_ASSERT(!cinfo->src);
|
||||
IODeviceJpegSourceManager* src = (IODeviceJpegSourceManager*)
|
||||
(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof(IODeviceJpegSourceManager));
|
||||
cinfo->src = src;
|
||||
|
||||
src->init_source = init_source;
|
||||
src->fill_input_buffer = fill_input_buffer;
|
||||
src->skip_input_data = skip_input_data;
|
||||
src->resync_to_restart = jpeg_resync_to_restart;
|
||||
src->term_source = term_source;
|
||||
|
||||
src->mIODevice = ioDevice;
|
||||
}
|
||||
|
||||
} // IODeviceJpegSourceManager namespace
|
||||
} // Gwenview namespace
|
|
@ -1,51 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef IODEVICEJPEGSOURCEMANAGER_H
|
||||
#define IODEVICEJPEGSOURCEMANAGER_H
|
||||
|
||||
// Qt
|
||||
|
||||
// KDE
|
||||
|
||||
// Local
|
||||
|
||||
class QIODevice;
|
||||
struct jpeg_decompress_struct;
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
/**
|
||||
* This namespace provides a function which makes it possible to decode JPEG
|
||||
* files with libjpeg from a QIODevice instance.
|
||||
*
|
||||
* To use it, simply call setup() to initialize your jpeg_decompress_struct
|
||||
* with QIODevice-ready callbacks. The device should be opened for reading.
|
||||
*/
|
||||
namespace IODeviceJpegSourceManager
|
||||
{
|
||||
|
||||
void setup(jpeg_decompress_struct* cinfo, QIODevice* ioDevice);
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif /* IODEVICEJPEGSOURCEMANAGER_H */
|
|
@ -1,644 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2007 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#include "jpegcontent.h"
|
||||
|
||||
// System
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
extern "C" {
|
||||
#include <jpeglib.h>
|
||||
#include "transupp.h"
|
||||
}
|
||||
|
||||
// Qt
|
||||
#include <QBuffer>
|
||||
#include <QFile>
|
||||
#include <QImage>
|
||||
#include <QImageWriter>
|
||||
#include <QMatrix>
|
||||
|
||||
// KDE
|
||||
#include <KDebug>
|
||||
#include <KLocale>
|
||||
|
||||
// Exiv2
|
||||
#include <exiv2/exif.hpp>
|
||||
#include <exiv2/image.hpp>
|
||||
|
||||
// Local
|
||||
#include "jpegerrormanager.h"
|
||||
#include "iodevicejpegsourcemanager.h"
|
||||
#include "exiv2imageloader.h"
|
||||
#include "gwenviewconfig.h"
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
const int INMEM_DST_DELTA = 4096;
|
||||
|
||||
//-----------------------------------------------
|
||||
//
|
||||
// In-memory data destination manager for libjpeg
|
||||
//
|
||||
//-----------------------------------------------
|
||||
struct inmem_dest_mgr : public jpeg_destination_mgr
|
||||
{
|
||||
QByteArray* mOutput;
|
||||
|
||||
void dump()
|
||||
{
|
||||
kDebug() << "dest_mgr:\n";
|
||||
kDebug() << "- next_output_byte: " << next_output_byte;
|
||||
kDebug() << "- free_in_buffer: " << free_in_buffer;
|
||||
kDebug() << "- output size: " << mOutput->size();
|
||||
}
|
||||
};
|
||||
|
||||
void inmem_init_destination(j_compress_ptr cinfo)
|
||||
{
|
||||
inmem_dest_mgr* dest = (inmem_dest_mgr*)(cinfo->dest);
|
||||
if (dest->mOutput->size() == 0) {
|
||||
dest->mOutput->resize(INMEM_DST_DELTA);
|
||||
}
|
||||
dest->free_in_buffer = dest->mOutput->size();
|
||||
dest->next_output_byte = (JOCTET*)(dest->mOutput->data());
|
||||
}
|
||||
|
||||
boolean inmem_empty_output_buffer(j_compress_ptr cinfo)
|
||||
{
|
||||
inmem_dest_mgr* dest = (inmem_dest_mgr*)(cinfo->dest);
|
||||
dest->mOutput->resize(dest->mOutput->size() + INMEM_DST_DELTA);
|
||||
dest->next_output_byte = (JOCTET*)(dest->mOutput->data() + dest->mOutput->size() - INMEM_DST_DELTA);
|
||||
dest->free_in_buffer = INMEM_DST_DELTA;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void inmem_term_destination(j_compress_ptr cinfo)
|
||||
{
|
||||
inmem_dest_mgr* dest = (inmem_dest_mgr*)(cinfo->dest);
|
||||
int finalSize = dest->next_output_byte - (JOCTET*)(dest->mOutput->data());
|
||||
Q_ASSERT(finalSize >= 0);
|
||||
dest->mOutput->resize(finalSize);
|
||||
}
|
||||
|
||||
//---------------------
|
||||
//
|
||||
// JpegContent::Private
|
||||
//
|
||||
//---------------------
|
||||
struct JpegContent::Private
|
||||
{
|
||||
// JpegContent usually stores the image pixels as compressed JPEG data in
|
||||
// mRawData. However if the image is set with setImage() because the user
|
||||
// performed a lossy image manipulation, mRawData is cleared and the image
|
||||
// pixels are kept in mImage until updateRawDataFromImage() is called.
|
||||
QImage mImage;
|
||||
QByteArray mRawData;
|
||||
QSize mSize;
|
||||
QString mComment;
|
||||
bool mPendingTransformation;
|
||||
QMatrix mTransformMatrix;
|
||||
Exiv2::ExifData mExifData;
|
||||
QString mErrorString;
|
||||
|
||||
Private()
|
||||
{
|
||||
mPendingTransformation = false;
|
||||
}
|
||||
|
||||
void setupInmemDestination(j_compress_ptr cinfo, QByteArray* outputData)
|
||||
{
|
||||
Q_ASSERT(!cinfo->dest);
|
||||
inmem_dest_mgr* dest = (inmem_dest_mgr*)
|
||||
(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof(inmem_dest_mgr));
|
||||
cinfo->dest = (struct jpeg_destination_mgr*)(dest);
|
||||
|
||||
dest->init_destination = inmem_init_destination;
|
||||
dest->empty_output_buffer = inmem_empty_output_buffer;
|
||||
dest->term_destination = inmem_term_destination;
|
||||
|
||||
dest->mOutput = outputData;
|
||||
}
|
||||
bool readSize()
|
||||
{
|
||||
struct jpeg_decompress_struct srcinfo;
|
||||
|
||||
// Init JPEG structs
|
||||
JPEGErrorManager errorManager;
|
||||
|
||||
// Initialize the JPEG decompression object
|
||||
srcinfo.err = &errorManager;
|
||||
jpeg_create_decompress(&srcinfo);
|
||||
if (setjmp(errorManager.jmp_buffer)) {
|
||||
kError() << "libjpeg fatal error\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Specify data source for decompression
|
||||
QBuffer buffer(&mRawData);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
IODeviceJpegSourceManager::setup(&srcinfo, &buffer);
|
||||
|
||||
// Read the header
|
||||
jcopy_markers_setup(&srcinfo, JCOPYOPT_ALL);
|
||||
int result = jpeg_read_header(&srcinfo, true);
|
||||
if (result != JPEG_HEADER_OK) {
|
||||
kError() << "Could not read jpeg header\n";
|
||||
jpeg_destroy_decompress(&srcinfo);
|
||||
return false;
|
||||
}
|
||||
mSize = QSize(srcinfo.image_width, srcinfo.image_height);
|
||||
|
||||
jpeg_destroy_decompress(&srcinfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool updateRawDataFromImage()
|
||||
{
|
||||
QBuffer buffer;
|
||||
QImageWriter writer(&buffer, "jpeg");
|
||||
if (!writer.write(mImage)) {
|
||||
mErrorString = writer.errorString();
|
||||
return false;
|
||||
}
|
||||
mRawData = buffer.data();
|
||||
mImage = QImage();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
//------------
|
||||
//
|
||||
// JpegContent
|
||||
//
|
||||
//------------
|
||||
JpegContent::JpegContent()
|
||||
{
|
||||
d = new JpegContent::Private();
|
||||
}
|
||||
|
||||
JpegContent::~JpegContent()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool JpegContent::load(const QString& path)
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
kError() << "Could not open '" << path << "' for reading\n";
|
||||
return false;
|
||||
}
|
||||
return loadFromData(file.readAll());
|
||||
}
|
||||
|
||||
bool JpegContent::loadFromData(const QByteArray& data)
|
||||
{
|
||||
Exiv2::Image::AutoPtr image;
|
||||
Exiv2ImageLoader loader;
|
||||
if (!loader.load(data)) {
|
||||
kError() << "Could not load image with Exiv2, reported error:" << loader.errorMessage();
|
||||
}
|
||||
image = loader.popImage();
|
||||
|
||||
return loadFromData(data, image.get());
|
||||
}
|
||||
|
||||
bool JpegContent::loadFromData(const QByteArray& data, Exiv2::Image* exiv2Image)
|
||||
{
|
||||
d->mPendingTransformation = false;
|
||||
d->mTransformMatrix.reset();
|
||||
|
||||
d->mRawData = data;
|
||||
if (d->mRawData.size() == 0) {
|
||||
kError() << "No data\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!d->readSize()) return false;
|
||||
|
||||
d->mExifData = exiv2Image->exifData();
|
||||
d->mComment = QString::fromUtf8(exiv2Image->comment().c_str());
|
||||
|
||||
if (!GwenviewConfig::applyExifOrientation()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Adjust the size according to the orientation
|
||||
switch (orientation()) {
|
||||
case TRANSPOSE:
|
||||
case ROT_90:
|
||||
case TRANSVERSE:
|
||||
case ROT_270:
|
||||
d->mSize.transpose();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QByteArray JpegContent::rawData() const
|
||||
{
|
||||
return d->mRawData;
|
||||
}
|
||||
|
||||
Orientation JpegContent::orientation() const
|
||||
{
|
||||
Exiv2::ExifKey key("Exif.Image.Orientation");
|
||||
Exiv2::ExifData::iterator it = d->mExifData.findKey(key);
|
||||
|
||||
// We do the same checks as in libexiv2's src/crwimage.cpp:
|
||||
// http://dev.exiv2.org/projects/exiv2/repository/entry/trunk/src/crwimage.cpp?rev=2681#L1336
|
||||
if (it == d->mExifData.end() || it->count() == 0 || it->typeId() != Exiv2::unsignedShort) {
|
||||
return NOT_AVAILABLE;
|
||||
}
|
||||
return Orientation(it->toLong());
|
||||
}
|
||||
|
||||
int JpegContent::dotsPerMeterX() const
|
||||
{
|
||||
return dotsPerMeter("XResolution");
|
||||
}
|
||||
|
||||
int JpegContent::dotsPerMeterY() const
|
||||
{
|
||||
return dotsPerMeter("YResolution");
|
||||
}
|
||||
|
||||
int JpegContent::dotsPerMeter(const QString& keyName) const
|
||||
{
|
||||
Exiv2::ExifKey keyResUnit("Exif.Image.ResolutionUnit");
|
||||
Exiv2::ExifData::iterator it = d->mExifData.findKey(keyResUnit);
|
||||
if (it == d->mExifData.end()) {
|
||||
return 0;
|
||||
}
|
||||
int res = it->toLong();
|
||||
QString keyVal = "Exif.Image." + keyName;
|
||||
Exiv2::ExifKey keyResolution(keyVal.toAscii().data());
|
||||
it = d->mExifData.findKey(keyResolution);
|
||||
if (it == d->mExifData.end()) {
|
||||
return 0;
|
||||
}
|
||||
// The unit for measuring XResolution and YResolution. The same unit is used for both XResolution and YResolution.
|
||||
// If the image resolution in unknown, 2 (inches) is designated.
|
||||
// Default = 2
|
||||
// 2 = inches
|
||||
// 3 = centimeters
|
||||
// Other = reserved
|
||||
const float INCHESPERMETER = (100. / 2.54);
|
||||
switch (res) {
|
||||
case 3: // dots per cm
|
||||
return int(it->toLong() * 100);
|
||||
default: // dots per inch
|
||||
return int(it->toLong() * INCHESPERMETER);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JpegContent::resetOrientation()
|
||||
{
|
||||
Exiv2::ExifKey key("Exif.Image.Orientation");
|
||||
Exiv2::ExifData::iterator it = d->mExifData.findKey(key);
|
||||
if (it == d->mExifData.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
*it = uint16_t(NORMAL);
|
||||
}
|
||||
|
||||
QSize JpegContent::size() const
|
||||
{
|
||||
return d->mSize;
|
||||
}
|
||||
|
||||
QString JpegContent::comment() const
|
||||
{
|
||||
return d->mComment;
|
||||
}
|
||||
|
||||
void JpegContent::setComment(const QString& comment)
|
||||
{
|
||||
d->mComment = comment;
|
||||
}
|
||||
|
||||
static QMatrix createRotMatrix(int angle)
|
||||
{
|
||||
QMatrix matrix;
|
||||
matrix.rotate(angle);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
static QMatrix createScaleMatrix(int dx, int dy)
|
||||
{
|
||||
QMatrix matrix;
|
||||
matrix.scale(dx, dy);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
struct OrientationInfo
|
||||
{
|
||||
OrientationInfo()
|
||||
: orientation(NOT_AVAILABLE)
|
||||
, jxform(JXFORM_NONE)
|
||||
{}
|
||||
|
||||
OrientationInfo(Orientation o, QMatrix m, JXFORM_CODE j)
|
||||
: orientation(o), matrix(m), jxform(j)
|
||||
{}
|
||||
|
||||
Orientation orientation;
|
||||
QMatrix matrix;
|
||||
JXFORM_CODE jxform;
|
||||
};
|
||||
typedef QList<OrientationInfo> OrientationInfoList;
|
||||
|
||||
static const OrientationInfoList& orientationInfoList()
|
||||
{
|
||||
static OrientationInfoList list;
|
||||
if (list.size() == 0) {
|
||||
QMatrix rot90 = createRotMatrix(90);
|
||||
QMatrix hflip = createScaleMatrix(-1, 1);
|
||||
QMatrix vflip = createScaleMatrix(1, -1);
|
||||
|
||||
list
|
||||
<< OrientationInfo()
|
||||
<< OrientationInfo(NORMAL, QMatrix(), JXFORM_NONE)
|
||||
<< OrientationInfo(HFLIP, hflip, JXFORM_FLIP_H)
|
||||
<< OrientationInfo(ROT_180, createRotMatrix(180), JXFORM_ROT_180)
|
||||
<< OrientationInfo(VFLIP, vflip, JXFORM_FLIP_V)
|
||||
<< OrientationInfo(TRANSPOSE, hflip * rot90, JXFORM_TRANSPOSE)
|
||||
<< OrientationInfo(ROT_90, rot90, JXFORM_ROT_90)
|
||||
<< OrientationInfo(TRANSVERSE, vflip * rot90, JXFORM_TRANSVERSE)
|
||||
<< OrientationInfo(ROT_270, createRotMatrix(270), JXFORM_ROT_270)
|
||||
;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void JpegContent::transform(Orientation orientation)
|
||||
{
|
||||
if (orientation != NOT_AVAILABLE && orientation != NORMAL) {
|
||||
d->mPendingTransformation = true;
|
||||
OrientationInfoList::ConstIterator it(orientationInfoList().begin()), end(orientationInfoList().end());
|
||||
for (; it != end; ++it) {
|
||||
if ((*it).orientation == orientation) {
|
||||
d->mTransformMatrix = (*it).matrix * d->mTransformMatrix;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (it == end) {
|
||||
kWarning() << "Could not find matrix for orientation\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void dumpMatrix(const QMatrix& matrix)
|
||||
{
|
||||
kDebug() << "matrix | " << matrix.m11() << ", " << matrix.m12() << " |\n";
|
||||
kDebug() << " | " << matrix.m21() << ", " << matrix.m22() << " |\n";
|
||||
kDebug() << " ( " << matrix.dx() << ", " << matrix.dy() << " )\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool matricesAreSame(const QMatrix& m1, const QMatrix& m2, double tolerance)
|
||||
{
|
||||
return fabs(m1.m11() - m2.m11()) < tolerance
|
||||
&& fabs(m1.m12() - m2.m12()) < tolerance
|
||||
&& fabs(m1.m21() - m2.m21()) < tolerance
|
||||
&& fabs(m1.m22() - m2.m22()) < tolerance
|
||||
&& fabs(m1.dx() - m2.dx()) < tolerance
|
||||
&& fabs(m1.dy() - m2.dy()) < tolerance;
|
||||
}
|
||||
|
||||
static JXFORM_CODE findJxform(const QMatrix& matrix)
|
||||
{
|
||||
OrientationInfoList::ConstIterator it(orientationInfoList().begin()), end(orientationInfoList().end());
|
||||
for (; it != end; ++it) {
|
||||
if (matricesAreSame((*it).matrix, matrix, 0.001)) {
|
||||
return (*it).jxform;
|
||||
}
|
||||
}
|
||||
kWarning() << "findJxform: failed\n";
|
||||
return JXFORM_NONE;
|
||||
}
|
||||
|
||||
void JpegContent::applyPendingTransformation()
|
||||
{
|
||||
if (d->mRawData.size() == 0) {
|
||||
kError() << "No data loaded\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// The following code is inspired by jpegtran.c from the libjpeg
|
||||
|
||||
// Init JPEG structs
|
||||
struct jpeg_decompress_struct srcinfo;
|
||||
struct jpeg_compress_struct dstinfo;
|
||||
jvirt_barray_ptr * src_coef_arrays;
|
||||
jvirt_barray_ptr * dst_coef_arrays;
|
||||
|
||||
// Initialize the JPEG decompression object
|
||||
JPEGErrorManager srcErrorManager;
|
||||
srcinfo.err = &srcErrorManager;
|
||||
jpeg_create_decompress(&srcinfo);
|
||||
if (setjmp(srcErrorManager.jmp_buffer)) {
|
||||
kError() << "libjpeg error in src\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the JPEG compression object
|
||||
JPEGErrorManager dstErrorManager;
|
||||
dstinfo.err = &dstErrorManager;
|
||||
jpeg_create_compress(&dstinfo);
|
||||
if (setjmp(dstErrorManager.jmp_buffer)) {
|
||||
kError() << "libjpeg error in dst\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// Specify data source for decompression
|
||||
QBuffer buffer(&d->mRawData);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
IODeviceJpegSourceManager::setup(&srcinfo, &buffer);
|
||||
|
||||
// Enable saving of extra markers that we want to copy
|
||||
jcopy_markers_setup(&srcinfo, JCOPYOPT_ALL);
|
||||
|
||||
(void) jpeg_read_header(&srcinfo, true);
|
||||
|
||||
// Init transformation
|
||||
jpeg_transform_info transformoption;
|
||||
memset(&transformoption, 0, sizeof(jpeg_transform_info));
|
||||
transformoption.transform = findJxform(d->mTransformMatrix);
|
||||
jtransform_request_workspace(&srcinfo, &transformoption);
|
||||
|
||||
/* Read source file as DCT coefficients */
|
||||
src_coef_arrays = jpeg_read_coefficients(&srcinfo);
|
||||
|
||||
/* Initialize destination compression parameters from source values */
|
||||
jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
|
||||
|
||||
/* Adjust destination parameters if required by transform options;
|
||||
* also find out which set of coefficient arrays will hold the output.
|
||||
*/
|
||||
dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
|
||||
src_coef_arrays,
|
||||
&transformoption);
|
||||
|
||||
/* Specify data destination for compression */
|
||||
QByteArray output;
|
||||
output.resize(d->mRawData.size());
|
||||
d->setupInmemDestination(&dstinfo, &output);
|
||||
|
||||
/* Start compressor (note no image data is actually written here) */
|
||||
jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
|
||||
|
||||
/* Copy to the output file any extra markers that we want to preserve */
|
||||
jcopy_markers_execute(&srcinfo, &dstinfo, JCOPYOPT_ALL);
|
||||
|
||||
/* Execute image transformation, if any */
|
||||
jtransform_execute_transformation(&srcinfo, &dstinfo,
|
||||
src_coef_arrays,
|
||||
&transformoption);
|
||||
|
||||
/* Finish compression and release memory */
|
||||
jpeg_finish_compress(&dstinfo);
|
||||
jpeg_destroy_compress(&dstinfo);
|
||||
(void) jpeg_finish_decompress(&srcinfo);
|
||||
jpeg_destroy_decompress(&srcinfo);
|
||||
|
||||
// Set rawData to our new JPEG
|
||||
d->mRawData = output;
|
||||
}
|
||||
|
||||
QImage JpegContent::thumbnail() const
|
||||
{
|
||||
QImage image;
|
||||
if (!d->mExifData.empty()) {
|
||||
#if(EXIV2_TEST_VERSION(0,17,91))
|
||||
Exiv2::ExifThumbC thumb(d->mExifData);
|
||||
Exiv2::DataBuf thumbnail = thumb.copy();
|
||||
#else
|
||||
Exiv2::DataBuf thumbnail = d->mExifData.copyThumbnail();
|
||||
#endif
|
||||
image.loadFromData(thumbnail.pData_, thumbnail.size_);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
void JpegContent::setThumbnail(const QImage& thumbnail)
|
||||
{
|
||||
if (d->mExifData.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray array;
|
||||
QBuffer buffer(&array);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
QImageWriter writer(&buffer, "JPEG");
|
||||
if (!writer.write(thumbnail)) {
|
||||
kError() << "Could not write thumbnail\n";
|
||||
return;
|
||||
}
|
||||
|
||||
#if (EXIV2_TEST_VERSION(0,17,91))
|
||||
Exiv2::ExifThumb thumb(d->mExifData);
|
||||
thumb.setJpegThumbnail((unsigned char*)array.data(), array.size());
|
||||
#else
|
||||
d->mExifData.setJpegThumbnail((unsigned char*)array.data(), array.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool JpegContent::save(const QString& path)
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
d->mErrorString = i18nc("@info", "Could not open file for writing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return save(&file);
|
||||
}
|
||||
|
||||
bool JpegContent::save(QIODevice* device)
|
||||
{
|
||||
if (!d->mImage.isNull()) {
|
||||
if (!d->updateRawDataFromImage()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (d->mRawData.size() == 0) {
|
||||
d->mErrorString = i18nc("@info", "No data to store.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (d->mPendingTransformation) {
|
||||
applyPendingTransformation();
|
||||
d->mPendingTransformation = false;
|
||||
}
|
||||
|
||||
Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((unsigned char*)d->mRawData.data(), d->mRawData.size());
|
||||
|
||||
// Store Exif info
|
||||
image->setExifData(d->mExifData);
|
||||
image->setComment(d->mComment.toUtf8().data());
|
||||
image->writeMetadata();
|
||||
|
||||
// Update mRawData
|
||||
Exiv2::BasicIo& io = image->io();
|
||||
d->mRawData.resize(io.size());
|
||||
io.read((unsigned char*)d->mRawData.data(), io.size());
|
||||
|
||||
QDataStream stream(device);
|
||||
stream.writeRawData(d->mRawData.data(), d->mRawData.size());
|
||||
|
||||
// Make sure we are up to date
|
||||
loadFromData(d->mRawData);
|
||||
return true;
|
||||
}
|
||||
|
||||
QString JpegContent::errorString() const
|
||||
{
|
||||
return d->mErrorString;
|
||||
}
|
||||
|
||||
void JpegContent::setImage(const QImage& image)
|
||||
{
|
||||
d->mRawData.clear();
|
||||
d->mImage = image;
|
||||
d->mSize = image.size();
|
||||
d->mExifData["Exif.Photo.PixelXDimension"] = image.width();
|
||||
d->mExifData["Exif.Photo.PixelYDimension"] = image.height();
|
||||
resetOrientation();
|
||||
|
||||
d->mPendingTransformation = false;
|
||||
d->mTransformMatrix = QMatrix();
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -1,92 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2007 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef JPEGCONTENT_H
|
||||
#define JPEGCONTENT_H
|
||||
|
||||
// Local
|
||||
#include <lib/orientation.h>
|
||||
#include <lib/gwenviewlib_export.h>
|
||||
|
||||
class QImage;
|
||||
class QSize;
|
||||
class QString;
|
||||
class QIODevice;
|
||||
|
||||
namespace Exiv2
|
||||
{
|
||||
class Image;
|
||||
}
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
class GWENVIEWLIB_EXPORT JpegContent
|
||||
{
|
||||
public:
|
||||
JpegContent();
|
||||
~JpegContent();
|
||||
|
||||
Orientation orientation() const;
|
||||
void resetOrientation();
|
||||
|
||||
int dotsPerMeterX() const;
|
||||
int dotsPerMeterY() const;
|
||||
|
||||
QSize size() const;
|
||||
|
||||
QString comment() const;
|
||||
void setComment(const QString&);
|
||||
|
||||
void transform(Orientation);
|
||||
|
||||
QImage thumbnail() const;
|
||||
void setThumbnail(const QImage&);
|
||||
|
||||
// Recreate raw data to represent image
|
||||
// Note: thumbnail must be updated separately
|
||||
void setImage(const QImage& image);
|
||||
|
||||
bool load(const QString& file);
|
||||
bool loadFromData(const QByteArray& rawData);
|
||||
/**
|
||||
* Use this version of loadFromData if you already have an Exiv2::Image*
|
||||
*/
|
||||
bool loadFromData(const QByteArray& rawData, Exiv2::Image*);
|
||||
bool save(const QString& file);
|
||||
bool save(QIODevice*);
|
||||
|
||||
QByteArray rawData() const;
|
||||
|
||||
QString errorString() const;
|
||||
|
||||
private:
|
||||
struct Private;
|
||||
Private *d;
|
||||
|
||||
JpegContent(const JpegContent&);
|
||||
void operator=(const JpegContent&);
|
||||
void applyPendingTransformation();
|
||||
int dotsPerMeter(const QString& keyName) const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* JPEGCONTENT_H */
|
|
@ -1,66 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2007 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef JPEGERRORMANAGER_H
|
||||
#define JPEGERRORMANAGER_H
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
extern "C" {
|
||||
#define XMD_H
|
||||
#include <jpeglib.h>
|
||||
#undef const
|
||||
}
|
||||
|
||||
namespace Gwenview
|
||||
{
|
||||
|
||||
/**
|
||||
* A simple error manager which overrides jpeg_error_mgr.error_exit to avoid
|
||||
* calls to exit(). It uses setjmp, which I don't like, but I don't fill like
|
||||
* introducing exceptions to the code base for now.
|
||||
*
|
||||
* In order to use it, give an instance of it to jpeg_decompress_struct.err,
|
||||
* then call setjmp(errorManager.jmp_buffer)
|
||||
*/
|
||||
struct JPEGErrorManager : public jpeg_error_mgr
|
||||
{
|
||||
JPEGErrorManager()
|
||||
: jpeg_error_mgr()
|
||||
{
|
||||
jpeg_std_error(this);
|
||||
error_exit = errorExitCallBack;
|
||||
}
|
||||
|
||||
jmp_buf jmp_buffer;
|
||||
|
||||
static void errorExitCallBack(j_common_ptr cinfo)
|
||||
{
|
||||
JPEGErrorManager* myerr = static_cast<JPEGErrorManager*>(cinfo->err);
|
||||
char buffer[JMSG_LENGTH_MAX];
|
||||
(*cinfo->err->format_message)(cinfo, buffer);
|
||||
kWarning() << buffer ;
|
||||
longjmp(myerr->jmp_buffer, 1);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif /* JPEGERRORMANAGER_H */
|
|
@ -1,385 +0,0 @@
|
|||
The Independent JPEG Group's JPEG software
|
||||
==========================================
|
||||
|
||||
README for release 6b of 27-Mar-1998
|
||||
====================================
|
||||
|
||||
This distribution contains the sixth public release of the Independent JPEG
|
||||
Group's free JPEG software. You are welcome to redistribute this software and
|
||||
to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
|
||||
|
||||
Serious users of this software (particularly those incorporating it into
|
||||
larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
|
||||
our electronic mailing list. Mailing list members are notified of updates
|
||||
and have a chance to participate in technical discussions, etc.
|
||||
|
||||
This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
|
||||
Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
|
||||
Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG
|
||||
Group.
|
||||
|
||||
IJG is not affiliated with the official ISO JPEG standards committee.
|
||||
|
||||
|
||||
DOCUMENTATION ROADMAP
|
||||
=====================
|
||||
|
||||
This file contains the following sections:
|
||||
|
||||
OVERVIEW General description of JPEG and the IJG software.
|
||||
LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
|
||||
REFERENCES Where to learn more about JPEG.
|
||||
ARCHIVE LOCATIONS Where to find newer versions of this software.
|
||||
RELATED SOFTWARE Other stuff you should get.
|
||||
FILE FORMAT WARS Software *not* to get.
|
||||
TO DO Plans for future IJG releases.
|
||||
|
||||
Other documentation files in the distribution are:
|
||||
|
||||
User documentation:
|
||||
install.doc How to configure and install the IJG software.
|
||||
usage.doc Usage instructions for cjpeg, djpeg, jpegtran,
|
||||
rdjpgcom, and wrjpgcom.
|
||||
*.1 Unix-style man pages for programs (same info as usage.doc).
|
||||
wizard.doc Advanced usage instructions for JPEG wizards only.
|
||||
change.log Version-to-version change highlights.
|
||||
Programmer and internal documentation:
|
||||
libjpeg.doc How to use the JPEG library in your own programs.
|
||||
example.c Sample code for calling the JPEG library.
|
||||
structure.doc Overview of the JPEG library's internal structure.
|
||||
filelist.doc Road map of IJG files.
|
||||
coderules.doc Coding style rules --- please read if you contribute code.
|
||||
|
||||
Please read at least the files install.doc and usage.doc. Useful information
|
||||
can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
|
||||
ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
|
||||
|
||||
If you want to understand how the JPEG code works, we suggest reading one or
|
||||
more of the REFERENCES, then looking at the documentation files (in roughly
|
||||
the order listed) before diving into the code.
|
||||
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
|
||||
This package contains C software to implement JPEG image compression and
|
||||
decompression. JPEG (pronounced "jay-peg") is a standardized compression
|
||||
method for full-color and gray-scale images. JPEG is intended for compressing
|
||||
"real-world" scenes; line drawings, cartoons and other non-realistic images
|
||||
are not its strong suit. JPEG is lossy, meaning that the output image is not
|
||||
exactly identical to the input image. Hence you must not use JPEG if you
|
||||
have to have identical output bits. However, on typical photographic images,
|
||||
very good compression levels can be obtained with no visible change, and
|
||||
remarkably high compression levels are possible if you can tolerate a
|
||||
low-quality image. For more details, see the references, or just experiment
|
||||
with various compression settings.
|
||||
|
||||
This software implements JPEG baseline, extended-sequential, and progressive
|
||||
compression processes. Provision is made for supporting all variants of these
|
||||
processes, although some uncommon parameter settings aren't implemented yet.
|
||||
For legal reasons, we are not distributing code for the arithmetic-coding
|
||||
variants of JPEG; see LEGAL ISSUES. We have made no provision for supporting
|
||||
the hierarchical or lossless processes defined in the standard.
|
||||
|
||||
We provide a set of library routines for reading and writing JPEG image files,
|
||||
plus two sample applications "cjpeg" and "djpeg", which use the library to
|
||||
perform conversion between JPEG and some other popular image file formats.
|
||||
The library is intended to be reused in other applications.
|
||||
|
||||
In order to support file conversion and viewing software, we have included
|
||||
considerable functionality beyond the bare JPEG coding/decoding capability;
|
||||
for example, the color quantization modules are not strictly part of JPEG
|
||||
decoding, but they are essential for output to colormapped file formats or
|
||||
colormapped displays. These extra functions can be compiled out of the
|
||||
library if not required for a particular application. We have also included
|
||||
"jpegtran", a utility for lossless transcoding between different JPEG
|
||||
processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
|
||||
inserting and extracting textual comments in JFIF files.
|
||||
|
||||
The emphasis in designing this software has been on achieving portability and
|
||||
flexibility, while also making it fast enough to be useful. In particular,
|
||||
the software is not intended to be read as a tutorial on JPEG. (See the
|
||||
REFERENCES section for introductory material.) Rather, it is intended to
|
||||
be reliable, portable, industrial-strength code. We do not claim to have
|
||||
achieved that goal in every aspect of the software, but we strive for it.
|
||||
|
||||
We welcome the use of this software as a component of commercial products.
|
||||
No royalty is required, but we do ask for an acknowledgement in product
|
||||
documentation, as described under LEGAL ISSUES.
|
||||
|
||||
|
||||
LEGAL ISSUES
|
||||
============
|
||||
|
||||
In plain English:
|
||||
|
||||
1. We don't promise that this software works. (But if you find any bugs,
|
||||
please let us know!)
|
||||
2. You can use this software for whatever you want. You don't have to pay us.
|
||||
3. You may not pretend that you wrote this software. If you use it in a
|
||||
program, you must acknowledge somewhere in your documentation that
|
||||
you've used the IJG code.
|
||||
|
||||
In legalese:
|
||||
|
||||
The authors make NO WARRANTY or representation, either express or implied,
|
||||
with respect to this software, its quality, accuracy, merchantability, or
|
||||
fitness for a particular purpose. This software is provided "AS IS", and you,
|
||||
its user, assume the entire risk as to its quality and accuracy.
|
||||
|
||||
This software is copyright (C) 1991-1998, Thomas G. Lane.
|
||||
All Rights Reserved except as specified below.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute this
|
||||
software (or portions thereof) for any purpose, without fee, subject to these
|
||||
conditions:
|
||||
(1) If any part of the source code for this software is distributed, then this
|
||||
README file must be included, with this copyright and no-warranty notice
|
||||
unaltered; and any additions, deletions, or changes to the original files
|
||||
must be clearly indicated in accompanying documentation.
|
||||
(2) If only executable code is distributed, then the accompanying
|
||||
documentation must state that "this software is based in part on the work of
|
||||
the Independent JPEG Group".
|
||||
(3) Permission for use of this software is granted only if the user accepts
|
||||
full responsibility for any undesirable consequences; the authors accept
|
||||
NO LIABILITY for damages of any kind.
|
||||
|
||||
These conditions apply to any software derived from or based on the IJG code,
|
||||
not just to the unmodified library. If you use our work, you ought to
|
||||
acknowledge us.
|
||||
|
||||
Permission is NOT granted for the use of any IJG author's name or company name
|
||||
in advertising or publicity relating to this software or products derived from
|
||||
it. This software may be referred to only as "the Independent JPEG Group's
|
||||
software".
|
||||
|
||||
We specifically permit and encourage the use of this software as the basis of
|
||||
commercial products, provided that all warranty or liability claims are
|
||||
assumed by the product vendor.
|
||||
|
||||
|
||||
ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
|
||||
sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
|
||||
ansi2knr.c is NOT covered by the above copyright and conditions, but instead
|
||||
by the usual distribution terms of the Free Software Foundation; principally,
|
||||
that you must include source code if you redistribute it. (See the file
|
||||
ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
|
||||
of any program generated from the IJG code, this does not limit you more than
|
||||
the foregoing paragraphs do.
|
||||
|
||||
The Unix configuration script "configure" was produced with GNU Autoconf.
|
||||
It is copyright by the Free Software Foundation but is freely distributable.
|
||||
The same holds for its supporting scripts (config.guess, config.sub,
|
||||
ltconfig, ltmain.sh). Another support script, install-sh, is copyright
|
||||
by M.I.T. but is also freely distributable.
|
||||
|
||||
It appears that the arithmetic coding option of the JPEG spec is covered by
|
||||
patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot
|
||||
legally be used without obtaining one or more licenses. For this reason,
|
||||
support for arithmetic coding has been removed from the free JPEG software.
|
||||
(Since arithmetic coding provides only a marginal gain over the unpatented
|
||||
Huffman mode, it is unlikely that very many implementations will support it.)
|
||||
So far as we are aware, there are no patent restrictions on the remaining
|
||||
code.
|
||||
|
||||
The IJG distribution formerly included code to read and write GIF files.
|
||||
To avoid entanglement with the Unisys LZW patent, GIF reading support has
|
||||
been removed altogether, and the GIF writer has been simplified to produce
|
||||
"uncompressed GIFs". This technique does not use the LZW algorithm; the
|
||||
resulting GIF files are larger than usual, but are readable by all standard
|
||||
GIF decoders.
|
||||
|
||||
We are required to state that
|
||||
"The Graphics Interchange Format(c) is the Copyright property of
|
||||
CompuServe Incorporated. GIF(sm) is a Service Mark property of
|
||||
CompuServe Incorporated."
|
||||
|
||||
|
||||
REFERENCES
|
||||
==========
|
||||
|
||||
We highly recommend reading one or more of these references before trying to
|
||||
understand the innards of the JPEG software.
|
||||
|
||||
The best short technical introduction to the JPEG compression algorithm is
|
||||
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
||||
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
|
||||
(Adjacent articles in that issue discuss MPEG motion picture compression,
|
||||
applications of JPEG, and related topics.) If you don't have the CACM issue
|
||||
handy, a PostScript file containing a revised version of Wallace's article is
|
||||
available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz. The file (actually
|
||||
a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
|
||||
omits the sample images that appeared in CACM, but it includes corrections
|
||||
and some added material. Note: the Wallace article is copyright ACM and IEEE,
|
||||
and it may not be used for commercial purposes.
|
||||
|
||||
A somewhat less technical, more leisurely introduction to JPEG can be found in
|
||||
"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
|
||||
M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides
|
||||
good explanations and example C code for a multitude of compression methods
|
||||
including JPEG. It is an excellent source if you are comfortable reading C
|
||||
code but don't know much about data compression in general. The book's JPEG
|
||||
sample code is far from industrial-strength, but when you are ready to look
|
||||
at a full implementation, you've got one here...
|
||||
|
||||
The best full description of JPEG is the textbook "JPEG Still Image Data
|
||||
Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
|
||||
by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp.
|
||||
The book includes the complete text of the ISO JPEG standards (DIS 10918-1
|
||||
and draft DIS 10918-2). This is by far the most complete exposition of JPEG
|
||||
in existence, and we highly recommend it.
|
||||
|
||||
The JPEG standard itself is not available electronically; you must order a
|
||||
paper copy through ISO or ITU. (Unless you feel a need to own a certified
|
||||
official copy, we recommend buying the Pennebaker and Mitchell book instead;
|
||||
it's much cheaper and includes a great deal of useful explanatory material.)
|
||||
In the USA, copies of the standard may be ordered from ANSI Sales at (212)
|
||||
642-4900, or from Global Engineering Documents at (800) 854-7179. (ANSI
|
||||
doesn't take credit card orders, but Global does.) It's not cheap: as of
|
||||
1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
|
||||
shipping/handling. The standard is divided into two parts, Part 1 being the
|
||||
actual specification, while Part 2 covers compliance testing methods. Part 1
|
||||
is titled "Digital Compression and Coding of Continuous-tone Still Images,
|
||||
Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
|
||||
10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
|
||||
Continuous-tone Still Images, Part 2: Compliance testing" and has document
|
||||
numbers ISO/IEC IS 10918-2, ITU-T T.83.
|
||||
|
||||
Some extensions to the original JPEG standard are defined in JPEG Part 3,
|
||||
a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84. IJG
|
||||
currently does not support any Part 3 extensions.
|
||||
|
||||
The JPEG standard does not specify all details of an interchangeable file
|
||||
format. For the omitted details we follow the "JFIF" conventions, revision
|
||||
1.02. A copy of the JFIF spec is available from:
|
||||
Literature Department
|
||||
C-Cube Microsystems, Inc.
|
||||
1778 McCarthy Blvd.
|
||||
Milpitas, CA 95035
|
||||
phone (408) 944-6300, fax (408) 944-6314
|
||||
A PostScript version of this document is available by FTP at
|
||||
ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz. There is also a plain text
|
||||
version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
|
||||
the figures.
|
||||
|
||||
The TIFF 6.0 file format specification can be obtained by FTP from
|
||||
ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
|
||||
found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
|
||||
IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
|
||||
Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
|
||||
(Compression tag 7). Copies of this Note can be obtained from ftp.sgi.com or
|
||||
from ftp://ftp.uu.net/graphics/jpeg/. It is expected that the next revision
|
||||
of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
|
||||
Although IJG's own code does not support TIFF/JPEG, the free libtiff library
|
||||
uses our library to implement TIFF/JPEG per the Note. libtiff is available
|
||||
from ftp://ftp.sgi.com/graphics/tiff/.
|
||||
|
||||
|
||||
ARCHIVE LOCATIONS
|
||||
=================
|
||||
|
||||
The "official" archive site for this software is ftp.uu.net (Internet
|
||||
address 192.48.96.9). The most recent released version can always be found
|
||||
there in directory graphics/jpeg. This particular version will be archived
|
||||
as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz. If you don't have
|
||||
direct Internet access, UUNET's archives are also available via UUCP; contact
|
||||
help@uunet.uu.net for information on retrieving files that way.
|
||||
|
||||
Numerous Internet sites maintain copies of the UUNET files. However, only
|
||||
ftp.uu.net is guaranteed to have the latest official version.
|
||||
|
||||
You can also obtain this software in DOS-compatible "zip" archive format from
|
||||
the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
|
||||
on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
|
||||
"JPEG Tools". Again, these versions may sometimes lag behind the ftp.uu.net
|
||||
release.
|
||||
|
||||
The JPEG FAQ (Frequently Asked Questions) article is a useful source of
|
||||
general information about JPEG. It is updated constantly and therefore is
|
||||
not included in this distribution. The FAQ is posted every two weeks to
|
||||
Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
|
||||
It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
|
||||
and other news.answers archive sites, including the official news.answers
|
||||
archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
|
||||
If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
|
||||
with body
|
||||
send usenet/news.answers/jpeg-faq/part1
|
||||
send usenet/news.answers/jpeg-faq/part2
|
||||
|
||||
|
||||
RELATED SOFTWARE
|
||||
================
|
||||
|
||||
Numerous viewing and image manipulation programs now support JPEG. (Quite a
|
||||
few of them use this library to do so.) The JPEG FAQ described above lists
|
||||
some of the more popular free and shareware viewers, and tells where to
|
||||
obtain them on Internet.
|
||||
|
||||
If you are on a Unix machine, we highly recommend Jef Poskanzer's free
|
||||
PBMPLUS software, which provides many useful operations on PPM-format image
|
||||
files. In particular, it can convert PPM images to and from a wide range of
|
||||
other formats, thus making cjpeg/djpeg considerably more useful. The latest
|
||||
version is distributed by the NetPBM group, and is available from numerous
|
||||
sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
|
||||
Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
|
||||
you are likely to have difficulty making it work on any non-Unix machine.
|
||||
|
||||
A different free JPEG implementation, written by the PVRG group at Stanford,
|
||||
is available from ftp://havefun.stanford.edu/pub/jpeg/. This program
|
||||
is designed for research and experimentation rather than production use;
|
||||
it is slower, harder to use, and less portable than the IJG code, but it
|
||||
is easier to read and modify. Also, the PVRG code supports lossless JPEG,
|
||||
which we do not. (On the other hand, it doesn't do progressive JPEG.)
|
||||
|
||||
|
||||
FILE FORMAT WARS
|
||||
================
|
||||
|
||||
Some JPEG programs produce files that are not compatible with our library.
|
||||
The root of the problem is that the ISO JPEG committee failed to specify a
|
||||
concrete file format. Some vendors "filled in the blanks" on their own,
|
||||
creating proprietary formats that no one else could read. (For example, none
|
||||
of the early commercial JPEG implementations for the Macintosh were able to
|
||||
exchange compressed files.)
|
||||
|
||||
The file format we have adopted is called JFIF (see REFERENCES). This format
|
||||
has been agreed to by a number of major commercial JPEG vendors, and it has
|
||||
become the de facto standard. JFIF is a minimal or "low end" representation.
|
||||
We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
|
||||
Technical Note #2) for "high end" applications that need to record a lot of
|
||||
additional data about an image. TIFF/JPEG is fairly new and not yet widely
|
||||
supported, unfortunately.
|
||||
|
||||
The upcoming JPEG Part 3 standard defines a file format called SPIFF.
|
||||
SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
|
||||
be able to read the most common variant of SPIFF. SPIFF has some technical
|
||||
advantages over JFIF, but its major claim to fame is simply that it is an
|
||||
official standard rather than an informal one. At this point it is unclear
|
||||
whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
|
||||
standard. IJG intends to support SPIFF once the standard is frozen, but we
|
||||
have not decided whether it should become our default output format or not.
|
||||
(In any case, our decoder will remain capable of reading JFIF indefinitely.)
|
||||
|
||||
Various proprietary file formats incorporating JPEG compression also exist.
|
||||
We have little or no sympathy for the existence of these formats. Indeed,
|
||||
one of the original reasons for developing this free software was to help
|
||||
force convergence on common, open format standards for JPEG files. Don't
|
||||
use a proprietary file format!
|
||||
|
||||
|
||||
TO DO
|
||||
=====
|
||||
|
||||
The major thrust for v7 will probably be improvement of visual quality.
|
||||
The current method for scaling the quantization tables is known not to be
|
||||
very good at low Q values. We also intend to investigate block boundary
|
||||
smoothing, "poor man's variable quantization", and other means of improving
|
||||
quality-vs-file-size performance without sacrificing compatibility.
|
||||
|
||||
In future versions, we are considering supporting some of the upcoming JPEG
|
||||
Part 3 extensions --- principally, variable quantization and the SPIFF file
|
||||
format.
|
||||
|
||||
As always, speeding things up is of great interest.
|
||||
|
||||
Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* jinclude.h
|
||||
*
|
||||
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file exists to provide a single place to fix any problems with
|
||||
* including the wrong system include files. (Common problems are taken
|
||||
* care of by the standard jconfig symbols, but on really weird systems
|
||||
* you may have to edit this file.)
|
||||
*
|
||||
* NOTE: this file is NOT intended to be included by applications using the
|
||||
* JPEG library. Most applications need only include jpeglib.h.
|
||||
*/
|
||||
|
||||
/* Include auto-config file to find out which system include files we need. */
|
||||
|
||||
#include "jconfig.h" /* auto configuration options */
|
||||
#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
|
||||
|
||||
/*
|
||||
* We need the NULL macro and size_t typedef.
|
||||
* On an ANSI-conforming system it is sufficient to include <stddef.h>.
|
||||
* Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
|
||||
* pull in <sys/types.h> as well.
|
||||
* Note that the core JPEG library does not require <stdio.h>;
|
||||
* only the default error handler and data source/destination modules do.
|
||||
* But we must pull it in because of the references to FILE in jpeglib.h.
|
||||
* You can remove those references if you want to compile without <stdio.h>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef NEED_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* We need memory copying and zeroing functions, plus strncpy().
|
||||
* ANSI and System V implementations declare these in <string.h>.
|
||||
* BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
|
||||
* Some systems may declare memset and memcpy in <memory.h>.
|
||||
*
|
||||
* NOTE: we assume the size parameters to these functions are of type size_t.
|
||||
* Change the casts in these macros if not!
|
||||
*/
|
||||
|
||||
#ifdef NEED_BSD_STRINGS
|
||||
|
||||
#include <strings.h>
|
||||
#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
|
||||
#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
|
||||
|
||||
#else /* not BSD, assume ANSI/SysV string lib */
|
||||
|
||||
#include <string.h>
|
||||
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
|
||||
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In ANSI C, and indeed any rational implementation, size_t is also the
|
||||
* type returned by sizeof(). However, it seems there are some irrational
|
||||
* implementations out there, in which sizeof() returns an int even though
|
||||
* size_t is defined as long or unsigned long. To ensure consistent results
|
||||
* we always use this SIZEOF() macro in place of using sizeof() directly.
|
||||
*/
|
||||
|
||||
#define SIZEOF(object) ((size_t) sizeof(object))
|
||||
|
||||
/*
|
||||
* The modules that use fread() and fwrite() always invoke them through
|
||||
* these macros. On some systems you may need to twiddle the argument casts.
|
||||
* CAUTION: argument order is different from underlying functions!
|
||||
*/
|
||||
|
||||
#define JFREAD(file,buf,sizeofbuf) \
|
||||
((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||
#define JFWRITE(file,buf,sizeofbuf) \
|
||||
((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
|
@ -1,389 +0,0 @@
|
|||
/*
|
||||
* jpegint.h
|
||||
*
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README.jpeg file.
|
||||
*
|
||||
* This file provides common declarations for the various JPEG modules.
|
||||
* These declarations are considered internal to the JPEG library; most
|
||||
* applications using the library shouldn't need to include this file.
|
||||
*/
|
||||
|
||||
/* Declarations for both compression & decompression */
|
||||
|
||||
typedef enum { /* Operating modes for buffer controllers */
|
||||
JBUF_PASS_THRU, /* Plain stripwise operation */
|
||||
/* Remaining modes require a full-image buffer to have been created */
|
||||
JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
|
||||
JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
|
||||
JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
|
||||
} J_BUF_MODE;
|
||||
|
||||
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
|
||||
#define CSTATE_START 100 /* after create_compress */
|
||||
#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
|
||||
#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
|
||||
#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
|
||||
#define DSTATE_START 200 /* after create_decompress */
|
||||
#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
|
||||
#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
|
||||
#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
|
||||
#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
|
||||
#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
|
||||
#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
|
||||
#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
|
||||
#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
|
||||
#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
|
||||
#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
|
||||
|
||||
/* Declarations for compression modules */
|
||||
|
||||
/* Master control module */
|
||||
struct jpeg_comp_master {
|
||||
JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean call_pass_startup; /* True if pass_startup must be called */
|
||||
boolean is_last_pass; /* True during last pass */
|
||||
};
|
||||
|
||||
/* Main buffer control (downsampled-data buffer) */
|
||||
struct jpeg_c_main_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, process_data, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
|
||||
JDIMENSION in_rows_avail));
|
||||
};
|
||||
|
||||
/* Compression preprocessing (downsampling input buffer control) */
|
||||
struct jpeg_c_prep_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf,
|
||||
JDIMENSION *in_row_ctr,
|
||||
JDIMENSION in_rows_avail,
|
||||
JSAMPIMAGE output_buf,
|
||||
JDIMENSION *out_row_group_ctr,
|
||||
JDIMENSION out_row_groups_avail));
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
struct jpeg_c_coef_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf));
|
||||
};
|
||||
|
||||
/* Colorspace conversion */
|
||||
struct jpeg_color_converter {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, color_convert, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||
JDIMENSION output_row, int num_rows));
|
||||
};
|
||||
|
||||
/* Downsampling */
|
||||
struct jpeg_downsampler {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, downsample, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION in_row_index,
|
||||
JSAMPIMAGE output_buf,
|
||||
JDIMENSION out_row_group_index));
|
||||
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Forward DCT (also controls coefficient quantization) */
|
||||
struct jpeg_forward_dct {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
/* perhaps this should be an array??? */
|
||||
JMETHOD(void, forward_DCT, (j_compress_ptr cinfo,
|
||||
jpeg_component_info * compptr,
|
||||
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||
JDIMENSION start_row, JDIMENSION start_col,
|
||||
JDIMENSION num_blocks));
|
||||
};
|
||||
|
||||
/* Entropy encoding */
|
||||
struct jpeg_entropy_encoder {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
|
||||
JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
|
||||
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
|
||||
};
|
||||
|
||||
/* Marker writing */
|
||||
struct jpeg_marker_writer {
|
||||
JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
|
||||
/* These routines are exported to allow insertion of extra markers */
|
||||
/* Probably only COM and APPn markers should be written this way */
|
||||
JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker,
|
||||
unsigned int datalen));
|
||||
JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val));
|
||||
};
|
||||
|
||||
/* Declarations for decompression modules */
|
||||
|
||||
/* Master control module */
|
||||
struct jpeg_decomp_master {
|
||||
JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
|
||||
};
|
||||
|
||||
/* Input control module */
|
||||
struct jpeg_input_controller {
|
||||
JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean has_multiple_scans; /* True if file has multiple scans */
|
||||
boolean eoi_reached; /* True when EOI has been consumed */
|
||||
};
|
||||
|
||||
/* Main buffer control (downsampled-data buffer) */
|
||||
struct jpeg_d_main_controller {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, process_data, (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
struct jpeg_d_coef_controller {
|
||||
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE output_buf));
|
||||
/* Pointer to array of coefficient virtual arrays, or NULL if none */
|
||||
jvirt_barray_ptr *coef_arrays;
|
||||
};
|
||||
|
||||
/* Decompression postprocessing (color quantization buffer control) */
|
||||
struct jpeg_d_post_controller {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf,
|
||||
JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
};
|
||||
|
||||
/* Marker reading & parsing */
|
||||
struct jpeg_marker_reader {
|
||||
JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
|
||||
/* Read markers until SOS or EOI.
|
||||
* Returns same codes as are defined for jpeg_consume_input:
|
||||
* JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||
*/
|
||||
JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
|
||||
/* Read a restart marker --- exported for use by entropy decoder only */
|
||||
jpeg_marker_parser_method read_restart_marker;
|
||||
|
||||
/* State of marker reader --- nominally internal, but applications
|
||||
* supplying COM or APPn handlers might like to know the state.
|
||||
*/
|
||||
boolean saw_SOI; /* found SOI? */
|
||||
boolean saw_SOF; /* found SOF? */
|
||||
int next_restart_num; /* next restart number expected (0-7) */
|
||||
unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
|
||||
};
|
||||
|
||||
/* Entropy decoding */
|
||||
struct jpeg_entropy_decoder {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
|
||||
/* This is here to share code between baseline and progressive decoders; */
|
||||
/* other modules probably should not use it */
|
||||
boolean insufficient_data; /* set TRUE after emitting warning */
|
||||
};
|
||||
|
||||
/* Inverse DCT (also performs dequantization) */
|
||||
typedef JMETHOD(void, inverse_DCT_method_ptr,
|
||||
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block,
|
||||
JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
|
||||
struct jpeg_inverse_dct {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
/* It is useful to allow each component to have a separate IDCT method. */
|
||||
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
|
||||
};
|
||||
|
||||
/* Upsampling (note that upsampler must also call color converter) */
|
||||
struct jpeg_upsampler {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, upsample, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf,
|
||||
JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Colorspace conversion */
|
||||
struct jpeg_color_deconverter {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||
JSAMPARRAY output_buf, int num_rows));
|
||||
};
|
||||
|
||||
/* Color quantization or color precision reduction */
|
||||
struct jpeg_color_quantizer {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
|
||||
JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JSAMPARRAY output_buf,
|
||||
int num_rows));
|
||||
JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
|
||||
};
|
||||
|
||||
/* Miscellaneous useful macros */
|
||||
|
||||
#undef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#undef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
/* We assume that right shift corresponds to signed division by 2 with
|
||||
* rounding towards minus infinity. This is correct for typical "arithmetic
|
||||
* shift" instructions that shift in copies of the sign bit. But some
|
||||
* C compilers implement >> with an unsigned shift. For these machines you
|
||||
* must define RIGHT_SHIFT_IS_UNSIGNED.
|
||||
* RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
|
||||
* It is only applied with constant shift counts. SHIFT_TEMPS must be
|
||||
* included in the variables of any routine using RIGHT_SHIFT.
|
||||
*/
|
||||
|
||||
#ifdef RIGHT_SHIFT_IS_UNSIGNED
|
||||
#define SHIFT_TEMPS INT32 shift_temp;
|
||||
#define RIGHT_SHIFT(x,shft) \
|
||||
((shift_temp = (x)) < 0 ? \
|
||||
(shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
|
||||
(shift_temp >> (shft)))
|
||||
#else
|
||||
#define SHIFT_TEMPS
|
||||
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
|
||||
#endif
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jinit_compress_master jICompress
|
||||
#define jinit_c_master_control jICMaster
|
||||
#define jinit_c_main_controller jICMainC
|
||||
#define jinit_c_prep_controller jICPrepC
|
||||
#define jinit_c_coef_controller jICCoefC
|
||||
#define jinit_color_converter jICColor
|
||||
#define jinit_downsampler jIDownsampler
|
||||
#define jinit_forward_dct jIFDCT
|
||||
#define jinit_huff_encoder jIHEncoder
|
||||
#define jinit_phuff_encoder jIPHEncoder
|
||||
#define jinit_marker_writer jIMWriter
|
||||
#define jinit_master_decompress jIDMaster
|
||||
#define jinit_d_main_controller jIDMainC
|
||||
#define jinit_d_coef_controller jIDCoefC
|
||||
#define jinit_d_post_controller jIDPostC
|
||||
#define jinit_input_controller jIInCtlr
|
||||
#define jinit_marker_reader jIMReader
|
||||
#define jinit_huff_decoder jIHDecoder
|
||||
#define jinit_phuff_decoder jIPHDecoder
|
||||
#define jinit_inverse_dct jIIDCT
|
||||
#define jinit_upsampler jIUpsampler
|
||||
#define jinit_color_deconverter jIDColor
|
||||
#define jinit_1pass_quantizer jI1Quant
|
||||
#define jinit_2pass_quantizer jI2Quant
|
||||
#define jinit_merged_upsampler jIMUpsampler
|
||||
#define jinit_memory_mgr jIMemMgr
|
||||
#define jdiv_round_up jDivRound
|
||||
#define jround_up jRound
|
||||
#define jcopy_sample_rows jCopySamples
|
||||
#define jcopy_block_row jCopyBlocks
|
||||
#define jzero_far jZeroFar
|
||||
#define jpeg_zigzag_order jZIGTable
|
||||
#define jpeg_natural_order jZAGTable
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
/* Compression module initialization routines */
|
||||
EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
|
||||
boolean transcode_only));
|
||||
EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
|
||||
/* Decompression module initialization routines */
|
||||
EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
|
||||
/* Memory manager initialization */
|
||||
EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
|
||||
|
||||
/* Utility routines in jutils.c */
|
||||
EXTERN(long) jdiv_round_up JPP((long a, long b));
|
||||
EXTERN(long) jround_up JPP((long a, long b));
|
||||
EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
|
||||
JSAMPARRAY output_array, int dest_row,
|
||||
int num_rows, JDIMENSION num_cols));
|
||||
EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
|
||||
JDIMENSION num_blocks));
|
||||
EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero));
|
||||
/* Constant tables in jutils.c */
|
||||
#if 0 /* This table is not actually needed in v6a */
|
||||
extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
|
||||
#endif
|
||||
extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
|
||||
|
||||
/* Suppress undefined-structure complaints if necessary. */
|
||||
|
||||
#ifdef INCOMPLETE_TYPES_BROKEN
|
||||
#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */
|
||||
struct jvirt_sarray_control {
|
||||
long dummy;
|
||||
};
|
||||
struct jvirt_barray_control {
|
||||
long dummy;
|
||||
};
|
||||
#endif
|
||||
#endif /* INCOMPLETE_TYPES_BROKEN */
|
|
@ -1,930 +0,0 @@
|
|||
/*
|
||||
* transupp.c
|
||||
*
|
||||
* Copyright (C) 1997, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains image transformation routines and other utility code
|
||||
* used by the jpegtran sample application. These are NOT part of the core
|
||||
* JPEG library. But we keep these routines separate from jpegtran.c to
|
||||
* ease the task of maintaining jpegtran-like programs that have other user
|
||||
* interfaces.
|
||||
*/
|
||||
|
||||
/* Although this file really shouldn't have access to the library internals,
|
||||
* it's helpful to let it call jround_up() and jcopy_block_row().
|
||||
*/
|
||||
#define JPEG_INTERNALS
|
||||
|
||||
#include "jinclude.h"
|
||||
#include "jpeglib.h"
|
||||
#include "transupp.h" /* My own external interface */
|
||||
|
||||
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
|
||||
/*
|
||||
* Lossless image transformation routines. These routines work on DCT
|
||||
* coefficient arrays and thus do not require any lossy decompression
|
||||
* or recompression of the image.
|
||||
* Thanks to Guido Vollbeding for the initial design and code of this feature.
|
||||
*
|
||||
* Horizontal flipping is done in-place, using a single top-to-bottom
|
||||
* pass through the virtual source array. It will thus be much the
|
||||
* fastest option for images larger than main memory.
|
||||
*
|
||||
* The other routines require a set of destination virtual arrays, so they
|
||||
* need twice as much memory as jpegtran normally does. The destination
|
||||
* arrays are always written in normal scan order (top to bottom) because
|
||||
* the virtual array manager expects this. The source arrays will be scanned
|
||||
* in the corresponding order, which means multiple passes through the source
|
||||
* arrays for most of the transforms. That could result in much thrashing
|
||||
* if the image is larger than main memory.
|
||||
*
|
||||
* Some notes about the operating environment of the individual transform
|
||||
* routines:
|
||||
* 1. Both the source and destination virtual arrays are allocated from the
|
||||
* source JPEG object, and therefore should be manipulated by calling the
|
||||
* source's memory manager.
|
||||
* 2. The destination's component count should be used. It may be smaller
|
||||
* than the source's when forcing to grayscale.
|
||||
* 3. Likewise the destination's sampling factors should be used. When
|
||||
* forcing to grayscale the destination's sampling factors will be all 1,
|
||||
* and we may as well take that as the effective iMCU size.
|
||||
* 4. When "trim" is in effect, the destination's dimensions will be the
|
||||
* trimmed values but the source's will be untrimmed.
|
||||
* 5. All the routines assume that the source and destination buffers are
|
||||
* padded out to a full iMCU boundary. This is true, although for the
|
||||
* source buffer it is an undocumented property of jdcoefct.c.
|
||||
* Notes 2,3,4 boil down to this: generally we should use the destination's
|
||||
* dimensions and ignore the source's.
|
||||
*/
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays)
|
||||
/* Horizontal flip; done in-place, so no separate dest array is required */
|
||||
{
|
||||
JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
|
||||
int ci, k, offset_y;
|
||||
JBLOCKARRAY buffer;
|
||||
JCOEFPTR ptr1, ptr2;
|
||||
JCOEF temp1, temp2;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Horizontal mirroring of DCT blocks is accomplished by swapping
|
||||
* pairs of blocks in-place. Within a DCT block, we perform horizontal
|
||||
* mirroring by changing the signs of odd-numbered columns.
|
||||
* Partial iMCUs at the right edge are left untouched.
|
||||
*/
|
||||
MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_width = MCU_cols * compptr->h_samp_factor;
|
||||
for (blk_y = 0; blk_y < compptr->height_in_blocks;
|
||||
blk_y += compptr->v_samp_factor) {
|
||||
buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
|
||||
ptr1 = buffer[offset_y][blk_x];
|
||||
ptr2 = buffer[offset_y][comp_width - blk_x - 1];
|
||||
/* this unrolled loop doesn't need to know which row it's on... */
|
||||
for (k = 0; k < DCTSIZE2; k += 2) {
|
||||
temp1 = *ptr1; /* swap even column */
|
||||
temp2 = *ptr2;
|
||||
*ptr1++ = temp2;
|
||||
*ptr2++ = temp1;
|
||||
temp1 = *ptr1; /* swap odd column with sign change */
|
||||
temp2 = *ptr2;
|
||||
*ptr1++ = -temp2;
|
||||
*ptr2++ = -temp1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* Vertical flip */
|
||||
{
|
||||
JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JBLOCKROW src_row_ptr, dst_row_ptr;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* We output into a separate array because we can't touch different
|
||||
* rows of the source virtual array simultaneously. Otherwise, this
|
||||
* is a pretty straightforward analog of horizontal flip.
|
||||
* Within a DCT block, vertical mirroring is done by changing the signs
|
||||
* of odd-numbered rows.
|
||||
* Partial iMCUs at the bottom edge are copied verbatim.
|
||||
*/
|
||||
MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_height = MCU_rows * compptr->v_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Row is within the mirrorable area. */
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci],
|
||||
comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
} else {
|
||||
/* Bottom-edge blocks will be copied verbatim. */
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
}
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Row is within the mirrorable area. */
|
||||
dst_row_ptr = dst_buffer[offset_y];
|
||||
src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[dst_blk_x];
|
||||
for (i = 0; i < DCTSIZE; i += 2) {
|
||||
/* copy even row */
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
/* copy odd row with sign change */
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Just copy row verbatim. */
|
||||
jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
|
||||
compptr->width_in_blocks);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* Transpose source into destination */
|
||||
{
|
||||
JDIMENSION dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_x, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Transposing pixels within a block just requires transposing the
|
||||
* DCT coefficients.
|
||||
* Partial iMCUs at the edges require no special treatment; we simply
|
||||
* process all the available DCT blocks for every component.
|
||||
*/
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x += compptr->h_samp_factor) {
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
|
||||
(JDIMENSION) compptr->h_samp_factor, FALSE);
|
||||
for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
|
||||
src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* 90 degree rotation is equivalent to
|
||||
* 1. Transposing the image;
|
||||
* 2. Horizontal mirroring.
|
||||
* These two steps are merged into a single processing routine.
|
||||
*/
|
||||
{
|
||||
JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_x, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Because of the horizontal mirror step, we can't process partial iMCUs
|
||||
* at the (output) right edge properly. They just get transposed and
|
||||
* not mirrored.
|
||||
*/
|
||||
MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_width = MCU_cols * compptr->h_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x += compptr->h_samp_factor) {
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
|
||||
(JDIMENSION) compptr->h_samp_factor, FALSE);
|
||||
for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
|
||||
src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
|
||||
if (dst_blk_x < comp_width) {
|
||||
/* Block is within the mirrorable area. */
|
||||
dst_ptr = dst_buffer[offset_y]
|
||||
[comp_width - dst_blk_x - offset_x - 1];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
i++;
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
} else {
|
||||
/* Edge blocks are transposed but not mirrored. */
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* 270 degree rotation is equivalent to
|
||||
* 1. Horizontal mirroring;
|
||||
* 2. Transposing the image.
|
||||
* These two steps are merged into a single processing routine.
|
||||
*/
|
||||
{
|
||||
JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_x, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
/* Because of the horizontal mirror step, we can't process partial iMCUs
|
||||
* at the (output) bottom edge properly. They just get transposed and
|
||||
* not mirrored.
|
||||
*/
|
||||
MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_height = MCU_rows * compptr->v_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x += compptr->h_samp_factor) {
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
|
||||
(JDIMENSION) compptr->h_samp_factor, FALSE);
|
||||
for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Block is within the mirrorable area. */
|
||||
src_ptr = src_buffer[offset_x]
|
||||
[comp_height - dst_blk_y - offset_y - 1];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++) {
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
j++;
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Edge blocks are transposed but not mirrored. */
|
||||
src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* 180 degree rotation is equivalent to
|
||||
* 1. Vertical mirroring;
|
||||
* 2. Horizontal mirroring.
|
||||
* These two steps are merged into a single processing routine.
|
||||
*/
|
||||
{
|
||||
JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JBLOCKROW src_row_ptr, dst_row_ptr;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
|
||||
MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_width = MCU_cols * compptr->h_samp_factor;
|
||||
comp_height = MCU_rows * compptr->v_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Row is within the vertically mirrorable area. */
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci],
|
||||
comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
} else {
|
||||
/* Bottom-edge rows are only mirrored horizontally. */
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
||||
}
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
if (dst_blk_y < comp_height) {
|
||||
/* Row is within the mirrorable area. */
|
||||
dst_row_ptr = dst_buffer[offset_y];
|
||||
src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
|
||||
/* Process the blocks that can be mirrored both ways. */
|
||||
for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
|
||||
for (i = 0; i < DCTSIZE; i += 2) {
|
||||
/* For even row, negate every odd column. */
|
||||
for (j = 0; j < DCTSIZE; j += 2) {
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
}
|
||||
/* For odd row, negate every even column. */
|
||||
for (j = 0; j < DCTSIZE; j += 2) {
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Any remaining right-edge blocks are only mirrored vertically. */
|
||||
for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[dst_blk_x];
|
||||
for (i = 0; i < DCTSIZE; i += 2) {
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Remaining rows are just mirrored horizontally. */
|
||||
dst_row_ptr = dst_buffer[offset_y];
|
||||
src_row_ptr = src_buffer[offset_y];
|
||||
/* Process the blocks that can be mirrored. */
|
||||
for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
|
||||
for (i = 0; i < DCTSIZE2; i += 2) {
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
*dst_ptr++ = - *src_ptr++;
|
||||
}
|
||||
}
|
||||
/* Any remaining right-edge blocks are only copied. */
|
||||
for (; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
|
||||
dst_ptr = dst_row_ptr[dst_blk_x];
|
||||
src_ptr = src_row_ptr[dst_blk_x];
|
||||
for (i = 0; i < DCTSIZE2; i++)
|
||||
*dst_ptr++ = *src_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOCAL(void)
|
||||
do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jvirt_barray_ptr *dst_coef_arrays)
|
||||
/* Transverse transpose is equivalent to
|
||||
* 1. 180 degree rotation;
|
||||
* 2. Transposition;
|
||||
* or
|
||||
* 1. Horizontal mirroring;
|
||||
* 2. Transposition;
|
||||
* 3. Horizontal mirroring.
|
||||
* These steps are merged into a single processing routine.
|
||||
*/
|
||||
{
|
||||
JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
|
||||
int ci, i, j, offset_x, offset_y;
|
||||
JBLOCKARRAY src_buffer, dst_buffer;
|
||||
JCOEFPTR src_ptr, dst_ptr;
|
||||
jpeg_component_info *compptr;
|
||||
|
||||
MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
|
||||
MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
|
||||
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
comp_width = MCU_cols * compptr->h_samp_factor;
|
||||
comp_height = MCU_rows * compptr->v_samp_factor;
|
||||
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
||||
dst_blk_y += compptr->v_samp_factor) {
|
||||
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
||||
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
||||
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
||||
for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
|
||||
dst_blk_x += compptr->h_samp_factor) {
|
||||
src_buffer = (*srcinfo->mem->access_virt_barray)
|
||||
((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
|
||||
(JDIMENSION) compptr->h_samp_factor, FALSE);
|
||||
for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
|
||||
if (dst_blk_y < comp_height) {
|
||||
src_ptr = src_buffer[offset_x]
|
||||
[comp_height - dst_blk_y - offset_y - 1];
|
||||
if (dst_blk_x < comp_width) {
|
||||
/* Block is within the mirrorable area. */
|
||||
dst_ptr = dst_buffer[offset_y]
|
||||
[comp_width - dst_blk_x - offset_x - 1];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++) {
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
j++;
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
i++;
|
||||
for (j = 0; j < DCTSIZE; j++) {
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
j++;
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Right-edge blocks are mirrored in y only */
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++) {
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
j++;
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
|
||||
if (dst_blk_x < comp_width) {
|
||||
/* Bottom-edge blocks are mirrored in x only */
|
||||
dst_ptr = dst_buffer[offset_y]
|
||||
[comp_width - dst_blk_x - offset_x - 1];
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
i++;
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
} else {
|
||||
/* At lower right corner, just transpose, no mirroring */
|
||||
dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
|
||||
for (i = 0; i < DCTSIZE; i++)
|
||||
for (j = 0; j < DCTSIZE; j++)
|
||||
dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Request any required workspace.
|
||||
*
|
||||
* We allocate the workspace virtual arrays from the source decompression
|
||||
* object, so that all the arrays (both the original data and the workspace)
|
||||
* will be taken into account while making memory management decisions.
|
||||
* Hence, this routine must be called after jpeg_read_header (which reads
|
||||
* the image dimensions) and before jpeg_read_coefficients (which realizes
|
||||
* the source's virtual arrays).
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jtransform_request_workspace (j_decompress_ptr srcinfo,
|
||||
jpeg_transform_info *info)
|
||||
{
|
||||
jvirt_barray_ptr *coef_arrays = NULL;
|
||||
jpeg_component_info *compptr;
|
||||
int ci;
|
||||
|
||||
if (info->force_grayscale &&
|
||||
srcinfo->jpeg_color_space == JCS_YCbCr &&
|
||||
srcinfo->num_components == 3) {
|
||||
/* We'll only process the first component */
|
||||
info->num_components = 1;
|
||||
} else {
|
||||
/* Process all the components */
|
||||
info->num_components = srcinfo->num_components;
|
||||
}
|
||||
|
||||
switch (info->transform) {
|
||||
case JXFORM_NONE:
|
||||
case JXFORM_FLIP_H:
|
||||
/* Don't need a workspace array */
|
||||
break;
|
||||
case JXFORM_FLIP_V:
|
||||
case JXFORM_ROT_180:
|
||||
/* Need workspace arrays having same dimensions as source image.
|
||||
* Note that we allocate arrays padded out to the next iMCU boundary,
|
||||
* so that transform routines need not worry about missing edge blocks.
|
||||
*/
|
||||
coef_arrays = (jvirt_barray_ptr *)
|
||||
(*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
|
||||
SIZEOF(jvirt_barray_ptr) * info->num_components);
|
||||
for (ci = 0; ci < info->num_components; ci++) {
|
||||
compptr = srcinfo->comp_info + ci;
|
||||
coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
|
||||
((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) compptr->v_samp_factor);
|
||||
}
|
||||
break;
|
||||
case JXFORM_TRANSPOSE:
|
||||
case JXFORM_TRANSVERSE:
|
||||
case JXFORM_ROT_90:
|
||||
case JXFORM_ROT_270:
|
||||
/* Need workspace arrays having transposed dimensions.
|
||||
* Note that we allocate arrays padded out to the next iMCU boundary,
|
||||
* so that transform routines need not worry about missing edge blocks.
|
||||
*/
|
||||
coef_arrays = (jvirt_barray_ptr *)
|
||||
(*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
|
||||
SIZEOF(jvirt_barray_ptr) * info->num_components);
|
||||
for (ci = 0; ci < info->num_components; ci++) {
|
||||
compptr = srcinfo->comp_info + ci;
|
||||
coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
|
||||
((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
|
||||
(JDIMENSION) jround_up((long) compptr->height_in_blocks,
|
||||
(long) compptr->v_samp_factor),
|
||||
(JDIMENSION) jround_up((long) compptr->width_in_blocks,
|
||||
(long) compptr->h_samp_factor),
|
||||
(JDIMENSION) compptr->h_samp_factor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
info->workspace_coef_arrays = coef_arrays;
|
||||
}
|
||||
|
||||
|
||||
/* Transpose destination image parameters */
|
||||
|
||||
LOCAL(void)
|
||||
transpose_critical_parameters (j_compress_ptr dstinfo)
|
||||
{
|
||||
int tblno, i, j, ci, itemp;
|
||||
jpeg_component_info *compptr;
|
||||
JQUANT_TBL *qtblptr;
|
||||
JDIMENSION dtemp;
|
||||
UINT16 qtemp;
|
||||
|
||||
/* Transpose basic image dimensions */
|
||||
dtemp = dstinfo->image_width;
|
||||
dstinfo->image_width = dstinfo->image_height;
|
||||
dstinfo->image_height = dtemp;
|
||||
|
||||
/* Transpose sampling factors */
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
compptr = dstinfo->comp_info + ci;
|
||||
itemp = compptr->h_samp_factor;
|
||||
compptr->h_samp_factor = compptr->v_samp_factor;
|
||||
compptr->v_samp_factor = itemp;
|
||||
}
|
||||
|
||||
/* Transpose quantization tables */
|
||||
for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
|
||||
qtblptr = dstinfo->quant_tbl_ptrs[tblno];
|
||||
if (qtblptr != NULL) {
|
||||
for (i = 0; i < DCTSIZE; i++) {
|
||||
for (j = 0; j < i; j++) {
|
||||
qtemp = qtblptr->quantval[i*DCTSIZE+j];
|
||||
qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
|
||||
qtblptr->quantval[j*DCTSIZE+i] = qtemp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Trim off any partial iMCUs on the indicated destination edge */
|
||||
|
||||
LOCAL(void)
|
||||
trim_right_edge (j_compress_ptr dstinfo)
|
||||
{
|
||||
int ci, max_h_samp_factor;
|
||||
JDIMENSION MCU_cols;
|
||||
|
||||
/* We have to compute max_h_samp_factor ourselves,
|
||||
* because it hasn't been set yet in the destination
|
||||
* (and we don't want to use the source's value).
|
||||
*/
|
||||
max_h_samp_factor = 1;
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
|
||||
max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
|
||||
}
|
||||
MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
|
||||
if (MCU_cols > 0) /* can't trim to 0 pixels */
|
||||
dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
|
||||
}
|
||||
|
||||
LOCAL(void)
|
||||
trim_bottom_edge (j_compress_ptr dstinfo)
|
||||
{
|
||||
int ci, max_v_samp_factor;
|
||||
JDIMENSION MCU_rows;
|
||||
|
||||
/* We have to compute max_v_samp_factor ourselves,
|
||||
* because it hasn't been set yet in the destination
|
||||
* (and we don't want to use the source's value).
|
||||
*/
|
||||
max_v_samp_factor = 1;
|
||||
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
||||
int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
|
||||
max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
|
||||
}
|
||||
MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
|
||||
if (MCU_rows > 0) /* can't trim to 0 pixels */
|
||||
dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
|
||||
}
|
||||
|
||||
|
||||
/* Adjust output image parameters as needed.
|
||||
*
|
||||
* This must be called after jpeg_copy_critical_parameters()
|
||||
* and before jpeg_write_coefficients().
|
||||
*
|
||||
* The return value is the set of virtual coefficient arrays to be written
|
||||
* (either the ones allocated by jtransform_request_workspace, or the
|
||||
* original source data arrays). The caller will need to pass this value
|
||||
* to jpeg_write_coefficients().
|
||||
*/
|
||||
|
||||
GLOBAL(jvirt_barray_ptr *)
|
||||
jtransform_adjust_parameters (j_decompress_ptr srcinfo,
|
||||
j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info)
|
||||
{
|
||||
srcinfo = srcinfo; /* avoid unsued parameter warning */
|
||||
/* If force-to-grayscale is requested, adjust destination parameters */
|
||||
if (info->force_grayscale) {
|
||||
/* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
|
||||
* properly. Among other things, the target h_samp_factor & v_samp_factor
|
||||
* will get set to 1, which typically won't match the source.
|
||||
* In fact we do this even if the source is already grayscale; that
|
||||
* provides an easy way of coercing a grayscale JPEG with funny sampling
|
||||
* factors to the customary 1,1. (Some decoders fail on other factors.)
|
||||
*/
|
||||
if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
|
||||
dstinfo->num_components == 3) ||
|
||||
(dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
|
||||
dstinfo->num_components == 1)) {
|
||||
/* We have to preserve the source's quantization table number. */
|
||||
int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
|
||||
jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
|
||||
dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
|
||||
} else {
|
||||
/* Sorry, can't do it */
|
||||
ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Correct the destination's image dimensions etc if necessary */
|
||||
switch (info->transform) {
|
||||
case JXFORM_NONE:
|
||||
/* Nothing to do */
|
||||
break;
|
||||
case JXFORM_FLIP_H:
|
||||
if (info->trim)
|
||||
trim_right_edge(dstinfo);
|
||||
break;
|
||||
case JXFORM_FLIP_V:
|
||||
if (info->trim)
|
||||
trim_bottom_edge(dstinfo);
|
||||
break;
|
||||
case JXFORM_TRANSPOSE:
|
||||
transpose_critical_parameters(dstinfo);
|
||||
/* transpose does NOT have to trim anything */
|
||||
break;
|
||||
case JXFORM_TRANSVERSE:
|
||||
transpose_critical_parameters(dstinfo);
|
||||
if (info->trim) {
|
||||
trim_right_edge(dstinfo);
|
||||
trim_bottom_edge(dstinfo);
|
||||
}
|
||||
break;
|
||||
case JXFORM_ROT_90:
|
||||
transpose_critical_parameters(dstinfo);
|
||||
if (info->trim)
|
||||
trim_right_edge(dstinfo);
|
||||
break;
|
||||
case JXFORM_ROT_180:
|
||||
if (info->trim) {
|
||||
trim_right_edge(dstinfo);
|
||||
trim_bottom_edge(dstinfo);
|
||||
}
|
||||
break;
|
||||
case JXFORM_ROT_270:
|
||||
transpose_critical_parameters(dstinfo);
|
||||
if (info->trim)
|
||||
trim_bottom_edge(dstinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return the appropriate output data set */
|
||||
if (info->workspace_coef_arrays != NULL)
|
||||
return info->workspace_coef_arrays;
|
||||
return src_coef_arrays;
|
||||
}
|
||||
|
||||
|
||||
/* Execute the actual transformation, if any.
|
||||
*
|
||||
* This must be called *after* jpeg_write_coefficients, because it depends
|
||||
* on jpeg_write_coefficients to have computed subsidiary values such as
|
||||
* the per-component width and height fields in the destination object.
|
||||
*
|
||||
* Note that some transformations will modify the source data arrays!
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jtransform_execute_transformation (j_decompress_ptr srcinfo,
|
||||
j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info)
|
||||
{
|
||||
jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
|
||||
|
||||
switch (info->transform) {
|
||||
case JXFORM_NONE:
|
||||
break;
|
||||
case JXFORM_FLIP_H:
|
||||
do_flip_h(srcinfo, dstinfo, src_coef_arrays);
|
||||
break;
|
||||
case JXFORM_FLIP_V:
|
||||
do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_TRANSPOSE:
|
||||
do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_TRANSVERSE:
|
||||
do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_ROT_90:
|
||||
do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_ROT_180:
|
||||
do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
case JXFORM_ROT_270:
|
||||
do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* TRANSFORMS_SUPPORTED */
|
||||
|
||||
|
||||
/* Setup decompression object to save desired markers in memory.
|
||||
* This must be called before jpeg_read_header() to have the desired effect.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
|
||||
{
|
||||
#ifdef SAVE_MARKERS_SUPPORTED
|
||||
int m;
|
||||
|
||||
/* Save comments except under NONE option */
|
||||
if (option != JCOPYOPT_NONE) {
|
||||
jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
|
||||
}
|
||||
/* Save all types of APPn markers iff ALL option */
|
||||
if (option == JCOPYOPT_ALL) {
|
||||
for (m = 0; m < 16; m++)
|
||||
jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
|
||||
}
|
||||
#endif /* SAVE_MARKERS_SUPPORTED */
|
||||
}
|
||||
|
||||
/* Copy markers saved in the given source object to the destination object.
|
||||
* This should be called just after jpeg_start_compress() or
|
||||
* jpeg_write_coefficients().
|
||||
* Note that those routines will have written the SOI, and also the
|
||||
* JFIF APP0 or Adobe APP14 markers if selected.
|
||||
*/
|
||||
|
||||
GLOBAL(void)
|
||||
jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
JCOPY_OPTION option)
|
||||
{
|
||||
option = option; /* avoid unsued parameter warning */
|
||||
jpeg_saved_marker_ptr marker;
|
||||
|
||||
/* In the current implementation, we don't actually need to examine the
|
||||
* option flag here; we just copy everything that got saved.
|
||||
* But to avoid confusion, we do not output JFIF and Adobe APP14 markers
|
||||
* if the encoder library already wrote one.
|
||||
*/
|
||||
for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
|
||||
if (dstinfo->write_JFIF_header &&
|
||||
marker->marker == JPEG_APP0 &&
|
||||
marker->data_length >= 5 &&
|
||||
GETJOCTET(marker->data[0]) == 0x4A &&
|
||||
GETJOCTET(marker->data[1]) == 0x46 &&
|
||||
GETJOCTET(marker->data[2]) == 0x49 &&
|
||||
GETJOCTET(marker->data[3]) == 0x46 &&
|
||||
GETJOCTET(marker->data[4]) == 0)
|
||||
continue; /* reject duplicate JFIF */
|
||||
if (dstinfo->write_Adobe_marker &&
|
||||
marker->marker == JPEG_APP0+14 &&
|
||||
marker->data_length >= 5 &&
|
||||
GETJOCTET(marker->data[0]) == 0x41 &&
|
||||
GETJOCTET(marker->data[1]) == 0x64 &&
|
||||
GETJOCTET(marker->data[2]) == 0x6F &&
|
||||
GETJOCTET(marker->data[3]) == 0x62 &&
|
||||
GETJOCTET(marker->data[4]) == 0x65)
|
||||
continue; /* reject duplicate Adobe */
|
||||
#ifdef NEED_FAR_POINTERS
|
||||
/* We could use jpeg_write_marker if the data weren't FAR... */
|
||||
{
|
||||
unsigned int i;
|
||||
jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
|
||||
for (i = 0; i < marker->data_length; i++)
|
||||
jpeg_write_m_byte(dstinfo, marker->data[i]);
|
||||
}
|
||||
#else
|
||||
jpeg_write_marker(dstinfo, marker->marker,
|
||||
marker->data, marker->data_length);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* transupp.h
|
||||
*
|
||||
* Copyright (C) 1997, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains declarations for image transformation routines and
|
||||
* other utility code used by the jpegtran sample application. These are
|
||||
* NOT part of the core JPEG library. But we keep these routines separate
|
||||
* from jpegtran.c to ease the task of maintaining jpegtran-like programs
|
||||
* that have other user interfaces.
|
||||
*
|
||||
* NOTE: all the routines declared here have very specific requirements
|
||||
* about when they are to be executed during the reading and writing of the
|
||||
* source and destination files. See the comments in transupp.c, or see
|
||||
* jpegtran.c for an example of correct usage.
|
||||
*/
|
||||
|
||||
#ifndef TRANSUPP_H
|
||||
#define TRANSUPP_H
|
||||
|
||||
/* If you happen not to want the image transform support, disable it here */
|
||||
#ifndef TRANSFORMS_SUPPORTED
|
||||
#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
|
||||
#endif
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jtransform_request_workspace jTrRequest
|
||||
#define jtransform_adjust_parameters jTrAdjust
|
||||
#define jtransform_execute_transformation jTrExec
|
||||
#define jcopy_markers_setup jCMrkSetup
|
||||
#define jcopy_markers_execute jCMrkExec
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
/*
|
||||
* Codes for supported types of image transformations.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JXFORM_NONE, /* no transformation */
|
||||
JXFORM_FLIP_H, /* horizontal flip */
|
||||
JXFORM_FLIP_V, /* vertical flip */
|
||||
JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
|
||||
JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
|
||||
JXFORM_ROT_90, /* 90-degree clockwise rotation */
|
||||
JXFORM_ROT_180, /* 180-degree rotation */
|
||||
JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
|
||||
} JXFORM_CODE;
|
||||
|
||||
/*
|
||||
* Although rotating and flipping data expressed as DCT coefficients is not
|
||||
* hard, there is an asymmetry in the JPEG format specification for images
|
||||
* whose dimensions aren't multiples of the iMCU size. The right and bottom
|
||||
* image edges are padded out to the next iMCU boundary with junk data; but
|
||||
* no padding is possible at the top and left edges. If we were to flip
|
||||
* the whole image including the pad data, then pad garbage would become
|
||||
* visible at the top and/or left, and real pixels would disappear into the
|
||||
* pad margins --- perhaps permanently, since encoders & decoders may not
|
||||
* bother to preserve DCT blocks that appear to be completely outside the
|
||||
* nominal image area. So, we have to exclude any partial iMCUs from the
|
||||
* basic transformation.
|
||||
*
|
||||
* Transpose is the only transformation that can handle partial iMCUs at the
|
||||
* right and bottom edges completely cleanly. flip_h can flip partial iMCUs
|
||||
* at the bottom, but leaves any partial iMCUs at the right edge untouched.
|
||||
* Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
|
||||
* The other transforms are defined as combinations of these basic transforms
|
||||
* and process edge blocks in a way that preserves the equivalence.
|
||||
*
|
||||
* The "trim" option causes untransformable partial iMCUs to be dropped;
|
||||
* this is not strictly lossless, but it usually gives the best-looking
|
||||
* result for odd-size images. Note that when this option is active,
|
||||
* the expected mathematical equivalences between the transforms may not hold.
|
||||
* (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
|
||||
* followed by -rot 180 -trim trims both edges.)
|
||||
*
|
||||
* We also offer a "force to grayscale" option, which simply discards the
|
||||
* chrominance channels of a YCbCr image. This is lossless in the sense that
|
||||
* the luminance channel is preserved exactly. It's not the same kind of
|
||||
* thing as the rotate/flip transformations, but it's convenient to handle it
|
||||
* as part of this package, mainly because the transformation routines have to
|
||||
* be aware of the option to know how many components to work on.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
/* Options: set by caller */
|
||||
JXFORM_CODE transform; /* image transform operator */
|
||||
boolean trim; /* if TRUE, trim partial MCUs as needed */
|
||||
boolean force_grayscale; /* if TRUE, convert color image to grayscale */
|
||||
|
||||
/* Internal workspace: caller should not touch these */
|
||||
int num_components; /* # of components in workspace */
|
||||
jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
|
||||
} jpeg_transform_info;
|
||||
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
|
||||
/* Request any required workspace */
|
||||
EXTERN(void) jtransform_request_workspace
|
||||
JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
|
||||
/* Adjust output image parameters */
|
||||
EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info));
|
||||
/* Execute the actual transformation, if any */
|
||||
EXTERN(void) jtransform_execute_transformation
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info));
|
||||
|
||||
#endif /* TRANSFORMS_SUPPORTED */
|
||||
|
||||
/*
|
||||
* Support for copying optional markers from source to destination file.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JCOPYOPT_NONE, /* copy no optional markers */
|
||||
JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */
|
||||
JCOPYOPT_ALL /* copy all optional markers */
|
||||
} JCOPY_OPTION;
|
||||
|
||||
#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */
|
||||
|
||||
/* Setup decompression object to save desired markers in memory */
|
||||
EXTERN(void) jcopy_markers_setup
|
||||
JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option));
|
||||
/* Copy markers saved in the given source object to the destination object */
|
||||
EXTERN(void) jcopy_markers_execute
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
JCOPY_OPTION option));
|
||||
|
||||
#endif
|
||||
|
|
@ -1,325 +0,0 @@
|
|||
The Independent JPEG Group's JPEG software
|
||||
==========================================
|
||||
|
||||
README for release 8 of 10-Jan-2010
|
||||
===================================
|
||||
|
||||
This distribution contains the eighth public release of the Independent JPEG
|
||||
Group's free JPEG software. You are welcome to redistribute this software and
|
||||
to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
|
||||
|
||||
This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone,
|
||||
Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson,
|
||||
Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers,
|
||||
and other members of the Independent JPEG Group.
|
||||
|
||||
IJG is not affiliated with the official ISO JPEG standards committee.
|
||||
|
||||
|
||||
DOCUMENTATION ROADMAP
|
||||
=====================
|
||||
|
||||
This file contains the following sections:
|
||||
|
||||
OVERVIEW General description of JPEG and the IJG software.
|
||||
LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
|
||||
REFERENCES Where to learn more about JPEG.
|
||||
ARCHIVE LOCATIONS Where to find newer versions of this software.
|
||||
ACKNOWLEDGMENTS Special thanks.
|
||||
FILE FORMAT WARS Software *not* to get.
|
||||
TO DO Plans for future IJG releases.
|
||||
|
||||
Other documentation files in the distribution are:
|
||||
|
||||
User documentation:
|
||||
install.txt How to configure and install the IJG software.
|
||||
usage.txt Usage instructions for cjpeg, djpeg, jpegtran,
|
||||
rdjpgcom, and wrjpgcom.
|
||||
*.1 Unix-style man pages for programs (same info as usage.txt).
|
||||
wizard.txt Advanced usage instructions for JPEG wizards only.
|
||||
change.log Version-to-version change highlights.
|
||||
Programmer and internal documentation:
|
||||
libjpeg.txt How to use the JPEG library in your own programs.
|
||||
example.c Sample code for calling the JPEG library.
|
||||
structure.txt Overview of the JPEG library's internal structure.
|
||||
filelist.txt Road map of IJG files.
|
||||
coderules.txt Coding style rules --- please read if you contribute code.
|
||||
|
||||
Please read at least the files install.txt and usage.txt. Some information
|
||||
can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
|
||||
ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
|
||||
|
||||
If you want to understand how the JPEG code works, we suggest reading one or
|
||||
more of the REFERENCES, then looking at the documentation files (in roughly
|
||||
the order listed) before diving into the code.
|
||||
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
|
||||
This package contains C software to implement JPEG image encoding, decoding,
|
||||
and transcoding. JPEG (pronounced "jay-peg") is a standardized compression
|
||||
method for full-color and gray-scale images.
|
||||
|
||||
This software implements JPEG baseline, extended-sequential, and progressive
|
||||
compression processes. Provision is made for supporting all variants of these
|
||||
processes, although some uncommon parameter settings aren't implemented yet.
|
||||
We have made no provision for supporting the hierarchical or lossless
|
||||
processes defined in the standard.
|
||||
|
||||
We provide a set of library routines for reading and writing JPEG image files,
|
||||
plus two sample applications "cjpeg" and "djpeg", which use the library to
|
||||
perform conversion between JPEG and some other popular image file formats.
|
||||
The library is intended to be reused in other applications.
|
||||
|
||||
In order to support file conversion and viewing software, we have included
|
||||
considerable functionality beyond the bare JPEG coding/decoding capability;
|
||||
for example, the color quantization modules are not strictly part of JPEG
|
||||
decoding, but they are essential for output to colormapped file formats or
|
||||
colormapped displays. These extra functions can be compiled out of the
|
||||
library if not required for a particular application.
|
||||
|
||||
We have also included "jpegtran", a utility for lossless transcoding between
|
||||
different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple
|
||||
applications for inserting and extracting textual comments in JFIF files.
|
||||
|
||||
The emphasis in designing this software has been on achieving portability and
|
||||
flexibility, while also making it fast enough to be useful. In particular,
|
||||
the software is not intended to be read as a tutorial on JPEG. (See the
|
||||
REFERENCES section for introductory material.) Rather, it is intended to
|
||||
be reliable, portable, industrial-strength code. We do not claim to have
|
||||
achieved that goal in every aspect of the software, but we strive for it.
|
||||
|
||||
We welcome the use of this software as a component of commercial products.
|
||||
No royalty is required, but we do ask for an acknowledgement in product
|
||||
documentation, as described under LEGAL ISSUES.
|
||||
|
||||
|
||||
LEGAL ISSUES
|
||||
============
|
||||
|
||||
In plain English:
|
||||
|
||||
1. We don't promise that this software works. (But if you find any bugs,
|
||||
please let us know!)
|
||||
2. You can use this software for whatever you want. You don't have to pay us.
|
||||
3. You may not pretend that you wrote this software. If you use it in a
|
||||
program, you must acknowledge somewhere in your documentation that
|
||||
you've used the IJG code.
|
||||
|
||||
In legalese:
|
||||
|
||||
The authors make NO WARRANTY or representation, either express or implied,
|
||||
with respect to this software, its quality, accuracy, merchantability, or
|
||||
fitness for a particular purpose. This software is provided "AS IS", and you,
|
||||
its user, assume the entire risk as to its quality and accuracy.
|
||||
|
||||
This software is copyright (C) 1991-2010, Thomas G. Lane, Guido Vollbeding.
|
||||
All Rights Reserved except as specified below.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute this
|
||||
software (or portions thereof) for any purpose, without fee, subject to these
|
||||
conditions:
|
||||
(1) If any part of the source code for this software is distributed, then this
|
||||
README file must be included, with this copyright and no-warranty notice
|
||||
unaltered; and any additions, deletions, or changes to the original files
|
||||
must be clearly indicated in accompanying documentation.
|
||||
(2) If only executable code is distributed, then the accompanying
|
||||
documentation must state that "this software is based in part on the work of
|
||||
the Independent JPEG Group".
|
||||
(3) Permission for use of this software is granted only if the user accepts
|
||||
full responsibility for any undesirable consequences; the authors accept
|
||||
NO LIABILITY for damages of any kind.
|
||||
|
||||
These conditions apply to any software derived from or based on the IJG code,
|
||||
not just to the unmodified library. If you use our work, you ought to
|
||||
acknowledge us.
|
||||
|
||||
Permission is NOT granted for the use of any IJG author's name or company name
|
||||
in advertising or publicity relating to this software or products derived from
|
||||
it. This software may be referred to only as "the Independent JPEG Group's
|
||||
software".
|
||||
|
||||
We specifically permit and encourage the use of this software as the basis of
|
||||
commercial products, provided that all warranty or liability claims are
|
||||
assumed by the product vendor.
|
||||
|
||||
|
||||
ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
|
||||
sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
|
||||
ansi2knr.c is NOT covered by the above copyright and conditions, but instead
|
||||
by the usual distribution terms of the Free Software Foundation; principally,
|
||||
that you must include source code if you redistribute it. (See the file
|
||||
ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
|
||||
of any program generated from the IJG code, this does not limit you more than
|
||||
the foregoing paragraphs do.
|
||||
|
||||
The Unix configuration script "configure" was produced with GNU Autoconf.
|
||||
It is copyright by the Free Software Foundation but is freely distributable.
|
||||
The same holds for its supporting scripts (config.guess, config.sub,
|
||||
ltmain.sh). Another support script, install-sh, is copyright by X Consortium
|
||||
but is also freely distributable.
|
||||
|
||||
The IJG distribution formerly included code to read and write GIF files.
|
||||
To avoid entanglement with the Unisys LZW patent, GIF reading support has
|
||||
been removed altogether, and the GIF writer has been simplified to produce
|
||||
"uncompressed GIFs". This technique does not use the LZW algorithm; the
|
||||
resulting GIF files are larger than usual, but are readable by all standard
|
||||
GIF decoders.
|
||||
|
||||
We are required to state that
|
||||
"The Graphics Interchange Format(c) is the Copyright property of
|
||||
CompuServe Incorporated. GIF(sm) is a Service Mark property of
|
||||
CompuServe Incorporated."
|
||||
|
||||
|
||||
REFERENCES
|
||||
==========
|
||||
|
||||
We recommend reading one or more of these references before trying to
|
||||
understand the innards of the JPEG software.
|
||||
|
||||
The best short technical introduction to the JPEG compression algorithm is
|
||||
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
||||
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
|
||||
(Adjacent articles in that issue discuss MPEG motion picture compression,
|
||||
applications of JPEG, and related topics.) If you don't have the CACM issue
|
||||
handy, a PostScript file containing a revised version of Wallace's article is
|
||||
available at http://www.ijg.org/files/wallace.ps.gz. The file (actually
|
||||
a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
|
||||
omits the sample images that appeared in CACM, but it includes corrections
|
||||
and some added material. Note: the Wallace article is copyright ACM and IEEE,
|
||||
and it may not be used for commercial purposes.
|
||||
|
||||
A somewhat less technical, more leisurely introduction to JPEG can be found in
|
||||
"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
|
||||
M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides
|
||||
good explanations and example C code for a multitude of compression methods
|
||||
including JPEG. It is an excellent source if you are comfortable reading C
|
||||
code but don't know much about data compression in general. The book's JPEG
|
||||
sample code is far from industrial-strength, but when you are ready to look
|
||||
at a full implementation, you've got one here...
|
||||
|
||||
The best currently available description of JPEG is the textbook "JPEG Still
|
||||
Image Data Compression Standard" by William B. Pennebaker and Joan L.
|
||||
Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1.
|
||||
Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG
|
||||
standards (DIS 10918-1 and draft DIS 10918-2).
|
||||
Although this is by far the most detailed and comprehensive exposition of
|
||||
JPEG publicly available, we point out that it is still missing an explanation
|
||||
of the most essential properties and algorithms of the underlying DCT
|
||||
technology.
|
||||
If you think that you know about DCT-based JPEG after reading this book,
|
||||
then you are in delusion. The real fundamentals and corresponding potential
|
||||
of DCT-based JPEG are not publicly known so far, and that is the reason for
|
||||
all the mistaken developments taking place in the image coding domain.
|
||||
|
||||
The original JPEG standard is divided into two parts, Part 1 being the actual
|
||||
specification, while Part 2 covers compliance testing methods. Part 1 is
|
||||
titled "Digital Compression and Coding of Continuous-tone Still Images,
|
||||
Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
|
||||
10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
|
||||
Continuous-tone Still Images, Part 2: Compliance testing" and has document
|
||||
numbers ISO/IEC IS 10918-2, ITU-T T.83.
|
||||
IJG JPEG 8 introduces an implementation of the JPEG SmartScale extension
|
||||
which is specified in a contributed document at ITU and ISO with title "ITU-T
|
||||
JPEG-Plus Proposal for Extending ITU-T T.81 for Advanced Image Coding", April
|
||||
2006, Geneva, Switzerland. The latest version of the document is Revision 3.
|
||||
|
||||
The JPEG standard does not specify all details of an interchangeable file
|
||||
format. For the omitted details we follow the "JFIF" conventions, revision
|
||||
1.02. JFIF 1.02 has been adopted as an Ecma International Technical Report
|
||||
and thus received a formal publication status. It is available as a free
|
||||
download in PDF format from
|
||||
http://www.ecma-international.org/publications/techreports/E-TR-098.htm.
|
||||
A PostScript version of the JFIF document is available at
|
||||
http://www.ijg.org/files/jfif.ps.gz. There is also a plain text version at
|
||||
http://www.ijg.org/files/jfif.txt.gz, but it is missing the figures.
|
||||
|
||||
The TIFF 6.0 file format specification can be obtained by FTP from
|
||||
ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
|
||||
found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
|
||||
IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
|
||||
Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
|
||||
(Compression tag 7). Copies of this Note can be obtained from
|
||||
http://www.ijg.org/files/. It is expected that the next revision
|
||||
of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
|
||||
Although IJG's own code does not support TIFF/JPEG, the free libtiff library
|
||||
uses our library to implement TIFF/JPEG per the Note.
|
||||
|
||||
|
||||
ARCHIVE LOCATIONS
|
||||
=================
|
||||
|
||||
The "official" archive site for this software is www.ijg.org.
|
||||
The most recent released version can always be found there in
|
||||
directory "files". This particular version will be archived as
|
||||
http://www.ijg.org/files/jpegsrc.v8.tar.gz, and in Windows-compatible
|
||||
"zip" archive format as http://www.ijg.org/files/jpegsr8.zip.
|
||||
|
||||
The JPEG FAQ (Frequently Asked Questions) article is a source of some
|
||||
general information about JPEG.
|
||||
It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
|
||||
and other news.answers archive sites, including the official news.answers
|
||||
archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
|
||||
If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
|
||||
with body
|
||||
send usenet/news.answers/jpeg-faq/part1
|
||||
send usenet/news.answers/jpeg-faq/part2
|
||||
|
||||
|
||||
ACKNOWLEDGMENTS
|
||||
===============
|
||||
|
||||
Thank to Juergen Bruder for providing me with a copy of the common DCT
|
||||
algorithm article, only to find out that I had come to the same result
|
||||
in a more direct and comprehensible way with a more generative approach.
|
||||
|
||||
Thank to Istvan Sebestyen and Joan L. Mitchell for inviting me to the
|
||||
ITU JPEG (Study Group 16) meeting in Geneva, Switzerland.
|
||||
|
||||
Thank to Thomas Wiegand and Gary Sullivan for inviting me to the
|
||||
Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland.
|
||||
|
||||
Thank to John Korejwa and Massimo Ballerini for inviting me to
|
||||
fruitful consultations in Boston, MA and Milan, Italy.
|
||||
|
||||
Thank to Hendrik Elstner, Roland Fassauer, Simone Zuck, Guenther
|
||||
Maier-Gerber, and Walter Stoeber for corresponding business development.
|
||||
|
||||
Thank to Nico Zschach and Dirk Stelling of the technical support team
|
||||
at the Digital Images company in Halle for providing me with extra
|
||||
equipment for configuration tests.
|
||||
|
||||
Thank to Richard F. Lyon (then of Foveon Inc.) for fruitful
|
||||
communication about JPEG configuration in Sigma Photo Pro software.
|
||||
|
||||
Thank to Andrew Finkenstadt for hosting the ijg.org site.
|
||||
|
||||
Last but not least special thank to Thomas G. Lane for the original
|
||||
design and development of this singular software package.
|
||||
|
||||
|
||||
FILE FORMAT WARS
|
||||
================
|
||||
|
||||
The ISO JPEG standards committee actually promotes different formats like
|
||||
"JPEG 2000" or "JPEG XR" which are incompatible with original DCT-based
|
||||
JPEG and which are based on faulty technologies. IJG therefore does not
|
||||
and will not support such momentary mistakes (see REFERENCES).
|
||||
We have little or no sympathy for the promotion of these formats. Indeed,
|
||||
one of the original reasons for developing this free software was to help
|
||||
force convergence on common, interoperable format standards for JPEG files.
|
||||
Don't use an incompatible file format!
|
||||
(In any case, our decoder will remain capable of reading existing JPEG
|
||||
image files indefinitely.)
|
||||
|
||||
|
||||
TO DO
|
||||
=====
|
||||
|
||||
Version 8.0 is the first release of a new generation JPEG standard
|
||||
to overcome the limitations of the original JPEG specification.
|
||||
More features are being prepared for coming releases...
|
||||
|
||||
Please send bug reports, offers of help, etc. to jpeg-info@uc.ag.
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* jinclude.h
|
||||
*
|
||||
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file exists to provide a single place to fix any problems with
|
||||
* including the wrong system include files. (Common problems are taken
|
||||
* care of by the standard jconfig symbols, but on really weird systems
|
||||
* you may have to edit this file.)
|
||||
*
|
||||
* NOTE: this file is NOT intended to be included by applications using the
|
||||
* JPEG library. Most applications need only include jpeglib.h.
|
||||
*/
|
||||
|
||||
/* Include auto-config file to find out which system include files we need. */
|
||||
|
||||
#include "jconfig.h" /* auto configuration options */
|
||||
#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
|
||||
|
||||
/*
|
||||
* We need the NULL macro and size_t typedef.
|
||||
* On an ANSI-conforming system it is sufficient to include <stddef.h>.
|
||||
* Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
|
||||
* pull in <sys/types.h> as well.
|
||||
* Note that the core JPEG library does not require <stdio.h>;
|
||||
* only the default error handler and data source/destination modules do.
|
||||
* But we must pull it in because of the references to FILE in jpeglib.h.
|
||||
* You can remove those references if you want to compile without <stdio.h>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef NEED_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* We need memory copying and zeroing functions, plus strncpy().
|
||||
* ANSI and System V implementations declare these in <string.h>.
|
||||
* BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
|
||||
* Some systems may declare memset and memcpy in <memory.h>.
|
||||
*
|
||||
* NOTE: we assume the size parameters to these functions are of type size_t.
|
||||
* Change the casts in these macros if not!
|
||||
*/
|
||||
|
||||
#ifdef NEED_BSD_STRINGS
|
||||
|
||||
#include <strings.h>
|
||||
#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
|
||||
#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
|
||||
|
||||
#else /* not BSD, assume ANSI/SysV string lib */
|
||||
|
||||
#include <string.h>
|
||||
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
|
||||
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In ANSI C, and indeed any rational implementation, size_t is also the
|
||||
* type returned by sizeof(). However, it seems there are some irrational
|
||||
* implementations out there, in which sizeof() returns an int even though
|
||||
* size_t is defined as long or unsigned long. To ensure consistent results
|
||||
* we always use this SIZEOF() macro in place of using sizeof() directly.
|
||||
*/
|
||||
|
||||
#define SIZEOF(object) ((size_t) sizeof(object))
|
||||
|
||||
/*
|
||||
* The modules that use fread() and fwrite() always invoke them through
|
||||
* these macros. On some systems you may need to twiddle the argument casts.
|
||||
* CAUTION: argument order is different from underlying functions!
|
||||
*/
|
||||
|
||||
#define JFREAD(file,buf,sizeofbuf) \
|
||||
((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||
#define JFWRITE(file,buf,sizeofbuf) \
|
||||
((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
|
@ -1,404 +0,0 @@
|
|||
/*
|
||||
* jpegint.h
|
||||
*
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file provides common declarations for the various JPEG modules.
|
||||
* These declarations are considered internal to the JPEG library; most
|
||||
* applications using the library shouldn't need to include this file.
|
||||
*/
|
||||
|
||||
/* Declarations for both compression & decompression */
|
||||
|
||||
typedef enum { /* Operating modes for buffer controllers */
|
||||
JBUF_PASS_THRU, /* Plain stripwise operation */
|
||||
/* Remaining modes require a full-image buffer to have been created */
|
||||
JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
|
||||
JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
|
||||
JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
|
||||
} J_BUF_MODE;
|
||||
|
||||
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
|
||||
#define CSTATE_START 100 /* after create_compress */
|
||||
#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
|
||||
#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
|
||||
#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
|
||||
#define DSTATE_START 200 /* after create_decompress */
|
||||
#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
|
||||
#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
|
||||
#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
|
||||
#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
|
||||
#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
|
||||
#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
|
||||
#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
|
||||
#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
|
||||
#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
|
||||
#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
|
||||
|
||||
/* Declarations for compression modules */
|
||||
|
||||
/* Master control module */
|
||||
struct jpeg_comp_master {
|
||||
JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean call_pass_startup; /* True if pass_startup must be called */
|
||||
boolean is_last_pass; /* True during last pass */
|
||||
};
|
||||
|
||||
/* Main buffer control (downsampled-data buffer) */
|
||||
struct jpeg_c_main_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, process_data, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
|
||||
JDIMENSION in_rows_avail));
|
||||
};
|
||||
|
||||
/* Compression preprocessing (downsampling input buffer control) */
|
||||
struct jpeg_c_prep_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf,
|
||||
JDIMENSION *in_row_ctr,
|
||||
JDIMENSION in_rows_avail,
|
||||
JSAMPIMAGE output_buf,
|
||||
JDIMENSION *out_row_group_ctr,
|
||||
JDIMENSION out_row_groups_avail));
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
struct jpeg_c_coef_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf));
|
||||
};
|
||||
|
||||
/* Colorspace conversion */
|
||||
struct jpeg_color_converter {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, color_convert, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||
JDIMENSION output_row, int num_rows));
|
||||
};
|
||||
|
||||
/* Downsampling */
|
||||
struct jpeg_downsampler {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, downsample, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION in_row_index,
|
||||
JSAMPIMAGE output_buf,
|
||||
JDIMENSION out_row_group_index));
|
||||
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Forward DCT (also controls coefficient quantization) */
|
||||
typedef JMETHOD(void, forward_DCT_ptr,
|
||||
(j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||
JDIMENSION start_row, JDIMENSION start_col,
|
||||
JDIMENSION num_blocks));
|
||||
|
||||
struct jpeg_forward_dct {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
/* It is useful to allow each component to have a separate FDCT method. */
|
||||
forward_DCT_ptr forward_DCT[MAX_COMPONENTS];
|
||||
};
|
||||
|
||||
/* Entropy encoding */
|
||||
struct jpeg_entropy_encoder {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
|
||||
JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
|
||||
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
|
||||
};
|
||||
|
||||
/* Marker writing */
|
||||
struct jpeg_marker_writer {
|
||||
JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
|
||||
/* These routines are exported to allow insertion of extra markers */
|
||||
/* Probably only COM and APPn markers should be written this way */
|
||||
JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker,
|
||||
unsigned int datalen));
|
||||
JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val));
|
||||
};
|
||||
|
||||
/* Declarations for decompression modules */
|
||||
|
||||
/* Master control module */
|
||||
struct jpeg_decomp_master {
|
||||
JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
|
||||
};
|
||||
|
||||
/* Input control module */
|
||||
struct jpeg_input_controller {
|
||||
JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean has_multiple_scans; /* True if file has multiple scans */
|
||||
boolean eoi_reached; /* True when EOI has been consumed */
|
||||
};
|
||||
|
||||
/* Main buffer control (downsampled-data buffer) */
|
||||
struct jpeg_d_main_controller {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, process_data, (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
struct jpeg_d_coef_controller {
|
||||
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE output_buf));
|
||||
/* Pointer to array of coefficient virtual arrays, or NULL if none */
|
||||
jvirt_barray_ptr *coef_arrays;
|
||||
};
|
||||
|
||||
/* Decompression postprocessing (color quantization buffer control) */
|
||||
struct jpeg_d_post_controller {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf,
|
||||
JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
};
|
||||
|
||||
/* Marker reading & parsing */
|
||||
struct jpeg_marker_reader {
|
||||
JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
|
||||
/* Read markers until SOS or EOI.
|
||||
* Returns same codes as are defined for jpeg_consume_input:
|
||||
* JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||
*/
|
||||
JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
|
||||
/* Read a restart marker --- exported for use by entropy decoder only */
|
||||
jpeg_marker_parser_method read_restart_marker;
|
||||
|
||||
/* State of marker reader --- nominally internal, but applications
|
||||
* supplying COM or APPn handlers might like to know the state.
|
||||
*/
|
||||
boolean saw_SOI; /* found SOI? */
|
||||
boolean saw_SOF; /* found SOF? */
|
||||
int next_restart_num; /* next restart number expected (0-7) */
|
||||
unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
|
||||
};
|
||||
|
||||
/* Entropy decoding */
|
||||
struct jpeg_entropy_decoder {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
|
||||
JBLOCKROW *MCU_data));
|
||||
};
|
||||
|
||||
/* Inverse DCT (also performs dequantization) */
|
||||
typedef JMETHOD(void, inverse_DCT_method_ptr,
|
||||
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block,
|
||||
JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
|
||||
struct jpeg_inverse_dct {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
/* It is useful to allow each component to have a separate IDCT method. */
|
||||
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
|
||||
};
|
||||
|
||||
/* Upsampling (note that upsampler must also call color converter) */
|
||||
struct jpeg_upsampler {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, upsample, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf,
|
||||
JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Colorspace conversion */
|
||||
struct jpeg_color_deconverter {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||
JSAMPARRAY output_buf, int num_rows));
|
||||
};
|
||||
|
||||
/* Color quantization or color precision reduction */
|
||||
struct jpeg_color_quantizer {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
|
||||
JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JSAMPARRAY output_buf,
|
||||
int num_rows));
|
||||
JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
|
||||
};
|
||||
|
||||
/* Miscellaneous useful macros */
|
||||
|
||||
#undef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#undef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
/* We assume that right shift corresponds to signed division by 2 with
|
||||
* rounding towards minus infinity. This is correct for typical "arithmetic
|
||||
* shift" instructions that shift in copies of the sign bit. But some
|
||||
* C compilers implement >> with an unsigned shift. For these machines you
|
||||
* must define RIGHT_SHIFT_IS_UNSIGNED.
|
||||
* RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
|
||||
* It is only applied with constant shift counts. SHIFT_TEMPS must be
|
||||
* included in the variables of any routine using RIGHT_SHIFT.
|
||||
*/
|
||||
|
||||
#ifdef RIGHT_SHIFT_IS_UNSIGNED
|
||||
#define SHIFT_TEMPS INT32 shift_temp;
|
||||
#define RIGHT_SHIFT(x,shft) \
|
||||
((shift_temp = (x)) < 0 ? \
|
||||
(shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
|
||||
(shift_temp >> (shft)))
|
||||
#else
|
||||
#define SHIFT_TEMPS
|
||||
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
|
||||
#endif
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jinit_compress_master jICompress
|
||||
#define jinit_c_master_control jICMaster
|
||||
#define jinit_c_main_controller jICMainC
|
||||
#define jinit_c_prep_controller jICPrepC
|
||||
#define jinit_c_coef_controller jICCoefC
|
||||
#define jinit_color_converter jICColor
|
||||
#define jinit_downsampler jIDownsampler
|
||||
#define jinit_forward_dct jIFDCT
|
||||
#define jinit_huff_encoder jIHEncoder
|
||||
#define jinit_arith_encoder jIAEncoder
|
||||
#define jinit_marker_writer jIMWriter
|
||||
#define jinit_master_decompress jIDMaster
|
||||
#define jinit_d_main_controller jIDMainC
|
||||
#define jinit_d_coef_controller jIDCoefC
|
||||
#define jinit_d_post_controller jIDPostC
|
||||
#define jinit_input_controller jIInCtlr
|
||||
#define jinit_marker_reader jIMReader
|
||||
#define jinit_huff_decoder jIHDecoder
|
||||
#define jinit_arith_decoder jIADecoder
|
||||
#define jinit_inverse_dct jIIDCT
|
||||
#define jinit_upsampler jIUpsampler
|
||||
#define jinit_color_deconverter jIDColor
|
||||
#define jinit_1pass_quantizer jI1Quant
|
||||
#define jinit_2pass_quantizer jI2Quant
|
||||
#define jinit_merged_upsampler jIMUpsampler
|
||||
#define jinit_memory_mgr jIMemMgr
|
||||
#define jdiv_round_up jDivRound
|
||||
#define jround_up jRound
|
||||
#define jcopy_sample_rows jCopySamples
|
||||
#define jcopy_block_row jCopyBlocks
|
||||
#define jzero_far jZeroFar
|
||||
#define jpeg_zigzag_order jZIGTable
|
||||
#define jpeg_natural_order jZAGTable
|
||||
#define jpeg_natural_order7 jZAGTable7
|
||||
#define jpeg_natural_order6 jZAGTable6
|
||||
#define jpeg_natural_order5 jZAGTable5
|
||||
#define jpeg_natural_order4 jZAGTable4
|
||||
#define jpeg_natural_order3 jZAGTable3
|
||||
#define jpeg_natural_order2 jZAGTable2
|
||||
#define jpeg_aritab jAriTab
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
/* Compression module initialization routines */
|
||||
EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
|
||||
boolean transcode_only));
|
||||
EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
|
||||
/* Decompression module initialization routines */
|
||||
EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
|
||||
/* Memory manager initialization */
|
||||
EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
|
||||
|
||||
/* Utility routines in jutils.c */
|
||||
EXTERN(long) jdiv_round_up JPP((long a, long b));
|
||||
EXTERN(long) jround_up JPP((long a, long b));
|
||||
EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
|
||||
JSAMPARRAY output_array, int dest_row,
|
||||
int num_rows, JDIMENSION num_cols));
|
||||
EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
|
||||
JDIMENSION num_blocks));
|
||||
EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero));
|
||||
/* Constant tables in jutils.c */
|
||||
#if 0 /* This table is not actually needed in v6a */
|
||||
extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
|
||||
#endif
|
||||
extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
|
||||
extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */
|
||||
extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */
|
||||
extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */
|
||||
extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */
|
||||
extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */
|
||||
extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */
|
||||
|
||||
/* Arithmetic coding probability estimation tables in jaricom.c */
|
||||
extern const INT32 jpeg_aritab[];
|
||||
|
||||
/* Suppress undefined-structure complaints if necessary. */
|
||||
|
||||
#ifdef INCOMPLETE_TYPES_BROKEN
|
||||
#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */
|
||||
struct jvirt_sarray_control {
|
||||
long dummy;
|
||||
};
|
||||
struct jvirt_barray_control {
|
||||
long dummy;
|
||||
};
|
||||
#endif
|
||||
#endif /* INCOMPLETE_TYPES_BROKEN */
|
File diff suppressed because it is too large
Load diff
|
@ -1,206 +0,0 @@
|
|||
/*
|
||||
* transupp.h
|
||||
*
|
||||
* Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains declarations for image transformation routines and
|
||||
* other utility code used by the jpegtran sample application. These are
|
||||
* NOT part of the core JPEG library. But we keep these routines separate
|
||||
* from jpegtran.c to ease the task of maintaining jpegtran-like programs
|
||||
* that have other user interfaces.
|
||||
*
|
||||
* NOTE: all the routines declared here have very specific requirements
|
||||
* about when they are to be executed during the reading and writing of the
|
||||
* source and destination files. See the comments in transupp.c, or see
|
||||
* jpegtran.c for an example of correct usage.
|
||||
*/
|
||||
|
||||
/* If you happen not to want the image transform support, disable it here */
|
||||
#ifndef TRANSFORMS_SUPPORTED
|
||||
#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Although rotating and flipping data expressed as DCT coefficients is not
|
||||
* hard, there is an asymmetry in the JPEG format specification for images
|
||||
* whose dimensions aren't multiples of the iMCU size. The right and bottom
|
||||
* image edges are padded out to the next iMCU boundary with junk data; but
|
||||
* no padding is possible at the top and left edges. If we were to flip
|
||||
* the whole image including the pad data, then pad garbage would become
|
||||
* visible at the top and/or left, and real pixels would disappear into the
|
||||
* pad margins --- perhaps permanently, since encoders & decoders may not
|
||||
* bother to preserve DCT blocks that appear to be completely outside the
|
||||
* nominal image area. So, we have to exclude any partial iMCUs from the
|
||||
* basic transformation.
|
||||
*
|
||||
* Transpose is the only transformation that can handle partial iMCUs at the
|
||||
* right and bottom edges completely cleanly. flip_h can flip partial iMCUs
|
||||
* at the bottom, but leaves any partial iMCUs at the right edge untouched.
|
||||
* Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
|
||||
* The other transforms are defined as combinations of these basic transforms
|
||||
* and process edge blocks in a way that preserves the equivalence.
|
||||
*
|
||||
* The "trim" option causes untransformable partial iMCUs to be dropped;
|
||||
* this is not strictly lossless, but it usually gives the best-looking
|
||||
* result for odd-size images. Note that when this option is active,
|
||||
* the expected mathematical equivalences between the transforms may not hold.
|
||||
* (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
|
||||
* followed by -rot 180 -trim trims both edges.)
|
||||
*
|
||||
* We also offer a lossless-crop option, which discards data outside a given
|
||||
* image region but losslessly preserves what is inside. Like the rotate and
|
||||
* flip transforms, lossless crop is restricted by the JPEG format: the upper
|
||||
* left corner of the selected region must fall on an iMCU boundary. If this
|
||||
* does not hold for the given crop parameters, we silently move the upper left
|
||||
* corner up and/or left to make it so, simultaneously increasing the region
|
||||
* dimensions to keep the lower right crop corner unchanged. (Thus, the
|
||||
* output image covers at least the requested region, but may cover more.)
|
||||
*
|
||||
* We also provide a lossless-resize option, which is kind of a lossless-crop
|
||||
* operation in the DCT coefficient block domain - it discards higher-order
|
||||
* coefficients and losslessly preserves lower-order coefficients of a
|
||||
* sub-block.
|
||||
*
|
||||
* Rotate/flip transform, resize, and crop can be requested together in a
|
||||
* single invocation. The crop is applied last --- that is, the crop region
|
||||
* is specified in terms of the destination image after transform/resize.
|
||||
*
|
||||
* We also offer a "force to grayscale" option, which simply discards the
|
||||
* chrominance channels of a YCbCr image. This is lossless in the sense that
|
||||
* the luminance channel is preserved exactly. It's not the same kind of
|
||||
* thing as the rotate/flip transformations, but it's convenient to handle it
|
||||
* as part of this package, mainly because the transformation routines have to
|
||||
* be aware of the option to know how many components to work on.
|
||||
*/
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jtransform_parse_crop_spec jTrParCrop
|
||||
#define jtransform_request_workspace jTrRequest
|
||||
#define jtransform_adjust_parameters jTrAdjust
|
||||
#define jtransform_execute_transform jTrExec
|
||||
#define jtransform_perfect_transform jTrPerfect
|
||||
#define jcopy_markers_setup jCMrkSetup
|
||||
#define jcopy_markers_execute jCMrkExec
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
/*
|
||||
* Codes for supported types of image transformations.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JXFORM_NONE, /* no transformation */
|
||||
JXFORM_FLIP_H, /* horizontal flip */
|
||||
JXFORM_FLIP_V, /* vertical flip */
|
||||
JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
|
||||
JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
|
||||
JXFORM_ROT_90, /* 90-degree clockwise rotation */
|
||||
JXFORM_ROT_180, /* 180-degree rotation */
|
||||
JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
|
||||
} JXFORM_CODE;
|
||||
|
||||
/*
|
||||
* Codes for crop parameters, which can individually be unspecified,
|
||||
* positive, or negative. (Negative width or height makes no sense, though.)
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JCROP_UNSET,
|
||||
JCROP_POS,
|
||||
JCROP_NEG
|
||||
} JCROP_CODE;
|
||||
|
||||
/*
|
||||
* Transform parameters struct.
|
||||
* NB: application must not change any elements of this struct after
|
||||
* calling jtransform_request_workspace.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
/* Options: set by caller */
|
||||
JXFORM_CODE transform; /* image transform operator */
|
||||
boolean perfect; /* if TRUE, fail if partial MCUs are requested */
|
||||
boolean trim; /* if TRUE, trim partial MCUs as needed */
|
||||
boolean force_grayscale; /* if TRUE, convert color image to grayscale */
|
||||
boolean crop; /* if TRUE, crop source image */
|
||||
|
||||
/* Crop parameters: application need not set these unless crop is TRUE.
|
||||
* These can be filled in by jtransform_parse_crop_spec().
|
||||
*/
|
||||
JDIMENSION crop_width; /* Width of selected region */
|
||||
JCROP_CODE crop_width_set;
|
||||
JDIMENSION crop_height; /* Height of selected region */
|
||||
JCROP_CODE crop_height_set;
|
||||
JDIMENSION crop_xoffset; /* X offset of selected region */
|
||||
JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */
|
||||
JDIMENSION crop_yoffset; /* Y offset of selected region */
|
||||
JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */
|
||||
|
||||
/* Internal workspace: caller should not touch these */
|
||||
int num_components; /* # of components in workspace */
|
||||
jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
|
||||
JDIMENSION output_width; /* cropped destination dimensions */
|
||||
JDIMENSION output_height;
|
||||
JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */
|
||||
JDIMENSION y_crop_offset;
|
||||
int iMCU_sample_width; /* destination iMCU size */
|
||||
int iMCU_sample_height;
|
||||
} jpeg_transform_info;
|
||||
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
|
||||
/* Parse a crop specification (written in X11 geometry style) */
|
||||
EXTERN(boolean) jtransform_parse_crop_spec
|
||||
JPP((jpeg_transform_info *info, const char *spec));
|
||||
/* Request any required workspace */
|
||||
EXTERN(boolean) jtransform_request_workspace
|
||||
JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
|
||||
/* Adjust output image parameters */
|
||||
EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info));
|
||||
/* Execute the actual transformation, if any */
|
||||
EXTERN(void) jtransform_execute_transform
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info));
|
||||
/* Determine whether lossless transformation is perfectly
|
||||
* possible for a specified image and transformation.
|
||||
*/
|
||||
EXTERN(boolean) jtransform_perfect_transform
|
||||
JPP((JDIMENSION image_width, JDIMENSION image_height,
|
||||
int MCU_width, int MCU_height,
|
||||
JXFORM_CODE transform));
|
||||
|
||||
/* jtransform_execute_transform used to be called
|
||||
* jtransform_execute_transformation, but some compilers complain about
|
||||
* routine names that long. This macro is here to avoid breaking any
|
||||
* old source code that uses the original name...
|
||||
*/
|
||||
#define jtransform_execute_transformation jtransform_execute_transform
|
||||
|
||||
#endif /* TRANSFORMS_SUPPORTED */
|
||||
|
||||
/*
|
||||
* Support for copying optional markers from source to destination file.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JCOPYOPT_NONE, /* copy no optional markers */
|
||||
JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */
|
||||
JCOPYOPT_ALL /* copy all optional markers */
|
||||
} JCOPY_OPTION;
|
||||
|
||||
#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */
|
||||
|
||||
/* Setup decompression object to save desired markers in memory */
|
||||
EXTERN(void) jcopy_markers_setup
|
||||
JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option));
|
||||
/* Copy markers saved in the given source object to the destination object */
|
||||
EXTERN(void) jcopy_markers_execute
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
JCOPY_OPTION option));
|
|
@ -1,381 +0,0 @@
|
|||
The Independent JPEG Group's JPEG software
|
||||
==========================================
|
||||
|
||||
README for release 9a of 19-Jan-2014
|
||||
====================================
|
||||
|
||||
This distribution contains the ninth public release of the Independent JPEG
|
||||
Group's free JPEG software. You are welcome to redistribute this software and
|
||||
to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
|
||||
|
||||
This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone,
|
||||
Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson,
|
||||
Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers,
|
||||
and other members of the Independent JPEG Group.
|
||||
|
||||
IJG is not affiliated with the ISO/IEC JTC1/SC29/WG1 standards committee
|
||||
(previously known as JPEG, together with ITU-T SG16).
|
||||
|
||||
|
||||
DOCUMENTATION ROADMAP
|
||||
=====================
|
||||
|
||||
This file contains the following sections:
|
||||
|
||||
OVERVIEW General description of JPEG and the IJG software.
|
||||
LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
|
||||
REFERENCES Where to learn more about JPEG.
|
||||
ARCHIVE LOCATIONS Where to find newer versions of this software.
|
||||
ACKNOWLEDGMENTS Special thanks.
|
||||
FILE FORMAT WARS Software *not* to get.
|
||||
TO DO Plans for future IJG releases.
|
||||
|
||||
Other documentation files in the distribution are:
|
||||
|
||||
User documentation:
|
||||
install.txt How to configure and install the IJG software.
|
||||
usage.txt Usage instructions for cjpeg, djpeg, jpegtran,
|
||||
rdjpgcom, and wrjpgcom.
|
||||
*.1 Unix-style man pages for programs (same info as usage.txt).
|
||||
wizard.txt Advanced usage instructions for JPEG wizards only.
|
||||
change.log Version-to-version change highlights.
|
||||
Programmer and internal documentation:
|
||||
libjpeg.txt How to use the JPEG library in your own programs.
|
||||
example.c Sample code for calling the JPEG library.
|
||||
structure.txt Overview of the JPEG library's internal structure.
|
||||
filelist.txt Road map of IJG files.
|
||||
coderules.txt Coding style rules --- please read if you contribute code.
|
||||
|
||||
Please read at least the files install.txt and usage.txt. Some information
|
||||
can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
|
||||
ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
|
||||
|
||||
If you want to understand how the JPEG code works, we suggest reading one or
|
||||
more of the REFERENCES, then looking at the documentation files (in roughly
|
||||
the order listed) before diving into the code.
|
||||
|
||||
|
||||
OVERVIEW
|
||||
========
|
||||
|
||||
This package contains C software to implement JPEG image encoding, decoding,
|
||||
and transcoding. JPEG (pronounced "jay-peg") is a standardized compression
|
||||
method for full-color and gray-scale images.
|
||||
|
||||
This software implements JPEG baseline, extended-sequential, and progressive
|
||||
compression processes. Provision is made for supporting all variants of these
|
||||
processes, although some uncommon parameter settings aren't implemented yet.
|
||||
We have made no provision for supporting the hierarchical or lossless
|
||||
processes defined in the standard.
|
||||
|
||||
We provide a set of library routines for reading and writing JPEG image files,
|
||||
plus two sample applications "cjpeg" and "djpeg", which use the library to
|
||||
perform conversion between JPEG and some other popular image file formats.
|
||||
The library is intended to be reused in other applications.
|
||||
|
||||
In order to support file conversion and viewing software, we have included
|
||||
considerable functionality beyond the bare JPEG coding/decoding capability;
|
||||
for example, the color quantization modules are not strictly part of JPEG
|
||||
decoding, but they are essential for output to colormapped file formats or
|
||||
colormapped displays. These extra functions can be compiled out of the
|
||||
library if not required for a particular application.
|
||||
|
||||
We have also included "jpegtran", a utility for lossless transcoding between
|
||||
different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple
|
||||
applications for inserting and extracting textual comments in JFIF files.
|
||||
|
||||
The emphasis in designing this software has been on achieving portability and
|
||||
flexibility, while also making it fast enough to be useful. In particular,
|
||||
the software is not intended to be read as a tutorial on JPEG. (See the
|
||||
REFERENCES section for introductory material.) Rather, it is intended to
|
||||
be reliable, portable, industrial-strength code. We do not claim to have
|
||||
achieved that goal in every aspect of the software, but we strive for it.
|
||||
|
||||
We welcome the use of this software as a component of commercial products.
|
||||
No royalty is required, but we do ask for an acknowledgement in product
|
||||
documentation, as described under LEGAL ISSUES.
|
||||
|
||||
|
||||
LEGAL ISSUES
|
||||
============
|
||||
|
||||
In plain English:
|
||||
|
||||
1. We don't promise that this software works. (But if you find any bugs,
|
||||
please let us know!)
|
||||
2. You can use this software for whatever you want. You don't have to pay us.
|
||||
3. You may not pretend that you wrote this software. If you use it in a
|
||||
program, you must acknowledge somewhere in your documentation that
|
||||
you've used the IJG code.
|
||||
|
||||
In legalese:
|
||||
|
||||
The authors make NO WARRANTY or representation, either express or implied,
|
||||
with respect to this software, its quality, accuracy, merchantability, or
|
||||
fitness for a particular purpose. This software is provided "AS IS", and you,
|
||||
its user, assume the entire risk as to its quality and accuracy.
|
||||
|
||||
This software is copyright (C) 1991-2014, Thomas G. Lane, Guido Vollbeding.
|
||||
All Rights Reserved except as specified below.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute this
|
||||
software (or portions thereof) for any purpose, without fee, subject to these
|
||||
conditions:
|
||||
(1) If any part of the source code for this software is distributed, then this
|
||||
README file must be included, with this copyright and no-warranty notice
|
||||
unaltered; and any additions, deletions, or changes to the original files
|
||||
must be clearly indicated in accompanying documentation.
|
||||
(2) If only executable code is distributed, then the accompanying
|
||||
documentation must state that "this software is based in part on the work of
|
||||
the Independent JPEG Group".
|
||||
(3) Permission for use of this software is granted only if the user accepts
|
||||
full responsibility for any undesirable consequences; the authors accept
|
||||
NO LIABILITY for damages of any kind.
|
||||
|
||||
These conditions apply to any software derived from or based on the IJG code,
|
||||
not just to the unmodified library. If you use our work, you ought to
|
||||
acknowledge us.
|
||||
|
||||
Permission is NOT granted for the use of any IJG author's name or company name
|
||||
in advertising or publicity relating to this software or products derived from
|
||||
it. This software may be referred to only as "the Independent JPEG Group's
|
||||
software".
|
||||
|
||||
We specifically permit and encourage the use of this software as the basis of
|
||||
commercial products, provided that all warranty or liability claims are
|
||||
assumed by the product vendor.
|
||||
|
||||
|
||||
The Unix configuration script "configure" was produced with GNU Autoconf.
|
||||
It is copyright by the Free Software Foundation but is freely distributable.
|
||||
The same holds for its supporting scripts (config.guess, config.sub,
|
||||
ltmain.sh). Another support script, install-sh, is copyright by X Consortium
|
||||
but is also freely distributable.
|
||||
|
||||
The IJG distribution formerly included code to read and write GIF files.
|
||||
To avoid entanglement with the Unisys LZW patent (now expired), GIF reading
|
||||
support has been removed altogether, and the GIF writer has been simplified
|
||||
to produce "uncompressed GIFs". This technique does not use the LZW
|
||||
algorithm; the resulting GIF files are larger than usual, but are readable
|
||||
by all standard GIF decoders.
|
||||
|
||||
We are required to state that
|
||||
"The Graphics Interchange Format(c) is the Copyright property of
|
||||
CompuServe Incorporated. GIF(sm) is a Service Mark property of
|
||||
CompuServe Incorporated."
|
||||
|
||||
|
||||
REFERENCES
|
||||
==========
|
||||
|
||||
We recommend reading one or more of these references before trying to
|
||||
understand the innards of the JPEG software.
|
||||
|
||||
The best short technical introduction to the JPEG compression algorithm is
|
||||
Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
|
||||
Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
|
||||
(Adjacent articles in that issue discuss MPEG motion picture compression,
|
||||
applications of JPEG, and related topics.) If you don't have the CACM issue
|
||||
handy, a PostScript file containing a revised version of Wallace's article is
|
||||
available at http://www.ijg.org/files/wallace.ps.gz. The file (actually
|
||||
a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
|
||||
omits the sample images that appeared in CACM, but it includes corrections
|
||||
and some added material. Note: the Wallace article is copyright ACM and IEEE,
|
||||
and it may not be used for commercial purposes.
|
||||
|
||||
A somewhat less technical, more leisurely introduction to JPEG can be found in
|
||||
"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
|
||||
M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides
|
||||
good explanations and example C code for a multitude of compression methods
|
||||
including JPEG. It is an excellent source if you are comfortable reading C
|
||||
code but don't know much about data compression in general. The book's JPEG
|
||||
sample code is far from industrial-strength, but when you are ready to look
|
||||
at a full implementation, you've got one here...
|
||||
|
||||
The best currently available description of JPEG is the textbook "JPEG Still
|
||||
Image Data Compression Standard" by William B. Pennebaker and Joan L.
|
||||
Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1.
|
||||
Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG
|
||||
standards (DIS 10918-1 and draft DIS 10918-2).
|
||||
Although this is by far the most detailed and comprehensive exposition of
|
||||
JPEG publicly available, we point out that it is still missing an explanation
|
||||
of the most essential properties and algorithms of the underlying DCT
|
||||
technology.
|
||||
If you think that you know about DCT-based JPEG after reading this book,
|
||||
then you are in delusion. The real fundamentals and corresponding potential
|
||||
of DCT-based JPEG are not publicly known so far, and that is the reason for
|
||||
all the mistaken developments taking place in the image coding domain.
|
||||
|
||||
The original JPEG standard is divided into two parts, Part 1 being the actual
|
||||
specification, while Part 2 covers compliance testing methods. Part 1 is
|
||||
titled "Digital Compression and Coding of Continuous-tone Still Images,
|
||||
Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
|
||||
10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
|
||||
Continuous-tone Still Images, Part 2: Compliance testing" and has document
|
||||
numbers ISO/IEC IS 10918-2, ITU-T T.83.
|
||||
IJG JPEG 8 introduced an implementation of the JPEG SmartScale extension
|
||||
which is specified in two documents: A contributed document at ITU and ISO
|
||||
with title "ITU-T JPEG-Plus Proposal for Extending ITU-T T.81 for Advanced
|
||||
Image Coding", April 2006, Geneva, Switzerland. The latest version of this
|
||||
document is Revision 3. And a contributed document ISO/IEC JTC1/SC29/WG1 N
|
||||
5799 with title "Evolution of JPEG", June/July 2011, Berlin, Germany.
|
||||
IJG JPEG 9 introduces a reversible color transform for improved lossless
|
||||
compression which is described in a contributed document ISO/IEC JTC1/SC29/
|
||||
WG1 N 6080 with title "JPEG 9 Lossless Coding", June/July 2012, Paris,
|
||||
France.
|
||||
|
||||
The JPEG standard does not specify all details of an interchangeable file
|
||||
format. For the omitted details we follow the "JFIF" conventions, revision
|
||||
1.02. JFIF 1.02 has been adopted as an Ecma International Technical Report
|
||||
and thus received a formal publication status. It is available as a free
|
||||
download in PDF format from
|
||||
http://www.ecma-international.org/publications/techreports/E-TR-098.htm.
|
||||
A PostScript version of the JFIF document is available at
|
||||
http://www.ijg.org/files/jfif.ps.gz. There is also a plain text version at
|
||||
http://www.ijg.org/files/jfif.txt.gz, but it is missing the figures.
|
||||
|
||||
The TIFF 6.0 file format specification can be obtained by FTP from
|
||||
ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
|
||||
found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
|
||||
IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
|
||||
Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
|
||||
(Compression tag 7). Copies of this Note can be obtained from
|
||||
http://www.ijg.org/files/. It is expected that the next revision
|
||||
of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
|
||||
Although IJG's own code does not support TIFF/JPEG, the free libtiff library
|
||||
uses our library to implement TIFF/JPEG per the Note.
|
||||
|
||||
|
||||
ARCHIVE LOCATIONS
|
||||
=================
|
||||
|
||||
The "official" archive site for this software is www.ijg.org.
|
||||
The most recent released version can always be found there in
|
||||
directory "files". This particular version will be archived as
|
||||
http://www.ijg.org/files/jpegsrc.v9a.tar.gz, and in Windows-compatible
|
||||
"zip" archive format as http://www.ijg.org/files/jpegsr9a.zip.
|
||||
|
||||
The JPEG FAQ (Frequently Asked Questions) article is a source of some
|
||||
general information about JPEG.
|
||||
It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
|
||||
and other news.answers archive sites, including the official news.answers
|
||||
archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
|
||||
If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
|
||||
with body
|
||||
send usenet/news.answers/jpeg-faq/part1
|
||||
send usenet/news.answers/jpeg-faq/part2
|
||||
|
||||
|
||||
ACKNOWLEDGMENTS
|
||||
===============
|
||||
|
||||
Thank to Juergen Bruder for providing me with a copy of the common DCT
|
||||
algorithm article, only to find out that I had come to the same result
|
||||
in a more direct and comprehensible way with a more generative approach.
|
||||
|
||||
Thank to Istvan Sebestyen and Joan L. Mitchell for inviting me to the
|
||||
ITU JPEG (Study Group 16) meeting in Geneva, Switzerland.
|
||||
|
||||
Thank to Thomas Wiegand and Gary Sullivan for inviting me to the
|
||||
Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland.
|
||||
|
||||
Thank to Thomas Richter and Daniel Lee for inviting me to the
|
||||
ISO/IEC JTC1/SC29/WG1 (previously known as JPEG, together with ITU-T SG16)
|
||||
meeting in Berlin, Germany.
|
||||
|
||||
Thank to John Korejwa and Massimo Ballerini for inviting me to
|
||||
fruitful consultations in Boston, MA and Milan, Italy.
|
||||
|
||||
Thank to Hendrik Elstner, Roland Fassauer, Simone Zuck, Guenther
|
||||
Maier-Gerber, Walter Stoeber, Fred Schmitz, and Norbert Braunagel
|
||||
for corresponding business development.
|
||||
|
||||
Thank to Nico Zschach and Dirk Stelling of the technical support team
|
||||
at the Digital Images company in Halle for providing me with extra
|
||||
equipment for configuration tests.
|
||||
|
||||
Thank to Richard F. Lyon (then of Foveon Inc.) for fruitful
|
||||
communication about JPEG configuration in Sigma Photo Pro software.
|
||||
|
||||
Thank to Andrew Finkenstadt for hosting the ijg.org site.
|
||||
|
||||
Last but not least special thank to Thomas G. Lane for the original
|
||||
design and development of this singular software package.
|
||||
|
||||
|
||||
FILE FORMAT WARS
|
||||
================
|
||||
|
||||
The ISO/IEC JTC1/SC29/WG1 standards committee (previously known as JPEG,
|
||||
together with ITU-T SG16) currently promotes different formats containing
|
||||
the name "JPEG" which is misleading because these formats are incompatible
|
||||
with original DCT-based JPEG and are based on faulty technologies.
|
||||
IJG therefore does not and will not support such momentary mistakes
|
||||
(see REFERENCES).
|
||||
There exist also distributions under the name "OpenJPEG" promoting such
|
||||
kind of formats which is misleading because they don't support original
|
||||
JPEG images.
|
||||
We have no sympathy for the promotion of inferior formats. Indeed, one of
|
||||
the original reasons for developing this free software was to help force
|
||||
convergence on common, interoperable format standards for JPEG files.
|
||||
Don't use an incompatible file format!
|
||||
(In any case, our decoder will remain capable of reading existing JPEG
|
||||
image files indefinitely.)
|
||||
|
||||
The ISO committee pretends to be "responsible for the popular JPEG" in their
|
||||
public reports which is not true because they don't respond to actual
|
||||
requirements for the maintenance of the original JPEG specification.
|
||||
Furthermore, the ISO committee pretends to "ensure interoperability" with
|
||||
their standards which is not true because their "standards" support only
|
||||
application-specific and proprietary use cases and contain mathematically
|
||||
incorrect code.
|
||||
|
||||
There are currently different distributions in circulation containing the
|
||||
name "libjpeg" which is misleading because they don't have the features and
|
||||
are incompatible with formats supported by actual IJG libjpeg distributions.
|
||||
One of those fakes is released by members of the ISO committee and just uses
|
||||
the name of libjpeg for misdirection of people, similar to the abuse of the
|
||||
name JPEG as described above, while having nothing in common with actual IJG
|
||||
libjpeg distributions and containing mathematically incorrect code.
|
||||
The other one claims to be a "derivative" or "fork" of the original libjpeg,
|
||||
but violates the license conditions as described under LEGAL ISSUES above
|
||||
and violates basic C programming properties.
|
||||
We have no sympathy for the release of misleading, incorrect and illegal
|
||||
distributions derived from obsolete code bases.
|
||||
Don't use an obsolete code base!
|
||||
|
||||
According to the UCC (Uniform Commercial Code) law, IJG has the lawful and
|
||||
legal right to foreclose on certain standardization bodies and other
|
||||
institutions or corporations that knowingly perform substantial and
|
||||
systematic deceptive acts and practices, fraud, theft, and damaging of the
|
||||
value of the people of this planet without their knowing, willing and
|
||||
intentional consent.
|
||||
The titles, ownership, and rights of these institutions and all their assets
|
||||
are now duly secured and held in trust for the free people of this planet.
|
||||
People of the planet, on every country, may have a financial interest in
|
||||
the assets of these former principals, agents, and beneficiaries of the
|
||||
foreclosed institutions and corporations.
|
||||
IJG asserts what is: that each man, woman, and child has unalienable value
|
||||
and rights granted and deposited in them by the Creator and not any one of
|
||||
the people is subordinate to any artificial principality, corporate fiction
|
||||
or the special interest of another without their appropriate knowing,
|
||||
willing and intentional consent made by contract or accommodation agreement.
|
||||
IJG expresses that which already was.
|
||||
The people have already determined and demanded that public administration
|
||||
entities, national governments, and their supporting judicial systems must
|
||||
be fully transparent, accountable, and liable.
|
||||
IJG has secured the value for all concerned free people of the planet.
|
||||
|
||||
A partial list of foreclosed institutions and corporations ("Hall of Shame")
|
||||
is currently prepared and will be published later.
|
||||
|
||||
|
||||
TO DO
|
||||
=====
|
||||
|
||||
Version 9 is the second release of a new generation JPEG standard
|
||||
to overcome the limitations of the original JPEG specification,
|
||||
and is the first true source reference JPEG codec.
|
||||
More features are being prepared for coming releases...
|
||||
|
||||
Please send bug reports, offers of help, etc. to jpeg-info@jpegclub.org.
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* jinclude.h
|
||||
*
|
||||
* Copyright (C) 1991-1994, Thomas G. Lane.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file exists to provide a single place to fix any problems with
|
||||
* including the wrong system include files. (Common problems are taken
|
||||
* care of by the standard jconfig symbols, but on really weird systems
|
||||
* you may have to edit this file.)
|
||||
*
|
||||
* NOTE: this file is NOT intended to be included by applications using the
|
||||
* JPEG library. Most applications need only include jpeglib.h.
|
||||
*/
|
||||
|
||||
|
||||
/* Include auto-config file to find out which system include files we need. */
|
||||
|
||||
#include "jconfig.h" /* auto configuration options */
|
||||
#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
|
||||
|
||||
/*
|
||||
* We need the NULL macro and size_t typedef.
|
||||
* On an ANSI-conforming system it is sufficient to include <stddef.h>.
|
||||
* Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
|
||||
* pull in <sys/types.h> as well.
|
||||
* Note that the core JPEG library does not require <stdio.h>;
|
||||
* only the default error handler and data source/destination modules do.
|
||||
* But we must pull it in because of the references to FILE in jpeglib.h.
|
||||
* You can remove those references if you want to compile without <stdio.h>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef NEED_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* We need memory copying and zeroing functions, plus strncpy().
|
||||
* ANSI and System V implementations declare these in <string.h>.
|
||||
* BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
|
||||
* Some systems may declare memset and memcpy in <memory.h>.
|
||||
*
|
||||
* NOTE: we assume the size parameters to these functions are of type size_t.
|
||||
* Change the casts in these macros if not!
|
||||
*/
|
||||
|
||||
#ifdef NEED_BSD_STRINGS
|
||||
|
||||
#include <strings.h>
|
||||
#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
|
||||
#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
|
||||
|
||||
#else /* not BSD, assume ANSI/SysV string lib */
|
||||
|
||||
#include <string.h>
|
||||
#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
|
||||
#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In ANSI C, and indeed any rational implementation, size_t is also the
|
||||
* type returned by sizeof(). However, it seems there are some irrational
|
||||
* implementations out there, in which sizeof() returns an int even though
|
||||
* size_t is defined as long or unsigned long. To ensure consistent results
|
||||
* we always use this SIZEOF() macro in place of using sizeof() directly.
|
||||
*/
|
||||
|
||||
#define SIZEOF(object) ((size_t) sizeof(object))
|
||||
|
||||
/*
|
||||
* The modules that use fread() and fwrite() always invoke them through
|
||||
* these macros. On some systems you may need to twiddle the argument casts.
|
||||
* CAUTION: argument order is different from underlying functions!
|
||||
*/
|
||||
|
||||
#define JFREAD(file,buf,sizeofbuf) \
|
||||
((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
||||
#define JFWRITE(file,buf,sizeofbuf) \
|
||||
((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
|
|
@ -1,426 +0,0 @@
|
|||
/*
|
||||
* jpegint.h
|
||||
*
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 1997-2013 by Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file provides common declarations for the various JPEG modules.
|
||||
* These declarations are considered internal to the JPEG library; most
|
||||
* applications using the library shouldn't need to include this file.
|
||||
*/
|
||||
|
||||
|
||||
/* Declarations for both compression & decompression */
|
||||
|
||||
typedef enum { /* Operating modes for buffer controllers */
|
||||
JBUF_PASS_THRU, /* Plain stripwise operation */
|
||||
/* Remaining modes require a full-image buffer to have been created */
|
||||
JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
|
||||
JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
|
||||
JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
|
||||
} J_BUF_MODE;
|
||||
|
||||
/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
|
||||
#define CSTATE_START 100 /* after create_compress */
|
||||
#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
|
||||
#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
|
||||
#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
|
||||
#define DSTATE_START 200 /* after create_decompress */
|
||||
#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
|
||||
#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
|
||||
#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
|
||||
#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
|
||||
#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
|
||||
#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
|
||||
#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
|
||||
#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
|
||||
#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
|
||||
#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
|
||||
|
||||
|
||||
/* Declarations for compression modules */
|
||||
|
||||
/* Master control module */
|
||||
struct jpeg_comp_master {
|
||||
JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean call_pass_startup; /* True if pass_startup must be called */
|
||||
boolean is_last_pass; /* True during last pass */
|
||||
};
|
||||
|
||||
/* Main buffer control (downsampled-data buffer) */
|
||||
struct jpeg_c_main_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, process_data, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
|
||||
JDIMENSION in_rows_avail));
|
||||
};
|
||||
|
||||
/* Compression preprocessing (downsampling input buffer control) */
|
||||
struct jpeg_c_prep_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf,
|
||||
JDIMENSION *in_row_ctr,
|
||||
JDIMENSION in_rows_avail,
|
||||
JSAMPIMAGE output_buf,
|
||||
JDIMENSION *out_row_group_ctr,
|
||||
JDIMENSION out_row_groups_avail));
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
struct jpeg_c_coef_controller {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf));
|
||||
};
|
||||
|
||||
/* Colorspace conversion */
|
||||
struct jpeg_color_converter {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, color_convert, (j_compress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
|
||||
JDIMENSION output_row, int num_rows));
|
||||
};
|
||||
|
||||
/* Downsampling */
|
||||
struct jpeg_downsampler {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, downsample, (j_compress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION in_row_index,
|
||||
JSAMPIMAGE output_buf,
|
||||
JDIMENSION out_row_group_index));
|
||||
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Forward DCT (also controls coefficient quantization) */
|
||||
typedef JMETHOD(void, forward_DCT_ptr,
|
||||
(j_compress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
|
||||
JDIMENSION start_row, JDIMENSION start_col,
|
||||
JDIMENSION num_blocks));
|
||||
|
||||
struct jpeg_forward_dct {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo));
|
||||
/* It is useful to allow each component to have a separate FDCT method. */
|
||||
forward_DCT_ptr forward_DCT[MAX_COMPONENTS];
|
||||
};
|
||||
|
||||
/* Entropy encoding */
|
||||
struct jpeg_entropy_encoder {
|
||||
JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
|
||||
JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
|
||||
JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
|
||||
};
|
||||
|
||||
/* Marker writing */
|
||||
struct jpeg_marker_writer {
|
||||
JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
|
||||
JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
|
||||
/* These routines are exported to allow insertion of extra markers */
|
||||
/* Probably only COM and APPn markers should be written this way */
|
||||
JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker,
|
||||
unsigned int datalen));
|
||||
JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val));
|
||||
};
|
||||
|
||||
|
||||
/* Declarations for decompression modules */
|
||||
|
||||
/* Master control module */
|
||||
struct jpeg_decomp_master {
|
||||
JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
|
||||
};
|
||||
|
||||
/* Input control module */
|
||||
struct jpeg_input_controller {
|
||||
JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
|
||||
|
||||
/* State variables made visible to other modules */
|
||||
boolean has_multiple_scans; /* True if file has multiple scans */
|
||||
boolean eoi_reached; /* True when EOI has been consumed */
|
||||
};
|
||||
|
||||
/* Main buffer control (downsampled-data buffer) */
|
||||
struct jpeg_d_main_controller {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, process_data, (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
};
|
||||
|
||||
/* Coefficient buffer control */
|
||||
struct jpeg_d_coef_controller {
|
||||
JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE output_buf));
|
||||
/* Pointer to array of coefficient virtual arrays, or NULL if none */
|
||||
jvirt_barray_ptr *coef_arrays;
|
||||
};
|
||||
|
||||
/* Decompression postprocessing (color quantization buffer control) */
|
||||
struct jpeg_d_post_controller {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
|
||||
JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf,
|
||||
JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
};
|
||||
|
||||
/* Marker reading & parsing */
|
||||
struct jpeg_marker_reader {
|
||||
JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
|
||||
/* Read markers until SOS or EOI.
|
||||
* Returns same codes as are defined for jpeg_consume_input:
|
||||
* JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
|
||||
*/
|
||||
JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
|
||||
/* Read a restart marker --- exported for use by entropy decoder only */
|
||||
jpeg_marker_parser_method read_restart_marker;
|
||||
|
||||
/* State of marker reader --- nominally internal, but applications
|
||||
* supplying COM or APPn handlers might like to know the state.
|
||||
*/
|
||||
boolean saw_SOI; /* found SOI? */
|
||||
boolean saw_SOF; /* found SOF? */
|
||||
int next_restart_num; /* next restart number expected (0-7) */
|
||||
unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
|
||||
};
|
||||
|
||||
/* Entropy decoding */
|
||||
struct jpeg_entropy_decoder {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data));
|
||||
JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
|
||||
};
|
||||
|
||||
/* Inverse DCT (also performs dequantization) */
|
||||
typedef JMETHOD(void, inverse_DCT_method_ptr,
|
||||
(j_decompress_ptr cinfo, jpeg_component_info * compptr,
|
||||
JCOEFPTR coef_block,
|
||||
JSAMPARRAY output_buf, JDIMENSION output_col));
|
||||
|
||||
struct jpeg_inverse_dct {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
/* It is useful to allow each component to have a separate IDCT method. */
|
||||
inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
|
||||
};
|
||||
|
||||
/* Upsampling (note that upsampler must also call color converter) */
|
||||
struct jpeg_upsampler {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, upsample, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf,
|
||||
JDIMENSION *in_row_group_ctr,
|
||||
JDIMENSION in_row_groups_avail,
|
||||
JSAMPARRAY output_buf,
|
||||
JDIMENSION *out_row_ctr,
|
||||
JDIMENSION out_rows_avail));
|
||||
|
||||
boolean need_context_rows; /* TRUE if need rows above & below */
|
||||
};
|
||||
|
||||
/* Colorspace conversion */
|
||||
struct jpeg_color_deconverter {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
|
||||
JSAMPIMAGE input_buf, JDIMENSION input_row,
|
||||
JSAMPARRAY output_buf, int num_rows));
|
||||
};
|
||||
|
||||
/* Color quantization or color precision reduction */
|
||||
struct jpeg_color_quantizer {
|
||||
JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
|
||||
JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
|
||||
JSAMPARRAY input_buf, JSAMPARRAY output_buf,
|
||||
int num_rows));
|
||||
JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
|
||||
JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
|
||||
};
|
||||
|
||||
|
||||
/* Miscellaneous useful macros */
|
||||
|
||||
#undef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#undef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
|
||||
/* We assume that right shift corresponds to signed division by 2 with
|
||||
* rounding towards minus infinity. This is correct for typical "arithmetic
|
||||
* shift" instructions that shift in copies of the sign bit. But some
|
||||
* C compilers implement >> with an unsigned shift. For these machines you
|
||||
* must define RIGHT_SHIFT_IS_UNSIGNED.
|
||||
* RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
|
||||
* It is only applied with constant shift counts. SHIFT_TEMPS must be
|
||||
* included in the variables of any routine using RIGHT_SHIFT.
|
||||
*/
|
||||
|
||||
#ifdef RIGHT_SHIFT_IS_UNSIGNED
|
||||
#define SHIFT_TEMPS INT32 shift_temp;
|
||||
#define RIGHT_SHIFT(x,shft) \
|
||||
((shift_temp = (x)) < 0 ? \
|
||||
(shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
|
||||
(shift_temp >> (shft)))
|
||||
#else
|
||||
#define SHIFT_TEMPS
|
||||
#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
|
||||
#endif
|
||||
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jinit_compress_master jICompress
|
||||
#define jinit_c_master_control jICMaster
|
||||
#define jinit_c_main_controller jICMainC
|
||||
#define jinit_c_prep_controller jICPrepC
|
||||
#define jinit_c_coef_controller jICCoefC
|
||||
#define jinit_color_converter jICColor
|
||||
#define jinit_downsampler jIDownsampler
|
||||
#define jinit_forward_dct jIFDCT
|
||||
#define jinit_huff_encoder jIHEncoder
|
||||
#define jinit_arith_encoder jIAEncoder
|
||||
#define jinit_marker_writer jIMWriter
|
||||
#define jinit_master_decompress jIDMaster
|
||||
#define jinit_d_main_controller jIDMainC
|
||||
#define jinit_d_coef_controller jIDCoefC
|
||||
#define jinit_d_post_controller jIDPostC
|
||||
#define jinit_input_controller jIInCtlr
|
||||
#define jinit_marker_reader jIMReader
|
||||
#define jinit_huff_decoder jIHDecoder
|
||||
#define jinit_arith_decoder jIADecoder
|
||||
#define jinit_inverse_dct jIIDCT
|
||||
#define jinit_upsampler jIUpsampler
|
||||
#define jinit_color_deconverter jIDColor
|
||||
#define jinit_1pass_quantizer jI1Quant
|
||||
#define jinit_2pass_quantizer jI2Quant
|
||||
#define jinit_merged_upsampler jIMUpsampler
|
||||
#define jinit_memory_mgr jIMemMgr
|
||||
#define jdiv_round_up jDivRound
|
||||
#define jround_up jRound
|
||||
#define jzero_far jZeroFar
|
||||
#define jcopy_sample_rows jCopySamples
|
||||
#define jcopy_block_row jCopyBlocks
|
||||
#define jpeg_zigzag_order jZIGTable
|
||||
#define jpeg_natural_order jZAGTable
|
||||
#define jpeg_natural_order7 jZAG7Table
|
||||
#define jpeg_natural_order6 jZAG6Table
|
||||
#define jpeg_natural_order5 jZAG5Table
|
||||
#define jpeg_natural_order4 jZAG4Table
|
||||
#define jpeg_natural_order3 jZAG3Table
|
||||
#define jpeg_natural_order2 jZAG2Table
|
||||
#define jpeg_aritab jAriTab
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
|
||||
/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
|
||||
* and coefficient-block arrays. This won't work on 80x86 because the arrays
|
||||
* are FAR and we're assuming a small-pointer memory model. However, some
|
||||
* DOS compilers provide far-pointer versions of memcpy() and memset() even
|
||||
* in the small-model libraries. These will be used if USE_FMEM is defined.
|
||||
* Otherwise, the routines in jutils.c do it the hard way.
|
||||
*/
|
||||
|
||||
#ifndef NEED_FAR_POINTERS /* normal case, same as regular macro */
|
||||
#define FMEMZERO(target,size) MEMZERO(target,size)
|
||||
#else /* 80x86 case */
|
||||
#ifdef USE_FMEM
|
||||
#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size))
|
||||
#else
|
||||
EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero));
|
||||
#define FMEMZERO(target,size) jzero_far(target, size)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* Compression module initialization routines */
|
||||
EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
|
||||
boolean transcode_only));
|
||||
EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo));
|
||||
EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
|
||||
/* Decompression module initialization routines */
|
||||
EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
|
||||
boolean need_full_buffer));
|
||||
EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
|
||||
EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
|
||||
/* Memory manager initialization */
|
||||
EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
|
||||
|
||||
/* Utility routines in jutils.c */
|
||||
EXTERN(long) jdiv_round_up JPP((long a, long b));
|
||||
EXTERN(long) jround_up JPP((long a, long b));
|
||||
EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
|
||||
JSAMPARRAY output_array, int dest_row,
|
||||
int num_rows, JDIMENSION num_cols));
|
||||
EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
|
||||
JDIMENSION num_blocks));
|
||||
/* Constant tables in jutils.c */
|
||||
#if 0 /* This table is not actually needed in v6a */
|
||||
extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
|
||||
#endif
|
||||
extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
|
||||
extern const int jpeg_natural_order7[]; /* zz to natural order for 7x7 block */
|
||||
extern const int jpeg_natural_order6[]; /* zz to natural order for 6x6 block */
|
||||
extern const int jpeg_natural_order5[]; /* zz to natural order for 5x5 block */
|
||||
extern const int jpeg_natural_order4[]; /* zz to natural order for 4x4 block */
|
||||
extern const int jpeg_natural_order3[]; /* zz to natural order for 3x3 block */
|
||||
extern const int jpeg_natural_order2[]; /* zz to natural order for 2x2 block */
|
||||
|
||||
/* Arithmetic coding probability estimation tables in jaricom.c */
|
||||
extern const INT32 jpeg_aritab[];
|
||||
|
||||
/* Suppress undefined-structure complaints if necessary. */
|
||||
|
||||
#ifdef INCOMPLETE_TYPES_BROKEN
|
||||
#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */
|
||||
struct jvirt_sarray_control { long dummy; };
|
||||
struct jvirt_barray_control { long dummy; };
|
||||
#endif
|
||||
#endif /* INCOMPLETE_TYPES_BROKEN */
|
File diff suppressed because it is too large
Load diff
|
@ -1,219 +0,0 @@
|
|||
/*
|
||||
* transupp.h
|
||||
*
|
||||
* Copyright (C) 1997-2013, Thomas G. Lane, Guido Vollbeding.
|
||||
* This file is part of the Independent JPEG Group's software.
|
||||
* For conditions of distribution and use, see the accompanying README file.
|
||||
*
|
||||
* This file contains declarations for image transformation routines and
|
||||
* other utility code used by the jpegtran sample application. These are
|
||||
* NOT part of the core JPEG library. But we keep these routines separate
|
||||
* from jpegtran.c to ease the task of maintaining jpegtran-like programs
|
||||
* that have other user interfaces.
|
||||
*
|
||||
* NOTE: all the routines declared here have very specific requirements
|
||||
* about when they are to be executed during the reading and writing of the
|
||||
* source and destination files. See the comments in transupp.c, or see
|
||||
* jpegtran.c for an example of correct usage.
|
||||
*/
|
||||
|
||||
/* If you happen not to want the image transform support, disable it here */
|
||||
#ifndef TRANSFORMS_SUPPORTED
|
||||
#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Although rotating and flipping data expressed as DCT coefficients is not
|
||||
* hard, there is an asymmetry in the JPEG format specification for images
|
||||
* whose dimensions aren't multiples of the iMCU size. The right and bottom
|
||||
* image edges are padded out to the next iMCU boundary with junk data; but
|
||||
* no padding is possible at the top and left edges. If we were to flip
|
||||
* the whole image including the pad data, then pad garbage would become
|
||||
* visible at the top and/or left, and real pixels would disappear into the
|
||||
* pad margins --- perhaps permanently, since encoders & decoders may not
|
||||
* bother to preserve DCT blocks that appear to be completely outside the
|
||||
* nominal image area. So, we have to exclude any partial iMCUs from the
|
||||
* basic transformation.
|
||||
*
|
||||
* Transpose is the only transformation that can handle partial iMCUs at the
|
||||
* right and bottom edges completely cleanly. flip_h can flip partial iMCUs
|
||||
* at the bottom, but leaves any partial iMCUs at the right edge untouched.
|
||||
* Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
|
||||
* The other transforms are defined as combinations of these basic transforms
|
||||
* and process edge blocks in a way that preserves the equivalence.
|
||||
*
|
||||
* The "trim" option causes untransformable partial iMCUs to be dropped;
|
||||
* this is not strictly lossless, but it usually gives the best-looking
|
||||
* result for odd-size images. Note that when this option is active,
|
||||
* the expected mathematical equivalences between the transforms may not hold.
|
||||
* (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
|
||||
* followed by -rot 180 -trim trims both edges.)
|
||||
*
|
||||
* We also offer a lossless-crop option, which discards data outside a given
|
||||
* image region but losslessly preserves what is inside. Like the rotate and
|
||||
* flip transforms, lossless crop is restricted by the current JPEG format: the
|
||||
* upper left corner of the selected region must fall on an iMCU boundary. If
|
||||
* this does not hold for the given crop parameters, we silently move the upper
|
||||
* left corner up and/or left to make it so, simultaneously increasing the
|
||||
* region dimensions to keep the lower right crop corner unchanged. (Thus, the
|
||||
* output image covers at least the requested region, but may cover more.)
|
||||
* The adjustment of the region dimensions may be optionally disabled.
|
||||
*
|
||||
* A complementary lossless-wipe option is provided to discard (gray out) data
|
||||
* inside a given image region while losslessly preserving what is outside.
|
||||
*
|
||||
* We also provide a lossless-resize option, which is kind of a lossless-crop
|
||||
* operation in the DCT coefficient block domain - it discards higher-order
|
||||
* coefficients and losslessly preserves lower-order coefficients of a
|
||||
* sub-block.
|
||||
*
|
||||
* Rotate/flip transform, resize, and crop can be requested together in a
|
||||
* single invocation. The crop is applied last --- that is, the crop region
|
||||
* is specified in terms of the destination image after transform/resize.
|
||||
*
|
||||
* We also offer a "force to grayscale" option, which simply discards the
|
||||
* chrominance channels of a YCbCr image. This is lossless in the sense that
|
||||
* the luminance channel is preserved exactly. It's not the same kind of
|
||||
* thing as the rotate/flip transformations, but it's convenient to handle it
|
||||
* as part of this package, mainly because the transformation routines have to
|
||||
* be aware of the option to know how many components to work on.
|
||||
*/
|
||||
|
||||
|
||||
/* Short forms of external names for systems with brain-damaged linkers. */
|
||||
|
||||
#ifdef NEED_SHORT_EXTERNAL_NAMES
|
||||
#define jtransform_parse_crop_spec jTrParCrop
|
||||
#define jtransform_request_workspace jTrRequest
|
||||
#define jtransform_adjust_parameters jTrAdjust
|
||||
#define jtransform_execute_transform jTrExec
|
||||
#define jtransform_perfect_transform jTrPerfect
|
||||
#define jcopy_markers_setup jCMrkSetup
|
||||
#define jcopy_markers_execute jCMrkExec
|
||||
#endif /* NEED_SHORT_EXTERNAL_NAMES */
|
||||
|
||||
|
||||
/*
|
||||
* Codes for supported types of image transformations.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JXFORM_NONE, /* no transformation */
|
||||
JXFORM_FLIP_H, /* horizontal flip */
|
||||
JXFORM_FLIP_V, /* vertical flip */
|
||||
JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
|
||||
JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
|
||||
JXFORM_ROT_90, /* 90-degree clockwise rotation */
|
||||
JXFORM_ROT_180, /* 180-degree rotation */
|
||||
JXFORM_ROT_270, /* 270-degree clockwise (or 90 ccw) */
|
||||
JXFORM_WIPE /* wipe */
|
||||
} JXFORM_CODE;
|
||||
|
||||
/*
|
||||
* Codes for crop parameters, which can individually be unspecified,
|
||||
* positive or negative for xoffset or yoffset,
|
||||
* positive or forced for width or height.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JCROP_UNSET,
|
||||
JCROP_POS,
|
||||
JCROP_NEG,
|
||||
JCROP_FORCE
|
||||
} JCROP_CODE;
|
||||
|
||||
/*
|
||||
* Transform parameters struct.
|
||||
* NB: application must not change any elements of this struct after
|
||||
* calling jtransform_request_workspace.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
/* Options: set by caller */
|
||||
JXFORM_CODE transform; /* image transform operator */
|
||||
boolean perfect; /* if TRUE, fail if partial MCUs are requested */
|
||||
boolean trim; /* if TRUE, trim partial MCUs as needed */
|
||||
boolean force_grayscale; /* if TRUE, convert color image to grayscale */
|
||||
boolean crop; /* if TRUE, crop or wipe source image */
|
||||
|
||||
/* Crop parameters: application need not set these unless crop is TRUE.
|
||||
* These can be filled in by jtransform_parse_crop_spec().
|
||||
*/
|
||||
JDIMENSION crop_width; /* Width of selected region */
|
||||
JCROP_CODE crop_width_set; /* (forced disables adjustment) */
|
||||
JDIMENSION crop_height; /* Height of selected region */
|
||||
JCROP_CODE crop_height_set; /* (forced disables adjustment) */
|
||||
JDIMENSION crop_xoffset; /* X offset of selected region */
|
||||
JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */
|
||||
JDIMENSION crop_yoffset; /* Y offset of selected region */
|
||||
JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */
|
||||
|
||||
/* Internal workspace: caller should not touch these */
|
||||
int num_components; /* # of components in workspace */
|
||||
jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
|
||||
JDIMENSION output_width; /* cropped destination dimensions */
|
||||
JDIMENSION output_height;
|
||||
JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */
|
||||
JDIMENSION y_crop_offset;
|
||||
JDIMENSION drop_width; /* drop/wipe dimensions measured in iMCUs */
|
||||
JDIMENSION drop_height;
|
||||
int iMCU_sample_width; /* destination iMCU size */
|
||||
int iMCU_sample_height;
|
||||
} jpeg_transform_info;
|
||||
|
||||
|
||||
#if TRANSFORMS_SUPPORTED
|
||||
|
||||
/* Parse a crop specification (written in X11 geometry style) */
|
||||
EXTERN(boolean) jtransform_parse_crop_spec
|
||||
JPP((jpeg_transform_info *info, const char *spec));
|
||||
/* Request any required workspace */
|
||||
EXTERN(boolean) jtransform_request_workspace
|
||||
JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
|
||||
/* Adjust output image parameters */
|
||||
EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info));
|
||||
/* Execute the actual transformation, if any */
|
||||
EXTERN(void) jtransform_execute_transform
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
jvirt_barray_ptr *src_coef_arrays,
|
||||
jpeg_transform_info *info));
|
||||
/* Determine whether lossless transformation is perfectly
|
||||
* possible for a specified image and transformation.
|
||||
*/
|
||||
EXTERN(boolean) jtransform_perfect_transform
|
||||
JPP((JDIMENSION image_width, JDIMENSION image_height,
|
||||
int MCU_width, int MCU_height,
|
||||
JXFORM_CODE transform));
|
||||
|
||||
/* jtransform_execute_transform used to be called
|
||||
* jtransform_execute_transformation, but some compilers complain about
|
||||
* routine names that long. This macro is here to avoid breaking any
|
||||
* old source code that uses the original name...
|
||||
*/
|
||||
#define jtransform_execute_transformation jtransform_execute_transform
|
||||
|
||||
#endif /* TRANSFORMS_SUPPORTED */
|
||||
|
||||
|
||||
/*
|
||||
* Support for copying optional markers from source to destination file.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
JCOPYOPT_NONE, /* copy no optional markers */
|
||||
JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */
|
||||
JCOPYOPT_ALL /* copy all optional markers */
|
||||
} JCOPY_OPTION;
|
||||
|
||||
#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */
|
||||
|
||||
/* Setup decompression object to save desired markers in memory */
|
||||
EXTERN(void) jcopy_markers_setup
|
||||
JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option));
|
||||
/* Copy markers saved in the given source object to the destination object */
|
||||
EXTERN(void) jcopy_markers_execute
|
||||
JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
||||
JCOPY_OPTION option));
|
|
@ -23,7 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
|
|||
|
||||
// Local
|
||||
#include "imageutils.h"
|
||||
#include "jpegcontent.h"
|
||||
#include "gwenviewconfig.h"
|
||||
#include "exiv2imageloader.h"
|
||||
|
||||
|
@ -66,69 +65,15 @@ bool ThumbnailContext::load(const QString &pixPath, int pixelSize)
|
|||
QByteArray formatHint = pixPath.section('.', -1).toAscii().toLower();
|
||||
QImageReader reader(pixPath);
|
||||
|
||||
JpegContent content;
|
||||
QByteArray format;
|
||||
QByteArray data;
|
||||
QBuffer buffer;
|
||||
int previewRatio = 1;
|
||||
|
||||
// raw images deserve special treatment
|
||||
if (KDcrawIface::KDcraw::rawFilesList().contains(QString(formatHint))) {
|
||||
// use KDCraw to extract the preview
|
||||
bool ret = KDcrawIface::KDcraw::loadEmbeddedPreview(data, pixPath);
|
||||
|
||||
// We need QImage. Loading JpegContent from QImage - exif lost
|
||||
// Loading QImage from JpegContent - unimplemented, would go with loadFromData
|
||||
if (!ret || !originalImage.loadFromData(data) || qMin(originalImage.width(), originalImage.height()) < MIN_PREV_SIZE) {
|
||||
// if the emebedded preview loading failed or gets just a small image, load
|
||||
// half preview instead. That's slower...
|
||||
if (!KDcrawIface::KDcraw::loadHalfPreview(data, pixPath)) {
|
||||
kWarning() << "unable to get preview for " << pixPath.toUtf8().constData();
|
||||
return false;
|
||||
}
|
||||
previewRatio = 2;
|
||||
}
|
||||
|
||||
// And we need JpegContent too because of EXIF (orientation!).
|
||||
if (!content.loadFromData(data)) {
|
||||
kWarning() << "unable to load preview for " << pixPath.toUtf8().constData();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer.setBuffer(&data);
|
||||
buffer.open(QIODevice::ReadOnly);
|
||||
reader.setDevice(&buffer);
|
||||
reader.setFormat(formatHint);
|
||||
} else {
|
||||
if (!reader.canRead()) {
|
||||
reader.setDecideFormatFromContent(true);
|
||||
// Set filename again, otherwise QImageReader won't restart from scratch
|
||||
reader.setFileName(pixPath);
|
||||
}
|
||||
|
||||
if (reader.format() == "jpeg" && GwenviewConfig::applyExifOrientation()) {
|
||||
content.load(pixPath);
|
||||
}
|
||||
}
|
||||
|
||||
// If there's jpeg content (from jpg or raw files), try to load an embedded thumbnail, if available.
|
||||
// If applyExifOrientation is not set, don't use the
|
||||
// embedded thumbnail since it might be rotated differently
|
||||
// than the actual image
|
||||
if (!content.rawData().isEmpty() && GwenviewConfig::applyExifOrientation()) {
|
||||
QImage thumbnail = content.thumbnail();
|
||||
orientation = content.orientation();
|
||||
|
||||
if (qMax(thumbnail.width(), thumbnail.height()) >= pixelSize) {
|
||||
mImage = thumbnail;
|
||||
if (orientation != NORMAL && orientation != NOT_AVAILABLE) {
|
||||
QMatrix matrix = ImageUtils::transformMatrix(orientation);
|
||||
mImage = mImage.transformed(matrix);
|
||||
}
|
||||
mOriginalWidth = content.size().width();
|
||||
mOriginalHeight = content.size().height();
|
||||
return true;
|
||||
}
|
||||
if (!reader.canRead()) {
|
||||
reader.setDecideFormatFromContent(true);
|
||||
// Set filename again, otherwise QImageReader won't restart from scratch
|
||||
reader.setFileName(pixPath);
|
||||
}
|
||||
|
||||
// Generate thumbnail from full image
|
||||
|
|
|
@ -44,7 +44,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "../lib/documentview/documentview.h"
|
||||
#include "../lib/documentview/documentviewcontainer.h"
|
||||
#include "../lib/documentview/documentviewcontroller.h"
|
||||
#include "../lib/imageformats/imageformats.h"
|
||||
#include "../lib/urlutils.h"
|
||||
#include "../lib/zoomwidget.h"
|
||||
#include "gvbrowserextension.h"
|
||||
|
@ -83,7 +82,6 @@ GVPart::GVPart(QWidget* parentWidget, QObject* parent, const QVariantList& /*arg
|
|||
|
||||
KStandardAction::saveAs(this, SLOT(saveAs()), actionCollection());
|
||||
|
||||
Gwenview::ImageFormats::registerPlugins();
|
||||
new GVBrowserExtension(this);
|
||||
|
||||
setXMLFile("gvpart/gvpart.rc");
|
||||
|
|
|
@ -24,7 +24,6 @@ gv_add_unit_test(imagescalertest testutils.cpp)
|
|||
gv_add_unit_test(paintutilstest)
|
||||
gv_add_unit_test(documenttest testutils.cpp)
|
||||
gv_add_unit_test(transformimageoperationtest)
|
||||
gv_add_unit_test(jpegcontenttest)
|
||||
gv_add_unit_test(thumbnailprovidertest testutils.cpp)
|
||||
gv_add_unit_test(timeutilstest)
|
||||
gv_add_unit_test(placetreemodeltest testutils.cpp)
|
||||
|
@ -38,6 +37,5 @@ gv_add_unit_test(importertest
|
|||
gv_add_unit_test(sorteddirmodeltest testutils.cpp)
|
||||
gv_add_unit_test(slidecontainerautotest slidecontainerautotest.cpp)
|
||||
gv_add_unit_test(imagemetainfomodeltest testutils.cpp)
|
||||
gv_add_unit_test(cmsprofiletest testutils.cpp)
|
||||
gv_add_unit_test(recursivedirmodeltest testutils.cpp)
|
||||
gv_add_unit_test(contextmanagertest testutils.cpp)
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
// Self
|
||||
#include "moc_cmsprofiletest.cpp"
|
||||
|
||||
// Local
|
||||
#include <lib/cms/cmsprofile.h>
|
||||
#include <lib/exiv2imageloader.h>
|
||||
#include <testutils.h>
|
||||
|
||||
// KDE
|
||||
#include <qtest_kde.h>
|
||||
|
||||
// Qt
|
||||
|
||||
QTEST_KDEMAIN(CmsProfileTest, GUI)
|
||||
|
||||
using namespace Gwenview;
|
||||
|
||||
void CmsProfileTest::testLoadFromImageData()
|
||||
{
|
||||
QFETCH(QString, fileName);
|
||||
QFETCH(QByteArray, format);
|
||||
QByteArray data;
|
||||
{
|
||||
QString path = pathForTestFile(fileName);
|
||||
QFile file(path);
|
||||
QVERIFY(file.open(QIODevice::ReadOnly));
|
||||
data = file.readAll();
|
||||
}
|
||||
Cms::Profile::Ptr ptr = Cms::Profile::loadFromImageData(data, format);
|
||||
QVERIFY(!ptr.isNull());
|
||||
}
|
||||
|
||||
#define NEW_ROW(fileName, format) QTest::newRow(fileName) << fileName << QByteArray(format)
|
||||
void CmsProfileTest::testLoadFromImageData_data()
|
||||
{
|
||||
QTest::addColumn<QString>("fileName");
|
||||
QTest::addColumn<QByteArray>("format");
|
||||
NEW_ROW("cms/colourTestFakeBRG.png", "png");
|
||||
NEW_ROW("cms/colourTestsRGB.png", "png");
|
||||
NEW_ROW("cms/Upper_Left.jpg", "jpeg");
|
||||
NEW_ROW("cms/Upper_Right.jpg", "jpeg");
|
||||
NEW_ROW("cms/Lower_Left.jpg", "jpeg");
|
||||
NEW_ROW("cms/Lower_Right.jpg", "jpeg");
|
||||
}
|
||||
#undef NEW_ROW
|
||||
|
||||
#if 0
|
||||
|
||||
void CmsProfileTest::testLoadFromExiv2Image()
|
||||
{
|
||||
QFETCH(QString, fileName);
|
||||
Exiv2::Image::AutoPtr image;
|
||||
{
|
||||
QByteArray data;
|
||||
QString path = pathForTestFile(fileName);
|
||||
kWarning() << path;
|
||||
QFile file(path);
|
||||
QVERIFY(file.open(QIODevice::ReadOnly));
|
||||
data = file.readAll();
|
||||
|
||||
Exiv2ImageLoader loader;
|
||||
QVERIFY(loader.load(data));
|
||||
image = loader.popImage();
|
||||
}
|
||||
Cms::Profile::Ptr ptr = Cms::Profile::loadFromExiv2Image(image.get());
|
||||
QVERIFY(!ptr.isNull());
|
||||
}
|
||||
|
||||
#define NEW_ROW(fileName) QTest::newRow(fileName) << fileName
|
||||
void CmsProfileTest::testLoadFromExiv2Image_data()
|
||||
{
|
||||
QTest::addColumn<QString>("fileName");
|
||||
}
|
||||
#undef NEW_ROW
|
||||
|
||||
#endif
|
|
@ -1,44 +0,0 @@
|
|||
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
||||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2012 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef CMSPROFILETEST_H
|
||||
#define CMSPROFILETEST_H
|
||||
|
||||
// Local
|
||||
|
||||
// KDE
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
class CmsProfileTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void testLoadFromImageData();
|
||||
void testLoadFromImageData_data();
|
||||
#if 0 // Need some test data
|
||||
void testLoadFromExiv2Image();
|
||||
void testLoadFromExiv2Image_data();
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* CMSPROFILETEST_H */
|
|
@ -1,303 +0,0 @@
|
|||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2007 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#include "moc_jpegcontenttest.cpp"
|
||||
#include <iostream>
|
||||
|
||||
// Qt
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QImage>
|
||||
#include <QString>
|
||||
|
||||
// KDE
|
||||
#include <qtest_kde.h>
|
||||
#include <KDebug>
|
||||
#include <KFileMetaInfo>
|
||||
|
||||
// Local
|
||||
#include "../lib/orientation.h"
|
||||
#include "../lib/jpegcontent.h"
|
||||
#include "testutils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char* ORIENT6_FILE = "orient6.jpg";
|
||||
const char* ORIENT1_VFLIP_FILE = "orient1_vflip.jpg";
|
||||
const char* CUT_FILE = "cut.jpg";
|
||||
const char* TMP_FILE = "tmp.jpg";
|
||||
const char* THUMBNAIL_FILE = "test_thumbnail.jpg";
|
||||
|
||||
const int ORIENT6_WIDTH = 128; // This size is the size *after* orientation
|
||||
const int ORIENT6_HEIGHT = 256; // has been applied
|
||||
const QString ORIENT6_COMMENT = "a comment";
|
||||
|
||||
QTEST_KDEMAIN(JpegContentTest, GUI)
|
||||
|
||||
void JpegContentTest::initTestCase()
|
||||
{
|
||||
bool result;
|
||||
QFile in(pathForTestFile(ORIENT6_FILE));
|
||||
result = in.open(QIODevice::ReadOnly);
|
||||
QVERIFY(result);
|
||||
|
||||
QFileInfo info(in);
|
||||
int size = info.size() / 2;
|
||||
|
||||
char* data = new char[size];
|
||||
int readSize = in.read(data, size);
|
||||
QCOMPARE(size, readSize);
|
||||
|
||||
QFile out(CUT_FILE);
|
||||
result = out.open(QIODevice::WriteOnly);
|
||||
QVERIFY(result);
|
||||
|
||||
int wroteSize = out.write(data, size);
|
||||
QCOMPARE(size, wroteSize);
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void JpegContentTest::cleanupTestCase()
|
||||
{
|
||||
QDir::current().remove(CUT_FILE);
|
||||
}
|
||||
|
||||
typedef QMap<QString, QString> MetaInfoMap;
|
||||
|
||||
MetaInfoMap getMetaInfo(const QString& path)
|
||||
{
|
||||
KFileMetaInfo fmi(path);
|
||||
QStringList list = fmi.supportedKeys();
|
||||
QStringList::ConstIterator it = list.constBegin();
|
||||
MetaInfoMap map;
|
||||
|
||||
for (; it != list.constEnd(); ++it) {
|
||||
KFileMetaInfoItem item = fmi.item(*it);
|
||||
map[*it] = item.value().toString();
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
void compareMetaInfo(const QString& path1, const QString& path2, const QStringList& ignoredKeys)
|
||||
{
|
||||
MetaInfoMap mim1 = getMetaInfo(path1);
|
||||
MetaInfoMap mim2 = getMetaInfo(path2);
|
||||
|
||||
QCOMPARE(mim1.keys(), mim2.keys());
|
||||
QList<QString> keys = mim1.keys();
|
||||
QList<QString>::ConstIterator it = keys.constBegin();
|
||||
for (; it != keys.constEnd(); ++it) {
|
||||
QString key = *it;
|
||||
if (ignoredKeys.contains(key)) continue;
|
||||
|
||||
QString msg =
|
||||
QString("Meta info differs for key '%1': v1=%2 v2=%3")
|
||||
.arg(key)
|
||||
.arg(mim1[key])
|
||||
.arg(mim2[key]);
|
||||
|
||||
QVERIFY2(mim1[key] == mim2[key], msg.toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
void JpegContentTest::testResetOrientation()
|
||||
{
|
||||
Gwenview::JpegContent content;
|
||||
bool result;
|
||||
|
||||
// Test resetOrientation without transform
|
||||
result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
|
||||
content.resetOrientation();
|
||||
|
||||
result = content.save(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
result = content.load(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
QCOMPARE(content.orientation(), Gwenview::NORMAL);
|
||||
|
||||
// Test resetOrientation with transform
|
||||
result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
|
||||
content.resetOrientation();
|
||||
content.transform(Gwenview::ROT_90);
|
||||
|
||||
result = content.save(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
result = content.load(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
QCOMPARE(content.orientation(), Gwenview::NORMAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function tests JpegContent::transform() by applying a ROT_90
|
||||
* transformation, saving, reloading and applying a ROT_270 to undo the ROT_90.
|
||||
* Saving and reloading are necessary because lossless transformation only
|
||||
* happens in JpegContent::save()
|
||||
*/
|
||||
void JpegContentTest::testTransform()
|
||||
{
|
||||
bool result;
|
||||
QImage finalImage, expectedImage;
|
||||
|
||||
Gwenview::JpegContent content;
|
||||
result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
|
||||
content.transform(Gwenview::ROT_90);
|
||||
result = content.save(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
result = content.load(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
content.transform(Gwenview::ROT_270);
|
||||
result = content.save(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
result = finalImage.load(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
result = expectedImage.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
|
||||
QCOMPARE(finalImage , expectedImage);
|
||||
}
|
||||
|
||||
void JpegContentTest::testSetComment()
|
||||
{
|
||||
QString comment = "test comment";
|
||||
Gwenview::JpegContent content;
|
||||
bool result;
|
||||
result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
|
||||
content.setComment(comment);
|
||||
QCOMPARE(content.comment() , comment);
|
||||
result = content.save(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
result = content.load(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
QCOMPARE(content.comment() , comment);
|
||||
}
|
||||
|
||||
void JpegContentTest::testReadInfo()
|
||||
{
|
||||
Gwenview::JpegContent content;
|
||||
bool result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
QCOMPARE(int(content.orientation()), 6);
|
||||
QCOMPARE(content.comment() , ORIENT6_COMMENT);
|
||||
QCOMPARE(content.size() , QSize(ORIENT6_WIDTH, ORIENT6_HEIGHT));
|
||||
}
|
||||
|
||||
void JpegContentTest::testThumbnail()
|
||||
{
|
||||
Gwenview::JpegContent content;
|
||||
bool result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
QImage thumbnail = content.thumbnail();
|
||||
result = thumbnail.save(THUMBNAIL_FILE, "JPEG");
|
||||
QVERIFY(result);
|
||||
}
|
||||
|
||||
void JpegContentTest::testMultipleRotations()
|
||||
{
|
||||
// Test that rotating a file a lot of times does not cause findJxform() to fail
|
||||
Gwenview::JpegContent content;
|
||||
bool result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
|
||||
// 12*4 + 1 is the same as 1, since rotating four times brings you back
|
||||
for (int loop = 0; loop < 12 * 4 + 1; ++loop) {
|
||||
content.transform(Gwenview::ROT_90);
|
||||
}
|
||||
result = content.save(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
result = content.load(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
QCOMPARE(content.size() , QSize(ORIENT6_HEIGHT, ORIENT6_WIDTH));
|
||||
|
||||
// Check the other meta info are still here
|
||||
QStringList ignoredKeys;
|
||||
ignoredKeys << "Orientation" << "Comment";
|
||||
compareMetaInfo(pathForTestFile(ORIENT6_FILE), pathForTestFile(ORIENT1_VFLIP_FILE), ignoredKeys);
|
||||
}
|
||||
|
||||
void JpegContentTest::testLoadTruncated()
|
||||
{
|
||||
// Test that loading and manipulating a truncated file does not crash
|
||||
Gwenview::JpegContent content;
|
||||
bool result = content.load(CUT_FILE);
|
||||
QVERIFY(result);
|
||||
QCOMPARE(int(content.orientation()), 6);
|
||||
QCOMPARE(content.comment() , ORIENT6_COMMENT);
|
||||
content.transform(Gwenview::VFLIP);
|
||||
kWarning() << "# Next function should output errors about incomplete image" ;
|
||||
content.save(TMP_FILE);
|
||||
kWarning() << "#" ;
|
||||
}
|
||||
|
||||
void JpegContentTest::testRawData()
|
||||
{
|
||||
Gwenview::JpegContent content;
|
||||
bool result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
|
||||
QByteArray fileData;
|
||||
QFile file(pathForTestFile(ORIENT6_FILE));
|
||||
result = file.open(QIODevice::ReadOnly);
|
||||
QVERIFY(result);
|
||||
fileData = file.readAll();
|
||||
|
||||
QCOMPARE(content.rawData(), fileData);
|
||||
}
|
||||
|
||||
void JpegContentTest::testSetImage()
|
||||
{
|
||||
Gwenview::JpegContent content;
|
||||
bool result = content.load(pathForTestFile(ORIENT6_FILE));
|
||||
QVERIFY(result);
|
||||
|
||||
QImage image = QImage(400, 300, QImage::Format_RGB32);
|
||||
image.fill(Qt::red);
|
||||
|
||||
content.setImage(image);
|
||||
|
||||
result = content.save(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
result = content.load(TMP_FILE);
|
||||
QVERIFY(result);
|
||||
|
||||
QCOMPARE(content.size(), image.size());
|
||||
|
||||
QStringList ignoredKeys;
|
||||
ignoredKeys << "Orientation";
|
||||
compareMetaInfo(pathForTestFile(ORIENT6_FILE), pathForTestFile(TMP_FILE), ignoredKeys);
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
Gwenview: an image viewer
|
||||
Copyright 2007 Aurélien Gâteau <agateau@kde.org>
|
||||
|
||||
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
|
||||
of the License, 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 this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
*/
|
||||
#ifndef JPEGCONTENTTEST_H
|
||||
#define JPEGCONTENTTEST_H
|
||||
|
||||
// Qt
|
||||
#include <QObject>
|
||||
|
||||
class JpegContentTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
void testReadInfo();
|
||||
void testThumbnail();
|
||||
void testResetOrientation();
|
||||
void testTransform();
|
||||
void testSetComment();
|
||||
void testMultipleRotations();
|
||||
void testLoadTruncated();
|
||||
void testRawData();
|
||||
void testSetImage();
|
||||
};
|
||||
|
||||
#endif // JPEGCONTENTTEST_H
|
|
@ -32,7 +32,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include <KIO/DeleteJob>
|
||||
|
||||
// Local
|
||||
#include "../lib/imageformats/imageformats.h"
|
||||
#include "../lib/thumbnailprovider/thumbnailprovider.h"
|
||||
#include "testutils.h"
|
||||
|
||||
|
@ -97,7 +96,6 @@ void SandBox::createTestImage(const QString& name, int width, int height, const
|
|||
void ThumbnailProviderTest::initTestCase()
|
||||
{
|
||||
qRegisterMetaType<KFileItem>("KFileItem");
|
||||
Gwenview::ImageFormats::registerPlugins();
|
||||
}
|
||||
|
||||
void ThumbnailProviderTest::init()
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
#include <QImageReader>
|
||||
#include <QtCore/qdatetime.h>
|
||||
|
||||
#include <lib/imageformats/imageformats.h>
|
||||
|
||||
const int ITERATIONS = 2;
|
||||
const QSize SCALED_SIZE(1280, 800);
|
||||
|
||||
|
@ -53,7 +51,6 @@ int main(int argc, char** argv)
|
|||
|
||||
qDebug() << "Using Qt loader";
|
||||
bench(&buffer, "qt.png");
|
||||
Gwenview::ImageFormats::registerPlugins();
|
||||
qDebug() << "Using Gwenview loader";
|
||||
bench(&buffer, "gv.png");
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue