This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch fix-image-display
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit 1167b1e3f634166e201c0e85b240d5698faadc37
Author: Dominik Riemer <[email protected]>
AuthorDate: Thu Jun 6 15:59:31 2024 +0200

    fix: Image rendering in data explorer
---
 .../streampipes/ps/DataLakeImageResource.java      |  10 +-
 .../image-bar-preview.component.html               |   2 +-
 .../image-bar-preview.component.scss               |   1 +
 .../image/image-bar/image-bar.component.html       | 114 ++++++++++-----------
 .../image/image-bar/image-bar.component.scss       |   4 -
 .../image-container.component.html}                |  18 ++--
 .../image-container.component.scss}                |   7 +-
 .../image-container/image-container.component.ts   |  81 +++++++++++++++
 .../image/image-viewer/image-viewer.component.html |  30 +++---
 .../widgets/image/image-widget.component.html      |  31 +++---
 .../widgets/image/image-widget.component.ts        |  21 +---
 ui/src/app/data-explorer/data-explorer.module.ts   |   2 +
 12 files changed, 191 insertions(+), 130 deletions(-)

diff --git 
a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeImageResource.java
 
b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeImageResource.java
index 6e71ec1a36..4dd67466c6 100644
--- 
a/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeImageResource.java
+++ 
b/streampipes-platform-services/src/main/java/org/apache/streampipes/ps/DataLakeImageResource.java
@@ -21,21 +21,23 @@ package org.apache.streampipes.ps;
 import 
org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
 import org.apache.streampipes.storage.management.StorageDispatcher;
 
