function encodeBmp(s:String){
s = Base64.Encode(s);
var width:Number = Math.ceil(Math.sqrt(s.length/4));
var bmp:BitmapData = new BitmapData(width,width,true,0x00000000);
var pos:Number=0; //track position in string
for(var x:Number=0;x<width;x++){
for(var y:Number=0;y<width;y++){
var col="0x";
for(var i:Number=0;i<4;i++){
col+=getHex(s.charAt(pos));
pos++;
}
bmp.setPixel32(x,y,col);
trace(col + " > 0x" + bmp.getPixel32(x,y).toString(16));
}
}
return bmp.clone();
}
Basically, the trace statement returns this:
0x56326868 > 0x56326868
0x64434270 > 0x64424270
0x63794230 > 0x63794331
...
Why is the result of getPixel32 different from that of the set value, and how can I resolve this?
EDIT: getPixel is accurate, but doesn't have the extra bit that get/setPixel32 does... I would prefer to have more data per pixel.
You're Base64 encoding a String to store it in a BitmapData. I hope you didn't know that, or are ashamed.
Anyway, here is what I see happening:
First, if you type col as a String, you'll get a compile error on setPixel32, because it's expecting a uint.
Now, we can ignore all the looping and hex strings to get some simple code to reproduce the problem.
var bitmapData:BitmapData = new BitmapData(1, 1);
bitmapData.setPixel32(0, 0, 1682129520);
trace(bitmapData.getPixel32(0, 0));
By using an int literal, we can see that it's not a problem with type coercion, but something inside of BitmapData. This makes sense, since BitmapData is intended to store graphics data, so storing the graphics in a way that is graphically similar but not exact is fine.
You're probably seeing the side-effects of pre-multiplied alpha in Flash. This would also explain why you don't see any problems with getPixel and setPixel.
You can read more about it here: http://www.quasimondo.com/archives/000665.php
So how do you fix the problem? Use the correct data type. A ByteArray is designed to store binary data.
Related
I have a type:
type T =
{
a: int
b: string
}
and an array of type T called 'myArray'.
and I want to serialize myArray with FSPickler:
FsPickler.CreateBinarySerializer().Pickle myArray
but in the pickle file, the type T is fully qualified and if I relocate it to another app/namespace, then the unpickle fails.
I asked on the FSPickler git but the answer I received is:
Per documentation in http://mbraceproject.github.io/FsPickler/ the serializer is not > designed with version tolerance in mind. That being said, it should be possible to work > around that issue by providing a custom implementation of the ITypeNameConverter interface.
ok, fair enough.
However, the documentation is providing examples clearly written by someone that knows picklers in general and geared toward other people that know picklers as well.
Can anyone post an example where I could make a custom serializer / deserializer for this basic case? From the docs, I see all the odd cases explained with the assumption that the reader knows how to make a basic serializer with FSPickler.
Or, maybe I missed something terribly obvious in the doc and I'd gladly recognize it if I saw it :)
The doc is here: https://mbraceproject.github.io/FsPickler/tutorial.html
and, for context, I'm going through 24 GB of data (with a type more complex than in this example obviously), so SPEED is everything and FSPickler seems quite fast.
There doesn't seem to be any documentation on this at all, but I managed to hack together something that works. The trick I found is to use a very simple converter that always uses the same type name, like this:
let converter =
{
new ITypeNameConverter with
member this.OfSerializedType(typeInfo) =
{ typeInfo with Name = "dummy" } // always use dummy type name
member this.ToDeserializedType(typeInfo) =
typeInfo
}
We can then pickle an array of Ts like this:
type T =
{
a: int
b: string
}
let tArray =
[|
{ a = 1; b = "one" }
{ a = 2; b = "two" }
{ a = 3; b = "three" }
|]
let serializer = FsPickler.CreateBinarySerializer(typeConverter = converter)
let bytes = serializer.Pickle(tArray)
And then we can unpickle it to an array of a different type that has the same structure ("duck typing"):
type U =
{
a: int
b: string
}
let uArray = serializer.UnPickle<U[]>(bytes)
I have no idea if this is the "right" way to do it. I found that ITypeNameConverter didn't behave like I expected. In particular, it seems that OfSerializedType is called during both pickling and unpickling, while ToDeserializedType isn't called at all. Maybe I'm missing something important.
I'm building a FF extension, and I'm processing some xhtml for myself in order to supporn subforms loading, so I have to identify the elements with l10n attributes defined and add them the string value. Because the l10n can't be shared from main code to content scripts (because isn't a simple JSON object), I managed the situation by getting the loaded keys values and defining an "localized array bundle", like this:
lStrings = ["step_title", ........ ];
for (var i = 0; i < lStrings.length; i++) {
bundle[lStrings[i]] = this.locale(lStrings[i]);
}
The thing is, I have to write here every entry in the .properties files... SO, do you know how to access this key values? I already tryed with .toString .toLocalString and inspecting the object, but can't find the way the object to be capable of returning all the key collection.
Do you have a better idea for improvement?
var yourStringBundle = Services.strings.createBundle('chrome://blah#jetpack/content/bootstrap.properties?' + Math.random()); /* Randomize URI to work around bug 719376 */
var props = yourStringBundle.getSimpleEnumeration();
// MDN says getSimpleEnumeration returns nsIPropertyElement // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIStringBundle#getSimpleEnumeration%28%29
while (props.hasMoreElements()) {
var prop = props.getNext();
// doing console.log(prop) says its an XPCWrappedObject but we see QueryInterface (QI), so let's try QI'ing to nsiPropertyElement
var propEl = prop.QueryInterface(Ci.nsIPropertyElement);
// doing console.log(propEl) shows the object has some fields that interest us
var key = propEl.key;
var str = propEl.value;
console.info(key, str); // there you go
}
See comments for learning. Nice quesiton. I learned more about QI from replying.
Lets say I have a GLib.Array<Item?> and want to convert that into a Item[], how would I do that in Vala?
First off, unless you need to for interoperability with existing code, don't use GLib.Array. Use GLib.GenericArray, which is much easier to use correctly and harder to use incorrectly.
GLib.Array.data is a regular array (Item?[] in your case), as is GLib.GenericArray.data, so you can just use that. If you assign it to an owned variable Vala will make a copy.
A naive approach would be, that you take out all the items from the array with the index() method and append them to an empty Item[] array, using +=.
A simple example program:
public int main (string[] args) {
Array<string> array = new Array<string> ();
array.append_val ("1. entry");
array.append_val ("2. entry");
string[] builtin = {};
for (var i = 0; i < array.length; i++) {
builtin += array.index (i);
}
return 0;
}
update: GLib.GenericArray really seems like a better solution. As for the data attribute: At GenericArray it is documented at Valadoc, at Array it isn't (that doesn't mean it does not work, but I haven't tried it).
Given a Map, assignment, what is the fastest way to check if it contains any duplicate values in Dart? I am currently using a Set formed from the Map's values and checking its length against the original Map, which works of course, but I'm wondering if there's an especially performant alternative.
Set d = new Set.from(assignment.values);
if (d.length < assignment.length) {
return false; // indicates has duplicates in this context
}
EDIT:
Tried #mezoni's solution modified for my program, but it actually ran a bit slower than my original version. It probably has more to do with constant times than anything else.
List values = new List.from(assignment.values);
Set set = new Set();
for (var i = 0; i < assignment.length; i++) {
if (!set.add(values[i])) {
return false;
}
}
Complexity wise you won't be able to get anything faster. Creating the Set and filling it with the values of the Map is linear in the number of elements. Clearly you have to run through all the values, so you can't do any better than that.
Maybe you could find a solution with a smaller constant factor, but that's not clear. In particular for larger sets I think the Set solution is pretty efficient.
This is more of a algorithms question than a Dart question. In any case, you have to check every value against the others, giving n-1 + n-2 + ... + n-(n-1) checks, or n^2/2. Programmatically, it's easy to create a set, but you could also generate an array, sort the array, and then iterate once to check for duplicates. That finishes in O(n log n).
Fastets way (if you realy need better performance):
void main() {
// Values from map
var values = [1,2,3,2,1,3,2,1];
var length = values.length;
var set = new Set();
var duplicate = false;
// Only for statistics purpose
var statistics = 0;
for(var i = 0; i < length; i++) {
statistics++;
if(!set.add(values[i])) {
duplicate = true;
break;
}
}
print("Duplicate: $duplicate");
print("Performed in ${statistics} iteration(s) from $length possible");
}
Output:
Duplicate: true
Performed in 4 iteration(s) from 8 possible
P.S.
The first example can be recommended to use with List values.
But because Map.values not a List but Iterable then it would be more efficient do not convert them to List but use as is.
Here is modified sample for use with Iterable objects.
It will be work faster because in this algorithm not required convert all values to the List object because it not want using of all elements without exception.
Instead it wants use as less as possible access operation on original source. If the source supports lazy operation of the access to values (as Iterable) this will be even better.
void main() {
// Values from map
var values = [1,2,3,2,1,3,2,1];
var assignment = {};
var length = values.length;
var key = 0;
for(var value in values) {
assignment[key++] = value;
}
var set = new Set();
var duplicate = false;
// Only for statistics purpose
var statistics = 0;
for(var value in assignment.values) {
statistics++;
if(!set.add(value)) {
duplicate = true;
break;
}
}
print("Duplicate: $duplicate");
print("Performed in ${statistics} iteration(s) from $length possible");
}
Its a little tricky to search for 'var:*' because most search engines wont find it.
I'm not clear exactly what var:* means, compared to say var:Object
I thought it would let me set arbitrary properties on an object like :
var x:* = myObject;
x.nonExistantProperty = "123";
but this gives me an error :
Property nonExistantProperty not found on x
What does * mean exactly?
Edit: I fixed the original var:* to the correct var x:*. Lost my internet connection
Expanding on the other answers, declaring something with type asterisk is exactly the same as leaving it untyped.
var x:* = {};
var y = {}; // equivalent
However, the question of whether you are allowed to assign non-existant properties to objects has nothing to do with the type of the reference, and is determined by whether or not the object is an instance of a dynamic class.
For example, since Object is dynamic and String is not:
var o:Object = {};
o.foo = 1; // fine
var a:* = o;
a.bar = 1; // again, fine
var s:String = "";
s.foo = 1; // compile-time error
var b:* = s;
b.bar = 1; // run-time error
Note how you can always assign new properties to the object, regardless of what kind of reference you use. Likewise, you can never assign new properties to the String, but if you use a typed reference then this will be caught by the compiler, and with an untyped reference the compiler doesn't know whether b is dynamic or not, so the error occurs at runtime.
Incidentally, doc reference on type-asterisk can be found here:
http://livedocs.adobe.com/labs/air/1/aslr/specialTypes.html#*
(The markup engine refuses to linkify that, because of the asterisk.)
It's a way of specifying an untyped variable so that you can basically assign any type to it. The code
var x:* = oneTypeObject;
creates the variable x then assigns the oneTypeObject variable to it. You can assign an entirely different type to it as well as follows:
var x:* = anotherTypeObject;
However, you still can't arbitrarily set or access properties; they have to exist in the underlying type (of either oneTypeObject or anotherTypeObject).
Both types may have identically named properties which means you can access or set that property in x without having to concern yourself with the underlying type.
It's the "untyped" type. It just means that the variable can be of any type. Basically the same effect as using this:
var x = myObject;
It means that the type is not specified and can be used with any type. However, you can't set random properties on it. It will behave like whatever type you set it to. The exact syntax is:
var x:*;
As they said before, it's untyped, so it may hold any kind of data. However, you cannot treat it as such in operations. For example, this is valid code:
var untyped:* = functionThatReturnsSomeValue();
But if you go one step farther, you have to watch out or you might get bitten:
var name:String = untyped.name;
Now, if the object returned by that function happens to be an object with a field with an id of "name," you are in the clear. However, unless you know for sure that this is the case, it's better to use typed objects. In this way, the compiler will alert you if you do something that might throw an error at runtime:
(elsewhere)
public class TypedObject()
{
public var name:String = "";
}
(and the code at hand)
var typed:TypedObject = functionThatReturnsTypedObject();
var name:String = typed.name;