Гость
Map
Форумы / Java [игнор отключен] [закрыт для гостей] / Создание скриншота с глубиной цвета 8 bit / 7 сообщений из 7, страница 1 из 1
23.04.2020, 14:10
    #39950483
Mandarin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание скриншота с глубиной цвета 8 bit
Всем привет! Помогите пожалуйста разобраться как сделать восьми битный скриншот.
Я могу сделать 24 и 16 битный а вот 8 битный не получается, наверное не правильно битовую маску указываю. Вот пример кода.
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
package javaapplication28;

import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DirectColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

import com.sun.jna.Memory;
import com.sun.jna.platform.win32.GDI32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HBITMAP;
import com.sun.jna.platform.win32.WinDef.HDC;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinGDI;
import com.sun.jna.platform.win32.WinGDI.BITMAPINFO;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferUShort;

public class TestGDI {

    // 24bit
    public static final DirectColorModel SCREENSHOT_COLOR_MODEL_24 = new DirectColorModel(24, 0x00FF0000, 0xFF00, 0xFF);
    // 16bit
    public static final DirectColorModel SCREENSHOT_COLOR_MODEL_16 = new DirectColorModel(16, 0x7C00, 0x3E0, 0x1F);
    // 8bit
    public static final DirectColorModel SCREENSHOT_COLOR_MODEL_8 = new DirectColorModel(8, 3, 3, 2);

    public static final int[] SCREENSHOT_BAND_MASKS_24 = {
        SCREENSHOT_COLOR_MODEL_24.getRedMask(),
        SCREENSHOT_COLOR_MODEL_24.getGreenMask(),
        SCREENSHOT_COLOR_MODEL_24.getBlueMask()
    };
    public static final int[] SCREENSHOT_BAND_MASKS_16 = {
        SCREENSHOT_COLOR_MODEL_16.getRedMask(),
        SCREENSHOT_COLOR_MODEL_16.getGreenMask(),
        SCREENSHOT_COLOR_MODEL_16.getBlueMask()
    };
    public static final int[] SCREENSHOT_BAND_MASKS_8 = {
        SCREENSHOT_COLOR_MODEL_8.getRedMask(),
        SCREENSHOT_COLOR_MODEL_8.getGreenMask(),
        SCREENSHOT_COLOR_MODEL_8.getBlueMask()
    };

    public static BufferedImage getScreenshot(HWND target, int width, int height) throws Exception {
        int bit = 8;
        HDC hdcTarget = User32.INSTANCE.GetDC(target);
        HDC hdcTargetMem = GDI32.INSTANCE.CreateCompatibleDC(hdcTarget);
        HBITMAP hBitmap = GDI32.INSTANCE.CreateCompatibleBitmap(hdcTarget, width, height);
        GDI32.INSTANCE.SelectObject(hdcTargetMem, hBitmap);
        GDI32.INSTANCE.BitBlt(hdcTargetMem, 0, 0, width, height, hdcTarget, 0, 0, GDI32.SRCCOPY);
        //
        int bufferSize = width * height;
        int pixelByte;
        DirectColorModel colorModel;
        int[] bandMask;
        short bitCount;
        //
        switch (bit) {
            case 24:
                pixelByte = 4;
                colorModel = SCREENSHOT_COLOR_MODEL_24;
                bandMask = SCREENSHOT_BAND_MASKS_24;
                bitCount = 32;
                break;
            case 16:
                pixelByte = 2;
                colorModel = SCREENSHOT_COLOR_MODEL_16;
                bandMask = SCREENSHOT_BAND_MASKS_16;
                bitCount = 16;
                break;
            case 8:
                pixelByte = 1;
                colorModel = SCREENSHOT_COLOR_MODEL_8;
                bandMask = SCREENSHOT_BAND_MASKS_8;
                bitCount = 8;
                break;
            default:
                throw new Exception("unknown bit");
        }
        //
        BITMAPINFO bmi = new BITMAPINFO();
        bmi.bmiHeader.biWidth = width;
        bmi.bmiHeader.biHeight = -height;
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = bitCount;
        bmi.bmiHeader.biCompression = WinGDI.BI_RGB;
        //

        Memory buffer = new Memory(bufferSize * pixelByte);
        GDI32.INSTANCE.GetDIBits(hdcTarget, hBitmap, 0, height, buffer, bmi, WinGDI.DIB_RGB_COLORS);
        DataBuffer dataBuffer;
        switch (bit) {
            case 24:
                dataBuffer = new DataBufferInt(buffer.getIntArray(0, bufferSize), bufferSize);
                break;
            case 16:
                dataBuffer = new DataBufferUShort(buffer.getShortArray(0, bufferSize), bufferSize);
                break;
            case 8:
                dataBuffer = new DataBufferByte(buffer.getByteArray(0, bufferSize), bufferSize);
                break;
            default:
                throw new Exception("unknown bit");
        }

        WritableRaster raster = Raster.createPackedRaster(dataBuffer, width, height, width, bandMask, null);
        GDI32.INSTANCE.DeleteObject(hBitmap);
        GDI32.INSTANCE.DeleteDC(hdcTargetMem);
        User32.INSTANCE.ReleaseDC(target, hdcTarget);
        return new BufferedImage(colorModel, raster, false, null);
    }
}
...
Рейтинг: 0 / 0
23.04.2020, 14:49
    #39950513
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание скриншота с глубиной цвета 8 bit
Обычно RGB пространство цветов заканчивается на 16 битах.

