Skip to content

Commit

Permalink
BMP format support
Browse files Browse the repository at this point in the history
  • Loading branch information
mvladic committed Mar 5, 2020
1 parent 165b929 commit dd4de1d
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 16 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,13 @@ list (APPEND header_files ${header_eez_libs_sd_fat})
source_group("eez\\libs\\sd_fat" FILES ${src_eez_libs_sd_fat} ${header_eez_libs_sd_fat})

set(src_eez_libs_image
src/eez/libs/image/bitmap.cpp
src/eez/libs/image/jpeg.cpp
src/eez/libs/image/toojpeg.cpp
)
list (APPEND src_files ${src_eez_libs_image})
set(header_eez_libs_image
src/eez/libs/image/bitmap.h
src/eez/libs/image/jpeg.h
src/eez/libs/image/toojpeg.h
)
Expand Down
5 changes: 5 additions & 0 deletions src/eez/file_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ FileType getFileTypeFromExtension(const char *filePath) {
return (FileType)fileType;
}
}

if (endsWithNoCase(filePath, ".bmp")) {
return FILE_TYPE_IMAGE;
}

return FILE_TYPE_OTHER;
}

Expand Down
163 changes: 163 additions & 0 deletions src/eez/libs/image/bitmap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* EEZ Modular Firmware
* Copyright (C) 2015-present, Envox d.o.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdint.h>

#include <eez/memory.h>
#include <eez/libs/sd_fat/sd_fat.h>
#include <eez/libs/image/bitmap.h>

// const uint8_t buffer[] = {
// // BMP Header (14 bytes)

// // ID field (42h, 4Dh): BM
// 0x42, 0x4D,
// // size of BMP file
// 0x36, 0xFA, 0x05, 0x00, // 14 + 40 + (480 * 272 * 3) = 391734‬ = 0x5FA36
// // unused
// 0x00, 0x00,
// // unused
// 0x00, 0x00,
// // Offset where the pixel array (bitmap data) can be found
// 0x36, 0x00, 0x00, 0x00, // 53 = 0x36

// // DIB Header (40 bytes)

// // Number of bytes in the DIB header (from this point)
// 0x28, 0x00, 0x00, 0x00, // 40 = 0x28
// // Width of the bitmap in pixels
// 0xE0, 0x01, 0x00, 0x00, // 480 = 0x1E0
// // Height of the bitmap in pixels. Positive for bottom to top pixel order.
// 0x10, 0x01, 0x00, 0x00, // 272 = 0x110
// // Number of color planes being used
// 0x01, 0x00,
// // Number of bits per pixel
// 0x18, 0x00, // 24 = 0x18
// // BI_RGB, no pixel array compression used
// 0x00, 0x00, 0x00, 0x00,
// // Size of the raw bitmap data (including padding)
// 0x00, 0xFA, 0x05, 0x00, // 480 * 272 * 3 = 0x5FA00
// // Print resolution of the image,
// // 72 DPI × 39.3701 inches per metre yields 2834.6472
// 0x13, 0x0B, 0x00, 0x00, // 2835 pixels/metre horizontal
// 0x13, 0x0B, 0x00, 0x00, // 2835 pixels/metre vertical
// // Number of colors in the palette
// 0x00, 0x00, 0x00, 0x00,
// // 0 means all colors are important
// 0x00, 0x00, 0x00, 0x00,
// };

uint32_t readUint32(const uint8_t *bytes) {
return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
}

uint16_t readUint16(const uint8_t *bytes) {
return bytes[0] | (bytes[1] << 8);
}

uint8_t *bitmapDecode(const char *filePath, int *imageWidth, int *imageHeight) {
uint32_t offset;
uint32_t width;
uint32_t height;
uint16_t numColorPlanes;
uint16_t bitsPerPixel;
uint32_t lineBytes;
auto lineBuffer = FILE_VIEW_BUFFER;

eez::File file;
if (!file.open(filePath, FILE_OPEN_EXISTING | FILE_READ)) {
goto ErrorNoClose;
}

uint32_t bytesRead;

uint8_t bmpHeader[14];

bytesRead = file.read(bmpHeader, sizeof(bmpHeader));
if (bytesRead != sizeof(bmpHeader)) {
goto Error;
}

uint8_t dibHeader[40];

bytesRead = file.read(dibHeader, sizeof(dibHeader));
if (bytesRead != sizeof(dibHeader)) {
goto Error;
}

offset = readUint32(bmpHeader + 10);

width = readUint32(dibHeader + 4);
if (width > 480) {
goto Error;
}

height = readUint32(dibHeader + 8);
if (height > 272) {
goto Error;
}

numColorPlanes = readUint16(dibHeader + 12);
if (numColorPlanes != 1) {
goto Error;
}

bitsPerPixel = readUint16(dibHeader + 14);
if (bitsPerPixel != 24) {
goto Error;
}

lineBytes = width * 3;

offset += height * lineBytes;

for (uint32_t line = 0; line < height; line++) {
offset -= lineBytes;
if (!file.seek(offset)) {
goto Error;
}

bytesRead = file.read(lineBuffer, lineBytes);
if (bytesRead != lineBytes) {
goto Error;
}

for (uint32_t i = 0; i < lineBytes; i += 3) {
auto temp = lineBuffer[i];
lineBuffer[i] = lineBuffer[i + 2];
lineBuffer[i + 2] = temp;
}

lineBuffer += lineBytes;
}

// FILE_VIEW_BUFFER_SIZE

file.close();

*imageWidth = width;
*imageHeight = height;

return FILE_VIEW_BUFFER;

Error:
file.close();

ErrorNoClose:
return nullptr;
}
21 changes: 21 additions & 0 deletions src/eez/libs/image/bitmap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* EEZ Modular Firmware
* Copyright (C) 2020-present, Envox d.o.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

