Wednesday, March 19, 2014

[coding] The Best Punching Bags are Made of Straw Men

I've been accused of hating my "own kind" by various people.  In my defense...its completely true.  At the moment, the group of people I'd like to bitch about are Java programmers, who, based on useless answers I've been reading on Stack Overflow, are ostensibly obsessed with trying to make Java a non-turing-complete language.  Let me try to describe, with an analogy, the kind of frustration I'm dealing with at the moment:


Me:  "I'm trying to build a calculator, but when I run a Servlet inside [thing1] on [thing2], the 'Add' feature doesnt work."

Enterprise Java Dev:  "Well, what numbers to do you want to add?"

Me:  "Well I was gonna start with 5 and 8, but-"

Enterprise Java Dev:  "No problem!  Just edit your spring configuration--Spring is way better than Jetty because it has more xml--and add this:

<resources>
 
<resource>
   
<directory>${basedir}/src/main/resources/META-INF</directory>
   
<includes>
     
<include><add name="fivePlusEight"><operand which="left" type="five"><operand which=right type="nine"></include>
   
</includes>
   
<targetPath>${project.build.directory}/dependency</targetPath>
 
</resource> 
</resources>

...and that way you don't have to write any code!"

Me:  "mother fucking cuntbag"


Sunday, March 16, 2014

The State of Piracy

I just found an oatmeal comic that describes the exact process I go through over and over again when trying to watch movies.

In conclusion, fuck amazon for blocking linux users and bittorrent is awesome.

Thursday, March 13, 2014

[coding] Nancy Drew and the Case of the Fucked Up Camera Orientation

That Android devices may be held in different orientations, and that the users of those devices don't want upside down pictures is probably obvious to everyone.  For some reason, the Android SDK developers chose not to include right-side-up rotation code in the SDK.  It is clear that they knew there would be a nearly universal need for it because the put the alleged algorithm for it directly into the comments of the Camera API.  However they apparently couldn't be bothered to write the method to calculate it for us.

Which leaves me with The Problem.  I'm going to skip the intermediate steps because I don't remember them.  Here is what I know now:

1.  my camera rotation code is wrong according to the API documentation
2.  my camera rotation code is most definitely wrong according to common sense
3.  my camera rotation code works perfectly on:  the Nexus 7, the Acer Iconia A, the Acer Iconia B, the Digital2, and the lenovo Yoga 8.
4.  my camera rotation code DOES NOT work on the Galaxy Tab 3
4b.  The preview does work, but the final picture doesn't, and the preview and the final picture are using the same rotation angle.
5. the inputs and outputs of my camera rotation code are identical on the Galaxy Tab 3 and the Acer Iconia A.  That is to say, the camera angle is the same on both devices, and my resulting rotation calculations are the same value on both devices, AND I'm setting the same rotation parameters on the camera, but its working on the Iconia A and not on the Galaxy Tab.

I don't know whats going on.  The fucking code I wrote shouldn't work on any of the devices (I switched the front and back camera algorithms), and the behavior should be consistent, especially between the preview and the final picture.  Even worse, no one on stack overflow appears to be having this problem--that, or everyone asking the right questions are just being drowned out by people asking how to use the camera.

Once thing I'm doing differently is that I am choosing not to handle orientation changes myself--the sample camera code appears to assume that people would do that.  Another thing I can try is to look at the code for the camera app, if its open source.



[Edit]
Quick update:  android orientation handling is fucked up.  I still prefer it over windows phone though.

[Edit]
First of all, to get the source for the camera app apparently now you have to use git:

    git clone https://android.googlesource.com/platform/packages/apps/Camera.git








Fixed my code...the problem is now occurring only on samsung devices.

based on some spot tests, it looks like the culprit is the EXIF orientation, which the android documentation did warn me about...I guess I just assumed the android bitmap decoder knew how to read jpg files correctly.


[Edit]
The windows picture viewer ALSO ignores the EXIF orientation.

GIMP detects the orientation, and prompts you to "change" it if you want to see the image in the correct orientation.

What I'm gathering from this, is that EXIF orientation is bullshit, and also the Samsung camera device driver developers were fucking lazy.


[Edit]
Android provides an EXIF parser for you.

The EXIF parser provided by android cannot read from a Stream.  Only a file.  (the source code of the Camera app uses some 3d library that is not part of the SDK)

The Camera code callback gives you a stream, not a file.

The core design of Java can be accused of being bloated but it has, from the beginning, made a giant fucking deal about file vs stream abstractions.

You don't need to memorize Code Complete to avoid these types of design mistakes.


[Final Edit ?]
Yeah, so cam orientation is still messed up on this piece of shit Digital Pad 2.  I'm going to write that one off, partly because my code is consistent with the official camera app and partly because the manufacturer's website did not come up in web searches.

Ladies and Gentlemen, I give you fuckers the Glorious Arrow of Orientation:


