Тема: Растровое изображение

Вобщем идея такая. Есть растровое изображение. Мы его выбираем. А дальше делаем что-то похожее на rubersheet растердизайна. Только с бОльшим количеством вариантов "совмещения" точек рисунка с их новым положением. Все в принципе есть, математика не сильно сложная. Вот только одна проблема - это растр.
Можно конечно получить имя файла выбранного растра, потом с ним провести ряд действий, сохранив в другой файл, а потом незаметно вставить его вместо исходного.
Но. Автокад подгружает, по-моему, ВСЕ типы растров (jpeg, gif, bmp). Короче очень, даже очень лень писать собственную читалку для всех графических расширений с разными вариантами сжатия.
Первый вопрос.
Можно ли как-то получить уже созданную автокадом матрицу растра, ведь не с потолка же он рисует картинки?
На сколько я понял из хелпа она есть, и лежит в IeImg (если я не ошибаюсь). Только как ее достать?
Ну и второй вопрос, можно ли эту матрицу сохранять в графический файл?

...
ads_name entImage; ads_point p;
AcDbRasterImage * pImage;        
AcDbObjectId eId;
bool next = true;
while (next)
{
  switch (acedEntSel("\nУкажите растровое изображение: ", entImage, p))
  {
    case RTCAN :
      return;
    case RTERROR :
      continue;
    case RTNORM :
      if (acdbGetObjectId(eId,entImage) != Acad::eOk) return;        
      if (acdbOpenObject(pImage, eId, AcDb::kForRead) != Acad::eOk) return;
      if (pImage == NULL) continue;
    next = false;
      pImage->close();
    break;
  }
}
/* потом выбираются точки (уже в координатах растра) (кода много и он скорей всего не нужен, но если нада, могу выложить)
   дальше математика, получаем набор коэффициентов для изменения рисунка
//-> а вот тут уже нужна матрица пикселей растра.
*/

Re: Растровое изображение

Думаю, что этот код тебе поможет понять с чего начать:

static void ImageUtilGetPixel(void)
{
  ads_name name; AcGePoint3d pt;
  Acad::ErrorStatus es;
  if (acedEntSel("\nВыберите растр: ", name, asDblArray(pt)) != RTNORM) return;
  AcDbObjectId objId; acdbGetObjectId(objId, name);
  AcDbObjectPointer<AcDbRasterImage> pRaster(objId,AcDb::kForRead);
  if (pRaster.openStatus() != Acad::eOk) return;
  AcGeVector2d imgSize = pRaster->imageSize();
  AcGeMatrix3d mat; es = pRaster->getPixelToModelTransform(mat);
  if (acedGetPoint(NULL, "\nУкажите точку на растре : ", asDblArray(pt)) != RTNORM) return;
  acdbUcs2Wcs(asDblArray(pt),asDblArray(pt),false); // Не забываем про систему координат!
  AcGePoint3d pixpt(0,0,0);    pixpt = mat.inverse()*pt;
  int x = (int)pixpt[X], y = (int)pixpt[Y];
  if ((x > imgSize.x) || (x < 0) || (y > imgSize.y) || (y < 0)) {
    acutPrintf("\nТочка вне растра!!!");
    return;
  }
  acutPrintf("\nВыбран пиксель: (%d, %d)", x, y);
  AcDbObjectPointer<AcDbRasterImageDef> pDef(pRaster->imageDefId(),AcDb::kForRead);
  if (pDef.openStatus() != Acad::eOk) return;
  IeImg * pImg = pDef->imageCopy();
  IePixTyp pixType = pImg->pixTyp(); // Тип растра
  int imgBPP = pixType.bitsPerPixel(); // Количество бит на пиксел
  IeCxt * pCxt = pImg->getReadCxt(); // Считываем растр
  UINT pix = 0;
  switch (imgBPP) {
    case 1:  pix = pCxt->get1(x,y); break;
    case 8:  pix = pCxt->get8(x,y); break;
    case 24:
    case 32: pix = pCxt->get32(x,y); break;
  }
  acutPrintf("\nЦвет пиксела RGB = (%u,%u,%u)", GetRValue(pix),GetGValue(pix),GetBValue(pix));
  delete pCxt; delete pImg;
  return;
}

Re: Растровое изображение

А вот и второй пример:

