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