Zoomify – Im Hintergrund Ausgabedateien erstellen

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!

Kommentare sind geschlossen.