Swirly Mein Kopf

Saturday, May 12. 2012

10 years of using Debian

Debian

Today, it must have been exactly 10 years that I started using Debian. The story of how I came to Debian shows some of its strengths, so I’ll use this occasion to share it.

I spent the first half of 2002 as an high-school exchange student in Wenatchee, USA. I was already a user of Linux at that time: I made my first contact roughly in 1996 and did my first installation at home two years later, but all that time I was dual-booting and my main system was a well-arranged Windows 98. The machine was a regular tower PC, but nevertheless I put the computer into my trunk when I flew to the US. It took away most of the space, and I had to put some of my cloths inside the case.

So I was there, happily using my Windows and my manually set up “Linux From Scratch” until one day the inevitable happened; inevitable at least until you start doing backups: On April 30th, my hard drive crashed, and took the two systems together with 4 years of personal data with it.

Two weeks later I had a new hard drive and was pondering my options. I did plan to install Windows again; at that time Windows XP was just released. But I wanted a German version of Windows, which would be hard to get there. Also, I did not want to use Linux from Scratch any more, and wanted to make a well-founded choice of a distribution. On the other hand, I really wanted to get my machine up and running quickly, to be able to read my mail more comfortably. I had heard that Debian had good support for network installations (downloading a full 700MB CD was something to avoid at that time), so I grabbed some netinst images, burned a CD, and quickly installed Debian.

I was planning to use the system for about two weeks. I did not pay any particular attention to the setup. Heck, I even picked from my Simpsons sidekick machine naming scheme one that I would not miss being used up (“barney”). Nevertheless, I was using this installation for many years (and many upgrades), until I eventually switched to using laptops. In fact, that very installation is still on the machine somewhere and works. I did install Windows XP a few weeks later as well, but hardly used it. So May 12th of 2002 was when I turned into a full-time Linux and Debian user.

I soon became interested in Debian the project and started to contribute. But that is another story for another ten year anniversary blog post, most likely on October 21, 2013...

Monday, May 7. 2012

Free Groups in Agda

Digital World

I must say that I do like free groups. At least whenever I play around with some theorem provers, I find myself formalizing free groups in them. For Isabelle, my development of free groups is already part of the Archive of Formal Proofs. Now I became interested in the theorem prover/programming language Agda,so I did it there as well. I was curious how well Agda is suited for doing math, and how comfortable with intuitionalistic logic I’d be.

At first I wanted to follow the same path again and tried to define the free group on the set of fully reduced words. This is the natural way in Isabelle, where the existing setup for groups expects you to define the carrier as a subset of an existing type (the type here being lists of generators and their inverses). But I did not get far, and also I had to start using stuff like DecidableEquivalence, an indication that this might not go well with the intuitionalistic logic. So I changed my approach and defined the free group on all words as elements of the group, with a suitable equivalence relation. This allowed me define the free group construction and show its group properties without any smell of classical logic.

The agda files can be found in my darcs repository, and the HTML export can be browsed: Generators.agda defines the sets-of-generators-and-inverses and FreeGroups.agda (parametrized by the Setoid it is defined over) the reduction relation and the group axioms. Here are some observations I (disclaimer: Agda-beginer) made:

  • Fun fact: Free groups exist not only in classical logic.
  • Without any automation as in Isabelle, even simple things get quite complicated. A simple substitution of an equality with subst requires me to specify not only the equality and the term I want it to apply, but also to repeat the common part of the terms. Or when using the associativity of list concatenation, I have to pass all three sublists to the lemma. Maybe I am a bit spoiled by Isabelle, but I’d be worried that this would prevent large proofs.
  • The levels are also annoying. Although my theory stays within one level, I have to annotate it everywhere. I’d expect the type inference to figure this out for me.
  • Equality reasoning with begin ... ∎ is quite nice and surprisingly well readable.
  • Besides the additional work, it is nice to be able to do the proof in almost all detail. There is a limitation, though, as some steps are done automatically (if they happen to occur when evaluating/normalizing a term) and the others, even if similar-looking, are not.
  • It’d be great if one would be free in the choice of editor, but vim users generally have a hard time in the field of theorem provers.

If I were to extend this theory, there are two important facts to be shown: That there is a unique reduced word in every equivalence class (norm_form_uniq), and the universal property of the free group. For the former (started in NormalForm.agda) I’m missing some general lemmas about relations (e.g. that local confluence implies global confluence, and even the reflexive, symmetric, transitive hull is missing in the standard library). For the latter, some general notions such as a group homomorphism need to be developed first.

I planned to compare the two developments, Isabelle and Agda. But as they turned out to show quite things in different orders, this is not really possible any more. One motivation to look at Agda was to see if a dependently typed language frees me from doing lots of set-element-checking (see the “mems” lemma in the Isabelle proof of the Ping-Pong-Lemma). So far I had no such problems, but I did not get far enough yet to actually tell.

Thanks to Helmut Grohne for an educating evening of Agda hacking!

Tuesday, March 13. 2012

ghc-heap-view: Complete referential opacity

Haskell

During the last week, I created ghc-heap-view, a library to investigate the actual memory representation of Haskell values. It is inspired by vacuum and the GHCi debugger, but goes beyond them by allowing the user to look inside thunks and functions and see what other values they refer to. Let me demonstrate it by running the included demo:

ghc-heap-view-demo

Here are a four different lists, where the first three are already evaluated.
The first one, l, was defined as a top level constant as

> l = [1,2,3]

and is now found at 0x00000000006d1750/2 (where the /2 is the pointer tag information) and fully evaluated:

    ConsClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = CONSTR_STATIC, srtlen = 1}, 
                 ptrArgs = [0x00000000006d16e0/1,0x00000000006d1730/2],
                 dataArgs = [], descr = "ghc-prim:GHC.Types.:"}

The second one, l2, is locally defined

> let l2 = 4:l

and now found at 0x00007fdce19fe4b0/2. See how the cons-cell references l!

    ConsClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = CONSTR_2_0, srtlen = 1},
                 ptrArgs = [0x00000000006dca50/1,0x00000000006d1750/2],
                 dataArgs = [],
                 descr = "ghc-prim:GHC.Types.:"}

And the binding

> args <- map length `fmap` getArgs

evaluates to the “one”, global empty list at 0x00000000006db640/1:

    ConsClosure {info = StgInfoTable {ptrs = 0, nptrs = 0, tipe = CONSTR_NOCAF_STATIC, srtlen = 0},
                 ptrArgs = [],
                 dataArgs = [],
                 descr = "ghc-prim:GHC.Types.[]"}

And now we have, at 0x00007fdce19fe4c8, the concatenation of them, but unevaluated:

> let x = l ++ l2 ++ args

The thunk keeps a reference to l2 and args, but not l, as that is at a static address, unless you are running this in GHCi:

    ThunkClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = THUNK_2_0, srtlen = 1},
                  ptrArgs = [0x00007fdce19fe4b0/2,0x00000000006db640/1],
                  dataArgs = []}

Now to some more closure types. m and m' locally bound of type the unboxed type Int#, with values 42 resp. 23.

> let f = \x n -> take (I# m + I# x) n ++ args
      t = f m' l2

So here is (0x00007fdce1937d50/2), referencing its free variables args and 42:

    FunClosure {info = StgInfoTable {ptrs = 1, nptrs = 1, tipe = FUN_1_1, srtlen = 65553},
                ptrArgs = [0x00000000006db640/1],
                dataArgs = [42]}

And t is a thunk that applies f (also referenced here) to an unboxed value (23) and l2:

    ThunkClosure {info = StgInfoTable {ptrs = 2, nptrs = 1, tipe = THUNK, srtlen = 0},
                  ptrArgs = [0x00007fdce19fe4b0/2,0x00007fdce1937d50/2],
                  dataArgs = [23]}

Lastly, here is the standard example for self reference:

> let x = id (:) () x

This is what x (0x00007fdce1947940) looks like, at least without -O:

    ThunkClosure {info = StgInfoTable {ptrs = 0, nptrs = 0, tipe = THUNK, srtlen = 1},
                  ptrArgs = [],
                  dataArgs = []}

So it is unevaluated. Let us evaluate it using seq. Now we have, still at 0x00007fdce1947940:

    IndClosure {info = StgInfoTable {ptrs = 1, nptrs = 0, tipe = BLACKHOLE, srtlen = 0},
                indirectee = 0x00007fdce194cc98/2}

The thunk was replaced by an indirection. If we look at the target, 0x00007fdce194cc98/2, we see that it is a newly created cons-cell referencing the original location of x:

    ConsClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = CONSTR_2_0, srtlen = 1},
                 ptrArgs = [0x00000000006db620/1,0x00007fdce1947940],
                 dataArgs = [],
                 descr = "ghc-prim:GHC.Types.:"}

