If you are intializing a memory, you can specify a .coe file when you generate the memory core and the memory. Once implemented, will power up with the values in the .coe file. Refer to Xilinx documentation for information on how to do that.
for FPGAs, readmemh is synthesizable. Xilinx has slightly better support than Altera. Xilinx allows any generic/constant/literal to be used for a filename, while Altera only allows hard-coded literals. But both XST and quartus support readmem.
readmemh is simply placed in an initial begin-end block.
I suspect the issue is the invalid data width or such. I don't know the declaration of mem_RGB, nor the first line of "water.txt"
it is in the sections about inferring block rams. Also, Altera's tools are a bit dangerous in that in some cases they will fail silently. Eg, some use cases of inferred block ram will not use the readmemh line, but will not show any info/warning/error. Ironically, it becomes easier to mis-size (widths or depth) the entries in the readmem file as these conditions are warnings and will show that the RAM is initialized in synthesis.
https://www.xilinx.com/support/documentation/sw_manuals/xilinx13_1/xst_v6s6.pdf
This is described in the XST (13.1, v6s6) user manual on pages 86 and 221. The Quartus manual also shows how to use readmem. Just be sure to read the sections about all of the HDL issues with inferring specific hardware features, as they can be device dependent or non-obvious or benefit from additional synthesizer attributes. For example, many of Xilinx's non-slice registers only have synchronous resets, if any reset at all. Likewise, RAMs may need to register the address, but might not provide that registered signal back into fabric.
If you want to see something really interesting, look at the example of a true dual port inferred block ram starting on page 188 -- it uses VHDL's "shared variables".