Фактор сжатия OpenCV cvSaveImage Jpeg

Поскольку activeBusinessCase устанавливается асинхронно, и вы хотите получать уведомления об изменениях значений в другой части вашего приложения, это должно быть Subject. Используйте BehaviorSubject, чтобы сразу получить текущее значение при подписке.

// ----- UserAuthService -----

public activeBusinessCase$ = new BehaviorSubject<string>(null);

setActiveBusinessCase(bcase: string) {
  this.activeBusinessCase.next(bcase);
  this.setTitle(bcase);
}

Прослушайте изменения значений activeBusinessCase$ в вашем ConfigurationService и отобразите входящие значения на язык, который вы хотите вернуть.

// ----- ConfigurationService -----

// will emit a new language every time activeBusinessCase changes,
// this behavior could be changed depending on your specific needs
getAutoConfiguredBCLanguage$(): Observable<string> {
  return this.authService.activeBusinessCase$
    .pipe(
      // use 'distinctUntilChanged' to only emit values that are different from the previous,
      distinctUntilChanged(),
      map(abc => this.getAutoConfiguredBCLanguage(abc))
    );     
}

private getAutoConfiguredBCLanguage(activeBusinessCase: string): string {
  // no changes here apart from the input parameter - I omitted the code for brevity
  // use the parameter activeBusinessCase instead of this.activeBusinessCase here
}

Подпишитесь на getAutoConfiguredBCLanguage$, где вам нужен язык.

// ----- AppComponent -----

initLanguage() {
  this.configService.getAutoConfiguredBCLanguage$()
    .pipe(takeUntil(this.destroy$)) // unsubscribe when the component gets destroyed
    .subscribe(lang => {
      // use the language here
    });
}

private destroy$ = new Subject<void>();

onDestroy() {
  this.destroy$.next();
  this.destroy$.complete();
}

A BehaviorSubject имеет функцию getValue, которая возвращает последнее значение, выданное BehaviorSubject. Вы можете использовать эту функцию, чтобы получить текущее значение activeBusinessCase, но делать это только в том случае, если вы знаете, что делаете, т.е. если вы действительно хотите получить текущее значение в определенное время , которое вы вызываете getValue. Помните, что вы имеете дело с асинхронными действиями в вашем приложении. Если вы хотите быть уверены, что получите значение activeBusinessCase$ после его установки, вызвав this.authService.setActiveBusinessCase, вы должны подписаться на BehaviorSubject. Если вас не волнует, было ли уже установлено activeBusinessCase$, и вы просто хотите использовать текущее значение activeBusinessCase$, вы можете использовать getValue (который затем может вернуть null, который был установлен в качестве начального значения activeBusinessCase$ ).

Мое предложение:

// ---- HomeComponent ----

ngOnInit() {
  // To navigate to a route once the activeBusinessCase has a non null value
  // subscribe but only take the first non null element and no further values afterwards
  this.authService.activeBusinessCase$
    .pipe(first(Boolean))
    .subscribe(bc => this.router.navigate([Constants.routing.explorer + bc.toLowerCase()]));
}

// ---- SmagHttpService & UserAuthService ----

// Don't subscribe to activeBusinessCase$ in here!! Instead use
this.authService.activeBusinessCase$.getValue()
// when you need the current value (which might not have been set yet, 
// but you already have null checks here and if this part of your app worked before 
// there will be no differences)

// Example:
const businessCase = this.authService.activeBusinessCase$.getValue();
if (businessCase) {
  this.router.navigate([Constants.routing.explorer + businessCase.toLowerCase()]);
}

businessCase ? businessCase : environment.default_business_case
11
задан Jav_Rock 11 June 2012 в 20:58
поделиться

2 ответа

Currently cvSaveImage() is declared to take only two parameters:

int cvSaveImage( const char* filename, const CvArr* image );

However, the "latest tested snapshot" has:

  #define CV_IMWRITE_JPEG_QUALITY 1
  #define CV_IMWRITE_PNG_COMPRESSION 16
  #define CV_IMWRITE_PXM_BINARY 32

  /* save image to file */
  CVAPI(int) cvSaveImage( const char* filename, const CvArr* image,
                          const int* params CV_DEFAULT(0) );

I've been unable to find any documentation, but my impression from poking through this code is that you would build an array of int values to pass in the third parameter:

int p[3];
p[0] = CV_IMWRITE_JPEG_QUALITY;
p[1] = desired_quality_value;
p[2] = 0;

I don't know how the quality value is encoded, and I've never tried this, so caveat emptor.

Edit:

Being a bit curious about this, I downloaded and built the latest trunk version of OpenCV, and was able to confirm the above via this bit of throwaway code:

#include "cv.h"
#include "highgui.h"
int main(int argc, char **argv)
{
    int p[3];
    IplImage *img = cvLoadImage("test.jpg");

    p[0] = CV_IMWRITE_JPEG_QUALITY;
    p[1] = 10;
    p[2] = 0;

    cvSaveImage("out1.jpg", img, p);

    p[0] = CV_IMWRITE_JPEG_QUALITY;
    p[1] = 100;
    p[2] = 0;

    cvSaveImage("out2.jpg", img, p);

    exit(0);
}

My "test.jpg" was 2,054 KB, the created "out1.jpg" was 182 KB and "out2.jpg" was 4,009 KB.

Looks like you should be in good shape assuming you can use the latest code available from the Subversion repository.

BTW, the range for the quality parameter is 0-100, default is 95.

26
ответ дан 3 December 2019 в 02:20
поделиться
  1. You can probably find this by poking around in the source code here: http://opencvlibrary.svn.sourceforge.net/viewvc/opencvlibrary/
  2. You can't, as the function does not accept such a parameter. If you want to control the compression then the simplest method I can think of is first saving your image as a bitmap with cvSaveImage() (or another lossless format of your choice) and then use another image library to convert it to a JPEG of the desired compression factor.
1
ответ дан 3 December 2019 в 02:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: