summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/source/filter/jpeg/JpegReader.cxx214
-rw-r--r--vcl/source/filter/jpeg/JpegReader.hxx23
-rw-r--r--vcl/source/filter/jpeg/jpegc.cxx149
3 files changed, 139 insertions, 247 deletions
diff --git a/vcl/source/filter/jpeg/JpegReader.cxx b/vcl/source/filter/jpeg/JpegReader.cxx
index 8959e4e8bd99..cd00518dcf44 100644
--- a/vcl/source/filter/jpeg/JpegReader.cxx
+++ b/vcl/source/filter/jpeg/JpegReader.cxx
@@ -178,9 +178,6 @@ void jpeg_svstream_src (j_decompress_ptr cinfo, void* input)
JPEGReader::JPEGReader( SvStream& rStream, void* /*pCallData*/, bool bSetLogSize ) :
mrStream ( rStream ),
- mpAcc ( nullptr ),
- mpAcc1 ( nullptr ),
- mpBuffer ( nullptr ),
mnLastPos ( rStream.Tell() ),
mnLastLines ( 0 ),
mbSetLogSize ( bSetLogSize )
@@ -191,46 +188,32 @@ JPEGReader::JPEGReader( SvStream& rStream, void* /*pCallData*/, bool bSetLogSize
JPEGReader::~JPEGReader()
{
- delete[] mpBuffer;
-
- if( mpAcc )
- Bitmap::ReleaseAccess( mpAcc );
-
- if( mpAcc1 )
- Bitmap::ReleaseAccess( mpAcc1 );
}
-unsigned char * JPEGReader::CreateBitmap(JPEGCreateBitmapParam& rParam)
+bool JPEGReader::CreateBitmap(JPEGCreateBitmapParam& rParam)
{
if (rParam.nWidth > SAL_MAX_INT32 / 8 || rParam.nHeight > SAL_MAX_INT32 / 8)
- return nullptr; // avoid overflows later
+ return false; // avoid overflows later
if (rParam.nWidth == 0 || rParam.nHeight == 0)
- return nullptr;
+ return false;
- Size aSize(rParam.nWidth, rParam.nHeight );
- bool bGray = rParam.bGray != 0;
+ Size aSize(rParam.nWidth, rParam.nHeight);
+ bool bGray = rParam.bGray;
- unsigned char * pBmpBuf = nullptr;
+ maBitmap = Bitmap();
- if( mpAcc )
- {
- Bitmap::ReleaseAccess( mpAcc );
- maBmp = Bitmap();
- mpAcc = nullptr;
- }
+ sal_uInt64 nSize = aSize.Width() * aSize.Height();
- sal_uInt64 nSize = aSize.Width();
- nSize *= aSize.Height();
if (nSize > SAL_MAX_INT32 / (bGray?1:3))
- return nullptr;
+ return false;
// Check if the bitmap is atypically large.
if (nSize*(bGray?1:3) > MAX_BITMAP_BYTE_SIZE)
{
// Do not try to acquire resources for the large bitmap or to
// read the bitmap into memory.
- return nullptr;
+ return false;
}
if( bGray )
@@ -243,18 +226,18 @@ unsigned char * JPEGReader::CreateBitmap(JPEGCreateBitmapParam& rParam)
aGrayPal[ n ] = BitmapColor( cGray, cGray, cGray );
}
- maBmp = Bitmap( aSize, 8, &aGrayPal );
+ maBitmap = Bitmap(aSize, 8, &aGrayPal);
}
else
{
- maBmp = Bitmap( aSize, 24 );
+ maBitmap = Bitmap(aSize, 24);
}
- if ( mbSetLogSize )
+ if (mbSetLogSize)
{
unsigned long nUnit = rParam.density_unit;
- if( ( ( 1 == nUnit ) || ( 2 == nUnit ) ) && rParam.X_density && rParam.Y_density )
+ if (((1 == nUnit) || (2 == nUnit)) && rParam.X_density && rParam.Y_density )
{
Point aEmptyPoint;
Fraction aFractX( 1, rParam.X_density );
@@ -262,161 +245,48 @@ unsigned char * JPEGReader::CreateBitmap(JPEGCreateBitmapParam& rParam)
MapMode aMapMode( nUnit == 1 ? MAP_INCH : MAP_CM, aEmptyPoint, aFractX, aFractY );
Size aPrefSize = OutputDevice::LogicToLogic( aSize, aMapMode, MAP_100TH_MM );
- maBmp.SetPrefSize( aPrefSize );
- maBmp.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
+ maBitmap.SetPrefSize(aPrefSize);
+ maBitmap.SetPrefMapMode(MapMode(MAP_100TH_MM));
}
}
- mpAcc = maBmp.AcquireWriteAccess();
-
- if( mpAcc )
- {
- const ScanlineFormat nFormat = mpAcc->GetScanlineFormat();
-
- if(
- ( bGray && ( ScanlineFormat::N8BitPal == nFormat ) ) ||
- ( !bGray && ( ScanlineFormat::N24BitTcRgb == nFormat ) )
- )
- {
- pBmpBuf = mpAcc->GetBuffer();
- rParam.nAlignedWidth = mpAcc->GetScanlineSize();
- rParam.bTopDown = mpAcc->IsTopDown();
- }
- else
- {
- rParam.nAlignedWidth = AlignedWidth4Bytes( aSize.Width() * ( bGray ? 8 : 24 ) );
- rParam.bTopDown = true;
- pBmpBuf = mpBuffer = new unsigned char[rParam.nAlignedWidth * aSize.Height()];
- }
- }
-
- // clean up, if no Bitmap buffer can be provided.
- if ( !pBmpBuf )
- {
- Bitmap::ReleaseAccess( mpAcc );
- maBmp = Bitmap();
- mpAcc = nullptr;
- }
-
- return pBmpBuf;
-}
-
-void JPEGReader::FillBitmap()
-{
- if( mpBuffer && mpAcc )
- {
- unsigned char * pTmp;
- BitmapColor aColor;
- long nAlignedWidth;
- long nWidth = mpAcc->Width();
- long nHeight = mpAcc->Height();
-
- if( mpAcc->GetBitCount() == 8 )
- {
- std::unique_ptr<BitmapColor[]> pCols(new BitmapColor[ 256 ]);
-
- for( sal_uInt16 n = 0; n < 256; n++ )
- {
- const sal_uInt8 cGray = (sal_uInt8) n;
- pCols[ n ] = mpAcc->GetBestMatchingColor( BitmapColor( cGray, cGray, cGray ) );
- }
-
- nAlignedWidth = AlignedWidth4Bytes( mpAcc->Width() * 8L );
-
- for( long nY = 0L; nY < nHeight; nY++ )
- {
- pTmp = mpBuffer + nY * nAlignedWidth;
-
- for( long nX = 0L; nX < nWidth; nX++ )
- {
- mpAcc->SetPixel( nY, nX, pCols[ *pTmp++ ] );
- }
- }
- }
- else
- {
- nAlignedWidth = AlignedWidth4Bytes( mpAcc->Width() * 24L );
-
- for( long nY = 0L; nY < nHeight; nY++ )
- {
- // #i122985# Added fast-lane implementations using CopyScanline with direct supported mem formats
- static bool bCheckOwnReader(true);
-
- if(bCheckOwnReader)
- {
- // #i122985# Trying to copy the RGB data from jpeg import to make things faster. Unfortunately
- // it has no GBR format, so RGB three-byte groups need to be 'flipped' to GBR first,
- // then CopyScanline can use a memcpy to do the data transport. CopyScanline can also
- // do the needed conversion from ScanlineFormat::N24BitTcRgb (and it works well), but this
- // is not faster that the old loop below using SetPixel.
- sal_uInt8* aSource(mpBuffer + nY * nAlignedWidth);
- sal_uInt8* aEnd(aSource + (nWidth * 3));
-
- for(sal_uInt8* aTmp(aSource); aTmp < aEnd; aTmp += 3)
- {
- ::std::swap(*aTmp, *(aTmp + 2));
- }
-
- mpAcc->CopyScanline(nY, aSource, ScanlineFormat::N24BitTcBgr, nWidth * 3);
- }
- else
- {
- // old version: WritePixel
- pTmp = mpBuffer + nY * nAlignedWidth;
-
- for( long nX = 0L; nX < nWidth; nX++ )
- {
- aColor.SetRed( *pTmp++ );
- aColor.SetGreen( *pTmp++ );
- aColor.SetBlue( *pTmp++ );
- mpAcc->SetPixel( nY, nX, aColor );
- }
- }
- }
- }
- }
+ return true;
}
-Graphic JPEGReader::CreateIntermediateGraphic( const Bitmap& rBitmap, long nLines )
+Graphic JPEGReader::CreateIntermediateGraphic(long nLines)
{
- Graphic aGraphic;
- const Size aSizePixel( rBitmap.GetSizePixel() );
+ Graphic aGraphic;
+ const Size aSizePixel(maBitmap.GetSizePixel());
- if( !mnLastLines )
+ if (!mnLastLines)
{
- if( mpAcc1 )
- {
- Bitmap::ReleaseAccess( mpAcc1 );
- }
-
- maBmp1 = Bitmap( rBitmap.GetSizePixel(), 1 );
- maBmp1.Erase( Color( COL_WHITE ) );
- mpAcc1 = maBmp1.AcquireWriteAccess();
+ maIncompleteAlpha = Bitmap(aSizePixel, 1);
+ maIncompleteAlpha.Erase(Color(COL_WHITE));
}
- if( nLines && ( nLines < aSizePixel.Height() ) )
+ if (nLines && (nLines < aSizePixel.Height()))
{
- if( mpAcc1 )
- {
- const long nNewLines = nLines - mnLastLines;
+ const long nNewLines = nLines - mnLastLines;
- if( nNewLines )
+ if (nNewLines > 0)
+ {
{
- mpAcc1->SetFillColor( Color( COL_BLACK ) );
- mpAcc1->FillRect( Rectangle( Point( 0, mnLastLines ), Size( mpAcc1->Width(), nNewLines ) ) );
+ Bitmap::ScopedWriteAccess pAccess(maIncompleteAlpha);
+ pAccess->SetFillColor(Color(COL_BLACK));
+ pAccess->FillRect(Rectangle(Point(0, mnLastLines), Size(pAccess->Width(), nNewLines)));
}
- Bitmap::ReleaseAccess( mpAcc1 );
- aGraphic = BitmapEx( rBitmap, maBmp1 );
- mpAcc1 = maBmp1.AcquireWriteAccess();
+ aGraphic = BitmapEx(maBitmap, maIncompleteAlpha);
}
else
{
- aGraphic = rBitmap;
+ aGraphic = maBitmap;
}
}
else
- aGraphic = rBitmap;
+ {
+ aGraphic = maBitmap;
+ }
mnLastLines = nLines;
@@ -454,25 +324,15 @@ ReadState JPEGReader::Read( Graphic& rGraphic )
// read the (partial) image
ReadJPEG( this, &mrStream, &nLines, GetPreviewSize() );
- if( mpAcc )
+ if (!maBitmap.IsEmpty())
{
- if( mpBuffer )
- {
- FillBitmap();
- delete[] mpBuffer;
- mpBuffer = nullptr;
- }
-
- Bitmap::ReleaseAccess( mpAcc );
- mpAcc = nullptr;
-
if( mrStream.GetError() == ERRCODE_IO_PENDING )
{
- rGraphic = CreateIntermediateGraphic( maBmp, nLines );
+ rGraphic = CreateIntermediateGraphic(nLines);
}
else
{
- rGraphic = maBmp;
+ rGraphic = maBitmap;
}
bRet = true;
diff --git a/vcl/source/filter/jpeg/JpegReader.hxx b/vcl/source/filter/jpeg/JpegReader.hxx
index 71f8b9ae37e2..c3b52fd2abf9 100644
--- a/vcl/source/filter/jpeg/JpegReader.hxx
+++ b/vcl/source/filter/jpeg/JpegReader.hxx
@@ -39,34 +39,33 @@ struct JPEGCreateBitmapParam
unsigned long density_unit;
unsigned long X_density;
unsigned long Y_density;
- long bGray;
- long nAlignedWidth; // these members will be filled by the
- bool bTopDown; // CreateBitmap method in svtools
+ bool bGray;
+ bool bTopDown; // CreateBitmap method in svtools
};
class JPEGReader : public GraphicReader
{
SvStream& mrStream;
- Bitmap maBmp;
- Bitmap maBmp1;
- BitmapWriteAccess* mpAcc;
- BitmapWriteAccess* mpAcc1;
- unsigned char * mpBuffer;
+ Bitmap maBitmap;
+ Bitmap maIncompleteAlpha;
+
long mnLastPos;
long mnFormerPos;
long mnLastLines;
bool mbSetLogSize;
- Graphic CreateIntermediateGraphic( const Bitmap& rBitmap, long nLines );
- void FillBitmap();
+ Graphic CreateIntermediateGraphic(long nLines);
public:
JPEGReader( SvStream& rStream, void* pCallData, bool bSetLogSize );
virtual ~JPEGReader() override;
- ReadState Read( Graphic& rGraphic );
- unsigned char * CreateBitmap( JPEGCreateBitmapParam& param );
+ ReadState Read(Graphic& rGraphic);
+
+ bool CreateBitmap(JPEGCreateBitmapParam& param);
+
+ Bitmap& GetBitmap() { return maBitmap; }
};
#endif // INCLUDED_VCL_SOURCE_FILTER_JPEG_JPEGREADER_HXX
diff --git a/vcl/source/filter/jpeg/jpegc.cxx b/vcl/source/filter/jpeg/jpegc.cxx
index 74be061644c1..28af8c915d4b 100644
--- a/vcl/source/filter/jpeg/jpegc.cxx
+++ b/vcl/source/filter/jpeg/jpegc.cxx
@@ -36,6 +36,7 @@ extern "C" {
#include <JpegReader.hxx>
#include <JpegWriter.hxx>
#include <memory>
+#include <vcl/bitmapaccess.hxx>
#ifdef _MSC_VER
#pragma warning(push, 1) /* disable to __declspec(align()) aligned warning */
@@ -68,16 +69,8 @@ extern "C" void outputMessage (j_common_ptr cinfo)
void ReadJPEG( JPEGReader* pJPEGReader, void* pInputStream, long* pLines,
Size const & previewSize )
{
- jpeg_decompress_struct cinfo;
- ErrorManagerStruct jerr;
- JPEGCreateBitmapParam aCreateBitmapParam;
- unsigned char * pDIB;
- unsigned char * pTmp;
- long nWidth;
- long nHeight;
- long nAlignedWidth;
- JSAMPLE* aRangeLimit;
- std::unique_ptr<unsigned char[]> pScanLineBuffer;
+ jpeg_decompress_struct cinfo;
+ ErrorManagerStruct jerr;
if ( setjmp( jerr.setjmp_buffer ) )
{
@@ -151,72 +144,114 @@ void ReadJPEG( JPEGReader* pJPEGReader, void* pInputStream, long* pLines,
jpeg_start_decompress( &cinfo );
- nWidth = cinfo.output_width;
- nHeight = cinfo.output_height;
+ long nWidth = cinfo.output_width;
+ long nHeight = cinfo.output_height;
+
+ bool bGray = (cinfo.output_components == 1);
+
+ JPEGCreateBitmapParam aCreateBitmapParam;
+
aCreateBitmapParam.nWidth = nWidth;
aCreateBitmapParam.nHeight = nHeight;
aCreateBitmapParam.density_unit = cinfo.density_unit;
aCreateBitmapParam.X_density = cinfo.X_density;
aCreateBitmapParam.Y_density = cinfo.Y_density;
- aCreateBitmapParam.bGray = long(cinfo.output_components == 1);
- pDIB = pJPEGReader->CreateBitmap(aCreateBitmapParam);
- nAlignedWidth = aCreateBitmapParam.nAlignedWidth;
- aRangeLimit = cinfo.sample_range_limit;
+ aCreateBitmapParam.bGray = bGray;
- long nScanLineBufferComponents = 0;
- if ( cinfo.out_color_space == JCS_CMYK )
- {
- nScanLineBufferComponents = cinfo.output_width * 4;
- pScanLineBuffer.reset(new unsigned char[nScanLineBufferComponents]);
- }
+ bool bBitmapCreated = pJPEGReader->CreateBitmap(aCreateBitmapParam);
- if( pDIB )
+ if (bBitmapCreated)
{
- if( aCreateBitmapParam.bTopDown )
- {
- pTmp = pDIB;
- }
- else
- {
- pTmp = pDIB + ( nHeight - 1 ) * nAlignedWidth;
- nAlignedWidth = -nAlignedWidth;
- }
+ Bitmap::ScopedWriteAccess pAccess(pJPEGReader->GetBitmap());
- for ( *pLines = 0; *pLines < nHeight; (*pLines)++ )
+ if (pAccess)
{
- if (pScanLineBuffer)
- { // in other words cinfo.out_color_space == JCS_CMYK
- int i;
- int j;
- unsigned char *pSLB = pScanLineBuffer.get();
- jpeg_read_scanlines( &cinfo, reinterpret_cast<JSAMPARRAY>(&pSLB), 1 );
- // convert CMYK to RGB
- for( i=0, j=0; i < nScanLineBufferComponents; i+=4, j+=3 )
+ JSAMPLE* aRangeLimit = cinfo.sample_range_limit;
+
+ std::vector<sal_uInt8> pScanLineBuffer(nWidth * (bGray ? 1 : 3));
+ std::vector<sal_uInt8> pCYMKBuffer;
+
+ if (cinfo.out_color_space == JCS_CMYK)
+ {
+ pCYMKBuffer.resize(nWidth * 4);
+ }
+
+ const ScanlineFormat nFormat = pAccess->GetScanlineFormat();
+
+ bool bTopDown = true;
+
+ if (( bGray && nFormat == ScanlineFormat::N8BitPal) ||
+ (!bGray && nFormat == ScanlineFormat::N24BitTcRgb))
+ {
+ bTopDown = pAccess->IsTopDown();
+ }
+
+ std::unique_ptr<BitmapColor[]> pCols;
+
+ if (bGray)
+ {
+ pCols.reset(new BitmapColor[256]);
+
+ for (sal_uInt16 n = 0; n < 256; n++)
{
- int color_C = 255 - pScanLineBuffer[i+0];
- int color_M = 255 - pScanLineBuffer[i+1];
- int color_Y = 255 - pScanLineBuffer[i+2];
- int color_K = 255 - pScanLineBuffer[i+3];
- pTmp[j+0] = aRangeLimit[ 255L - ( color_C + color_K ) ];
- pTmp[j+1] = aRangeLimit[ 255L - ( color_M + color_K ) ];
- pTmp[j+2] = aRangeLimit[ 255L - ( color_Y + color_K ) ];
+ const sal_uInt8 cGray = n;
+ pCols[n] = pAccess->GetBestMatchingColor(BitmapColor(cGray, cGray, cGray));
}
}
- else
+
+ for (*pLines = 0; *pLines < nHeight; (*pLines)++)
{
- jpeg_read_scanlines( &cinfo, reinterpret_cast<JSAMPARRAY>(&pTmp), 1 );
- }
+ size_t yIndex = *pLines;
- /* PENDING ??? */
- if ( cinfo.err->msg_code == 113 )
- break;
+ if (cinfo.out_color_space == JCS_CMYK)
+ {
+ sal_uInt8* p = pCYMKBuffer.data();
+ jpeg_read_scanlines(&cinfo, reinterpret_cast<JSAMPARRAY>(&p), 1);
+
+ // convert CMYK to RGB
+ for (int cmyk = 0, rgb = 0; cmyk < nWidth * 4; cmyk += 4, rgb += 3)
+ {
+ int color_C = 255 - pCYMKBuffer[cmyk + 0];
+ int color_M = 255 - pCYMKBuffer[cmyk + 1];
+ int color_Y = 255 - pCYMKBuffer[cmyk + 2];
+ int color_K = 255 - pCYMKBuffer[cmyk + 3];
+
+ pScanLineBuffer[rgb + 0] = aRangeLimit[255L - (color_C + color_K)];
+ pScanLineBuffer[rgb + 1] = aRangeLimit[255L - (color_M + color_K)];
+ pScanLineBuffer[rgb + 2] = aRangeLimit[255L - (color_Y + color_K)];
+ }
+ }
+ else
+ {
+ sal_uInt8* p = pScanLineBuffer.data();
+ jpeg_read_scanlines(&cinfo, reinterpret_cast<JSAMPARRAY>(&p), 1);
+ }
+
+ if (!bTopDown)
+ yIndex = nHeight - 1 - yIndex;
- pTmp += nAlignedWidth;
+ if (bGray)
+ {
+ for (long x = 0; x < nWidth; ++x)
+ {
+ sal_uInt8 nColorGray = pScanLineBuffer[x];
+ pAccess->SetPixel(yIndex, x, pCols[nColorGray]);
+ }
+ }
+ else
+ {
+ pAccess->CopyScanline(yIndex, pScanLineBuffer.data(), ScanlineFormat::N24BitTcRgb, nWidth * 3);
+ }
+
+ /* PENDING ??? */
+ if (cinfo.err->msg_code == 113)
+ break;
+ }
}
}
- if ( pDIB )
+ if (bBitmapCreated)
{
jpeg_finish_decompress( &cinfo );
}
@@ -225,8 +260,6 @@ void ReadJPEG( JPEGReader* pJPEGReader, void* pInputStream, long* pLines,
jpeg_abort_decompress( &cinfo );
}
- pScanLineBuffer.reset();
-
jpeg_destroy_decompress( &cinfo );
}