That picture was actually taken on my Samsung Galaxy S 2 with the official Camera app, which means that since I was holding the phone ostensibly right side up, that file actually has the rotation wrong--if you open it in the wrong program, the arrow is pointing to the left.

So.

Conclusions:

There are four ways to get device orientation:

1.  toDegrees(getWindowManager().getDefaultDisplay().getRotation())
2.  toDegrees(getResources().getConfiguration().orientation)
3.  onConfigurationChanged(Configuration)
4.  OrientationEventListener

1 & 2 are equivalent, so lets revise our list for impact:

1.  toDegrees(getWindowManager().getDefaultDisplay().getRotation()) / toDegrees(getResources().getConfiguration().orientation)
2.  onConfigurationChanged(Configuration)
3.  OrientationEventListener

Each of those methods gives a DIFFERENT FUCKING ANSWER.  One of them actually only seems to give the values 90 and 180 regardless of which orientation.

The one that works with the Camera is #3.  Naturally, it is the most inconvenient to use.  You can't pull the value (and in fact, when your activity is getting created, the value might be wrong anyway so you have to update later), you have to receive it in the listener.  The value you get will be in the range [0-359], but the camera only takes {0, 90, 180, 270} so you have to:

lastReadOrientation = (orientation + 45) / 90 * 90 % 360;

Then you set the orientation on the camera.  The API code turned to be right, however you'll note that for the Front Camera, the preview is mirrored while the camera is not, so you need two different algorithms.

Next, some cameras actually give you a messed up picture.  That is to say the camera didn't actually rotate the image;  it just put a "hey this image is rotated" note in the EXIF header.

I don't give a fuck how well the data matches the EXIF standard;  the fact that the  platforms own bitmap decoder can't fix the rotation automatically  and probably half of the image editing programs out there ignore the EXIF orientation means the data is fucked up.

The official Camera app actually doesnt fix the orientation.  The android developers and most of the posters on stack overflow appear to believe it is acceptable to just save the corrupt picture and deal with the rotation every fucking time an image is loaded.  I consider that unacceptable;  so I'm rotating the image in memory.

If you were paying attention, you'll note that I just decided to do something the API devs didn't specifically anticipate.  As always, this means we're in for a big fucking headache.  First, the stupid ass EXIF tools in the API can't read bytes in memory.  So I used a third party lib:

http://javadoc.metadata-extractor.googlecode.com/git/2.6.4/index.html

    public static int getExifOrientation(byte[] jpg) {
       
        // http://stackoverflow.com/questions/12944123/reading-android-jpeg-exif-metadata-from-picture-callback
       
       
        if(jpg == null) return 0;
       
       
       
        try{
           
            //uses metadata-extractor-2.6.4.jar and xmpcore.jar
           
            Metadata metadata = JpegMetadataReader.readMetadata(
                    new BufferedInputStream(new ByteArrayInputStream(jpg)), false);
           
            // Get the EXIF orientation.
            final ExifIFD0Directory exifIFD0Directory = metadata.getDirectory(ExifIFD0Directory.class);
            if(exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION))
            {
                return exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);

               
            }
            else
            {
                return 0;
            }
           
        }catch(Exception e){
            log("cant read exif orientation", e);
            return 0;
        }
    }
   
    public static Matrix getMatrixForExifOrientation(int exifOrientation){
       
        // from http://stackoverflow.com/questions/12944123/reading-android-jpeg-exif-metadata-from-picture-callback
       
        final Matrix bitmapMatrix = new Matrix();
        switch(exifOrientation)
        {
            case 1:                                                                                     break;  // top left
            case 2:                                                 bitmapMatrix.postScale(-1, 1);      break;  // top right
            case 3:         bitmapMatrix.postRotate(180);                                               break;  // bottom right
            case 4:         bitmapMatrix.postRotate(180);           bitmapMatrix.postScale(-1, 1);      break;  // bottom left
            case 5:         bitmapMatrix.postRotate(90);            bitmapMatrix.postScale(-1, 1);      break;  // left top
            case 6:         bitmapMatrix.postRotate(90);                                                break;  // right top
            case 7:         bitmapMatrix.postRotate(270);           bitmapMatrix.postScale(-1, 1);      break;  // right bottom
            case 8:         bitmapMatrix.postRotate(270);                                               break;  // left bottom
            default:                                                                                    break;  // Unknown
        }
       
        return bitmapMatrix;
    }




That code will probably look like shit...I don't care.

Next, we have to deal with the fact that bitmaps can be transformed in place.  You have to create a new bitmap in the process, which invariably causes an Out of Memory Error.

To mitigate this, first put this in the application tag in your manifest:

android:largeHeap="true"


Secondly, ONLY do the transform if the EXIF orientation != 1.  One means no orientation change, and--of the devices I found in Best Buy--samsung appears to be the only manufacturer I found that uses the EXIF orientation, so by limiting the transformation code to only those devices we greatly reduce the chances of Out of Memory Errors.