After running the garbage collector (performGC), we find that the address of x is now 0x00007fdce19f30d0/2 and that the self-reference is without indirections:

    ConsClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = CONSTR_2_0, srtlen = 1},
                 ptrArgs = [0x00000000006db620/1,0x00007fdce19f30d0/2],
                 dataArgs = [],
                 descr = "ghc-prim:GHC.Types.:"}

Future plans

The output of ghc-heap-view is not really pretty yet; even the indentation in this blog post was added manually by me, so this really needs a pretty printer providing a nicer, possibly more compact representation, including something like what vacuum provides. Maybe vacuum can be ported to use this library, and also include the thunk’s and function’s references in the output. Maybe also the GHCi debugger can be extended to show more information about unevaluated expressions using this. Internally, the library is not very polished yet either. It only handles those closures types that I have seen so far, and is likely to break horribly if run in a threaded or debugging enabled runtime.

How it works

Obviously, this is not standard Haskell 98 code, but rather deep trickery involving the GHC API and some C code. Initially I tried to use the API that vacuum and the GHCi debugger rely on, which is an operation

unpackClosure# :: a -> (# Addr#, Array# b, ByteArray# #)

which takes any Haskell value and returns the address to its info table, the pointers and the non-pointer-data in the closure. Unfortunately, it was not complete in that it was meant only for data closures and will for other closure types, e.g. thunks, return no data and no pointers (as can be seen in the code). So I implemented my own version of this operation:

foreign import prim "slurpClosurezh" slurpClosure# :: Any -> (# Addr#, ByteArray#, Array# b #)

where the returned ByteArray# contains the complete closure, including extra information fields such as the arity of a function. The Array# is again the list of pointers in the closure. At first glance, this is a duplication, as the pointers are of course also contained in the ByteArray#. But as soon as the GHC runtime reigns again, a garbage collector run can happen, the referenced values will move somewhere else, and the words that once were pointers in the ByteArray# become useless. But the corresponding entries in the Array# are updated by the garbage collector, as it knows that these are pointers, and not just words. This way, we get both a faithful copy of the closure on the heap and useful references to the contained data. Here is a demonstration of this effect:

$ ghci -XMagicHash -package ghc-heap-view
GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
[..]
Loading package ghc-7.4.1 ... linking ... done.
Loading package ghc-heap-view-0.1 ... linking ... done.
Prelude> let {a = [1,2,3,4]; b = 5:a}
Prelude> :m + GHC.HeapView 
Prelude GHC.HeapView> rawHeapData <- getClosureRaw b
Prelude GHC.HeapView> rawHeapData 
(0x000000004080d658,[1082185320,140040739366568,140040739365928],[0x00007f5dc68626a8,0x00007f5dc6862428])
Prelude GHC.HeapView> System.Mem.performGC
Prelude GHC.HeapView> rawHeapData 
(0x000000004080d658,[1082185320,140040739366568,140040739365928],[0x00007f5dc41b3ad8,0x00007f5dc41b3b28]) 

The function rawHeapData is a thin wrapper around slurpClosure# which turns the primitive array in normal lists. Note that the second component of the triple is unchanged, but the third is updated by the garbage collector. Of course this means that the Show instance for the data type that ghc-heap-view uses to reference values is not referential transparent either.

The foreign function import above is of type “prim”, i.e. does not call a C function but rather a Cmm function. Cmm is a reduced C that GHC uses internally to compile the Haskell code to, and most primitive operations are implemented in this language – although I do quickly call regular C from my Cmm code to do the more complicated stuff, mainly figuring out what words of the closure are pointers.

The knowledgeable reader might notice that I am passing a boxed value of type Any to the foreign function. This is currently not possible with foreign prim functions, and to actually use that code, you need the patch in GHC ticket #5931. But you can use ghc-heap-view without that as well (and the Cabal package will by default use that path), using the following hack to obtain the pointer to a Haskell value on the Heap as an unboxed type that can pass to the primitive operation:

foreign import prim "slurpClosurezh" slurpClosure'# :: Word#  -> (# Addr#, ByteArray#, Array# b #)
data Ptr' a = Ptr' a
aToWord# :: Any -> Word#
aToWord# a = case Ptr' a of mb@(Ptr' _) -> case unsafeCoerce# mb :: Word of W# addr -> addr
slurpClosure# :: Any -> (# Addr#, ByteArray#, Array# b #)
slurpClosure# a = slurpClosure'# (aToWord# a)

