Я работаю над .NET-приложением, чтобы уменьшить размеры файлов изображений, используя ImageMagick. В моем приложении хранятся некоторые "настройки" в Hashtable
для использования в различных областях приложения. Теперь я добавляю функцию для уменьшения размера изображения на основе желаемого DPI в преобразованном изображении. В принципе, я просматриваю DPI в неизмененном изображении, вычисляя процентное соотношение желаемого DPI относительно текущего DPI, а затем я изменяю размеры изображения по этой пропорции.
ImageMagick передает изображение DPI как значения с плавающей запятой. Итак, 200x200 DPI действительно 199.975x199.975. Таким образом, я использую Math.Ceiling()
, чтобы получить значения в моем приложении. Когда я пытаюсь использовать желаемый DPI из моих настроек Hashtable
, чтобы выполнить вычисление процента, я получаю недопустимое исключение литых. Я не знаю, почему это происходит.
Вот пример, который терпит неудачу так же, как мой фактический код:
using System;
using System.Collections;
namespace typetest
{
class Program
{
private struct DPI {
public double x;
public double y;
}
public static void Main(string[] args)
{
Hashtable vars = new Hashtable();
DPI dpi;
string dpiString = "199.547:199.547";
string[] ret;
vars["newDpiX"] = 150;
vars["newDpiY"] = 150;
ret = dpiString.Split(':');
dpi.x = ( (double)vars["newDpiX"] / Math.Ceiling(double.Parse(ret[0])) ) * 100;
dpi.y = ( (double)vars["newDpiY"] / Math.Ceiling(double.Parse(ret[1])) ) * 100;
Console.WriteLine("New DPI percentage = " + dpi.x + "%x" + dpi.y +"%");
}
}
}
Если я изменю деление на
double newDpiX = 150.0;
dpi.x = ( newDpiX / Math.Ceiling(double.Parse(ret[0])) ) * 100;
он будет работать, как ожидалось. Что здесь происходит?
В Hashtable хранятся объекты. Когда вы помещаете int в объект, вы "вставляете" его. Unboxing требует того же типа, вы не можете преобразовать непосредственно из вложенного int в double.
Это не удастся:
object obj = 10;
double dbl = (double)obj;
Это будет успешным:
object obj = 10d; // a double value, could also have been 10.0
double dbl = (double)obj;
И это также будет работать:
object obj = 10; // an int
double dbl = (double)(int)obj;
сначала распаковывая int, и только затем сбрасывая double.
EDIT:
См. также http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx
Попробуйте
vars["newDpiX"] = 150d;
Использование:
dpi.y = ( Convert.ToDouble(vars["newDpiY"]) / Math.Ceiling(double.Parse(ret[1])) ) * 100;
Я думаю, ваша проблема в том, что vars [ "newDpiY" ] = 150; хранит int, а не double.
Объекты Hashtable hold, вам назначается 150, поэтому он хранится как int. Попробуйте назначить 150.0 или (double) 150 или что-нибудь в этом роде.