43 bool bAllowOneShortRead;
46 , nStart(rInStream.Tell())
47 , nSize(rInStream.remainingSize())
48 , bAllowOneShortRead(false)
54static tsize_t
tiff_read(thandle_t handle, tdata_t buf, tsize_t size)
56 Context* pContext =
static_cast<Context*
>(handle);
57 tsize_t nRead = pContext->rStream.ReadBytes(buf,
size);
60 if (nRead < size && pContext->bAllowOneShortRead)
62 memset(
static_cast<char*
>(buf) + nRead, 0,
size - nRead);
63 pContext->bAllowOneShortRead =
false;
74static toff_t
tiff_seek(thandle_t handle, toff_t offset,
int whence)
76 Context* pContext =
static_cast<Context*
>(handle);
81 offset = pContext->nStart + offset;
84 offset = pContext->rStream.Tell() + offset;
87 offset = pContext->rStream.TellEnd() + offset;
90 assert(
false &&
"unknown seek type");
94 pContext->rStream.Seek(offset);
96 return offset - pContext->nStart;
106 Context* pContext =
static_cast<Context*
>(handle);
107 return pContext->nSize;
112 auto origErrorHandler = TIFFSetErrorHandler(
nullptr);
113 auto origWarningHandler = TIFFSetWarningHandler(
nullptr);
115 TIFFSetErrorHandler(origErrorHandler);
116 TIFFSetWarningHandler(origWarningHandler);
119 Context aContext(rTIFF);
120 TIFF* tif = TIFFClientOpen(
"libtiff-svstream",
"r", &aContext,
128 const auto nOrigPos = rTIFF.
Tell();
133 uint64_t nTotalPixelsRequired = 0;
139 if (TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &
w) != 1)
141 SAL_WARN(
"filter.tiff",
"missing width");
145 if (TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &
h) != 1)
147 SAL_WARN(
"filter.tiff",
"missing height");
153 SAL_WARN(
"filter.tiff",
"image too large");
157 uint32_t nPixelsRequired;
159 constexpr size_t nMaxPixelsAllowed = (256 * 1024 * 1024) / 4;
162 SAL_WARN_IF(!bOk,
"filter.tiff",
"skipping oversized tiff image " <<
w <<
" x " <<
h);
164 if (!TIFFIsTiled(tif))
166 size_t nStripSize = TIFFStripSize(tif);
169 SAL_WARN(
"filter.tiff",
"skipping oversized tiff strip size " << nStripSize);
176 const uint64_t MAX_PIXEL_SIZE = 120000000;
177 const uint64_t MAX_TILE_SIZE = 100000000;
178 nTotalPixelsRequired += nPixelsRequired;
179 if (TIFFTileSize64(tif) > MAX_TILE_SIZE || nTotalPixelsRequired > MAX_PIXEL_SIZE)
181 SAL_WARN(
"filter.tiff",
"skipping large tiffs");
185 if (TIFFIsTiled(tif))
188 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
189 TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
191 if (tw >
w || th >
h)
193 bOk = th < 1000 * tw && tw < 1000 * th;
194 SAL_WARN_IF(!bOk,
"filter.tiff",
"skipping slow bizarre ratio tile of " << tw <<
" x " << th <<
" for image of " <<
w <<
" x " <<
h);
202 uint32_t nLogLBufferRequired;
204 SAL_WARN_IF(!bOk,
"filter.tiff",
"skipping oversized tiff tile " << tw <<
" x " << th);
209 if (TIFFGetField(tif, TIFFTAG_COMPRESSION, &
Compression) == 1)
215 SAL_WARN_IF(!bOk,
"filter.tiff",
"skipping oversized tiff tile width: " << tw);
224 std::vector<uint32_t> raster(nPixelsRequired);
225 aContext.bAllowOneShortRead =
true;
226 if (TIFFReadRGBAImageOriented(tif,
w,
h, raster.data(), ORIENTATION_TOPLEFT, 1))
232 SAL_WARN(
"filter.tiff",
"cannot create image " <<
w <<
" x " <<
h);
240 SAL_WARN(
"filter.tiff",
"cannot create alpha " <<
w <<
" x " <<
h);
254 uint16_t nOrientation;
255 if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &nOrientation) != 1)
258 for (uint32_t
y = 0;
y <
h; ++
y)
260 const uint32_t* src = raster.data() +
w *
y;
261 for (uint32_t
x = 0;
x <
w; ++
x)
269 switch (nOrientation)
271 case ORIENTATION_LEFTBOT:
279 access->SetPixel(
y, dest,
Color(r, g, b));
280 accessAlpha->SetPixelIndex(
y, dest,
a);
290 BitmapEx aBitmapEx(bitmap, bitmapAlpha);
294 switch (nOrientation)
296 case ORIENTATION_LEFTBOT:
308 float xres = 0, yres = 0;
310 if (TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) == 1 &&
311 TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) == 1 &&
312 xres != 0 && yres != 0)
325 aAnimation.
Insert(aAnimationFrame);
329 }
while (TIFFReadDirectory(tif));
333 const auto nImages = aAnimation.
Count();
339 rGraphic = aAnimation;
347 rTIFF.
Seek(nOrigPos);
#define ANIMATION_TIMEOUT_ON_CLICK
const BitmapEx & GetBitmapEx() const
bool Insert(const AnimationFrame &rAnimationFrame)
void SetPrefMapMode(const MapMode &rPrefMapMode)
void SetPrefSize(const Size &rPrefSize)
bool Rotate(Degree10 nAngle10, const Color &rFillColor)
Rotate bitmap by the specified angle.
const Size & GetSizePixel() const
sal_uInt64 Seek(sal_uInt64 nPos)
This template handles BitmapAccess the RAII way.
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
#define PhotometricInterpretation
static tsize_t tiff_write(thandle_t, tdata_t, tsize_t)
static int tiff_close(thandle_t)
static toff_t tiff_size(thandle_t handle)
static toff_t tiff_seek(thandle_t handle, toff_t offset, int whence)
bool ImportTiffGraphicImport(SvStream &rTIFF, Graphic &rGraphic)
static tsize_t tiff_read(thandle_t handle, tdata_t buf, tsize_t size)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
std::enable_if< std::is_signed< T >::value, bool >::type checked_multiply(T a, T b, T &result)
#define STREAM_SEEK_TO_END