What I did was to get media folder and save there the cropped image. After that update meta data:
$imageToCropPath= get_attached_file($attachmentId); // Get file path to the image that will be cropped
$img = imageCreateFromJpeg($imageToCropPath);
$croppedImage = imagecrop($img, ['x' => $cropX,
'y' => $cropY,
'width' => $cropWidth,
'height' => $cropHeight]);
$uniqueId = md5(uniqid()); // Create unique name for the new image
$imagePath = wp_upload_dir()['path'] . "https://wordpress.stackexchange.com/" . $uniqueId . '.jpg';
imagejpeg($croppedImage, $imagePath); // Save image in the media folder
$attachment = array(
'post_mime_type' => 'image/jpeg',
'post_title' => basename($imagePath),
'post_content' => '',
'post_status' => 'inherit'
);
$croppedAttachmentId = wp_insert_attachment( $attachment, $imagePath );
$attachedData = wp_generate_attachment_metadata( $croppedAttachmentId, $imagePath);
wp_update_attachment_metadata( $croppedAttachmentId , $attachedData );