24 private const EXPENSIVE_SIZE_LIMIT = 10_485_760;
27 private const STATE_DJVU_IMAGE =
'djvuImage';
28 private const STATE_TEXT_TREE =
'djvuTextTree';
29 private const STATE_META_TREE =
'djvuMetaTree';
30 private const CACHE_VERSION =
'v2';
38 if ( !$djvuRenderer || !$djvuDump ) {
40 wfDebug(
"DjVu is disabled, please set \$wgDjvuRenderer and \$wgDjvuDump" );
62 return $file->getSize() > static::EXPENSIVE_SIZE_LIMIT;
78 'img_width' =>
'width',
85 if ( $name ===
'page' ) {
86 return is_int( $value ) ||
89 ( is_string( $value ) && trim( $value ) === (string)intval( $value ) );
91 return in_array( $name, [
'width',
'height',
'page',
'physicalWidth',
'physicalHeight' ] ) &&
100 $page = $params[
'page'] ?? 1;
101 $width = $params[
'physicalWidth'] ?? $params[
'width'] ??
null;
106 return "page{$page}-{$width}px";
115 if ( preg_match(
'/^page(\d+)-(\d+)px$/', $str, $m ) ) {
116 return [
'width' => $m[2],
'page' => $m[1] ];
127 if ( !parent::normaliseParams( $image, $params ) ) {
130 $srcWidth = $image->getWidth( $params[
'page'] );
131 $srcHeight = $image->getHeight( $params[
'page'] );
133 $image, $params[
'physicalWidth'], $srcWidth, $srcHeight
135 $params[
'physicalHeight'] = File::scaleHeight( $srcWidth, $srcHeight, $params[
'physicalWidth'] );
145 'width' => $params[
'width'],
146 'page' => $params[
'page'],
158 public function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) {
165 $width = $params[
'width'];
166 $height = $params[
'height'];
167 $page = $params[
'page'];
169 if ( $flags & self::TRANSFORM_LATER ) {
193 if ( $image->getSize() >= 1e7 ) {
196 'doWork' =>
static function () use ( $image ) {
197 return $image->getLocalRefPath();
203 $srcPath = $image->getLocalRefPath();
206 if ( $srcPath ===
false ) {
210 sprintf(
'Thumbnail failed on %s: could not get local copy of "%s"',
214 $params[
'width'], $params[
'height'],
222 $cmd =
'(' . Shell::escape(
226 "-size={$params['physicalWidth']}x{$params['physicalHeight']}",
228 if ( $djvuPostProcessor ) {
229 $cmd .=
" | {$djvuPostProcessor}";
231 $cmd .=
' > ' . Shell::escape( $dstPath ) .
') 2>&1';
232 wfDebug( __METHOD__ .
": $cmd" );
233 $shell = Shell::command()->unsafeCommand( $cmd )->execute();
234 $retval = $shell->getExitCode();
235 $err = $shell->getStderr();
238 if ( ( $retval !== 0 || $removed ) && $retval !==
null ) {
258 $deja = $state->getHandlerState( self::STATE_DJVU_IMAGE );
273 private function getMetadataInternal( File $file,
bool $gettext ) {
274 $itemNames = [
'error',
'_error',
'data' ];
276 $itemNames[] =
'text';
278 $unser = $file->getMetadataItems( $itemNames );
280 if ( isset( $unser[
'error'] ) ) {
283 if ( isset( $unser[
'_error'] ) ) {
296 if ( $gettext && $image->getHandlerState( self::STATE_TEXT_TREE ) ) {
297 return $image->getHandlerState( self::STATE_TEXT_TREE );
299 if ( !$gettext && $image->getHandlerState( self::STATE_META_TREE ) ) {
300 return $image->getHandlerState( self::STATE_META_TREE );
303 $metadata = $this->getMetadataInternal( $image, $gettext );
309 unset( $metadata[
'text'] );
318 static $djvuMime =
null;
319 if ( $djvuMime ===
null ) {
321 $djvuMime = $magic->getMimeTypeFromExtensionOrNull( $djvuOutputExtension );
324 return [ $djvuOutputExtension, $djvuMime ];
329 wfDebug(
"Getting DjVu metadata for $path" );
331 $djvuImage = $this->getDjVuImage( $state,
$path );
332 $metadata = $djvuImage->retrieveMetaData();
333 if ( $metadata ===
false ) {
335 $metadata = [
'error' =>
'Error extracting metadata' ];
337 return [
'metadata' => $metadata ] + $djvuImage->getImageSize();
348 return $image->getMetadataArray() ? self::METADATA_GOOD : self::METADATA_BAD;
353 $info = $this->getDimensionInfo( $image );
355 return $info ? $info[
'pageCount'] :
false;
362 $info = $this->getDimensionInfo( $image );
363 if ( $info && isset( $info[
'dimensionsByPage'][$index] ) ) {
364 return $info[
'dimensionsByPage'][$index];
373 return $cache->getWithSetCallback(
374 $cache->makeKey(
'file-djvu',
'dimensions', self::CACHE_VERSION, $file->
getSha1() ),
375 $cache::TTL_INDEFINITE,
376 function () use ( $file ) {
377 $tree = $this->getMetaTree( $file );
378 return $this->getDimensionInfoFromMetaTree( $tree );
380 [
'pcTTL' => $cache::TTL_INDEFINITE ]
395 if ( !isset( $metatree[
'data'] ) || !$metatree[
'data'] ) {
398 foreach ( $metatree[
'data'][
'pages'] as $page ) {
400 $dimsByPage[] =
false;
403 'width' => (int)$page[
'width'],
404 'height' => (
int)$page[
'height'],
409 'pageCount' => count( $metatree[
'data'][
'pages'] ),
410 'dimensionsByPage' => $dimsByPage
420 $tree = $this->getMetaTree( $image,
true );
424 if ( isset( $tree[
'text'] ) && isset( $tree[
'text'][$page - 1] ) ) {
425 return $tree[
'text'][$page - 1];
437class_alias( DjVuHandler::class,
'DjVuHandler' );
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfHostname()
Get host name of the current machine, for use in error reporting.
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
A class containing constants representing the names of configuration variables.
const DjvuPostProcessor
Name constant for the DjvuPostProcessor setting, for use with Config::get()
const DjvuDump
Name constant for the DjvuDump setting, for use with Config::get()
const DjvuRenderer
Name constant for the DjvuRenderer setting, for use with Config::get()
const DjvuOutputExtension
Name constant for the DjvuOutputExtension setting, for use with Config::get()