Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,457 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/config-manager.h"
#include "common/savefile.h"
#include "common/system.h"
#include "ags/lib/aastr-0.1.1/aastr.h"
#include "ags/shared/gfx/allegro_bitmap.h"
#include "ags/shared/gfx/image.h"
namespace AGS3 {
extern void __my_setcolor(int *ctset, int newcol, int wantColDep);
namespace AGS {
namespace Shared {
Bitmap::Bitmap()
: _alBitmap(nullptr)
, _isDataOwner(false) {
}
Bitmap::Bitmap(int width, int height, int color_depth)
: _alBitmap(nullptr)
, _isDataOwner(false) {
Create(width, height, color_depth);
}
Bitmap::Bitmap(Bitmap *src, const Rect &rc)
: _alBitmap(nullptr)
, _isDataOwner(false) {
CreateSubBitmap(src, rc);
}
Bitmap::Bitmap(BITMAP *al_bmp, bool shared_data)
: _alBitmap(nullptr)
, _isDataOwner(false) {
WrapAllegroBitmap(al_bmp, shared_data);
}
Bitmap::~Bitmap() {
Destroy();
}
//=============================================================================
// Creation and destruction
//=============================================================================
bool Bitmap::Create(int width, int height, int color_depth) {
Destroy();
if (color_depth) {
_alBitmap = create_bitmap_ex(color_depth, width, height);
} else {
_alBitmap = create_bitmap(width, height);
}
_isDataOwner = true;
return _alBitmap != nullptr;
}
bool Bitmap::CreateTransparent(int width, int height, int color_depth) {
if (Create(width, height, color_depth)) {
clear_to_color(_alBitmap, bitmap_mask_color(_alBitmap));
return true;
}
return false;
}
bool Bitmap::CreateSubBitmap(Bitmap *src, const Rect &rc) {
Destroy();
_alBitmap = create_sub_bitmap(src->_alBitmap, rc.Left, rc.Top, rc.GetWidth(), rc.GetHeight());
_isDataOwner = true;
return _alBitmap != nullptr;
}
bool Bitmap::ResizeSubBitmap(int width, int height) {
if (!isSubBitmap())
return false;
// TODO: can't clamp to parent size, because subs do not keep parent ref;
// might require amending allegro bitmap struct
_alBitmap->w = _alBitmap->cr = width;
_alBitmap->h = _alBitmap->cb = height;
return true;
}
bool Bitmap::CreateCopy(Bitmap *src, int color_depth) {
if (Create(src->_alBitmap->w, src->_alBitmap->h, color_depth ? color_depth : bitmap_color_depth(src->_alBitmap))) {
blit(src->_alBitmap, _alBitmap, 0, 0, 0, 0, _alBitmap->w, _alBitmap->h);
return true;
}
return false;
}
bool Bitmap::WrapAllegroBitmap(BITMAP *al_bmp, bool shared_data) {
Destroy();
_alBitmap = al_bmp;
_isDataOwner = !shared_data;
return _alBitmap != nullptr;
}
void Bitmap::Destroy() {
if (_isDataOwner && _alBitmap) {
destroy_bitmap(_alBitmap);
}
_alBitmap = nullptr;
_isDataOwner = false;
}
bool Bitmap::LoadFromFile(const char *filename) {
Destroy();
BITMAP *al_bmp = load_bitmap(filename, nullptr);
if (al_bmp) {
_alBitmap = al_bmp;
_isDataOwner = true;
}
return _alBitmap != nullptr;
}
bool Bitmap::LoadFromFile(PACKFILE *pf) {
Destroy();
BITMAP *al_bmp = load_bitmap(pf, nullptr);
if (al_bmp) {
_alBitmap = al_bmp;
_isDataOwner = true;
}
return _alBitmap != nullptr;
}
bool Bitmap::SaveToFile(Common::WriteStream &out, const void *palette) {
return save_bitmap(out, _alBitmap, (const RGB *)palette);
}
bool Bitmap::SaveToFile(const char *filename, const void *palette) {
// Only keeps the file name and add the game target as prefix.
Common::String name = filename;
size_t lastSlash = name.findLastOf('/');
if (lastSlash != Common::String::npos)
name = name.substr(lastSlash + 1);
Common::String gameTarget = ConfMan.getActiveDomainName();
if (!name.hasPrefixIgnoreCase(gameTarget))
name = gameTarget + "-" + name;
Common::OutSaveFile *out = g_system->getSavefileManager()->openForSaving(name, false);
assert(out);
bool result = SaveToFile(*out, palette);
out->finalize();
delete out;
return result;
}
color_t Bitmap::GetCompatibleColor(color_t color) {
color_t compat_color = 0;
__my_setcolor(&compat_color, color, bitmap_color_depth(_alBitmap));
return compat_color;
}
//=============================================================================
// Clipping
//=============================================================================
void Bitmap::SetClip(const Rect &rc) {
set_clip_rect(_alBitmap, rc.Left, rc.Top, rc.Right, rc.Bottom);
}
void Bitmap::ResetClip() {
set_clip_rect(_alBitmap, 0, 0, _alBitmap->w - 1, _alBitmap->h - 1);
}
Rect Bitmap::GetClip() const {
Rect temp;
get_clip_rect(_alBitmap, &temp.Left, &temp.Top, &temp.Right, &temp.Bottom);
return temp;
}
//=============================================================================
// Blitting operations (drawing one bitmap over another)
//=============================================================================
void Bitmap::Blit(Bitmap *src, int dst_x, int dst_y, BitmapMaskOption mask) {
BITMAP *al_src_bmp = src->_alBitmap;
// WARNING: For some evil reason Allegro expects dest and src bitmaps in different order for blit and draw_sprite
if (mask == kBitmap_Transparency) {
draw_sprite(_alBitmap, al_src_bmp, dst_x, dst_y);
} else {
blit(al_src_bmp, _alBitmap, 0, 0, dst_x, dst_y, al_src_bmp->w, al_src_bmp->h);
}
}
void Bitmap::Blit(Bitmap *src, int src_x, int src_y, int dst_x, int dst_y, int width, int height, BitmapMaskOption mask) {
BITMAP *al_src_bmp = src->_alBitmap;
if (mask == kBitmap_Transparency) {
masked_blit(al_src_bmp, _alBitmap, src_x, src_y, dst_x, dst_y, width, height);
} else {
blit(al_src_bmp, _alBitmap, src_x, src_y, dst_x, dst_y, width, height);
}
}
void Bitmap::MaskedBlit(Bitmap *src, int dst_x, int dst_y) {
draw_sprite(_alBitmap, src->_alBitmap, dst_x, dst_y);
}
void Bitmap::StretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask) {
BITMAP *al_src_bmp = src->_alBitmap;
// WARNING: For some evil reason Allegro expects dest and src bitmaps in different order for blit and draw_sprite
if (mask == kBitmap_Transparency) {
stretch_sprite(_alBitmap, al_src_bmp,
dst_rc.Left, dst_rc.Top, dst_rc.GetWidth(), dst_rc.GetHeight());
} else {
stretch_blit(al_src_bmp, _alBitmap,
0, 0, al_src_bmp->w, al_src_bmp->h,
dst_rc.Left, dst_rc.Top, dst_rc.GetWidth(), dst_rc.GetHeight());
}
}
void Bitmap::StretchBlt(Bitmap *src, const Rect &src_rc, const Rect &dst_rc, BitmapMaskOption mask) {
BITMAP *al_src_bmp = src->_alBitmap;
if (mask == kBitmap_Transparency) {
masked_stretch_blit(al_src_bmp, _alBitmap,
src_rc.Left, src_rc.Top, src_rc.GetWidth(), src_rc.GetHeight(),
dst_rc.Left, dst_rc.Top, dst_rc.GetWidth(), dst_rc.GetHeight());
} else {
stretch_blit(al_src_bmp, _alBitmap,
src_rc.Left, src_rc.Top, src_rc.GetWidth(), src_rc.GetHeight(),
dst_rc.Left, dst_rc.Top, dst_rc.GetWidth(), dst_rc.GetHeight());
}
}
void Bitmap::AAStretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask) {
BITMAP *al_src_bmp = src->_alBitmap;
// WARNING: For some evil reason Allegro expects dest and src bitmaps in different order for blit and draw_sprite
if (mask == kBitmap_Transparency) {
aa_stretch_sprite(_alBitmap, al_src_bmp,
dst_rc.Left, dst_rc.Top, dst_rc.GetWidth(), dst_rc.GetHeight());
} else {
aa_stretch_blit(al_src_bmp, _alBitmap,
0, 0, al_src_bmp->w, al_src_bmp->h,
dst_rc.Left, dst_rc.Top, dst_rc.GetWidth(), dst_rc.GetHeight());
}
}
void Bitmap::AAStretchBlt(Bitmap *src, const Rect &src_rc, const Rect &dst_rc, BitmapMaskOption mask) {
BITMAP *al_src_bmp = src->_alBitmap;
if (mask == kBitmap_Transparency) {
// TODO: aastr lib does not expose method for masked stretch blit; should do that at some point since
// the source code is a gift-ware anyway
// aa_masked_blit(_alBitmap, al_src_bmp, src_rc.Left, src_rc.Top, src_rc.GetWidth(), src_rc.GetHeight(), dst_rc.Left, dst_rc.Top, dst_rc.GetWidth(), dst_rc.GetHeight());
error("aa_masked_blit is not yet supported!");
} else {
aa_stretch_blit(al_src_bmp, _alBitmap,
src_rc.Left, src_rc.Top, src_rc.GetWidth(), src_rc.GetHeight(),
dst_rc.Left, dst_rc.Top, dst_rc.GetWidth(), dst_rc.GetHeight());
}
}
void Bitmap::TransBlendBlt(Bitmap *src, int dst_x, int dst_y) {
BITMAP *al_src_bmp = src->_alBitmap;
draw_trans_sprite(_alBitmap, al_src_bmp, dst_x, dst_y);
}
void Bitmap::LitBlendBlt(Bitmap *src, int dst_x, int dst_y, int light_amount) {
BITMAP *al_src_bmp = src->_alBitmap;
draw_lit_sprite(_alBitmap, al_src_bmp, dst_x, dst_y, light_amount);
}
void Bitmap::FlipBlt(Bitmap *src, int dst_x, int dst_y, GraphicFlip flip) {
BITMAP *al_src_bmp = src->_alBitmap;
switch (flip) {
case kFlip_Horizontal:
draw_sprite_h_flip(_alBitmap, al_src_bmp, dst_x, dst_y);
break;
case kFlip_Vertical:
draw_sprite_v_flip(_alBitmap, al_src_bmp, dst_x, dst_y);
break;
case kFlip_Both:
draw_sprite_vh_flip(_alBitmap, al_src_bmp, dst_x, dst_y);
break;
default: // blit with no transform
Blit(src, dst_x, dst_y);
break;
}
}
void Bitmap::RotateBlt(Bitmap *src, int dst_x, int dst_y, fixed_t angle) {
BITMAP *al_src_bmp = src->_alBitmap;
rotate_sprite(_alBitmap, al_src_bmp, dst_x, dst_y, angle);
}
void Bitmap::RotateBlt(Bitmap *src, int dst_x, int dst_y, int pivot_x, int pivot_y, fixed_t angle) {
BITMAP *al_src_bmp = src->_alBitmap;
pivot_sprite(_alBitmap, al_src_bmp, dst_x, dst_y, pivot_x, pivot_y, angle);
}
//=============================================================================
// Pixel operations
//=============================================================================
void Bitmap::Clear(color_t color) {
if (color) {
clear_to_color(_alBitmap, color);
} else {
clear_bitmap(_alBitmap);
}
}
void Bitmap::ClearTransparent() {
clear_to_color(_alBitmap, bitmap_mask_color(_alBitmap));
}
void Bitmap::PutPixel(int x, int y, color_t color) {
if (x < 0 || x >= _alBitmap->w || y < 0 || y >= _alBitmap->h) {
return;
}
switch (bitmap_color_depth(_alBitmap)) {
case 8:
return _putpixel(_alBitmap, x, y, color);
case 15:
return _putpixel15(_alBitmap, x, y, color);
case 16:
return _putpixel16(_alBitmap, x, y, color);
case 24:
return _putpixel24(_alBitmap, x, y, color);
case 32:
return _putpixel32(_alBitmap, x, y, color);
}
assert(0); // this should not normally happen
return putpixel(_alBitmap, x, y, color);
}
int Bitmap::GetPixel(int x, int y) const {
if (x < 0 || x >= _alBitmap->w || y < 0 || y >= _alBitmap->h) {
return -1; // Allegros getpixel() implementation returns -1 in this case
}
switch (bitmap_color_depth(_alBitmap)) {
case 8:
return _getpixel(_alBitmap, x, y);
case 15:
return _getpixel15(_alBitmap, x, y);
case 16:
return _getpixel16(_alBitmap, x, y);
case 24:
return _getpixel24(_alBitmap, x, y);
case 32:
return _getpixel32(_alBitmap, x, y);
}
assert(0); // this should not normally happen
return getpixel(_alBitmap, x, y);
}
//=============================================================================
// Vector drawing operations
//=============================================================================
void Bitmap::DrawLine(const Line &ln, color_t color) {
line(_alBitmap, ln.X1, ln.Y1, ln.X2, ln.Y2, color);
}
void Bitmap::DrawTriangle(const Triangle &tr, color_t color) {
triangle(_alBitmap,
tr.X1, tr.Y1, tr.X2, tr.Y2, tr.X3, tr.Y3, color);
}
void Bitmap::DrawRect(const Rect &rc, color_t color) {
rect(_alBitmap, rc.Left, rc.Top, rc.Right, rc.Bottom, color);
}
void Bitmap::FillRect(const Rect &rc, color_t color) {
rectfill(_alBitmap, rc.Left, rc.Top, rc.Right, rc.Bottom, color);
}
void Bitmap::FillCircle(const Circle &circle, color_t color) {
circlefill(_alBitmap, circle.X, circle.Y, circle.Radius, color);
}
void Bitmap::Fill(color_t color) {
if (color) {
clear_to_color(_alBitmap, color);
} else {
clear_bitmap(_alBitmap);
}
}
void Bitmap::FillTransparent() {
clear_to_color(_alBitmap, bitmap_mask_color(_alBitmap));
}
void Bitmap::FloodFill(int x, int y, color_t color) {
_alBitmap->floodfill(x, y, color);
}
//=============================================================================
// Direct access operations
//=============================================================================
void Bitmap::SetScanLine(int index, unsigned char *data, int data_size) {
if (index < 0 || index >= GetHeight()) {
return;
}
int copy_length = data_size;
if (copy_length < 0) {
copy_length = GetLineLength();
} else // TODO: use Math namespace here
if (copy_length > GetLineLength()) {
copy_length = GetLineLength();
}
memcpy(_alBitmap->line[index], data, copy_length);
}
namespace BitmapHelper {
Bitmap *CreateRawBitmapOwner(BITMAP *al_bmp) {
Bitmap *bitmap = new Bitmap();
if (!bitmap->WrapAllegroBitmap(al_bmp, false)) {
delete bitmap;
bitmap = nullptr;
}
return bitmap;
}
Bitmap *CreateRawBitmapWrapper(BITMAP *al_bmp) {
Bitmap *bitmap = new Bitmap();
if (!bitmap->WrapAllegroBitmap(al_bmp, true)) {
delete bitmap;
bitmap = nullptr;
}
return bitmap;
}
} // namespace BitmapHelper
} // namespace Shared
} // namespace AGS
} // namespace AGS3