This works because a Word and a Ptr' have the same closure layout, only differing in the fact that one stores an a, and the other stores a Word#.

Once we obtained the raw representation of the closure, we do the parsing in Haskell. Using the info table and the raw closure, we have enough information to tell which words have to be replaced by the appropriate pointer (which might already have been updated by the garbage collector) in the pointers list.

This work was supported by a scholarship from the Deutsche Telekom Stiftung.

Sunday, February 26. 2012

GHC 7.4.1 speeds up arbtt by a factor of 22

Haskell

More than two years ago I wrote arbtt, a tool that silently records what programs you are using and allows you to do statistics on that data later, based on rules that you define afterwards, hence the name automatic rule based time tracker. I wasn’t doing much with it recently (the last release has been half a year ago), but it nevertheless was running on my machine and by now has tracked a total time span of 248 days in 350000 records.

Yesterday, I had a use for it again: measuring the time spent creating a certain document with LaTeX. So I added a rule to my categorize.cfg and ran arbtt-stats. I knew that it was not very fast, and that my data set has grown considerably since I last used it. And indeed, it took more than 6 minutes to process the data and spit out the result.

Since I’m currently working on the GHC 7.4.1 transition in Debian anyways, I decided to check what happens if I compile the code with that version of the Haskell compiler, instead of the previous version 7.0.4. And behold: The whole process took merely 17.3 seconds to complete! At first I did not believe it, but the result was identical, both binaries were built with the same option, i.e. no profiling enabled or anything like that. Wouldn’t you also like to have such speed ups for free, just by waiting for someone else to improve their work?

I tried to find out the reason for the speed up and created profiling output from both the old and the new binary. The old binary spends 83% of the time in Categorize.checkRegex, which basically just call Text.Regex.PCRE.Light.match. Since the version of pcre-light is the same in both binaries, I conclude that the Foreign Function Interface that GHC provides to interact with C libraries (libpcre in this case) is much faster now, although I do not find any mention in the release notes. And even if I do not count the 83% time spent in checkRegex, the code from the new compiler is still 2.7 times faster. Thanks, GHC devs, great work!

Wednesday, February 15. 2012

Including full LaTeX documents in another LaTeX document

Digital World

Assume the following situation: You set problem sheets for a class, and at the end of the semester, you have 13 individual LaTeX files, including the preamble (the stuff from \documentclass to \begin{document}). Now you want to provide a file that contains all problems, followed by all problems with solutions. You could just concatenate the resulting PDFs, but that would waste quite a bit of paper, as most problem sheets do not fill the whole page. You could just copy’n’paste the LaTeX code, but that is not neat either.

So you want to include the 13 individual documents in one LaTeX document. LaTeX provides \include and \input commands, but these would require that the content of the individual files, i.e. the stuff between \begin{document} and \end{document}, is put in a file of its own. You cannot just \input the full problem sheet document, as there must be only one \documentclass command, and a few preamble commands are invalid within the document.

There are various solutions suggested, e.g. on Wikibooks and StackOverflow, and there are packages helping with that functionality, such as combine or subfiles. I chose a rather rough, hands-on solution that worked great in my case: The idea is to simply re-define all commands that you have in your preamble to do nothing, including the document environment, before including the other files and constraint to a group. In my case, the preambles were relatively small, as the common definitions of the problem sheets were in a file of their own. I am also using the \foreach command provided by the TikZ package for a convenient loop over all problem sheets:

\foreach \x in {0,...,13} {
  {
    \excludecomment{solution}
    
    \DeclareDocumentCommand{\documentclass}{om}{}
    \DeclareDocumentCommand{\usepackage}{om}{}
    \newcommand{\Blattnummer}[1]{}
    \DeclareDocumentCommand{\FirstDueDate}{mmm}{}
    \DeclareDocumentCommand{\ThisDueDate}{mmm}{}
    \newcommand{\SkippedWeeks}[1]{}
    \renewenvironment{document}{}{}
    \section*{Problem Sheet \x}
    \setcounter{problem}{0}
    \input{GraphTheoryProblems\x}
  }
}
\clearpage
\label{sols}
\foreach \x in {0,...,13} {
  {
    \newenvironment{solution}{
      \par\addvspace{1em}
    }{
    }
    \DeclareDocumentCommand{\documentclass}{om}{}
    \DeclareDocumentCommand{\usepackage}{om}{}
    \newcommand{\Blattnummer}[1]{}
    \DeclareDocumentCommand{\FirstDueDate}{mmm}{}
    \DeclareDocumentCommand{\ThisDueDate}{mmm}{}
    \newcommand{\SkippedWeeks}[1]{}
    \renewenvironment{document}{}{}
    \section*{Solution Sheet \x}
    \setcounter{problem}{0}
    \input{GraphTheoryProblems\x}
  }
}

