Exif reading/writing and Jpeg lossless transformations support.

Support for reading/writing of Exif image metadata. Currently only
orientation is implemented, but support for other tags can be added.

Jpeg lossless transformations - currently only lossless rotation is
supported, but others can be added when needed.

Additionally GraphicNativeTransform and GraphicNativeMetadata has
been added. The responsibillity of GraphicNativeTransform is to
provide graphic transformations (like rotation) on native data and
the purpose is to be as lossless as possible in transformations.
GraphicNativeMetadata is a class for reading metadata which is
contained in a native data graphic stream. For now both support
only Jpeg.

Change-Id: I3e67cd3e7f5386746bcd1f0bfd2b90f5fe834b92
This commit is contained in:
Tomaž Vajngerl
2013-04-21 13:58:37 +02:00
parent 649f000084
commit b5a9cc71d2
16 changed files with 2626 additions and 9 deletions

View File

@@ -169,6 +169,8 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/filter/FilterConfigItem \
vcl/source/filter/graphicfilter \
vcl/source/filter/graphicfilter2 \
vcl/source/filter/GraphicNativeTransform \
vcl/source/filter/GraphicNativeMetadata \
vcl/source/filter/sgfbram \
vcl/source/filter/sgvmain \
vcl/source/filter/sgvspln \
@@ -177,9 +179,11 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/filter/igif/gifread \
vcl/source/filter/ixbm/xbmread \
vcl/source/filter/ixpm/xpmread \
vcl/source/filter/jpeg/Exif \
vcl/source/filter/jpeg/jpeg \
vcl/source/filter/jpeg/JpegReader \
vcl/source/filter/jpeg/JpegWriter \
vcl/source/filter/jpeg/JpegTransform \
vcl/source/filter/wmf/emfwr \
vcl/source/filter/wmf/enhwmf \
vcl/source/filter/wmf/winmtf \
@@ -317,6 +321,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
$(eval $(call gb_Library_add_cobjects,vcl,\
vcl/source/filter/jpeg/jpegc \
vcl/source/filter/jpeg/transupp \
))
# optional parts

View File

@@ -66,6 +66,8 @@ $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/gradient.hxx,vcl/gradient.hxx)
$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/graph.h,vcl/graph.h))
$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/graph.hxx,vcl/graph.hxx))
$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/graphicfilter.hxx,vcl/graphicfilter.hxx))
$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/GraphicNativeTransform.hxx,vcl/GraphicNativeTransform.hxx))
$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/GraphicNativeMetadata.hxx,vcl/GraphicNativeMetadata.hxx))
$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/graphictools.hxx,vcl/graphictools.hxx))
$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/group.hxx,vcl/group.hxx))
$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/hatch.hxx,vcl/hatch.hxx))

View File

