StretchBlt трабл

Тема в разделе "WASM.WIN32", создана пользователем Max, 5 янв 2005.

  1. Max

    Max Member

    Публикаций:
    0
    Регистрация:
    22 май 2003
    Сообщения:
    192
    вообщем есть два битмапа - src размером 903x1000, и dst размером 1029x944.

    надо src положить на dst с прозрачностью, предварительно сделав stretch до некоторого rect.



    пишется все это дело на делфях (ой!), но в конце концов все сводится к апишной StretchBlt.



    так вот, когда я делаю StretchBlt в прямоугольник rect=(142,66,3047,7325), то все нормально, а вот если увеличиваю ширину на 1, то есть получается rect=(142,66,3047,7325), то StretchBlt выдает ошибку, а GetLastError возвращает 0x8, что расшифровывается как "Недостаточно памяти для обработки команды".



    на машине стоит гиг озу, загрузка ~400Мб, ось - вин2к.



    кто мне скажет, в системе есть какое-то ограничение на размер битмапа?

    ...и как посоветуете с этим бороться?
     
  2. Max

    Max Member

    Публикаций:
    0
    Регистрация:
    22 май 2003
    Сообщения:
    192
    я так понял, никто не знает...

    придется писАть самому :)



    тогда такой вопрос на тему графики - как смасштабировать картинку собственными средствами?



    допустим есть битмап высотой 1000 пикселов, масштабируем его до высоты 100 пикселов.

    в простейшем случае получается, что мы должны взять каждую 10-ю строчку.

    но тогда теряется информация о строчках 1..9, 11..19 etc.



    кто видел описание более навороченых алгоритмов типа bilinear, bicubic etc?



    поделитесь плиз, а то заказ горит уже :dntknw:
     
  3. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    Max

    Возможно косяк 2к - в нем их монго - попробуй 2к3.

    Приведу свой грязный но рабочий код:
    Код (Text):
    1.  
    2. int CPicViewer::ShowPictures(HWND hwnd, HDC hdc, RECT *r, int nc)
    3. {
    4.   MyLock l(&lock);
    5.  
    6.   HDC MemoryDC = CreateCompatibleDC(hdc);
    7.   SelectClipRgn(MemoryDC, 0);
    8.  
    9.   int maty = (mats + matinrow - 1)/matinrow;
    10.   int mat = 0;
    11.   int drawed=0,ndrawed = 0;
    12.   for(int mat_ypos = 0; mat_ypos < maty; mat_ypos++)
    13.   {
    14.     int py = yofs + (sh + ytile)*mat_ypos + ytile/2;
    15.     for(int j = 0; j < matinrow; j++, mat++)
    16.     {
    17.       if (mat>=matspos) break;
    18.       FileBitmap *fb = cached_bitmaps[(mat + matsofs) % mats];
    19.       if (!fb) continue;
    20.       DIBSECTION ds;
    21.       GetObject(fb->CompatibleBitmap, sizeof(DIBSECTION), &ds);
    22.       //Bitmap *mb = fb->thumbnail;
    23.       int px = xofs + (sw + xtile)*j + xtile/2;
    24.       int x = px, y = py, w = sw, h = sh;
    25.       RECT r = {x, y, x + w, y + h};
    26.       // draw picture with aspect ration
    27.       int iw = fb->w;
    28.       int ih = fb->h;
    29.       int ix = x, iy = y;
    30.       int scale;
    31.       if (ScaleMode == SCALE_MODE_NORMAL) scale = (iw > w) || (ih > h); else scale = (iw != w) || (ih != h);
    32.       if (scale)
    33.       {
    34.         double fw = ((double)iw)/w;
    35.         double fh = ((double)ih)/h;
    36.         if (fw > fh)
    37.         {
    38.           iw = w;
    39.           ih = (int)floor(ih/fw + 0.5);
    40.         } else
    41.         {
    42.           iw = (int)floor(iw/fh + 0.5);
    43.           ih = h;
    44.         }
    45.       }
    46.       ix = x + (w - iw)/2;
    47.       iy = y + (h - ih)/2;
    48.       RECT r1={ix, iy, ix + iw, iy + ih};
    49.       int vis = RectVisible(hdc, &r1);
    50.       if (vis) drawed++; else ndrawed++;
    51.       if (vis)
    52.       {
    53.         fb->lock->Lock();
    54.         HDC memDC = MemoryDC;
    55.         HDC DC    = hdc;
    56.         if (scale) SetStretchBltMode(hdc, InperpolationMethood);
    57.         if (memDC)
    58.         { // fast
    59.           HBITMAP hOldBitmap = (HBITMAP)SelectObject(memDC, fb->CompatibleBitmap);
    60.           if (!scale)
    61.             BitBlt(DC, ix, iy, iw, ih, memDC, 0, 0, SRCCOPY);
    62.           else
    63.             StretchBlt(DC, ix, iy, iw, ih, memDC, 0, 0, fb->w, fb->h, SRCCOPY);
    64.           GdiFlush();
    65.           SelectObject(memDC, hOldBitmap);
    66.         } else
    67.         { // slow
    68.           DIBSECTION ds;
    69.           GetObject(fb->CompatibleBitmap, sizeof(DIBSECTION), &ds);
    70.           if (ds.dsBmih.biHeight > 0) ds.dsBmih.biHeight = -ds.dsBmih.biHeight;
    71.           if (!scale)
    72.             SetDIBitsToDevice(DC, ix, iy, iw, ih, 0, 0, 0, fb->h, ds.dsBm.bmBits,
    73.               (BITMAPINFO*)&ds.dsBmih, DIB_RGB_COLORS);
    74.           else
    75.             StretchDIBits(DC, ix, iy, iw, ih, 0, 0, fb->w, fb->h, ds.dsBm.bmBits,
    76.             (BITMAPINFO*)&ds.dsBmih, DIB_RGB_COLORS, SRCCOPY);
    77.         }
    78.         fb->lock->Unlock();
    79.       }
    80.       // draw background
    81.       ExcludeClipRect(hdc, r1.left, r1.top, r1.right, r1.bottom);
    82.       HBRUSH dark = CreateSolidBrush(RGB(64, 64, 64));
    83.       FillRect(hdc, &r, dark);
    84.       DeleteObject(dark);
    85.       ExcludeClipRect(hdc, r.left, r.top, r.right, r.bottom);
    86.     }
    87.     if (mat >= matspos) break;
    88.   }
    89.   // fill background
    90.   HBRUSH gray = CreateSolidBrush(RGB(128, 128, 128));
    91.   RECT ClientRect;
    92.   GetClientRect(hwnd, &ClientRect);
    93.   FillRect(hdc, &ClientRect, gray);
    94.   DeleteObject(gray);
    95.  
    96.   DeleteDC(MemoryDC);
    97.   return 1;
    98. }
    99.  
    100. // Билинейная интерполяция будет при InperpolationMethood == HALFTONE
    101.  
    102. void CPicViewer::SetQuality(int q)
    103. {
    104.   switch (q)
    105.   {
    106.     case 0: InperpolationMethood = COLORONCOLOR; InvalidateRect(hwnd,0,0); break;
    107.     case 1: InperpolationMethood = HALFTONE;     InvalidateRect(hwnd,0,0); break;
    108.     default: InperpolationMethood = COLORONCOLOR; InvalidateRect(hwnd,0,0); break;
    109.   }
    110. }
    111.  




    Еще обращаю внимание на MemoryDC - аппаратное ускорение по-моему работает только в этом случае. Насчет прозрачности - можно помутить с самими окнами. Еще можно юзать GDIPlus, но его в 2к по-моему нет по дефолту.
     
  4. SolidCode

    SolidCode New Member

    Публикаций:
    0
    Регистрация:
    2 дек 2002
    Сообщения:
    162
    Адрес:
    Kazakhstan
    Max

    Простите за глупый вопрос. А на х-на тебе такими большими битмапами ворочать?



    Документация по GDI гласит, что размеры битмап всегда не больше 65655.



    А DX-ными средствами не пробовал?
     
  5. Max

    Max Member

    Публикаций:
    0
    Регистрация:
    22 май 2003
    Сообщения:
    192
    semen

    сенкс, только я не понял, при чем тут InperpolationMethood? В CPicViewer::ShowPictures оно нигде не юзается...



    SolidCode

    А на х-на тебе такими большими битмапами ворочать?



    хех, это уже обрезанные битмапы.

    вообще они 6000x6000 :) - снимки со спутника, которые надо положить на подложку с масштабированием и прозрачностью.

    потом клацаешь мышкой и... пошла ракета... шутка :))



    Документация по GDI гласит, что размеры битмап всегда не больше 65655

    65655 чего?

    это размер в байтах, в пикселах или еще чего?
     
  6. SolidCode

    SolidCode New Member

    Публикаций:
    0
    Регистрация:
    2 дек 2002
    Сообщения:
    162
    Адрес:
    Kazakhstan


    Битмапы пикселами прежде всего меряются. Для них эти величины основные (с глубиной цвета и др.).
     
  7. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    Max

    Юзается :) - SetStretchBltMode(hdc, InperpolationMethood);

    Кстати, то что предложил SolidCode - юзать DX - тоже вариант - гибкости по выводу картинок на порядок выше...

    SolidCode

    Если всего больше 65536 пикселей - то очень даже могут :)

    Если w & h < 65536 - то этого в условиях max`а должно хватить. У меня например запросто отображалось 40000х40000 - больше не пробовал. И поподробнее, где ты это вычитал - беглый взгляд на последний MSDN не выявил таких ограничений, но тут явно ограничение по памяти - скока будет занимать картинка 65536x65536? - а вот 2х131072 - помойму запросто.
     
  8. SolidCode

    SolidCode New Member

    Публикаций:
    0
    Регистрация:
    2 дек 2002
    Сообщения:
    162
    Адрес:
    Kazakhstan
    Простите, я выразился неконкретно.

    65535 - предел размера по одной стороне. Т.е. максимальная картинка не должна превышать 65535 на 65535 пикселей. Да сами прочитайте в SDK. Это было в Win95 по любому.

    Хотя в графические функции идут 32-битные числа, внутри системы они будут обрезаны до установленного предела. Это они сами говорят.
     
  9. semen

    semen New Member

    Публикаций:
    0
    Регистрация:
    8 июн 2004
    Сообщения:
    334
    Адрес:
    Russia
    SolidCode

    Я попробовал - у мя 2х131072 отображается(2k3) :)

    А картинка 65536x65536 полюбе больше 4х гигов, если не чернобелая :))
     
  10. Max

    Max Member

    Публикаций:
    0
    Регистрация:
    22 май 2003
    Сообщения:
    192
    SolidCode

    Т.е. максимальная картинка не должна превышать 65535 на 65535 пикселей. Да сами прочитайте в SDK. Это было в Win95 по любому



    до вин98 включительно - графика 16-ти разрядная. То есть, во все gdi-ные процедуры координаты передаются 32 бит, но старшие 16 бит просто отрезаются.

    видимо поэтому в SDK и стоит цифра 65535.



    в NT и выше уже сделано по нормальному.

    я когда-то доолго бился с 98-й, пока понял в чем дело :)



    вообщем, проблему с выводом я поборол путем отсечения всего ненужного, и подсовывания винде относительно небольшой картинки для отрисовки. работает.



    но вот вопрос с алгоритмом масштабирования (собственным, а не апишным) остается открытым...
     
  11. Turkish

    Turkish New Member

    Публикаций:
    0
    Регистрация:
    25 окт 2004
    Сообщения:
    80
    Адрес:
    Russia
    65536x65536 = 4 ГБ, с такими объемами памяти винда (да и вообще комп) работать не могет
     
  12. murtix

    murtix New Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    110
    Адрес:
    Russia
    Если для делфи можно GraphicEx юзать или еще че-нить в этом роде.
     
  13. murtix

    murtix New Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    110
    Адрес:
    Russia
    Max

    Держи алгоритм,бикубической интерполяции изображения.

    Я с ним разобрался пока только в дельфи.

    только там про dx не так как надо написано.

    Пиши если что.

    [​IMG] _1603300408__Bicubic interpolation.rar