+import org.apache.commons.io.IOUtils;
+
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-
-import java.io.InputStream;
+import java.io.IOException;
 
 @RestController
 @RequestMapping("/api/v4/datalake/images")
 public class DataLakeImageResource extends AbstractAuthGuardedRestResource {
 
   @GetMapping(path = "{imageId}", produces = "image/jpeg")
-  public ResponseEntity<InputStream> getImage(@PathVariable("imageId") String 
imageId) {
-    return 
ok(StorageDispatcher.INSTANCE.getNoSqlStore().getImageStorage().getImageBytes(imageId));
+  public ResponseEntity<byte[]> getImage(@PathVariable("imageId") String 
imageId) throws IOException {
+    var image = 
StorageDispatcher.INSTANCE.getNoSqlStore().getImageStorage().getImageBytes(imageId);
+    return ok(IOUtils.toByteArray(image));
   }
 }
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.html
 
b/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.html
index 6bb8c48acc..f2c949996e 100644
--- 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.html
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.html
@@ -18,7 +18,7 @@
 
 <img
     [ngClass]="focus ? 'imagePreview imageFocus' : 'imagePreview'"
-    [style.height.px]="imagePreviewHeight"
+    [style.height.px]="imagePreviewHeight - 40"
     *ngIf="showImage"
     [src]="imagePath"
 />
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.scss
 
b/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.scss
index 499314a337..adc14cfa96 100644
--- 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.scss
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.scss
@@ -20,6 +20,7 @@
     height: 65px;
     margin-left: 10px;
     margin-right: 10px;
+    cursor: pointer;
 }
 
 .imageFocus {
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.html
 
b/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.html
index 6606552180..e1ba9ec18f 100644
--- 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.html
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.html
@@ -16,67 +16,59 @@
   ~
   -->
 
-<div fxLayout="row" fxLayoutAlign="center center">
-    <div>{{ selectedIndex + 1 }} / {{ maxImages }}</div>
-</div>
-
-<div fxLayout="row" fxLayoutAlign="space-around center">
-    <button mat-icon-button (click)="goToStart()">
-        <mat-icon>skip_previous</mat-icon>
-    </button>
-    <button mat-icon-button (click)="nextImage()">
-        <mat-icon>keyboard_arrow_left</mat-icon>
-    </button>
-
-    <div fxLayout="row" fxLayoutAlign="center center" class="imageBar">
-        <div fxFlex="40" fxLayoutAlign="end center">
-            <sp-image-bar-preview
-                [imagePreviewHeight]="imagePreviewHeight"
-                [imageSrc]="_imageRoutes[selectedIndex - 2]"
-                *ngIf="selectedIndex >= 2"
-                (click)="changeImage(selectedIndex - 2)"
-            ></sp-image-bar-preview>
-            <sp-image-bar-preview
-                [imagePreviewHeight]="imagePreviewHeight"
-                [imageSrc]="_imageRoutes[selectedIndex - 1]"
-                *ngIf="selectedIndex >= 1"
-                (click)="changeImage(selectedIndex - 1)"
-            ></sp-image-bar-preview>
-        </div>
-
-        <div fxFlex="20">
-            <div fxLayout="row" fxLayoutAlign="center">
-                <sp-image-bar-preview
-                    [imagePreviewHeight]="imagePreviewHeight"
-                    [imageSrc]="_imageRoutes[selectedIndex]"
-                    [focus]="true"
-                    (click)="changeImage(selectedIndex)"
-                ></sp-image-bar-preview>
-            </div>
-        </div>
-
-        <div fxFlex="40">
-            <div fxLayout="row" fxLayoutAlign="start center">
-                <sp-image-bar-preview
-                    [imagePreviewHeight]="imagePreviewHeight"
-                    [imageSrc]="_imageRoutes[selectedIndex + 1]"
-                    *ngIf="selectedIndex < maxImages - 1"
-                    (click)="changeImage(selectedIndex + 1)"
-                ></sp-image-bar-preview>
-                <sp-image-bar-preview
-                    [imagePreviewHeight]="imagePreviewHeight"
-                    [imageSrc]="_imageRoutes[selectedIndex + 2]"
-                    *ngIf="selectedIndex < maxImages - 2"
-                    (click)="changeImage(selectedIndex + 2)"
-                ></sp-image-bar-preview>
-            </div>
-        </div>
+<div fxFlex="100" fxLayout="column">
+    <div fxLayout="row" fxLayoutAlign="center center" class="mb-10">
+        <div>{{ selectedIndex + 1 }} / {{ maxImages }}</div>
     </div>
 
-    <button mat-icon-button (click)="previousImage()">
-        <mat-icon>keyboard_arrow_right</mat-icon>
-    </button>
-    <button mat-icon-button (click)="goToEnd()">
-        <mat-icon>skip_next</mat-icon>
-    </button>
+    <div
+        fxFlex
+        fxLayout="row"
+        fxLayoutAlign="center center"
+        class="imageBar"
+        fxLayoutGap="10px"
+    >
+        <button mat-icon-button (click)="goToStart()">
+            <mat-icon>skip_previous</mat-icon>
+        </button>
+        <button mat-icon-button (click)="nextImage()">
+            <mat-icon>keyboard_arrow_left</mat-icon>
+        </button>
+        <sp-image-bar-preview
+            [imagePreviewHeight]="imagePreviewHeight"
+            [imageSrc]="_imageRoutes[selectedIndex - 2]"
+            *ngIf="selectedIndex >= 2"
+            (click)="changeImage(selectedIndex - 2)"
+        ></sp-image-bar-preview>
+        <sp-image-bar-preview
+            [imagePreviewHeight]="imagePreviewHeight"
+            [imageSrc]="_imageRoutes[selectedIndex - 1]"
+            *ngIf="selectedIndex >= 1"
+            (click)="changeImage(selectedIndex - 1)"
+        ></sp-image-bar-preview>
+        <sp-image-bar-preview
+            [imagePreviewHeight]="imagePreviewHeight"
+            [imageSrc]="_imageRoutes[selectedIndex]"
+            [focus]="true"
+            (click)="changeImage(selectedIndex)"
+        ></sp-image-bar-preview>
+        <sp-image-bar-preview
+            [imagePreviewHeight]="imagePreviewHeight"
+            [imageSrc]="_imageRoutes[selectedIndex + 1]"
+            *ngIf="selectedIndex < maxImages - 1"
+            (click)="changeImage(selectedIndex + 1)"
+        ></sp-image-bar-preview>
+        <sp-image-bar-preview
+            [imagePreviewHeight]="imagePreviewHeight"
+            [imageSrc]="_imageRoutes[selectedIndex + 2]"
+            *ngIf="selectedIndex < maxImages - 2"
+            (click)="changeImage(selectedIndex + 2)"
+        ></sp-image-bar-preview>
+        <button mat-icon-button (click)="previousImage()">
+            <mat-icon>keyboard_arrow_right</mat-icon>
+        </button>
+        <button mat-icon-button (click)="goToEnd()">
+            <mat-icon>skip_next</mat-icon>
+        </button>
+    </div>
 </div>
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.scss
 
b/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.scss
index 0c64d80038..13cbc4aacb 100644
--- 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.scss
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.scss
@@ -15,7 +15,3 @@
  * limitations under the License.
  *
  */
-
-.imageBar {
-    height: 70px;
-}
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.html
 
b/ui/src/app/data-explorer/components/widgets/image/image-container/image-container.component.html
similarity index 73%
copy from 
ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.html
copy to 
ui/src/app/data-explorer/components/widgets/image/image-container/image-container.component.html
index 6bb8c48acc..5536e7c2bb 100644
--- 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar-preview/image-bar-preview.component.html
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-container/image-container.component.html
@@ -15,10 +15,14 @@
   ~ limitations under the License.
   ~
   -->
-
-<img
-    [ngClass]="focus ? 'imagePreview imageFocus' : 'imagePreview'"
-    [style.height.px]="imagePreviewHeight"
-    *ngIf="showImage"
-    [src]="imagePath"
-/>
+<div class="main-image" fxLayoutAlign="center center" fxFlex="100">
+    <img
+        class="main-image"
+        [src]="imagePath"
+        [style.width.px]="imageWidth"
+        [style.height.px]="imageHeight"
+        #mainImg
+        *ngIf="showImage"
+        (load)="onImageLoaded()"
+    />
+</div>
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.scss
 
b/ui/src/app/data-explorer/components/widgets/image/image-container/image-container.component.scss
similarity index 88%
copy from 
ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.scss
copy to 
ui/src/app/data-explorer/components/widgets/image/image-container/image-container.component.scss
index 0c64d80038..754495c653 100644
--- 
a/ui/src/app/data-explorer/components/widgets/image/image-bar/image-bar.component.scss
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-container/image-container.component.scss
@@ -16,6 +16,9 @@
  *
  */
 
-.imageBar {
-    height: 70px;
+.main-image {
+    margin-left: auto;
+    margin-right: auto;
+    max-height: 100%;
+    max-width: 100%;
 }
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-container/image-container.component.ts
 
b/ui/src/app/data-explorer/components/widgets/image/image-container/image-container.component.ts
new file mode 100644
index 0000000000..ac5123b1c6
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-container/image-container.component.ts
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, ElementRef, Input, ViewChild } from '@angular/core';
+import { SafeUrl } from '@angular/platform-browser';
+import { Observable } from 'rxjs';
+
+@Component({
+    selector: 'sp-image-container',
+    templateUrl: './image-container.component.html',
+    styleUrls: ['./image-container.component.scss'],
+})
+export class SpImageContainerComponent {
+    imagePath: SafeUrl;
+    showImage = false;
+
+    @ViewChild('mainImg') imageRef: ElementRef;
+
+    @Input()
+    public canvasHeight = 500;
+
+    @Input()
+    public canvasWidth = 800;
+
+    imageWidth = 0;
+    imageHeight = 0;
+
+    constructor() {}
+
+    onImageLoaded() {
+        const naturalImageWidth = (
+            this.imageRef.nativeElement as HTMLImageElement
+        ).naturalWidth;
+        const naturalImageHeight = (
+            this.imageRef.nativeElement as HTMLImageElement
+        ).naturalHeight;
+        this.calculateImageDimensions(naturalImageWidth, naturalImageHeight);
+    }
+
+    calculateImageDimensions(imageWidth: number, imageHeight: number): void {
+        const canvasAspectRatio = this.canvasWidth / this.canvasHeight;
+        const imageAspectRatio = imageWidth / imageHeight;
+
+        let finalWidth: number;
+        let finalHeight: number;
+
+        if (imageAspectRatio > canvasAspectRatio) {
+            finalWidth = this.canvasWidth;
+            finalHeight = this.canvasWidth / imageAspectRatio;
+        } else {
+            finalHeight = this.canvasHeight;
+            finalWidth = this.canvasHeight * imageAspectRatio;
+        }
+
+        this.imageWidth = finalWidth;
+        this.imageHeight = finalHeight;
+    }
+
+    @Input()
+    set imageSrc(src: Observable<Blob>) {
+        src.subscribe(url => {
+            this.imagePath = url;
+            this.showImage = true;
+        });
+    }
+}
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-viewer/image-viewer.component.html
 
b/ui/src/app/data-explorer/components/widgets/image/image-viewer/image-viewer.component.html
index c6bfa13867..59d4bd48ad 100644
--- 
a/ui/src/app/data-explorer/components/widgets/image/image-viewer/image-viewer.component.html
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-viewer/image-viewer.component.html
@@ -17,22 +17,22 @@
   -->
 
 <div style="width: 100%; height: 100%">
-    <div fxLayout="column" fxLayoutAlign="space-between ">
-        <div fxLayout="row" fxLayoutAlign="space-around start">
-            <div fxLayout="column" fxLayoutAlign="space-between ">
-                <sp-image-container
-                    *ngIf="imagesRoutes.length > 0"
-                    [imageSrc]="imagesRoutes[imagesIndex]"
-                    [canvasWidth]="canvasWidth"
-                    [canvasHeight]="canvasHeight"
-                >
-                </sp-image-container>
-            </div>
-        </div>
-        <br />
-
+    <div [ngStyle]="{ width: canvasWidth, height: canvasHeight + 'px' }">
+        <sp-image-container
+            fxFlex="100"
+            *ngIf="imagesRoutes.length > 0"
+            [imageSrc]="imagesRoutes[imagesIndex]"
+            [canvasWidth]="canvasWidth"
+            [canvasHeight]="canvasHeight"
+        >
+        </sp-image-container>
+    </div>
+    <div
+        [ngStyle]="{ width: '100%', height: imagePreviewHeight + 'px' }"
+        fxLayout="row"
+    >
         <sp-image-bar
-            style="width: 100%"
+            fxFlex="100"
             [imagesRoutes]="imagesRoutes"
             [selectedIndex]="imagesIndex"
             [enableShortCuts]="true"
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-widget.component.html 
b/ui/src/app/data-explorer/components/widgets/image/image-widget.component.html
index 519fd70ebd..b492ab54e0 100644
--- 
a/ui/src/app/data-explorer/components/widgets/image/image-widget.component.html
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-widget.component.html
@@ -16,28 +16,21 @@
   ~
   -->
 
-<div
-    fxFlex="100"
-    fxLayoutAlign="center center"
-    fxLayout="column"
-    class="main-panel"
->
+<div fxFlex="100" fxLayoutAlign="center center" fxLayout="column">
     <sp-no-data-in-date-range
         *ngIf="showNoDataInDateRange"
         [viewDateRange]="timeSettings"
     ></sp-no-data-in-date-range>
 
-    <div class="widget-inner-content">
-        <sp-image-viewer
-            *ngIf="imagePaths.length > 0"
-            [imagesRoutes]="imagePaths"
-            [canvasHeight]="canvasHeight"
-            [canvasWidth]="canvasWidth"
-            [imagePreviewHeight]="imagePreviewHeight"
-            [ngStyle]="{
-                width: canvasWidth + 'px',
-                height: canvasHeight + 'px'
-            }"
-        ></sp-image-viewer>
-    </div>
+    <sp-image-viewer
+        *ngIf="imagePaths.length > 0"
+        [imagesRoutes]="imagePaths"
+        [canvasHeight]="canvasHeight"
+        [canvasWidth]="canvasWidth"
+        [imagePreviewHeight]="imagePreviewHeight"
+        [ngStyle]="{
+            width: '100%',
+            height: '100%'
+        }"
+    ></sp-image-viewer>
 </div>