View File

@@ -0,0 +1,277 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Allegro lib based bitmap
//
// TODO: probably should be moved to the Engine; check again when (if) it is
// clear that AGS.Native does not need allegro for drawing.
//
//=============================================================================
#ifndef AGS_SHARED_GFX_ALLEGRO_BITMAP_H
#define AGS_SHARED_GFX_ALLEGRO_BITMAP_H
#include "graphics/screen.h"
#include "ags/lib/allegro.h" // BITMAP
#include "ags/shared/core/types.h"
#include "ags/shared/gfx/bitmap.h"
#include "ags/shared/util/string.h"
namespace AGS3 {
namespace AGS {
namespace Shared {
class Bitmap {
public:
Bitmap();
Bitmap(int width, int height, int color_depth = 0);
Bitmap(Bitmap *src, const Rect &rc);
Bitmap(BITMAP *al_bmp, bool shared_data);
~Bitmap();
// Allocate new bitmap.
// NOTE: color_depth is in BITS per pixel (i.e. 8, 16, 24, 32...).
// NOTE: in all of these color_depth may be passed as 0 in which case a default
// color depth will be used (as previously set for the system).
// TODO: color_depth = 0 is used to call Allegro's create_bitmap, which uses
// some global color depth setting; not sure if this is OK to use for generic class,
// revise this in future
bool Create(int width, int height, int color_depth = 0);
// Create Bitmap and clear to transparent color
bool CreateTransparent(int width, int height, int color_depth = 0);
// Creates a sub-bitmap of the given bitmap; the sub-bitmap is a reference to
// particular region inside a parent.
// WARNING: the parent bitmap MUST be kept in memory for as long as sub-bitmap exists!
bool CreateSubBitmap(Bitmap *src, const Rect &rc);
// Resizes existing sub-bitmap within the borders of its parent
bool ResizeSubBitmap(int width, int height);
// Creates a plain copy of the given bitmap, optionally converting to a different color depth;
// pass color depth 0 to keep the original one.
bool CreateCopy(Bitmap *src, int color_depth = 0);
// TODO: this is a temporary solution for plugin support
// Wraps a raw allegro BITMAP object, optionally owns it (will delete on disposal)
bool WrapAllegroBitmap(BITMAP *al_bmp, bool shared_data);
// Deallocate bitmap
void Destroy();
bool LoadFromFile(const String &filename) {
return LoadFromFile(filename.GetCStr());
}
bool LoadFromFile(const char *filename);
bool LoadFromFile(PACKFILE *pf);
bool SaveToFile(const String &filename, const void *palette) {
return SaveToFile(filename.GetCStr(), palette);
}
bool SaveToFile(Common::WriteStream &out, const void *palette);
bool SaveToFile(const char *filename, const void *palette);
// TODO: This is temporary solution for cases when we cannot replace
// use of raw BITMAP struct with Bitmap
inline BITMAP *GetAllegroBitmap() {
return _alBitmap;
}
// Is this a "normal" bitmap created by application which data can be directly accessed for reading and writing
inline bool IsMemoryBitmap() const {
return true;
}
// Is this a video bitmap
inline bool IsVideoBitmap() const {
return dynamic_cast<Graphics::Screen *>(_alBitmap) != nullptr;
}
// Is this a linear bitmap, the one that can be accessed linearly within each scanline
inline bool IsLinearBitmap() const {
return true;
}
// Is this a subbitmap, referencing a part of another, bigger one?
inline bool isSubBitmap() const {
return _alBitmap->isSubBitmap();
}
// Do both bitmaps share same data (usually: subbitmaps, or parent/subbitmap)
inline bool IsSameBitmap(Bitmap *other) const {
return is_same_bitmap(_alBitmap, other->_alBitmap) != 0;
}
// Checks if bitmap cannot be used
inline bool IsNull() const {
return !_alBitmap;
}
// Checks if bitmap has zero size: either width or height (or both) is zero
inline bool IsEmpty() const {
return GetWidth() == 0 || GetHeight() == 0;
}
inline int GetWidth() const {
return _alBitmap->w;
}
inline int GetHeight() const {
return _alBitmap->h;
}
inline Size GetSize() const {
return Size(_alBitmap->w, _alBitmap->h);
}
// Get sub-bitmap's offset position within its parent
inline Point GetSubOffset() const {
Common::Point pt = _alBitmap->getOffsetFromOwner();
return Point(pt.x, pt.y);
}
inline int GetColorDepth() const {
return bitmap_color_depth(_alBitmap);
}
// BPP: bytes per pixel
inline int GetBPP() const {
return (GetColorDepth() + 7) / 8;
}
// CHECKME: probably should not be exposed, see comment to GetData()
inline int GetDataSize() const {
return GetWidth() * GetHeight() * GetBPP();
}
// Gets scanline length in bytes (is the same for any scanline)
inline int GetLineLength() const {
return GetWidth() * GetBPP();
}
// TODO: replace with byte *
// Gets a pointer to underlying graphic data
// FIXME: actually not a very good idea, since there's no 100% guarantee the scanline positions in memory are sequential
inline const unsigned char *GetData() const {
return _alBitmap->getPixels();
}
// Get scanline for direct reading
inline const unsigned char *GetScanLine(int index) const {
assert(index >= 0 && index < GetHeight());
return _alBitmap->getBasePtr(0, index);
}
inline unsigned char *GetScanLine(int index) {
assert(index >= 0 && index < GetHeight());
return (unsigned char *)_alBitmap->getBasePtr(0, index);
}
// Get bitmap's mask color (transparent color)
inline color_t GetMaskColor() const {
return bitmap_mask_color(_alBitmap);
}
// Converts AGS color-index into RGB color according to the bitmap format.
// TODO: this method was added to the Bitmap class during large refactoring,
// but that's a mistake, because in retrospect is has nothing to do with
// bitmap itself and should rather be a part of the game data logic.
color_t GetCompatibleColor(color_t color);
//=========================================================================
// Clipping
// TODO: consider implementing push-pop clipping stack logic.
//=========================================================================
void SetClip(const Rect &rc);
void ResetClip();
Rect GetClip() const;
//=========================================================================
// Blitting operations (drawing one bitmap over another)
//=========================================================================
// Draw other bitmap over current one
void Blit(Bitmap *src, int dst_x = 0, int dst_y = 0, BitmapMaskOption mask = kBitmap_Copy);
void Blit(Bitmap *src, int src_x, int src_y, int dst_x, int dst_y, int width, int height, BitmapMaskOption mask = kBitmap_Copy);
// Draw other bitmap in a masked mode (kBitmap_Transparency)
void MaskedBlit(Bitmap *src, int dst_x, int dst_y);
// Draw other bitmap, stretching or shrinking its size to given values
void StretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
void StretchBlt(Bitmap *src, const Rect &src_rc, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
// Antia-aliased stretch-blit
void AAStretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
void AAStretchBlt(Bitmap *src, const Rect &src_rc, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
// TODO: find more general way to call these operations, probably require pointer to Blending data struct?
// Draw bitmap using translucency preset
void TransBlendBlt(Bitmap *src, int dst_x, int dst_y);
// Draw bitmap using lighting preset
void LitBlendBlt(Bitmap *src, int dst_x, int dst_y, int light_amount);
// TODO: generic "draw transformed" function? What about mask option?
void FlipBlt(Bitmap *src, int dst_x, int dst_y, GraphicFlip flip);
void RotateBlt(Bitmap *src, int dst_x, int dst_y, fixed_t angle);
void RotateBlt(Bitmap *src, int dst_x, int dst_y, int pivot_x, int pivot_y, fixed_t angle);
//=========================================================================
// Pixel operations
//=========================================================================
// Fills the whole bitmap with given color (black by default)
void Clear(color_t color = 0);
void ClearTransparent();
// The PutPixel and GetPixel are supposed to be safe and therefore
// relatively slow operations. They should not be used for changing large
// blocks of bitmap memory - reading/writing from/to scan lines should be
// done in such cases.
void PutPixel(int x, int y, color_t color);
int GetPixel(int x, int y) const;
//=========================================================================
// Vector drawing operations
//=========================================================================
void DrawLine(const Line &ln, color_t color);
void DrawTriangle(const Triangle &tr, color_t color);
void DrawRect(const Rect &rc, color_t color);
void FillRect(const Rect &rc, color_t color);
void FillCircle(const Circle &circle, color_t color);
// Fills the whole bitmap with given color
void Fill(color_t color);
void FillTransparent();
// Floodfills an enclosed area, starting at point
void FloodFill(int x, int y, color_t color);
//=========================================================================
// Direct access operations
//=========================================================================
// TODO: think how to increase safety over this (some fixed memory buffer class with iterator?)
// Gets scanline for directly writing into it
inline unsigned char *GetScanLineForWriting(int index) {
assert(index >= 0 && index < GetHeight());
return _alBitmap->line[index];
}
inline unsigned char *GetDataForWriting() {
return _alBitmap->line[0];
}
// Copies buffer contents into scanline
void SetScanLine(int index, unsigned char *data, int data_size = -1);
private:
BITMAP *_alBitmap;
bool _isDataOwner;
};
namespace BitmapHelper {
// TODO: revise those functions later (currently needed in a few very specific cases)
// NOTE: the resulting object __owns__ bitmap data from now on
Bitmap *CreateRawBitmapOwner(BITMAP *al_bmp);
// NOTE: the resulting object __does not own__ bitmap data
Bitmap *CreateRawBitmapWrapper(BITMAP *al_bmp);
} // namespace BitmapHelper
} // namespace Shared
} // namespace AGS
} // namespace AGS3
#endif

View File

@@ -0,0 +1,240 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/shared/gfx/bitmap.h"
#include "ags/shared/util/memory.h"
namespace AGS3 {
namespace AGS {
namespace Shared {
// TODO: revise this construction later
namespace BitmapHelper {
Bitmap *CreateBitmap(int width, int height, int color_depth) {
Bitmap *bitmap = new Bitmap();
if (!bitmap->Create(width, height, color_depth)) {
delete bitmap;
bitmap = nullptr;
}
return bitmap;
}
Bitmap *CreateClearBitmap(int width, int height, int color_depth, int clear_color) {
Bitmap *bitmap = new Bitmap();
if (!bitmap->Create(width, height, color_depth)) {
delete bitmap;
return nullptr;
}
bitmap->Clear(clear_color);
return bitmap;
}
Bitmap *CreateTransparentBitmap(int width, int height, int color_depth) {
Bitmap *bitmap = new Bitmap();
if (!bitmap->CreateTransparent(width, height, color_depth)) {
delete bitmap;
bitmap = nullptr;
}
return bitmap;
}
Bitmap *CreateSubBitmap(Bitmap *src, const Rect &rc) {
Bitmap *bitmap = new Bitmap();
if (!bitmap->CreateSubBitmap(src, rc)) {
delete bitmap;
bitmap = nullptr;
}
return bitmap;
}
Bitmap *CreateBitmapCopy(Bitmap *src, int color_depth) {
Bitmap *bitmap = new Bitmap();
if (!bitmap->CreateCopy(src, color_depth)) {
delete bitmap;
bitmap = nullptr;
}
return bitmap;
}
Bitmap *LoadFromFile(const char *filename) {
Bitmap *bitmap = new Bitmap();
if (!bitmap->LoadFromFile(filename)) {
delete bitmap;
bitmap = nullptr;
}
return bitmap;
}
Bitmap *LoadFromFile(PACKFILE *pf) {
Bitmap *bitmap = new Bitmap();
if (!bitmap->LoadFromFile(pf)) {
delete bitmap;
bitmap = nullptr;
}
return bitmap;
}
Bitmap *AdjustBitmapSize(Bitmap *src, int width, int height) {
int oldw = src->GetWidth(), oldh = src->GetHeight();
if ((oldw == width) && (oldh == height))
return src;
Bitmap *bmp = BitmapHelper::CreateBitmap(width, height, src->GetColorDepth());
bmp->StretchBlt(src, RectWH(0, 0, oldw, oldh), RectWH(0, 0, width, height));
return bmp;
}
void MakeOpaque(Bitmap *bmp) {
if (bmp->GetColorDepth() < 32)
return; // no alpha channel
for (int i = 0; i < bmp->GetHeight(); ++i) {
uint32_t *line = reinterpret_cast<uint32_t *>(bmp->GetScanLineForWriting(i));
uint32_t *line_end = line + bmp->GetWidth();
for (uint32_t *px = line; px != line_end; ++px)
*px = makeacol32(getr32(*px), getg32(*px), getb32(*px), 255);
}
}
void MakeOpaqueSkipMask(Bitmap *bmp) {
if (bmp->GetColorDepth() < 32)
return; // no alpha channel
for (int i = 0; i < bmp->GetHeight(); ++i) {
uint32_t *line = reinterpret_cast<uint32_t *>(bmp->GetScanLineForWriting(i));
uint32_t *line_end = line + bmp->GetWidth();
for (uint32_t *px = line; px != line_end; ++px)
if (*px != MASK_COLOR_32)
*px = makeacol32(getr32(*px), getg32(*px), getb32(*px), 255);
}
}
void ReplaceAlphaWithRGBMask(Bitmap *bmp) {
if (bmp->GetColorDepth() < 32)
return; // no alpha channel
for (int i = 0; i < bmp->GetHeight(); ++i) {
uint32_t *line = reinterpret_cast<uint32_t *>(bmp->GetScanLineForWriting(i));
uint32_t *line_end = line + bmp->GetWidth();
for (uint32_t *px = line; px != line_end; ++px)
if (geta32(*px) == 0)
*px = MASK_COLOR_32;
}
}
// Functor that copies the "mask color" pixels from source to dest
template <class TPx, size_t BPP_>
struct PixelTransCpy {
static const size_t BPP = BPP_;
inline void operator ()(uint8_t *dst, const uint8_t *src, uint32_t mask_color, bool /*use_alpha*/) const {
if (*(const TPx *)src == mask_color)
*(TPx *)dst = mask_color;
}
};
// Functor that tells to never skip a pixel in the mask
struct PixelNoSkip {
inline bool operator ()(uint8_t * /*data*/, uint32_t /*mask_color*/, bool /*use_alpha*/) const {
return false;
}
};
typedef PixelTransCpy<uint8_t, 1> PixelTransCpy8;
typedef PixelTransCpy<uint16_t, 2> PixelTransCpy16;
// Functor that copies the "mask color" pixels from source to dest, 24-bit depth
struct PixelTransCpy24 {
static const size_t BPP = 3;
inline void operator ()(uint8_t *dst, const uint8_t *src, uint32_t mask_color, bool /*use_alpha*/) const {
const uint8_t *mcol_ptr = (const uint8_t *)&mask_color;
if (src[0] == mcol_ptr[0] && src[1] == mcol_ptr[1] && src[2] == mcol_ptr[2]) {
dst[0] = mcol_ptr[0];
dst[1] = mcol_ptr[1];
dst[2] = mcol_ptr[2];
}
}
};
// Functor that copies the "mask color" pixels from source to dest, 32-bit depth, with alpha
struct PixelTransCpy32 {
static const size_t BPP = 4;
inline void operator ()(uint8_t *dst, const uint8_t *src, uint32_t mask_color, bool use_alpha) const {
if (*(const uint32_t *)src == mask_color)
*(uint32_t *)dst = mask_color;
else if (use_alpha)
dst[3] = src[3]; // copy alpha channel
else
dst[3] = 0xFF; // set the alpha channel byte to opaque
}
};
// Functor that tells to skip pixels if they match the mask color or have alpha = 0
struct PixelTransSkip32 {
inline bool operator ()(uint8_t *data, uint32_t mask_color, bool use_alpha) const {
return *(const uint32_t *)data == mask_color || (use_alpha && data[3] == 0);
}
};
// Applies bitmap mask, using 2 functors:
// - one that tells whether to skip current pixel;
// - another that copies the color from src to dest
template <class FnPxProc, class FnSkip>
void ApplyMask(uint8_t *dst, const uint8_t *src, size_t pitch, size_t height,
FnPxProc proc, FnSkip skip, uint32_t mask_color, bool dst_has_alpha, bool mask_has_alpha) {
for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < pitch; x += FnPxProc::BPP, src += FnPxProc::BPP, dst += FnPxProc::BPP) {
if (!skip(dst, mask_color, dst_has_alpha))
proc(dst, src, mask_color, mask_has_alpha);
}
}
}
void CopyTransparency(Bitmap *dst, const Bitmap *mask, bool dst_has_alpha, bool mask_has_alpha) {
color_t mask_color = mask->GetMaskColor();
uint8_t *dst_ptr = dst->GetDataForWriting();
const uint8_t *src_ptr = mask->GetData();
const size_t bpp = mask->GetBPP();
const size_t pitch = mask->GetLineLength();
const size_t height = mask->GetHeight();
if (bpp == 1)
ApplyMask(dst_ptr, src_ptr, pitch, height, PixelTransCpy8(), PixelNoSkip(), mask_color, dst_has_alpha, mask_has_alpha);
else if (bpp == 2)
ApplyMask(dst_ptr, src_ptr, pitch, height, PixelTransCpy16(), PixelNoSkip(), mask_color, dst_has_alpha, mask_has_alpha);
else if (bpp == 3)
ApplyMask(dst_ptr, src_ptr, pitch, height, PixelTransCpy24(), PixelNoSkip(), mask_color, dst_has_alpha, mask_has_alpha);
else
ApplyMask(dst_ptr, src_ptr, pitch, height, PixelTransCpy32(), PixelTransSkip32(), mask_color, dst_has_alpha, mask_has_alpha);
}
void ReadPixelsFromMemory(Bitmap *dst, const uint8_t *src_buffer, const size_t src_pitch, const size_t src_px_offset) {
const size_t bpp = dst->GetBPP();
const size_t src_px_pitch = src_pitch / bpp;
if (src_px_offset >= src_px_pitch)
return; // nothing to copy
Memory::BlockCopy(dst->GetDataForWriting(), dst->GetLineLength(), 0, src_buffer, src_pitch, src_px_offset * bpp, dst->GetHeight());
}
} // namespace BitmapHelper
} // namespace Shared
} // namespace AGS
} // namespace AGS3