To redefine commands taking optional arguments, using the xparse package is convenient. You can see how I include every file twice, first with the solution environment turned into a comment and then again with the solution environment actually showing its content. I create a section header based on the counter of the foreach loop, but I could have easily redefined \title and use that for a header, if my problem sheets had used that command (They don’t, as they calculate the problem sheet number and the due date based on the number in the filename – very convenient, and maybe worth a blog post of its own). The problem counter is reset for each file, so that the problems are numbered individually. I could have left this out, then the problems would be numbered consecutively across all included problem sheets.

The individual and resulting files can be found on the Graph Theory course website.

Sunday, January 15. 2012

c't features heisse-news

Digital World

Several years ago, I created a computer news parody page called “heisse news”, emulating the look-and-feel of the German “heise news”, an online newsticker run by the most important German computer magazin publisher. Although my page did not see an updated since almost four years, it's featured in the latest issue of the publisher’s main print magzine, c't, in the section “Websites aktuell” on page 168, which I find very cool. As it is only fair to give and take, I posted a new entry on heisse news, featuring their website in the same manneras they featured mine...

Saturday, December 24. 2011

First (academic) publication

Mathe

Nice christmas present: I just got message that the paper “Loop subgroups of Fr and the image of their stabilizer subgroups in GLr(ℤ)” that I extracted from my Diploma thesis in Mathematics, and which I submitted to the Israel Journal of Mathematics in November 2010 was finally published today, in “Online First“ form and under the doi 10.1007/s11856-011-0213-3.

Tuesday, December 6. 2011

Guest lecture on Haskell performance

Haskell

Today, I had some business in Bonn, so Janis Voigtländer invited me to hold a guest lecture in his advanced functional programming course, maybe telling the students more about “real world” use of Haskell, given that he teaches mostly the theoretical foundations. I chose to discuss an experience I made while implementing SAT-Britney, namely that for the sake of good runtime and memory performance, it may be neither ideal to evaluate a list fully lazily, nor fully strict, but to have something in between. For the talk, I demonstrated this by a small example, showed how to use the GHCi debugger to get some insight in the evaluation order of things, how to benchmark the program and read the ghc statistics and a profiling chart, and finally how to get the most out of GHC’s List Fusion. I wanted to also touch on QuickCheck, but skipped it to finish in time. The full text of my talk (including graphs) is available, but in German; if you want an English version convince your prof to invite me for a guest lecture as well.

Afterwards I sat down with one of the students of the course, Helmut Grohne, who happened to take part in the Debian bug squashing party last weekend and had filed a release critical bug against the Haskell grammar generator frown (no better link available, homepage seems to be down) to debug the problem. It quickly became clear that the bug was introduced by me (can you spot it?) when trying to make it compile with a modern GHC – slightly embarrassing for me.

Saturday, December 3. 2011

Some late recognition of metainit

Debian

Four years ago, during DebConf 7 in Edinburgh, I had the idea of creating init scripts not by hand, but rather describe them in a declarative way that handles most common cases and generate the real init scripts from them. Back than, this was partly motivated by the varying quality of init scripts and the advent of an alternative init system, upstart, for which proper service files could be generated as well.

I implemented the idea and uploaded it as metainit to Debian, but it did not take off. Only one package uses it, and this package is not used much either. The project basically fell dormant.

Yesterday, I got this mail:

Hi Joachim,

I'm not very familiar with Debian ecosystem, however our company has recently switched to exclusively using Debian based servers, please forgive me if there exists a better channel for sending patches.

We need (in house) to create a lot of trivial services and the sysv init system seems an ideal way to manage them, and metainit an great way to keep the config simple.