static void ImageUtilSaveImage(void)
{
  ads_name name; AcGePoint3d pt;
  Acad::ErrorStatus es;
  if (acedEntSel("\nВыберите растр: ", name, asDblArray(pt)) != RTNORM) return;
  char buf[1024]="";
  if (acedGetString(TRUE,"\nУкажите имя файла для сохранения (без расширения): ",buf) != RTNORM) return;
  AcDbObjectId objId; acdbGetObjectId(objId, name);
  AcDbObjectPointer<AcDbRasterImage> pRaster(objId,AcDb::kForRead);
  if (pRaster.openStatus() != Acad::eOk) return;
  AcDbObjectPointer<AcDbRasterImageDef> pDef(pRaster->imageDefId(),AcDb::kForRead);
  if (pDef.openStatus() != Acad::eOk) return;
  IeImg *pImg = pDef->imageCopy();
  strcat(buf,"."); strcat(buf,pImg->fileDesc().fileType());
  pImg->storeFile(buf,pImg->fileDesc().fileType());
  delete pImg;
  return;
}

Re: Растровое изображение

Спасибо за помощь. Попробую разобраться

Re: Растровое изображение

> Александр Ривилис
О, родился еще такой вопрос интересный. На сколько я знаю Image Engine только для ACAD 2005/2006, а дальше автодеск хочет, чтоб все пользовались ATIL (Autodesk Technical Imaging Library). Там разница сильно большая? Может сталкивались?

Re: Растровое изображение

:) Это снова я
Раньше IE SDK не пользовался.
Сейчас прописал все пути в студии для подключения библиотек, вкинул в stdafx.h <ie.h>
и начал улыбаться:
- в adesk.h typedef char Int8;
- в csdefs.h typedef signed char Int8;
Убрал signed.
Дальше в первом примере error LNK2001: unresolved external symbol "struct IePixTypes const * const iePixTypes" (?iePixTypes@@3QBUIePixTypes@@B)
во втором error LNK2019: unresolved external symbol _ieFileDescConstructor2 referenced in function "public: __thiscall IeFileDesc::IeFileDesc(char const *,char const *,enum IeFileDesc::OpenMode)" (??0IeFileDesc@@QAE@PBD0W4OpenMode@0@@Z)
Что я делаю не так?

Re: Растровое изображение

1) В stdafx.h (если он сгенерирован ObjectARX Wizard) раскоментируй строку:

//#define _IE_SDK_SUPPORT_      //- Support for the Autodesk Image Engine API

и убери свой #include <ie.h>
2) В stdafx.h добавь до #include "arxHeaders.h" две строки:

#define CS_APP
#define CS_USEDLL

Пробуй.

Re: Растровое изображение

все получилось.
еще раз спасибо

Re: Растровое изображение

а как заставить Img перерисоваться при изменении точек, например, вставить в позицию x,y пустую точку.
Судя по хелпу IE это где-то так, но ничего не происходит :(

IeCxt * pCxt = pImg->getWriteCxt();
Ief * input = pImg->read();
pCxt->set1(x,y);
pImg->write(input);
...

Re: Растровое изображение

> Николай
Тебе придется сохранить изменения в файл и повторно загрузить его.

Re: Растровое изображение

А если у меня изображение с палитрой, для получения его цвета RGB я делаю так:

pix = pDestCxt->get8(x,y-1);
CsRgb8 rgbPix = colorSpace.get(pix);

Дело в том, что при растровых математических преобразованиях появляются точки, в которых ничего нет. Алгоритмов заполнения пустых точек я в IE не нашел, хотя по сглаживанию там куча :(
Что-то я отвлекся. При заполнении я беру среднее значение непустых точек и соответственно rgbPix[0],rgbPix[1]rgbPix[2] будут уже не такими как сначала.
как мне получить индекс из палитны максимально похожего цвета для rgbPix?

Re: Растровое изображение

сам спросил, сам и отвечу :)
У нас есть rgbPix - это цвет, полученный усреднением соседних ячеек (CsRgb8) Нада узнать индекс максимально похожего цвета

CsRgb8 rgb; // это будет цвет ячейки палитры
int fi, f_min=1000000;
for(int i=0;i <colorSpace.numColors(); i++)
{
  rgb = colorSpace.get(i);
  fi = 30 * pow(rgb[0] - rgbPix[0],2) +
       59 * pow(rgb[1] - rgbPix[1], 2) +
       11 * pow(rgb[2] - rgbPix[2], 2);
  if(fi<f_min){pix=i;f_min=fi;}
}
// здесь в pix будет храниться индекс максимально похожего цвета