View File

@@ -0,0 +1,114 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Base bitmap header
//
//=============================================================================
#ifndef AGS_SHARED_GFX_BITMAP_H
#define AGS_SHARED_GFX_BITMAP_H
#include "ags/shared/gfx/gfx_def.h"
#include "ags/shared/util/geometry.h"
#include "ags/shared/util/string.h"
namespace AGS3 {
namespace AGS {
namespace Shared {
// Mask option for blitting one bitmap on another
enum BitmapMaskOption {
// Plain copies bitmap pixels
kBitmap_Copy,
// Consider mask color fully transparent and do not copy pixels having it
kBitmap_Transparency
};
} // namespace Shared
} // namespace AGS
} // namespace AGS3
#include "ags/shared/gfx/allegro_bitmap.h"
namespace AGS3 {
namespace AGS {
namespace Shared {
class Bitmap;
// TODO: revise this construction later
namespace BitmapHelper {
// Helper functions, that delete faulty bitmaps automatically, and return
// NULL if bitmap could not be created.
// NOTE: color_depth is in BITS per pixel (i.e. 8, 16, 24, 32...).
// NOTE: in all of these color_depth may be passed as 0 in which case a default
// color depth will be used (as previously set for the system).
// Creates a new bitmap of the given format; the pixel contents are undefined.
Bitmap *CreateBitmap(int width, int height, int color_depth = 0);
// Creates a new bitmap and clears it with the given color
Bitmap *CreateClearBitmap(int width, int height, int color_depth = 0, int clear_color = 0);
// Creates a new bitmap and clears it with the transparent color
Bitmap *CreateTransparentBitmap(int width, int height, int color_depth = 0);
// Creates a sub-bitmap of the given bitmap; the sub-bitmap is a reference to
// particular region inside a parent.
// WARNING: the parent bitmap MUST be kept in memory for as long as sub-bitmap exists!
Bitmap *CreateSubBitmap(Bitmap *src, const Rect &rc);
// Creates a plain copy of the given bitmap, optionally converting to a different color depth;
// pass color depth 0 to keep the original one.
Bitmap *CreateBitmapCopy(Bitmap *src, int color_depth = 0);
// Load a bitmap from file; supported formats currently are: BMP, PCX.
Bitmap *LoadFromFile(const char *filename);
inline Bitmap *LoadFromFile(const String &filename) {
return LoadFromFile(filename.GetCStr());
}
Bitmap *LoadFromFile(PACKFILE *pf);
// Stretches bitmap to the requested size. The new bitmap will have same
// colour depth. Returns original bitmap if no changes are necessary.
Bitmap *AdjustBitmapSize(Bitmap *src, int width, int height);
// Makes the given bitmap opaque (full alpha), while keeping pixel RGB unchanged.
void MakeOpaque(Bitmap *bmp);
// Makes the given bitmap opaque (full alpha), while keeping pixel RGB unchanged.
// Skips mask color (leaves it with zero alpha).
void MakeOpaqueSkipMask(Bitmap *bmp);
// Replaces fully transparent (alpha = 0) pixels with standard mask color.
void ReplaceAlphaWithRGBMask(Bitmap *bmp);
// Copy transparency mask and/or alpha channel from one bitmap into another.
// Destination and mask bitmaps must be of the same pixel format.
// Transparency is merged, meaning that fully transparent pixels on
// destination should remain such regardless of mask pixel values.
void CopyTransparency(Bitmap *dst, const Bitmap *mask, bool dst_has_alpha, bool mask_has_alpha);
// Copy pixel data into bitmap from memory buffer. It is required that the
// source matches bitmap format and has enough data.
// Pitch is given in bytes and defines the length of the source scan line.
// Offset is optional and defines horizontal offset, in pixels.
void ReadPixelsFromMemory(Bitmap *dst, const uint8_t *src_buffer, const size_t src_pitch, const size_t src_px_offset = 0);
} // namespace BitmapHelper
} // namespace Shared
} // namespace AGS
} // namespace AGS3
#endif

