Be Developers' Conference Translation Kit Thingies Jon Watte |
Jon Watte: I'm Jon Watte. This session is on the translation kit. So what does the translation kit do? Well, it helps you translate data, obviously, in various formats. It's simplest form, it's a framework for taking data, anywhere, in memory in a file or on the network in one data format and translate into another format.
For instance, a GIF file into a bitmap, an HTML into a PDF file, or whatever kind of data transformation that you may want to perform in your application is a candidate. Some of you may have known about it before because it used to be known as Datatypes.lib. All of those things from the library have real adoption from third-party applications. And then Be came along and said, "This is a good thing. We want it." So when I got employed at Be, I just took the Datatypes, my sources, and munged them (unfortunately not using the translation kit) into a real Be kit.
So what we're going to talk about is how you can use your application strictly for import and export, how to extend it by writing translators into it. The translation kit is a regular BeOS kit. It comes in a shared library that you link with on PowerPC known as libtranslation.so. It also comes as a bunch of translator add-ons that actually perform the dirty work. It's a participant in the translation services, but your application is not a participant in the overall translation kit because your application cannot find out whether you are specifically a participant or not in the translations for the system.
How does this translator do its stuff? As I said, it's the translator add-ons that do all the hard work. We're going to go over quickly how one of these translator add-ons work. The translator add-on is a regular add-on that exports data and functions. The data is typically informational in nature; who made this translator, what can it do. It exports worker functions which are actually used in the translation kit to perform translations.
So you've got to be a little careful about the data you put in the translators. That data can be used in client applications, like menu items or list items, which also means that (unfortunately, this is the way it was designed two years ago) you have to create a new version of your translator for each language you want to support. If you want to have German menu items, you've got to have a German version of the translator. Unfortunately, a little bit legacy creeping into BeOS already.
The data that is exported from your translator add-on is the name of the add-on, not necessarily the name of whatever Datatype you're supporting. Suppose your translator, you can call it HTML to PDF. That's whatever you feel comfortable with, that's what the name of the translator should be.
There's the translator info strength which is more verbose, can be longer, can contain core information, shareware information addresses, secrets, the kind of thing you want to put in a little more secluded spot in your translator. There's the translator version, starting at 100. And it goes up. You set what version of your translator it is.
Currently the translation kit doesn't care, but a future version will find if there are duplicate translators installed that have the same name but different versions, it will use the later version. You can also tell in these two items the input formats and output formats; it's optional. InputFormats tells the world what your translator accepts as input and as reading. Output format tells the world about what type of data formats you're capable of writing from your translator. Those don't necessarily have to be the same. You can have something that can only read text, can only spit out executables. That would be a translator more normally known as a compiler. That's one way of thinking about it.
The export functions that do the real heavy work, the first function is "identify," and it's a required function. The translation kit will call "identify" within your translator whenever it has some data that doesn't know what it is at all. It doesn't know whether it's a text file, image, it has no idea. So it just goes down the list of all translators calling identify for each translator and the translator can say, "I have no idea what it is." It can say, "I looked for the magic cookie, and found it to be a bitmap file," or it can say, "The target format really doesn't have a magic cookie," but you can look at the fields, see where they extend, known values, within this chunk of data, and you can say, "Yeah I have a pretty good idea what this is."
What you do in your translator is you return the value from zero to one. It's a float, not an integer, so there's some play there. You can say, "I'm 0.4 sure this is the format. The translation kit can do some interesting things. Like return a list of translators sorted from most sure to least certain. The application can decide what to do.
There is the translate function which, the name implies, translates data. The format of that data is known already because the translation kit calls Identify on your translator first to determine what it it. That means your translator gets called twice, once the translation kit or the applications know what the data is or what format the data should be translated into. And it finds your translator somehow, either with help of the translation kit, or by the user explicitly specifying it -- translate, translator and your task is to take this one stream of data and turn it into this other stream of data that is requested. Fairly simple, but there is where the meat of your translator is actually implemented.
Two optional functions, MakeConfig and GetConfigMessage. Suppose you translate bitmaps into JPEG, you have a little, call it a slider that goes from zero percent to 100 percent, 1 percent to 100 percent. Unless you want really, really good compression. So that's your setting. It's not immediately obvious how to communicate the setting between the application that uses the translator and your translator. The way that communication happens is through a BMessage. The application can for any given translator ask the translator: Here is the message, please add whatever configuration you need to this message. I'll flatten this message and use it in two years. When I hand it back to you, rehydrate it and then please use whatever settings you are using now. So that's what your translator has to add to this message like, all the parameters you need. You could have a very elaborate setup, tweaky parameters.
However, there is another part. How does the user actually configure the slider? We were thinking about well, translator exporting settable values and ranges and applications figuring out how these relate, and we came up with a very complicated way of describing all this, which was way too complicated. This is supposed to be easy, quick, simple to use. So implement MakeConfiguration view and return a BView that knows how to edit your settings. The application will add you to a window and, you know, it assumes that whatever the user does to the view will be updated in the translator and once his window is closed, typically the application will call GetConfigurationMessage if your translator supports it." not get call, manipulated, translate support.
This is your claim to fame to actually provide a little part of user interface of every application that uses a translation kit. Please be gentle. No Kai's Power Tools, okay?
The translation kit itself is in a library, as I said before. At the core of how translation works is data format conventions. If you had one translator that can translate Lotus 123 to Excel, and another that can translate Word to RTF, to import text you would have to know about all the possible formats that translators could translate into and then why don't you read the formats directly,ignoring the translation kit. So for the translation kit there is a set of well defined formats, one for each kind of class of data that's the lowest level denominator that every translator is supposed to handle.
If your translator handles any type of text you need to read and write ASCII text, at least you can do it.
There is the BTranslatorRoster class. There is the BBitmapStream convenience class. This makes it very easy to read and write bitmaps stored in an instance of the system BBitmap class. There is the BTranslationUtils class, which contains utilities and standard functions. I didn't want to clutter the global name space with a lot of global functions, so instead I moved them all into the BTranslationUtils class as static functions.
So more about format conventions. There are some supertypes of data. There is bitmap images, text, vector images. There may be animated images and sound. I'll get to others in a while. And for each of these supertypes there's a well defined simple data format. Not necessarily to preserve all of the fidelity of the source format, but to make every application capable of reading a large amount of different file formats.
Also, for some reason I put this here, not elsewhere. Every translator uses BPositionIO . Any BPositionIO subclass works: BFile, BDataIO, BBitmapScreen, you could write your own BeNetworkIO class, that subclasses BPositionIO and BPositionIO interface and hand it to the translation kit. So your data doesn't have to live in files. It could live wherever as long as you can provide the subclass that knows how to access the data for each of these supertypes. Regarding supertypes: Remember, this \ was designed two years ago when the BeOS was different. So the translation kit, which stems from Datatypes, uses four-byte type codes to represent types in its interface. Usually in most places you can provide your type information format type or MIME string, but unfortunately for that case -- classes like image or bitmap or picts, it uses the four-byte constants, not actual strings. You'll have to use the classes by a trick of cleverness.
The format constant for a class format is the same as the constant used for identifying the type of low level format for the class. Another way to put it is that the type constant for B Translator Bitmap happens to be the name of the format for bitmaps, all bitmaps you want to read. This will make more sense when we go into code later in the session. for a class by a trick of cleverness."There's a BTranslatorRoster class. And as I said, this is what keeps track of what translators are installed in the system. This is what you use when your app interfaces with the Translation Kit, at least if you want to do kind of complicated and advanced things. Typically, what you'll do is use the default set of translators. The user can install translators in home/config/add-ons/Translators and system/add-ons/Translators. these translators that are the kind of default or general purpose translators will be loaded by the default translator roster, which you get from BTranslatorRoster::Default() If you're not a C++ guru, the code shows you how to exactly do this.
Typically, this becomes long to type; the documentation people give these functions these long names. What you'll want to do is use a temporary variable like this to help you write your program. Say, r = BTranslatorRoster::Default(); much better!
If you have specialized needs, suppose you're only importing specific subclass like CAD drawings or something and you have your own set of translators, you don't want to be installed in the general purpose, but installed in your own little folder somewhere, you can create your own instance of BTranslatorRoster. That will work fine, won't conflict with default. You can create your own and add your own translators and kind of customize what the translation kit will do for you. That's only for specialized applications.
Typical application just uses default code. Given a piece of code, a piece data, a file that you got from wherever, you have no idea what it is, you can still identify it using the translation kit. As you'll see this r, kind of shortcut, it's a good way of getting at the default translator. We create a Be file, the file you got from the network, and open it. We all need to identify it. And the information that we get from the translation kit will come out in a translator info, which you can find in the header file for the translation kit. You can go ahead and call Identify on this translate roster, pass in input and optional configuration. NULL is a very good value.
And last we get info. If this returns an error, typically no translator is installed that will recognize this file. If it returns okay, then your info contains some information bits: what is the supertype, bitmap or text file or so many or what it is. What image, Targa image? And it also comes up text description of what it is. So if you know the file format, it could actually very easily be implemented with the translation kit.
So we identified this as suppose it's text file in some format. Suppose it's some format that was used ten years ago. There's a translator installed for this format. So you identify the file, this is the text file, and what do you know, I know how to deal with text files. You use this little shortcut thing to get to the default translators some people define for you. There's no big overhead involved. It's just a lot of technical.
Again, we have the input position IO subclass which is a Be file. Then we have to have somewhere to translate that to, where to put the translated stuff. In this example we're using a BMallocIO. It has more data. So again, we call upon this translator roster. Translate from the input file using no special configuration into the output file, and what we want is the base level text format, which is the BeOS, ASCII text 3, no style, no markup, no nothing.
If there was nothing that could actually do this translation, we get an error back. The output stream will now have written to it the data in this format that we're requesting which was just regular text, so we'll go ahead. And suppose we have a text view laying around called SetText. The translator promises -- because it didn't return an error, it promises regular text. So we can go ahead and SetText. Pretty easy text import; isn't it? You could put this in your app; couldn't you? Good.
BPositionIO is nice because you can subclass it and you can make that do all sorts of neat tricks. There's one guy, I forget his name unfortunately, who wrote a HTTP subclass of BPositionIO. Actually, translate from something from URL directly. I thought that was kind of cool.
The BBitmapStream is another class of BPositionIO that performs read and write bitmaps using the standard bitmap format, basically saying this is the color space, the width, and this is the road map of the bitmap, and it kind of synthesizes from the bitmap data, the headers. When you read anywhere in the first 24 bytes of the stream, this will return what is supposed to be in that header. When you read anything after that little header, it will get things out of the bitmap. That's a fairly useful technique if you want to do a position IO, BBitmaps, without actually having to put everything in a big form of memory. This is very important when you want to use for buttons or display, whatever you want to use it for.
This is how you use it, the learning by repeating thing. This is very, very similar to the text import except -- again, all this typing, create input file, it could be something else, the bitmap stream for output and translate from this file to this output, and with the B Translator Bitmap format, which is the standard default format for understanding bitmaps.
Once we have the translation done, we're supposing this in return, no error now. We have DetachBitmap. Once you call it DetachBitmap, it's yours. If you never call the DetachBitmap, it will delete the screen, it goes away.
On to the next and last class which is BTranslationUtils. As I said, it's just a big grab bag of useful convenience functions for doing things. We have other kinds for doing others. Bitmaps are used in resource cases, also writing a game when you have different kinds of sprites, in separate files. It may be easier to just store them in some well-known format, Windows bitmap file or Targa file or some other very easily readable file.
Once you ship your application, you may want to have these bitmaps not in files where there is edit but in resources so you can move the file and all of the data follows the application without having a clutter of data files.
Well, luckily, there's a convenience function for getting a bitmap from either resource. It's called BBitmap. What this function will do is first look in the folder in which your application sits. The file in name now is splash screen. If it is there, it will translate from the file to the bitmap and return BBitmap, obviously. If the file is not there, it will go into the resources of the application to look for resource of typed bits, hard-coded, arbitrary what we used three years go. Resource type by the name, splash screen, use that data and translate that into a bitmap file.
So you can use NWBS as a last shipping stage for the application and beam all of these files into application resources and keep the same code working; you don't have to debug a different set of code. This just does the right thing. And even cooler if the user wants to replace the explosion in your spaceship or something, it can just stick one or two files with the right names in there. Those specific --
A Speaker: Will be read first.
Jon Watte: Those graphics will be read first. So I'm hoping to see some application to use that shortly.
Without add-ons, the translation kit does nothing. It sits there, takes up space, and is basically useless. So the add-ons are what add all of the value.
Now because that is the case, and it's kind of unfortunate we're shipping three add-ons, but we had some pretty severe things, translators to read and write and Targa and bit file formats. Luckily these are very common. The only two more common are JPEG and GIF. Unfortunately, we don't know, engineering doesn't get to sign licensing deals, so we don't know what will happen with GIF. Whether that will be supported or not, not up to me.
We hope there's actually going to be a viable third-party business: translators. If you are one of the those guys that just happens to have some Word document reading code laying around, maybe work for Microsoft, then you can make a business by writing. Just don't tell anyone I said that. I'm kidding here. You can write your own translators. You can install them in the home conflict add-ons translators folder, and every application that uses translation kit will instantly realize the benefits of your specific translator.
So obviously, we'll work ourselves toward the break even point or the point of no return. Someday the value of the translation kit is going to be so high that everybody is going to want to use it. Since everybody is using it, everybody is going to write translators, and we're almost getting there already on the PowerPC side because the data library has caused a lot of translators to be written, so there's a plethora. So we'll hopefully see those for Intel shortly.
What do you know, here's some more for Datatypes, used to be called Datahandlers, the Datatype translators. They use slightly different names. They're called translator names. Those old names work because we want to love these old translators, but sooner or later they will disappear. We encourage people to use the new names because this is the less official and we're not going to stay compatible with the old forever.
If you have an application that uses Datatypes, life is not as simple. You have to perform some surgery on your application because the Datatype driver was a C style function interface and now we change this into a Be class driven interface. Actually the names are almost identical so Datatranslator is now R2 translator. I did conversion of Datatype sample. Mostly global search and replace. So life is not that bad.
And then we have the, hey, I can't convert feu into feu* because the Be interface does not -- the Be API's typically don't use reference arguments. So everything that was reference and Datatypes is now a kernel. But the compiler will tell you where to fix.
Last are the structures that change names from translator. Again, the compiler will tell you what it doesn't know and then you just look at the header file in the various documentation. The online BeBook and the RFDC already contains translator kit documentation. It's been read. It's been reread, revised and I tend to think that Victor did a really excellent job. So if you run into him, just say, "Good job on that." Even if you didn't read it. Just trust me.
Advanced translation kit usage: custom set, new, and AddTranslators. It will scan for translators. And then you can archive this BTranslatorRoster because the BTranslatorRoster is Be archivable. And you can at some later point in time deflate that archive and use that translator archive. If you're writing a general purpose data conversion program like Midwatch, I strongly urge you to use the translation kit. For use of configuration of what translation to actually consider, if you want to have a little list where users can turn on and off different translators, this is what you have to do. You have to create your own translator roster and add the translator you want to use and you should have that list for later.
Also you can capture images from, say, a camera using a translation kit. This is kind of sneaky but works pretty well. One or two translators around that already do this. What you do is invent your own file format. This file format basically just consists of some magic dates and magic number; this is my file, nobody else's. And then some settings that tell your translator what to use, what port to, what your translator will do when it sees the file, I know how to file from there, file format into an image.
When the translate call comes, you open a window up and run in this window all the user interface you feel like running to talk to the camera and allow the interface to capture. The fun stuff, once the image is there, you write the data to the output stream. That's your translation from the steady file to the actual screen. Once this is done, you close your window and your application is done.
And last, you can also tell the translation kit to use a specific translator to form a translation. That's very useful if you want to do Save As.
I'm going to show you how to do that, but I'm not going to use these slides. This is the image application that ships with R3 instead of whatever the given application was called in R2. It uses the translation kit, weirdly enough. But if you have already installed and looked at R3, this image, this app which is a preview of the R4 is -- if you have an image, you can actually save the image. Incidentally, the same formats that have translators installed. And just to show you that, yes, I am really serious about this, here we have a good picture of our fearless leader for Windows NT format. If we go back up into home, you'll see yes, this is a Windows format bitmap file. We can go back in and open it again.
It looks very much the same, which is typically the case with these bitmap formats, but you tend to get the idea what this is good for. All right.
This is live source code, two days ago. Don't tell my boss that I'm actually showing you this. Don't be scared about the quality of the source either. This is one of those quick captures. This is the window that actually contains the image that we're showing and in the window we're creating many more, adding a bunch of menu items. Here is an item for Save As. Using MakeExportFunction, if you have a laptop, you could write this down and put that in your application and it will do the right thing if you want to export. I'm going to write a newsletter article basically with all of this sometime later this spring, and this code will get in there. If you can't memorize all that code, it's great for this article.
Create the menu, do the shortcut thing. And since we're not going to integrate all the installed translators, whether they can translate bitmaps, and if so, what formats they can translate bitmaps, ask the translation kit to get a list of all translators and then for each translator, we ask the translator, "So what formats can you beat?" If it can beat any formats in terms of error where the translator is not supposed to happen, but error taking is a good thing.
So for the good behaved translators that actually read formats, read over the formats looking for the B Translator Bitmap format. Again, this is kind of the standard format heavy we define for input, output that the Be stream bitmap provides for you. This translator can be a BBitmap.
So let's do more stuff with this translator. Ask it, "What output formats do you have?" We go, create all the formats and basically add these, each individual format, as a menu item to this menu that is the menu. We don't want to add the B Translator Bitmap, however, because, as I told you in the beginning of the session, every translator -- that the bitmaps should be able to write the bitmap format so every application that must import images has one simple format to understand and let the translator be a little more conflict-free.
If you had four BBitmaps, it wouldn't be all that convenient.
For this menu item you remember what was the format. This is it, the codes. What was the actual translation? You can use that as the message for the menu item for the export menu.
Leave the list of translators. It was allocated for us, but the documentation, you have to specifically leave this list and return to the menu. So when the user comes along, Save As, and it will go to MessageReceived, and do Save As and open a file panel. This file panel will get the same message, the model message. When the user then chooses the name, save, what will happen is the file panel will add the directory property to the message and then we'll go back. You know, the same constant, the same dispatch, same function, will pass this test. So this function really does two things. I apologize for the good quality.
Here we finally know where we want to stay. This is directory. We want to save it; the name of the file, we want to save it. This all comes from the panel.
The heading on the implementation of your application, you may have easier or more foolproof ways of getting at the bitmap you want to save, but this works, too.
This is the bitmap we want to save. We now have the file. Do you want to save? We created. I don't know if you knew this, but the storage kit actually allows you to pass these various code file flags. So you can say you created this file and truncated it, so zero. You don't need to deal with that separately. You can just have the Be file do that for you.
So we have a file to save to and we have the bitmap to read from. Now in the message we get back this format and the translator ID that we saved back when we created the menu so we know what translator to use and what format to save in. And last, the BBitmapStream on the Be class.
So finally we get to the meat of our export engine which is called translator. Using this translator, slightly different flavor of the translator which calls you to specify the specific translator. It works the same as the other translator, translate, which chooses for you.
From the input which is the bitmap to the output which is the file, using this format we can go from the menu item message. If there is an error, hey, we actually report it to the user -- helpful citizens here -- and we remove the file we created up here. Typically, there won't be an error. Unless we detach the bitmap, it will go away. We are using this window to display the image. It becomes unhappy. That's it. How you implement in 50 words of code or less a complete file export Save As menu in your application.
This, of course, I use bitmaps because I kind of like the data for it. You can use it for text data or vector data or other data that does not have realtime on the screens. There is no rule that translators can take 10 seconds to do their translation. No timing information really unless the data format you're reading and writing actually includes timing information. There is no API for timing information. So the translation kit is for import and export. It is not for realtime translation of the data. That is what the new media kit is supposed to do. I suggest if you're interested, attend the new media kit session tomorrow.
Thank you for coming. It's a pleasure. I know some of you have already used the translation kit, the new application, already using the translator kit, and it's already on BeWare. I find that amazing considering the time constraints, but it works. I've tried it. And I'm now going to take questions.
A Speaker: A couple of questions. Is there any chance of you posting that code or something similar to it to the FTP site?
Jon Watte: As I said, I'll write a newsletter article that will include the code. I may actually get around to doing that sooner than that. I'll try to remember that.
A Speaker: If you do that in your translation code, I think you're calling default and then leaking memory. Do you have plans for a formatted text supertype at some point?
Jon Watte: A very good question. I'm not sure if there's manpower right now to implement it. It would be very useful. I agree. But it would also require some -- the thing is you would really want to use well-known standard. There's no point in investing a data format if there's something out there already that does the job. Unfortunately, there's RTF, a total pain in the neck. You would want a data translator from RTF to something that could actually deal with it. Or you could use enriched text. Enriched text is very easy. Unfortunately, it's very simplistic. You can't do style sheets. Then there's not much else that I'm aware of unless you actually invent your own format. You need --
A Speaker: Be style text right now?
Jon Watte: Unfortunately, that is not a screen format. It is two-part, text and attributes. This much is text and this much is attributes. That would make it very easy, SetText, Be text. As I said, yes, we're looking at it. We are kind of short on manpower.
A Speaker: What does Be use?
A Speaker: Jon, can you repeat the questions when people ask them?
Jon Watte: He was asking the Be, it uses text files, runs through, sets file for each part of the text. Nothing to do with the translation kit.
A Speaker: Identifying member for bits? SOM format?
Jon Watte: The question was the SOM format, whether the data is 80 or 16-bit format. That is a correct observation. I felt an area too short, about as easy as you can get. You don't want to have to worry that if you are reading the SOM -- you don't want to worry if it is URL or what. You want to have one common format. And 16-bit format is the most common. The basic format for SOM format is 16-bit. The header actually allows you to change those parameters but the data is also too short. Read it and make sense out of it. That's kind of what the baseline format is all about. It's supposed to be easy to read and write.
A Speaker: What about MIME types since this is now an official, shouldn't we get into the MIME?
Jon Watte: The question is MIME types type constant. As I said, each and every of the translation kit functions allow you to specify both attack code and a MIME type. You can specify either and it will work, except for the supertype. The supertypes are, because we're going to use all of these translators, already out there for the data library. They expect the single type code for the supertype. For the supertype, we cannot use.
For all other types, for hinting, for instance, you can tell the translation kit, "I want to import this file," and the file says that it's the typed image slashed X bitmap or something else. You can get that and pass that in. That's the translation kit. So it can eliminate nine-tenths of all of the installed translators and do the job. So yes, MIME already works except for this one special case I specified.
A Speaker: On the one side where you're discussing the add-ons, you mentioned 3 with R3 and then you said planned, and what does RRaster mean?
Jon Watte: There was a bitmap raster. It was in R2. It used a plug-in format to identify specifically bitmap images. This was slightly less efficient than the translation kit way of importing data and also did not handle output, so that's why the translation kit is the class standard. Raster was kind of this sample code that we used to show people how to use add-ons and it just happens to, you know, become compiled as an image viewing application. Raster had a larger set of translators than the translation kit has right now and that's, you know, we're going to take all those raster translators that can only do the raster, quits both import and export. If you did anything using the raster, you should really stop doing that right now and use the translation kit and the translation kit will make sure to do all the raster things.
A Speaker: There was something for UNIX for translating files. How does this compare with that?
Jon Watte: Typically those UNIX utilities are hard-coded. They know a specific set of formats and that's all they know. The translation kit, a framework for plugging in any and all formats you want to write translator for, it's extendable. It works, has all this made up. The UNIX, for instance, don't typically give -- you couldn't do a Save As menu item, where as we kind of worked it so it is useful in the application in the translation kit.
A Speaker: What about a pict format?
Jon Watte: Vector graphics.
A Speaker: A lot of pict files it would be a lot easier to bring over to Be.
Jon Watte: The standard Apple pict format is complicated, two parts. I view this as the excellent third-party opportunity to write a parser that reads a pict file and spits out a Be picture and you can write that as a translator add-on. That will work just fine. I just don't have the time to do that and nobody else has time to do that. I'm sure you could actually charge money for that if you implemented it.
A Speaker: It seems to come in a variety of flavors, even one standard. How robust is the current TIFF translator?
Jon Watte: Actually uses the publicly available TIFF library. I think initially. It handles a wide variety of the various TIFF flavors. I'm not sure it handles each and every flavor that somebody at some point in time has decided to put inside TIFF, but it does -- it is capable of reading most of the currently available popular TIFF files out there.
A Speaker: Is there a general purpose -- what about like compression translators?
Jon Watte: Compression encryption?
A Speaker: Yeah.
Jon Watte: Those are similar. You could have translator translating from application/X GIF, but, however, the translation kit is explicitly not designed to do that because there are some things that we want to do with encryption and with compression that are different from when you know what the data is. The thing, when you encrypt something, compress it, you are just going to, if it's pict file, just data, and you can't translate data to other data without knowing anything about it. The translation kit is one step removed from that. It is data, knows data, and the purpose to figure out, is this data this, that. And using that, more specific type information, be even more specific, translate this bitmap into the specific BBitmap format, into the specific GIF format. I know there's been some talk about having a file transmunge a file or API that would handle maybe encryption and definitely compression. That wouldn't be using the current translation. The functionality is sufficiently different to warrant a different way of doing this.
Well, thanks a lot for coming.