@@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef _GRAPHICNATIVEMETADATA_HXX
#define _GRAPHICNATIVEMETADATA_HXX
#include <vcl/graph.hxx>
class VCL_DLLPUBLIC GraphicNativeMetadata
{
sal_uInt16 mRotation;
public:
GraphicNativeMetadata();
virtual ~GraphicNativeMetadata();
bool Read(Graphic& rGraphic);
sal_uInt16 GetRotation();
};
#endif //_GRAPHICNATIVEMETADATA_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef _GRAPHICNATIVETRANSFORM_HXX
#define _GRAPHICNATIVETRANSFORM_HXX
#include <vcl/graph.hxx>
class VCL_DLLPUBLIC GraphicNativeTransform
{
Graphic& mrGraphic;
public:
GraphicNativeTransform(Graphic& rGraphic);
virtual ~GraphicNativeTransform();
bool Rotate(sal_uInt16 aRotation);
};
#endif //_GRAPHICNATIVETRANSFORM_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <vcl/GraphicNativeMetadata.hxx>
#include <vcl/gfxlink.hxx>
#include "jpeg/Exif.hxx"
GraphicNativeMetadata::GraphicNativeMetadata() :
mRotation(0)
{}
GraphicNativeMetadata::~GraphicNativeMetadata()
{}
sal_uInt16 GraphicNativeMetadata::GetRotation()
{
return mRotation;
}
bool GraphicNativeMetadata::Read(Graphic& rGraphic)
{
GfxLink aLink = rGraphic.GetLink();
if ( aLink.GetType() != GFX_LINK_TYPE_NATIVE_JPG )
return false;
sal_uInt32 aDataSize = aLink.GetDataSize();
sal_uInt8* aBuffer = new sal_uInt8[aDataSize];
memcpy(aBuffer, aLink.GetData(), aDataSize);
SvMemoryStream aMemoryStream(aBuffer, aDataSize, STREAM_READ);
Exif aExif;
aExif.read(aMemoryStream);
mRotation = aExif.getRotation();
delete[] aBuffer;
return true;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <vcl/GraphicNativeTransform.hxx>
#include <vcl/gfxlink.hxx>
#include "jpeg/Exif.hxx"
#include "jpeg/JpegTransform.hxx"
GraphicNativeTransform::GraphicNativeTransform(Graphic& rGraphic) :
mrGraphic(rGraphic)
{}
GraphicNativeTransform::~GraphicNativeTransform()
{}
bool GraphicNativeTransform::Rotate(sal_uInt16 aRotation)
{
if (aRotation == 0)
return true;
if (aRotation != 900 && aRotation != 1800 && aRotation != 2700)
return false;
GfxLink aLink = mrGraphic.GetLink();
if ( aLink.GetType() != GFX_LINK_TYPE_NATIVE_JPG )
return false;
sal_uInt32 aDataSize = aLink.GetDataSize();
sal_uInt8* aInputBuffer = new sal_uInt8[aDataSize];
memcpy(aInputBuffer, aLink.GetData(), aDataSize);
SvMemoryStream aSourceStream(aInputBuffer, aDataSize, STREAM_READ);
SvMemoryStream aTargetStream;
JpegTransform tranform(aSourceStream, aTargetStream);
tranform.setRotate(aRotation);
tranform.perform();
aTargetStream.Seek( STREAM_SEEK_TO_BEGIN );
Exif exif;
exif.setOrientation(Orientation::TOP_LEFT);
exif.write(aTargetStream);
aTargetStream.Seek( STREAM_SEEK_TO_END );
sal_uInt32 aBufferSize = aTargetStream.Tell();
sal_uInt8* pBuffer = new sal_uInt8[ aBufferSize ];
aTargetStream.Seek( STREAM_SEEK_TO_BEGIN );
aTargetStream.Read( pBuffer, aBufferSize );
BitmapEx aBitmap = mrGraphic.GetBitmapEx();
aBitmap.Rotate(aRotation, COL_BLACK);
mrGraphic = aBitmap;
mrGraphic.SetLink( GfxLink( pBuffer, aBufferSize, aLink.GetType(), sal_True ) );
return true;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,167 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "Exif.hxx"
Exif::Exif() :
maOrientation(TOP_LEFT)
{}
Exif::~Exif()
{}
Orientation Exif::getOrientation() {
return maOrientation;
}
void Exif::setOrientation(Orientation aOrientation) {
maOrientation = aOrientation;
}
Orientation Exif::convertToOrientation(sal_Int32 value)
{
switch(value) {
case 1: return TOP_LEFT;
case 2: return TOP_RIGHT;
case 3: return BOTTOM_RIGHT;
case 4: return BOTTOM_LEFT;
case 5: return LEFT_TOP;
case 6: return RIGHT_TOP;
case 7: return RIGHT_BOTTOM;
case 8: return LEFT_BOTTOM;
}
return TOP_LEFT;
}
sal_Int32 Exif::getRotation()
{
switch(maOrientation) {
case TOP_LEFT:
return 0;
case BOTTOM_RIGHT:
return 1800;
case RIGHT_TOP:
return 2700;
case LEFT_BOTTOM:
return 900;
default:
return 0;
}
return 0;
}
bool Exif::read(SvStream& rStream)
{
sal_Int32 nStreamPosition = rStream.Tell();
bool result = processJpegStream(rStream, false);
rStream.Seek( nStreamPosition );
return result;
}
bool Exif::write(SvStream& rStream)
{
sal_Int32 nStreamPosition = rStream.Tell();
bool result = processJpegStream(rStream, true);
rStream.Seek( nStreamPosition );
return result;
}
bool Exif::processJpegStream(SvStream& rStream, bool bSetValue)
{
sal_uInt32 aMagic32;
sal_uInt16 aMagic16;
sal_uInt16 aLength;
rStream.SetNumberFormatInt( NUMBERFORMAT_INT_BIGENDIAN );
rStream >> aMagic32;
// Compare JPEG magic bytes
if( 0xffd8ff00 != ( aMagic32 & 0xffffff00 ) )
{
return false;
}
rStream >> aLength;
if (aLength < 8)
{
return false;
}
aLength -= 8;
rStream >> aMagic32;
rStream >> aMagic16;
// Compare EXIF magic bytes
if( 0x45786966 != aMagic32 || 0x0000 != aMagic16)
{
return false;
}
sal_uInt8* exifData = new sal_uInt8[aLength];
sal_uInt32 aExifDataBeginPosition = rStream.Tell();
rStream.Read(exifData, aLength);
sal_uInt16 offset;
offset = exifData[5];
offset <<= 8;
offset += exifData[4];
sal_uInt16 numberOfTags;
numberOfTags = exifData[offset+1];
numberOfTags <<= 8;
numberOfTags += exifData[offset];
offset += 2;
ExifIFD* ifd = NULL;
while (offset <= aLength - 12 && numberOfTags > 0) {
ifd = (ExifIFD*) &exifData[offset];
if (ifd->tag == Tag::ORIENTATION)
{
if(bSetValue)
{
ifd->tag = Tag::ORIENTATION;
ifd->type = 3;
ifd->count = 1;
ifd->offset = maOrientation;
}
else
{
maOrientation = convertToOrientation(ifd->offset);
}
}
numberOfTags--;
offset += 12;
}
if (bSetValue)
{
rStream.Seek(aExifDataBeginPosition);
rStream.Write(exifData, aLength);
}
return true;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef _EXIF_HXX
#define _EXIF_HXX
#include <vcl/graph.hxx>
#include <vcl/fltcall.hxx>
#include <com/sun/star/uno/Sequence.h>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/task/XStatusIndicator.hpp>
enum Orientation {
TOP_LEFT = 1,
TOP_RIGHT = 2,
BOTTOM_RIGHT = 3,
BOTTOM_LEFT = 4,
LEFT_TOP = 5,
RIGHT_TOP = 6,
RIGHT_BOTTOM = 7,
LEFT_BOTTOM = 8
};
enum Tag {
IMAGE_WIDTH = 0x0100,
IMAGE_HEIGHT = 0x0101,
BITS_PER_SAMPLE = 0x0102,
COMPRESSION = 0x0103,
ORIENTATION = 0x0112
};
class Exif
{
private:
Orientation maOrientation;
sal_Int32 mnStreamPosition;
bool processJpegStream(SvStream& rStream, bool bSetValue);
struct ExifIFD {
sal_uInt16 tag;
sal_uInt16 type;
sal_uInt32 count;
sal_uInt32 offset;
};
Orientation convertToOrientation(sal_Int32 value);
public :
Exif();
virtual ~Exif();
Orientation getOrientation();
sal_Int32 getRotation();
void setOrientation(Orientation orientation);
bool read(SvStream& rStream);
bool write(SvStream& rStream);
};
#endif // _EXIF_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
extern "C"
{
#include "jpeg.h"
}
#include "JpegTransform.hxx"
JpegTransform::JpegTransform(SvStream& rInputStream, SvStream& rOutputStream) :
maRotate ( 0 ),
mrInputStream ( rInputStream ),
mrOutputStream ( rOutputStream )
{}
JpegTransform::~JpegTransform()
{}
bool JpegTransform::perform()
{
long result = Transform( &mrInputStream, &mrOutputStream, maRotate );
return result;
}
void JpegTransform::setRotate(sal_uInt16 aRotate)
{
maRotate = aRotate;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,43 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef _JPEG_TRANSFROM_HXX
#define _JPEG_TRANSFORM_HXX
#include <tools/solar.h>
#include <vcl/graph.hxx>
class JpegTransform
{
sal_uInt16 maRotate;
SvStream& mrInputStream;
SvStream& mrOutputStream;
public:
JpegTransform(SvStream& rInputStream, SvStream& rOutputStream);
virtual ~JpegTransform();
void setRotate(sal_uInt16 aRotate);
bool perform();
};
#endif // _JPEG_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,91 @@
/*
* 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)))

View File

@@ -59,6 +59,8 @@ void* CreateBitmapFromJPEGReader( void* pJPEGReader, void* pJPEGCreateBitmapPa
the preview size hint should be redone */
void SetJpegPreviewSizeHint( int nWidth, int nHeight );
long Transform( void* pInputStream, void* pOutputStream, long nAngle );
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -22,9 +22,11 @@
#include <setjmp.h>
#include <jpeglib.h>
#include <jerror.h>
#include <rtl/alloc.h>
#include <osl/diagnose.h>
#include "transupp.h"
#include "jpeg.h"
struct ErrorManagerStruct
@@ -43,7 +45,6 @@ METHODDEF( void ) errorExit (j_common_ptr cinfo)
longjmp(error->setjmp_buffer, 1);
}
METHODDEF( void ) outputMessage (j_common_ptr cinfo)
{
char buffer[JMSG_LENGTH_MAX];
@@ -86,13 +87,13 @@ void ReadJPEG( void* pJPEGReader, void* pInputStream, long* pLines )
jpeg_create_decompress( &cinfo );
jpeg_svstream_src( &cinfo, pInputStream );
jpeg_read_header( &cinfo, sal_True );
jpeg_read_header( &cinfo, TRUE );
cinfo.scale_num = 1;
cinfo.scale_denom = 1;
cinfo.output_gamma = 1.0;
cinfo.raw_data_out = sal_False;
cinfo.quantize_colors = sal_False;
cinfo.raw_data_out = FALSE;
cinfo.quantize_colors = FALSE;
if ( cinfo.jpeg_color_space == JCS_YCbCr )
cinfo.out_color_space = JCS_RGB;
else if ( cinfo.jpeg_color_space == JCS_YCCK )
@@ -131,8 +132,8 @@ void ReadJPEG( void* pJPEGReader, void* pInputStream, long* pLines )
if( cinfo.scale_denom > 1 )
{
cinfo.dct_method = JDCT_FASTEST;
cinfo.do_fancy_upsampling = sal_False;
cinfo.do_block_smoothing = sal_False;
cinfo.do_fancy_upsampling = FALSE;
cinfo.do_block_smoothing = FALSE;
}
}
@@ -221,7 +222,8 @@ void ReadJPEG( void* pJPEGReader, void* pInputStream, long* pLines )
long WriteJPEG( void* pJPEGWriter, void* pOutputStream,
long nWidth, long nHeight, long bGreys,
long nQualityPercent, long aChromaSubsampling, void* pCallbackData )
long nQualityPercent, long aChromaSubsampling,
void* pCallbackData )
{
struct jpeg_compress_struct cinfo;
struct ErrorManagerStruct jerr;
@@ -255,7 +257,7 @@ long WriteJPEG( void* pJPEGWriter, void* pOutputStream,
}
jpeg_set_defaults( &cinfo );
jpeg_set_quality( &cinfo, (int) nQualityPercent, sal_False );
jpeg_set_quality( &cinfo, (int) nQualityPercent, FALSE );
if ( ( nWidth > 128 ) || ( nHeight > 128 ) )
jpeg_simple_progression( &cinfo );
@@ -276,7 +278,7 @@ long WriteJPEG( void* pJPEGWriter, void* pOutputStream,
cinfo.comp_info[0].v_samp_factor = 2;
}
jpeg_start_compress( &cinfo, sal_True );
jpeg_start_compress( &cinfo, TRUE );
for( nY = 0; nY < nHeight; nY++ )
{
@@ -300,4 +302,88 @@ long WriteJPEG( void* pJPEGWriter, void* pOutputStream,
return 1;
}
long Transform(void* pInputStream, void* pOutputStream, long nAngle)
{
jpeg_transform_info aTransformOption;
JCOPY_OPTION aCopyOption = JCOPYOPT_ALL;
struct jpeg_decompress_struct aSourceInfo;
struct jpeg_compress_struct aDestinationInfo;
struct ErrorManagerStruct aSourceError;
struct ErrorManagerStruct aDestinationError;
jvirt_barray_ptr* aSourceCoefArrays = 0;
jvirt_barray_ptr* aDestinationCoefArrays = 0;
aTransformOption.force_grayscale = FALSE;
aTransformOption.trim = FALSE;
aTransformOption.perfect = FALSE;
aTransformOption.crop = FALSE;
// Angle to transform option
// 90 Clockwise = 270 Counterclockwise
switch (nAngle)
{
case 2700:
aTransformOption.transform = JXFORM_ROT_90;
break;
case 1800:
aTransformOption.transform = JXFORM_ROT_180;
break;
case 900:
aTransformOption.transform = JXFORM_ROT_270;
break;
default:
aTransformOption.transform = JXFORM_NONE;
}
// Decompression
aSourceInfo.err = jpeg_std_error(&aSourceError.pub);
aSourceInfo.err->error_exit = errorExit;
aSourceInfo.err->output_message = outputMessage;
// Compression
aDestinationInfo.err = jpeg_std_error(&aDestinationError.pub);
aDestinationInfo.err->error_exit = errorExit;
aDestinationInfo.err->output_message = outputMessage;
aDestinationInfo.optimize_coding = TRUE;
if (setjmp(aSourceError.setjmp_buffer) || setjmp(aDestinationError.setjmp_buffer))
{
jpeg_destroy_decompress(&aSourceInfo);
jpeg_destroy_compress(&aDestinationInfo);
return 0;
}
jpeg_create_decompress(&aSourceInfo);
jpeg_create_compress(&aDestinationInfo);
jpeg_svstream_src (&aSourceInfo, pInputStream);
jcopy_markers_setup(&aSourceInfo, aCopyOption);
jpeg_read_header(&aSourceInfo, 1);
jtransform_request_workspace(&aSourceInfo, &aTransformOption);
aSourceCoefArrays = jpeg_read_coefficients(&aSourceInfo);
jpeg_copy_critical_parameters(&aSourceInfo, &aDestinationInfo);
aDestinationCoefArrays = jtransform_adjust_parameters(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
jpeg_svstream_dest (&aDestinationInfo, pOutputStream);
// Compute optimal Huffman coding tables instead of precomuted tables
aDestinationInfo.optimize_coding = 1;
jpeg_write_coefficients(&aDestinationInfo, aDestinationCoefArrays);
jcopy_markers_execute(&aSourceInfo, &aDestinationInfo, aCopyOption);
jtransform_execute_transformation(&aSourceInfo, &aDestinationInfo, aSourceCoefArrays, &aTransformOption);
jpeg_finish_compress(&aDestinationInfo);
jpeg_destroy_compress(&aDestinationInfo);
jpeg_finish_decompress(&aSourceInfo);
jpeg_destroy_decompress(&aSourceInfo);
return 1;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -0,0 +1,30 @@
/*
* jpegcomp.h
*
* Copyright (C) 2010, D. R. Commander
* For conditions of distribution and use, see the accompanying README file.
*
* JPEG compatibility macros
* These declarations are considered internal to the JPEG library; most
* applications using the library shouldn't need to include this file.
*/
#if JPEG_LIB_VERSION >= 70
#define _DCT_scaled_size DCT_h_scaled_size
#define _DCT_h_scaled_size DCT_h_scaled_size
#define _DCT_v_scaled_size DCT_v_scaled_size
#define _min_DCT_scaled_size min_DCT_h_scaled_size
#define _min_DCT_h_scaled_size min_DCT_h_scaled_size
#define _min_DCT_v_scaled_size min_DCT_v_scaled_size
#define _jpeg_width jpeg_width
#define _jpeg_height jpeg_height
#else
#define _DCT_scaled_size DCT_scaled_size
#define _DCT_h_scaled_size DCT_scaled_size
#define _DCT_v_scaled_size DCT_scaled_size
#define _min_DCT_scaled_size min_DCT_scaled_size
#define _min_DCT_h_scaled_size min_DCT_scaled_size
#define _min_DCT_v_scaled_size min_DCT_scaled_size
#define _jpeg_width image_width
#define _jpeg_height image_height
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,220 @@
/*
* transupp.h
*
* Copyright (C) 1997-2011, 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.)
* The adjustment of the region dimensions may be optionally disabled.
*
* 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 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 source image */
boolean slow_hflip; /* For best performance, the JXFORM_FLIP_H transform
normally modifies the source coefficients in place.
Setting this to TRUE will instead use a slower,
double-buffered algorithm, which leaves the source
coefficients in tact (necessary if other transformed
images must be generated from the same set of
coefficients. */
/* 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;
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));