View File

@@ -0,0 +1,152 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
//=============================================================================
//
// Graphic definitions and type/unit conversions.
//
//=============================================================================
#ifndef AGS_SHARED_GFX_GFX_DEF_H
#define AGS_SHARED_GFX_GFX_DEF_H
namespace AGS3 {
namespace AGS {
namespace Shared {
enum GraphicFlip {
kFlip_None,
kFlip_Horizontal, // this means - mirror over horizontal middle line
kFlip_Vertical, // this means - mirror over vertical middle line
kFlip_Both // mirror over diagonal (horizontal and vertical)
};
enum BlendMode {
// free blending (ARGB -> ARGB) modes
kBlendMode_NoAlpha = 0, // ignore alpha channel
kBlendMode_Alpha, // alpha-blend src to dest, combining src & dest alphas
// NOTE: add new modes here
kNumBlendModes
};
namespace GfxDef {
// Converts percentage of transparency into alpha
inline int Trans100ToAlpha255(int transparency) {
return ((100 - transparency) * 255) / 100;
}
// Converts alpha into percentage of transparency
inline int Alpha255ToTrans100(int alpha) {
return 100 - ((alpha * 100) / 255);
}
// Special formulae to reduce precision loss and support flawless forth &
// reverse conversion for multiplies of 10%
inline int Trans100ToAlpha250(int transparency) {
return ((100 - transparency) * 25) / 10;
}
inline int Alpha250ToTrans100(int alpha) {
return 100 - ((alpha * 10) / 25);
}
// Convert correct 100-ranged transparency into legacy 255-ranged
// transparency; legacy inconsistent transparency value range:
// 0 = opaque,
// 255 = invisible,
// 1 -to- 254 = barely visible -to- mostly visible (as proper alpha)
inline int Trans100ToLegacyTrans255(int transparency) {
switch (transparency) {
case 0:
return 0; // this means opaque
case 100:
return 255; // this means invisible
default:
// the rest of the range works as alpha
return Trans100ToAlpha250(transparency);
}
}
// Convert legacy 255-ranged "incorrect" transparency into proper
// 100-ranged transparency.
inline int LegacyTrans255ToTrans100(int legacy_transparency) {
switch (legacy_transparency) {
case 0:
return 0; // this means opaque
case 255:
return 100; // this means invisible
default:
// the rest of the range works as alpha
return Alpha250ToTrans100(legacy_transparency);
}
}
// Convert legacy 100-ranged transparency into proper 255-ranged alpha
// 0 => alpha 255
// 100 => alpha 0
// 1 - 99 => alpha 1 - 244
inline int LegacyTrans100ToAlpha255(int legacy_transparency) {
switch (legacy_transparency) {
case 0:
return 255; // this means opaque
case 100:
return 0; // this means invisible
default:
// the rest of the range works as alpha (only 100-ranged)
return legacy_transparency * 255 / 100;
}
}
// Convert legacy 255-ranged transparency into proper 255-ranged alpha
inline int LegacyTrans255ToAlpha255(int legacy_transparency) {
switch (legacy_transparency) {
case 0:
return 255; // this means opaque
case 255:
return 0; // this means invisible
default:
// the rest of the range works as alpha
return legacy_transparency;
}
}
// Convert 255-ranged alpha into legacy 255-ranged transparency
inline int Alpha255ToLegacyTrans255(int alpha) {
switch (alpha) {
case 255:
return 0; // this means opaque
case 0:
return 255; // this means invisible
default:
// the rest of the range works as alpha
return alpha;
}
}
} // namespace GfxDef
} // namespace Shared
} // namespace AGS
} // namespace AGS3
#endif

