вообщем есть два битмапа - 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к. кто мне скажет, в системе есть какое-то ограничение на размер битмапа? ...и как посоветуете с этим бороться?
я так понял, никто не знает... придется писАть самому тогда такой вопрос на тему графики - как смасштабировать картинку собственными средствами? допустим есть битмап высотой 1000 пикселов, масштабируем его до высоты 100 пикселов. в простейшем случае получается, что мы должны взять каждую 10-ю строчку. но тогда теряется информация о строчках 1..9, 11..19 etc. кто видел описание более навороченых алгоритмов типа bilinear, bicubic etc? поделитесь плиз, а то заказ горит уже
Max Возможно косяк 2к - в нем их монго - попробуй 2к3. Приведу свой грязный но рабочий код: Код (Text): int CPicViewer::ShowPictures(HWND hwnd, HDC hdc, RECT *r, int nc) { MyLock l(&lock); HDC MemoryDC = CreateCompatibleDC(hdc); SelectClipRgn(MemoryDC, 0); int maty = (mats + matinrow - 1)/matinrow; int mat = 0; int drawed=0,ndrawed = 0; for(int mat_ypos = 0; mat_ypos < maty; mat_ypos++) { int py = yofs + (sh + ytile)*mat_ypos + ytile/2; for(int j = 0; j < matinrow; j++, mat++) { if (mat>=matspos) break; FileBitmap *fb = cached_bitmaps[(mat + matsofs) % mats]; if (!fb) continue; DIBSECTION ds; GetObject(fb->CompatibleBitmap, sizeof(DIBSECTION), &ds); //Bitmap *mb = fb->thumbnail; int px = xofs + (sw + xtile)*j + xtile/2; int x = px, y = py, w = sw, h = sh; RECT r = {x, y, x + w, y + h}; // draw picture with aspect ration int iw = fb->w; int ih = fb->h; int ix = x, iy = y; int scale; if (ScaleMode == SCALE_MODE_NORMAL) scale = (iw > w) || (ih > h); else scale = (iw != w) || (ih != h); if (scale) { double fw = ((double)iw)/w; double fh = ((double)ih)/h; if (fw > fh) { iw = w; ih = (int)floor(ih/fw + 0.5); } else { iw = (int)floor(iw/fh + 0.5); ih = h; } } ix = x + (w - iw)/2; iy = y + (h - ih)/2; RECT r1={ix, iy, ix + iw, iy + ih}; int vis = RectVisible(hdc, &r1); if (vis) drawed++; else ndrawed++; if (vis) { fb->lock->Lock(); HDC memDC = MemoryDC; HDC DC = hdc; if (scale) SetStretchBltMode(hdc, InperpolationMethood); if (memDC) { // fast HBITMAP hOldBitmap = (HBITMAP)SelectObject(memDC, fb->CompatibleBitmap); if (!scale) BitBlt(DC, ix, iy, iw, ih, memDC, 0, 0, SRCCOPY); else StretchBlt(DC, ix, iy, iw, ih, memDC, 0, 0, fb->w, fb->h, SRCCOPY); GdiFlush(); SelectObject(memDC, hOldBitmap); } else { // slow DIBSECTION ds; GetObject(fb->CompatibleBitmap, sizeof(DIBSECTION), &ds); if (ds.dsBmih.biHeight > 0) ds.dsBmih.biHeight = -ds.dsBmih.biHeight; if (!scale) SetDIBitsToDevice(DC, ix, iy, iw, ih, 0, 0, 0, fb->h, ds.dsBm.bmBits, (BITMAPINFO*)&ds.dsBmih, DIB_RGB_COLORS); else StretchDIBits(DC, ix, iy, iw, ih, 0, 0, fb->w, fb->h, ds.dsBm.bmBits, (BITMAPINFO*)&ds.dsBmih, DIB_RGB_COLORS, SRCCOPY); } fb->lock->Unlock(); } // draw background ExcludeClipRect(hdc, r1.left, r1.top, r1.right, r1.bottom); HBRUSH dark = CreateSolidBrush(RGB(64, 64, 64)); FillRect(hdc, &r, dark); DeleteObject(dark); ExcludeClipRect(hdc, r.left, r.top, r.right, r.bottom); } if (mat >= matspos) break; } // fill background HBRUSH gray = CreateSolidBrush(RGB(128, 128, 128)); RECT ClientRect; GetClientRect(hwnd, &ClientRect); FillRect(hdc, &ClientRect, gray); DeleteObject(gray); DeleteDC(MemoryDC); return 1; } // Билинейная интерполяция будет при InperpolationMethood == HALFTONE void CPicViewer::SetQuality(int q) { switch (q) { case 0: InperpolationMethood = COLORONCOLOR; InvalidateRect(hwnd,0,0); break; case 1: InperpolationMethood = HALFTONE; InvalidateRect(hwnd,0,0); break; default: InperpolationMethood = COLORONCOLOR; InvalidateRect(hwnd,0,0); break; } } Еще обращаю внимание на MemoryDC - аппаратное ускорение по-моему работает только в этом случае. Насчет прозрачности - можно помутить с самими окнами. Еще можно юзать GDIPlus, но его в 2к по-моему нет по дефолту.
Max Простите за глупый вопрос. А на х-на тебе такими большими битмапами ворочать? Документация по GDI гласит, что размеры битмап всегда не больше 65655. А DX-ными средствами не пробовал?
semen сенкс, только я не понял, при чем тут InperpolationMethood? В CPicViewer::ShowPictures оно нигде не юзается... SolidCode А на х-на тебе такими большими битмапами ворочать? хех, это уже обрезанные битмапы. вообще они 6000x6000 - снимки со спутника, которые надо положить на подложку с масштабированием и прозрачностью. потом клацаешь мышкой и... пошла ракета... шутка ) Документация по GDI гласит, что размеры битмап всегда не больше 65655 65655 чего? это размер в байтах, в пикселах или еще чего?
Max Юзается - SetStretchBltMode(hdc, InperpolationMethood); Кстати, то что предложил SolidCode - юзать DX - тоже вариант - гибкости по выводу картинок на порядок выше... SolidCode Если всего больше 65536 пикселей - то очень даже могут Если w & h < 65536 - то этого в условиях max`а должно хватить. У меня например запросто отображалось 40000х40000 - больше не пробовал. И поподробнее, где ты это вычитал - беглый взгляд на последний MSDN не выявил таких ограничений, но тут явно ограничение по памяти - скока будет занимать картинка 65536x65536? - а вот 2х131072 - помойму запросто.
Простите, я выразился неконкретно. 65535 - предел размера по одной стороне. Т.е. максимальная картинка не должна превышать 65535 на 65535 пикселей. Да сами прочитайте в SDK. Это было в Win95 по любому. Хотя в графические функции идут 32-битные числа, внутри системы они будут обрезаны до установленного предела. Это они сами говорят.
SolidCode Я попробовал - у мя 2х131072 отображается(2k3) А картинка 65536x65536 полюбе больше 4х гигов, если не чернобелая )
SolidCode Т.е. максимальная картинка не должна превышать 65535 на 65535 пикселей. Да сами прочитайте в SDK. Это было в Win95 по любому до вин98 включительно - графика 16-ти разрядная. То есть, во все gdi-ные процедуры координаты передаются 32 бит, но старшие 16 бит просто отрезаются. видимо поэтому в SDK и стоит цифра 65535. в NT и выше уже сделано по нормальному. я когда-то доолго бился с 98-й, пока понял в чем дело вообщем, проблему с выводом я поборол путем отсечения всего ненужного, и подсовывания винде относительно небольшой картинки для отрисовки. работает. но вот вопрос с алгоритмом масштабирования (собственным, а не апишным) остается открытым...
Max Держи алгоритм,бикубической интерполяции изображения. Я с ним разобрался пока только в дельфи. только там про dx не так как надо написано. Пиши если что. _1603300408__Bicubic interpolation.rar