Fun fact:  The Samsung Galaxy S 2 cannot do reverse portrait.

Also, it is important to be constantly setting the camera orientation when the orientation listener fires.  You can't rely on having your activity recreated, or even on onConfigurationChanged() being fired when doing orientation changes manually;  the value will be wrong at those points in time, especially when you physically rotate the devices more than 135 degrees in one shot.  Also, the Acer Iconia A series seems to have the completely wrong orientation when the activity starts, so you need the listener to fire to fix that.

Tuesday, March 11, 2014

[coding] sudo vim /etc/motd

The programs included with The Linux Operating System are "free" software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright ...all you need to know is
they they all come with strings attached.

The Linux Operating System comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.


The raspberry device is pretty cool, but the recommended linux flavor is based on one of those douchebag versions that tack that weird shit on the front of the name linux.  Since none of the "free" software zealots are ever going to log into my print server, I thought I would save this message here in case a good opportunity ever presents itself.

Saturday, March 8, 2014

Philly / NYC 2014 Part 2

First things first.  I've accomplished my primary mission:  to find an apartment in NYC.  It was more difficult that I thought it would be, but luck, it would seem, had my back.

I literally booked a flight, threw my checkbook in a bag, and headed to NYC to find apartments.  I'm not joking; that was my plan.  In hindsight, this turned out a lot like the time I hopped on a plane to Kristy's wedding with no real plans and arrived to my surprise at a tiny airport with whicker chairs and, literally, no public transport.  I'm using the old definition of literally; there wasn't even a taxi stand. 

Anyway, turns out I showed up here way to early to get an apartment for May.   Most of the apartments on StreatEasy and craigslist were for either Right Now, or April.  Also, brokers want more paperwork than a checkbook.  They dont even take personal checks.  They want consecutive pay stubs, W2s, bank statements, and letters of recommendation.  Lots of letters of recommendation.  Like they thought my current apartment complex was going to bother writing a letter for me.

The thing that saved me was that I found a 'housing wanted' section of craigslist where people who need apartments are the ones who post the ad.  Seemed kind of backwards but I threw something up there on a whim.  Turns out that saved my ass, because exactly one of the responses ended up being perfect.  I got a temporary sublet on a two bedroom apartment in an area with young people where I can commute to work on the subway in a reasonable amount of time and I can keep my car in an off-street space.

It was rather amazing how much the entire trip changed for me as soon as I wired the deposit.  Previously I was quite stressed and questioning my overall game plan here.  I started to wonder if I really liked new york for itself, or if I just liked the fact that it wasn't seattle.  I mean, so far my favorite things about it are the simple facts that a subway system exists and people know how to cross the fucking street.  I'm not even joking;  those are my two favorite things right now.  Anyway.  The moment my living space was secured Everything became Awesome.  All the fun I've had since was just gravy.


So now that all that is solved, what to do with my last night here?  I tried going to a comedy show last night, but it was a very small venue, and apparently in venues that small all of the comics make crowdwork (making fun of people in the audience) most of their show.  I narrowly escaped being ridiculed because I ended up at the same table with a nice Venezuelen couple and the comics all assumed I was their light skinned Venezuelan friend, and apparently couldn't think of anything funny about that.  My real Venezuelen friend is going to be quite amused when he finds out about that. 

Tonight...idk.  I think I'm going to go find some pho, and then find another comedy show.

Thursday, March 6, 2014

The Potential Milestone

For this start up thing...our first beta tester received a production version of the app and apparently likes it.

I'm pretty sure I should be celebrating but I am too busy waiting for something to go wrong.

In other news...in NYC presently...I have no idea what I'm doing.

Sunday, March 2, 2014

Funny Hats

It has been a long, eventful, and interesting weekend.  I have continued my policy of, when being presented with two choices (left or right, to do or not to do), I always choice the option that, even if its the wrong choice, will at least bring me perfect clarity regarding which one I should have taken.

The highlight of the weekend was skiing.  I bought a silly hat, because my tiger hat is kind of broken.  This new hat was made for skiing, and it consists of hundreds of black and yellow dreadlock-like cloth ribbons that hang down to my waste.  I became somewhat of  a spectacle because I made a habit of skiing backwards to the cliff edge and then bombing the run with a friend, my fake dreads flying in the wind.  It was awesome.

Sadly, my silly hat did not bring me into the arms of a cute girl.  I will wear it again tomorrow.


Everything about the East Coast seems amazing.  Every turn I make on the roads makes me wish I had my WRX here to tear them up.  Every bridge I take makes me wish I had my sportbike to ride on.  Every familiar face I see makes me wish I never left.

In a strange way, it seems like I left very recently.  Despite all thats changed certain things have stayed very much the same.  Can I rekindle old connections?  Maybe.  Either way I'm going to have to make lots of new ones.