diff --git a/src/add-ons/translators/icotranslator/ICO.cpp b/src/add-ons/translators/icotranslator/ICO.cpp index 2337750256..4cd9c5a2de 100644 --- a/src/add-ons/translators/icotranslator/ICO.cpp +++ b/src/add-ons/translators/icotranslator/ICO.cpp @@ -41,6 +41,15 @@ class TempAllocator { }; +bool +ico_header::IsValid() const +{ + return reserved == 0 + && (type == kTypeIcon || type == kTypeCursor) + && entry_count < 32; +} + + void ico_header::SwapToHost() { @@ -305,8 +314,11 @@ convert_data_to_bits(ico_dir_entry &entry, ico_bitmap_header &header, if (bitsPerPixel != 32) { bytesRead = source.Read(andData, andDataSize); - if (bytesRead != andDataSize) - return B_BAD_DATA; + if (bytesRead != andDataSize) { + // reading the alpha channel failed, so we're ignoring it + // (but we're still able to show the image data) + andData = NULL; + } } for (uint32 row = 0; row < entry.height; row++) { @@ -355,7 +367,8 @@ convert_data_to_bits(ico_dir_entry &entry, ico_bitmap_header &header, if (bitsPerPixel != 32) { // set alpha channel - if (get_1_bit_per_pixel(get_data_row(andData, andDataSize, andRowBytes, row), x)) + if (andData != NULL + && get_1_bit_per_pixel(get_data_row(andData, andDataSize, andRowBytes, row), x)) outRowData[x] = kMagicTransparentColor; else outRowData[x].alpha = 255; @@ -483,7 +496,7 @@ convert_bits_to_data(TranslatorBitmap &bitsHeader, uint8 *bitsData, ico_dir_entr status_t -ICO::identify(BMessage *settings, BPositionIO &stream, int32 &bitsPerPixel) +ICO::identify(BMessage *settings, BPositionIO &stream, uint8 &type, int32 &bitsPerPixel) { // read in the header @@ -499,6 +512,7 @@ ICO::identify(BMessage *settings, BPositionIO &stream, int32 &bitsPerPixel) return B_BAD_VALUE; int32 iconIndex = 0; + type = header.type; if (settings) { // Add page count to ioExtension @@ -515,6 +529,8 @@ ICO::identify(BMessage *settings, BPositionIO &stream, int32 &bitsPerPixel) return B_NO_TRANSLATOR; } + TRACE(("iconIndex = %ld, count = %ld\n", iconIndex, header.entry_count)); + // read in directory entries for (uint32 i = 0; i < header.entry_count; i++) { diff --git a/src/add-ons/translators/icotranslator/ICO.h b/src/add-ons/translators/icotranslator/ICO.h index c7f29bcb1f..1dec2d8c15 100644 --- a/src/add-ons/translators/icotranslator/ICO.h +++ b/src/add-ons/translators/icotranslator/ICO.h @@ -17,12 +17,17 @@ namespace ICO { // All ICO structures are written in little endian format +enum ico_type { + kTypeIcon = 1, + kTypeCursor = 2, +}; + struct ico_header { uint16 reserved; uint16 type; uint16 entry_count; - bool IsValid() const { return reserved == 0 && type == 1 && entry_count < 32; } + bool IsValid() const; void SwapToHost(); void SwapFromHost(); } _PACKED; @@ -79,7 +84,7 @@ struct rgba32_color { }; -extern status_t identify(BMessage *settings, BPositionIO &stream, int32 &bitsPerPixel); +extern status_t identify(BMessage *settings, BPositionIO &stream, uint8 &type, int32 &bitsPerPixel); extern status_t convert_ico_to_bits(BMessage *settings, BPositionIO &source, BPositionIO &target); extern status_t convert_bits_to_ico(BMessage *settings, BPositionIO &source, TranslatorBitmap &bitsHeader, BPositionIO &target); diff --git a/src/add-ons/translators/icotranslator/ICOTranslator.cpp b/src/add-ons/translators/icotranslator/ICOTranslator.cpp index d6d4f3db9e..6713387c75 100644 --- a/src/add-ons/translators/icotranslator/ICOTranslator.cpp +++ b/src/add-ons/translators/icotranslator/ICOTranslator.cpp @@ -99,14 +99,16 @@ ICOTranslator::DerivedIdentify(BPositionIO *stream, return B_NO_TRANSLATOR; int32 bitsPerPixel; - if (ICO::identify(ioExtension, *stream, bitsPerPixel) != B_OK) + uint8 type; + if (ICO::identify(ioExtension, *stream, type, bitsPerPixel) != B_OK) return B_NO_TRANSLATOR; info->type = ICO_IMAGE_FORMAT; info->group = B_TRANSLATOR_BITMAP; info->quality = ICO_IN_QUALITY; info->capability = ICO_IN_CAPABILITY; - snprintf(info->name, sizeof(info->name), "Windows Icon %ld bit image", bitsPerPixel); + snprintf(info->name, sizeof(info->name), "Windows %s %ld bit image", + type == ICO::kTypeIcon ? "Icon" : "Cursor", bitsPerPixel); strcpy(info->MIME, kICOMimeType); return B_OK;