However all our scripts require a heartbeat, the way we normally do this is with a bunch of checkers launched from cron. Metainit was ideal, but lacked the simple 'status' task found in most init scripts.

This small patch adds that task, I hope you and others find it usefull.

Regards,

together with the mentioned patch. So it turned out that the idea was a useful one after all, although it found its use on our user’s machines, and not within the Debian packages, as I originally anticipated. Nice!

During the recent discussions about the latest init system, systemd, there were more thoughts about generating init scripts/upstart service descriptions/systemd units from a declarative description, and if metainit had taken off back then, things would be easier now. So if anyone feels like reviving the project: Please do.

Thursday, December 1. 2011

Poetry in the problem class

Mathe

I’m currently running the problem class for the graph theory course at the Karlsruhe Institute of Technology, held by Prof. Maria Axenovich. On one problem sheet, I felt like setting the question in verse, and indeed, two students submitted their solution is in verse form as well. I have assembled the problem and both solution – enjoy!

Tuesday, November 22. 2011

First contribution to a basic Haskell library

Haskell

While working on SAT-Britney, I made heavy use of the IntSet data type provided by the basic Haskell library “containers”. Since memory consumption was a problem, I looked at its implementation, which is a binary tree, and wondered whether this could be improved for dense sets by using a machine sized word as a bit map to represent a continuous part of the integers, so I started to implement it. The effect on my program was not as strong as I had hoped for, but nevertheless, the code made its way back into containers – after a thorough review and a considerable amount of further improvements by Milan Straka. I’m getting sucked deeper and deeper into the Haskell community... (which means that the Haskell community does not suck, of course.)

Sunday, November 13. 2011

Running GNOME 3 and noone will notice

Digital World

Two days ago, I finally brought my system up-to-date with regard to the GNOME packages that I use. I was very reluctant because I am using a heavily customized gnome-panel and I waited until all the applets that I use have been ported to gtk3 and the libgnome-applet library. I am the Debian maintainer of one of these applets, link-notification-daemon, and I have made the changes and tested them in a chroot before, but now that I am actually using it, I found and fixed more visual glitches. I think by now it is as usable as it was before on GNOME 2. I am still looking for someone to step up as the new upstream maintainer for it!

I had some trouble with gnome-session and notification-daemon, thought I found the cause and reported it, but a day later I could not reproduce it anymore. Weird. Other problems, such as the “busy cursor” not disappearing after the session start, or evolution going into a freeze also have stopped occurring by themselves.

Other problems I found and fixed, for example the battery status applet was not visible until a major state change, or panel applets were not loaded due to a race condition, or tooltips not working (which called for a fix in gtk+ itself). I also added to the xmonad package the files required to allow the user to select “GNOME with Xmonad” in GDM, and found out how to have Galeon appear in the list of possible default browsers.

I don’t really have to say much about GNOME3 itself. I disliked the default font, Cantarell, mostly because of the extra spacing that reduced the number of folders and mail I can see in evolution. (Also see what nekohayo has to say about that.) I also was under the impression that the font is much lighter, and I started to adjust the position of my laptop monitor to increase the contrast. So I switch back to DejaVu Sans.

I also disabled the sleep-on-lid-close feature – I often run backups, or download stuff, or compile stuff, or calculate stuff, so I want better control over this.

So, I guess, now that everything is almost as it was in GNOME2, I can say I like it...

Sunday, November 6. 2011

gtk-vector-screenshot featured in freiesMagazin

Digital World

I have published a small article in the November edition of the German electronic magazine “freiesMagazin” on gtk-vector-screenshot. Their format is especially nice for that, given that the vector screenshots are embedded as such in the PDF version of the magazine, so the reader can zoom in and check for herself that it is indeed a vector screenshot.

Thursday, November 3. 2011

Bildungssilo Uni?

Politik

Eine ungeschickte Wort-Trennung in der letzten Ausgabe von Zeit Campus zeigt, dass die Uni seit dem Bologna-Prozess ein reines Bildungs-Silo ist, denn was erhält ein Student nach 10 Semestern büffeln: Ein Mast-erzeugnis!

Sunday, October 23. 2011

RÜBE - T-Shirts für Veganer

Vor einiger Zeit war ich mit einem bekennenden Veganer unterwegs als mir sein Puma-T-Shirt auffiel. Ich fand das ein wenig paradox, dass jemand, der jegliche tierische Produkte ablehnt, ein Puma-Kleidungsstück tragen sollte, und so entwarf ich ein geeigneteres, alternatives Design:

Nun hätte ich euch gerne einen Link bereit gestellt, über den ihr das gleich als T-Shirt bestellen könnt. Sowohl spreadshirt als auch shirtcity bieten das eigentlich an: Dort kann man eigene Motive hochladen und bekommt eine Provision pro verkauftem Shirt.

Bei spreadshirt war das Hochladen der PDF-Datei kein Problem, und auch der automatische Qualitäts-Check, der zu dünne Linien breiter macht, machte einen guten Eindruck. Aber dann muss das Motiv noch durch eine rechtliche Prüfung, und da kam dann raus:

Die oben aufgeführten Motive bzw. Produkte beinhalten geistiges Eigentum Dritter oder verstoßen mit hoher Wahrscheinlichkeit gegen gewerbliche Schutzrechte oder Persönlichkeitsrechte.

Ich hab nochmal nachgehakt und auf andere existierende Motive hingewiesen, die bekannte Logos parodieren, aber nichts zu machen:

Das Motiv wurde für die Verwendung auf dem Marktplatz nicht freigegeben, weil es tatsächlich einer bekannten Marke ähnelt. Wir versuchen natürlich, die Motive so weit wie es geht, freizugeben. Allerdings ist es in diesem Fall nicht möglich gewesen, weil wir direkt darüber informiert wurden, daß die Verwendung einer Parodie nicht möglich sein wird, nicht auf dem Marktplatz und nicht ohne einen drohenden Konflikt mit dem Rechteinhaber zu riskieren. Das würden wir allerdings gern vermeiden. Ich hoffe, dass Du das nachvollziehen kannst.

Bei shirtcity hatte ich erst ein anderes Problem: Die Webseite erlaubte den Upload nur im Adobe-Illustrator-Format (und einigen weiteren noch obskureren Formaten), aber in keinem einzigem freien und standardisiertem Format. Ich habe die Graphik mit Inkscape erstellt und keinen Illustrator zu Hand, aber ganz so leicht lass ich mich als Kunde nicht abwimmeln. Erst versuchte ich es mit einem Konvertierungsprogramm (uniconvertor), aber das Ergebnis hatte Fehler. Dann wandte ich mich an den Support und bekam erstmal nur eine Antwort, die bestätigte, was in meiner Frage stand, mir aber nicht weiterhalf:

Die Vektor-Graphik-Formate die von unserem System angenommen werden sind:
.ai,
.cdr,
.fhx

Ich erklärte mein Problem ausführlicher und erwähnte dass Illustrator selbst kein Problem haben solle, Formate wie PDF zu lesen, erfuhr aber wiederum nur:

Vielen Dank für Ihre Anfrage, aber wir nehmen nur die Angegeben Dateiformate an. Sie sollten eine Methode wählen die das hochladen im Shop möglich macht.

Das wurde mir dann zu dumm und ich nahm einfach die PDF-Datei, änderte die Dateiendung zu .ai, damit die Webseite die Datei akzeptiert, und lud sie hoch. Und tatsächlich, kurz darauf erscheinte das Bild in meinem Profil.

Ich konnte das Motiv beschreiben und katalogisieren. Wenn ich es aber anklickte, um zu dem Teil des Shops zu kommen, in dem dann andere das Motiv bestellen könnten, landete ich stets nur wieder auf der Hauptseite. Als sich das auch nach ein paar Tagen nicht geändert hab, fragte ich mal nach, und erfuhr, dass nur ausgewählte Motive im Shop vertrieben werden – das hätte ich gewusst, bevor ich mir die Arbeit mache.

Also habe ich es mit den Shops sein lassen und stelle die PDF-Datei mit dem Rüben-Logo einfach hier auf meine Homepage, und wer damit sein T-Shirt oder sonst irgendwas bedrucken will, darf das gerne machen. Bei Bestellungen nur für sich müsste das auch über die genannten Webseiten gehen. Ich freu mich natürlich über Bilder der so entstandenen Werke oder zumindest ne kurze Mail.

Ach, und wer denkt dass eine Rübe im Vergleich zu einem Puma nicht dynamisch genug ist, möge sich dieses Video anschauen, das ich im Rahmen des Synfig-Workshops im Entropia Karlsruhe erstellt habe.

(Page 1 of 28, totaling 410 entries) » next page
Nach oben