GDI+ Загрузить jpg и сохранить как 24-битную проблему png

Проблема

Привет всем!

У меня есть этот код, который выполняет циклы моего jpg-изображения, изменяя пиксели и, наконец, сохраняя его как тип png. Проблема в том, что результирующее изображение имеет разрядность 32 бита. Мне нужно, чтобы он был 24-битным, может ли кто-нибудь пролить свет на правильный метод его настройки? Правильно ли я смотрю на настройку формата пикселей PixelFormat24bppRGB?

Код

static inline void Brighten(Gdiplus::Bitmap* img)
{
    int width = img->GetWidth()/8,height = img->GetHeight(), max = (width*height),r,g,b;
    Gdiplus::Color pixel;   
    for(int a = 0,x = 0, y = -1; a < max; ++a)
    {
        x = a%width;    
        if(x == 0)
            ++y;
        img->GetPixel(x,y,&pixel);
        r = pixel.GetR();
        g = pixel.GetG();
        b = pixel.GetB();
        if (r > 245) r = 245; 
        if (g > 245) g = 245;  
        if (b > 245) b = 245; 
        r += 10;
        g += 10;
        b += 10;
        pixel = Gdiplus::Color(r,g,b);
        img->SetPixel(x,y,pixel);;
    }
}

ULONG_PTR m_dwToken = 0;
Gdiplus::GdiplusStartupInput input;
Gdiplus::GdiplusStartupOutput output;
Gdiplus::GdiplusStartup( &m_dwToken, &input, &output );
USES_CONVERSION_EX;
Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(1040, _ATL_SAFE_ALLOCA_DEF_THRESHOLD));
Gdiplus::DllExports::GdipGetImageEncoders(5, 1040, pEncoders );
CLSID clsidEncoder = pEncoders[4].Clsid;

Gdiplus::Bitmap img1((CT2W)L"IMG_1.JPG");
Brighten(&img1);
img1.Save((CT2W)L"IMG_1_R3.PNG",&clsidEncoder,NULL);

Заранее спасибо!


person wookey    schedule 14.03.2010    source источник
comment
Убедитесь, что дополнительные 8 бит не являются частью альфа-канала. Если да, то все в порядке, просто игнорируйте лишние биты. Попробуйте установить для дополнительных 8 бит какое-нибудь значение, например 0x88, и посмотрите, станет ли ваше изображение полупрозрачным или нет.   -  person dirkgently    schedule 15.03.2010
comment
Спасибо за быстрый ответ, да, мое изображение становится прозрачным. Казалось бы, пиксель использует лишние биты. Любые идеи о том, как это остановить?   -  person wookey    schedule 15.03.2010
comment
Затем оставьте значение 0. Теперь у вас есть 8-битное изображение в кодировке ARGB/RGBA на канал.   -  person dirkgently    schedule 15.03.2010
comment
Вы можете дополнительно установить PixelFormat в качестве третьего параметра конструктора GdiPlus::Bitmap в PixelFormat24bppRGB. См.: msdn.microsoft.com/en-us/ библиотека/ms536313%28VS.85%29.aspx   -  person dirkgently    schedule 15.03.2010
comment
Вы имели в виду установку альфа-компонента цвета на 0? Потому что это делает изображение полностью прозрачным, а не отбрасывает его. Я также изучал использование конструктора растровых изображений и настройку формата пикселей, но мне было непонятно, как загрузить изображение обратно. (Также заметил небольшую ошибку в моем опубликованном коде, где r, g, b должны быть установлены на += 10, я изменил его, когда проверял, будет ли изменено все изображение. (не повлияло на мои результаты)) Я также проверено, и изменение значений rgb приводит к изменению его на 32-битное, потому что цвета gdi + являются argb.   -  person wookey    schedule 15.03.2010
comment
Ах, тогда установите его на 0xff. Думаю, тебе пора идти.   -  person dirkgently    schedule 15.03.2010
comment
Установка его на 0xff — это то, что argb делает по умолчанию, если вы указываете цвет только с rgb, что означает, что альфа-информация все еще включена и создает 32-битный png.   -  person wookey    schedule 15.03.2010


Ответы (1)


Хорошо, я на самом деле исправил это, я использовал LockBits() для прямого доступа к битам и их изменения, это дает мне столь необходимый прирост производительности и сохраняет его как 24-битное изображение.

static inline void Brighten(Gdiplus::Bitmap* img)
{
    int width = img->GetWidth(),height = img->GetHeight(),r,g,b;
    Gdiplus::Rect rect(0,0,width,height);
    Gdiplus::BitmapData data;
    img->LockBits(&rect,Gdiplus::ImageLockModeWrite,PixelFormat24bppRGB,&data);
    int stride = data.Stride,offset = stride - width*3;
    byte * p1 = (byte *)(void *)data.Scan0;
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            r = p1[0];
            g = p1[1];
            b = p1[2];
            if (r > 245) r = 245; 
            if (g > 245) g = 245;  
            if (b > 245) b = 245; 
            r += 10;
            g += 10;
            b += 10;    
            p1[0] = r;
            p1[1] = g;
            p1[2] = b;
            p1 += 3;
        }
        p1 += offset;
    }
    img->UnlockBits(&data);     
}

Спасибо за всю твою помощь!

person wookey    schedule 15.03.2010