So heute war ich es dann leid – ich habe ja versucht für das Applet von Zoomify die Ausgabedateien abgebatcht im Hintergrund zu generieren. Was ziemlich so gar nicht geht wenn man kein aktiven Desktop hat wo sich der EZ Zoomifyer einmal anzeigen kann. Da ich es aber auf einem Rechner ohne Anmeldung brauchte habe ich mir nun ein Programm in C# (C.Net) geschrieben was mir quasi selbst genau das macht, was das Programm aus dem Zoomify erledigt. Es zerschnippelt das Quellbild in entsprechende Teile, zerlegt es und nummeriert es passend durch und legt die entsprechenden Verzeichnisse an.
Ich brauchte es in meinem Fall als Windows Dienst – die Zoomify-Sachen sind aber (zusätzlich mit einem Timer Event) in einer Klasse gekapselt wodurch es eigentlich relativ einfach möglich sein dürfte es auf eigene Bedürfnisse in einer GUI Anwendung oder in einem Konsolenprogramm zu verarbeiten.
Leider war das ganze eine Quick & Dirty Lösung wodurch die der Quellcode kaum dokumentiert ist. Aber mit ein bisschen Durchschauen und C# Verständnis sollte es nicht sonderlich schwierig zu verstehen sein. Es ist nicht viel Code und recht rudimentär – ich stells online damit sich andere Leute denen es auf den Kekx geht sich mal fix bedienen können.
Ich habe übrigens gesehen das es eine Open-Source Lösung gibt auf die man bei Zoomify selbst verweist direkt auf der Startseite mit diesem Kommentar:
Need a Zoomify conversion solution for UNIX/Linux? ‘Zoomify Image’ is now available on SourceForge.net may meet your needs – and Python source is included to support easy porting to other scripting languages such as PHP and Perl.
Ich denke mal daher dürfte das online Stellen meines Quellcodes unproblematisch sein – wie das Ding untendrunter funktioniert ist eh recht einfach zu durchschauen und wer es so nicht rafft kanns im Python Quellcode vom Sourceforge-Projekt nachlesen.
Wenn Ihr Meinungen und Kommentare oder Verbesserungsfeedback habt, würde ich mich einfach über einen kurzen Kommentar freuen.
Den Quellcode für den Service findet man auf Seite 2 dieses Beitrages, den Quellcode für die Klasse welche die Bilder für den Zoomifyer erstellt findet man auf Seite 3.
Hier also einmal die Main-Klasse vom Windows Dienst
MyService.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | /* * Created by AM/AF. * User: AM * Date: 03.01.2006 * Time: 17:42 * */ using System; using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.ServiceProcess; using System.Configuration.Install; namespace PictureService { /// /// This is the class for my Service /// public class MyService : System.ServiceProcess.ServiceBase { private PicRun PRun; public MyService() { InitializeComponents(); // TODO: Add any further initialization code this.PRun = new PicRun(180); } private void InitializeComponents() { this.ServiceName = "EZ Picture Service"; } /// /// This method starts the service. /// public static void Main() { System.ServiceProcess.ServiceBase.Run(new System.ServiceProcess.ServiceBase[] { new MyService() // To run more than one service you have to add them here }); } /// /// Clean up any resources being used. /// protected override void Dispose(bool disposing) { // TODO: Add cleanup code here (if required) base.Dispose(disposing); } /// /// Start this service. /// protected override void OnStart(string[] args) { // TODO: Add start code here (if required) // to start your service. } /// /// Stop this service. /// protected override void OnStop() { // TODO: Add tear-down code here (if required) // to stop your service. } } } [RunInstaller(true)] public class ProjectInstaller : Installer { public ProjectInstaller() { ServiceProcessInstaller spi = new ServiceProcessInstaller(); spi.Account = ServiceAccount.LocalSystem; ServiceInstaller si = new ServiceInstaller(); si.ServiceName = "EZ Picture Generator"; si.StartType = ServiceStartMode.Automatic; Installers.AddRange(new Installer[] {spi, si}); } } |
Und hier die eigentlich Klasse die das ganze Bearbeiten übernimmt:
PicRun.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | /* * Created by AM/AF. * User: AM * Date: 03.01.2006 * Time: 17:44 * */ using System; using System.Timers; using System.IO; using System.Windows.Forms; using System.Threading; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; namespace PictureService { /// /// Description of PicRun. /// public class PicRun { private bool Debug = false; private System.Timers.Timer aTimer = new System.Timers.Timer(); private void AddLog(string l) { if (this.Debug == true) { StreamWriter sw = new StreamWriter(Application.StartupPath + "\\files.log", true); DateTime d = new DateTime(); d = DateTime.Now; sw.WriteLine("[" + d.ToString("dd.MM.yyyy") + "-" + d.ToString("hh:mm") + "] " + l); sw.Close(); } } private void OnEvntAct(object source, ElapsedEventArgs e) { try { if (File.Exists(Application.StartupPath + "\\progress.flg") == false) { FileStream fs = new FileStream(Application.StartupPath + "\\progress.flg",FileMode.Create); fs.Close(); string thePath = ""; StreamReader sr = new StreamReader(Application.StartupPath + "\\dirpath.cfg"); thePath = sr.ReadLine(); sr.Close(); if (thePath.Substring(thePath.Length-1) != "\\") { thePath += "\\"; } this.AddLog(thePath); string[] theFiles = Directory.GetFiles(thePath,"tmp_*"); // int runcycles = 0; if (theFiles.Length > 0) { for (int i = 0; i < = theFiles.Length-1; i++) { this.generateEZParts(theFiles[i],thePath); } for (int i = 0; i <= theFiles.Length-1; i++) { this.AddLog("Loesche nun Dateien."); File.Delete(theFiles[i]); } } string[] subdirs = Directory.GetDirectories(thePath,"tmp_*"); if (subdirs.Length > 0) { for (int i = 0; i < subdirs.Length; i++) { this.AddLog(subdirs[i]); string newname = subdirs[i].Substring(thePath.Length+4,subdirs[i].Length-4-thePath.Length); Directory.Move(subdirs[i],thePath+newname); } } File.Delete(Application.StartupPath + "\\progress.flg"); } } catch (Exception ex) { this.AddLog(ex.ToString()); if (File.Exists(Application.StartupPath + "\\progress.flg")) { File.Delete(Application.StartupPath + "\\progress.flg"); } } } private int numZooms(string file) { Bitmap myBitmap = new Bitmap( Image.FromFile(file) ); int ebenen = 0; int h = myBitmap.Height; int w = myBitmap.Width; this.AddLog("Start ebenen: "+ebenen.ToString()); this.AddLog("Start height: "+h.ToString()); this.AddLog("Start width: "+w.ToString()); while( (h > 256) || (w > 256) ) { h = this.Div(h,2); w = this.Div(w,2); ebenen++; this.AddLog("run ebenen: "+ebenen.ToString()); this.AddLog("run height: "+h.ToString()); this.AddLog("run width: "+w.ToString()); } return ebenen; } private int Div(double a, double b) { return System.Convert.ToInt32(Math.Ceiling((a/b))); } private void genEbene(string file, string targetdir, int ediv,int ebene) { int h = 0; int w = 0; Bitmap b = new Bitmap( Image.FromFile(file) ); h = b.Height; w = b.Width; for (int i = 0; i < ediv; i++) { h = this.Div(h,2); w = this.Div(w,2); } Size newSize = new Size(w,h); b = new Bitmap( Image.FromFile(file), newSize); int width_clips = 0; int height_clips = 0; int last_right = 0; int last_bottom = 0; int work_width = w; int work_height = h; while(work_width > 256) { width_clips++; work_width -= 256; } last_right = work_width; width_clips++; while(work_height > 256) { height_clips++; work_height -= 256; } last_bottom = work_height; height_clips++; this.AddLog("width-clips: "+width_clips.ToString()); this.AddLog("height-clips: "+height_clips.ToString()); this.AddLog("last-right: "+last_right.ToString()); this.AddLog("last-bottom: "+last_bottom.ToString()); this.AddLog("ebene: "+ebene.ToString()); this.AddLog("ebene-div: "+ediv.ToString()); this.AddLog("rest-height: "+h.ToString()); this.AddLog("rest-width: "+w.ToString()); int clw = 0; int clh = 0; int recwidth = 0; int recheight = 0; for (clh = 1; clh < = height_clips; clh++) { for (clw = 1; clw <= width_clips; clw++) { if (clw == width_clips) { recwidth = last_right; } else { recwidth = 256; } if (clh == height_clips) { recheight = last_bottom; } else { recheight = 256; } Rectangle myRect = new Rectangle((clw-1)*256,(clh-1)*256,recwidth,recheight); Image myImage = new Bitmap(recwidth,recheight); Graphics myGraphicsPart = Graphics.FromImage(myImage); myGraphicsPart.DrawImage(b,0,0,myRect,GraphicsUnit.Pixel); myImage.Save(targetdir + "\\TileGroup0\\" + ebene.ToString() + "-" + (clw-1).ToString() + "-" + (clh-1).ToString() + ".jpg",ImageFormat.Jpeg); } } } private void generateEZParts(string file, string targetDir) { string onlyfilenamewoex = file.Substring(targetDir.Length,file.Length-4-targetDir.Length); int ze = this.numZooms(file); Directory.CreateDirectory(targetDir+"\\"+onlyfilenamewoex); Directory.CreateDirectory(targetDir+"\\"+onlyfilenamewoex+"\\TileGroup0"); for (int i = ze; i >= 0; i--) { this.AddLog("i: "+i.ToString()); this.genEbene(file,targetDir+onlyfilenamewoex,ze-i,i); } Bitmap b = new Bitmap( Image.FromFile(file) ); int w = b.Width; int h = b.Height; b.Dispose(); StreamWriter sw = new StreamWriter(targetDir+"\\"+onlyfilenamewoex+"\\ImageProperties.xml"); string[] theTile = Directory.GetFiles(targetDir+"\\"+onlyfilenamewoex+"\\TileGroup0"); string theXml = ""; sw.Write(theXml); sw.Close(); } public PicRun(int Intval) { aTimer.Enabled = false; aTimer.Interval = Intval * 1000; aTimer.Elapsed += new ElapsedEventHandler(OnEvntAct); aTimer.Enabled = true; } } } |
Wie gesagt bei Verbesserungsvorschlägen oder Kommentaren einfach hier reinschreiben ich freu mich ![]()
Das ganze ist natürlich wirklich mit der heissen Nadel gestrickt und optisch und strukturiert nicht schön!