diff --git 
a/ui/src/app/data-explorer/components/widgets/image/image-widget.component.ts 
b/ui/src/app/data-explorer/components/widgets/image/image-widget.component.ts
index 4d8d7dc83c..c14cb303de 100644
--- 
a/ui/src/app/data-explorer/components/widgets/image/image-widget.component.ts
+++ 
b/ui/src/app/data-explorer/components/widgets/image/image-widget.component.ts
@@ -21,9 +21,6 @@ import { MatSort } from '@angular/material/sort';
 import { BaseDataExplorerWidgetDirective } from 
'../base/base-data-explorer-widget.directive';
 import {
     DataExplorerField,
-    DatalakeQueryParameterBuilder,
-    DatalakeQueryParameters,
-    EventPropertyUnion,
     SpQueryResult,
 } from '@streampipes/platform-services';
 import { ImageWidgetModel } from './model/image-widget.model';
@@ -43,9 +40,6 @@ export class ImageWidgetComponent
     imageBaseUrl: string;
     imagePaths = [];
 
-    availableColumns: EventPropertyUnion[];
-    selectedColumn: EventPropertyUnion;
-
     canvasHeight;
     canvasWidth;
     imagePreviewHeight;
@@ -58,24 +52,17 @@ export class ImageWidgetComponent
         super.ngOnInit();
         this.onResize(
             this.gridsterItemComponent.width,
-            this.gridsterItemComponent.height - 40,
+            this.gridsterItemComponent.height - 53,
         );
         this.imageBaseUrl = this.dataLakeRestService.dataLakeUrl + '/images/';
     }
 
     refreshView() {}
 
