Source

Usually when you create a form in Django, you have to know what items you want to allow as the initial values, otherwise it'll give you an invalid_choice error:

Select a valid choice. 'X' is not one of the available choices.

Normally it's fine, it's just some dope changing values on their browser and messing with your form by sending dodgy data.

But things get a little more complicated when you NEED dynamic choices in the form. For example, I want a form that will allow the user to list a bunch of cars with a given set of features. The "manufacturers" list we can generate using ModelChoiceField, but when you select one, it uses Ajax to dynamically change the "features" options.

note: This example is more verbose than it needs to be. That's just to help you understand what's going on. You can trim off the excess fat once you've got a hang of things.

Firstly, subclass the django.forms.MultipleChoiceField class.

class DynamicMultipleChoiceField(forms.MultipleChoiceField): # The only thing we need to override here is the validate function. def validate(self, value): if self.required and not value: raise ValidationError(self.error_messages['required'])

# Twig: This is part of the original code that we don't want. # Validate that each value in the value list is in self.choices. #for val in value: # if not self.valid_value(val): # raise ValidationError(self.error_messages['invalid_choice'] % {'value': val})

Now in your form, change the existing field of choice to use the new DynamicMultipleChoiceField:

What we've done here is set the field to be our DynamicMultipleChoiceField, but use the CheckboxSelectMultiple widget to render it.

When the manufacturer list changes, use Ajax to post the selected manufacturer information (your choice of either ID or name). Assuming you've set it up correctly, you can replace the whole choice field with the output from this view:

- If all required Diablo 2 '.MPQ' files are installed on the hard drive, the game will no longer require the CD to play.

For users that originally performed a 'Full Installation' and wish to run without the CD, all '.MPQ' files should be copied from the Diablo 2 CDs to the Diablo 2 directory. Most users will only need to copy D2Music.mpq from the Diablo 2 Play CD and/or D2xMusic.mpq from the Lord of Destruction CD. Mac users will need to copy these music files and rename them to 'Diablo II Music' and 'Diablo II Expansion Music' respectively.

So, assuming you've done a "full" install of the Diablo 2 game and that you've installed the expansion pack, you'll also need to copy over D2xMusic.mpq from the expansion CD to your installation folder (by default it should be C:\Program Files\Diablo II).

Something they forgot to mention is that you'll also need D2XVIDEO.MPQ as well. Otherwise you'll get the annoying "Insert Expansion Disc" message when you try to start the game.

It should work straight away once you've got those 2 files in your game folder.

if (cursor != null) { // Here you will get a null pointer if cursor is null // This can be if you used OI file manager for picking the media int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); selectedImagePath = cursor.getString(column_index); }

When I was first debugging my image watermark code, I found it strange it kept running out of memory. Why!?

You're doing it wrong!

Firstly, I was trying to edit an immutable (non-editable) Bitmap. You need to generate a mutable copy of the bitmap before you can start modifying it.

Secondly, my method was very heavy on memory usage. It involved loading the original immutable +4mega-pixel image into memory, then creating a new mutable Bitmap of equal size and colour depth, copying it over using a Canvas.

Keep in mind, the Android VM only allows 16M of memory per app. Each pixel in your image using ARGB_8888 can use up to 4 bytes of memory.

To help you get a perspective of things, a 32bit image with 724x724 has 524,176 pixels uses up 15.9M of memory. If you squish the sizes a bit, that's not very much on a mobile device, especially when you factor in that you need memory for other things in your app such as GUI elements and references to your Activity.

What does that mean? It means you can't load that 8mb photo on that SD card in full resolution no matter how hard you try. Your app has to make some compromises and trim it down a bit.

Not to mention my third step was to imprint a logo over the mutable new bitmap, which means loading yet another image into memory.

This is what the current situation felt like...

Looking for an answer

The internet and StackOverflow are littered with questions on this issue. Most responses tell you to either reduce the colour depth, partially process the bitmap or call Bitmap.recycle() on the source image before creating a new Bitmap.

Now that doesn't make much sense if I'm trying to COPY an image from Bitmap A to Bitmap B because I need both of them in order to do that.

Option A - Bump up the API level

BitmapFactory.Options has a new flag inMutable that allows loading of mutable bitmaps in Honeycomb (API level 11), but I try to maintain as much compatibility as possible.

If you choose to go this way, you will lose some of your market share. See the Android documentation for more information about which API level corresponds to the Android platform versions.

Since I don't actually have any Honeycomb compatible devices, this simply wasn't an option.

Option B - Load a smaller image

My preferred solution is to "pre-scale" the source bitmap so it isn't so damn big. That means loading it in a smaller immutable resolution so you have enough memory to hold both bitmaps at the same time.

The ideal size is 630px, since that's what Facebook uses for the photo album pictures and most people seem to be happy with it.

The downside is that scales works best in the power of 2's, so you can load an image that is 1/2 the size of the original, 1/4th the size, 1/8th the size, etc.

if (cursor != null) { // Here you will get a null pointer if cursor is null // This can be if you used OI file manager for picking the media int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); selectedImagePath = cursor.getString(column_index); }

Worked pretty well in the emulator! But for some reason on the actual test devices, it would fail every single time. Mind boggling!

After a few tests, I noticed something in the error logs.

decoder->decode returned false

The reason why the image fails to decode is because InputStream doesn't actually implement the skip() method.

This post pointed me in the right direction. Still unsure of how to implement it properly, it lead to Deep Shah's post. He had a perfectly solid implementation of FlushedInputStream that was well documented.

Below is a slightly cleaned up version with less documentation. If you need more information about how it works, see his post.