Okay, let's walk through what's happening.
size = {200, 200};
img = Graphics[Circle[], ImageSize -> size]
You now have a Graphics expression. It gets displayed in the UI and looks like a circle. However, this is not an Image. The ImageSize options does NOT set the size of the matrix of image data. It's just telling the UI how large to display the image according to some nuanced reasoning that we've already discussed. So, if you want to end up with an image, an actual image data structure that has certain dimensions, this WILL NOT WORK.
ImageCrop[img, 0.9 size]
The image dimensions of the displayed Graphics expression is NOT {200,200}. Let's say it's {400,400}. Now you're cropping to {180,180}, which will crop out everything except the empty middle part.
So, you figured out a workaround:
ImageCrop[img, 0.9 ImageDimensions[img]]
And this works, but what would be much, much easier is to work with actual image data instead of graphics data. You can use Rasterize to turn just about anything into an image.
newImg = Rasterize[img, RasterSize -> {200, 200}]
Now you'll have an actual Image whose dimensions are {200,200}. In my Mathematica, it still DISPLAYS as the same size, but you can see the pixelization because of that. Use RasterSize -> {50, 50} to see this effect more clearly.
Okay, so now you're ready to crop. Let's just bundle it all together.
rasterSize = {200, 200};
graphicsSize = {500, 500};
cropFactor = .9;
ImageCrop[
Rasterize[Graphics[Circle[], ImageSize -> graphicsSize], RasterSize -> rasterSize],
cropFactor rasterSize]
You can play with different values for rasterSize and graphicsSize so maximize or minimize pixelation.