-    buildQuery(): DatalakeQueryParameters {
-        return DatalakeQueryParameterBuilder.create(
-            this.timeSettings.startTime,
-            this.timeSettings.endTime,
-        ).build();
-    }
-
     onResize(width: number, height: number) {
-        this.canvasHeight = height - 50;
-        this.canvasWidth = width - 20;
-        this.imagePreviewHeight = width / 14;
+        this.canvasHeight = height * 0.8;
+        this.canvasWidth = width;
+        this.imagePreviewHeight = height * 0.2;
     }
 
     beforeDataFetched() {
diff --git a/ui/src/app/data-explorer/data-explorer.module.ts 
b/ui/src/app/data-explorer/data-explorer.module.ts
index aa0b3823b9..6d31754b25 100644
--- a/ui/src/app/data-explorer/data-explorer.module.ts
+++ b/ui/src/app/data-explorer/data-explorer.module.ts
@@ -112,6 +112,7 @@ import { MatDividerModule } from 
'@angular/material/divider';
 import { MatTooltipModule } from '@angular/material/tooltip';
 import { MatProgressBarModule } from '@angular/material/progress-bar';
 import { MatButtonToggleModule } from '@angular/material/button-toggle';
+import { SpImageContainerComponent } from 
'./components/widgets/image/image-container/image-container.component';
 
 @NgModule({
     imports: [
@@ -225,6 +226,7 @@ import { MatButtonToggleModule } from 
'@angular/material/button-toggle';
         SpValueHeatmapWidgetConfigComponent,
         SpHistogramChartWidgetConfigComponent,
         SpPieChartWidgetConfigComponent,
+        SpImageContainerComponent,
         SpInvalidConfigurationComponent,
         SpConfigurationBoxComponent,
         SpVisualizationConfigOuterComponent,

Reply via email to