uint8_t *bitmapDecode(const char *filePath, int *imageWidth, int *imageHeight);
10 changes: 6 additions & 4 deletions src/eez/libs/image/jpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@

#include <eez/system.h>
#include <eez/debug.h>
#include <eez/libs/sd_fat/sd_fat.h>

#include <eez/memory.h>
#include <eez/libs/sd_fat/sd_fat.h>

static size_t g_imageDataSize;

Expand Down Expand Up @@ -81,7 +80,7 @@ extern "C" void njCopyMem(void* dest, const void* src, int size) {
memcpy(dest, src, size);
}

uint8_t *jpegDecode(const char *filePath) {
uint8_t *jpegDecode(const char *filePath, int *imageWidth, int *imageHeight) {
// DebugTrace("context size: %d\n", sizeof(nj_context_t));

uint32_t fileSize;
Expand Down Expand Up @@ -113,10 +112,13 @@ uint8_t *jpegDecode(const char *filePath) {
goto Error;
}

if (njGetWidth() != 480 || njGetHeight() != 272 || !njIsColor() || njGetImageSize() != 480 * 272 * 3) {
if (njGetWidth() > 480 || njGetHeight() > 272 || !njIsColor() || njGetImageSize() > 480 * 272 * 3) {
goto Error;
}

*imageWidth = njGetWidth();
*imageHeight = njGetHeight();

return njGetImage();

Error:
Expand Down
2 changes: 1 addition & 1 deletion src/eez/libs/image/jpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@

int jpegEncode(const uint8_t *screenshotPixels, unsigned char **imageData, size_t *imageDataSize);

uint8_t *jpegDecode(const char *filePath);
uint8_t *jpegDecode(const char *filePath, int *imageWidth, int *imageHeight);
25 changes: 15 additions & 10 deletions src/eez/modules/psu/gui/file_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include <eez/libs/sd_fat/sd_fat.h>

#include <eez/libs/image/jpeg.h>
#include <eez/libs/image/bitmap.h>

namespace eez {
namespace gui {
Expand Down Expand Up @@ -85,6 +86,8 @@ int32_t g_selectedFileIndex = -1;

bool g_imageLoadFailed;
uint8_t *g_openedImagePixels;
int g_openedImageWidth;
int g_openedImageHeight;

bool g_fileBrowserMode;
DialogType g_dialogType;
Expand Down Expand Up @@ -673,18 +676,20 @@ void openImageFile() {
strcpy(filePath, g_currentDirectory);
strcat(filePath, "/");
strcat(filePath, fileItem->name);

g_openedImagePixels = jpegDecode(filePath);

if (endsWithNoCase(fileItem->name, ".bmp")) {
g_openedImagePixels = bitmapDecode(filePath, &g_openedImageWidth, &g_openedImageHeight);
} else {

g_openedImagePixels = jpegDecode(filePath, &g_openedImageWidth, &g_openedImageHeight);
}

if (!g_openedImagePixels) {
g_imageLoadFailed = true;
}
}
}
}

uint8_t *getOpenedImagePixels() {
return g_openedImagePixels;
}

bool isUploadFileEnabled() {
#if !defined(EEZ_PLATFORM_SIMULATOR)
if (psu::serial::isConnected()) {
Expand Down Expand Up @@ -1106,11 +1111,11 @@ void data_file_manager_delete_file_enabled(data::DataOperationEnum operation, da

void data_file_manager_opened_image(data::DataOperationEnum operation, data::Cursor &cursor, data::Value &value) {
if (operation == data::DATA_OPERATION_GET_BITMAP_PIXELS) {
value = Value(getOpenedImagePixels(), VALUE_TYPE_POINTER);
value = Value(g_openedImagePixels, VALUE_TYPE_POINTER);
} else if (operation == data::DATA_OPERATION_GET_BITMAP_WIDTH) {
value = Value(480, VALUE_TYPE_UINT16);
value = Value(g_openedImageWidth, VALUE_TYPE_UINT16);
} else if (operation == data::DATA_OPERATION_GET_BITMAP_HEIGHT) {
value = Value(272, VALUE_TYPE_UINT16);
value = Value(g_openedImageHeight, VALUE_TYPE_UINT16);
}
}

Expand Down
1 change: 0 additions & 1 deletion src/eez/modules/psu/gui/file_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ bool isDeleteFileEnabled();
void deleteFile();

void openImageFile();
uint8_t *getOpenedImagePixels();

void onEncoder(int couter);

Expand Down

0 comments on commit dd4de1d

Please sign in to comment.