r104390 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r104389‎ | r104390 | r104391 >
Date:05:06, 28 November 2011
Author:tstarling
Status:ok
Tags:
Comment:
Copied VipsScaler from trunk
Modified paths:
  • /branches/wmf/1.18wmf1/extensions/VipsScaler (added) (history)

Diff [purge]

Index: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsScaler.i18n.php
@@ -0,0 +1,402 @@
 2+<?php
 3+/**
 4+ * Internationalisation file for extension VipsScaler.
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$messages = array();
 11+
 12+$messages['en'] = array(
 13+ 'vipstest' => 'VIPS scaling test page',
 14+
 15+ 'vipsscaler-desc' => 'Create thumbnails using VIPS',
 16+ 'vipsscaler-invalid-file' => 'Could not process requested file. Check that it exists on this wiki.',
 17+ 'vipsscaler-invalid-width' => 'Thumbnail width should be larger than zero and not larger than file width.',
 18+ 'vipsscaler-invalid-sharpen' => 'Sharpening amount should be a number larger than zero and smaller than five.',
 19+ 'vipsscaler-thumb-error' => 'VIPS could not generate a thumbnail with given parameters.',
 20+
 21+ # Vipscaler test form:
 22+ 'vipsscaler-form-legend' => 'VIPS scaling',
 23+ 'vipsscaler-form-width' => 'Thumbnail width:',
 24+ 'vipsscaler-form-file' => 'File on this wiki:',
 25+ 'vipsscaler-form-sharpen-radius' => 'Amount of sharpening:',
 26+ 'vipsscaler-form-bilinear' => 'Bilinear scaling',
 27+ 'vipsscaler-form-submit' => 'Generate thumbnails',
 28+
 29+ 'vipsscaler-default-thumb' => 'Thumbnail generated with default scaler',
 30+ 'vipsscaler-vips-thumb' => 'Thumbnail generated with VIPS',
 31+
 32+ 'vipsscaler-show-both' => 'Show both thumbnails',
 33+ 'vipsscaler-show-default' => 'Show default thumbnail only',
 34+ 'vipsscaler-show-vips' => 'Show VIPS thumbnail only',
 35+
 36+ # User rights
 37+ 'right-vipsscaler-test' => 'Use the VIPS scaling test interface [[Special:VipsTest]]',
 38+);
 39+
 40+/** Message documentation (Message documentation)
 41+ * @author Purodha
 42+ * @author Umherirrender
 43+ */
 44+$messages['qqq'] = array(
 45+ 'vipstest' => 'Title of the Special:VipsTest page',
 46+ 'vipsscaler-desc' => '{{desc}}',
 47+ 'vipsscaler-invalid-file' => 'Error message when SpecialVipsTest was given a non existent or invalid file name',
 48+ 'vipsscaler-invalid-width' => 'Error message when SpecialVipsTest did not get a valid width parameter',
 49+ 'vipsscaler-thumb-error' => 'Error message when VIPS did not manage to generate a thumbnail',
 50+ 'vipsscaler-form-legend' => 'Special:VipsTest form: legend at top of the form',
 51+ 'vipsscaler-form-width' => 'Special:VipsTest form: label for the width input box',
 52+ 'vipsscaler-form-file' => 'Special:VipsTest form: label for the file input box',
 53+ 'vipsscaler-form-sharpen-radius' => 'Special:VipsTest form: label for the sharpening amount input box',
 54+ 'vipsscaler-form-bilinear' => 'Special:VipsTest form: Checkbox label to determine whether to enable bilinear scaling',
 55+ 'vipsscaler-form-submit' => 'Special:VipsTest form: submit button text. The page will then attempt to generate a thumbnail with the given parameters.',
 56+ 'vipsscaler-default-thumb' => 'Special:VipsTest: caption of the default thumbnail',
 57+ 'vipsscaler-vips-thumb' => 'Special:VipsTest: caption of the vips thumbnail',
 58+ 'vipsscaler-show-both' => 'Special:VipsTest: button to show both thumbnails',
 59+ 'vipsscaler-show-default' => 'Special:VipsTest: button to show default thumbnail only',
 60+ 'vipsscaler-show-vips' => 'Special:VipsTest: button to show VIPS thumbnail only',
 61+ 'right-vipsscaler-test' => '{{doc-right|vipsscaler-test}}',
 62+);
 63+
 64+/** Afrikaans (Afrikaans)
 65+ * @author Naudefj
 66+ */
 67+$messages['af'] = array(
 68+ 'vipsscaler-desc' => 'Skep duimnaels met behulp van VIPS.',
 69+);
 70+
 71+/** Asturian (Asturianu)
 72+ * @author Xuacu
 73+ */
 74+$messages['ast'] = array(
 75+ 'vipsscaler-desc' => 'Crear miniatures usando VIPS',
 76+);
 77+
 78+/** Belarusian (Taraškievica orthography) (‪Беларуская (тарашкевіца)‬)
 79+ * @author Wizardist
 80+ */
 81+$messages['be-tarask'] = array(
 82+ 'vipsscaler-desc' => 'Стварае мініятуры з дапамогай VIPS',
 83+);
 84+
 85+/** Breton (Brezhoneg)
 86+ * @author Fulup
 87+ */
 88+$messages['br'] = array(
 89+ 'vipsscaler-desc' => 'Krouiñ a ra munudoù en ur ober gant VIPS',
 90+ 'vipsscaler-form-file' => 'Restr er wiki-mañ :',
 91+);
 92+
 93+/** Bosnian (Bosanski)
 94+ * @author CERminator
 95+ */
 96+$messages['bs'] = array(
 97+ 'vipsscaler-desc' => 'Pravljenje smanjenog pregleda koristeći VIPS',
 98+);
 99+
 100+/** Danish (Dansk)
 101+ * @author Peter Alberti
 102+ */
 103+$messages['da'] = array(
 104+ 'vipstest' => 'Testside for skalering vha. VIPS',
 105+ 'vipsscaler-desc' => 'Opret miniaturebilleder ved hjælp af VIPS',
 106+ 'vipsscaler-invalid-file' => 'Ugyldig fil: kunne ikke behandle den angivne fil. Findes den på denne wiki?',
 107+ 'vipsscaler-invalid-width' => 'Du skal angive en bredde (heltal > 0).',
 108+ 'vipsscaler-thumb-error' => 'VIPS kunne ikke oprette et miniaturebillede med de angivne parametre.',
 109+ 'vipsscaler-form-legend' => 'Skalering vha. VIPS',
 110+ 'vipsscaler-form-width' => 'Miniaturebredde:',
 111+ 'vipsscaler-form-file' => 'Fil på denne wiki:',
 112+ 'vipsscaler-form-submit' => 'Opret miniature',
 113+ 'right-vipsscaler-test' => 'Brug brugerfladen til test af skalering ved hjælp af VIPS på [[Special:VipsTest]]',
 114+);
 115+
 116+/** German (Deutsch)
 117+ * @author Kghbln
 118+ */
 119+$messages['de'] = array(
 120+ 'vipstest' => 'Testseite zur VIPS-Skalierung',
 121+ 'vipsscaler-desc' => 'Ermöglicht das Erstellen von Miniaturbildern mit VIPS',
 122+ 'vipsscaler-invalid-file' => 'Die angeforderte Datei konnte nicht verarbeitet werden. Bitte überprüfen, ob Sie auf diesem Wiki vorhanden ist.',
 123+ 'vipsscaler-invalid-width' => 'Die Breite des Miniaturbildes sollte größer als Null und nicht größer als die Breite des Bildes sein.',
 124+ 'vipsscaler-invalid-sharpen' => 'Der Wert der Bildschärfe sollte größer als Null und kleiner als Fünf sein.',
 125+ 'vipsscaler-thumb-error' => 'VIPS konnte auf Basis der angegebenen Parameter kein Miniaturbild generieren.',
 126+ 'vipsscaler-form-legend' => 'VIPS-Skalierung',
 127+ 'vipsscaler-form-width' => 'Breite des Miniaturbildes:',
 128+ 'vipsscaler-form-file' => 'Datei in diesem Wiki:',
 129+ 'vipsscaler-form-sharpen-radius' => 'Wert der Bildschärfe:',
 130+ 'vipsscaler-form-bilinear' => 'Bilineare Skalierung',
 131+ 'vipsscaler-form-submit' => 'Miniaturbild generieren',
 132+ 'vipsscaler-default-thumb' => 'Das Miniaturbild wurde mit dem Standardsaklierungsprogramm generiert.',
 133+ 'vipsscaler-vips-thumb' => 'Das Miniaturbild wurde mit VIPS generiert.',
 134+ 'vipsscaler-show-both' => 'Beide Miniaturbilder anzeigen',
 135+ 'vipsscaler-show-default' => 'Nur das Standardminiaturbild anzeigen',
 136+ 'vipsscaler-show-vips' => 'Nur das VIPS-Miniaturbild anzeigen',
 137+ 'right-vipsscaler-test' => 'Nutze das Testinterface zur VIPS-Skalierung [[Special:VipsTest]]',
 138+);
 139+
 140+/** German (formal address) (‪Deutsch (Sie-Form)‬)
 141+ * @author Kghbln
 142+ */
 143+$messages['de-formal'] = array(
 144+ 'right-vipsscaler-test' => 'Nutzen Sie das Testinterface zur VIPS-Skalierung [[Special:VipsTest]]',
 145+);
 146+
 147+/** French (Français)
 148+ * @author Gomoko
 149+ * @author IAlex
 150+ */
 151+$messages['fr'] = array(
 152+ 'vipstest' => "Page de test de la mise à l'échelle de VIPS",
 153+ 'vipsscaler-desc' => "Créer des miniatures à l'aide de VIPS",
 154+ 'vipsscaler-invalid-file' => "Impossible de traiter le fichier demandé. Vérifiez qu'il existe sur ce wiki.",
 155+ 'vipsscaler-invalid-width' => 'La largeur de la vignette doit être supérieure à zéro et pas supérieure à la largeur du fichier.',
 156+ 'vipsscaler-invalid-sharpen' => 'La quantité de netteté doit être un nombre plus grand que zéro et plus petit que cinq.',
 157+ 'vipsscaler-thumb-error' => "VIPS n'a pas pu générer une miniature avec les paramètres fournis.",
 158+ 'vipsscaler-form-legend' => "Mise à l'échelle de VIPS",
 159+ 'vipsscaler-form-width' => 'Largeur de la miniature :',
 160+ 'vipsscaler-form-file' => 'Fichier sur ce wiki :',
 161+ 'vipsscaler-form-sharpen-radius' => 'Montant de netteté :',
 162+ 'vipsscaler-form-bilinear' => "Mise à l'échelle bilinéaire",
 163+ 'vipsscaler-form-submit' => 'Générer la vignette',
 164+ 'vipsscaler-default-thumb' => "Vignette générée avec une mise à l'échelle par défaut",
 165+ 'vipsscaler-vips-thumb' => 'Vignette générée avec VIPS',
 166+ 'vipsscaler-show-both' => 'Afficher les deux vignettes',
 167+ 'vipsscaler-show-default' => 'Afficher uniquement la vignette par défaut',
 168+ 'vipsscaler-show-vips' => 'Afficher uniquement la vignette VIPS',
 169+ 'right-vipsscaler-test' => "Utiliser l'interface de test de mise à l'échelle de VIP [[Special:VipsTest]]",
 170+);
 171+
 172+/** Franco-Provençal (Arpetan)
 173+ * @author ChrisPtDe
 174+ */
 175+$messages['frp'] = array(
 176+ 'vipsscaler-desc' => 'Fât des figures avouéc VIPS.',
 177+);
 178+
 179+/** Galician (Galego)
 180+ * @author Toliño
 181+ */
 182+$messages['gl'] = array(
 183+ 'vipstest' => 'Páxina de probas da escala de VIPS',
 184+ 'vipsscaler-desc' => 'Crear miniaturas utilizando VIPS',
 185+ 'vipsscaler-invalid-file' => 'Non se puido procesar o ficheiro solicitado. Comprobe que existe neste wiki.',
 186+ 'vipsscaler-invalid-width' => 'O largo da miniatura debe ser maior que cero e non pode superar o largo do ficheiro.',
 187+ 'vipsscaler-invalid-sharpen' => 'A cantidade de agudización debe ser un número maior que cero e menor que cinco.',
 188+ 'vipsscaler-thumb-error' => 'VIPS non pode xerar unha miniatura cos parámetros proporcionados.',
 189+ 'vipsscaler-form-legend' => 'Escala de VIPS',
 190+ 'vipsscaler-form-width' => 'Largo da miniatura:',
 191+ 'vipsscaler-form-file' => 'Ficheiro neste wiki:',
 192+ 'vipsscaler-form-sharpen-radius' => 'Cantidade de agudización:',
 193+ 'vipsscaler-form-bilinear' => 'Escala bilinear',
 194+ 'vipsscaler-form-submit' => 'Xerar a miniatura',
 195+ 'vipsscaler-default-thumb' => 'Miniatura xerada coa escala por defecto',
 196+ 'vipsscaler-vips-thumb' => 'Miniatura xerada con VIPS',
 197+ 'vipsscaler-show-both' => 'Mostrar ambas as miniaturas',
 198+ 'vipsscaler-show-default' => 'Mostrar só a miniatura por defecto',
 199+ 'vipsscaler-show-vips' => 'Mostrar só a miniatura de VIPS',
 200+ 'right-vipsscaler-test' => 'Utilizar a interface de probas de escala de VIPS, [[Special:VipsTest]]',
 201+);
 202+
 203+/** Hebrew (עברית)
 204+ * @author Amire80
 205+ */
 206+$messages['he'] = array(
 207+ 'vipsscaler-desc' => 'יצירות תמונות ממוזערות באמצעות VIPS',
 208+);
 209+
 210+/** Upper Sorbian (Hornjoserbsce)
 211+ * @author Michawiki
 212+ */
 213+$messages['hsb'] = array(
 214+ 'vipsscaler-desc' => 'Přehladowe wobrazki z pomocu VIPS wutworić',
 215+);
 216+
 217+/** Interlingua (Interlingua)
 218+ * @author McDutchie
 219+ */
 220+$messages['ia'] = array(
 221+ 'vipstest' => 'Pagina de test pro scalation VIPS',
 222+ 'vipsscaler-desc' => 'Crear miniaturas con VIPS',
 223+ 'vipsscaler-invalid-file' => 'Non poteva processar le file requestate. Verifica que illo existe in iste wiki.',
 224+ 'vipsscaler-invalid-width' => 'Le latitude del miniatura debe esser superior a zero e non superior al latitude del file.',
 225+ 'vipsscaler-invalid-sharpen' => 'Le quantitate de acutiamento debe esser un numero superior a zero e inferior a cinque.',
 226+ 'vipsscaler-thumb-error' => 'VIPS non poteva generar un miniatura con le parametros specificate.',
 227+ 'vipsscaler-form-legend' => 'Scalation VIPS',
 228+ 'vipsscaler-form-width' => 'Latitude del miniatura:',
 229+ 'vipsscaler-form-file' => 'File in iste wiki:',
 230+ 'vipsscaler-form-sharpen-radius' => 'Quantitate de acutiamento:',
 231+ 'vipsscaler-form-bilinear' => 'Redimensionamento bilinear',
 232+ 'vipsscaler-form-submit' => 'Generar miniatura',
 233+ 'vipsscaler-default-thumb' => 'Miniatura generate con redimensionator predefinite',
 234+ 'vipsscaler-vips-thumb' => 'Miniatura generate con VIPS',
 235+ 'vipsscaler-show-both' => 'Monstrar ambe miniaturas',
 236+ 'vipsscaler-show-default' => 'Monstrar miniatura predefinite solmente',
 237+ 'vipsscaler-show-vips' => 'Monstrar miniatura VIPS solmente',
 238+ 'right-vipsscaler-test' => 'Usar le interfacie de test pro scalation VIPS [[Special:VipsTest]]',
 239+);
 240+
 241+/** Indonesian (Bahasa Indonesia)
 242+ * @author IvanLanin
 243+ */
 244+$messages['id'] = array(
 245+ 'vipsscaler-desc' => 'Membuat gambar mini dengan menggunakan VIPS',
 246+);
 247+
 248+/** Italian (Italiano)
 249+ * @author Beta16
 250+ */
 251+$messages['it'] = array(
 252+ 'vipsscaler-desc' => 'Crea miniature utilizzando VIPS',
 253+);
 254+
 255+/** Japanese (日本語)
 256+ * @author Schu
 257+ */
 258+$messages['ja'] = array(
 259+ 'vipsscaler-desc' => 'VIPS を用いてサムネイルを作成します。',
 260+);
 261+
 262+/** Colognian (Ripoarisch)
 263+ * @author Purodha
 264+ */
 265+$messages['ksh'] = array(
 266+ 'vipsscaler-desc' => 'Minibeldsche met <i lang="en">VIPS</i> maache.',
 267+);
 268+
 269+/** Luxembourgish (Lëtzebuergesch)
 270+ * @author Robby
 271+ */
 272+$messages['lb'] = array(
 273+ 'vipsscaler-desc' => 'Miniaturbiller mat VIPS maachen',
 274+ 'vipsscaler-form-file' => 'Fichier an dëser Wiki:',
 275+);
 276+
 277+/** Macedonian (Македонски)
 278+ * @author Bjankuloski06
 279+ */
 280+$messages['mk'] = array(
 281+ 'vipstest' => 'Проба за менување на размер со VIPS',
 282+ 'vipsscaler-desc' => 'Создавање на минијатури со VIPS',
 283+ 'vipsscaler-invalid-file' => 'Не можев да ја обработам бараната податотека. Проверете дали воопшто постои на ова вики.',
 284+ 'vipsscaler-invalid-width' => 'Минијатурата мора да е поширока од нула, а потесна од изворната ширина на податотеката.',
 285+ 'vipsscaler-invalid-sharpen' => 'Изострувањето треба да е поголемо од нула а помало од пет.',
 286+ 'vipsscaler-thumb-error' => 'VIPS не можеше да создаде минијатура со зададените параметри.',
 287+ 'vipsscaler-form-legend' => 'Менување големина со VIPS',
 288+ 'vipsscaler-form-width' => 'Ширина на минијатурата:',
 289+ 'vipsscaler-form-file' => 'Податотека на ова вики:',
 290+ 'vipsscaler-form-sharpen-radius' => 'Изострување:',
 291+ 'vipsscaler-form-bilinear' => 'Билинеарно размерување',
 292+ 'vipsscaler-form-submit' => 'Создај минијатура',
 293+ 'vipsscaler-default-thumb' => 'Минијатура создадена со основно-зададениот размерител',
 294+ 'vipsscaler-vips-thumb' => 'Минијатура создадена со VIPS',
 295+ 'vipsscaler-show-both' => 'Прикажи ги двете минијатури',
 296+ 'vipsscaler-show-default' => 'Прикажи ја само основната минијатура',
 297+ 'vipsscaler-show-vips' => 'Прикажи ја само минијатурата од VIPS',
 298+ 'right-vipsscaler-test' => 'Употреба на го посредникот [[Special:VipsTest]] за испробување на менување големина со VIPS',
 299+);
 300+
 301+/** Malay (Bahasa Melayu)
 302+ * @author Anakmalaysia
 303+ */
 304+$messages['ms'] = array(
 305+ 'vipsscaler-desc' => 'Cipta gambar kenit dengan VIPS',
 306+);
 307+
 308+/** Dutch (Nederlands)
 309+ * @author Saruman
 310+ * @author Siebrand
 311+ */
 312+$messages['nl'] = array(
 313+ 'vipstest' => 'Testpagina voor VIPS-transformaties',
 314+ 'vipsscaler-desc' => 'Miniaturen van bestanden aanmaken met VIPS',
 315+ 'vipsscaler-invalid-file' => 'Het was niet mogelijk het gevraagde bestand te verwerken. Controleer of het binnen deze wiki aanwezig is.',
 316+ 'vipsscaler-invalid-width' => 'De breedte van de miniatuur moet groter zijn dan 0 en niet groter dan de breedte van het bestand.',
 317+ 'vipsscaler-invalid-sharpen' => 'De hoeveelheid verscherping moet een getal zijn dat groter is dan nul en kleiner is dan vijf.',
 318+ 'vipsscaler-thumb-error' => 'VIPS kon geen miniatuur genereren met de opgegeven parameters.',
 319+ 'vipsscaler-form-legend' => 'VIPS-transformaties',
 320+ 'vipsscaler-form-width' => 'Breedte miniatuur:',
 321+ 'vipsscaler-form-file' => 'Bestand op deze wiki:',
 322+ 'vipsscaler-form-sharpen-radius' => 'Hoeveelheid verscherping:',
 323+ 'vipsscaler-form-bilinear' => 'Bilineair schalen',
 324+ 'vipsscaler-form-submit' => 'Miniatuur genereren',
 325+ 'vipsscaler-default-thumb' => 'Er is een miniatuurafbeelding aangemaakt met de standaard opschaler',
 326+ 'vipsscaler-vips-thumb' => 'Er is een miniatuurafbeelding aangemaakt met VIPS',
 327+ 'vipsscaler-show-both' => 'Beide miniatuurafbeeldingen weergeven',
 328+ 'vipsscaler-show-default' => 'Alleen de standaard miniatuurafbeelding weergeven',
 329+ 'vipsscaler-show-vips' => 'Alleen de VIPS-miniatuurafbeelding weergeven',
 330+ 'right-vipsscaler-test' => 'Gebruik de [[Special:VipsTest|testinterface voor VIPS-transformaties]]',
 331+);
 332+
 333+/** Norwegian (bokmål)‬ (‪Norsk (bokmål)‬)
 334+ * @author Nghtwlkr
 335+ */
 336+$messages['no'] = array(
 337+ 'vipsscaler-desc' => 'Opprett miniatyrbilder med VIPS',
 338+);
 339+
 340+/** Polish (Polski)
 341+ * @author Woytecr
 342+ */
 343+$messages['pl'] = array(
 344+ 'vipsscaler-desc' => 'Tworzy miniaturki korzystając z VIPS',
 345+);
 346+
 347+/** Piedmontese (Piemontèis)
 348+ * @author Borichèt
 349+ * @author Dragonòt
 350+ */
 351+$messages['pms'] = array(
 352+ 'vipsscaler-desc' => 'Creé dle miniadure dovrand VIPS',
 353+);
 354+
 355+/** Portuguese (Português)
 356+ * @author Hamilton Abreu
 357+ */
 358+$messages['pt'] = array(
 359+ 'vipsscaler-desc' => 'Criar miniaturas usando VIPS',
 360+);
 361+
 362+/** Tarandíne (Tarandíne)
 363+ * @author Joetaras
 364+ */
 365+$messages['roa-tara'] = array(
 366+ 'vipsscaler-desc' => 'Ccreje le miniature ausanne VIPS',
 367+);
 368+
 369+/** Russian (Русский)
 370+ * @author Александр Сигачёв
 371+ */
 372+$messages['ru'] = array(
 373+ 'vipsscaler-desc' => 'Создаёт миниатюры с помощью VIPS',
 374+);
 375+
 376+/** Slovenian (Slovenščina)
 377+ * @author Dbc334
 378+ */
 379+$messages['sl'] = array(
 380+ 'vipsscaler-desc' => 'Ustvari sličice z VIPS',
 381+);
 382+
 383+/** Serbian (Cyrillic script) (‪Српски (ћирилица)‬)
 384+ * @author Rancher
 385+ */
 386+$messages['sr-ec'] = array(
 387+ 'vipsscaler-desc' => 'Прављење умањених приказа слика користећи VIPS',
 388+);
 389+
 390+/** Telugu (తెలుగు)
 391+ * @author Veeven
 392+ */
 393+$messages['te'] = array(
 394+ 'vipsscaler-desc' => 'VIPSని ఉపయోగించి నఖచిత్రాలను తయారుచేయండి',
 395+);
 396+
 397+/** Tagalog (Tagalog)
 398+ * @author AnakngAraw
 399+ */
 400+$messages['tl'] = array(
 401+ 'vipsscaler-desc' => 'Lumikha ng mga kagyat na ginagamit ang VIPS',
 402+);
 403+
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsScaler.i18n.php
___________________________________________________________________
Added: svn:eol-style
1404 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsScaler.php
@@ -0,0 +1,107 @@
 2+<?php
 3+/**
 4+ * Copyright © Bryan Tong Minh, 2011
 5+ *
 6+ * This program is free software; you can redistribute it and/or modify
 7+ * it under the terms of the GNU General Public License as published by
 8+ * the Free Software Foundation; either version 2 of the License, or
 9+ * (at your option) any later version.
 10+ *
 11+ * This program is distributed in the hope that it will be useful,
 12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 14+ * GNU General Public License for more details.
 15+ *
 16+ * You should have received a copy of the GNU General Public License along
 17+ * with this program; if not, write to the Free Software Foundation, Inc.,
 18+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 19+ * http://www.gnu.org/copyleft/gpl.html
 20+ *
 21+ * @file
 22+ */
 23+
 24+$wgExtensionCredits['media'][] = array(
 25+ 'path' => __FILE__,
 26+ 'name' => 'VipsScaler',
 27+ 'author' => array( 'Bryan Tong Minh' ),
 28+ 'descriptionmsg' => 'vipsscaler-desc',
 29+ 'url' => 'http://www.mediawiki.org/wiki/VipsScaler',
 30+);
 31+
 32+$dir = dirname( __FILE__ );
 33+
 34+$wgAutoloadClasses['VipsScaler'] = "$dir/VipsScaler_body.php";
 35+$wgAutoloadClasses['VipsCommand'] = "$dir/VipsScaler_body.php";
 36+$wgAutoloadClasses['VipsConvolution'] = "$dir/VipsScaler_body.php";
 37+
 38+$wgExtensionMessagesFiles['VipsScaler'] = "$dir/VipsScaler.i18n.php";
 39+
 40+$wgHooks['BitmapHandlerTransform'][] = 'VipsScaler::onTransform';
 41+$wgHooks['BitmapHandlerCheckImageArea'][] = 'VipsScaler::onBitmapHandlerCheckImageArea';
 42+
 43+# Download vips from http://www.vips.ecs.soton.ac.uk/
 44+$wgVipsCommand = 'vips';
 45+
 46+/* Options and conditions for images to be scaled with this scaler.
 47+ * Set to an array of arrays. The inner array contains a condition array, which
 48+ * contains a list of conditions that the image should pass for it to be scaled
 49+ * with vips. Conditions are mimeType, minArea, maxArea, minShrinkFactor,
 50+ * maxShrinkFactor. The other items in the array are options. Options available
 51+ * are:
 52+ * - sharpen: Set to an array with keys 'radius' and 'sigma', which are
 53+ * parameters to gaussian sharpen matrix.
 54+ * - preconvert: Convert the file to a .v file first, which costs some space,
 55+ * but saves memory on the actual downsize
 56+ * - bilinear: Use im_resize_linear instead of im_shrink
 57+ * - convolution: Apply specified convolution matrix
 58+ * - setcomment: Add an exif comment specifying the source of the file.
 59+ * Requires $wgExiv2Command to be set properly.
 60+ */
 61+$wgVipsOptions = array(
 62+ # Sharpen jpeg files which are shrunk more than 1.2
 63+ array(
 64+ 'conditions' => array(
 65+ 'mimeType' => 'image/jpeg',
 66+ 'minShrinkFactor' => 1.2,
 67+ ),
 68+ 'sharpen' => array( 'radius' => 0, 'sigma' => 0.8 ),
 69+ ),
 70+ # Other jpeg files
 71+ array(
 72+ 'conditions' => array(
 73+ 'mimeType' => 'image/jpeg',
 74+ ),
 75+ 'sharpen' => false,
 76+ 'bilinear' => true,
 77+ ),
 78+ # Do a simple shrink for PNGs
 79+ array(
 80+ 'conditions' => array(
 81+ 'mimeType' => 'image/png',
 82+ ),
 83+ ),
 84+);
 85+
 86+# Package vipsScaler material in a resource loader module:
 87+$wgResourceModules['ext.vipsscaler'] = array(
 88+ 'scripts' => array( 'ext.vipsScaler.js', ),
 89+ 'styles' => array( 'ext.vipsScaler.css' ),
 90+ 'messages' => array( 'vipsscaler-show-both', 'vipsscaler-show-default', 'vipsscaler-show-vips' ),
 91+ 'dependencies' => array(
 92+ 'jquery.ucompare',
 93+ ),
 94+
 95+ 'localBasePath' => dirname( __FILE__ ) . '/modules/ext.vipsScaler',
 96+ 'remoteExtPath' => 'VipsScaler/modules/ext.vipsScaler',
 97+);
 98+
 99+# Also package upstream jquery.ucompare
 100+$wgResourceModules['jquery.ucompare'] = array(
 101+ 'scripts' => array( 'js/jquery.ucompare.js', ),
 102+ 'styles' => array( 'css/jquery.ucompare.css' ),
 103+
 104+ 'localBasePath' => dirname( __FILE__ ) . '/modules/jquery.ucompare',
 105+ 'remoteExtPath' => 'VipsScaler/modules/jquery.ucompare'
 106+);
 107+
 108+
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsScaler.php
___________________________________________________________________
Added: svn:eol-style
1109 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsTest.php
@@ -0,0 +1,33 @@
 2+<?php
 3+
 4+/**
 5+ * Extension registration file for Special:VipsTest. The VipsScaler extension
 6+ * must be enabled.
 7+ */
 8+
 9+if ( !defined( 'MEDIAWIKI' ) ) exit( 1 );
 10+
 11+/**
 12+ * The host to send the request to when doing the scaling remotely. Set this to
 13+ * null to do the scaling on the same server that receives the request.
 14+ */
 15+$wgVipsThumbnailerHost = null;
 16+
 17+/**
 18+ * The cache expiry time in seconds to use for images that we stream out.
 19+ */
 20+$wgVipsTestExpiry = 3600;
 21+
 22+/** Registration */
 23+$wgAutoloadClasses['SpecialVipsTest'] = "$dir/SpecialVipsTest.php";
 24+$wgExtensionAliasesFiles['VipsTest'] = "$dir/VipsScaler.alias.php";
 25+$wgAvailableRights[] = 'vipsscaler-test';
 26+$wgGroupPermissions['*']['vipsscaler-test'] = true;
 27+$wgSpecialPages['VipsTest'] = 'SpecialVipsTest';
 28+
 29+/**
 30+ * Disable VipsScaler for ordinary image scaling so that the test has something
 31+ * to compare against.
 32+ */
 33+$wgVipsOptions = array();
 34+
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsTest.php
___________________________________________________________________
Added: svn:eol-style
135 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/SpecialVipsTest.php
@@ -0,0 +1,363 @@
 2+<?php
 3+/*
 4+ * Copyright © Bryan Tong Minh, 2011
 5+ *
 6+ * This program is free software; you can redistribute it and/or modify
 7+ * it under the terms of the GNU General Public License as published by
 8+ * the Free Software Foundation; either version 2 of the License, or
 9+ * (at your option) any later version.
 10+ *
 11+ * This program is distributed in the hope that it will be useful,
 12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 14+ * GNU General Public License for more details.
 15+ *
 16+ * You should have received a copy of the GNU General Public License along
 17+ * with this program; if not, write to the Free Software Foundation, Inc.,
 18+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 19+ * http://www.gnu.org/copyleft/gpl.html
 20+ *
 21+ * @file
 22+ */
 23+
 24+/**
 25+ * A Special page intended to test the VipsScaler.
 26+ * @author Bryan Tong Minh
 27+ */
 28+class SpecialVipsTest extends SpecialPage {
 29+ public function __construct() {
 30+ parent::__construct( 'VipsTest', 'vipsscaler-test' );
 31+ }
 32+
 33+ /**
 34+ * Entry point
 35+ * @param $par Array TODO describe what is expected there
 36+ */
 37+ public function execute( $par ) {
 38+ $request = $this->getRequest();
 39+ $this->setHeaders();
 40+
 41+ if( !$this->userCanExecute( $this->getUser() ) ) {
 42+ $this->displayRestrictionError();
 43+ return;
 44+ }
 45+
 46+ if ( $request->getText( 'thumb' ) ) {
 47+ $this->streamThumbnail();
 48+ } else {
 49+ $this->showForm();
 50+ }
 51+ }
 52+
 53+ /**
 54+ */
 55+ protected function showThumbnails() {
 56+ $request = $this->getRequest();
 57+
 58+ # Check if valid file was provided
 59+ $title = Title::makeTitleSafe( NS_FILE, $request->getText( 'file' ) );
 60+ if ( is_null( $title ) ) {
 61+ $this->getOutput()->addWikiMsg( 'vipsscaler-invalid-file' );
 62+ return;
 63+ }
 64+ $file = wfFindFile( $title );
 65+ if ( !$file || !$file->exists() ) {
 66+ $this->getOutput()->addWikiMsg( 'vipsscaler-invalid-file' );
 67+ return;
 68+ }
 69+
 70+ # Create options
 71+ $width = $request->getInt( 'width' );
 72+ if ( !$width ) {
 73+ $this->getOutput()->addWikiMsg( 'vipsscaler-invalid-width' );
 74+ return;
 75+ }
 76+ $vipsUrlOptions = array( 'thumb' => $file->getName(), 'width' => $width );
 77+ if ( $request->getVal( 'sharpen' ) ) {
 78+ $vipsUrlOptions['sharpen'] = floatval( $request->getVal( 'sharpen' ) );
 79+ }
 80+ if ( $request->getCheck( 'bilinear' ) ) {
 81+ $vipsUrlOptions['bilinear'] = 1;
 82+ }
 83+
 84+
 85+ # Generate normal thumbnail
 86+ $params = array( 'width' => $width );
 87+ $thumb = $file->transform( $params );
 88+ if ( !$thumb || $thumb->isError() ) {
 89+ $this->getOutput()->addWikiMsg( 'vipsscaler-thumb-error' );
 90+ return;
 91+ }
 92+
 93+ # Check if we actually scaled the file
 94+ $normalThumbUrl = $thumb->getUrl();
 95+ if ( wfExpandUrl( $normalThumbUrl ) == $file->getFullUrl() ) {
 96+ // TODO: message
 97+ }
 98+
 99+ # Make url to the vips thumbnail
 100+ $vipsThumbUrl = $this->getTitle()->getLocalUrl( $vipsUrlOptions );
 101+
 102+ # Add to output
 103+ $html = Html::rawElement( 'div', array( 'id' => 'mw-vipstest-thumbnails' ),
 104+ Html::element( 'img', array(
 105+ 'src' => $normalThumbUrl,
 106+ 'alt' => wfMessage( 'vipsscaler-default-thumb' ),
 107+ ) ) . ' ' .
 108+ Html::element( 'img', array(
 109+ 'src' => $vipsThumbUrl,
 110+ 'alt' => wfMessage( 'vipsscaler-vips-thumb' ),
 111+ ) )
 112+ );
 113+ $this->getOutput()->addHTML( $html );
 114+ $this->getOutput()->addModules( array(
 115+ 'ext.vipsscaler',
 116+ 'jquery.ucompare',
 117+ ) );
 118+ }
 119+
 120+ /**
 121+ * TODO
 122+ */
 123+ protected function showForm() {
 124+ $form = new HTMLForm( $this->getFormFields(), $this->getContext() );
 125+ $form->setWrapperLegend( wfMsg( 'vipsscaler-form-legend' ) );
 126+ $form->setSubmitText( wfMsg( 'vipsscaler-form-submit' ) );
 127+ $form->setSubmitCallback( array( __CLASS__, 'processForm' ) );
 128+ $form->setMethod( 'get' );
 129+
 130+ // Looks like HTMLForm does not actually show the form if submission
 131+ // was correct. So we have to show it again.
 132+ // See HTMLForm::show()
 133+ $result = $form->show();
 134+ if( $result === true or $result instanceof Status && $result->isGood() ) {
 135+ $form->displayForm( $result );
 136+ $this->showThumbnails();
 137+ }
 138+ }
 139+
 140+ /**
 141+ * [[Special:VipsTest]] form structure for HTMLForm
 142+ * @return Array A form structure using the HTMLForm system
 143+ */
 144+ protected function getFormFields() {
 145+ $fields = array(
 146+ 'File' => array(
 147+ 'name' => 'file',
 148+ 'class' => 'HTMLTextField',
 149+ 'required' => true,
 150+ 'size' => '80',
 151+ 'label-message' => 'vipsscaler-form-file',
 152+ 'validation-callback' => array( __CLASS__, 'validateFileInput' ),
 153+ ),
 154+ 'Width' => array(
 155+ 'name' => 'width',
 156+ 'class' => 'HTMLIntField',
 157+ 'default' => '640',
 158+ 'size' => '5',
 159+ 'required' => true,
 160+ 'label-message' => 'vipsscaler-form-width',
 161+ 'validation-callback' => array( __CLASS__, 'validateWidth' ),
 162+ ),
 163+ 'SharpenRadius' => array(
 164+ 'name' => 'sharpen',
 165+ 'class' => 'HTMLFloatField',
 166+ 'default' => '0.0',
 167+ 'size' => '5',
 168+ 'label-message' => 'vipsscaler-form-sharpen-radius',
 169+ 'validation-callback' => array( __CLASS__, 'validateSharpen' ),
 170+ ),
 171+ 'Bilinear' => array(
 172+ 'name' => 'bilinear',
 173+ 'class' => 'HTMLCheckField',
 174+ 'label-message' => 'vipsscaler-form-bilinear',
 175+ ),
 176+ );
 177+
 178+ /**
 179+ * Match ImageMagick by default
 180+ */
 181+ global $wgSharpenParameter;
 182+ if ( preg_match( '/^[0-9.]+x([0-9.]+)$/', $wgSharpenParameter, $m ) ) {
 183+ $fields['SharpenRadius']['default'] = $m[1];
 184+ }
 185+ return $fields;
 186+ }
 187+
 188+ public static function validateFileInput( $input, $alldata ) {
 189+ if ( !trim( $input ) ) {
 190+ # Don't show an error if the file is not yet specified,
 191+ # because it is annoying
 192+ return true;
 193+ }
 194+
 195+ $title = Title::makeTitleSafe( NS_FILE, $input );
 196+ if( is_null( $title ) ) {
 197+ return wfMsg( 'vipsscaler-invalid-file' );
 198+ }
 199+ $file = wfFindFile( $title ); # TODO what does it do?
 200+ if ( !$file || !$file->exists() ) {
 201+ return wfMsg( 'vipsscaler-invalid-file' );
 202+ }
 203+
 204+ // Looks sane enough.
 205+ return true;
 206+ }
 207+ public static function validateWidth( $input, $allData ) {
 208+ if ( self::validateFileInput( $allData['File'], $allData ) !== true
 209+ || !trim( $allData['File'] ) ) {
 210+ # Invalid file, error will already be shown at file field
 211+ return true;
 212+ }
 213+ $title = Title::makeTitleSafe( NS_FILE, $allData['File'] );
 214+ $file = wfFindFile( $title );
 215+ if ( $input <= 0 || $input >= $file->getWidth() ) {
 216+ return wfMsg( 'vipsscaler-invalid-width' );
 217+ }
 218+ return true;
 219+ }
 220+ public static function validateSharpen( $input, $allData ) {
 221+ if ( $input >= 5.0 || $input < 0.0 ) {
 222+ return wfMsg( 'vipsscaler-invalid-sharpen' );
 223+ }
 224+ return true;
 225+
 226+ }
 227+
 228+ /**
 229+ * Process data submitted by the form.
 230+ */
 231+ public static function processForm( array $data ) {
 232+ return Status::newGood();
 233+ }
 234+
 235+ /**
 236+ *
 237+ */
 238+ protected function streamThumbnail() {
 239+ global $wgVipsThumbnailerHost, $wgVipsTestExpiry;
 240+
 241+ $request = $this->getRequest();
 242+
 243+ # Validate title and file existance
 244+ $title = Title::makeTitleSafe( NS_FILE, $request->getText( 'thumb' ) );
 245+ if ( is_null( $title ) ) {
 246+ return $this->streamError( 404 );
 247+ }
 248+ $file = wfFindFile( $title );
 249+ if ( !$file || !$file->exists() ) {
 250+ return $this->streamError( 404 );
 251+ }
 252+
 253+ # Check if vips can handle this file
 254+ if ( VipsScaler::getVipsHandler( $file ) === false ) {
 255+ return $this->streamError( 500 );
 256+ }
 257+
 258+ # Validate param string
 259+ $handler = $file->getHandler();
 260+ $params = array( 'width' => $request->getInt( 'width' ) );
 261+ if ( !$handler->normaliseParams( $file, $params ) ) {
 262+ return $this->streamError( 500 );
 263+ }
 264+
 265+
 266+ # Get the thumbnail
 267+ if ( is_null( $wgVipsThumbnailerHost ) || $request->getBool( 'noproxy' ) ) {
 268+ # No remote scaler, need to do it ourselves.
 269+ # Emulate the BitmapHandlerTransform hook
 270+
 271+ $dstPath = VipsCommand::makeTemp( $file->getExtension() );
 272+ $dstUrl = '';
 273+ wfDebug( __METHOD__ . ": Creating vips thumbnail at $dstPath\n" );
 274+
 275+ $scalerParams = array(
 276+ # The size to which the image will be resized
 277+ 'physicalWidth' => $params['physicalWidth'],
 278+ 'physicalHeight' => $params['physicalHeight'],
 279+ 'physicalDimensions' => "{$params['physicalWidth']}x{$params['physicalHeight']}",
 280+ # The size of the image on the page
 281+ 'clientWidth' => $params['width'],
 282+ 'clientHeight' => $params['height'],
 283+ # Comment as will be added to the EXIF of the thumbnail
 284+ 'comment' => isset( $params['descriptionUrl'] ) ?
 285+ "File source: {$params['descriptionUrl']}" : '',
 286+ # Properties of the original image
 287+ 'srcWidth' => $file->getWidth(),
 288+ 'srcHeight' => $file->getHeight(),
 289+ 'mimeType' => $file->getMimeType(),
 290+ 'srcPath' => $file->getPath(),
 291+ 'dstPath' => $dstPath,
 292+ 'dstUrl' => $dstUrl,
 293+ );
 294+
 295+ $options = array();
 296+ if ( $request->getBool( 'bilinear' ) ) {
 297+ $options['bilinear'] = true;
 298+ wfDebug( __METHOD__ . ": using bilinear scaling\n" );
 299+ }
 300+ if ( $request->getVal( 'sharpen' ) && $request->getVal( 'sharpen' ) < 5 ) {
 301+ # Limit sharpen sigma to 5, otherwise we have to write huge convolution matrices
 302+ $options['sharpen'] = array( 'sigma' => floatval( $request->getVal( 'sharpen' ) ) );
 303+ wfDebug( __METHOD__ . ": sharpening with radius {$options['sharpen']}\n" );
 304+ }
 305+
 306+
 307+ # Call the hook
 308+ $mto = null;
 309+ VipsScaler::doTransform( $handler, $file, $scalerParams, $options, $mto );
 310+ if ( $mto && !$mto->isError() ) {
 311+ wfDebug( __METHOD__ . ": streaming thumbnail...\n" );
 312+ $this->getOutput()->disable();
 313+ StreamFile::stream( $dstPath, array(
 314+ "Cache-Control: public, max-age=$wgVipsTestExpiry, s-maxage=$wgVipsTestExpiry",
 315+ 'Expires: ' . gmdate( 'r ', time() + $wgVipsTestExpiry )
 316+ ) );
 317+ } else {
 318+ $this->streamError( 500, $mto->getHtmlMsg() );
 319+ }
 320+
 321+ # Cleanup the temporary file
 322+ wfSuppressWarnings();
 323+ unlink( $dstPath );
 324+ wfRestoreWarnings();
 325+
 326+ } else {
 327+ # Request the thumbnail at a remote scaler
 328+ $url = wfExpandUrl( $request->getRequestURL(), PROTO_INTERNAL );
 329+ $url = wfAppendQuery( $url, array( 'noproxy' => '1' ) );
 330+ wfDebug( __METHOD__ . ": Getting vips thumb from remote url $url\n" );
 331+
 332+ $options = array( 'method' => 'GET' );
 333+
 334+ $req = MWHttpRequest::factory( $url, $options );
 335+ $status = $req->execute();
 336+ if ( $status->isOk() ) {
 337+ # Disable output and stream the file
 338+ $this->getOutput()->disable();
 339+ wfResetOutputBuffers();
 340+ header( 'Content-Type: ' . $file->getMimeType() );
 341+ header( 'Content-Length: ' . strlen( $req->getContent() ) );
 342+ header( "Cache-Control: public, max-age=$wgVipsTestExpiry, s-maxage=$wgVipsTestExpiry" );
 343+ header( 'Expires: ' . gmdate( 'r ', time() + $wgVipsTestExpiry ) );
 344+ print $req->getContent();
 345+ } else {
 346+ return $this->streamError( 500, $req->getContent() );
 347+ }
 348+
 349+ }
 350+ }
 351+
 352+
 353+ /**
 354+ * Generates a blank page with given HTTP error code
 355+ *
 356+ * @param $code Integer: HTTP error either 404 or 500
 357+ */
 358+ protected function streamError( $code, $error = '' ) {
 359+ $this->getOutput()->setStatusCode( $code );
 360+ $this->getOutput()->setArticleBodyOnly( true );
 361+ $this->getOutput()->addHTML( $error );
 362+ }
 363+
 364+}
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/SpecialVipsTest.php
___________________________________________________________________
Added: svn:eol-style
1365 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/license.gz
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/license.gz
___________________________________________________________________
Added: svn:mime-type
2366 + application/octet-stream
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/css/jquery.ucompare.css
@@ -0,0 +1,51 @@
 2+/*!
 3+ * jQuery uCompare
 4+ * http://www.userdot.net/#!/jquery
 5+ *
 6+ * Copyright 2011, UserDot www.userdot.net
 7+ * Licensed under the GPL Version 3 license.
 8+ * Version 1.0.0
 9+ *
 10+ */
 11+ .uc-mask {
 12+ position: absolute;
 13+ top: 0;
 14+ left: 0;
 15+ z-index: 100;
 16+ border-right: 3px solid #333;
 17+ overflow: hidden;
 18+ box-shadow: 3px 5px 5px rgba(0, 0, 0, 0.6);
 19+ box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.6);
 20+ -webkit-box-shadow: 5px 5px 7px rgba(0, 0, 0, 0.6);
 21+ -moz-box-shadow: 5px 0 7px rgba(0, 0, 0, 0.6);
 22+}
 23+.uc-bg {
 24+ position: absolute;
 25+ top: 0;
 26+ left: 0;
 27+ z-index: 0;
 28+}
 29+.uc-caption {
 30+ position: absolute;
 31+ bottom: 10px;
 32+ left: 10px;
 33+ z-index: 120;
 34+
 35+ background: #000;
 36+ filter: alpha(opacity=80);
 37+ -moz-opacity:0.8;
 38+ -khtml-opacity: 0.8;
 39+ opacity: 0.8;
 40+
 41+ color: #fff;
 42+ text-align: center;
 43+ font-size: 12px;
 44+ font-family: arial;
 45+
 46+ -webkit-border-radius: 5px;
 47+ -moz-border-radius: 5px;
 48+ border-radius: 5px;
 49+
 50+ padding: 5px;
 51+ display: none;
 52+}
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/css/jquery.ucompare.css
___________________________________________________________________
Added: svn:eol-style
153 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/css/index.html
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/css/index.html
___________________________________________________________________
Added: svn:eol-style
254 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/index.html
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/index.html
___________________________________________________________________
Added: svn:eol-style
355 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/js/jquery.ucompare.js
@@ -0,0 +1,97 @@
 2+/*!
 3+ * jQuery uCompare
 4+ * http://www.userdot.net/#!/jquery
 5+ *
 6+ * Copyright 2011, UserDot www.userdot.net
 7+ * Licensed under the GPL Version 3 license.
 8+ * Version 1.0.0
 9+ *
 10+ */
 11+( function ( $ ) {
 12+ $.fn.extend( {
 13+ // Hook into jquery.ucompage
 14+ ucompare: function ( localConfig ) {
 15+ // Configuration variable
 16+ var config = {
 17+ defaultgap: 50,
 18+ leftgap: 10,
 19+ rightgap: 10,
 20+ caption: false,
 21+ reveal: .5
 22+ };
 23+ $.extend( config, localConfig );
 24+ return this.each( function () {
 25+ /** Initialization function */
 26+
 27+ var container = $(this);
 28+ // Extract image attributes
 29+ var imageLeftSource = container.children("img:eq(0)").attr("src");
 30+ var imageRightSource = container.children("img:eq(1)").attr("src");
 31+ var caption = container.children("img:eq(0)").attr("alt");
 32+ var width = container.children("img:eq(0)").width();
 33+ var height = container.children("img:eq(0)").height();
 34+ // Hide both images
 35+ container.children("img").hide();
 36+ container.css({
 37+ overflow: "hidden",
 38+ position: "relative"
 39+ });
 40+
 41+ /**
 42+ * MediaWiki hack:
 43+ * Parent element height can still be 0px after hiding the images
 44+ * so we really want to update its dimensions.
 45+ */
 46+ container.width(width); container.height(height);
 47+
 48+ // The left part is the foreground image
 49+ container.append('<div class="uc-mask"></div>');
 50+ // The right part is the background image
 51+ container.append('<div class="uc-bg"></div>');
 52+ // Caption
 53+ container.append( $( '<div class="uc-caption" />' ).text( caption ) );
 54+ // Set the foreground and background image dimensions
 55+ container.children(".uc-mask, .uc-bg").width(width);
 56+ container.children(".uc-mask, .uc-bg").height(height);
 57+ // Fancy initial animation
 58+ container.children(".uc-mask").animate({
 59+ width: width - config.defaultgap
 60+ }, 1e3);
 61+ // Set the images
 62+ container.children(".uc-mask").css("backgroundImage", "url(" + imageLeftSource + ")");
 63+ container.children(".uc-bg").css("backgroundImage", "url(" + imageRightSource + ")");
 64+ if ( config.caption ) {
 65+ container.children(".uc-caption").show()
 66+ }
 67+ }).mousemove(function (event) {
 68+ /** Mouse movent event handler */
 69+
 70+ // Create a jQuery object of the container
 71+ var container = $(this);
 72+
 73+ // Calculate mouse position relative to the left of the image
 74+ var mousePosition = event.pageX - container.children(".uc-mask").offset().left;
 75+
 76+ // Extract image width
 77+ var imageWidth = container.width();
 78+
 79+ // Extract caption
 80+ var captionLeft = container.children("img:eq(0)").attr("alt");
 81+ var captionRight = container.children("img:eq(1)").attr("alt");
 82+
 83+ if ( mousePosition > config.leftgap &&
 84+ mousePosition < imageWidth - config.rightgap ) {
 85+ // Set the width of the left image
 86+ container.children(".uc-mask").width( mousePosition );
 87+ }
 88+
 89+ // Set caption
 90+ if ( mousePosition < imageWidth * config.reveal ) {
 91+ container.children(".uc-caption").text( captionRight );
 92+ } else {
 93+ container.children(".uc-caption").text( captionLeft );
 94+ }
 95+ } ); // End of return statement
 96+ } // End of ucompare function
 97+ } );
 98+} )( jQuery );
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/js/jquery.ucompare.js
___________________________________________________________________
Added: svn:eol-style
199 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/js/index.html
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/js/index.html
___________________________________________________________________
Added: svn:eol-style
2100 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/README
@@ -0,0 +1,9 @@
 2+The jQuery uCompare is a jQuery plugin written by Marius Stanciu - Sergiu
 3+for Userdot, a plugin which gives you the ability to compare two images
 4+(before and after, etc) via a nice interface.
 5+
 6+Source: http://www.userdot.net/files/jquery/jquery.ucompare/
 7+Demo: http://www.userdot.net/files/jquery/jquery.ucompare/demo/
 8+
 9+--
 10+Copied to MediaWiki subversion repository on 2011-11-15 by hashar
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/jquery.ucompare/README
___________________________________________________________________
Added: svn:eol-style
111 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/ext.vipsScaler/ext.vipsScaler.css
@@ -0,0 +1,17 @@
 2+#mw-vipstest-default-thumb, #mw-vipstest-vips-thumb {
 3+ float: left;
 4+ margin-top: 1em;
 5+ margin-right: 1em;
 6+}
 7+.uc-caption {
 8+ /** Overrides ucompare caption position from bottom (bottom:10px) to top */
 9+ top:10px;
 10+ bottom:auto;
 11+}
 12+.uc-mask {
 13+ /* Remove annoying shadow */
 14+ box-shadow: none;
 15+ box-shadow: none;
 16+ -webkit-box-shadow: none;
 17+ -moz-box-shadow: none;
 18+}
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/ext.vipsScaler/ext.vipsScaler.css
___________________________________________________________________
Added: svn:eol-style
119 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/ext.vipsScaler/ext.vipsScaler.js
@@ -0,0 +1,75 @@
 2+jQuery( function( $ ) {
 3+ var container = document.getElementById( 'mw-vipstest-thumbnails' );
 4+ if ( container ) {
 5+/*
 6+ $( '<p id="mw-vipstest-buttons">\n' +
 7+ '<button id="mw-vipstest-show-both">' +
 8+ mediaWiki.message( 'vipsscaler-show-both' ).escaped() +
 9+ '</button> ' +
 10+ '<button id="mw-vipstest-show-default">' +
 11+ mediaWiki.message( 'vipsscaler-show-default' ).escaped() +
 12+ '</button> ' +
 13+ '<button id="mw-vipstest-show-vips">' +
 14+ mediaWiki.message( 'vipsscaler-show-vips' ).escaped() +
 15+ '</button> ' +
 16+ '</p>'
 17+ ).prependTo( container );
 18+*/
 19+/**
 20+ $( '#mw-vipstest-show-both' ).click( function() {
 21+ document.getElementById( 'mw-vipstest-show-default' ).style.display = 'inline';
 22+ document.getElementById( 'mw-vipstest-show-vips' ).style.display = 'inline';
 23+ document.getElementById( 'mw-vipstest-default-thumb' ).style.display = 'block';
 24+ document.getElementById( 'mw-vipstest-vips-thumb' ).style.display = 'block';
 25+ } );
 26+ $( '#mw-vipstest-show-default' ).click( function() {
 27+ document.getElementById( 'mw-vipstest-show-default' ).style.display = 'none';
 28+ document.getElementById( 'mw-vipstest-show-vips' ).style.display = 'inline';
 29+ document.getElementById( 'mw-vipstest-default-thumb' ).style.display = 'block';
 30+ document.getElementById( 'mw-vipstest-vips-thumb' ).style.display = 'none';
 31+ } );
 32+ $( '#mw-vipstest-show-vips' ).click( function() {
 33+ document.getElementById( 'mw-vipstest-show-default' ).style.display = 'inline';
 34+ document.getElementById( 'mw-vipstest-show-vips' ).style.display = 'none';
 35+ document.getElementById( 'mw-vipstest-default-thumb' ).style.display = 'none';
 36+ document.getElementById( 'mw-vipstest-vips-thumb' ).style.display = 'block';
 37+ } );
 38+**/
 39+ /**
 40+ * options are detailed in upstream documentation available at
 41+ * http://www.userdot.net/files/jquery/jquery.ucompare/demo/
 42+ *
 43+ * Copying them here for version 1.0
 44+ * - caption: toggle the
 45+ * - leftgap: the gap to the left of the image
 46+ * - rightgap: the gap to the right of the image
 47+ * - defaultgap: the default gap shown before any interactions
 48+ */
 49+ $('#mw-vipstest-thumbnails').ucompare({
 50+ defaultgap: 50,
 51+ leftgap: 0,
 52+ rightgap: 0,
 53+ caption: true,
 54+ reveal: 0.5
 55+ });
 56+
 57+ /** Also add a click handler to instantly switch beetween pics */
 58+ $('#mw-vipstest-thumbnails').click( function() {
 59+ var e = $(this)
 60+ var mask = e.children(".uc-mask")
 61+ var caption = e.children(".uc-caption")
 62+
 63+ width = e.width();
 64+ maskWidth = mask.width();
 65+
 66+ if( maskWidth < width / 2 ) {
 67+ mask.width( width );
 68+ caption.html( e.children("img:eq(0)").attr("alt") );
 69+ } else {
 70+ mask.width( 0 );
 71+ caption.html( e.children("img:eq(1)").attr("alt") );
 72+ }
 73+ });
 74+ }
 75+}
 76+);
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/modules/ext.vipsScaler/ext.vipsScaler.js
___________________________________________________________________
Added: svn:eol-style
177 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsScaler.alias.php
@@ -0,0 +1,20 @@
 2+<?php
 3+/**
 4+ * Aliases for extension VipsScaler
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$specialPageAliases = array();
 11+
 12+/** English (English) */
 13+$specialPageAliases['en'] = array(
 14+ 'VipsTest' => array( 'VipsTest' )
 15+);
 16+
 17+
 18+/**
 19+ * For backwards compatibility with MediaWiki 1.15 and earlier.
 20+ */
 21+$aliases =& $specialPageAliases;
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsScaler.alias.php
___________________________________________________________________
Added: svn:eol-style
122 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/README
@@ -0,0 +1,27 @@
 2+VipsScaler extension for MediaWiki
 3+
 4+This extension is a wrapper around VIPS a free image processing software.
 5+
 6+== VIPS installation ==
 7+
 8+http://www.vips.ecs.soton.ac.uk/
 9+
 10+=== Debian / Ubuntu ===
 11+
 12+ $ apt-get install vips
 13+
 14+If you want to build from source have a look at upstream documentation:
 15+http://www.vips.ecs.soton.ac.uk/index.php?title=Build_on_Ubuntu
 16+
 17+=== Mac OS X ===
 18+
 19+; homebrew
 20+: brew install vips
 21+: binary symlink is /usr/local/bin/vips
 22+
 23+== Configuration ==
 24+
 25+$wgVipsCommand : path to the vips command (default: vips).
 26+
 27+By default everything is scaled using vips. To disable scaling, set
 28+$wgVipsOptions = array();
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/README
___________________________________________________________________
Added: svn:eol-style
129 + native
Index: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsScaler_body.php
@@ -0,0 +1,465 @@
 2+<?php
 3+/**
 4+ * PHP wrapper class for VIPS under MediaWiki
 5+ *
 6+ * Copyright © Bryan Tong Minh, 2011
 7+ *
 8+ * This program is free software; you can redistribute it and/or modify
 9+ * it under the terms of the GNU General Public License as published by
 10+ * the Free Software Foundation; either version 2 of the License, or
 11+ * (at your option) any later version.
 12+ *
 13+ * This program is distributed in the hope that it will be useful,
 14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 16+ * GNU General Public License for more details.
 17+ *
 18+ * You should have received a copy of the GNU General Public License along
 19+ * with this program; if not, write to the Free Software Foundation, Inc.,
 20+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 21+ * http://www.gnu.org/copyleft/gpl.html
 22+ * @file
 23+ */
 24+
 25+/**
 26+ * Wrapper class for VIPS, a free image processing system good at handling
 27+ * large pictures.
 28+ *
 29+ * http://www.vips.ecs.soton.ac.uk/
 30+ *
 31+ * @author Bryan Tong Minh
 32+ */
 33+class VipsScaler {
 34+ /**
 35+ * Hook to BitmapHandlerTransform. Transforms the file using VIPS if it
 36+ * matches a condition in $wgVipsConditions
 37+ *
 38+ * @param BitmapHandler $handler
 39+ * @param File $file
 40+ * @param array $params
 41+ * @param MediaTransformOutput $mto
 42+ */
 43+ public static function onTransform( $handler, $file, &$params, &$mto ) {
 44+ # Check $wgVipsConditions
 45+ $options = self::getHandlerOptions( $handler, $file, $params );
 46+ if ( !$options ) {
 47+ wfDebug( "...\n" );
 48+ return true;
 49+ }
 50+
 51+ return self::doTransform( $handler, $file, $params, $options, $mto );
 52+ }
 53+
 54+ /**
 55+ * Performs a transform with VIPS
 56+ *
 57+ * @see VipsScaler::onTransform
 58+ *
 59+ * @param BitmapHandler $handler
 60+ * @param File $file
 61+ * @param array $params
 62+ * @param array $options
 63+ * @param MediaTransformOutput &$mto
 64+ * @return bool
 65+ */
 66+ public static function doTransform( $handler, $file, $params, $options, &$mto ) {
 67+ wfDebug( __METHOD__ . ': scaling ' . $file->getName() . " using vips\n" );
 68+
 69+ $vipsCommands = self::makeCommands( $handler, $file, $params, $options );
 70+ if ( count( $vipsCommands ) == 0 ) {
 71+ return true;
 72+ }
 73+
 74+ # Execute the commands
 75+ foreach ( $vipsCommands as $i => $command ) {
 76+ # Set input/output files
 77+ if ( $i == 0 && count( $vipsCommands ) == 1 ) {
 78+ # Single command, so output directly to dstPath
 79+ $command->setIO( $params['srcPath'], $params['dstPath'] );
 80+ } elseif ( $i == 0 ) {
 81+ # First command, input from srcPath, output to temp
 82+ $command->setIO( $params['srcPath'], 'v', VipsCommand::TEMP_OUTPUT );
 83+ } elseif ( $i + 1 == count( $vipsCommands ) ) {
 84+ # Last command, output to dstPath
 85+ $command->setIO( $vipsCommands[$i - 1], $params['dstPath'] );
 86+ } else {
 87+ $command->setIO( $vipsCommands[$i - 1], 'v', VipsCommand::TEMP_OUTPUT );
 88+ }
 89+
 90+ $retval = $command->execute();
 91+ if ( $retval != 0 ) {
 92+ wfDebug( __METHOD__ . ": vips command failed!\n" );
 93+ $mto = $handler->getMediaTransformError( $params, $command->getErrorString() );
 94+ return false;
 95+ }
 96+ }
 97+
 98+ # Set comment
 99+ if ( !empty( $options['setcomment'] ) && !empty( $params['comment'] ) ) {
 100+ self::setJpegComment( $params['dstPath'], $params['comment'] );
 101+ }
 102+
 103+ # Set the output variable
 104+ $mto = new ThumbnailImage( $file, $params['dstUrl'],
 105+ $params['clientWidth'], $params['clientHeight'], $params['dstPath'] );
 106+
 107+ # Stop processing
 108+ return false;
 109+ }
 110+
 111+ /**
 112+ * @param $handler
 113+ * @param $file
 114+ * @param $params
 115+ * @param $options
 116+ */
 117+ public static function makeCommands( $handler, $file, $params, $options ) {
 118+ global $wgVipsCommand;
 119+ $commands = array();
 120+
 121+ # Get the proper im_XXX2vips handler
 122+ $vipsHandler = self::getVipsHandler( $file );
 123+ if ( !$vipsHandler ) {
 124+ return array();
 125+ }
 126+
 127+ # Check if we need to convert to a .v file first
 128+ if ( !empty( $options['preconvert'] ) ) {
 129+ $commands[] = new VipsCommand( $wgVipsCommand, array( $vipsHandler ) );
 130+ }
 131+
 132+ # Do the resizing
 133+ $rotation = 360 - $handler->getRotation( $file );
 134+
 135+ wfDebug( __METHOD__ . " rotating '{$file->getName()}' by {$rotation}°\n" );
 136+ if ( empty( $options['bilinear'] ) ) {
 137+ # Calculate shrink factors. Offsetting by 0.5 pixels is required
 138+ # because of rounding down of the target size by VIPS. See 25990#c7
 139+ # No need to invert source and physical dimensions. They already got switched if needed.
 140+ $rx = $params['srcWidth'] / ($params['physicalWidth'] + 0.5);
 141+ $ry = $params['srcHeight'] / ($params['physicalHeight'] + 0.5);
 142+
 143+ wfDebug( sprintf(
 144+ "%s to shrink '%s'. Source: %sx%s, Physical: %sx%s. Shrink factors (rx,ry) = %sx%s.\n",
 145+ __METHOD__, $file->getName(),
 146+ $params['srcWidth'], $params['srcHeight'],
 147+ $params['physicalWidth'], $params['physicalHeight'],
 148+ $rx, $ry
 149+ ));
 150+
 151+ $commands[] = new VipsCommand( $wgVipsCommand, array( 'im_shrink', $rx, $ry ) );
 152+ } else {
 153+ if ( $rotation % 180 == 90 ) {
 154+ $dstWidth = $params['physicalHeight'];
 155+ $dstHeight = $params['physicalWidth'];
 156+ } else {
 157+ $dstWidth = $params['physicalWidth'];
 158+ $dstHeight = $params['physicalHeight'];
 159+ }
 160+ wfDebug( sprintf(
 161+ "%s to bilinear resize %s. Source: %sx%s, Physical: %sx%s. Destination: %sx%s\n",
 162+ __METHOD__, $file->getName(),
 163+ $params['srcWidth'], $params['srcHeight'],
 164+ $params['physicalWidth'], $params['physicalHeight'],
 165+ $dstWidth, $dstHeight
 166+ ));
 167+
 168+ $commands[] = new VipsCommand( $wgVipsCommand,
 169+ array( 'im_resize_linear', $dstWidth, $dstHeight ) );
 170+ }
 171+
 172+ if ( !empty( $options['sharpen'] ) ) {
 173+ $options['convolution'] = self::makeSharpenMatrix( $options['sharpen'] );
 174+ }
 175+
 176+ if ( !empty( $options['convolution'] ) ) {
 177+ $commands[] = new VipsConvolution( $wgVipsCommand,
 178+ array( 'im_convf', $options['convolution'] ) );
 179+ }
 180+
 181+ # Rotation
 182+ if ( $rotation % 360 != 0 && $rotation % 90 == 0 ) {
 183+ $commands[] = new VipsCommand( $wgVipsCommand, array( "im_rot{$rotation}" ) );
 184+ }
 185+
 186+ return $commands;
 187+ }
 188+
 189+ /**
 190+ * Create a sharpening matrix suitable for im_convf. Uses the ImageMagick
 191+ * sharpening algorithm from SharpenImage() in magick/effect.c
 192+ *
 193+ * @param mixed $params
 194+ * @return array
 195+ */
 196+ public static function makeSharpenMatrix( $params ) {
 197+ $sigma = $params['sigma'];
 198+ $radius = empty( $params['radius'] ) ?
 199+ # After 3 sigma there should be no significant values anymore
 200+ intval( round( $sigma * 3 ) ) : $params['radius'];
 201+
 202+ $norm = 0;
 203+ $conv = array();
 204+
 205+ # Fill the matrix with a negative Gaussian distribution
 206+ $variance = $sigma * $sigma;
 207+ for ( $x = -$radius; $x <= $radius; $x++ ) {
 208+ $row = array();
 209+ for ( $y = -$radius; $y <= $radius; $y++ ) {
 210+ $z = -exp( -( $x*$x + $y*$y ) / ( 2 * $variance ) ) /
 211+ ( 2 * pi() * $variance );
 212+ $row[] = $z;
 213+ $norm += $z;
 214+ }
 215+ $conv[] = $row;
 216+ }
 217+
 218+ # Calculate the scaling parameter to ensure that the mean of the
 219+ # matrix is zero
 220+ $scale = - $conv[$radius][$radius] - $norm;
 221+ # Set the center pixel to obtain a sharpening matrix
 222+ $conv[$radius][$radius] = -$norm * 2;
 223+ # Add the matrix descriptor
 224+ array_unshift( $conv, array( $radius * 2 + 1, $radius * 2 + 1, $scale, 0 ) );
 225+ return $conv;
 226+ }
 227+
 228+
 229+ /**
 230+ * Check the file and params against $wgVipsOptions
 231+ *
 232+ * @param BitmapHandler $handler
 233+ * @param File $file
 234+ * @param array $params
 235+ * @return bool
 236+ */
 237+ protected static function getHandlerOptions( $handler, $file, $params ) {
 238+ global $wgVipsOptions;
 239+ # Iterate over conditions
 240+ foreach ( $wgVipsOptions as $option ) {
 241+ if ( isset( $option['conditions'] ) ) {
 242+ $condition = $option['conditions'];
 243+ } else {
 244+ # Unconditionally pass
 245+ return $option;
 246+ }
 247+
 248+ if ( isset( $condition['mimeType'] ) &&
 249+ $file->getMimeType() != $condition['mimeType'] ) {
 250+ continue;
 251+ }
 252+
 253+ $area = $handler->getImageArea( $file );
 254+ if ( isset( $condition['minArea'] ) && $area < $condition['minArea'] ) {
 255+ continue;
 256+ }
 257+ if ( isset( $condition['maxArea'] ) && $area >= $condition['maxArea'] ) {
 258+ continue;
 259+ }
 260+
 261+ $shrinkFactor = $file->getWidth() / (
 262+ ( ( $handler->getRotation( $file ) % 180 ) == 90 ) ?
 263+ $params['physicalHeight'] : $params['physicalWidth'] );
 264+ if ( isset( $condition['minShrinkFactor'] ) &&
 265+ $shrinkFactor < $condition['minShrinkFactor'] ) {
 266+ continue;
 267+ }
 268+ if ( isset( $condition['maxShrinkFactor'] ) &&
 269+ $shrinkFactor >= $condition['maxShrinkFactor'] ) {
 270+ continue;
 271+ }
 272+
 273+ # This condition passed
 274+ return $option;
 275+ }
 276+ # All conditions failed
 277+ return false;
 278+ }
 279+
 280+ /**
 281+ * Sets the JPEG comment on a file using exiv2.
 282+ * Requires $wgExiv2Command to be setup properly.
 283+ *
 284+ * @todo FIXME need to handle errors such as $wgExiv2Command not available
 285+ *
 286+ * @param string $fileName File where the comment needs to be set
 287+ * @param string $comment The comment
 288+ */
 289+ public static function setJpegComment( $fileName, $comment ) {
 290+ global $wgExiv2Command;
 291+
 292+ wfShellExec( wfEscapeShellArg( $wgExiv2Command ) . ' mo -c '
 293+ . wfEscapeShellArg( $comment ) . ' '
 294+ . wfEscapeShellArg( $fileName )
 295+ );
 296+ }
 297+
 298+ /**
 299+ * Return the appropriate im_XXX2vips handler for this file
 300+ * @param File $file
 301+ * @return mixed String or false
 302+ */
 303+ public static function getVipsHandler( $file ) {
 304+ list( $major, $minor ) = File::splitMime( $file->getMimeType() );
 305+
 306+ if ( $major == 'image' && in_array( $minor, array( 'jpeg', 'png', 'tiff' ) ) ) {
 307+ return "im_{$minor}2vips";
 308+ } else {
 309+ return false;
 310+ }
 311+ }
 312+
 313+ /**
 314+ * Hook to BitmapHandlerCheckImageArea. Will set $result to true if the
 315+ * file will by handled by VipsScaler.
 316+ *
 317+ * @param File $file
 318+ * @param array &$params
 319+ * @param mixed &$result
 320+ * @return bool
 321+ */
 322+ public static function onBitmapHandlerCheckImageArea( $file, &$params, &$result ) {
 323+ global $wgMaxImageArea;
 324+ if ( self::getHandlerOptions( $file->getHandler(), $file, $params ) !== false ) {
 325+ wfDebug( __METHOD__ . ": Overriding $wgMaxImageArea\n" );
 326+ $result = true;
 327+ return false;
 328+ }
 329+ return true;
 330+ }
 331+}
 332+
 333+/**
 334+ * Wrapper class around the vips command, useful to chain multiple commands
 335+ * with intermediate .v files
 336+ */
 337+class VipsCommand {
 338+
 339+ /** Flag to indicate that the output file should be a temporary .v file */
 340+ const TEMP_OUTPUT = true;
 341+ /**
 342+ * Constructor
 343+ *
 344+ * @param string $vips Path to binary
 345+ * @param array $args Array or arguments
 346+ */
 347+ public function __construct( $vips, $args ) {
 348+ $this->vips = $vips;
 349+ $this->args = $args;
 350+ }
 351+ /**
 352+ * Set the input and output file of this command
 353+ *
 354+ * @param mixed $input Input file name or an VipsCommand object to use the
 355+ * output of that command
 356+ * @param string $output Output file name or extension of the temporary file
 357+ * @param bool $tempOutput Output to a temporary file
 358+ */
 359+ public function setIO( $input, $output, $tempOutput = false ) {
 360+ if ( $input instanceof VipsCommand ) {
 361+ $this->input = $input->getOutput();
 362+ $this->removeInput = true;
 363+ } else {
 364+ $this->input = $input;
 365+ $this->removeInput = false;
 366+ }
 367+ if ( $tempOutput ) {
 368+ $this->output = self::makeTemp( $output );
 369+ } else {
 370+ $this->output = $output;
 371+ }
 372+ }
 373+ /**
 374+ * Returns the output filename
 375+ * @return string
 376+ */
 377+ public function getOutput() {
 378+ return $this->output;
 379+ }
 380+ /**
 381+ * Return the output of the command
 382+ * @return string
 383+ */
 384+ public function getErrorString() {
 385+ return $this->err;
 386+ }
 387+
 388+ /**
 389+ * Call the vips binary with varargs and returns the return value.
 390+ *
 391+ * @return int Return value
 392+ */
 393+ public function execute() {
 394+ # Build and escape the command string
 395+ $cmd = wfEscapeShellArg( $this->vips,
 396+ array_shift( $this->args ),
 397+ $this->input, $this->output );
 398+
 399+ foreach ( $this->args as $arg ) {
 400+ $cmd .= ' ' . wfEscapeShellArg( $arg );
 401+ }
 402+
 403+ $cmd .= ' 2>&1';
 404+
 405+ # Execute
 406+ $retval = 0;
 407+ $this->err = wfShellExec( $cmd, $retval );
 408+
 409+ # Cleanup temp file
 410+ if ( $this->removeInput ) {
 411+ unlink( $this->input );
 412+ }
 413+
 414+ return $retval;
 415+ }
 416+
 417+ /**
 418+ * Generate a random, non-existent temporary file with a specified
 419+ * extension.
 420+ *
 421+ * @param string Extension
 422+ * @return string
 423+ */
 424+ public static function makeTemp( $extension ) {
 425+ do {
 426+ # Generate a random file
 427+ $fileName = wfTempDir() . DIRECTORY_SEPARATOR .
 428+ dechex( mt_rand() ) . dechex( mt_rand() ) .
 429+ '.' . $extension;
 430+ } while ( file_exists( $fileName ) );
 431+ # Create the file
 432+ touch( $fileName );
 433+
 434+ return $fileName;
 435+ }
 436+
 437+}
 438+
 439+/**
 440+ * A wrapper class around im_conv because that command expects a a convolution
 441+ * matrix file as its last argument
 442+ */
 443+class VipsConvolution extends VipsCommand {
 444+ public function execute() {
 445+ # Convert a 2D array into a space/newline separated matrix
 446+ $convolutionMatrix = array_pop( $this->args );
 447+ $convolutionString = '';
 448+ foreach ( $convolutionMatrix as $i=>$row ) {
 449+ $convolutionString .= implode( ' ', $row ) . "\n";
 450+ }
 451+ # Save the matrix in a tempfile
 452+ $convolutionFile = self::makeTemp( 'conv' );
 453+ file_put_contents( $convolutionFile, $convolutionString );
 454+ array_push( $this->args, $convolutionFile );
 455+
 456+ wfDebug( __METHOD__ . ": Convolving image [\n" . $convolutionString . "] \n" );
 457+
 458+ # Call the parent to actually execute the command
 459+ $retval = parent::execute();
 460+
 461+ # Remove the temporary matrix file
 462+ unlink( $convolutionFile );
 463+
 464+ return $retval;
 465+ }
 466+}
Property changes on: branches/wmf/1.18wmf1/extensions/VipsScaler/VipsScaler_body.php
___________________________________________________________________
Added: svn:eol-style
1467 + native

Status & tagging log