Screenshot: fixed alpha channel handling.

* Screenshot always used B_RGBA32 color space, but did not care about the
  alpha channel at all. Now it only uses that space when "includeBorder"
  is used.
* Utility::_MakeTabSpaceTransparent() now also makes sure that the rest
  of the bitmap has the correct alpha channel set. This fixes bug #10491.
* Minor cleanup.
This commit is contained in:
Axel Dörfler
2014-01-31 00:43:31 +01:00
parent 6464f4f659
commit cc94643724
6 changed files with 152 additions and 141 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ SubDir HAIKU_TOP src apps screenshot ;
HAIKU_MULTIPLE_LOCALIZED_TARGETS on $(SUBDIR) = 1 ;
UsePrivateHeaders interface ;
UsePrivateHeaders interface shared ;
Application Screenshot :
ScreenshotApp.cpp
+25 -23
View File
@@ -63,22 +63,22 @@ Screenshot::ArgvReceived(int32 argc, char** argv)
for (int32 i = 0; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
_ShowHelp();
else if (strcmp(argv[i], "-b") == 0
else if (strcmp(argv[i], "-b") == 0
|| strcmp(argv[i], "--border") == 0)
includeBorder = true;
else if (strcmp(argv[i], "-m") == 0
else if (strcmp(argv[i], "-m") == 0
|| strcmp(argv[i], "--mouse-pointer") == 0)
includeCursor = true;
else if (strcmp(argv[i], "-w") == 0
else if (strcmp(argv[i], "-w") == 0
|| strcmp(argv[i], "--window") == 0)
grabActiveWindow = true;
else if (strcmp(argv[i], "-s") == 0
else if (strcmp(argv[i], "-s") == 0
|| strcmp(argv[i], "--silent") == 0)
saveScreenshotSilent = true;
else if (strcmp(argv[i], "-f") == 0
|| strncmp(argv[i], "--format", 6) == 0
|| strncmp(argv[i], "--format=", 7) == 0)
imageFileType = _GetImageType(argv[i + 1]);
imageFileType = _ImageType(argv[i + 1]);
else if (strcmp(argv[i], "-d") == 0
|| strncmp(argv[i], "--delay", 7) == 0
|| strncmp(argv[i], "--delay=", 8) == 0) {
@@ -94,9 +94,9 @@ Screenshot::ArgvReceived(int32 argc, char** argv)
fLaunchGui = false;
return;
}
} else if (strcmp(argv[i], "-c") == 0
} else if (strcmp(argv[i], "-c") == 0
|| strcmp(argv[i], "--clipboard") == 0)
copyToClipboard = true;
copyToClipboard = true;
else if (i == argc - 1)
outputFilename = argv[i];
}
@@ -105,7 +105,7 @@ Screenshot::ArgvReceived(int32 argc, char** argv)
if (copyToClipboard || saveScreenshotSilent) {
fLaunchGui = false;
BBitmap* screenshot = fUtility->MakeScreenshot(includeCursor,
grabActiveWindow, includeBorder);
@@ -114,9 +114,9 @@ Screenshot::ArgvReceived(int32 argc, char** argv)
if (copyToClipboard)
fUtility->CopyToClipboard(*screenshot);
if (saveScreenshotSilent)
fUtility->Save(&screenshot, outputFilename, imageFileType);
fUtility->Save(screenshot, outputFilename, imageFileType);
delete screenshot;
}
@@ -219,7 +219,7 @@ Screenshot::_New(bigtime_t delay)
BPoint cursorHotSpot;
get_mouse(&fUtility->cursorPosition, NULL);
get_mouse_bitmap(&fUtility->cursorBitmap, &cursorHotSpot);
fUtility->cursorPosition -= cursorHotSpot;
fUtility->cursorPosition -= cursorHotSpot;
// Put the mouse area in a bitmap
BRect bounds = fUtility->cursorBitmap->Bounds();
@@ -284,7 +284,7 @@ Screenshot::_GetActiveWindowFrame()
message.AddSpecifier("Active");
message.AddSpecifier("Window", index);
messenger.SendMessage(&message, &reply, B_INFINITE_TIMEOUT, 50000);
if (reply.what == B_MESSAGE_NOT_UNDERSTOOD)
break;
@@ -346,7 +346,7 @@ Screenshot::_GetActiveWindowFrame()
fUtility->borderSize = windowInfo->border_size;
free(windowInfo);
// Make sure that fActiveWindowFrame doesn't extend beyond the screen frame
BRect screenFrame(BScreen().Frame());
if (fUtility->activeWindowFrame.left < screenFrame.left)
@@ -363,26 +363,28 @@ Screenshot::_GetActiveWindowFrame()
int32
Screenshot::_GetImageType(const char* name) const
Screenshot::_ImageType(const char* name) const
{
if (strcmp(name, "bmp") == 0)
if (strcasecmp(name, "bmp") == 0)
return B_BMP_FORMAT;
else if (strcmp(name, "gif") == 0)
if (strcasecmp(name, "gif") == 0)
return B_GIF_FORMAT;
else if (strcmp(name, "jpg") == 0 || strcmp(name, "jpeg") == 0)
if (strcasecmp(name, "jpg") == 0 || strcmp(name, "jpeg") == 0)
return B_JPEG_FORMAT;
else if (strcmp(name, "ppm") == 0)
if (strcasecmp(name, "ppm") == 0)
return B_PPM_FORMAT;
else if (strcmp(name, "tga") == 0 || strcmp(name, "targa") == 0)
if (strcasecmp(name, "tga") == 0 || strcmp(name, "targa") == 0)
return B_TGA_FORMAT;
else if (strcmp(name, "tif") == 0 || strcmp(name, "tiff") == 0)
if (strcasecmp(name, "tif") == 0 || strcmp(name, "tiff") == 0)
return B_TIFF_FORMAT;
else {
return B_PNG_FORMAT;
}
return B_PNG_FORMAT;
}
// #pragma mark -
int
main()
{
+3 -3
View File
@@ -26,10 +26,10 @@ private:
void _ShowHelp();
void _New(bigtime_t delay);
status_t _GetActiveWindowFrame();
int32 _GetImageType(const char* name) const;
int32 _ImageType(const char* name) const;
private:
Utility* fUtility;
bool fLaunchGui;
};
+47 -69
View File
@@ -1,4 +1,5 @@
/*
* Copyright 2010-2014, Haiku Inc. All rights reserved.
* Copyright 2010 Wim van der Meer <[email protected]>
* Copyright Karsten Heimrich, [email protected].
* All rights reserved. Distributed under the terms of the MIT License.
@@ -110,8 +111,8 @@ ScreenshotWindow::ScreenshotWindow(const Utility& utility, bool silent,
:
BWindow(BRect(0, 0, 200.0, 100.0), B_TRANSLATE_SYSTEM_NAME("Screenshot"),
B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_AVOID_FRONT
| B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS
| B_CLOSE_ON_ESCAPE),
| B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS
| B_CLOSE_ON_ESCAPE),
fUtility(utility),
fDelayControl(NULL),
fScreenshot(NULL),
@@ -181,9 +182,10 @@ ScreenshotWindow::ScreenshotWindow(const Utility& utility, bool silent,
fTranslatorMenu);
menuFormat->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BButton* showSettings = new BButton("", B_TRANSLATE("Settings"B_UTF8_ELLIPSIS),
new BMessage(kSettings));
showSettings->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, B_ALIGN_BOTTOM));
BButton* showSettings = new BButton("",
B_TRANSLATE("Settings" B_UTF8_ELLIPSIS), new BMessage(kSettings));
showSettings->SetExplicitAlignment(
BAlignment(B_ALIGN_RIGHT, B_ALIGN_BOTTOM));
BBox* divider = new BBox(B_FANCY_BORDER, NULL);
divider->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1));
@@ -195,7 +197,7 @@ ScreenshotWindow::ScreenshotWindow(const Utility& utility, bool silent,
const float kLabelSpacing = be_control_look->DefaultLabelSpacing();
fPreview = new BView("preview", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
BBox *previewBox = new BBox(B_FANCY_BORDER, fPreview);
BBox* previewBox = new BBox(B_FANCY_BORDER, fPreview);
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
.SetInsets(kSpacing)
@@ -219,6 +221,7 @@ ScreenshotWindow::ScreenshotWindow(const Utility& utility, bool silent,
.Add(menuFormat->CreateLabelLayoutItem(), 0, 3)
.Add(menuFormat->CreateMenuBarLayoutItem(), 1, 3, 3, 1)
.End()
.AddStrut(kSpacing / 2)
.Add(showSettings)
.AddGlue()
.End()
@@ -337,7 +340,6 @@ ScreenshotWindow::MessageReceived(BMessage* message)
BEntry entry(&ref, true);
if (entry.InitCheck() == B_OK) {
BPath path;
// Could return B_BUSY
if (entry.GetPath(&path) == B_OK) {
BString label(path.Path());
_AddItemToPathMenu(path.Path(), label, 3, true);
@@ -438,7 +440,6 @@ void
ScreenshotWindow::_UpdatePreviewPanel()
{
float height = 150.0f;
float width = (fScreenshot->Bounds().Width()
/ fScreenshot->Bounds().Height()) * height;
@@ -481,34 +482,35 @@ ScreenshotWindow::_SetupOutputPathMenu(const BMessage& settings)
BString label(B_TRANSLATE("Home folder"));
_AddItemToPathMenu(path.Path(), label, 0,
(path.Path() == lastSelectedPath), 'H');
path.Path() == lastSelectedPath, 'H');
path.Append("Desktop");
label.SetTo(B_TRANSLATE("Desktop"));
_AddItemToPathMenu(path.Path(), label, 0, (
path.Path() == lastSelectedPath), 'D');
_AddItemToPathMenu(path.Path(), label, 0,
path.Path() == lastSelectedPath, 'D');
find_directory(B_BEOS_ETC_DIRECTORY, &path);
path.Append("artwork");
label.SetTo(B_TRANSLATE("Artwork folder"));
_AddItemToPathMenu(path.Path(), label, 2,
(path.Path() == lastSelectedPath), 'A');
path.Path() == lastSelectedPath, 'A');
int32 i = 0;
BString userPath;
while (settings.FindString("path", ++i, &userPath) == B_OK) {
_AddItemToPathMenu(userPath.String(), userPath, 3,
(userPath == lastSelectedPath));
userPath == lastSelectedPath);
}
if (!fLastSelectedPath) {
if (settings.IsEmpty() || lastSelectedPath.Length() == 0) {
fOutputPathMenu->ItemAt(1)->SetMarked(true);
fLastSelectedPath = fOutputPathMenu->ItemAt(1);
} else
} else {
_AddItemToPathMenu(lastSelectedPath.String(), lastSelectedPath, 3,
true);
}
}
fOutputPathMenu->AddItem(new BSeparatorItem());
@@ -581,7 +583,7 @@ ScreenshotWindow::_SetupTranslatorMenu()
int32 imageFileType;
for (int32 i = 0; i < fTranslatorMenu->CountItems(); ++i) {
BMenuItem* item = fTranslatorMenu->ItemAt(i);
if (item && item->Message()) {
if (item != NULL && item->Message()) {
item->Message()->FindInt32("be:type", &imageFileType);
if (fImageFileType == imageFileType) {
item->SetMarked(true);
@@ -618,13 +620,13 @@ ScreenshotWindow::_SaveScreenshot()
B_TRANSLATE("Overwrite"),
NULL, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
overwriteAlert->SetShortcut(0, B_ESCAPE);
overwriteAlert->SetShortcut(0, B_ESCAPE);
if (overwriteAlert->Go() == 0)
return B_CANCELED;
if (overwriteAlert->Go() == 0)
return B_CANCELED;
}
return fUtility.Save(&fScreenshot, path.Path(), fImageFileType);
return fUtility.Save(fScreenshot, path.Path(), fImageFileType);
}
@@ -635,62 +637,38 @@ ScreenshotWindow::_ShowSettings(bool activate)
return;
// Find a translator
translator_id translator = 0;
BTranslatorRoster *roster = BTranslatorRoster::Default();
translator_id* translators = NULL;
int32 numTranslators = 0;
if (roster->GetAllTranslators(&translators, &numTranslators) != B_OK)
return;
bool foundTranslator = false;
for (int32 x = 0; x < numTranslators; x++) {
const translation_format* formats = NULL;
int32 numFormats;
if (roster->GetOutputFormats(translators[x], &formats,
&numFormats) == B_OK) {
for (int32 i = 0; i < numFormats; ++i) {
if (formats[i].type == static_cast<uint32>(fImageFileType)) {
translator = translators[x];
foundTranslator = true;
break;
}
}
}
if (foundTranslator)
break;
}
delete [] translators;
if (!foundTranslator)
translator_id translator;
if (fUtility.FindTranslator(fImageFileType, translator) != B_OK)
return;
// Create a window with a configuration view
BView *view;
BView* view;
BRect rect(0, 0, 239, 239);
status_t err = roster->MakeConfigurationView(translator, NULL, &view,
&rect);
if (err < B_OK || view == NULL) {
BAlert *alert = new BAlert(NULL, strerror(err), "OK");
status_t status = BTranslatorRoster::Default()->MakeConfigurationView(
translator, NULL, &view, &rect);
if (status != B_OK || view == NULL) {
// TODO: proper translation, better error dialog
BAlert* alert = new BAlert(NULL, strerror(status), "OK");
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
alert->Go();
} else if (fSettingsWindow != NULL) {
fSettingsWindow->RemoveChild(fSettingsWindow->ChildAt(0));
float width, height;
view->GetPreferredSize(&width, &height);
fSettingsWindow->ResizeTo(width, height);
fSettingsWindow->AddChild(view);
if (activate)
fSettingsWindow->Activate();
} else {
if (fSettingsWindow) {
fSettingsWindow->RemoveChild(fSettingsWindow->ChildAt(0));
float width, height;
view->GetPreferredSize(&width, &height);
fSettingsWindow->ResizeTo(width, height);
fSettingsWindow->AddChild(view);
if (activate)
fSettingsWindow->Activate();
} else {
fSettingsWindow = new BWindow(rect,
B_TRANSLATE("Translator Settings"),
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_NOT_ZOOMABLE | B_NOT_RESIZABLE);
fSettingsWindow->AddFilter(new QuitMessageFilter(this));
fSettingsWindow->AddChild(view);
fSettingsWindow->CenterOnScreen();
fSettingsWindow->Show();
}
fSettingsWindow = new BWindow(rect,
B_TRANSLATE("Translator Settings"),
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_NOT_ZOOMABLE | B_NOT_RESIZABLE);
fSettingsWindow->AddFilter(new QuitMessageFilter(this));
fSettingsWindow->AddChild(view);
fSettingsWindow->CenterOnScreen();
fSettingsWindow->Show();
}
}
@@ -700,7 +678,7 @@ ScreenshotWindow::_FindValidFileName(const char* name)
{
BString baseName(name);
if (fExtension.Compare(""))
if (!fExtension.IsEmpty())
baseName.RemoveLast(fExtension);
if (!fLastSelectedPath)
@@ -710,7 +688,7 @@ ScreenshotWindow::_FindValidFileName(const char* name)
if (orgPath == NULL)
return baseName;
fExtension = fUtility.GetFileNameExtension(fImageFileType);
fExtension = fUtility.FileNameExtension(fImageFileType);
BPath outputPath = orgPath;
BString fileName;
+69 -39
View File
@@ -1,9 +1,11 @@
/*
* Copyright 2010-2014, Haiku Inc. All rights reserved.
* Copyright 2010 Wim van der Meer <WPJvanderMeer@gmail.com>
* Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler
* Karsten Heimrich
* Fredrik Modéen
* Christophe Huriaux
@@ -31,14 +33,15 @@
#include <Translator.h>
#include <View.h>
#include <AutoDeleter.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "Screenshot"
const char* Utility::sDefaultFileNameBase =
B_TRANSLATE_MARK_COMMENT("screenshot",
"Base filename of screenshot files");
const char* Utility::sDefaultFileNameBase = B_TRANSLATE_MARK_COMMENT(
"screenshot", "Base filename of screenshot files");
Utility::Utility()
@@ -64,7 +67,7 @@ Utility::CopyToClipboard(const BBitmap& screenshot) const
if (be_clipboard->Lock()) {
be_clipboard->Clear();
BMessage* clipboard = be_clipboard->Data();
if (clipboard) {
if (clipboard != NULL) {
BMessage* bitmap = new BMessage();
screenshot.Archive(bitmap);
clipboard->AddMessage("image/bitmap", bitmap);
@@ -75,13 +78,12 @@ Utility::CopyToClipboard(const BBitmap& screenshot) const
}
/*!
Save the screenshot to the file with the specified filename and type.
/*! Save the screenshot to the file with the specified filename and type.
Note that any existing file with the same filename will be overwritten
without warning.
*/
status_t
Utility::Save(BBitmap** screenshot, const char* fileName, uint32 imageType)
Utility::Save(BBitmap* screenshot, const char* fileName, uint32 imageType)
const
{
BString fileNameString(fileName);
@@ -94,7 +96,7 @@ Utility::Save(BBitmap** screenshot, const char* fileName, uint32 imageType)
BEntry entry;
int32 index = 1;
BString extension = GetFileNameExtension(imageType);
BString extension = FileNameExtension(imageType);
do {
fileNameString.SetTo(homePath.Path());
fileNameString << "/" << B_TRANSLATE_NOCOLLECT(sDefaultFileNameBase)
@@ -109,18 +111,22 @@ Utility::Save(BBitmap** screenshot, const char* fileName, uint32 imageType)
return B_ERROR;
// Write the screenshot bitmap to the file
BBitmapStream stream(*screenshot);
BBitmapStream stream(screenshot);
BTranslatorRoster* roster = BTranslatorRoster::Default();
roster->Translate(&stream, NULL, NULL, &file, imageType,
status_t status = roster->Translate(&stream, NULL, NULL, &file, imageType,
B_TRANSLATOR_BITMAP);
*screenshot = NULL;
// Set the file MIME attribute
BBitmap* bitmap;
stream.DetachBitmap(&bitmap);
// The stream takes over ownership of the bitmap
if (status != B_OK)
return status;
// Set the file MIME attribute (don't mind too much if this fails)
BNodeInfo nodeInfo(&file);
if (nodeInfo.InitCheck() != B_OK)
return B_ERROR;
nodeInfo.SetType(_GetMimeString(imageType));
if (nodeInfo.InitCheck() == B_OK)
nodeInfo.SetType(_MimeType(imageType));
return B_OK;
}
@@ -160,20 +166,20 @@ Utility::MakeScreenshot(bool includeMouse, bool activeWindow,
BBitmap* screenshot = NULL;
if (activeWindow && activeWindowFrame.IsValid()) {
BRect frame(activeWindowFrame);
if (includeBorder) {
frame.InsetBy(-borderSize, -borderSize);
frame.top -= tabFrame.bottom - tabFrame.top;
}
screenshot = new BBitmap(frame.OffsetToCopy(B_ORIGIN), B_RGBA32, true);
screenshot = new BBitmap(frame.OffsetToCopy(B_ORIGIN),
includeBorder ? B_RGBA32 : B_RGB32, true);
if (screenshot->ImportBits(wholeScreen->Bits(),
wholeScreen->BitsLength(), wholeScreen->BytesPerRow(),
wholeScreen->ColorSpace(), frame.LeftTop(),
BPoint(0, 0), frame.IntegerWidth() + 1,
frame.IntegerHeight() + 1) != B_OK) {
wholeScreen->BitsLength(), wholeScreen->BytesPerRow(),
wholeScreen->ColorSpace(), frame.LeftTop(),
BPoint(0, 0), frame.IntegerWidth() + 1,
frame.IntegerHeight() + 1) != B_OK) {
delete screenshot;
return NULL;
}
@@ -188,35 +194,36 @@ Utility::MakeScreenshot(bool includeMouse, bool activeWindow,
BString
Utility::GetFileNameExtension(uint32 imageType) const
Utility::FileNameExtension(uint32 imageType) const
{
BMimeType mimeType(_GetMimeString(imageType));
BString extension("");
BMimeType mimeType(_MimeType(imageType));
BMessage message;
if (mimeType.GetFileExtensions(&message) == B_OK) {
const char* ext;
if (message.FindString("extensions", 0, &ext) == B_OK) {
extension.SetTo(ext);
BString extension;
if (message.FindString("extensions", 0, &extension) == B_OK) {
extension.Prepend(".");
} else
extension.SetTo("");
return extension;
}
}
return extension;
return "";
}
BString
Utility::_GetMimeString(uint32 imageType) const
status_t
Utility::FindTranslator(uint32 imageType, translator_id& id,
BString* _mimeType) const
{
const char *dummy = "";
translator_id* translators = NULL;
int32 numTranslators = 0;
BTranslatorRoster* roster = BTranslatorRoster::Default();
status_t status = roster->GetAllTranslators(&translators, &numTranslators);
if (status != B_OK)
return dummy;
return status;
ArrayDeleter<translator_id> deleter(translators);
for (int32 x = 0; x < numTranslators; x++) {
const translation_format* formats = NULL;
@@ -226,23 +233,46 @@ Utility::_GetMimeString(uint32 imageType) const
== B_OK) {
for (int32 i = 0; i < numFormats; ++i) {
if (formats[i].type == imageType) {
delete [] translators;
return formats[i].MIME;
id = translators[x];
if (_mimeType != NULL)
*_mimeType = formats[i].MIME;
return B_OK;
}
}
}
}
delete [] translators;
return dummy;
return B_ERROR;
}
BString
Utility::_MimeType(uint32 imageType) const
{
translator_id id;
BString type;
FindTranslator(imageType, id, &type);
return type;
}
/*! Makes the space around the tab transparent, and also makes sure that the
contents of the window aren't, as the screen does not have an alpha channel.
*/
void
Utility::_MakeTabSpaceTransparent(BBitmap* screenshot, BRect frame) const
{
if (!frame.IsValid() || screenshot->ColorSpace() != B_RGBA32)
return;
// Set the transparency to opaque on the complete bitmap
uint8* pixel = (uint8*)screenshot->Bits();
uint32 count = screenshot->BitsLength();
for (uint32 i = 0; i < count; i += 4) {
pixel[i + 3] = 255;
}
// Then make the space around the tab transparent
if (!frame.Contains(tabFrame))
return;
+7 -6
View File
@@ -1,4 +1,5 @@
/*
* Copyright 2010-2014, Haiku Inc. All rights reserved.
* Copyright 2010 Wim van der Meer <WPJvanderMeer@gmail.com>
* Distributed under the terms of the MIT License.
*/
@@ -9,9 +10,7 @@
#include <Point.h>
#include <Rect.h>
#include <String.h>
class BBitmap;
#include <TranslatorRoster.h>
// Command constant for sending utility data to the GUI app
@@ -24,11 +23,13 @@ public:
~Utility();
void CopyToClipboard(const BBitmap& screenshot) const;
status_t Save(BBitmap** screenshot, const char* fileName,
status_t Save(BBitmap* screenshot, const char* fileName,
uint32 imageType) const;
BBitmap* MakeScreenshot(bool includeCursor, bool activeWindow,
bool includeBorder) const;
BString GetFileNameExtension(uint32 imageType) const;
BString FileNameExtension(uint32 imageType) const;
status_t FindTranslator(uint32 imageType, translator_id& id,
BString* _mimeType = NULL) const;
BBitmap* wholeScreen;
BBitmap* cursorBitmap;
@@ -43,7 +44,7 @@ public:
private:
void _MakeTabSpaceTransparent(BBitmap* screenshot,
BRect frame) const;
BString _GetMimeString(uint32 imageType) const;
BString _MimeType(uint32 imageType) const;
};