My first reaction would be to use a large external RAM to keep the data being edited in. But instead of making that a direct image copy, I would pre-allocate blocks of RAM in a linked list. Each block would have a forward pointer, backward pointer, used size, and the fixed-size data buffer.
Make each block a power of two bytes in size. That means the low few address bits for each block are known to be 0, so don't need to stored. The forward and backward pointers could then be 16 bits and the used length 1 byte, for a total of 5 bytes overhead per block. With 32 byte blocks, for example, this represents 16% overhead. 1 Mbyte of RAM would yield 885 kBytes of actual data storage, well more than the 300 kBytes you asked for.
In effect, this scheme creates a linear memory that can have data inserted or deleted at arbitrary places with little overhead. When adding or deleting, you don't have to look past the adjacent blocks in the chain, so can easily be done instantaneously in human time.
You keep two chains, one for the blocks holding the data and one for the unused blocks. Just the right kind of editing in just the right places could cause so much fragmentation overhead as to make the memory look much smaller, and eventually unable to hold 300 kBytes. However, such specific editing is unlikely to occur, and you can always do simple local recombinations (if two adjacent blocks hold less data than one block, then merge the two and put one back on the free list) which will most of the time keep fragmentation down well enough. Fragmentation doesn't actually matter until you need a free block and there isn't one. When that happens, you do a defrag and the user has to wait a few seconds, but this will be very rare. A good strategy would be to do automatic defrag in the background during the inevitable long periods of time (from the processor's point of view) where the user is doing nothing. With this strategy, I think it's very very unlikely you ever run out of free blocks and have to defrag while the user waits.
This scheme is easy to manage even in a small microcontroller, user response to editing operations is fast, and the SD card is only accessed at the start and end of editing sessions.
I was considering fragmentation more after writing the post, and I think it can be shown that as long as you do simple local defrag on any insert or delete operation, you never loose more than 1/2 of the available memory. Using the 1 Mbyte memory with 32 byte blocks example again, you are guaranteed at least 442 kBytes of storage.
After a delete, you merge the block that had a byte deleted with one of its neighbors if the two together now hold one block worth of data or less. On a byte add, you flow data from the current block into a neighbor to make room instead of grabbing a new block unless both neighbors (and of course the current block) are completely full.
All these operations never envolve more than 3 blocks, so are instantaneous in human time. If you can live with up to half the available memory unused, then you don't need to do anything further. There is little harm in doing background defragging though when nothing else is going on.