Всё что ниже - индексный цвет. Тоесть цвет №1==красный .... цвет №256 == черный.
Цвета рандомные или по выбору пользователя.
И тут какоаз на сцене появляется выбор палитры. Начиная от стандартных
VGA-256 и заканивая адаптивными палитрами которые беруться из
центров кластеров исходного цветового пространства картики.
Можно также 8 бит представить как RGB=3:3:2 бита
но качество такой адаптации будет ужасным. Я сам пробовал.

Потом еще Microsoft различает 4-х битный цвет. И 1-битный для би-тональных картинок.
...
Рейтинг: 0 / 0
23.04.2020, 15:04
    #39950523
Mandarin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание скриншота с глубиной цвета 8 bit
mayton,

Вы все правильно и интересно говорите, как это превратить в рабочий код? :)
...
Рейтинг: 0 / 0
23.04.2020, 15:11
    #39950527
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание скриншота с глубиной цвета 8 bit
Я опираюсь на свои базовые знания Windows и графики. Но в Java
я никогда не использовал пакет com.sun.jna.platform.win32

Тоесть то что я написал - теория. И как правильно обращатся с этим пакетом хз.
...
Рейтинг: 0 / 0
23.04.2020, 15:42
    #39950550
Mandarin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание скриншота с глубиной цвета 8 bit
mayton,

Как превратить в знания в Java я знаю. Сможете подсказать на примере с++ например?
Я так понимаю что всё дело в правильно заполнении массива RGBQUAD?
...
Рейтинг: 0 / 0
23.04.2020, 16:01
    #39950570
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание скриншота с глубиной цвета 8 bit
Да.
1) Создаешь 256 штук RGBQUAD. (палитра)
2) Заполняешь их любыми цветами (но желательно брать самые популярные из изсходной картинки)
3) Генеришь destination и на каждый пиксел находишь из палитры самый близкий цвет
(по декартову расстоянию) или там есть более точная формула. Декартово расстояние
но перед каждым цветом есть весовой коэффициент. Для зеленого он самый большой.
...
Рейтинг: 0 / 0
24.04.2020, 14:12
    #39950999
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Создание скриншота с глубиной цвета 8 bit
А зачем такой странных хардкод?
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
    public static BufferedImage getScreenshot(HWND target, int width, int height) throws Exception {
        int bit = 8;
        HDC hdcTarget = User32.INSTANCE.GetDC(target);
        HDC hdcTargetMem = GDI32.INSTANCE.CreateCompatibleDC(hdcTarget);
        HBITMAP hBitmap = GDI32.INSTANCE.CreateCompatibleBitmap(hdcTarget, width, height);
        GDI32.INSTANCE.SelectObject(hdcTargetMem, hBitmap);
        GDI32.INSTANCE.BitBlt(hdcTargetMem, 0, 0, width, height, hdcTarget, 0, 0, GDI32.SRCCOPY);
        //
        int bufferSize = width * height;
        int pixelByte;
        DirectColorModel colorModel;
        int[] bandMask;
        short bitCount;
        //
        switch (bit) {
            case 24:
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Создание скриншота с глубиной цвета 8 bit / 7 сообщений из 7, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]