View File

@@ -0,0 +1,151 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/shared/gfx/image.h"
#include "ags/shared/util/file.h"
#include "ags/shared/util/stream.h"
#include "ags/lib/allegro.h"
#include "common/file.h"
#include "common/str.h"
#include "common/stream.h"
#include "common/textconsole.h"
#include "image/bmp.h"
#include "image/iff.h"
#include "image/pcx.h"
#include "image/tga.h"
#define VGA_COLOR_TRANS(x) ((x) * 255 / 63)
namespace AGS3 {
template<class DECODER>
BITMAP *decodeImageStream(Common::SeekableReadStream &stream, color *pal) {
DECODER decoder;
if (decoder.loadStream(stream)) {
// Create the output surface
const Graphics::Surface *src = decoder.getSurface();
// Copy the decoded surface
int bpp = 8 * src->format.bytesPerPixel;
if (bpp == 24)
bpp = 32;
Surface *dest = (Surface *)create_bitmap_ex(bpp, src->w, src->h);
dest->blitFrom(*src);
// Copy the palette
const Graphics::Palette &palP = decoder.getPalette();
if (pal) {
for (uint idx = 0; idx < palP.size(); ++idx) {
palP.get(idx, pal[idx].r, pal[idx].g, pal[idx].b);
pal[idx].filler = 0xff;
}
}
return dest;
} else {
return nullptr;
}
}
template<class DECODER>
BITMAP *decodeImage(const char *filename, color *pal) {
AGS::Shared::Stream *file = AGS3::AGS::Shared::File::OpenFileRead(filename);
if (!file)
return nullptr;
AGS::Shared::ScummVMReadStream f(file);
return decodeImageStream<DECODER>(f, pal);
}
template<class DECODER>
BITMAP *decodeImage(PACKFILE *pf, color *pal) {
if (!pf)
return nullptr;
AGS::Shared::ScummVMPackReadStream f(pf);
f.seek(0);
return decodeImageStream<DECODER>(f, pal);
}
BITMAP *load_bmp(const char *filename, color *pal) {
return decodeImage<Image::BitmapDecoder>(filename, pal);
}
BITMAP *load_lbm(const char *filename, color *pal) {
return decodeImage<Image::IFFDecoder>(filename, pal);
}
BITMAP *load_pcx(const char *filename, color *pal) {
return decodeImage<Image::PCXDecoder>(filename, pal);
}
BITMAP *load_tga(const char *filename, color *pal) {
return decodeImage<Image::TGADecoder>(filename, pal);
}
BITMAP *load_bitmap(const char *filename, color *pal) {
Common::String fname(filename);
if (fname.hasSuffixIgnoreCase(".bmp"))
return load_bmp(filename, pal);
else if (fname.hasSuffixIgnoreCase(".lbm"))
return load_lbm(filename, pal);
else if (fname.hasSuffixIgnoreCase(".pcx"))
return load_pcx(filename, pal);
else if (fname.hasSuffixIgnoreCase(".tga"))
return load_tga(filename, pal);
else
error("Unknown image file - %s", filename);
}
BITMAP *load_bitmap(PACKFILE *pf, color *pal) {
BITMAP *result;
if ((result = decodeImage<Image::BitmapDecoder>(pf, pal)) != nullptr)
return result;
if ((result = decodeImage<Image::IFFDecoder>(pf, pal)) != nullptr)
return result;
if ((result = decodeImage<Image::PCXDecoder>(pf, pal)) != nullptr)
return result;
if ((result = decodeImage<Image::TGADecoder>(pf, pal)) != nullptr)
return result;
error("Unknown image file");
}
bool save_bitmap(Common::WriteStream &out, BITMAP *bmp, const RGB *pal) {
const Graphics::ManagedSurface &src = bmp->getSurface();
if (bmp->format.isCLUT8() && pal) {
byte palette[256 * 3];
for (int c = 0, i = 0; c < 256; ++c, i += 3) {
palette[i] = VGA_COLOR_TRANS(pal[c].r);
palette[i + 1] = VGA_COLOR_TRANS(pal[c].g);
palette[i + 2] = VGA_COLOR_TRANS(pal[c].b);
}
return Image::writeBMP(out, src, palette);
} else {
return Image::writeBMP(out, src);
}
}
} // namespace AGS

View File

@@ -0,0 +1,42 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_SHARED_GFX_IMAGE_H
#define AGS_SHARED_GFX_IMAGE_H
#include "ags/lib/allegro.h"
namespace AGS3 {
struct PACKFILE;
extern BITMAP *load_bitmap(PACKFILE *pf, color *pal);
extern BITMAP *load_bitmap(const char *filename, color *pal);
extern BITMAP *load_bmp(const char *filename, color *pal);
extern BITMAP *load_lbm(const char *filename, color *pal);
extern BITMAP *load_pcx(const char *filename, color *pal);
extern BITMAP *load_tga(const char *filename, color *pal);
extern bool save_bitmap(Common::WriteStream &out, BITMAP *bmp, const RGB *pal);
} // namespace AGS3
#endif