First a general note: most clients have used SkPictures as a way to experiment with display lists and then almost invariably find they need something beyond what SkPictures allow (e.g. inspection, mutability, version stability) and wind up creating their own representation. Flutter, Chrome, and Android are all examples of this pattern. They all started with SkPIctures and eventually created their own display lists. So this is our recommendation. Serialized SkPictures are mostly used for debugging Skia issues (e.g. grabbing serialized SKP from client applications in order to debug a rendering problem in standalone Skia tools).
More specifically to your questions: I believe if you start with images that are created by SkImage::MakeFromEncoded and "draw" those to a picture recording canvas and then serialize the picture it will just write the encoded data into the serialization without ever decoding (and non-encoded images get written as PNG). On deserialization the images should stay encoded until they are drawn the first time. You can use SkGraphics::SetResourceCacheTotalByteLimit to set a cache size that will limit how much memory images (and other things cached by Skia) consume on the CPU. If you're using GPU then you may also use GrDirectContext's APIs for limiting the GPU cache size (texture memory). Please let me know if this isn't in line with what you're seeing.
Additionally, you can pass SkSerialProcs and SkDeserialProcs at serialization and deserialization time with customized functions to serialize and deserialize images. This would let you do something like compress all images in a lossy format to reduce size and then decompress on deserialization.