19949213aSStephan Aßmus /* 29949213aSStephan Aßmus 39949213aSStephan Aßmus Copyright (c) 2002-2003, Marcin 'Shard' Konicki 49949213aSStephan Aßmus All rights reserved. 59949213aSStephan Aßmus 69949213aSStephan Aßmus Redistribution and use in source and binary forms, with or without 79949213aSStephan Aßmus modification, are permitted provided that the following conditions are met: 89949213aSStephan Aßmus 99949213aSStephan Aßmus * Redistributions of source code must retain the above copyright notice, 109949213aSStephan Aßmus this list of conditions and the following disclaimer. 119949213aSStephan Aßmus * Redistributions in binary form must reproduce the above copyright notice, 129949213aSStephan Aßmus this list of conditions and the following disclaimer in the documentation and/or 139949213aSStephan Aßmus other materials provided with the distribution. 149949213aSStephan Aßmus * Name "Marcin Konicki", "Shard" or any combination of them, 159949213aSStephan Aßmus must not be used to endorse or promote products derived from this 169949213aSStephan Aßmus software without specific prior written permission from Marcin Konicki. 179949213aSStephan Aßmus 189949213aSStephan Aßmus THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 199949213aSStephan Aßmus ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 209949213aSStephan Aßmus THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 219949213aSStephan Aßmus ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 229949213aSStephan Aßmus BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 239949213aSStephan Aßmus OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 249949213aSStephan Aßmus PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 259949213aSStephan Aßmus OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 269949213aSStephan Aßmus WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 279949213aSStephan Aßmus OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 289949213aSStephan Aßmus EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 299949213aSStephan Aßmus 309949213aSStephan Aßmus */ 319949213aSStephan Aßmus 329949213aSStephan Aßmus 339949213aSStephan Aßmus #include "JPEGTranslator.h" 349949213aSStephan Aßmus 359949213aSStephan Aßmus 369949213aSStephan Aßmus // Set these accordingly 379949213aSStephan Aßmus #define JPEG_ACRONYM "JPEG" 389949213aSStephan Aßmus #define JPEG_FORMAT 'JPEG' 399949213aSStephan Aßmus #define JPEG_MIME_STRING "image/jpeg" 409949213aSStephan Aßmus #define JPEG_DESCRIPTION "JPEG image" 419949213aSStephan Aßmus 429949213aSStephan Aßmus // The translation kit's native file type 439949213aSStephan Aßmus #define B_TRANSLATOR_BITMAP_MIME_STRING "image/x-be-bitmap" 449949213aSStephan Aßmus #define B_TRANSLATOR_BITMAP_DESCRIPTION "Be Bitmap image" 459949213aSStephan Aßmus 469949213aSStephan Aßmus // Translation Kit required globals 479949213aSStephan Aßmus char translatorName[] = "JPEG translator"; 48758b1d0eSIngo Weinhold char translatorInfo[] = "© 2002-2003, Shard\n" 49758b1d0eSIngo Weinhold "\n" 50758b1d0eSIngo Weinhold "Based on IJG library © 1991-1998, Thomas G. Lane\"\n" 51758b1d0eSIngo Weinhold " http://www.ijg.org/files/\n" 52758b1d0eSIngo Weinhold "with \"Lossless\" encoding support patch by Ken Murchison\n" 53758b1d0eSIngo Weinhold " http://www.oceana.com/ftp/ljpeg/\n" 54758b1d0eSIngo Weinhold "\n" 55758b1d0eSIngo Weinhold "With some colorspace conversion routines by Magnus Hellman\n" 56758b1d0eSIngo Weinhold " http://www.bebits.com/app/802\n" 57758b1d0eSIngo Weinhold ""; 58*d8e2fb50SAxel Dörfler 599949213aSStephan Aßmus int32 translatorVersion = 273; // 256 = v1.0.0 609949213aSStephan Aßmus 619949213aSStephan Aßmus // Define the formats we know how to read 629949213aSStephan Aßmus translation_format inputFormats[] = { 639949213aSStephan Aßmus { JPEG_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5, 649949213aSStephan Aßmus JPEG_MIME_STRING, JPEG_DESCRIPTION }, 659949213aSStephan Aßmus { B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5, 669949213aSStephan Aßmus B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION }, 67*d8e2fb50SAxel Dörfler {} 689949213aSStephan Aßmus }; 699949213aSStephan Aßmus 709949213aSStephan Aßmus // Define the formats we know how to write 719949213aSStephan Aßmus translation_format outputFormats[] = { 729949213aSStephan Aßmus { JPEG_FORMAT, B_TRANSLATOR_BITMAP, 0.5, 0.5, 739949213aSStephan Aßmus JPEG_MIME_STRING, JPEG_DESCRIPTION }, 749949213aSStephan Aßmus { B_TRANSLATOR_BITMAP, B_TRANSLATOR_BITMAP, 0.5, 0.5, 759949213aSStephan Aßmus B_TRANSLATOR_BITMAP_MIME_STRING, B_TRANSLATOR_BITMAP_DESCRIPTION }, 76*d8e2fb50SAxel Dörfler {} 779949213aSStephan Aßmus }; 789949213aSStephan Aßmus 79*d8e2fb50SAxel Dörfler 80*d8e2fb50SAxel Dörfler bool gAreSettingsRunning = false; 819949213aSStephan Aßmus 829949213aSStephan Aßmus 83*d8e2fb50SAxel Dörfler //! Make settings to defaults 84*d8e2fb50SAxel Dörfler void 85*d8e2fb50SAxel Dörfler LoadDefaultSettings(jpeg_settings *settings) 86*d8e2fb50SAxel Dörfler { 87*d8e2fb50SAxel Dörfler settings->Smoothing = 0; 88*d8e2fb50SAxel Dörfler settings->Quality = 95; 89*d8e2fb50SAxel Dörfler settings->Progressive = true; 90*d8e2fb50SAxel Dörfler settings->OptimizeColors = true; 91*d8e2fb50SAxel Dörfler settings->SmallerFile = false; 92*d8e2fb50SAxel Dörfler settings->B_GRAY1_as_B_RGB24 = false; 93*d8e2fb50SAxel Dörfler settings->Always_B_RGB32 = true; 94*d8e2fb50SAxel Dörfler settings->PhotoshopCMYK = true; 95*d8e2fb50SAxel Dörfler settings->ShowReadWarningBox = true; 96*d8e2fb50SAxel Dörfler } 979949213aSStephan Aßmus 98*d8e2fb50SAxel Dörfler 99*d8e2fb50SAxel Dörfler //! Save settings to config file 100*d8e2fb50SAxel Dörfler void 101*d8e2fb50SAxel Dörfler SaveSettings(jpeg_settings *settings) 102*d8e2fb50SAxel Dörfler { 103*d8e2fb50SAxel Dörfler // Make path to settings file 104*d8e2fb50SAxel Dörfler BPath path; 105*d8e2fb50SAxel Dörfler if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) { 106*d8e2fb50SAxel Dörfler path.SetTo(SETTINGS_PATH); 107*d8e2fb50SAxel Dörfler path.Append(SETTINGS_FILE); 108*d8e2fb50SAxel Dörfler } else 109*d8e2fb50SAxel Dörfler path.Append(SETTINGS_FILE); 110*d8e2fb50SAxel Dörfler 111*d8e2fb50SAxel Dörfler // Open settings file (create it if there's no file) and write settings 112*d8e2fb50SAxel Dörfler FILE *file = NULL; 113*d8e2fb50SAxel Dörfler if ((file = fopen( path.Path(), "wb+"))) { 114*d8e2fb50SAxel Dörfler fwrite(settings, sizeof(jpeg_settings), 1, file); 115*d8e2fb50SAxel Dörfler fclose(file); 116*d8e2fb50SAxel Dörfler } 117*d8e2fb50SAxel Dörfler } 118*d8e2fb50SAxel Dörfler 119*d8e2fb50SAxel Dörfler 120*d8e2fb50SAxel Dörfler //! Return true if settings were run, false if not 121*d8e2fb50SAxel Dörfler bool 122*d8e2fb50SAxel Dörfler SettingsChangedAlert() 123*d8e2fb50SAxel Dörfler { 124*d8e2fb50SAxel Dörfler // If settings view wasn't already initialized (settings not running) 125*d8e2fb50SAxel Dörfler // and user wants to run settings 126*d8e2fb50SAxel Dörfler if (!gAreSettingsRunning 127*d8e2fb50SAxel Dörfler && (new BAlert("Different settings file", 128*d8e2fb50SAxel Dörfler "JPEG settings were set to default because of incompatible settings file.", 129*d8e2fb50SAxel Dörfler "Configure settings", "OK", NULL, B_WIDTH_AS_USUAL, 130*d8e2fb50SAxel Dörfler B_WARNING_ALERT))->Go() == 0) { 131*d8e2fb50SAxel Dörfler // Create settings window (with no quit on close!), launch 132*d8e2fb50SAxel Dörfler // it and wait until it's closed 133*d8e2fb50SAxel Dörfler status_t err; 134*d8e2fb50SAxel Dörfler TranslatorWindow *window = new TranslatorWindow(false); 135*d8e2fb50SAxel Dörfler window->Show(); 136*d8e2fb50SAxel Dörfler wait_for_thread(window->Thread(), &err); 137*d8e2fb50SAxel Dörfler return true; 138*d8e2fb50SAxel Dörfler } 139*d8e2fb50SAxel Dörfler 140*d8e2fb50SAxel Dörfler return false; 141*d8e2fb50SAxel Dörfler } 142*d8e2fb50SAxel Dörfler 143*d8e2fb50SAxel Dörfler 144*d8e2fb50SAxel Dörfler /*! 145*d8e2fb50SAxel Dörfler Load settings from config file 146*d8e2fb50SAxel Dörfler If can't find it make them default and try to save 147*d8e2fb50SAxel Dörfler */ 148*d8e2fb50SAxel Dörfler void 149*d8e2fb50SAxel Dörfler LoadSettings(jpeg_settings *settings) 150*d8e2fb50SAxel Dörfler { 151*d8e2fb50SAxel Dörfler // Make path to settings file 152*d8e2fb50SAxel Dörfler BPath path; 153*d8e2fb50SAxel Dörfler if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) { 154*d8e2fb50SAxel Dörfler path.SetTo(SETTINGS_PATH); 155*d8e2fb50SAxel Dörfler path.Append(SETTINGS_FILE); 156*d8e2fb50SAxel Dörfler } else 157*d8e2fb50SAxel Dörfler path.Append(SETTINGS_FILE); 158*d8e2fb50SAxel Dörfler 159*d8e2fb50SAxel Dörfler // Open settings file (create it if there's no file) and write settings 160*d8e2fb50SAxel Dörfler FILE *file = NULL; 161*d8e2fb50SAxel Dörfler if ((file = fopen( path.Path(), "rb"))) { 162*d8e2fb50SAxel Dörfler if ( !fread(settings, sizeof(jpeg_settings), 1, file)) { 163*d8e2fb50SAxel Dörfler // settings struct has changed size 164*d8e2fb50SAxel Dörfler // Load default settings, and Save them 165*d8e2fb50SAxel Dörfler fclose(file); 166*d8e2fb50SAxel Dörfler LoadDefaultSettings(settings); 167*d8e2fb50SAxel Dörfler SaveSettings(settings); 168*d8e2fb50SAxel Dörfler // Tell user settings were changed to default, and ask to run settings panel or not 169*d8e2fb50SAxel Dörfler if (SettingsChangedAlert()) 170*d8e2fb50SAxel Dörfler // User configured settings, load them again 171*d8e2fb50SAxel Dörfler LoadSettings(settings); 172*d8e2fb50SAxel Dörfler } else 173*d8e2fb50SAxel Dörfler fclose(file); 174*d8e2fb50SAxel Dörfler } else if ((file = fopen( path.Path(), "wb+"))) { 175*d8e2fb50SAxel Dörfler LoadDefaultSettings(settings); 176*d8e2fb50SAxel Dörfler fwrite(settings, sizeof(jpeg_settings), 1, file); 177*d8e2fb50SAxel Dörfler fclose(file); 178*d8e2fb50SAxel Dörfler // Tell user settings were changed to default, and ask to run settings panel or not 179*d8e2fb50SAxel Dörfler if (SettingsChangedAlert()) 180*d8e2fb50SAxel Dörfler // User configured settings, load them again 181*d8e2fb50SAxel Dörfler LoadSettings(settings); 182*d8e2fb50SAxel Dörfler } 183*d8e2fb50SAxel Dörfler } 184*d8e2fb50SAxel Dörfler 185*d8e2fb50SAxel Dörfler 186*d8e2fb50SAxel Dörfler // #pragma mark - conversion routines 187*d8e2fb50SAxel Dörfler 188*d8e2fb50SAxel Dörfler 189*d8e2fb50SAxel Dörfler inline void 190*d8e2fb50SAxel Dörfler convert_from_gray1_to_gray8(uchar *in, uchar *out, int in_bytes) 191*d8e2fb50SAxel Dörfler { 192*d8e2fb50SAxel Dörfler int32 index = 0; 193*d8e2fb50SAxel Dörfler int32 index2 = 0; 194*d8e2fb50SAxel Dörfler while (index < in_bytes) { 195*d8e2fb50SAxel Dörfler unsigned char c = in[index++]; 196*d8e2fb50SAxel Dörfler for (int b = 128; b; b = b>>1) { 197*d8e2fb50SAxel Dörfler unsigned char color; 198*d8e2fb50SAxel Dörfler if (c & b) 199*d8e2fb50SAxel Dörfler color = 0; 200*d8e2fb50SAxel Dörfler else 201*d8e2fb50SAxel Dörfler color = 255; 202*d8e2fb50SAxel Dörfler out[index2++] = color; 203*d8e2fb50SAxel Dörfler } 204*d8e2fb50SAxel Dörfler } 205*d8e2fb50SAxel Dörfler } 206*d8e2fb50SAxel Dörfler 207*d8e2fb50SAxel Dörfler 208*d8e2fb50SAxel Dörfler inline void 209*d8e2fb50SAxel Dörfler convert_from_gray1_to_24(uchar *in, uchar *out, int in_bytes) 210*d8e2fb50SAxel Dörfler { 211*d8e2fb50SAxel Dörfler int32 index = 0; 212*d8e2fb50SAxel Dörfler int32 index2 = 0; 213*d8e2fb50SAxel Dörfler while (index < in_bytes) { 214*d8e2fb50SAxel Dörfler unsigned char c = in[index++]; 215*d8e2fb50SAxel Dörfler for (int b = 128; b; b = b>>1) { 216*d8e2fb50SAxel Dörfler unsigned char color; 217*d8e2fb50SAxel Dörfler if (c & b) 218*d8e2fb50SAxel Dörfler color = 0; 219*d8e2fb50SAxel Dörfler else 220*d8e2fb50SAxel Dörfler color = 255; 221*d8e2fb50SAxel Dörfler out[index2++] = color; 222*d8e2fb50SAxel Dörfler out[index2++] = color; 223*d8e2fb50SAxel Dörfler out[index2++] = color; 224*d8e2fb50SAxel Dörfler } 225*d8e2fb50SAxel Dörfler } 226*d8e2fb50SAxel Dörfler } 227*d8e2fb50SAxel Dörfler 228*d8e2fb50SAxel Dörfler 229*d8e2fb50SAxel Dörfler inline void 230*d8e2fb50SAxel Dörfler convert_from_cmap8_to_24(uchar *in, uchar *out, int in_bytes) 231*d8e2fb50SAxel Dörfler { 232*d8e2fb50SAxel Dörfler const color_map * map = system_colors(); 233*d8e2fb50SAxel Dörfler int32 index = 0; 234*d8e2fb50SAxel Dörfler int32 index2 = 0; 235*d8e2fb50SAxel Dörfler while (index < in_bytes) { 236*d8e2fb50SAxel Dörfler rgb_color color = map->color_list[in[index++]]; 237*d8e2fb50SAxel Dörfler 238*d8e2fb50SAxel Dörfler out[index2++] = color.red; 239*d8e2fb50SAxel Dörfler out[index2++] = color.green; 240*d8e2fb50SAxel Dörfler out[index2++] = color.blue; 241*d8e2fb50SAxel Dörfler } 242*d8e2fb50SAxel Dörfler } 243*d8e2fb50SAxel Dörfler 244*d8e2fb50SAxel Dörfler 245*d8e2fb50SAxel Dörfler inline void 246*d8e2fb50SAxel Dörfler convert_from_15_to_24(uchar *in, uchar *out, int in_bytes) 247*d8e2fb50SAxel Dörfler { 248*d8e2fb50SAxel Dörfler int32 index = 0; 249*d8e2fb50SAxel Dörfler int32 index2 = 0; 250*d8e2fb50SAxel Dörfler int16 in_pixel; 251*d8e2fb50SAxel Dörfler while (index < in_bytes) { 252*d8e2fb50SAxel Dörfler in_pixel = in[index] | (in[index+1] << 8); 253*d8e2fb50SAxel Dörfler index += 2; 254*d8e2fb50SAxel Dörfler 255*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12); 256*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7); 257*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2); 258*d8e2fb50SAxel Dörfler } 259*d8e2fb50SAxel Dörfler } 260*d8e2fb50SAxel Dörfler 261*d8e2fb50SAxel Dörfler 262*d8e2fb50SAxel Dörfler inline void 263*d8e2fb50SAxel Dörfler convert_from_15b_to_24(uchar *in, uchar *out, int in_bytes) 264*d8e2fb50SAxel Dörfler { 265*d8e2fb50SAxel Dörfler int32 index = 0; 266*d8e2fb50SAxel Dörfler int32 index2 = 0; 267*d8e2fb50SAxel Dörfler int16 in_pixel; 268*d8e2fb50SAxel Dörfler while (index < in_bytes) { 269*d8e2fb50SAxel Dörfler in_pixel = in[index+1] | (in[index] << 8); 270*d8e2fb50SAxel Dörfler index += 2; 271*d8e2fb50SAxel Dörfler 272*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x7c00)) >> 7) | (((in_pixel & 0x7c00)) >> 12); 273*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x3e0)) >> 2) | (((in_pixel & 0x3e0)) >> 7); 274*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2); 275*d8e2fb50SAxel Dörfler } 276*d8e2fb50SAxel Dörfler } 277*d8e2fb50SAxel Dörfler 278*d8e2fb50SAxel Dörfler 279*d8e2fb50SAxel Dörfler inline void 280*d8e2fb50SAxel Dörfler convert_from_16_to_24(uchar *in, uchar *out, int in_bytes) 281*d8e2fb50SAxel Dörfler { 282*d8e2fb50SAxel Dörfler int32 index = 0; 283*d8e2fb50SAxel Dörfler int32 index2 = 0; 284*d8e2fb50SAxel Dörfler int16 in_pixel; 285*d8e2fb50SAxel Dörfler while (index < in_bytes) { 286*d8e2fb50SAxel Dörfler in_pixel = in[index] | (in[index+1] << 8); 287*d8e2fb50SAxel Dörfler index += 2; 288*d8e2fb50SAxel Dörfler 289*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0xf800)) >> 13); 290*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9); 291*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2); 292*d8e2fb50SAxel Dörfler } 293*d8e2fb50SAxel Dörfler } 294*d8e2fb50SAxel Dörfler 295*d8e2fb50SAxel Dörfler 296*d8e2fb50SAxel Dörfler inline void 297*d8e2fb50SAxel Dörfler convert_from_16b_to_24(uchar *in, uchar *out, int in_bytes) 298*d8e2fb50SAxel Dörfler { 299*d8e2fb50SAxel Dörfler int32 index = 0; 300*d8e2fb50SAxel Dörfler int32 index2 = 0; 301*d8e2fb50SAxel Dörfler int16 in_pixel; 302*d8e2fb50SAxel Dörfler while (index < in_bytes) { 303*d8e2fb50SAxel Dörfler in_pixel = in[index+1] | (in[index] << 8); 304*d8e2fb50SAxel Dörfler index += 2; 305*d8e2fb50SAxel Dörfler 306*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0xf800)) >> 8) | (((in_pixel & 0xf800)) >> 13); 307*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x7e0)) >> 3) | (((in_pixel & 0x7e0)) >> 9); 308*d8e2fb50SAxel Dörfler out[index2++] = (((in_pixel & 0x1f)) << 3) | (((in_pixel & 0x1f)) >> 2); 309*d8e2fb50SAxel Dörfler } 310*d8e2fb50SAxel Dörfler } 311*d8e2fb50SAxel Dörfler 312*d8e2fb50SAxel Dörfler 313*d8e2fb50SAxel Dörfler inline void 314*d8e2fb50SAxel Dörfler convert_from_24_to_24(uchar *in, uchar *out, int in_bytes) 315*d8e2fb50SAxel Dörfler { 316*d8e2fb50SAxel Dörfler int32 index = 0; 317*d8e2fb50SAxel Dörfler int32 index2 = 0; 318*d8e2fb50SAxel Dörfler while (index < in_bytes) { 319*d8e2fb50SAxel Dörfler out[index2++] = in[index+2]; 320*d8e2fb50SAxel Dörfler out[index2++] = in[index+1]; 321*d8e2fb50SAxel Dörfler out[index2++] = in[index]; 322*d8e2fb50SAxel Dörfler index+=3; 323*d8e2fb50SAxel Dörfler } 324*d8e2fb50SAxel Dörfler } 325*d8e2fb50SAxel Dörfler 326*d8e2fb50SAxel Dörfler 327*d8e2fb50SAxel Dörfler inline void 328*d8e2fb50SAxel Dörfler convert_from_32_to_24(uchar *in, uchar *out, int in_bytes) 329*d8e2fb50SAxel Dörfler { 330*d8e2fb50SAxel Dörfler int32 index = 0; 331*d8e2fb50SAxel Dörfler int32 index2 = 0; 332*d8e2fb50SAxel Dörfler while (index < in_bytes) { 333*d8e2fb50SAxel Dörfler out[index2++] = in[index+2]; 334*d8e2fb50SAxel Dörfler out[index2++] = in[index+1]; 335*d8e2fb50SAxel Dörfler out[index2++] = in[index]; 336*d8e2fb50SAxel Dörfler index+=4; 337*d8e2fb50SAxel Dörfler } 338*d8e2fb50SAxel Dörfler } 339*d8e2fb50SAxel Dörfler 340*d8e2fb50SAxel Dörfler 341*d8e2fb50SAxel Dörfler inline void 342*d8e2fb50SAxel Dörfler convert_from_32b_to_24(uchar *in, uchar *out, int in_bytes) 343*d8e2fb50SAxel Dörfler { 344*d8e2fb50SAxel Dörfler int32 index = 0; 345*d8e2fb50SAxel Dörfler int32 index2 = 0; 346*d8e2fb50SAxel Dörfler while (index < in_bytes) { 347*d8e2fb50SAxel Dörfler index++; 348*d8e2fb50SAxel Dörfler out[index2++] = in[index++]; 349*d8e2fb50SAxel Dörfler out[index2++] = in[index++]; 350*d8e2fb50SAxel Dörfler out[index2++] = in[index++]; 351*d8e2fb50SAxel Dörfler } 352*d8e2fb50SAxel Dörfler } 353*d8e2fb50SAxel Dörfler 354*d8e2fb50SAxel Dörfler 355*d8e2fb50SAxel Dörfler inline void 356*d8e2fb50SAxel Dörfler convert_from_CMYK_to_32_photoshop(uchar *in, uchar *out, int out_bytes) 357*d8e2fb50SAxel Dörfler { 358*d8e2fb50SAxel Dörfler int32 index = 0; 359*d8e2fb50SAxel Dörfler int32 index2 = 0; 360*d8e2fb50SAxel Dörfler int32 black = 0; 361*d8e2fb50SAxel Dörfler while (index < out_bytes) { 362*d8e2fb50SAxel Dörfler black = in[index2+3]; 363*d8e2fb50SAxel Dörfler out[index++] = in[index2+2]*black/255; 364*d8e2fb50SAxel Dörfler out[index++] = in[index2+1]*black/255; 365*d8e2fb50SAxel Dörfler out[index++] = in[index2]*black/255; 366*d8e2fb50SAxel Dörfler out[index++] = 255; 367*d8e2fb50SAxel Dörfler index2 += 4; 368*d8e2fb50SAxel Dörfler } 369*d8e2fb50SAxel Dörfler } 370*d8e2fb50SAxel Dörfler 371*d8e2fb50SAxel Dörfler 372*d8e2fb50SAxel Dörfler //! !!! UNTESTED !!! 373*d8e2fb50SAxel Dörfler inline void 374*d8e2fb50SAxel Dörfler convert_from_CMYK_to_32(uchar *in, uchar *out, int out_bytes) 375*d8e2fb50SAxel Dörfler { 376*d8e2fb50SAxel Dörfler int32 index = 0; 377*d8e2fb50SAxel Dörfler int32 index2 = 0; 378*d8e2fb50SAxel Dörfler int32 black = 0; 379*d8e2fb50SAxel Dörfler while (index < out_bytes) { 380*d8e2fb50SAxel Dörfler black = 255 - in[index2+3]; 381*d8e2fb50SAxel Dörfler out[index++] = ((255-in[index2+2])*black)/255; 382*d8e2fb50SAxel Dörfler out[index++] = ((255-in[index2+1])*black)/255; 383*d8e2fb50SAxel Dörfler out[index++] = ((255-in[index2])*black)/255; 384*d8e2fb50SAxel Dörfler out[index++] = 255; 385*d8e2fb50SAxel Dörfler index2 += 4; 386*d8e2fb50SAxel Dörfler } 387*d8e2fb50SAxel Dörfler } 388*d8e2fb50SAxel Dörfler 389*d8e2fb50SAxel Dörfler 390*d8e2fb50SAxel Dörfler //! RGB24 8:8:8 to xRGB 8:8:8:8 391*d8e2fb50SAxel Dörfler inline void 392*d8e2fb50SAxel Dörfler convert_from_24_to_32(uchar *in, uchar *out, int out_bytes) 393*d8e2fb50SAxel Dörfler { 394*d8e2fb50SAxel Dörfler int32 index = 0; 395*d8e2fb50SAxel Dörfler int32 index2 = 0; 396*d8e2fb50SAxel Dörfler while (index < out_bytes) { 397*d8e2fb50SAxel Dörfler out[index++] = in[index2+2]; 398*d8e2fb50SAxel Dörfler out[index++] = in[index2+1]; 399*d8e2fb50SAxel Dörfler out[index++] = in[index2]; 400*d8e2fb50SAxel Dörfler out[index++] = 255; 401*d8e2fb50SAxel Dörfler index2 += 3; 402*d8e2fb50SAxel Dörfler } 403*d8e2fb50SAxel Dörfler } 404*d8e2fb50SAxel Dörfler 405*d8e2fb50SAxel Dörfler 406*d8e2fb50SAxel Dörfler // #pragma mark - 407*d8e2fb50SAxel Dörfler 408*d8e2fb50SAxel Dörfler 409*d8e2fb50SAxel Dörfler SSlider::SSlider(BRect frame, const char *name, const char *label, 410*d8e2fb50SAxel Dörfler BMessage *message, int32 minValue, int32 maxValue, orientation posture, 411*d8e2fb50SAxel Dörfler thumb_style thumbType, uint32 resizingMode, uint32 flags) 412*d8e2fb50SAxel Dörfler : BSlider(frame, name, label, message, minValue, maxValue, 413*d8e2fb50SAxel Dörfler posture, thumbType, resizingMode, flags) 4149949213aSStephan Aßmus { 4159949213aSStephan Aßmus rgb_color bar_color = { 0, 0, 229, 255 }; 4169949213aSStephan Aßmus UseFillColor(true, &bar_color); 4179949213aSStephan Aßmus } 4189949213aSStephan Aßmus 4199949213aSStephan Aßmus //--------------------------------------------------- 4209949213aSStephan Aßmus // Update status string - show actual value 4219949213aSStephan Aßmus //--------------------------------------------------- 4229949213aSStephan Aßmus char* 4239949213aSStephan Aßmus SSlider::UpdateText() const 4249949213aSStephan Aßmus { 4259949213aSStephan Aßmus sprintf( (char*)statusLabel, "%ld", Value()); 4269949213aSStephan Aßmus return (char*)statusLabel; 4279949213aSStephan Aßmus } 4289949213aSStephan Aßmus 4299949213aSStephan Aßmus //--------------------------------------------------- 4309949213aSStephan Aßmus // BSlider::ResizeToPreferred + Resize width if it's too small to show label and status 4319949213aSStephan Aßmus //--------------------------------------------------- 4329949213aSStephan Aßmus void 4339949213aSStephan Aßmus SSlider::ResizeToPreferred() 4349949213aSStephan Aßmus { 4359949213aSStephan Aßmus int32 width = (int32)ceil(StringWidth( Label()) + StringWidth("9999")); 4369949213aSStephan Aßmus if (width < 230) width = 230; 4379949213aSStephan Aßmus float w, h; 4389949213aSStephan Aßmus GetPreferredSize(&w, &h); 4399949213aSStephan Aßmus ResizeTo(width, h); 4409949213aSStephan Aßmus } 4419949213aSStephan Aßmus 4429949213aSStephan Aßmus 443*d8e2fb50SAxel Dörfler // #pragma mark - 4449949213aSStephan Aßmus 445*d8e2fb50SAxel Dörfler 446*d8e2fb50SAxel Dörfler TranslatorReadView::TranslatorReadView(const char *name, jpeg_settings *settings, 447*d8e2fb50SAxel Dörfler float x, float y) 4489949213aSStephan Aßmus : SView(name, x, y), 449*d8e2fb50SAxel Dörfler fSettings(settings) 4509949213aSStephan Aßmus { 451*d8e2fb50SAxel Dörfler alwaysrgb32 = new BCheckBox( BRect(10, GetPreferredHeight(), 10, 452*d8e2fb50SAxel Dörfler GetPreferredHeight()), "alwaysrgb32", VIEW_LABEL_ALWAYSRGB32, 453*d8e2fb50SAxel Dörfler new BMessage(VIEW_MSG_SET_ALWAYSRGB32)); 4549949213aSStephan Aßmus alwaysrgb32->SetFont(be_plain_font); 455*d8e2fb50SAxel Dörfler if (fSettings->Always_B_RGB32) 4569949213aSStephan Aßmus alwaysrgb32->SetValue(1); 4579949213aSStephan Aßmus 4589949213aSStephan Aßmus AddChild(alwaysrgb32); 4599949213aSStephan Aßmus 4609949213aSStephan Aßmus photoshopCMYK = new BCheckBox( BRect(10, GetPreferredHeight(), 10, GetPreferredHeight()), "photoshopCMYK", VIEW_LABEL_PHOTOSHOPCMYK, new BMessage(VIEW_MSG_SET_PHOTOSHOPCMYK)); 4619949213aSStephan Aßmus photoshopCMYK->SetFont(be_plain_font); 462*d8e2fb50SAxel Dörfler if (fSettings->PhotoshopCMYK) 4639949213aSStephan Aßmus photoshopCMYK->SetValue(1); 4649949213aSStephan Aßmus 4659949213aSStephan Aßmus AddChild(photoshopCMYK); 4669949213aSStephan Aßmus 4679949213aSStephan Aßmus showerrorbox = new BCheckBox( BRect(10, GetPreferredHeight(), 10, GetPreferredHeight()), "progress", VIEW_LABEL_SHOWREADERRORBOX, new BMessage(VIEW_MSG_SET_SHOWREADERRORBOX)); 4689949213aSStephan Aßmus showerrorbox->SetFont(be_plain_font); 469*d8e2fb50SAxel Dörfler if (fSettings->ShowReadWarningBox) 4709949213aSStephan Aßmus showerrorbox->SetValue(1); 4719949213aSStephan Aßmus 4729949213aSStephan Aßmus AddChild(showerrorbox); 4739949213aSStephan Aßmus 4749949213aSStephan Aßmus ResizeToPreferred(); 4759949213aSStephan Aßmus } 4769949213aSStephan Aßmus 4779949213aSStephan Aßmus //--------------------------------------------------- 4789949213aSStephan Aßmus // Attached to window - set children target 4799949213aSStephan Aßmus //--------------------------------------------------- 4809949213aSStephan Aßmus void 4819949213aSStephan Aßmus TranslatorReadView::AttachedToWindow() 4829949213aSStephan Aßmus { 4839949213aSStephan Aßmus alwaysrgb32->SetTarget(this); 4849949213aSStephan Aßmus photoshopCMYK->SetTarget(this); 4859949213aSStephan Aßmus showerrorbox->SetTarget(this); 4869949213aSStephan Aßmus } 4879949213aSStephan Aßmus 4889949213aSStephan Aßmus //--------------------------------------------------- 4899949213aSStephan Aßmus // MessageReceived - receive GUI changes, save settings 4909949213aSStephan Aßmus //--------------------------------------------------- 4919949213aSStephan Aßmus void 4929949213aSStephan Aßmus TranslatorReadView::MessageReceived(BMessage *message) 4939949213aSStephan Aßmus { 4949949213aSStephan Aßmus switch (message->what) 4959949213aSStephan Aßmus { 4969949213aSStephan Aßmus case VIEW_MSG_SET_ALWAYSRGB32: 4979949213aSStephan Aßmus { 4989949213aSStephan Aßmus int32 value; 4999949213aSStephan Aßmus if (message->FindInt32("be:value", &value) == B_OK) { 500*d8e2fb50SAxel Dörfler fSettings->Always_B_RGB32 = value; 501*d8e2fb50SAxel Dörfler SaveSettings(fSettings); 5029949213aSStephan Aßmus } 5039949213aSStephan Aßmus break; 5049949213aSStephan Aßmus } 5059949213aSStephan Aßmus case VIEW_MSG_SET_PHOTOSHOPCMYK: 5069949213aSStephan Aßmus { 5079949213aSStephan Aßmus int32 value; 5089949213aSStephan Aßmus if (message->FindInt32("be:value", &value) == B_OK) { 509*d8e2fb50SAxel Dörfler fSettings->PhotoshopCMYK = value; 510*d8e2fb50SAxel Dörfler SaveSettings(fSettings); 5119949213aSStephan Aßmus } 5129949213aSStephan Aßmus break; 5139949213aSStephan Aßmus } 5149949213aSStephan Aßmus case VIEW_MSG_SET_SHOWREADERRORBOX: 5159949213aSStephan Aßmus { 5169949213aSStephan Aßmus int32 value; 5179949213aSStephan Aßmus if (message->FindInt32("be:value", &value) == B_OK) { 518*d8e2fb50SAxel Dörfler fSettings->ShowReadWarningBox = value; 519*d8e2fb50SAxel Dörfler SaveSettings(fSettings); 5209949213aSStephan Aßmus } 5219949213aSStephan Aßmus break; 5229949213aSStephan Aßmus } 5239949213aSStephan Aßmus default: 5249949213aSStephan Aßmus BView::MessageReceived(message); 5259949213aSStephan Aßmus break; 5269949213aSStephan Aßmus } 5279949213aSStephan Aßmus } 5289949213aSStephan Aßmus 5299949213aSStephan Aßmus 5309949213aSStephan Aßmus //---------------------------------------------------------------------------- 5319949213aSStephan Aßmus // 5329949213aSStephan Aßmus // Functions :: TranslatorWriteView 5339949213aSStephan Aßmus // 5349949213aSStephan Aßmus //---------------------------------------------------------------------------- 5359949213aSStephan Aßmus 5369949213aSStephan Aßmus //--------------------------------------------------- 5379949213aSStephan Aßmus // Constructor 5389949213aSStephan Aßmus //--------------------------------------------------- 539*d8e2fb50SAxel Dörfler TranslatorWriteView::TranslatorWriteView(const char *name, jpeg_settings *settings, float x, float y) 5409949213aSStephan Aßmus : SView(name, x, y), 541*d8e2fb50SAxel Dörfler fSettings(settings) 5429949213aSStephan Aßmus { 5439949213aSStephan Aßmus quality = new SSlider( BRect(10, GetPreferredHeight(), 10, GetPreferredHeight()), "quality", VIEW_LABEL_QUALITY, new BMessage(VIEW_MSG_SET_QUALITY), 0, 100); 5449949213aSStephan Aßmus quality->SetHashMarks(B_HASH_MARKS_BOTTOM); 5459949213aSStephan Aßmus quality->SetHashMarkCount(10); 5469949213aSStephan Aßmus quality->SetLimitLabels("Low", "High"); 5479949213aSStephan Aßmus quality->SetFont(be_plain_font); 548*d8e2fb50SAxel Dörfler quality->SetValue(fSettings->Quality); 5499949213aSStephan Aßmus 5509949213aSStephan Aßmus AddChild(quality); 5519949213aSStephan Aßmus 5529949213aSStephan Aßmus smoothing = new SSlider( BRect(10, GetPreferredHeight()+10, 10, GetPreferredHeight()), "smoothing", VIEW_LABEL_SMOOTHING, new BMessage(VIEW_MSG_SET_SMOOTHING), 0, 100); 5539949213aSStephan Aßmus smoothing->SetHashMarks(B_HASH_MARKS_BOTTOM); 5549949213aSStephan Aßmus smoothing->SetHashMarkCount(10); 5559949213aSStephan Aßmus smoothing->SetLimitLabels("None", "High"); 5569949213aSStephan Aßmus smoothing->SetFont(be_plain_font); 557*d8e2fb50SAxel Dörfler smoothing->SetValue(fSettings->Smoothing); 5589949213aSStephan Aßmus 5599949213aSStephan Aßmus AddChild(smoothing); 5609949213aSStephan Aßmus 5619949213aSStephan Aßmus progress = new BCheckBox( BRect(10, GetPreferredHeight()+10, 10, GetPreferredHeight()), "progress", VIEW_LABEL_PROGRESSIVE, new BMessage(VIEW_MSG_SET_PROGRESSIVE)); 5629949213aSStephan Aßmus progress->SetFont(be_plain_font); 563*d8e2fb50SAxel Dörfler if (fSettings->Progressive) 5649949213aSStephan Aßmus progress->SetValue(1); 5659949213aSStephan Aßmus 5669949213aSStephan Aßmus AddChild(progress); 5679949213aSStephan Aßmus 5689949213aSStephan Aßmus optimizecolors = new BCheckBox( BRect(10, GetPreferredHeight()+5, 10, GetPreferredHeight()+5), "optimizecolors", VIEW_LABEL_OPTIMIZECOLORS, new BMessage(VIEW_MSG_SET_OPTIMIZECOLORS)); 5699949213aSStephan Aßmus optimizecolors->SetFont(be_plain_font); 570*d8e2fb50SAxel Dörfler if (fSettings->OptimizeColors) 5719949213aSStephan Aßmus optimizecolors->SetValue(1); 5729949213aSStephan Aßmus 5739949213aSStephan Aßmus AddChild(optimizecolors); 5749949213aSStephan Aßmus 5759949213aSStephan Aßmus smallerfile = new BCheckBox( BRect(25, GetPreferredHeight()+5, 25, GetPreferredHeight()+5), "smallerfile", VIEW_LABEL_SMALLERFILE, new BMessage(VIEW_MSG_SET_SMALLERFILE)); 5769949213aSStephan Aßmus smallerfile->SetFont(be_plain_font); 577*d8e2fb50SAxel Dörfler if (fSettings->SmallerFile) 5789949213aSStephan Aßmus smallerfile->SetValue(1); 579*d8e2fb50SAxel Dörfler if (!fSettings->OptimizeColors) 5809949213aSStephan Aßmus smallerfile->SetEnabled(false); 5819949213aSStephan Aßmus 5829949213aSStephan Aßmus AddChild(smallerfile); 5839949213aSStephan Aßmus 5849949213aSStephan Aßmus gray1asrgb24 = new BCheckBox( BRect(10, GetPreferredHeight()+5, 25, GetPreferredHeight()+5), "gray1asrgb24", VIEW_LABEL_GRAY1ASRGB24, new BMessage(VIEW_MSG_SET_GRAY1ASRGB24)); 5859949213aSStephan Aßmus gray1asrgb24->SetFont(be_plain_font); 586*d8e2fb50SAxel Dörfler if (fSettings->B_GRAY1_as_B_RGB24) 5879949213aSStephan Aßmus gray1asrgb24->SetValue(1); 5889949213aSStephan Aßmus 5899949213aSStephan Aßmus AddChild(gray1asrgb24); 5909949213aSStephan Aßmus 5919949213aSStephan Aßmus ResizeToPreferred(); 5929949213aSStephan Aßmus } 5939949213aSStephan Aßmus 5949949213aSStephan Aßmus //--------------------------------------------------- 5959949213aSStephan Aßmus // Attached to window - set children target 5969949213aSStephan Aßmus //--------------------------------------------------- 5979949213aSStephan Aßmus void 5989949213aSStephan Aßmus TranslatorWriteView::AttachedToWindow() 5999949213aSStephan Aßmus { 6009949213aSStephan Aßmus quality->SetTarget(this); 6019949213aSStephan Aßmus smoothing->SetTarget(this); 6029949213aSStephan Aßmus progress->SetTarget(this); 6039949213aSStephan Aßmus optimizecolors->SetTarget(this); 6049949213aSStephan Aßmus smallerfile->SetTarget(this); 6059949213aSStephan Aßmus gray1asrgb24->SetTarget(this); 6069949213aSStephan Aßmus } 6079949213aSStephan Aßmus 6089949213aSStephan Aßmus //--------------------------------------------------- 6099949213aSStephan Aßmus // MessageReceived - receive GUI changes, save settings 6109949213aSStephan Aßmus //--------------------------------------------------- 6119949213aSStephan Aßmus void 6129949213aSStephan Aßmus TranslatorWriteView::MessageReceived(BMessage *message) 6139949213aSStephan Aßmus { 6149949213aSStephan Aßmus switch (message->what) 6159949213aSStephan Aßmus { 6169949213aSStephan Aßmus case VIEW_MSG_SET_QUALITY: 6179949213aSStephan Aßmus { 6189949213aSStephan Aßmus int32 value; 6199949213aSStephan Aßmus if (message->FindInt32("be:value", &value) == B_OK) { 620*d8e2fb50SAxel Dörfler fSettings->Quality = value; 621*d8e2fb50SAxel Dörfler SaveSettings(fSettings); 6229949213aSStephan Aßmus } 6239949213aSStephan Aßmus break; 6249949213aSStephan Aßmus } 6259949213aSStephan Aßmus case VIEW_MSG_SET_SMOOTHING: 6269949213aSStephan Aßmus { 6279949213aSStephan Aßmus int32 value; 6289949213aSStephan Aßmus if (message->FindInt32("be:value", &value) == B_OK) { 629*d8e2fb50SAxel Dörfler fSettings->Smoothing = value; 630*d8e2fb50SAxel Dörfler SaveSettings(fSettings); 6319949213aSStephan Aßmus } 6329949213aSStephan Aßmus break; 6339949213aSStephan Aßmus } 6349949213aSStephan Aßmus case VIEW_MSG_SET_PROGRESSIVE: 6359949213aSStephan Aßmus { 6369949213aSStephan Aßmus int32 value; 6379949213aSStephan Aßmus if (message->FindInt32("be:value", &value) == B_OK) { 638*d8e2fb50SAxel Dörfler fSettings->Progressive = value; 639*d8e2fb50SAxel Dörfler SaveSettings(fSettings); 6409949213aSStephan Aßmus } 6419949213aSStephan Aßmus break; 6429949213aSStephan Aßmus } 6439949213aSStephan Aßmus case VIEW_MSG_SET_OPTIMIZECOLORS: 6449949213aSStephan Aßmus { 6459949213aSStephan Aßmus int32 value; 6469949213aSStephan Aßmus if (message->FindInt32("be:value", &value) == B_OK) { 647*d8e2fb50SAxel Dörfler fSettings->OptimizeColors = value; 648*d8e2fb50SAxel Dörfler SaveSettings(fSettings); 6499949213aSStephan Aßmus } 650*d8e2fb50SAxel Dörfler smallerfile->SetEnabled(fSettings->OptimizeColors); 6519949213aSStephan Aßmus break; 6529949213aSStephan Aßmus } 6539949213aSStephan Aßmus case VIEW_MSG_SET_SMALLERFILE: 6549949213aSStephan Aßmus { 6559949213aSStephan Aßmus int32 value; 6569949213aSStephan Aßmus if (message->FindInt32("be:value", &value) == B_OK) { 657*d8e2fb50SAxel Dörfler fSettings->SmallerFile = value; 658*d8e2fb50SAxel Dörfler SaveSettings(fSettings); 6599949213aSStephan Aßmus } 6609949213aSStephan Aßmus break; 6619949213aSStephan Aßmus } 6629949213aSStephan Aßmus case VIEW_MSG_SET_GRAY1ASRGB24: 6639949213aSStephan Aßmus { 6649949213aSStephan Aßmus int32 value; 6659949213aSStephan Aßmus if (message->FindInt32("be:value", &value) == B_OK) { 666*d8e2fb50SAxel Dörfler fSettings->B_GRAY1_as_B_RGB24 = value; 667*d8e2fb50SAxel Dörfler SaveSettings(fSettings); 6689949213aSStephan Aßmus } 6699949213aSStephan Aßmus break; 6709949213aSStephan Aßmus } 6719949213aSStephan Aßmus default: 6729949213aSStephan Aßmus BView::MessageReceived(message); 6739949213aSStephan Aßmus break; 6749949213aSStephan Aßmus } 6759949213aSStephan Aßmus } 6769949213aSStephan Aßmus 6779949213aSStephan Aßmus 678*d8e2fb50SAxel Dörfler // #pragma mark - 6799949213aSStephan Aßmus 680*d8e2fb50SAxel Dörfler 6819949213aSStephan Aßmus TranslatorAboutView::TranslatorAboutView(const char *name, float x, float y) 6829949213aSStephan Aßmus : SView(name, x, y) 6839949213aSStephan Aßmus { 6849949213aSStephan Aßmus BStringView *title = new BStringView( BRect(10, 0, 10, 0), "Title", translatorName); 6859949213aSStephan Aßmus title->SetFont(be_bold_font); 6869949213aSStephan Aßmus 6879949213aSStephan Aßmus AddChild(title); 6889949213aSStephan Aßmus 6899949213aSStephan Aßmus BRect rect = title->Bounds(); 6909949213aSStephan Aßmus float space = title->StringWidth(" "); 6919949213aSStephan Aßmus 6929949213aSStephan Aßmus char versionString[16]; 693*d8e2fb50SAxel Dörfler sprintf(versionString, "v%d.%d.%d", (int)(translatorVersion >> 8), 694*d8e2fb50SAxel Dörfler (int)((translatorVersion >> 4) & 0xf), (int)(translatorVersion & 0xf)); 6959949213aSStephan Aßmus 696*d8e2fb50SAxel Dörfler BStringView *version = new BStringView(BRect(rect.right+space, rect.top, 697*d8e2fb50SAxel Dörfler rect.right+space, rect.top), "Version", versionString); 6989949213aSStephan Aßmus version->SetFont(be_plain_font); 6999949213aSStephan Aßmus version->SetFontSize( 9); 7009949213aSStephan Aßmus // Make version be in the same line as title 7019949213aSStephan Aßmus version->ResizeToPreferred(); 7029949213aSStephan Aßmus version->MoveBy(0, rect.bottom-version->Frame().bottom); 7039949213aSStephan Aßmus 7049949213aSStephan Aßmus AddChild(version); 7059949213aSStephan Aßmus 7069949213aSStephan Aßmus // Now for each line in translatorInfo add BStringView 7079949213aSStephan Aßmus BStringView *copyright; 7089949213aSStephan Aßmus const char *current = translatorInfo; 7099949213aSStephan Aßmus char *temp = translatorInfo; 7109949213aSStephan Aßmus while (*current != 0) { 7119949213aSStephan Aßmus // Find next line char 7129949213aSStephan Aßmus temp = strchr(current, 0x0a); 7139949213aSStephan Aßmus // If found replace it with 0 so current will look like ending here 7149949213aSStephan Aßmus if (temp) 7159949213aSStephan Aßmus *temp = 0; 7169949213aSStephan Aßmus // Add BStringView showing what's under current 717*d8e2fb50SAxel Dörfler copyright = new BStringView(BRect(10, GetPreferredHeight(), 718*d8e2fb50SAxel Dörfler 10, GetPreferredHeight()), "Copyright", current); 7199949213aSStephan Aßmus copyright->SetFont(be_plain_font); 7209949213aSStephan Aßmus copyright->SetFontSize( 9); 7219949213aSStephan Aßmus AddChild(copyright); 7229949213aSStephan Aßmus 7239949213aSStephan Aßmus // If there was next line, move current there and put next line char back 7249949213aSStephan Aßmus if (temp) { 7259949213aSStephan Aßmus current = temp+1; 7269949213aSStephan Aßmus *temp = 0x0a; 7279949213aSStephan Aßmus } else 7289949213aSStephan Aßmus // If there was no next line char break loop 7299949213aSStephan Aßmus break; 7309949213aSStephan Aßmus } 7319949213aSStephan Aßmus 7329949213aSStephan Aßmus ResizeToPreferred(); 7339949213aSStephan Aßmus } 7349949213aSStephan Aßmus 7359949213aSStephan Aßmus 736*d8e2fb50SAxel Dörfler // #pragma mark - 7379949213aSStephan Aßmus 738*d8e2fb50SAxel Dörfler 7399949213aSStephan Aßmus TranslatorView::TranslatorView(const char *name) 740*d8e2fb50SAxel Dörfler : SView(name), 741*d8e2fb50SAxel Dörfler fTabWidth(30), 742*d8e2fb50SAxel Dörfler fTabHeight(7 + (int32)be_plain_font->Size()), 743*d8e2fb50SAxel Dörfler // TODO: this apparently uses BFont::Size() as height in pixels!!! 744*d8e2fb50SAxel Dörfler fActiveChild(0) 7459949213aSStephan Aßmus { 7469949213aSStephan Aßmus // Set global var to true 747*d8e2fb50SAxel Dörfler gAreSettingsRunning = true; 7489949213aSStephan Aßmus 7499949213aSStephan Aßmus // Without this strings are not correctly aliased 7509949213aSStephan Aßmus // THX to Jack Burton for info :) 7519949213aSStephan Aßmus SetLowColor( ViewColor()); 7529949213aSStephan Aßmus 753*d8e2fb50SAxel Dörfler // Load settings to global settings struct 754*d8e2fb50SAxel Dörfler LoadSettings(&fSettings); 7559949213aSStephan Aßmus 7569949213aSStephan Aßmus // Add left and top margins 757*d8e2fb50SAxel Dörfler float top = fTabHeight+15; 7589949213aSStephan Aßmus float left = 0; 7599949213aSStephan Aßmus 7609949213aSStephan Aßmus // This will remember longest string width 7619949213aSStephan Aßmus int32 nameWidth = 0; 7629949213aSStephan Aßmus 763*d8e2fb50SAxel Dörfler SView *view = new TranslatorWriteView("Write", &fSettings, left, top); 7649949213aSStephan Aßmus AddChild(view); 765*d8e2fb50SAxel Dörfler nameWidth = (int32)StringWidth(view->Name()); 7669949213aSStephan Aßmus 767*d8e2fb50SAxel Dörfler view = new TranslatorReadView("Read", &fSettings, left, top); 7689949213aSStephan Aßmus AddChild(view); 7699949213aSStephan Aßmus if (nameWidth < StringWidth(view->Name())) 770*d8e2fb50SAxel Dörfler nameWidth = (int32)StringWidth(view->Name()); 7719949213aSStephan Aßmus 7729949213aSStephan Aßmus view = new TranslatorAboutView("About", left, top); 7739949213aSStephan Aßmus AddChild(view); 7749949213aSStephan Aßmus if (nameWidth < StringWidth(view->Name())) 775*d8e2fb50SAxel Dörfler nameWidth = (int32)StringWidth(view->Name()); 7769949213aSStephan Aßmus 777*d8e2fb50SAxel Dörfler fTabWidth += nameWidth; 778*d8e2fb50SAxel Dörfler if (fTabWidth * CountChildren() > GetPreferredWidth()) 779*d8e2fb50SAxel Dörfler ResizePreferredBy((fTabWidth * CountChildren()) - GetPreferredWidth(), 0); 7809949213aSStephan Aßmus 7819949213aSStephan Aßmus // Add right and bottom margins 7829949213aSStephan Aßmus ResizePreferredBy(10, 15); 7839949213aSStephan Aßmus 7849949213aSStephan Aßmus ResizeToPreferred(); 7859949213aSStephan Aßmus 7869949213aSStephan Aßmus // Make TranslatorView resize itself with parent 7879949213aSStephan Aßmus SetFlags( Flags() | B_FOLLOW_ALL); 7889949213aSStephan Aßmus } 7899949213aSStephan Aßmus 790*d8e2fb50SAxel Dörfler 791*d8e2fb50SAxel Dörfler TranslatorView::~TranslatorView() 792*d8e2fb50SAxel Dörfler { 793*d8e2fb50SAxel Dörfler gAreSettingsRunning = false; 794*d8e2fb50SAxel Dörfler } 795*d8e2fb50SAxel Dörfler 796*d8e2fb50SAxel Dörfler 797*d8e2fb50SAxel Dörfler //! Attached to window - resize parent to preferred 7989949213aSStephan Aßmus void 7999949213aSStephan Aßmus TranslatorView::AttachedToWindow() 8009949213aSStephan Aßmus { 8019949213aSStephan Aßmus // Hide all children except first one 802*d8e2fb50SAxel Dörfler BView *child; 8039949213aSStephan Aßmus int32 index = 1; 804*d8e2fb50SAxel Dörfler while ((child = ChildAt(index++)) != NULL) 8059949213aSStephan Aßmus child->Hide(); 8069949213aSStephan Aßmus 8079949213aSStephan Aßmus // Hack for DataTranslations which doesn't resize visible area to requested by view 8089949213aSStephan Aßmus // which makes some parts of bigger than usual translationviews out of visible area 8099949213aSStephan Aßmus // so if it was loaded to DataTranslations resize window if needed 8109949213aSStephan Aßmus BWindow *window = Window(); 8119949213aSStephan Aßmus if (!strcmp(window->Name(), "DataTranslations")) { 8129949213aSStephan Aßmus BView *view = Parent(); 8139949213aSStephan Aßmus if (view) { 8149949213aSStephan Aßmus BRect frame = view->Frame(); 815*d8e2fb50SAxel Dörfler if (frame.Width() < GetPreferredWidth() 816*d8e2fb50SAxel Dörfler || (frame.Height()-48) < GetPreferredHeight()) { 8179949213aSStephan Aßmus float x = ceil(GetPreferredWidth() - frame.Width()); 8189949213aSStephan Aßmus float y = ceil(GetPreferredHeight() - (frame.Height()-48)); 819*d8e2fb50SAxel Dörfler if (x < 0) 820*d8e2fb50SAxel Dörfler x = 0; 821*d8e2fb50SAxel Dörfler if (y < 0) 822*d8e2fb50SAxel Dörfler y = 0; 8239949213aSStephan Aßmus 8249949213aSStephan Aßmus // DataTranslations has main view called "Background" 8259949213aSStephan Aßmus // change it's resizing mode so it will always resize with window 8269949213aSStephan Aßmus // also make sure view will be redrawed after resize 8279949213aSStephan Aßmus view = window->FindView("Background"); 8289949213aSStephan Aßmus if (view) { 8299949213aSStephan Aßmus view->SetResizingMode(B_FOLLOW_ALL); 8309949213aSStephan Aßmus view->SetFlags(B_FULL_UPDATE_ON_RESIZE); 8319949213aSStephan Aßmus } 8329949213aSStephan Aßmus 8339949213aSStephan Aßmus // The same with "Info..." button, except redrawing, which isn't needed 8349949213aSStephan Aßmus view = window->FindView("Info…"); 8359949213aSStephan Aßmus if (view) 8369949213aSStephan Aßmus view->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 8379949213aSStephan Aßmus 8389949213aSStephan Aßmus window->ResizeBy(x, y); 8399949213aSStephan Aßmus 8409949213aSStephan Aßmus // Let user resize window if resizing option is not already there... 8419949213aSStephan Aßmus uint32 flags = window->Flags(); 8429949213aSStephan Aßmus if (flags & B_NOT_RESIZABLE) { 8439949213aSStephan Aßmus // ...but first prevent too small window (so "Info..." button will not look strange ;) 8449949213aSStephan Aßmus // max will be 800x600 which should be enough for now 8459949213aSStephan Aßmus window->SetSizeLimits(400, 800, 66, 600); 8469949213aSStephan Aßmus 8479949213aSStephan Aßmus flags ^= B_NOT_RESIZABLE; 8489949213aSStephan Aßmus window->SetFlags(flags); 8499949213aSStephan Aßmus } 8509949213aSStephan Aßmus } 8519949213aSStephan Aßmus } 8529949213aSStephan Aßmus } 8539949213aSStephan Aßmus } 8549949213aSStephan Aßmus 855*d8e2fb50SAxel Dörfler 8569949213aSStephan Aßmus void 8579949213aSStephan Aßmus TranslatorView::Draw(BRect updateRect) 8589949213aSStephan Aßmus { 8599949213aSStephan Aßmus // This is needed because DataTranslations app hides children 8609949213aSStephan Aßmus // after user changes translator 861*d8e2fb50SAxel Dörfler if (ChildAt(fActiveChild)->IsHidden()) 862*d8e2fb50SAxel Dörfler ChildAt(fActiveChild)->Show(); 8639949213aSStephan Aßmus 8649949213aSStephan Aßmus // Prepare colors used for drawing "tabs" 8659949213aSStephan Aßmus rgb_color dark_line_color = tint_color( ViewColor(), B_DARKEN_2_TINT); 8669949213aSStephan Aßmus rgb_color darkest_line_color = tint_color( ViewColor(), B_DARKEN_3_TINT); 8679949213aSStephan Aßmus rgb_color light_line_color = tint_color( ViewColor(), B_LIGHTEN_MAX_TINT); 8689949213aSStephan Aßmus rgb_color text_color = ui_color(B_MENU_ITEM_TEXT_COLOR); 8699949213aSStephan Aßmus 8709949213aSStephan Aßmus // Clear 8719949213aSStephan Aßmus SetHighColor( ViewColor()); 872*d8e2fb50SAxel Dörfler FillRect(BRect(0, 0, Frame().right, fTabHeight)); 8739949213aSStephan Aßmus 874*d8e2fb50SAxel Dörfler int32 index = 0; 875*d8e2fb50SAxel Dörfler float left = 0; 876*d8e2fb50SAxel Dörfler BView *child; 877*d8e2fb50SAxel Dörfler while ((child = ChildAt(index)) != NULL) { 878*d8e2fb50SAxel Dörfler // TODO: this apparently uses BFont::Size() as height in pixels!!! 8799949213aSStephan Aßmus // Draw outline 8809949213aSStephan Aßmus SetHighColor(dark_line_color); 881*d8e2fb50SAxel Dörfler StrokeLine(BPoint(left, 10), BPoint(left, fTabHeight)); 8829949213aSStephan Aßmus StrokeArc(BPoint(left + 10, 10), 10, 10, 90, 90); 883*d8e2fb50SAxel Dörfler StrokeLine(BPoint(left + 10, 0), BPoint(left + fTabWidth - 10, 0)); 884*d8e2fb50SAxel Dörfler StrokeArc(BPoint(left + fTabWidth - 10, 10), 9, 10, 0, 90); 885*d8e2fb50SAxel Dörfler StrokeLine(BPoint(left + fTabWidth - 1, 10), 886*d8e2fb50SAxel Dörfler BPoint(left + fTabWidth - 1, fTabHeight)); 8879949213aSStephan Aßmus // Draw "shadow" on the right side 8889949213aSStephan Aßmus SetHighColor(darkest_line_color); 889*d8e2fb50SAxel Dörfler StrokeArc( BPoint(left+fTabWidth-10, 10), 10, 10, 0, 50); 890*d8e2fb50SAxel Dörfler StrokeLine( BPoint(left+fTabWidth, 10), BPoint(left + fTabWidth, fTabHeight - 1)); 8919949213aSStephan Aßmus // Draw label 8929949213aSStephan Aßmus SetHighColor(text_color); 893*d8e2fb50SAxel Dörfler DrawString(child->Name(), BPoint(left + (fTabWidth / 2) 894*d8e2fb50SAxel Dörfler - (StringWidth(child->Name()) / 2), 3 + be_plain_font->Size())); 895*d8e2fb50SAxel Dörfler 8969949213aSStephan Aßmus // Draw "light" on left and top side 8979949213aSStephan Aßmus SetHighColor(light_line_color); 8989949213aSStephan Aßmus StrokeArc(BPoint(left + 10, 10), 9, 9, 90, 90); 899*d8e2fb50SAxel Dörfler StrokeLine(BPoint(left + 1, 10), BPoint(left + 1, fTabHeight)); 900*d8e2fb50SAxel Dörfler StrokeLine(BPoint(left + 10, 1), BPoint(left + fTabWidth - 8, 1)); 9019949213aSStephan Aßmus // Draw bottom edge 902*d8e2fb50SAxel Dörfler if (fActiveChild != index) 903*d8e2fb50SAxel Dörfler StrokeLine(BPoint(left - 2, fTabHeight), BPoint(left + fTabWidth, fTabHeight)); 9049949213aSStephan Aßmus else 905*d8e2fb50SAxel Dörfler StrokeLine(BPoint(left - 2, fTabHeight), BPoint(left + 1, fTabHeight)); 9069949213aSStephan Aßmus 907*d8e2fb50SAxel Dörfler left += fTabWidth + 2; 9089949213aSStephan Aßmus index++; 9099949213aSStephan Aßmus } 910*d8e2fb50SAxel Dörfler 9119949213aSStephan Aßmus // Draw bottom edge to the rigth side 912*d8e2fb50SAxel Dörfler StrokeLine(BPoint(left - 2, fTabHeight), BPoint(Bounds().Width(), fTabHeight)); 9139949213aSStephan Aßmus } 9149949213aSStephan Aßmus 915*d8e2fb50SAxel Dörfler 916*d8e2fb50SAxel Dörfler //! MouseDown, check if on tab, if so change tab if needed 9179949213aSStephan Aßmus void 9189949213aSStephan Aßmus TranslatorView::MouseDown(BPoint where) 9199949213aSStephan Aßmus { 9209949213aSStephan Aßmus // If user clicked on tabs part of view 921*d8e2fb50SAxel Dörfler if (where.y <= fTabHeight) { 9229949213aSStephan Aßmus // If there is a tab (not whole width is occupied by tabs) 923*d8e2fb50SAxel Dörfler if (where.x < fTabWidth*CountChildren()) { 9249949213aSStephan Aßmus // Which tab was selected? 925*d8e2fb50SAxel Dörfler int32 index = int32(where.x / fTabWidth); 926*d8e2fb50SAxel Dörfler if (fActiveChild != index) { 9279949213aSStephan Aßmus // Hide current visible child 928*d8e2fb50SAxel Dörfler ChildAt(fActiveChild)->Hide(); 9299949213aSStephan Aßmus // This loop is needed because it looks like in DataTranslations 9309949213aSStephan Aßmus // view gets hidden more than one time when user changes translator 9319949213aSStephan Aßmus while (ChildAt(index)->IsHidden()) 9329949213aSStephan Aßmus ChildAt(index)->Show(); 9339949213aSStephan Aßmus // Remember which one is currently visible 934*d8e2fb50SAxel Dörfler fActiveChild = index; 9359949213aSStephan Aßmus // Redraw 9369949213aSStephan Aßmus Draw( Frame()); 9379949213aSStephan Aßmus } 9389949213aSStephan Aßmus } 9399949213aSStephan Aßmus } 940*d8e2fb50SAxel Dörfler } 9419949213aSStephan Aßmus 9429949213aSStephan Aßmus 943*d8e2fb50SAxel Dörfler // #pragma mark - 9449949213aSStephan Aßmus 945*d8e2fb50SAxel Dörfler 946*d8e2fb50SAxel Dörfler TranslatorWindow::TranslatorWindow(bool quitOnClose) 9479949213aSStephan Aßmus : BWindow(BRect(100, 100, 100, 100), "JPEG Settings", B_TITLED_WINDOW, B_NOT_ZOOMABLE) 9489949213aSStephan Aßmus { 9499949213aSStephan Aßmus BRect extent(0, 0, 0, 0); 9509949213aSStephan Aßmus BView *config = NULL; 9519949213aSStephan Aßmus MakeConfig(NULL, &config, &extent); 9529949213aSStephan Aßmus 9539949213aSStephan Aßmus AddChild(config); 9549949213aSStephan Aßmus ResizeTo(extent.Width(), extent.Height()); 9559949213aSStephan Aßmus 9569949213aSStephan Aßmus // Make application quit after this window close 957*d8e2fb50SAxel Dörfler if (quitOnClose) 9589949213aSStephan Aßmus SetFlags(Flags() | B_QUIT_ON_WINDOW_CLOSE); 9599949213aSStephan Aßmus } 9609949213aSStephan Aßmus 9619949213aSStephan Aßmus 962*d8e2fb50SAxel Dörfler // #pragma mark - Translator Add-On 9639949213aSStephan Aßmus 9649949213aSStephan Aßmus 9659949213aSStephan Aßmus 966*d8e2fb50SAxel Dörfler /*! Hook to create and return our configuration view */ 9679949213aSStephan Aßmus status_t 9689949213aSStephan Aßmus MakeConfig(BMessage *ioExtension, BView **outView, BRect *outExtent) 9699949213aSStephan Aßmus { 9709949213aSStephan Aßmus *outView = new TranslatorView("TranslatorView"); 9719949213aSStephan Aßmus *outExtent = (*outView)->Frame(); 9729949213aSStephan Aßmus return B_OK; 9739949213aSStephan Aßmus } 9749949213aSStephan Aßmus 975*d8e2fb50SAxel Dörfler /*! Determine whether or not we can handle this data */ 9769949213aSStephan Aßmus status_t 977*d8e2fb50SAxel Dörfler Identify(BPositionIO *inSource, const translation_format *inFormat, 978*d8e2fb50SAxel Dörfler BMessage *ioExtension, translator_info *outInfo, uint32 outType) 9799949213aSStephan Aßmus { 9809949213aSStephan Aßmus 981*d8e2fb50SAxel Dörfler if (outType != 0 && outType != B_TRANSLATOR_BITMAP && outType != JPEG_FORMAT) 9829949213aSStephan Aßmus return B_NO_TRANSLATOR; 9839949213aSStephan Aßmus 9849949213aSStephan Aßmus // !!! You might need to make this buffer bigger to test for your native format 9859949213aSStephan Aßmus off_t position = inSource->Position(); 9869949213aSStephan Aßmus char header[sizeof(TranslatorBitmap)]; 9879949213aSStephan Aßmus status_t err = inSource->Read(header, sizeof(TranslatorBitmap)); 9889949213aSStephan Aßmus inSource->Seek(position, SEEK_SET); 989*d8e2fb50SAxel Dörfler if (err < B_OK) 990*d8e2fb50SAxel Dörfler return err; 9919949213aSStephan Aßmus 9929949213aSStephan Aßmus if (B_BENDIAN_TO_HOST_INT32(((TranslatorBitmap *)header)->magic) == B_TRANSLATOR_BITMAP) { 9939949213aSStephan Aßmus outInfo->type = inputFormats[1].type; 9949949213aSStephan Aßmus outInfo->translator = 0; 9959949213aSStephan Aßmus outInfo->group = inputFormats[1].group; 9969949213aSStephan Aßmus outInfo->quality = inputFormats[1].quality; 9979949213aSStephan Aßmus outInfo->capability = inputFormats[1].capability; 9989949213aSStephan Aßmus strcpy(outInfo->name, inputFormats[1].name); 9999949213aSStephan Aßmus strcpy(outInfo->MIME, inputFormats[1].MIME); 10009949213aSStephan Aßmus } else { 10019949213aSStephan Aßmus // First 3 bytes in jpg files are always the same from what i've seen so far 10029949213aSStephan Aßmus // check them 10039949213aSStephan Aßmus if (header[0] == (char)0xff && header[1] == (char)0xd8 && header[2] == (char)0xff) { 10049949213aSStephan Aßmus /* this below would be safer but it slows down whole thing 10059949213aSStephan Aßmus 10069949213aSStephan Aßmus struct jpeg_decompress_struct cinfo; 10079949213aSStephan Aßmus struct jpeg_error_mgr jerr; 10089949213aSStephan Aßmus cinfo.err = jpeg_std_error(&jerr); 10099949213aSStephan Aßmus jpeg_create_decompress(&cinfo); 10109949213aSStephan Aßmus be_jpeg_stdio_src(&cinfo, inSource); 10119949213aSStephan Aßmus // now try to read header 10129949213aSStephan Aßmus // it can't be read before checking first 3 bytes 10139949213aSStephan Aßmus // because it will hang up if there is no header (not jpeg file) 10149949213aSStephan Aßmus int result = jpeg_read_header(&cinfo, FALSE); 10159949213aSStephan Aßmus jpeg_destroy_decompress(&cinfo); 10169949213aSStephan Aßmus if (result == JPEG_HEADER_OK) { 10179949213aSStephan Aßmus */ outInfo->type = inputFormats[0].type; 10189949213aSStephan Aßmus outInfo->translator = 0; 10199949213aSStephan Aßmus outInfo->group = inputFormats[0].group; 10209949213aSStephan Aßmus outInfo->quality = inputFormats[0].quality; 10219949213aSStephan Aßmus outInfo->capability = inputFormats[0].capability; 10229949213aSStephan Aßmus strcpy(outInfo->name, inputFormats[0].name); 10239949213aSStephan Aßmus strcpy(outInfo->MIME, inputFormats[0].MIME); 10249949213aSStephan Aßmus return B_OK; 10259949213aSStephan Aßmus /* } else 10269949213aSStephan Aßmus return B_NO_TRANSLATOR; 10279949213aSStephan Aßmus */ 10289949213aSStephan Aßmus } else 10299949213aSStephan Aßmus return B_NO_TRANSLATOR; 10309949213aSStephan Aßmus } 10319949213aSStephan Aßmus 10329949213aSStephan Aßmus return B_OK; 10339949213aSStephan Aßmus } 10349949213aSStephan Aßmus 1035*d8e2fb50SAxel Dörfler /*! Arguably the most important method in the add-on */ 10369949213aSStephan Aßmus status_t 1037*d8e2fb50SAxel Dörfler Translate(BPositionIO *inSource, const translator_info *inInfo, 1038*d8e2fb50SAxel Dörfler BMessage *ioExtension, uint32 outType, BPositionIO *outDestination) 10399949213aSStephan Aßmus { 10409949213aSStephan Aßmus // If no specific type was requested, convert to the interchange format 10419949213aSStephan Aßmus if (outType == 0) outType = B_TRANSLATOR_BITMAP; 10429949213aSStephan Aßmus 10439949213aSStephan Aßmus // What action to take, based on the findings of Identify() 10449949213aSStephan Aßmus if (outType == inInfo->type) { 10459949213aSStephan Aßmus return Copy(inSource, outDestination); 10469949213aSStephan Aßmus } else if (inInfo->type == B_TRANSLATOR_BITMAP && outType == JPEG_FORMAT) { 10479949213aSStephan Aßmus return Compress(inSource, outDestination); 10489949213aSStephan Aßmus } else if (inInfo->type == JPEG_FORMAT && outType == B_TRANSLATOR_BITMAP) { 10499949213aSStephan Aßmus return Decompress(inSource, outDestination); 10509949213aSStephan Aßmus } 10519949213aSStephan Aßmus 10529949213aSStephan Aßmus return B_NO_TRANSLATOR; 10539949213aSStephan Aßmus } 10549949213aSStephan Aßmus 1055*d8e2fb50SAxel Dörfler /*! The user has requested the same format for input and output, so just copy */ 10569949213aSStephan Aßmus status_t 10579949213aSStephan Aßmus Copy(BPositionIO *in, BPositionIO *out) 10589949213aSStephan Aßmus { 10599949213aSStephan Aßmus int block_size = 65536; 10609949213aSStephan Aßmus void *buffer = malloc(block_size); 10619949213aSStephan Aßmus char temp[1024]; 10629949213aSStephan Aßmus if (buffer == NULL) { 10639949213aSStephan Aßmus buffer = temp; 10649949213aSStephan Aßmus block_size = 1024; 10659949213aSStephan Aßmus } 10669949213aSStephan Aßmus status_t err = B_OK; 10679949213aSStephan Aßmus 10689949213aSStephan Aßmus // Read until end of file or error 10699949213aSStephan Aßmus while (1) { 10709949213aSStephan Aßmus ssize_t to_read = block_size; 10719949213aSStephan Aßmus err = in->Read(buffer, to_read); 10729949213aSStephan Aßmus // Explicit check for EOF 10739949213aSStephan Aßmus if (err == -1) { 10749949213aSStephan Aßmus if (buffer != temp) free(buffer); 10759949213aSStephan Aßmus return B_OK; 10769949213aSStephan Aßmus } 10779949213aSStephan Aßmus if (err <= B_OK) break; 10789949213aSStephan Aßmus to_read = err; 10799949213aSStephan Aßmus err = out->Write(buffer, to_read); 10809949213aSStephan Aßmus if (err != to_read) if (err >= 0) err = B_DEVICE_FULL; 10819949213aSStephan Aßmus if (err < B_OK) break; 10829949213aSStephan Aßmus } 10839949213aSStephan Aßmus 10849949213aSStephan Aßmus if (buffer != temp) free(buffer); 10859949213aSStephan Aßmus return (err >= 0) ? B_OK : err; 10869949213aSStephan Aßmus } 10879949213aSStephan Aßmus 1088*d8e2fb50SAxel Dörfler 1089*d8e2fb50SAxel Dörfler /*! Encode into the native format */ 10909949213aSStephan Aßmus status_t 10919949213aSStephan Aßmus Compress(BPositionIO *in, BPositionIO *out) 10929949213aSStephan Aßmus { 10939949213aSStephan Aßmus // Load Settings 1094*d8e2fb50SAxel Dörfler jpeg_settings settings; 1095*d8e2fb50SAxel Dörfler LoadSettings(&settings); 10969949213aSStephan Aßmus 10979949213aSStephan Aßmus // Read info about bitmap 10989949213aSStephan Aßmus TranslatorBitmap header; 10999949213aSStephan Aßmus status_t err = in->Read(&header, sizeof(TranslatorBitmap)); 1100*d8e2fb50SAxel Dörfler if (err < B_OK) 1101*d8e2fb50SAxel Dörfler return err; 1102*d8e2fb50SAxel Dörfler else if (err < (int)sizeof(TranslatorBitmap)) 1103*d8e2fb50SAxel Dörfler return B_ERROR; 11049949213aSStephan Aßmus 11059949213aSStephan Aßmus // Grab dimension, color space, and size information from the stream 11069949213aSStephan Aßmus BRect bounds; 11079949213aSStephan Aßmus bounds.left = B_BENDIAN_TO_HOST_FLOAT(header.bounds.left); 11089949213aSStephan Aßmus bounds.top = B_BENDIAN_TO_HOST_FLOAT(header.bounds.top); 11099949213aSStephan Aßmus bounds.right = B_BENDIAN_TO_HOST_FLOAT(header.bounds.right); 11109949213aSStephan Aßmus bounds.bottom = B_BENDIAN_TO_HOST_FLOAT(header.bounds.bottom); 11119949213aSStephan Aßmus 11129949213aSStephan Aßmus int32 in_row_bytes = B_BENDIAN_TO_HOST_INT32(header.rowBytes); 11139949213aSStephan Aßmus 11149949213aSStephan Aßmus int width = bounds.IntegerWidth() + 1; 11159949213aSStephan Aßmus int height = bounds.IntegerHeight() + 1; 11169949213aSStephan Aßmus 11179949213aSStephan Aßmus // Function pointer to convert function 11189949213aSStephan Aßmus // It will point to proper function if needed 11199949213aSStephan Aßmus void (*converter)(uchar *inscanline, uchar *outscanline, int inrow_bytes) = NULL; 11209949213aSStephan Aßmus 11219949213aSStephan Aßmus // Default color info 11229949213aSStephan Aßmus J_COLOR_SPACE jpg_color_space = JCS_RGB; 11239949213aSStephan Aßmus int jpg_input_components = 3; 11249949213aSStephan Aßmus int32 out_row_bytes; 11259949213aSStephan Aßmus int padding = 0; 11269949213aSStephan Aßmus 1127*d8e2fb50SAxel Dörfler switch ((color_space)B_BENDIAN_TO_HOST_INT32(header.colors)) { 11289949213aSStephan Aßmus case B_CMAP8: 11299949213aSStephan Aßmus converter = convert_from_cmap8_to_24; 11309949213aSStephan Aßmus padding = in_row_bytes - width; 11319949213aSStephan Aßmus break; 1132*d8e2fb50SAxel Dörfler 11339949213aSStephan Aßmus case B_GRAY1: 1134*d8e2fb50SAxel Dörfler if (settings.B_GRAY1_as_B_RGB24) { 11359949213aSStephan Aßmus converter = convert_from_gray1_to_24; 11369949213aSStephan Aßmus } else { 11379949213aSStephan Aßmus jpg_input_components = 1; 11389949213aSStephan Aßmus jpg_color_space = JCS_GRAYSCALE; 11399949213aSStephan Aßmus converter = convert_from_gray1_to_gray8; 11409949213aSStephan Aßmus } 11419949213aSStephan Aßmus padding = in_row_bytes - (width/8); 11429949213aSStephan Aßmus break; 1143*d8e2fb50SAxel Dörfler 11449949213aSStephan Aßmus case B_GRAY8: 11459949213aSStephan Aßmus jpg_input_components = 1; 11469949213aSStephan Aßmus jpg_color_space = JCS_GRAYSCALE; 11479949213aSStephan Aßmus padding = in_row_bytes - width; 11489949213aSStephan Aßmus break; 1149*d8e2fb50SAxel Dörfler 11509949213aSStephan Aßmus case B_RGB15: 11519949213aSStephan Aßmus case B_RGBA15: 11529949213aSStephan Aßmus converter = convert_from_15_to_24; 11539949213aSStephan Aßmus padding = in_row_bytes - (width * 2); 11549949213aSStephan Aßmus break; 1155*d8e2fb50SAxel Dörfler 11569949213aSStephan Aßmus case B_RGB15_BIG: 11579949213aSStephan Aßmus case B_RGBA15_BIG: 11589949213aSStephan Aßmus converter = convert_from_15b_to_24; 11599949213aSStephan Aßmus padding = in_row_bytes - (width * 2); 11609949213aSStephan Aßmus break; 1161*d8e2fb50SAxel Dörfler 11629949213aSStephan Aßmus case B_RGB16: 11639949213aSStephan Aßmus converter = convert_from_16_to_24; 11649949213aSStephan Aßmus padding = in_row_bytes - (width * 2); 11659949213aSStephan Aßmus break; 1166*d8e2fb50SAxel Dörfler 11679949213aSStephan Aßmus case B_RGB16_BIG: 11689949213aSStephan Aßmus converter = convert_from_16b_to_24; 11699949213aSStephan Aßmus padding = in_row_bytes - (width * 2); 11709949213aSStephan Aßmus break; 1171*d8e2fb50SAxel Dörfler 11729949213aSStephan Aßmus case B_RGB24: 11739949213aSStephan Aßmus converter = convert_from_24_to_24; 11749949213aSStephan Aßmus padding = in_row_bytes - (width * 3); 11759949213aSStephan Aßmus break; 1176*d8e2fb50SAxel Dörfler 11779949213aSStephan Aßmus case B_RGB24_BIG: 11789949213aSStephan Aßmus padding = in_row_bytes - (width * 3); 11799949213aSStephan Aßmus break; 1180*d8e2fb50SAxel Dörfler 11819949213aSStephan Aßmus case B_RGB32: 11829949213aSStephan Aßmus case B_RGBA32: 11839949213aSStephan Aßmus converter = convert_from_32_to_24; 11849949213aSStephan Aßmus padding = in_row_bytes - (width * 4); 11859949213aSStephan Aßmus break; 1186*d8e2fb50SAxel Dörfler 11879949213aSStephan Aßmus case B_RGB32_BIG: 11889949213aSStephan Aßmus case B_RGBA32_BIG: 11899949213aSStephan Aßmus converter = convert_from_32b_to_24; 11909949213aSStephan Aßmus padding = in_row_bytes - (width * 4); 11919949213aSStephan Aßmus break; 1192*d8e2fb50SAxel Dörfler 11939949213aSStephan Aßmus case B_CMYK32: 11949949213aSStephan Aßmus jpg_color_space = JCS_CMYK; 11959949213aSStephan Aßmus jpg_input_components = 4; 11969949213aSStephan Aßmus padding = in_row_bytes - (width * 4); 11979949213aSStephan Aßmus break; 1198*d8e2fb50SAxel Dörfler 11999949213aSStephan Aßmus default: 12009949213aSStephan Aßmus fprintf(stderr, "Wrong type: Color space not implemented.\n"); 12019949213aSStephan Aßmus return B_ERROR; 12029949213aSStephan Aßmus } 12039949213aSStephan Aßmus out_row_bytes = jpg_input_components * width; 12049949213aSStephan Aßmus 12059949213aSStephan Aßmus // Set basic things needed for jpeg writing 12069949213aSStephan Aßmus struct jpeg_compress_struct cinfo; 12079949213aSStephan Aßmus struct jpeg_error_mgr jerr; 1208*d8e2fb50SAxel Dörfler cinfo.err = be_jpeg_std_error(&jerr, &settings); 12099949213aSStephan Aßmus jpeg_create_compress(&cinfo); 12109949213aSStephan Aßmus be_jpeg_stdio_dest(&cinfo, out); 12119949213aSStephan Aßmus 12129949213aSStephan Aßmus // Set basic values 12139949213aSStephan Aßmus cinfo.image_width = width; 12149949213aSStephan Aßmus cinfo.image_height = height; 12159949213aSStephan Aßmus cinfo.input_components = jpg_input_components; 12169949213aSStephan Aßmus cinfo.in_color_space = jpg_color_space; 12179949213aSStephan Aßmus jpeg_set_defaults(&cinfo); 12189949213aSStephan Aßmus 12199949213aSStephan Aßmus // Set better accuracy 12209949213aSStephan Aßmus cinfo.dct_method = JDCT_ISLOW; 12219949213aSStephan Aßmus 12229949213aSStephan Aßmus // This is needed to prevent some colors loss 12239949213aSStephan Aßmus // With it generated jpegs are as good as from Fireworks (at last! :D) 1224*d8e2fb50SAxel Dörfler if (settings.OptimizeColors) { 12259949213aSStephan Aßmus int index = 0; 12269949213aSStephan Aßmus while (index < cinfo.num_components) { 12279949213aSStephan Aßmus cinfo.comp_info[index].h_samp_factor = 1; 12289949213aSStephan Aßmus cinfo.comp_info[index].v_samp_factor = 1; 12299949213aSStephan Aßmus // This will make file smaller, but with worse quality more or less 12309949213aSStephan Aßmus // like with 93%-94% (but it's subjective opinion) on tested images 12319949213aSStephan Aßmus // but with smaller size (between 92% and 93% on tested images) 1232*d8e2fb50SAxel Dörfler if (settings.SmallerFile) 12339949213aSStephan Aßmus cinfo.comp_info[index].quant_tbl_no = 1; 12349949213aSStephan Aßmus // This will make bigger file, but also better quality ;] 12359949213aSStephan Aßmus // from my tests it seems like useless - better quality with smaller 12369949213aSStephan Aßmus // can be acheived without this 12379949213aSStephan Aßmus // cinfo.comp_info[index].dc_tbl_no = 1; 12389949213aSStephan Aßmus // cinfo.comp_info[index].ac_tbl_no = 1; 12399949213aSStephan Aßmus index++; 12409949213aSStephan Aßmus } 12419949213aSStephan Aßmus } 12429949213aSStephan Aßmus 12439949213aSStephan Aßmus // Set quality 1244*d8e2fb50SAxel Dörfler jpeg_set_quality(&cinfo, settings.Quality, true); 12459949213aSStephan Aßmus 12469949213aSStephan Aßmus // Set progressive compression if needed 12479949213aSStephan Aßmus // if not, turn on optimizing in libjpeg 1248*d8e2fb50SAxel Dörfler if (settings.Progressive) 12499949213aSStephan Aßmus jpeg_simple_progression(&cinfo); 12509949213aSStephan Aßmus else 12519949213aSStephan Aßmus cinfo.optimize_coding = TRUE; 12529949213aSStephan Aßmus 12539949213aSStephan Aßmus // Set smoothing (effect like Blur) 1254*d8e2fb50SAxel Dörfler cinfo.smoothing_factor = settings.Smoothing; 12559949213aSStephan Aßmus 12569949213aSStephan Aßmus // Initialize compression 12579949213aSStephan Aßmus jpeg_start_compress(&cinfo, TRUE); 12589949213aSStephan Aßmus 12599949213aSStephan Aßmus // Declare scanlines 12609949213aSStephan Aßmus JSAMPROW in_scanline = NULL; 12619949213aSStephan Aßmus JSAMPROW out_scanline = NULL; 12629949213aSStephan Aßmus JSAMPROW writeline; // Pointer to in_scanline (default) or out_scanline (if there will be conversion) 12639949213aSStephan Aßmus 12649949213aSStephan Aßmus // Allocate scanline 12659949213aSStephan Aßmus // Use libjpeg memory allocation functions, so in case of error it will free them itself 1266*d8e2fb50SAxel Dörfler in_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo, 1267*d8e2fb50SAxel Dörfler JPOOL_PERMANENT, in_row_bytes); 12689949213aSStephan Aßmus 12699949213aSStephan Aßmus // We need 2nd scanline storage ony for conversion 12709949213aSStephan Aßmus if (converter != NULL) { 12719949213aSStephan Aßmus // There will be conversion, allocate second scanline... 12729949213aSStephan Aßmus // Use libjpeg memory allocation functions, so in case of error it will free them itself 1273*d8e2fb50SAxel Dörfler out_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo, 1274*d8e2fb50SAxel Dörfler JPOOL_PERMANENT, out_row_bytes); 12759949213aSStephan Aßmus // ... and make it the one to write to file 12769949213aSStephan Aßmus writeline = out_scanline; 12779949213aSStephan Aßmus } else 12789949213aSStephan Aßmus writeline = in_scanline; 12799949213aSStephan Aßmus 12809949213aSStephan Aßmus while (cinfo.next_scanline < cinfo.image_height) { 12819949213aSStephan Aßmus // Read scanline 12829949213aSStephan Aßmus err = in->Read(in_scanline, in_row_bytes); 12839949213aSStephan Aßmus if (err < in_row_bytes) 1284*d8e2fb50SAxel Dörfler return err < B_OK ? Error((j_common_ptr)&cinfo, err) 1285*d8e2fb50SAxel Dörfler : Error((j_common_ptr)&cinfo, B_ERROR); 12869949213aSStephan Aßmus 12879949213aSStephan Aßmus // Convert if needed 12889949213aSStephan Aßmus if (converter != NULL) 12899949213aSStephan Aßmus converter(in_scanline, out_scanline, in_row_bytes-padding); 12909949213aSStephan Aßmus 12919949213aSStephan Aßmus // Write scanline 12929949213aSStephan Aßmus jpeg_write_scanlines(&cinfo, &writeline, 1); 12939949213aSStephan Aßmus } 12949949213aSStephan Aßmus 12959949213aSStephan Aßmus jpeg_finish_compress(&cinfo); 12969949213aSStephan Aßmus jpeg_destroy_compress(&cinfo); 12979949213aSStephan Aßmus return B_OK; 12989949213aSStephan Aßmus } 12999949213aSStephan Aßmus 1300*d8e2fb50SAxel Dörfler 1301*d8e2fb50SAxel Dörfler /*! Decode the native format */ 13029949213aSStephan Aßmus status_t 13039949213aSStephan Aßmus Decompress(BPositionIO *in, BPositionIO *out) 13049949213aSStephan Aßmus { 13059949213aSStephan Aßmus // Load Settings 1306*d8e2fb50SAxel Dörfler jpeg_settings settings; 1307*d8e2fb50SAxel Dörfler LoadSettings(&settings); 13089949213aSStephan Aßmus 13099949213aSStephan Aßmus // Set basic things needed for jpeg reading 13109949213aSStephan Aßmus struct jpeg_decompress_struct cinfo; 13119949213aSStephan Aßmus struct jpeg_error_mgr jerr; 1312*d8e2fb50SAxel Dörfler cinfo.err = be_jpeg_std_error(&jerr, &settings); 13139949213aSStephan Aßmus jpeg_create_decompress(&cinfo); 13149949213aSStephan Aßmus be_jpeg_stdio_src(&cinfo, in); 13159949213aSStephan Aßmus 13169949213aSStephan Aßmus // Read info about image 13179949213aSStephan Aßmus jpeg_read_header(&cinfo, TRUE); 13189949213aSStephan Aßmus 13199949213aSStephan Aßmus // Default color info 13209949213aSStephan Aßmus color_space out_color_space = B_RGB32; 13219949213aSStephan Aßmus int out_color_components = 4; 13229949213aSStephan Aßmus 13239949213aSStephan Aßmus // Function pointer to convert function 13249949213aSStephan Aßmus // It will point to proper function if needed 13259949213aSStephan Aßmus void (*converter)(uchar *inscanline, uchar *outscanline, int inrow_bytes) = convert_from_24_to_32; 13269949213aSStephan Aßmus 13279949213aSStephan Aßmus // If color space isn't rgb 13289949213aSStephan Aßmus if (cinfo.out_color_space != JCS_RGB) { 1329*d8e2fb50SAxel Dörfler switch (cinfo.out_color_space) { 13309949213aSStephan Aßmus case JCS_UNKNOWN: /* error/unspecified */ 13319949213aSStephan Aßmus fprintf(stderr, "From Type: Jpeg uses unknown color type\n"); 13329949213aSStephan Aßmus break; 13339949213aSStephan Aßmus case JCS_GRAYSCALE: /* monochrome */ 13349949213aSStephan Aßmus // Check if user wants to read only as RGB32 or not 1335*d8e2fb50SAxel Dörfler if (!settings.Always_B_RGB32) { 13369949213aSStephan Aßmus // Grayscale 13379949213aSStephan Aßmus out_color_space = B_GRAY8; 13389949213aSStephan Aßmus out_color_components = 1; 13399949213aSStephan Aßmus converter = NULL; 13409949213aSStephan Aßmus } else { 13419949213aSStephan Aßmus // RGB 13429949213aSStephan Aßmus cinfo.out_color_space = JCS_RGB; 13439949213aSStephan Aßmus cinfo.output_components = 3; 13449949213aSStephan Aßmus converter = convert_from_24_to_32; 13459949213aSStephan Aßmus } 13469949213aSStephan Aßmus break; 13479949213aSStephan Aßmus case JCS_YCbCr: /* Y/Cb/Cr (also known as YUV) */ 13489949213aSStephan Aßmus cinfo.out_color_space = JCS_RGB; 13499949213aSStephan Aßmus converter = convert_from_24_to_32; 13509949213aSStephan Aßmus break; 13519949213aSStephan Aßmus case JCS_YCCK: /* Y/Cb/Cr/K */ 13529949213aSStephan Aßmus // Let libjpeg convert it to CMYK 13539949213aSStephan Aßmus cinfo.out_color_space = JCS_CMYK; 13549949213aSStephan Aßmus // Fall through to CMYK since we need the same settings 13559949213aSStephan Aßmus case JCS_CMYK: /* C/M/Y/K */ 13569949213aSStephan Aßmus // Use proper converter 1357*d8e2fb50SAxel Dörfler if (settings.PhotoshopCMYK) 13589949213aSStephan Aßmus converter = convert_from_CMYK_to_32_photoshop; 13599949213aSStephan Aßmus else 13609949213aSStephan Aßmus converter = convert_from_CMYK_to_32; 13619949213aSStephan Aßmus break; 13629949213aSStephan Aßmus default: 13639949213aSStephan Aßmus fprintf(stderr, "From Type: Jpeg uses hmm... i don't know really :(\n"); 13649949213aSStephan Aßmus break; 13659949213aSStephan Aßmus } 13669949213aSStephan Aßmus } 13679949213aSStephan Aßmus 13689949213aSStephan Aßmus // Initialize decompression 13699949213aSStephan Aßmus jpeg_start_decompress(&cinfo); 13709949213aSStephan Aßmus 13719949213aSStephan Aßmus // !!! Initialize this bounds rect to the size of your image 13729949213aSStephan Aßmus BRect bounds( 0, 0, cinfo.output_width-1, cinfo.output_height-1); 13739949213aSStephan Aßmus 13749949213aSStephan Aßmus // Bytes count in one line of image (scanline) 13759949213aSStephan Aßmus int64 row_bytes = cinfo.output_width * out_color_components; 13769949213aSStephan Aßmus 13779949213aSStephan Aßmus // Fill out the B_TRANSLATOR_BITMAP's header 13789949213aSStephan Aßmus TranslatorBitmap header; 13799949213aSStephan Aßmus header.magic = B_HOST_TO_BENDIAN_INT32(B_TRANSLATOR_BITMAP); 13809949213aSStephan Aßmus header.bounds.left = B_HOST_TO_BENDIAN_FLOAT(bounds.left); 13819949213aSStephan Aßmus header.bounds.top = B_HOST_TO_BENDIAN_FLOAT(bounds.top); 13829949213aSStephan Aßmus header.bounds.right = B_HOST_TO_BENDIAN_FLOAT(bounds.right); 13839949213aSStephan Aßmus header.bounds.bottom = B_HOST_TO_BENDIAN_FLOAT(bounds.bottom); 13849949213aSStephan Aßmus header.colors = (color_space)B_HOST_TO_BENDIAN_INT32(out_color_space); 13859949213aSStephan Aßmus header.rowBytes = B_HOST_TO_BENDIAN_INT32(row_bytes); 13869949213aSStephan Aßmus header.dataSize = B_HOST_TO_BENDIAN_INT32(row_bytes * cinfo.output_height); 13879949213aSStephan Aßmus 13889949213aSStephan Aßmus // Write out the header 13899949213aSStephan Aßmus status_t err = out->Write(&header, sizeof(TranslatorBitmap)); 1390*d8e2fb50SAxel Dörfler if (err < B_OK) 1391*d8e2fb50SAxel Dörfler return Error((j_common_ptr)&cinfo, err); 1392*d8e2fb50SAxel Dörfler else if (err < (int)sizeof(TranslatorBitmap)) 1393*d8e2fb50SAxel Dörfler return Error((j_common_ptr)&cinfo, B_ERROR); 13949949213aSStephan Aßmus 13959949213aSStephan Aßmus // Declare scanlines 13969949213aSStephan Aßmus JSAMPROW in_scanline = NULL; 13979949213aSStephan Aßmus JSAMPROW out_scanline = NULL; 13989949213aSStephan Aßmus JSAMPROW writeline; // Pointer to in_scanline or out_scanline (if there will be conversion) 13999949213aSStephan Aßmus 14009949213aSStephan Aßmus // Allocate scanline 14019949213aSStephan Aßmus // Use libjpeg memory allocation functions, so in case of error it will free them itself 1402*d8e2fb50SAxel Dörfler in_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo, 1403*d8e2fb50SAxel Dörfler JPOOL_PERMANENT, row_bytes); 14049949213aSStephan Aßmus 14059949213aSStephan Aßmus // We need 2nd scanline storage only for conversion 14069949213aSStephan Aßmus if (converter != NULL) { 14079949213aSStephan Aßmus // There will be conversion, allocate second scanline... 14089949213aSStephan Aßmus // Use libjpeg memory allocation functions, so in case of error it will free them itself 1409*d8e2fb50SAxel Dörfler out_scanline = (unsigned char *)(cinfo.mem->alloc_large)((j_common_ptr)&cinfo, 1410*d8e2fb50SAxel Dörfler JPOOL_PERMANENT, row_bytes); 14119949213aSStephan Aßmus // ... and make it the one to write to file 14129949213aSStephan Aßmus writeline = out_scanline; 14139949213aSStephan Aßmus } else 14149949213aSStephan Aßmus writeline = in_scanline; 14159949213aSStephan Aßmus 14169949213aSStephan Aßmus while (cinfo.output_scanline < cinfo.output_height) { 14179949213aSStephan Aßmus // Read scanline 14189949213aSStephan Aßmus jpeg_read_scanlines(&cinfo, &in_scanline, 1); 14199949213aSStephan Aßmus 14209949213aSStephan Aßmus // Convert if needed 14219949213aSStephan Aßmus if (converter != NULL) 14229949213aSStephan Aßmus converter(in_scanline, out_scanline, row_bytes); 14239949213aSStephan Aßmus 14249949213aSStephan Aßmus // Write the scanline buffer to the output stream 14259949213aSStephan Aßmus err = out->Write(writeline, row_bytes); 14269949213aSStephan Aßmus if (err < row_bytes) 1427*d8e2fb50SAxel Dörfler return err < B_OK ? Error((j_common_ptr)&cinfo, err) 1428*d8e2fb50SAxel Dörfler : Error((j_common_ptr)&cinfo, B_ERROR); 14299949213aSStephan Aßmus } 14309949213aSStephan Aßmus 14319949213aSStephan Aßmus jpeg_finish_decompress(&cinfo); 14329949213aSStephan Aßmus jpeg_destroy_decompress(&cinfo); 14339949213aSStephan Aßmus return B_OK; 14349949213aSStephan Aßmus } 14359949213aSStephan Aßmus 1436*d8e2fb50SAxel Dörfler /*! 1437*d8e2fb50SAxel Dörfler Frees jpeg alocated memory 1438*d8e2fb50SAxel Dörfler Returns given error (B_ERROR by default) 1439*d8e2fb50SAxel Dörfler */ 14409949213aSStephan Aßmus status_t 14419949213aSStephan Aßmus Error(j_common_ptr cinfo, status_t error) 14429949213aSStephan Aßmus { 14439949213aSStephan Aßmus jpeg_destroy(cinfo); 14449949213aSStephan Aßmus return error; 14459949213aSStephan Aßmus } 1446*d8e2fb50SAxel Dörfler 1447*d8e2fb50SAxel Dörfler 1448*d8e2fb50SAxel Dörfler // #pragma mark - 1449*d8e2fb50SAxel Dörfler 1450*d8e2fb50SAxel Dörfler 1451*d8e2fb50SAxel Dörfler int 1452*d8e2fb50SAxel Dörfler main() { 1453*d8e2fb50SAxel Dörfler BApplication app("application/x-vnd.Shard.JPEGTranslator"); 1454*d8e2fb50SAxel Dörfler 1455*d8e2fb50SAxel Dörfler TranslatorWindow *window = new TranslatorWindow(); 1456*d8e2fb50SAxel Dörfler window->Show(); 1457*d8e2fb50SAxel Dörfler 1458*d8e2fb50SAxel Dörfler app.Run(); 1459*d8e2fb50SAxel Dörfler return 0; 1460*d8e2fb50SAxel Dörfler } 1461*d8e2fb50SAxel Dörfler 1462